diff --git a/CMakeLists.txt b/CMakeLists.txt
index b120d118..dfb7e8a2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -31,6 +31,8 @@ file(GLOB dvmhost_SRC
"p25/edac/*.cpp"
"p25/lc/*.h"
"p25/lc/*.cpp"
+ "p25/lc/tsbk/*.h"
+ "p25/lc/tsbk/*.cpp"
"p25/lookups/*.h"
"p25/lookups/*.cpp"
"p25/packet/*.h"
@@ -109,7 +111,7 @@ else ()
endif (ENABLE_DMR)
message(CHECK_START "P25 Digital Mode")
if (ENABLE_P25)
- add_definitions(-DEANBLE_P25)
+ add_definitions(-DENABLE_P25)
message(CHECK_PASS "enabled")
else ()
message(CHECK_PASS "disabled")
diff --git a/Defines.h b/Defines.h
index f0ca0296..0db4a276 100644
--- a/Defines.h
+++ b/Defines.h
@@ -227,6 +227,30 @@ inline std::string __IP_FROM_ULONG(const ulong64_t& value) {
(buffer[offset + 1U] << 8) | \
(buffer[offset + 2U] << 0);
+/**
+ * Class Copy Code Pattern
+ */
+/// Creates a private copy implementation.
+/// This requires the copy(const type& data) to be declared in the class definition.
+#define __COPY(type) \
+ private: void copy(const type& data); \
+ public: __forceinline type& operator=(const type& data) { \
+ if (this != &data) { \
+ copy(data); \
+ } \
+ return *this; \
+ }
+/// Creates a protected copy implementation.
+/// This requires the copy(const type& data) to be declared in the class definition.
+#define __PROTECTED_COPY(type) \
+ protected: void copy(const type& data); \
+ public: __forceinline type& operator=(const type& data) { \
+ if (this != &data) { \
+ copy(data); \
+ } \
+ return *this; \
+ }
+
/**
* Property Creation
* These macros should always be used LAST in the "public" section of a class definition.
@@ -235,6 +259,10 @@ inline std::string __IP_FROM_ULONG(const ulong64_t& value) {
#define __READONLY_PROPERTY(type, variableName, propName) \
private: type m_##variableName; \
public: __forceinline type get##propName(void) const { return m_##variableName; }
+/// Creates a read-only get property.
+#define __PROTECTED_READONLY_PROPERTY(type, variableName, propName) \
+ protected: type m_##variableName; \
+ public: __forceinline type get##propName(void) const { return m_##variableName; }
/// Creates a read-only get property, does not use "get".
#define __READONLY_PROPERTY_PLAIN(type, variableName, propName) \
private: type m_##variableName; \
@@ -244,16 +272,26 @@ inline std::string __IP_FROM_ULONG(const ulong64_t& value) {
private: type m_##variableName; \
public: __forceinline type& get##propName(void) const { return m_##variableName; }
-/// Creates a get and set property.
+/// Creates a get and set private property.
#define __PROPERTY(type, variableName, propName) \
private: type m_##variableName; \
public: __forceinline type get##propName(void) const { return m_##variableName; } \
__forceinline void set##propName(type val) { m_##variableName = val; }
-/// Creates a get and set property, does not use "get"/"set".
+/// Creates a get and set protected property.
+#define __PROTECTED_PROPERTY(type, variableName, propName) \
+ protected: type m_##variableName; \
+ public: __forceinline type get##propName(void) const { return m_##variableName; } \
+ __forceinline void set##propName(type val) { m_##variableName = val; }
+/// Creates a get and set private property, does not use "get"/"set".
#define __PROPERTY_PLAIN(type, variableName, propName) \
private: type m_##variableName; \
public: __forceinline type propName(void) const { return m_##variableName; } \
__forceinline void propName(type val) { m_##variableName = val; }
+/// Creates a get and set protected property, does not use "get"/"set".
+#define __PROTECTED_PROPERTY_PLAIN(type, variableName, propName) \
+ protected: type m_##variableName; \
+ public: __forceinline type propName(void) const { return m_##variableName; } \
+ __forceinline void propName(type val) { m_##variableName = val; }
/// Creates a get and set property by reference.
#define __PROPERTY_BYREF(type, variableName, propName) \
private: type m_##variableName; \
diff --git a/host/calibrate/HostCal.cpp b/host/calibrate/HostCal.cpp
index b82e1251..9837c8f0 100644
--- a/host/calibrate/HostCal.cpp
+++ b/host/calibrate/HostCal.cpp
@@ -35,6 +35,7 @@
#include "p25/P25Defines.h"
#include "p25/data/DataHeader.h"
#include "p25/lc/LC.h"
+#include "p25/lc/tsbk/TSBKFactory.h"
#include "p25/P25Utils.h"
#include "nxdn/NXDNDefines.h"
#include "nxdn/channel/LICH.h"
@@ -411,6 +412,10 @@ int HostCal::run()
return 2;
}
+ p25::lc::TSBK::setVerbose(true);
+ p25::lc::TSBK::setWarnCRC(true);
+ p25::lc::tsbk::TSBKFactory::setWarnCRC(true);
+
m_modem = new Modem(modemPort, false, rxInvert, txInvert, pttInvert, dcBlocker, false, fdmaPreamble, dmrRxDelay, p25CorrCount, 10U, false, ignoreModemConfigArea, false, false, false);
m_modem->setLevels(rxLevel, txLevel, txLevel, txLevel, txLevel);
m_modem->setSymbolAdjust(dmrSymLevel3Adj, dmrSymLevel1Adj, p25SymLevel3Adj, p25SymLevel1Adj, nxdnSymLevel3Adj, nxdnSymLevel1Adj);
@@ -2100,21 +2105,18 @@ void HostCal::processP25BER(const uint8_t* buffer)
else if (duid == P25_DUID_TSDU) {
timerStop();
- lc::TSBK tsbk = lc::TSBK(SiteData(), lookups::IdenTable());
- tsbk.setVerbose(true); // always verbose in CAL
- tsbk.setWarnCRC(true);
+ lc::TSBK *tsbk = lc::tsbk::TSBKFactory::createTSBK(buffer + 1U);
Utils::dump(1U, "Raw TSBK Dump", buffer + 1U, P25_TSDU_FRAME_LENGTH_BYTES);
- bool ret = tsbk.decode(buffer + 1U);
- if (!ret) {
+ if (tsbk == NULL) {
LogWarning(LOG_CAL, P25_TSDU_STR ", undecodable LC");
m_berUndecodableLC++;
}
else {
- LogMessage(LOG_CAL, P25_TSDU_STR ", mfId = $%02X, lco = $%02X, srcId = %u, dstId = %u, service = %u, status = %u, message = %u, extFunc = %u, netId = %u, sysId = %u",
- tsbk.getMFId(), tsbk.getLCO(), tsbk.getSrcId(), tsbk.getDstId(), tsbk.getService(), tsbk.getStatus(), tsbk.getMessage(), tsbk.getExtendedFunction(),
- tsbk.getNetId(), tsbk.getSysId());
+ LogMessage(LOG_CAL, P25_TSDU_STR ", mfId = $%02X, lco = $%02X, srcId = %u, dstId = %u, service = %u, netId = %u, sysId = %u",
+ tsbk->getMFId(), tsbk->getLCO(), tsbk->getSrcId(), tsbk->getDstId(), tsbk->getService(), tsbk->getNetId(), tsbk->getSysId());
+ delete tsbk;
}
}
}
diff --git a/network/BaseNetwork.cpp b/network/BaseNetwork.cpp
index d5bdbae3..2aa54bb8 100644
--- a/network/BaseNetwork.cpp
+++ b/network/BaseNetwork.cpp
@@ -439,10 +439,10 @@ bool BaseNetwork::writeP25TDU(const p25::lc::LC& control, const p25::data::LowSp
///
/// Writes P25 TSDU frame data to the network.
///
-///
+///
///
///
-bool BaseNetwork::writeP25TSDU(const p25::lc::TSBK& tsbk, const uint8_t* data)
+bool BaseNetwork::writeP25TSDU(const p25::lc::LC& control, const uint8_t* data)
{
if (m_status != NET_STAT_RUNNING && m_status != NET_STAT_MST_RUNNING)
return false;
@@ -453,7 +453,7 @@ bool BaseNetwork::writeP25TSDU(const p25::lc::TSBK& tsbk, const uint8_t* data)
m_streamId[0] = m_p25StreamId;
- return writeP25TSDU(m_id, m_p25StreamId, tsbk, data);
+ return writeP25TSDU(m_id, m_p25StreamId, control, data);
}
///
@@ -962,30 +962,32 @@ bool BaseNetwork::writeP25TDU(const uint32_t id, const uint32_t streamId, const
///
///
///
-///
+///
///
///
-bool BaseNetwork::writeP25TSDU(const uint32_t id, const uint32_t streamId, const p25::lc::TSBK& tsbk, const uint8_t* data)
+bool BaseNetwork::writeP25TSDU(const uint32_t id, const uint32_t streamId, const p25::lc::LC& control, const uint8_t* data)
{
if (m_status != NET_STAT_RUNNING && m_status != NET_STAT_MST_RUNNING)
return false;
+ assert(data != NULL);
+
uint8_t buffer[DATA_PACKET_LENGTH];
::memset(buffer, 0x00U, DATA_PACKET_LENGTH);
::memcpy(buffer + 0U, TAG_P25_DATA, 4U);
- buffer[4U] = tsbk.getLCO(); // LCO
+ buffer[4U] = control.getLCO(); // LCO
- uint32_t srcId = tsbk.getSrcId(); // Source Address
+ uint32_t srcId = control.getSrcId(); // Source Address
__SET_UINT16(srcId, buffer, 5U);
- uint32_t dstId = tsbk.getDstId(); // Target Address
+ uint32_t dstId = control.getDstId(); // Target Address
__SET_UINT16(dstId, buffer, 8U);
__SET_UINT32(id, buffer, 11U); // Peer ID
- buffer[15U] = tsbk.getMFId(); // MFId
+ buffer[15U] = control.getMFId(); // MFId
__SET_UINT32(streamId, buffer, 16U); // Stream ID
diff --git a/network/BaseNetwork.h b/network/BaseNetwork.h
index d56e17db..8e10d8eb 100644
--- a/network/BaseNetwork.h
+++ b/network/BaseNetwork.h
@@ -36,6 +36,7 @@
#include "p25/P25Defines.h"
#include "nxdn/NXDNDefines.h"
#include "dmr/data/Data.h"
+#include "p25/data/DataHeader.h"
#include "p25/data/LowSpeedData.h"
#include "p25/dfsi/DFSIDefines.h"
#include "p25/dfsi/LC.h"
@@ -155,7 +156,7 @@ namespace network
/// Writes P25 TDU frame data to the network.
virtual bool writeP25TDU(const p25::lc::LC& control, const p25::data::LowSpeedData& lsd);
/// Writes P25 TSDU frame data to the network.
- virtual bool writeP25TSDU(const p25::lc::TSBK& control, const uint8_t* data);
+ virtual bool writeP25TSDU(const p25::lc::LC& control, const uint8_t* data);
/// Writes P25 PDU frame data to the network.
virtual bool writeP25PDU(const p25::data::DataHeader& header, const p25::data::DataHeader& secHeader, const uint8_t currentBlock,
const uint8_t* data, const uint32_t len);
@@ -235,7 +236,7 @@ namespace network
/// Writes P25 TDU frame data to the network.
bool writeP25TDU(const uint32_t id, const uint32_t streamId, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd);
/// Writes P25 TSDU frame data to the network.
- bool writeP25TSDU(const uint32_t id, const uint32_t streamId, const p25::lc::TSBK& control, const uint8_t* data);
+ bool writeP25TSDU(const uint32_t id, const uint32_t streamId, const p25::lc::LC& control, const uint8_t* data);
/// Writes P25 PDU frame data to the network.
bool writeP25PDU(const uint32_t id, const uint32_t streamId, const p25::data::DataHeader& header, const p25::data::DataHeader& secHeader, const uint8_t currentBlock,
const uint8_t* data, const uint32_t len);
diff --git a/network/RemoteControl.cpp b/network/RemoteControl.cpp
index a5d23cd3..959fb213 100644
--- a/network/RemoteControl.cpp
+++ b/network/RemoteControl.cpp
@@ -94,8 +94,6 @@ using namespace modem;
#define RCD_P25_RID_GAQ "p25-rid-gaq"
#define RCD_P25_RID_UREG "p25-rid-ureg"
-#define RCD_P25_PATCH "p25-patch"
-
#define RCD_P25_RELEASE_GRANTS "p25-rel-grnts"
#define RCD_P25_RELEASE_AFFS "p25-rel-affs"
@@ -612,7 +610,8 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
if (p25 != NULL) {
uint32_t dstId = getArgUInt32(args, 0U);
if (dstId != 0U) {
- p25->trunk()->setMFId(m_p25MFId);
+ // FIXME
+ //p25->trunk()->setMFId(m_p25MFId);
p25->trunk()->writeRF_TSDU_Call_Alrt(p25::P25_WUID_FNE, dstId);
}
else {
@@ -629,7 +628,8 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
if (p25 != NULL) {
uint32_t dstId = getArgUInt32(args, 0U);
if (dstId != 0U) {
- p25->trunk()->setMFId(m_p25MFId);
+ // FIXME
+ //p25->trunk()->setMFId(m_p25MFId);
p25->trunk()->writeRF_TSDU_Ext_Func(p25::P25_EXT_FNCT_CHECK, p25::P25_WUID_FNE, dstId);
}
else {
@@ -646,7 +646,8 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
if (p25 != NULL) {
uint32_t dstId = getArgUInt32(args, 0U);
if (dstId != 0U) {
- p25->trunk()->setMFId(m_p25MFId);
+ // FIXME
+ //p25->trunk()->setMFId(m_p25MFId);
p25->trunk()->writeRF_TSDU_Ext_Func(p25::P25_EXT_FNCT_INHIBIT, p25::P25_WUID_FNE, dstId);
}
else {
@@ -663,7 +664,8 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
if (p25 != NULL) {
uint32_t dstId = getArgUInt32(args, 0U);
if (dstId != 0U) {
- p25->trunk()->setMFId(m_p25MFId);
+ // FIXME
+ //p25->trunk()->setMFId(m_p25MFId);
p25->trunk()->writeRF_TSDU_Ext_Func(p25::P25_EXT_FNCT_UNINHIBIT, p25::P25_WUID_FNE, dstId);
}
else {
@@ -680,7 +682,8 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
if (p25 != NULL) {
uint32_t dstId = getArgUInt32(args, 0U);
if (dstId != 0U) {
- p25->trunk()->setMFId(m_p25MFId);
+ // FIXME
+ //p25->trunk()->setMFId(m_p25MFId);
p25->trunk()->writeRF_TSDU_Grp_Aff_Q(dstId);
}
else {
@@ -697,7 +700,8 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
if (p25 != NULL) {
uint32_t dstId = getArgUInt32(args, 0U);
if (dstId != 0U) {
- p25->trunk()->setMFId(m_p25MFId);
+ // FIXME
+ //p25->trunk()->setMFId(m_p25MFId);
p25->trunk()->writeRF_TSDU_U_Reg_Cmd(dstId);
}
else {
@@ -710,26 +714,6 @@ void RemoteControl::process(Host* host, dmr::Control* dmr, p25::Control* p25, nx
LogError(LOG_RCON, reply.c_str());
}
}
- else if (rcom == RCD_P25_PATCH && argCnt >= 1U) {
- if (p25 != NULL) {
- uint32_t group1 = getArgUInt32(args, 0U);
- uint32_t group2 = getArgUInt32(args, 1U);
- uint32_t group3 = getArgUInt32(args, 2U);
-
- if (group1 != 0U) {
- p25->trunk()->setMFId(m_p25MFId);
- p25->trunk()->writeRF_TSDU_Mot_Patch(group1, group2, group3);
- }
- else {
- reply = INVALID_OPT_STR "tried to add P25 group patch with no TGID?";
- LogError(LOG_RCON, reply.c_str());
- }
- }
- else {
- reply = CMD_FAILED_STR "P25 mode is not enabled!";
- LogError(LOG_RCON, reply.c_str());
- }
- }
else if (rcom == RCD_P25_RELEASE_GRANTS) {
if (p25 != NULL) {
p25->affiliations().releaseGrant(0, true);
diff --git a/p25/Control.cpp b/p25/Control.cpp
index f1cb311e..1d7c8cae 100644
--- a/p25/Control.cpp
+++ b/p25/Control.cpp
@@ -285,6 +285,12 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s
m_siteData = SiteData(netId, sysId, rfssId, siteId, 0U, channelId, channelNo, serviceClass, lto);
m_siteData.setCallsign(cwCallsign);
+ lc::LC::setSiteData(m_siteData);
+ lc::TDULC::setSiteData(m_siteData);
+
+ lc::TSBK::setCallsign(cwCallsign);
+ lc::TSBK::setSiteData(m_siteData);
+
std::vector<::lookups::IdenTable> entries = m_idenTable->list();
for (auto it = entries.begin(); it != entries.end(); ++it) {
::lookups::IdenTable entry = *it;
@@ -294,6 +300,8 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s
}
}
+ lc::TDULC::setIdenEntry(m_idenEntry);
+
std::vector availCh = voiceChNo;
m_siteData.setChCnt((uint8_t)availCh.size());
@@ -349,11 +357,6 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s
if (m_data != NULL) {
m_data->resetRF();
}
-
- if (m_trunk != NULL) {
- m_trunk->resetRF();
- m_trunk->resetNet();
- }
}
///
@@ -431,8 +434,6 @@ bool Control::processFrame(uint8_t* data, uint32_t len)
m_voice->resetRF();
m_data->resetRF();
- m_trunk->m_rfTSBK = lc::TSBK(m_siteData, m_idenEntry);
-
return false;
}
@@ -705,8 +706,6 @@ void Control::clock(uint32_t ms)
m_voice->resetNet();
- m_trunk->m_netTSBK = lc::TSBK(m_siteData, m_idenEntry);
-
m_netTimeout.stop();
}
}
@@ -720,9 +719,6 @@ void Control::clock(uint32_t ms)
m_data->resetRF();
- m_trunk->m_rfTSBK = lc::TSBK(m_siteData, m_idenEntry);
- m_trunk->m_netTSBK = lc::TSBK(m_siteData, m_idenEntry);
-
if (m_network != NULL)
m_network->resetP25();
diff --git a/p25/P25Defines.h b/p25/P25Defines.h
index 59133ee6..13fbd59b 100644
--- a/p25/P25Defines.h
+++ b/p25/P25Defines.h
@@ -293,6 +293,8 @@ namespace p25
const uint8_t TSBK_IOSP_STS_UPDT = 0x18U; // STS UPDT REQ - Status Update Request (ISP), STS UPDT - Status Update (OSP)
const uint8_t TSBK_IOSP_STS_Q = 0x1AU; // STS Q REQ - Status Query Request (ISP), STS Q - Status Query (OSP)
const uint8_t TSBK_IOSP_MSG_UPDT = 0x1CU; // MSG UPDT REQ - Message Update Request (ISP), MSG UPDT - Message Update (OSP)
+ const uint8_t TSBK_IOSP_RAD_MON = 0x1DU; // RAD MON REQ - Radio Unit Monitor Request (ISP), RAD MON CMD - Radio Monitor Command (OSP)
+ const uint8_t TSBK_IOSP_RAD_MON_ENH = 0x1EU; // RAD MON ENH REQ - Radio Unit Monitor Enhanced Request (ISP), RAD MON ENH CMD - Radio Unit Monitor Enhanced Command (OSP)
const uint8_t TSBK_IOSP_CALL_ALRT = 0x1FU; // CALL ALRT REQ - Call Alert Request (ISP), CALL ALRT - Call Alert (OSP)
const uint8_t TSBK_IOSP_ACK_RSP = 0x20U; // ACK RSP U - Acknowledge Response - Unit (ISP), ACK RSP FNE - Acknowledge Response - FNE (OSP)
const uint8_t TSBK_IOSP_EXT_FNCT = 0x24U; // EXT FNCT RSP - Extended Function Response (ISP), EXT FNCT CMD - Extended Function Command (OSP)
@@ -303,27 +305,23 @@ namespace p25
const uint8_t TSBK_ISP_TELE_INT_PSTN_REQ = 0x09U; // TELE INT PSTN REQ - Telephone Interconnect Request - Implicit
const uint8_t TSBK_ISP_SNDCP_CH_REQ = 0x12U; // SNDCP CH REQ - SNDCP Data Channel Request
const uint8_t TSBK_ISP_STS_Q_RSP = 0x19U; // STS Q RSP - Status Query Response
- const uint8_t TSBK_ISP_STS_Q_REQ = 0x1CU; // STS_Q_REQ - Status Query Request
- const uint8_t TSBK_ISP_RAD_MON_REQ = 0x1DU; // RAD_MON_REQ - Radio Unit Monitor Request
- const uint8_t TSBK_ISP_RAD_MON_ENH_REQ = 0x1EU; // RAD_MON_ENH_REQ - Radio Unit Monitor Enhanced Request
+ const uint8_t TSBK_ISP_STS_Q_REQ = 0x1CU; // STS Q REQ - Status Query Request
const uint8_t TSBK_ISP_CAN_SRV_REQ = 0x23U; // CAN SRV REQ - Cancel Service Request
const uint8_t TSBK_ISP_EMERG_ALRM_REQ = 0x27U; // EMERG ALRM REQ - Emergency Alarm Request
const uint8_t TSBK_ISP_GRP_AFF_Q_RSP = 0x29U; // GRP AFF Q RSP - Group Affiliation Query Response
const uint8_t TSBK_ISP_U_DEREG_REQ = 0x2BU; // U DE REG REQ - Unit De-Registration Request
const uint8_t TSBK_ISP_LOC_REG_REQ = 0x2DU; // LOC REG REQ - Location Registration Request
- const uint8_t TSBK_ISP_AUTH_RESP = 0x38U; // AUTH_RESP - Authentication Response
- const uint8_t TSBK_ISP_AUTH_RESP_M = 0x39U; // AUTH_RESP_M - Authentication Response Mutual
- const uint8_t TSBK_ISP_AUTH_FNE_RST = 0x3AU; // AUTH_FNE_RST - Authentication FNE Result
- const uint8_t TSBK_ISP_AUTH_SU_DMD = 0x3BU; // AUTH_SU_DMD - Authentication SU Demand
+ const uint8_t TSBK_ISP_AUTH_RESP = 0x38U; // AUTH RESP - Authentication Response
+ const uint8_t TSBK_ISP_AUTH_RESP_M = 0x39U; // AUTH RESP M - Authentication Response Mutual
+ const uint8_t TSBK_ISP_AUTH_FNE_RST = 0x3AU; // AUTH FNE RST - Authentication FNE Result
+ const uint8_t TSBK_ISP_AUTH_SU_DMD = 0x3BU; // AUTH SU DMD - Authentication SU Demand
// TSBK Outbound Signalling Packet (OSP) Opcode(s)
const uint8_t TSBK_OSP_GRP_VCH_GRANT_UPD = 0x02U; // GRP VCH GRANT UPD - Group Voice Channel Grant Update
const uint8_t TSBK_OSP_UU_VCH_GRANT_UPD = 0x06U; // UU VCH GRANT UPD - Unit-to-Unit Voice Channel Grant Update
const uint8_t TSBK_OSP_SNDCP_CH_GNT = 0x14U; // SNDCP CH GNT - SNDCP Data Channel Grant
const uint8_t TSBK_OSP_SNDCP_CH_ANN = 0x16U; // SNDCP CH ANN - SNDCP Data Channel Announcement
- const uint8_t TSBK_OSP_STS_Q = 0x1AU; // STS_Q - Status Query
- const uint8_t TSBK_OSP_RAD_MON_CMD = 0x1DU; // RAD_MON_CMD - Radio Monitor Command
- const uint8_t TSBK_OSP_RAD_MON_ENH_CMD = 0x1EU; // RAD_MON_ENH_CMD - Radio Unit Monitor Enhanced Command
+ const uint8_t TSBK_OSP_STS_Q = 0x1AU; // STS Q - Status Query
const uint8_t TSBK_OSP_DENY_RSP = 0x27U; // DENY RSP - Deny Response
const uint8_t TSBK_OSP_SCCB_EXP = 0x29U; // SCCB - Secondary Control Channel Broadcast - Explicit
const uint8_t TSBK_OSP_GRP_AFF_Q = 0x2AU; // GRP AFF Q - Group Affiliation Query
@@ -331,8 +329,8 @@ namespace p25
const uint8_t TSBK_OSP_U_REG_CMD = 0x2DU; // U REG CMD - Unit Registration Command
const uint8_t TSBK_OSP_U_DEREG_ACK = 0x2FU; // U DE REG ACK - Unit De-Registration Acknowledge
const uint8_t TSBK_OSP_SYNC_BCAST = 0x30U; // SYNC BCAST - Synchronization Broadcast
- const uint8_t TSBK_OSP_AUTH_DMD = 0x31U; // AUTH_DMD - Authentication Demand
- const uint8_t TSBK_OSP_AUTH_FNE_RESP = 0x32U; // AUTH_FNE_RESP - Authentication FNE Response
+ const uint8_t TSBK_OSP_AUTH_DMD = 0x31U; // AUTH DMD - Authentication Demand
+ const uint8_t TSBK_OSP_AUTH_FNE_RESP = 0x32U; // AUTH FNE RESP - Authentication FNE Response
const uint8_t TSBK_OSP_QUE_RSP = 0x33U; // QUE RSP - Queued Response
const uint8_t TSBK_OSP_IDEN_UP_VU = 0x34U; // IDEN UP VU - Channel Identifier Update for VHF/UHF Bands
const uint8_t TSBK_OSP_SYS_SRV_BCAST = 0x38U; // SYS SRV BCAST - System Service Broadcast
diff --git a/p25/dfsi/LC.cpp b/p25/dfsi/LC.cpp
index b726b965..3b603b23 100644
--- a/p25/dfsi/LC.cpp
+++ b/p25/dfsi/LC.cpp
@@ -27,6 +27,7 @@
#include "p25/P25Defines.h"
#include "p25/dfsi/DFSIDefines.h"
#include "p25/dfsi/LC.h"
+#include "p25/lc/tsbk/TSBKFactory.h"
#include "p25/P25Utils.h"
#include "Log.h"
#include "Utils.h"
@@ -53,7 +54,7 @@ LC::LC() :
m_rssi(0U),
m_source(P25_DFSI_DEF_SOURCE),
m_control(),
- m_tsbk(),
+ m_tsbk(NULL),
m_lsd(),
m_mi(NULL)
{
@@ -717,7 +718,10 @@ void LC::encodeLDU2(uint8_t* data, const uint8_t* imbe)
bool LC::decodeTSBK(const uint8_t* data)
{
assert(data != NULL);
- m_tsbk = lc::TSBK();
+ if (m_tsbk != NULL) {
+ delete m_tsbk;
+ m_tsbk = NULL;
+ }
m_frameType = data[0U]; // Frame Type
if (m_frameType != P25_DFSI_TSBK) {
@@ -729,7 +733,13 @@ bool LC::decodeTSBK(const uint8_t* data)
uint8_t tsbk[P25_TSBK_LENGTH_BYTES];
::memcpy(tsbk, data + 9U, P25_TSBK_LENGTH_BYTES); // Raw TSBK + CRC
- return m_tsbk.decode(tsbk, true);
+
+ m_tsbk = lc::tsbk::TSBKFactory::createTSBK(tsbk, true);
+ if (m_tsbk != NULL) {
+ return true;
+ } else {
+ return false;
+ }
}
///
@@ -738,10 +748,11 @@ bool LC::decodeTSBK(const uint8_t* data)
///
void LC::encodeTSBK(uint8_t* data)
{
+ assert(m_tsbk != NULL);
assert(data != NULL);
uint8_t tsbk[P25_TSBK_LENGTH_BYTES];
- m_tsbk.encode(tsbk, true, true);
+ m_tsbk->encode(tsbk, true, true);
uint8_t dfsiFrame[P25_DFSI_TSBK_FRAME_LENGTH_BYTES];
::memset(dfsiFrame, 0x00U, P25_DFSI_TSBK_FRAME_LENGTH_BYTES);
@@ -777,7 +788,7 @@ void LC::copy(const LC& data)
m_source = data.m_source;
m_control = lc::LC(data.m_control);
- m_tsbk = lc::TSBK(data.m_tsbk);
+ //m_tsbk = lc::TSBK(data.m_tsbk);
m_lsd = data.m_lsd;
delete[] m_mi;
diff --git a/p25/dfsi/LC.h b/p25/dfsi/LC.h
index 8d965090..6f0f2122 100644
--- a/p25/dfsi/LC.h
+++ b/p25/dfsi/LC.h
@@ -108,7 +108,7 @@ namespace p25
/// Link control data.
__PROPERTY_PLAIN(p25::lc::LC, control, control);
/// TSBK.
- __PROPERTY_PLAIN(p25::lc::TSBK, tsbk, tsbk);
+ __PROPERTY_PLAIN(p25::lc::TSBK*, tsbk, tsbk);
/// Low speed data.
__PROPERTY_PLAIN(p25::data::LowSpeedData, lsd, lsd);
diff --git a/p25/dfsi/packet/DFSITrunk.cpp b/p25/dfsi/packet/DFSITrunk.cpp
index efa84341..2c10e379 100644
--- a/p25/dfsi/packet/DFSITrunk.cpp
+++ b/p25/dfsi/packet/DFSITrunk.cpp
@@ -41,34 +41,14 @@ using namespace p25::dfsi::packet;
// Public Class Members
// ---------------------------------------------------------------------------
-///
-/// Resets the data states for the RF interface.
-///
-void DFSITrunk::resetRF()
-{
- Trunk::resetRF();
- LC lc = LC();
- m_rfDFSILC = lc;
-}
-
-///
-/// Resets the data states for the network.
-///
-void DFSITrunk::resetNet()
-{
- Trunk::resetNet();
- LC lc = LC();
- m_netDFSILC = lc;
-}
-
///
/// Process a data frame from the RF interface.
///
/// Buffer containing data frame.
/// Length of data frame.
-/// Flag indicating the TSBK data is pre-decoded TSBK data.
+/// Pre-decoded TSBK.
///
-bool DFSITrunk::process(uint8_t* data, uint32_t len, bool preDecoded)
+bool DFSITrunk::process(uint8_t* data, uint32_t len, lc::TSBK* preDecodedTSBK)
{
assert(data != NULL);
@@ -78,16 +58,12 @@ bool DFSITrunk::process(uint8_t* data, uint32_t len, bool preDecoded)
if (!m_p25->m_control)
return false;
- if (preDecoded) {
- return Trunk::process(data + 2U, len, preDecoded);
+ if (preDecodedTSBK != NULL) {
+ return Trunk::process(data + 2U, len, preDecodedTSBK);
}
else {
- resetRF();
- resetNet();
-
if (m_rfDFSILC.decodeTSBK(data + 2U)) {
- m_rfTSBK = m_rfDFSILC.tsbk();
- return Trunk::process(tsbk, P25_TSBK_LENGTH_BYTES, true);
+ return Trunk::process(tsbk, P25_TSBK_LENGTH_BYTES, m_rfDFSILC.tsbk());
}
}
@@ -133,14 +109,17 @@ void DFSITrunk::writeRF_TDULC(lc::TDULC lc, bool noNetwork)
///
/// Helper to write a single-block P25 TSDU packet.
///
+///
///
///
///
-void DFSITrunk::writeRF_TSDU_SBF(bool noNetwork, bool clearBeforeWrite, bool force)
+void DFSITrunk::writeRF_TSDU_SBF(lc::TSBK* tsbk, bool noNetwork, bool clearBeforeWrite, bool force)
{
if (!m_p25->m_control)
return;
+ assert(tsbk != NULL);
+
writeRF_DFSI_Start(P25_DFSI_TYPE_TSBK);
uint8_t data[P25_TSDU_FRAME_LENGTH_BYTES + 2U];
@@ -149,7 +128,7 @@ void DFSITrunk::writeRF_TSDU_SBF(bool noNetwork, bool clearBeforeWrite, bool for
m_rfDFSILC.setFrameType(P25_DFSI_TSBK);
m_rfDFSILC.setStartStop(P25_DFSI_START_FLAG);
m_rfDFSILC.setType(P25_DFSI_TYPE_TSBK);
- m_rfDFSILC.tsbk(m_rfTSBK);
+ m_rfDFSILC.tsbk(tsbk);
// Generate Sync
Sync::addP25Sync(data + 2U);
@@ -158,13 +137,13 @@ void DFSITrunk::writeRF_TSDU_SBF(bool noNetwork, bool clearBeforeWrite, bool for
m_p25->m_nid.encode(data + 2U, P25_DUID_TSDU);
// Generate TSBK block
- m_rfTSBK.setLastBlock(true); // always set last block -- this a Single Block TSDU
- m_rfTSBK.encode(data + 2U);
+ tsbk->setLastBlock(true); // always set last block -- this a Single Block TSDU
+ tsbk->encode(data + 2U);
if (m_debug) {
LogDebug(LOG_RF, P25_TSDU_STR " DFSI, lco = $%02X, mfId = $%02X, lastBlock = %u, AIV = %u, EX = %u, srcId = %u, dstId = %u, sysId = $%03X, netId = $%05X",
- m_rfTSBK.getLCO(), m_rfTSBK.getMFId(), m_rfTSBK.getLastBlock(), m_rfTSBK.getAIV(), m_rfTSBK.getEX(), m_rfTSBK.getSrcId(), m_rfTSBK.getDstId(),
- m_rfTSBK.getSysId(), m_rfTSBK.getNetId());
+ tsbk->getLCO(), tsbk->getMFId(), tsbk->getLastBlock(), tsbk->getAIV(), tsbk->getEX(), tsbk->getSrcId(), tsbk->getDstId(),
+ tsbk->getSysId(), tsbk->getNetId());
Utils::dump(1U, "!!! *TSDU (SBF) TSBK Block Data", data + P25_PREAMBLE_LENGTH_BYTES + 2U, P25_TSBK_FEC_LENGTH_BYTES);
}
@@ -176,7 +155,7 @@ void DFSITrunk::writeRF_TSDU_SBF(bool noNetwork, bool clearBeforeWrite, bool for
m_p25->setBusyBits(data + 2U, P25_SS0_START, true, true);
if (!noNetwork)
- writeNetworkRF(data + 2U, true);
+ writeNetworkRF(tsbk, data + 2U, true);
if (!force) {
if (clearBeforeWrite) {
@@ -201,20 +180,26 @@ void DFSITrunk::writeRF_TSDU_SBF(bool noNetwork, bool clearBeforeWrite, bool for
///
/// Helper to write a alternate multi-block trunking PDU packet.
///
+///
///
-void DFSITrunk::writeRF_TSDU_AMBT(bool clearBeforeWrite)
+void DFSITrunk::writeRF_TSDU_AMBT(lc::AMBT* ambt, bool clearBeforeWrite)
{
if (!m_p25->m_control)
return;
+ assert(ambt != NULL);
+
// for now this is ignored...
}
///
/// Helper to write a network single-block P25 TSDU packet.
///
-void DFSITrunk::writeNet_TSDU()
+///
+void DFSITrunk::writeNet_TSDU(lc::TSBK* tsbk)
{
+ assert(tsbk != NULL);
+
uint8_t buffer[P25_DFSI_TSBK_FRAME_LENGTH_BYTES + 2U];
::memset(buffer, 0x00U, P25_DFSI_TSBK_FRAME_LENGTH_BYTES + 2U);
@@ -222,7 +207,7 @@ void DFSITrunk::writeNet_TSDU()
buffer[1U] = 0x00U;
// Regenerate TSDU Data
- m_netDFSILC.tsbk(m_netTSBK);
+ m_netDFSILC.tsbk(tsbk);
m_netDFSILC.encodeTSBK(buffer + 2U);
m_p25->addFrame(buffer, P25_DFSI_TSBK_FRAME_LENGTH_BYTES + 2U, true);
diff --git a/p25/dfsi/packet/DFSITrunk.h b/p25/dfsi/packet/DFSITrunk.h
index 195ebb83..cac6fc4e 100644
--- a/p25/dfsi/packet/DFSITrunk.h
+++ b/p25/dfsi/packet/DFSITrunk.h
@@ -52,13 +52,8 @@ namespace p25
class HOST_SW_API DFSITrunk : public p25::packet::Trunk {
public:
- /// Resets the data states for the RF interface.
- virtual void resetRF();
- /// Resets the data states for the network.
- virtual void resetNet();
-
/// Process a data frame from the RF interface.
- virtual bool process(uint8_t* data, uint32_t len, bool preDecoded = false);
+ virtual bool process(uint8_t* data, uint32_t len, lc::TSBK* preDecodedTSBK = NULL);
protected:
LC m_rfDFSILC;
@@ -73,14 +68,14 @@ namespace p25
virtual void writeRF_TDULC(lc::TDULC lc, bool noNetwork);
/// Helper to write a single-block P25 TSDU packet.
- virtual void writeRF_TSDU_SBF(bool noNetwork, bool clearBeforeWrite = false, bool force = false);
+ virtual void writeRF_TSDU_SBF(lc::TSBK* tsbk, bool noNetwork, bool clearBeforeWrite = false, bool force = false);
/// Helper to write a alternate multi-block trunking PDU packet.
- virtual void writeRF_TSDU_AMBT(bool clearBeforeWrite = false);
+ virtual void writeRF_TSDU_AMBT(lc::AMBT* ambt, bool clearBeforeWrite = false);
/// Helper to write a network P25 TDU w/ link control packet.
//virtual void writeNet_TDULC(lc::TDULC lc);
/// Helper to write a network single-block P25 TSDU packet.
- virtual void writeNet_TSDU();
+ virtual void writeNet_TSDU(lc::TSBK* tsbk);
/// Helper to write start DFSI data.
void writeRF_DFSI_Start(uint8_t type);
diff --git a/p25/dfsi/packet/DFSIVoice.cpp b/p25/dfsi/packet/DFSIVoice.cpp
index 313e7dbb..4d944c2b 100644
--- a/p25/dfsi/packet/DFSIVoice.cpp
+++ b/p25/dfsi/packet/DFSIVoice.cpp
@@ -229,15 +229,12 @@ bool DFSIVoice::process(uint8_t* data, uint32_t len)
}
}
- m_p25->m_trunk->m_rfTSBK = lc::TSBK(&lc);
- m_p25->m_trunk->m_rfTSBK.setVerbose(m_p25->m_trunk->m_dumpTSBK);
-
// validate the source RID
if (!acl::AccessControl::validateSrcId(srcId)) {
if (m_lastRejectId == 0U || m_lastRejectId != srcId) {
LogWarning(LOG_RF, P25_HDU_STR " denial, RID rejection, srcId = %u", srcId);
if (m_p25->m_control) {
- m_p25->m_trunk->writeRF_TSDU_Deny(P25_DENY_RSN_REQ_UNIT_NOT_VALID, (group ? TSBK_IOSP_GRP_VCH : TSBK_IOSP_UU_VCH));
+ m_p25->m_trunk->writeRF_TSDU_Deny(srcId, P25_DENY_RSN_REQ_UNIT_NOT_VALID, (group ? TSBK_IOSP_GRP_VCH : TSBK_IOSP_UU_VCH));
m_p25->m_trunk->denialInhibit(srcId);
}
@@ -259,7 +256,7 @@ bool DFSIVoice::process(uint8_t* data, uint32_t len)
if (m_lastRejectId == 0 || m_lastRejectId != dstId) {
LogWarning(LOG_RF, P25_HDU_STR " denial, RID rejection, dstId = %u", dstId);
if (m_p25->m_control) {
- m_p25->m_trunk->writeRF_TSDU_Deny(P25_DENY_RSN_TGT_UNIT_NOT_VALID, TSBK_IOSP_UU_VCH);
+ m_p25->m_trunk->writeRF_TSDU_Deny(srcId, P25_DENY_RSN_TGT_UNIT_NOT_VALID, TSBK_IOSP_UU_VCH);
}
::ActivityLog("P25", true, "RF voice rejection from %u to %s%u ", srcId, group ? "TG " : "", dstId);
@@ -279,7 +276,7 @@ bool DFSIVoice::process(uint8_t* data, uint32_t len)
if (m_lastRejectId == 0 || m_lastRejectId != dstId) {
LogWarning(LOG_RF, P25_HDU_STR " denial, TGID rejection, dstId = %u", dstId);
if (m_p25->m_control) {
- m_p25->m_trunk->writeRF_TSDU_Deny(P25_DENY_RSN_TGT_GROUP_NOT_VALID, TSBK_IOSP_GRP_VCH);
+ m_p25->m_trunk->writeRF_TSDU_Deny(srcId, P25_DENY_RSN_TGT_GROUP_NOT_VALID, TSBK_IOSP_GRP_VCH);
}
::ActivityLog("P25", true, "RF voice rejection from %u to %s%u ", srcId, group ? "TG " : "", dstId);
@@ -300,7 +297,7 @@ bool DFSIVoice::process(uint8_t* data, uint32_t len)
if (!m_p25->m_affiliations.isGroupAff(srcId, dstId) && m_p25->m_trunk->m_verifyAff) {
if (m_lastRejectId == 0 || m_lastRejectId != srcId) {
LogWarning(LOG_RF, P25_HDU_STR " denial, RID not affiliated to TGID, srcId = %u, dstId = %u", srcId, dstId);
- m_p25->m_trunk->writeRF_TSDU_Deny(P25_DENY_RSN_REQ_UNIT_NOT_AUTH, TSBK_IOSP_GRP_VCH);
+ m_p25->m_trunk->writeRF_TSDU_Deny(srcId, P25_DENY_RSN_REQ_UNIT_NOT_AUTH, TSBK_IOSP_GRP_VCH);
m_p25->m_trunk->writeRF_TSDU_U_Reg_Cmd(srcId);
::ActivityLog("P25", true, "RF voice rejection from %u to %s%u ", srcId, group ? "TG " : "", dstId);
@@ -321,6 +318,10 @@ bool DFSIVoice::process(uint8_t* data, uint32_t len)
m_lastRejectId = 0U;
::ActivityLog("P25", true, "RF %svoice transmission from %u to %s%u", encrypted ? "encrypted " : "", srcId, group ? "TG " : "", dstId);
+ uint8_t serviceOptions = (m_rfLC.getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
+ (m_rfLC.getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
+ (m_rfLC.getPriority() & 0x07U); // Priority
+
if (m_p25->m_control) {
// if the group wasn't granted out -- explicitly grant the group
if (!m_p25->m_affiliations.isGranted(dstId)) {
@@ -335,7 +336,7 @@ bool DFSIVoice::process(uint8_t* data, uint32_t len)
}
}
- if (!m_p25->m_trunk->writeRF_TSDU_Grant(group)) {
+ if (!m_p25->m_trunk->writeRF_TSDU_Grant(srcId, dstId, serviceOptions, group)) {
::memset(m_dfsiLDU1, 0x00U, 9U * 25U);
return false;
}
@@ -349,7 +350,7 @@ bool DFSIVoice::process(uint8_t* data, uint32_t len)
// single-channel trunking or voice on control support?
if (m_p25->m_control && m_p25->m_voiceOnControl) {
- m_p25->m_trunk->writeRF_TSDU_Grant(group, true);
+ m_p25->m_trunk->writeRF_TSDU_Grant(srcId, dstId, serviceOptions, group, true);
}
m_hadVoice = true;
@@ -406,7 +407,7 @@ bool DFSIVoice::process(uint8_t* data, uint32_t len)
m_p25->m_rfTimeout.start();
m_lastDUID = P25_DUID_HDU;
- m_rfLastHDU = lc::LC(m_p25->m_siteData);
+ m_rfLastHDU = lc::LC();
}
if (m_p25->m_rfState == RS_RF_AUDIO) {
@@ -751,9 +752,6 @@ bool DFSIVoice::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, dat
resetRF();
resetNet();
- m_p25->m_trunk->m_rfTSBK = lc::TSBK(m_p25->m_siteData, m_p25->m_idenEntry, m_p25->m_trunk->m_dumpTSBK);
- m_p25->m_trunk->m_netTSBK = lc::TSBK(m_p25->m_siteData, m_p25->m_idenEntry, m_p25->m_trunk->m_dumpTSBK);
-
writeNet_LDU1();
}
else {
@@ -934,7 +932,7 @@ void DFSIVoice::writeNet_LDU1()
}
// set network and RF link control states
- m_netLC = lc::LC(m_p25->m_siteData);
+ m_netLC = lc::LC();
m_netLC.setLCO(control.getLCO());
m_netLC.setMFId(control.getMFId());
m_netLC.setSrcId(srcId);
@@ -944,7 +942,7 @@ void DFSIVoice::writeNet_LDU1()
m_netLC.setEncrypted(control.getEncrypted());
m_netLC.setPriority(control.getPriority());
- m_rfLC = lc::LC(m_p25->m_siteData);
+ m_rfLC = lc::LC();
m_rfLC.setLCO(control.getLCO());
m_rfLC.setMFId(control.getMFId());
m_rfLC.setSrcId(srcId);
@@ -970,11 +968,6 @@ void DFSIVoice::writeNet_LDU1()
m_netLC.setKId(control.getKId());
m_rfLC.setKId(control.getKId());
- m_p25->m_trunk->m_rfTSBK = lc::TSBK(&m_rfLC);
- m_p25->m_trunk->m_rfTSBK.setVerbose(m_p25->m_trunk->m_dumpTSBK);
- m_p25->m_trunk->m_netTSBK = lc::TSBK(&m_netLC);
- m_p25->m_trunk->m_netTSBK.setVerbose(m_p25->m_trunk->m_dumpTSBK);
-
// validate source RID
if (!acl::AccessControl::validateSrcId(srcId)) {
LogWarning(LOG_NET, P25_HDU_STR " denial, RID rejection, srcId = %u", srcId);
@@ -999,9 +992,13 @@ void DFSIVoice::writeNet_LDU1()
::ActivityLog("P25", false, "network %svoice transmission from %u to %s%u", m_netLC.getEncrypted() ? "encrypted " : "", srcId, group ? "TG " : "", dstId);
+ uint8_t serviceOptions = (m_rfLC.getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
+ (m_rfLC.getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
+ (m_rfLC.getPriority() & 0x07U); // Priority
+
// single-channel trunking or voice on control support?
if (m_p25->m_control && m_p25->m_voiceOnControl) {
- if (!m_p25->m_trunk->writeRF_TSDU_Grant(group, false, true)) {
+ if (!m_p25->m_trunk->writeRF_TSDU_Grant(srcId, dstId, serviceOptions, group, false, true)) {
if (m_network != NULL)
m_network->resetP25();
@@ -1011,8 +1008,8 @@ void DFSIVoice::writeNet_LDU1()
m_p25->m_netTimeout.stop();
m_p25->m_networkWatchdog.stop();
- m_netLC = lc::LC(m_p25->m_siteData);
- m_netLastLDU1 = lc::LC(m_p25->m_siteData);
+ m_netLC = lc::LC();
+ m_netLastLDU1 = lc::LC();
m_p25->m_netState = RS_NET_IDLE;
m_p25->m_netLastDstId = 0U;
diff --git a/p25/lc/AMBT.cpp b/p25/lc/AMBT.cpp
new file mode 100644
index 00000000..da9b6453
--- /dev/null
+++ b/p25/lc/AMBT.cpp
@@ -0,0 +1,178 @@
+/**
+* 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 "p25/P25Defines.h"
+#include "p25/lc/AMBT.h"
+#include "edac/CRC.h"
+#include "HostMain.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc;
+using namespace p25;
+
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the AMBT class.
+///
+AMBT::AMBT() : TSBK()
+{
+ /* stub */
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool AMBT::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ LogError(LOG_P25, "AMBT::decode(), bad call, not implemented");
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void AMBT::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ LogError(LOG_P25, "AMBT::encode(), bad call, not implemented");
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to convert TSBK bytes to a 64-bit long value.
+///
+///
+///
+ulong64_t AMBT::tsbkValue(const data::DataHeader dataHeader, const uint8_t* pduUserData)
+{
+ ulong64_t tsbkValue = 0U;
+
+ // combine bytes into ulong64_t (8 byte) value
+ tsbkValue = dataHeader.getAMBTField8();
+ tsbkValue = (tsbkValue << 8) + dataHeader.getAMBTField9();
+ tsbkValue = (tsbkValue << 8) + pduUserData[0U];
+ tsbkValue = (tsbkValue << 8) + pduUserData[1U];
+ tsbkValue = (tsbkValue << 8) + pduUserData[2U];
+ tsbkValue = (tsbkValue << 8) + pduUserData[3U];
+ tsbkValue = (tsbkValue << 8) + pduUserData[4U];
+ tsbkValue = (tsbkValue << 8) + pduUserData[5U];
+
+ return tsbkValue;
+}
+
+///
+/// Internal helper to decode a trunking signalling block.
+///
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool AMBT::decode(const data::DataHeader dataHeader, const data::DataBlock* blocks, uint8_t* pduUserData)
+{
+ assert(blocks != NULL);
+ assert(pduUserData != NULL);
+
+ if (dataHeader.getFormat() != PDU_FMT_AMBT) {
+ LogError(LOG_P25, "TSBK::decodeMBT(), PDU is not a AMBT PDU");
+ return false;
+ }
+
+ if (dataHeader.getBlocksToFollow() == 0U) {
+ LogError(LOG_P25, "TSBK::decodeMBT(), PDU contains no data blocks");
+ return false;
+ }
+
+ m_lco = dataHeader.getAMBTOpcode(); // LCO
+ m_lastBlock = true;
+ m_mfId = dataHeader.getMFId(); // Mfg Id.
+
+ if (dataHeader.getOutbound()) {
+ LogWarning(LOG_P25, "TSBK::decodeMBT(), MBT is an outbound MBT?, mfId = $%02X, lco = $%02X", m_mfId, m_lco);
+ }
+
+ // get PDU block data
+ ::memset(pduUserData, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow());
+
+ uint32_t dataOffset = 0U;
+ for (uint8_t i = 0; i < dataHeader.getBlocksToFollow(); i++) {
+ uint32_t len = blocks[i].getData(pduUserData + dataOffset);
+ if (len != P25_PDU_UNCONFIRMED_LENGTH_BYTES) {
+ LogError(LOG_P25, "TSBK::decodeMBT(), failed to read PDU data block");
+ return false;
+ }
+
+ dataOffset += P25_PDU_UNCONFIRMED_LENGTH_BYTES;
+ }
+
+ return true;
+}
+
+///
+/// Internal helper to encode a trunking signalling block.
+///
+///
+///
+void AMBT::encode(data::DataHeader& dataHeader, uint8_t* pduUserData)
+{
+ assert(pduUserData != NULL);
+
+ dataHeader.setFormat(PDU_FMT_AMBT);
+ dataHeader.setMFId(m_mfId);
+ dataHeader.setAckNeeded(false);
+ dataHeader.setOutbound(true);
+ dataHeader.setSAP(PDU_SAP_TRUNK_CTRL);
+ dataHeader.setLLId(m_srcId);
+ dataHeader.setFullMessage(true);
+ dataHeader.setBlocksToFollow(1U);
+
+ dataHeader.setAMBTOpcode(m_lco);
+
+ // generate packet CRC-32 and set data blocks
+ if (dataHeader.getBlocksToFollow() > 1U) {
+ edac::CRC::addCRC32(pduUserData, P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow());
+ } else {
+ edac::CRC::addCRC32(pduUserData, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
+ }
+}
diff --git a/p25/lc/AMBT.h b/p25/lc/AMBT.h
new file mode 100644
index 00000000..bc6dc82d
--- /dev/null
+++ b/p25/lc/AMBT.h
@@ -0,0 +1,70 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC__AMBT_H__)
+#define __P25_LC__AMBT_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+#include "p25/data/DataHeader.h"
+#include "p25/data/DataBlock.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Represents link control data for Alternate Trunking packets.
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API AMBT : public TSBK {
+ public:
+ /// Initializes a new instance of the AMBT class.
+ AMBT();
+
+ /// Decode a alternate trunking signalling block.
+ virtual bool decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks) = 0;
+ /// Encode a alternate trunking signalling block.
+ virtual void encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData) = 0;
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ protected:
+ /// Internal helper to convert TSBK bytes to a 64-bit long value.
+ static ulong64_t tsbkValue(const data::DataHeader dataHeader, const uint8_t* pduUserData);
+
+ /// Internal helper to decode a trunking signalling block.
+ bool decode(const data::DataHeader dataHeader, const data::DataBlock* blocks, uint8_t* pduUserData);
+ /// Internal helper to encode a trunking signalling block.
+ void encode(data::DataHeader& dataHeader, uint8_t* pduUserData);
+ };
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC__AMBT_H__
diff --git a/p25/lc/LC.cpp b/p25/lc/LC.cpp
index 38c029e6..fd2ba5c0 100644
--- a/p25/lc/LC.cpp
+++ b/p25/lc/LC.cpp
@@ -45,6 +45,12 @@ using namespace p25;
#include
#include
+// ---------------------------------------------------------------------------
+// Static Class Members
+// ---------------------------------------------------------------------------
+
+SiteData LC::m_siteData = SiteData();
+
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
@@ -66,7 +72,6 @@ LC::LC() :
m_group(true),
m_algId(P25_ALGO_UNENCRYPT),
m_kId(0U),
- m_siteData(SiteData()),
m_rs(),
m_encryptOverride(false),
m_tsbkVendorSkip(false),
@@ -86,16 +91,6 @@ LC::LC(const LC& data) : LC()
copy(data);
}
-///
-/// Initializes a new instance of the LC class.
-///
-///
-LC::LC(SiteData siteData) : LC()
-{
- m_siteData = siteData;
- m_grpVchNo = m_siteData.channelNo();
-}
-
///
/// Finalizes a instance of LC class.
///
diff --git a/p25/lc/LC.h b/p25/lc/LC.h
index f6175f6b..5cfce141 100644
--- a/p25/lc/LC.h
+++ b/p25/lc/LC.h
@@ -61,8 +61,6 @@ namespace p25
LC();
/// Initializes a copy instance of the LC class.
LC(const LC& data);
- /// Initializes a new instance of the LC class.
- LC(SiteData siteData);
/// Finalizes a instance of the LC class.
~LC();
@@ -90,6 +88,12 @@ namespace p25
/// Gets the encryption message indicator.
void getMI(uint8_t* mi) const;
+ /** Local Site data */
+ /// Gets the local site data.
+ static SiteData getSiteData() { return m_siteData; }
+ /// Sets the local site data.
+ static void setSiteData(SiteData siteData) { m_siteData = siteData; }
+
public:
/** Common Data */
/// Flag indicating the link control data is protected.
@@ -123,10 +127,6 @@ namespace p25
/// Encryption key ID.
__PROPERTY(uint32_t, kId, KId);
- /** Local Site data */
- /// Local Site Data.
- __PROPERTY_PLAIN(SiteData, siteData, siteData);
-
private:
friend class TSBK;
friend class TDULC;
@@ -139,6 +139,9 @@ namespace p25
/** Encryption data */
uint8_t* m_mi;
+ /** Local Site data */
+ static SiteData m_siteData;
+
/// Internal helper to copy the class.
void copy(const LC& data);
diff --git a/p25/lc/TDULC.cpp b/p25/lc/TDULC.cpp
index 5c074cb9..464e2a9d 100644
--- a/p25/lc/TDULC.cpp
+++ b/p25/lc/TDULC.cpp
@@ -40,6 +40,15 @@ using namespace p25;
#include
#include
+// ---------------------------------------------------------------------------
+// Static Class Members
+// ---------------------------------------------------------------------------
+
+bool TDULC::m_verbose = false;
+
+SiteData TDULC::m_siteData = SiteData();
+::lookups::IdenTable TDULC::m_siteIdenEntry = ::lookups::IdenTable();
+
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
@@ -53,35 +62,11 @@ TDULC::TDULC(const TDULC& data) : TDULC()
copy(data);
}
-///
-/// Initializes a new instance of the TDULC class.
-///
-///
-///
-TDULC::TDULC(SiteData siteData, ::lookups::IdenTable entry) : TDULC(siteData)
-{
- m_siteIdenEntry = entry;
- m_grpVchNo = m_siteData.channelNo();
-}
-
-///
-/// Initializes a new instance of the TDULC class.
-///
-///
-///
-///
-TDULC::TDULC(SiteData siteData, ::lookups::IdenTable entry, bool verbose) : TDULC(siteData)
-{
- m_verbose = verbose;
- m_siteIdenEntry = entry;
- m_grpVchNo = m_siteData.channelNo();
-}
-
///
/// Initializes a new instance of the TDULC class.
///
///
-TDULC::TDULC(LC* lc) : TDULC(lc->siteData())
+TDULC::TDULC(LC* lc) : TDULC()
{
m_protect = lc->m_protect;
m_lco = lc->m_lco;
@@ -101,6 +86,32 @@ TDULC::TDULC(LC* lc) : TDULC(lc->siteData())
m_callTimer = lc->m_callTimer;
}
+///
+/// Initializes a new instance of the TDULC class.
+///
+TDULC::TDULC() :
+ m_protect(false),
+ m_lco(LC_GROUP),
+ m_mfId(P25_MFG_STANDARD),
+ m_srcId(0U),
+ m_dstId(0U),
+ m_grpVchNo(0U),
+ m_adjCFVA(P25_CFVA_FAILURE),
+ m_adjRfssId(0U),
+ m_adjSiteId(0U),
+ m_adjChannelId(0U),
+ m_adjChannelNo(0U),
+ m_adjServiceClass(P25_SVC_CLS_INVALID),
+ m_emergency(false),
+ m_encrypted(false),
+ m_priority(4U),
+ m_group(true),
+ m_rs(),
+ m_callTimer(0U)
+{
+ m_grpVchNo = m_siteData.channelNo();
+}
+
///
/// Finalizes a instance of TDULC class.
///
@@ -207,45 +218,6 @@ void TDULC::encode(uint8_t * data)
// Private Class Members
// ---------------------------------------------------------------------------
-///
-/// Initializes a new instance of the TDULC class.
-///
-/// This should never be used.
-TDULC::TDULC() : TDULC(SiteData())
-{
- /* stub */
-}
-
-///
-/// Initializes a new instance of the TDULC class.
-///
-///
-TDULC::TDULC(SiteData siteData) :
- m_verbose(false),
- m_protect(false),
- m_lco(LC_GROUP),
- m_mfId(P25_MFG_STANDARD),
- m_srcId(0U),
- m_dstId(0U),
- m_grpVchNo(0U),
- m_adjCFVA(P25_CFVA_FAILURE),
- m_adjRfssId(0U),
- m_adjSiteId(0U),
- m_adjChannelId(0U),
- m_adjChannelNo(0U),
- m_adjServiceClass(P25_SVC_CLS_INVALID),
- m_emergency(false),
- m_encrypted(false),
- m_priority(4U),
- m_group(true),
- m_siteData(siteData),
- m_siteIdenEntry(),
- m_rs(),
- m_callTimer(0U)
-{
- m_grpVchNo = m_siteData.channelNo();
-}
-
///
/// Internal helper to copy the the class.
///
diff --git a/p25/lc/TDULC.h b/p25/lc/TDULC.h
index 97734b68..6d9750b9 100644
--- a/p25/lc/TDULC.h
+++ b/p25/lc/TDULC.h
@@ -57,11 +57,9 @@ namespace p25
/// Initializes a copy instance of the TDULC class.
TDULC(const TDULC& data);
/// Initializes a new instance of the TDULC class.
- TDULC(SiteData siteData, ::lookups::IdenTable entry);
- /// Initializes a new instance of the TDULC class.
- TDULC(SiteData siteData, ::lookups::IdenTable entry, bool verbose);
- /// Initializes a new instance of the TDULC class.
TDULC(LC* lc);
+ /// Initializes a new instance of the TDULC class.
+ TDULC();
/// Finalizes a instance of the TDULC class.
~TDULC();
@@ -73,10 +71,20 @@ namespace p25
/// Encode a terminator data unit w/ link control.
void encode(uint8_t* data);
- public:
- /// Flag indicating verbose log output.
- __PROPERTY(bool, verbose, Verbose);
+ /// Sets the flag indicating verbose log output.
+ static void setVerbose(bool verbose) { m_verbose = verbose; }
+ /** Local Site data */
+ /// Gets the local site data.
+ static SiteData getSiteData() { return m_siteData; }
+ /// Sets the local site data.
+ static void setSiteData(SiteData siteData) { m_siteData = siteData; }
+ /// Gets the local site identity entry.
+ static ::lookups::IdenTable getIdenEntry() { return m_siteIdenEntry; }
+ /// Sets the local site identity entry.
+ static void setIdenEntry(::lookups::IdenTable entry) { m_siteIdenEntry = entry; }
+
+ public:
/** Common Data */
/// Flag indicating the link control data is protected.
__PROPERTY(bool, protect, Protect);
@@ -119,24 +127,19 @@ namespace p25
/// Flag indicating a group/talkgroup operation.
__PROPERTY(bool, group, Group);
- /** Local Site data */
- /// Local Site Data.
- __PROPERTY_PLAIN(SiteData, siteData, siteData);
- /// Local Site Identity Entry.
- __PROPERTY_PLAIN(::lookups::IdenTable, siteIdenEntry, siteIdenEntry);
-
- private:
- /// Initializes a new instance of the TDULC class.
- TDULC();
- /// Initializes a new instance of the TDULC class.
- TDULC(SiteData siteData);
-
+ protected:
friend class LC;
friend class TSBK;
edac::RS634717 m_rs;
uint32_t m_callTimer;
+ static bool m_verbose;
+
+ /** Local Site data */
+ static SiteData m_siteData;
+ static ::lookups::IdenTable m_siteIdenEntry;
+
/// Internal helper to copy the class.
void copy(const TDULC& data);
diff --git a/p25/lc/TSBK.cpp b/p25/lc/TSBK.cpp
index e686de07..bd33e23a 100644
--- a/p25/lc/TSBK.cpp
+++ b/p25/lc/TSBK.cpp
@@ -8,7 +8,6 @@
*/
/*
* Copyright (C) 2017-2022 by Bryan Biedenkapp N2PLL
-* Copyright (C) 2022 by Jason- UWU - TIME_DATE_ANN & RAD_MON_CMD
*
* 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
@@ -29,19 +28,27 @@
#include "p25/lc/TSBK.h"
#include "p25/P25Utils.h"
#include "edac/CRC.h"
-#include "HostMain.h"
#include "Log.h"
#include "Utils.h"
using namespace p25::lc;
using namespace p25;
-#include
-#include
#include
-#include
-#include
-#include
+
+// ---------------------------------------------------------------------------
+// Static Class Members
+// ---------------------------------------------------------------------------
+
+bool TSBK::m_verbose = false;
+#if FORCE_TSBK_CRC_WARN
+bool TSBK::m_warnCRC = true;
+#else
+bool TSBK::m_warnCRC = false;
+#endif
+
+uint8_t *TSBK::m_siteCallsign = NULL;
+SiteData TSBK::m_siteData = SiteData();
// ---------------------------------------------------------------------------
// Public Class Members
@@ -56,44 +63,11 @@ TSBK::TSBK(const TSBK& data) : TSBK()
copy(data);
}
-///
-/// Initializes a new instance of the TSBK class.
-///
-///
-///
-TSBK::TSBK(SiteData siteData, ::lookups::IdenTable entry) : TSBK(siteData)
-{
- m_siteIdenEntry = entry;
-}
-
-///
-/// Initializes a new instance of the TSBK class.
-///
-///
-///
-///
-TSBK::TSBK(SiteData siteData, ::lookups::IdenTable entry, bool verbose) : TSBK(siteData, entry, verbose, false)
-{
- m_verbose = verbose;
-}
-
-///
-/// Initializes a new instance of the TSBK class.
-///
-///
-///
-///
-TSBK::TSBK(SiteData siteData, ::lookups::IdenTable entry, bool verbose, bool warnCRC) : TSBK(siteData)
-{
- m_warnCRC = warnCRC;
- m_siteIdenEntry = entry;
-}
-
///
/// Initializes a new instance of the TSBK class.
///
///
-TSBK::TSBK(LC* lc) : TSBK(lc->siteData())
+TSBK::TSBK(LC* lc) : TSBK()
{
m_protect = lc->m_protect;
m_lco = lc->m_lco;
@@ -102,8 +76,6 @@ TSBK::TSBK(LC* lc) : TSBK(lc->siteData())
m_srcId = lc->m_srcId;
m_dstId = lc->m_dstId;
- m_grpVchNo = lc->m_grpVchNo;
-
m_emergency = lc->m_emergency;
m_encrypted = lc->m_encrypted;
m_priority = lc->m_priority;
@@ -112,380 +84,125 @@ TSBK::TSBK(LC* lc) : TSBK(lc->siteData())
}
///
-/// Finalizes a instance of TSBK class.
+/// Initializes a new instance of the TSBK class.
///
-TSBK::~TSBK()
+/// This should never be used.
+TSBK::TSBK() :
+ m_protect(false),
+ m_lco(LC_GROUP),
+ m_mfId(P25_MFG_STANDARD),
+ m_srcId(0U),
+ m_dstId(0U),
+ m_lastBlock(false),
+ m_aivFlag(true),
+ m_extendedAddrFlag(false),
+ m_service(0U),
+ m_response(P25_RSP_ACCEPT),
+ m_netId(P25_WACN_STD_DEFAULT),
+ m_sysId(P25_SID_STD_DEFAULT),
+ m_emergency(false),
+ m_encrypted(false),
+ m_priority(4U),
+ m_group(true),
+ m_rs(),
+ m_trellis()
{
- if (m_authRes != NULL) {
- delete[] m_authRes;
- m_authRes = NULL;
- }
-
- if (m_authRS != NULL) {
- delete[] m_authRS;
- m_authRS = NULL;
- }
-
- if (m_authRC != NULL) {
- delete[] m_authRC;
- m_authRC = NULL;
+ if (m_siteCallsign == NULL) {
+ m_siteCallsign = new uint8_t[P25_MOT_CALLSIGN_LENGTH_BYTES];
+ ::memset(m_siteCallsign, 0x00U, P25_MOT_CALLSIGN_LENGTH_BYTES);
}
- delete[] m_siteCallsign;
+#if FORCE_TSBK_CRC_WARN
+ m_warnCRC = true;
+#endif
}
///
-/// Equals operator.
+/// Finalizes a instance of TSBK class.
///
-///
-///
-TSBK& TSBK::operator=(const TSBK& data)
+TSBK::~TSBK()
{
- if (this != &data) {
- copy(data);
- }
-
- return *this;
+ /* stub */
}
///
-/// Decode a alternate trunking signalling block.
+/// Sets the callsign.
///
-///
-///
-/// True, if TSBK was decoded, otherwise false.
-bool TSBK::decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks)
+/// Callsign.
+void TSBK::setCallsign(std::string callsign)
{
- assert(blocks != NULL);
-
- if (dataHeader.getFormat() != PDU_FMT_AMBT) {
- LogError(LOG_P25, "TSBK::decodeMBT(), PDU is not a AMBT PDU");
- return false;
- }
-
- if (dataHeader.getBlocksToFollow() == 0U) {
- LogError(LOG_P25, "TSBK::decodeMBT(), PDU contains no data blocks");
- return false;
- }
-
- m_lco = dataHeader.getAMBTOpcode(); // LCO
- m_lastBlock = true;
- m_mfId = dataHeader.getMFId(); // Mfg Id.
+ uint32_t idLength = callsign.length();
+ if (idLength > 0) {
+ ::memset(m_siteCallsign, 0x20U, P25_MOT_CALLSIGN_LENGTH_BYTES);
- if (dataHeader.getOutbound()) {
- LogWarning(LOG_P25, "TSBK::decodeMBT(), MBT is an outbound MBT?, mfId = $%02X, lco = $%02X", m_mfId, m_lco);
+ if (idLength > P25_MOT_CALLSIGN_LENGTH_BYTES)
+ idLength = P25_MOT_CALLSIGN_LENGTH_BYTES;
+ for (uint32_t i = 0; i < idLength; i++)
+ m_siteCallsign[i] = callsign[i];
}
+}
- // get PDU block data
- uint8_t pduUserData[P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow()];
- ::memset(pduUserData, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow());
-
- uint32_t dataOffset = 0U;
- for (uint8_t i = 0; i < dataHeader.getBlocksToFollow(); i++) {
- uint32_t len = blocks[i].getData(pduUserData + dataOffset);
- if (len != P25_PDU_UNCONFIRMED_LENGTH_BYTES) {
- LogError(LOG_P25, "TSBK::decodeMBT(), failed to read PDU data block");
- return false;
- }
-
- dataOffset += P25_PDU_UNCONFIRMED_LENGTH_BYTES;
- }
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+///
+/// Internal helper to convert TSBK bytes to a 64-bit long value.
+///
+///
+///
+ulong64_t TSBK::tsbkValue(const uint8_t* tsbk)
+{
ulong64_t tsbkValue = 0U;
// combine bytes into ulong64_t (8 byte) value
- tsbkValue = dataHeader.getAMBTField8();
- tsbkValue = (tsbkValue << 8) + dataHeader.getAMBTField9();
- tsbkValue = (tsbkValue << 8) + pduUserData[0U];
- tsbkValue = (tsbkValue << 8) + pduUserData[1U];
- tsbkValue = (tsbkValue << 8) + pduUserData[2U];
- tsbkValue = (tsbkValue << 8) + pduUserData[3U];
- tsbkValue = (tsbkValue << 8) + pduUserData[4U];
- tsbkValue = (tsbkValue << 8) + pduUserData[5U];
-
- // Motorola P25 vendor opcodes
- if (m_mfId == P25_MFG_MOT) {
- switch (m_lco) {
- case TSBK_IOSP_GRP_VCH:
- case TSBK_IOSP_UU_VCH:
- case TSBK_IOSP_UU_ANS:
- case TSBK_IOSP_TELE_INT_ANS:
- case TSBK_IOSP_STS_UPDT:
- case TSBK_IOSP_STS_Q:
- case TSBK_IOSP_MSG_UPDT:
- case TSBK_IOSP_CALL_ALRT:
- case TSBK_IOSP_ACK_RSP:
- case TSBK_IOSP_GRP_AFF:
- case TSBK_IOSP_U_REG:
- case TSBK_ISP_CAN_SRV_REQ:
- case TSBK_ISP_GRP_AFF_Q_RSP:
- case TSBK_OSP_DENY_RSP:
- case TSBK_OSP_QUE_RSP:
- case TSBK_ISP_U_DEREG_REQ:
- case TSBK_OSP_U_DEREG_ACK:
- case TSBK_ISP_LOC_REG_REQ:
- m_mfId = P25_MFG_STANDARD;
- break;
- default:
- LogError(LOG_P25, "TSBK::decodeMBT(), unknown TSBK LCO value, mfId = $%02X, lco = $%02X", m_mfId, m_lco);
- break;
- }
-
- if (m_mfId == P25_MFG_MOT) {
- return true;
- }
- else {
- m_mfId = dataHeader.getMFId();
- }
- }
-
- // standard P25 reference opcodes
- switch (m_lco) {
- case TSBK_IOSP_STS_UPDT:
- m_statusValue = (uint8_t)((tsbkValue >> 48) & 0xFFFFU); // Message Value
- m_netId = (uint32_t)((tsbkValue >> 28) & 0xFFFFFU); // Network ID
- m_sysId = (uint32_t)((tsbkValue >> 16) & 0xFFFU); // System ID
- m_dstId = (uint32_t)(((tsbkValue) & 0xFFFFU) << 8) + pduUserData[6U]; // Target Radio Address
- m_srcId = dataHeader.getLLId(); // Source Radio Address
- break;
- case TSBK_IOSP_MSG_UPDT:
- m_messageValue = (uint32_t)((tsbkValue >> 48) & 0xFFFFU); // Message Value
- m_netId = (uint32_t)((tsbkValue >> 28) & 0xFFFFFU); // Network ID
- m_sysId = (uint32_t)((tsbkValue >> 16) & 0xFFFU); // System ID
- m_dstId = (uint32_t)(((tsbkValue) & 0xFFFFU) << 8) + pduUserData[6U]; // Target Radio Address
- m_srcId = dataHeader.getLLId(); // Source Radio Address
- break;
- case TSBK_IOSP_CALL_ALRT:
- m_netId = (uint32_t)((tsbkValue >> 44) & 0xFFFFFU); // Network ID
- m_sysId = (uint32_t)((tsbkValue >> 32) & 0xFFFU); // System ID
- m_dstId = (uint32_t)((tsbkValue >> 8) & 0xFFFFFFU); // Target Radio Address
- m_srcId = dataHeader.getLLId(); // Source Radio Address
- break;
- case TSBK_IOSP_ACK_RSP:
- m_aivFlag = false;
- m_service = (uint8_t)((tsbkValue >> 56) & 0x3FU); // Service Type
- m_netId = (uint32_t)((tsbkValue >> 36) & 0xFFFFFU); // Network ID
- m_sysId = (uint32_t)((tsbkValue >> 24) & 0xFFFU); // System ID
- m_dstId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Target Radio Address
- m_srcId = dataHeader.getLLId(); // Source Radio Address
- break;
- case TSBK_IOSP_GRP_AFF:
- m_netId = (uint32_t)((tsbkValue >> 44) & 0xFFFFFU); // Network ID
- m_sysId = (uint32_t)((tsbkValue >> 32) & 0xFFFU); // System ID
- m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFU); // Talkgroup Address
- m_srcId = dataHeader.getLLId(); // Source Radio Address
- break;
- case TSBK_ISP_CAN_SRV_REQ:
- m_aivFlag = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Additional Info. Flag
- m_service = (uint8_t)((tsbkValue >> 56) & 0x3FU); // Service Type
- m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Reason
- m_netId = (uint32_t)((tsbkValue >> 20) & 0xFFFFFU); // Network ID
- m_sysId = (uint32_t)((tsbkValue >> 8) & 0xFFFU); // System ID
- m_dstId = (uint32_t)((((tsbkValue) & 0xFFU) << 16) + // Target Radio Address
- (pduUserData[6U] << 8) + (pduUserData[7U]));
- m_srcId = dataHeader.getLLId(); // Source Radio Address
- break;
- case TSBK_IOSP_EXT_FNCT:
- m_netId = (uint32_t)((tsbkValue >> 44) & 0xFFFFFU); // Network ID
- m_sysId = (uint32_t)((tsbkValue >> 32) & 0xFFFU); // System ID
- m_extendedFunction = (uint32_t)(((tsbkValue) & 0xFFFFU) << 8) + // Extended Function
- pduUserData[6U];
- m_srcId = dataHeader.getLLId(); // Source Radio Address
- break;
- case TSBK_ISP_AUTH_RESP_M:
- {
- if (dataHeader.getBlocksToFollow() != 2) {
- LogError(LOG_P25, "TSBK::decodeMBT(), PDU does not contain the appropriate amount of data blocks");
- return false;
- }
-
- m_netId = (uint32_t)((tsbkValue >> 44) & 0xFFFFFU); // Network ID
- m_sysId = (uint32_t)((tsbkValue >> 32) & 0xFFFU); // System ID
- m_srcId = dataHeader.getLLId(); // Source Radio Address
-
- /** Block 1 */
- m_authRC[4U] = (uint8_t)pduUserData[5U] & 0xFFU; // Random Challenge b4
- m_authRC[3U] = (uint8_t)pduUserData[6U] & 0xFFU; // Random Challenge b3
- m_authRC[2U] = (uint8_t)pduUserData[7U] & 0xFFU; // Random Challenge b2
- m_authRC[1U] = (uint8_t)pduUserData[8U] & 0xFFU; // Random Challenge b1
- m_authRC[0U] = (uint8_t)pduUserData[9U] & 0xFFU; // Random Challenge b0
- m_authRes[3U] = (uint8_t)pduUserData[10U] & 0xFFU; // Result b3
- m_authRes[2U] = (uint8_t)pduUserData[11U] & 0xFFU; // Result b2
-
- /** Block 2 */
- m_authRes[1U] = (uint8_t)pduUserData[12U] & 0xFFU; // Result b1
- m_authRes[0U] = (uint8_t)pduUserData[13U] & 0xFFU; // Result b0
- m_authStandalone = ((pduUserData[14U] & 0xFFU) & 0x01U) == 0x01U; // Authentication Standalone Flag
- }
- break;
- case TSBK_ISP_AUTH_SU_DMD:
- m_netId = (uint32_t)((tsbkValue >> 44) & 0xFFFFFU); // Network ID
- m_sysId = (uint32_t)((tsbkValue >> 32) & 0xFFFU); // System ID
- m_srcId = dataHeader.getLLId(); // Source Radio Address
- break;
- default:
- LogError(LOG_P25, "TSBK::decodeMBT(), unknown TSBK LCO value, mfId = $%02X, lco = $%02X", m_mfId, m_lco);
- break;
- }
+ tsbkValue = tsbk[2U];
+ tsbkValue = (tsbkValue << 8) + tsbk[3U];
+ tsbkValue = (tsbkValue << 8) + tsbk[4U];
+ tsbkValue = (tsbkValue << 8) + tsbk[5U];
+ tsbkValue = (tsbkValue << 8) + tsbk[6U];
+ tsbkValue = (tsbkValue << 8) + tsbk[7U];
+ tsbkValue = (tsbkValue << 8) + tsbk[8U];
+ tsbkValue = (tsbkValue << 8) + tsbk[9U];
- return true;
+ return tsbkValue;
}
///
-/// Encode a alternate trunking signalling block.
+/// Internal helper to convert a 64-bit long value to TSBK bytes.
///
-///
-///
-void TSBK::encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData)
+///
+///
+uint8_t* TSBK::tsbkValue(const ulong64_t tsbkValue)
{
- assert(pduUserData != NULL);
-
- dataHeader.setFormat(PDU_FMT_AMBT);
- dataHeader.setMFId(m_mfId);
- dataHeader.setAckNeeded(false);
- dataHeader.setOutbound(true);
- dataHeader.setSAP(PDU_SAP_TRUNK_CTRL);
- dataHeader.setLLId(m_srcId);
- dataHeader.setFullMessage(true);
- dataHeader.setBlocksToFollow(1U);
-
- dataHeader.setAMBTOpcode(m_lco);
-
- // standard P25 reference opcodes
- switch (m_lco) {
- case TSBK_OSP_AUTH_DMD:
- {
- dataHeader.setBlocksToFollow(2U);
-
- dataHeader.setAMBTField8((m_netId >> 12) & 0xFFU); // Network ID (b19-12)
- dataHeader.setAMBTField9((m_netId >> 4) & 0xFFU); // Network ID (b11-b4)
-
- /** Block 1 */
- pduUserData[0U] = ((m_netId & 0x0FU) << 4) + ((m_sysId >> 8) & 0xFFU); // Network ID (b3-b0) + System ID (b11-b8)
- pduUserData[1U] = (m_sysId & 0xFFU); // System ID (b7-b0)
-
- __SET_UINT16(m_dstId, pduUserData, 2U); // Target Radio Address
-
- pduUserData[5U] = m_authRS[9U]; // Random Salt b9
- pduUserData[6U] = m_authRS[8U]; // Random Salt b8
- pduUserData[7U] = m_authRS[7U]; // Random Salt b7
- pduUserData[8U] = m_authRS[6U]; // Random Salt b6
- pduUserData[9U] = m_authRS[5U]; // Random Salt b5
- pduUserData[10U] = m_authRS[4U]; // Random Salt b4
- pduUserData[11U] = m_authRS[3U]; // Random Salt b3
-
- /** Block 2 */
- pduUserData[12U] = m_authRS[2U]; // Random Salt b2
- pduUserData[13U] = m_authRS[1U]; // Random Salt b1
- pduUserData[14U] = m_authRS[0U]; // Random Salt b0
- pduUserData[15U] = m_authRC[4U]; // Random Challenge b4
- pduUserData[16U] = m_authRC[3U]; // Random Challenge b3
- pduUserData[17U] = m_authRC[2U]; // Random Challenge b2
- pduUserData[18U] = m_authRC[1U]; // Random Challenge b1
- pduUserData[19U] = m_authRC[0U]; // Random Challenge b0
- }
- break;
- case TSBK_OSP_RFSS_STS_BCAST:
- {
- // pack LRA and system ID into LLID
- uint32_t llId = m_siteData.lra(); // Location Registration Area
- llId = (llId << 12) + m_siteData.siteId(); // System ID
- if (m_siteData.netActive()) {
- llId |= 0x1000U; // Network Active Flag
- }
- dataHeader.setLLId(llId);
-
- /** Block 1 */
- pduUserData[0U] = (m_siteData.rfssId()) & 0xFFU; // RF Sub-System ID
- pduUserData[1U] = (m_siteData.siteId()) & 0xFFU; // Site ID
- pduUserData[2U] = ((m_siteData.channelId() & 0x0FU) << 4) + // Transmit Channel ID & Channel Number MSB
- ((m_siteData.channelNo() >> 8) & 0xFFU);
- pduUserData[3U] = (m_siteData.channelNo() >> 0) & 0xFFU; // Transmit Channel Number LSB
- pduUserData[4U] = ((m_siteData.channelId() & 0x0FU) << 4) + // Receive Channel ID & Channel Number MSB
- ((m_siteData.channelNo() >> 8) & 0xFFU);
- pduUserData[5U] = (m_siteData.channelNo() >> 0) & 0xFFU; // Receive Channel Number LSB
- pduUserData[6U] = m_siteData.serviceClass(); // System Service Class
- }
- break;
- case TSBK_OSP_NET_STS_BCAST:
- {
- // pack LRA and system ID into LLID
- uint32_t llId = m_siteData.lra(); // Location Registration Area
- llId = (llId << 12) + m_siteData.siteId(); // System ID
- dataHeader.setLLId(llId);
-
- /** Block 1 */
- pduUserData[0U] = (m_siteData.netId() >> 12) & 0xFFU; // Network ID (b19-12)
- pduUserData[1U] = (m_siteData.netId() >> 4) & 0xFFU; // Network ID (b11-b4)
- pduUserData[2U] = (m_siteData.netId() & 0x0FU) << 4; // Network ID (b3-b0)
- pduUserData[3U] = ((m_siteData.channelId() & 0x0FU) << 4) + // Transmit Channel ID & Channel Number MSB
- ((m_siteData.channelNo() >> 8) & 0xFFU);
- pduUserData[4U] = (m_siteData.channelNo() >> 0) & 0xFFU; // Transmit Channel Number LSB
- pduUserData[5U] = ((m_siteData.channelId() & 0x0FU) << 4) + // Receive Channel ID & Channel Number MSB
- ((m_siteData.channelNo() >> 8) & 0xFFU);
- pduUserData[6U] = (m_siteData.channelNo() >> 0) & 0xFFU; // Receive Channel Number LSB
- pduUserData[7U] = m_siteData.serviceClass(); // System Service Class
- }
- break;
- case TSBK_OSP_ADJ_STS_BCAST:
- {
- if ((m_adjRfssId != 0U) && (m_adjSiteId != 0U) && (m_adjChannelNo != 0U)) {
- if (m_adjSysId == 0U) {
- m_adjSysId = m_siteData.sysId();
- }
-
- // pack LRA, CFVA and system ID into LLID
- uint32_t llId = m_siteData.lra(); // Location Registration Area
- llId = (llId << 8) + m_adjCFVA; // CFVA
- llId = (llId << 4) + m_siteData.siteId(); // System ID
- dataHeader.setLLId(llId);
-
- dataHeader.setAMBTField8(m_adjRfssId); // RF Sub-System ID
- dataHeader.setAMBTField9(m_adjSiteId); // Site ID
+ uint8_t* tsbk = new uint8_t[P25_TSBK_LENGTH_BYTES];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
- /** Block 1 */
- pduUserData[0U] = ((m_adjChannelId & 0x0FU) << 4) + // Transmit Channel ID & Channel Number MSB
- ((m_adjChannelNo >> 8) & 0xFFU);
- pduUserData[1U] = (m_adjChannelNo >> 0) & 0xFFU; // Transmit Channel Number LSB
- pduUserData[2U] = ((m_adjChannelId & 0x0FU) << 4) + // Receive Channel ID & Channel Number MSB
- ((m_adjChannelNo >> 8) & 0xFFU);
- pduUserData[3U] = (m_adjChannelNo >> 0) & 0xFFU; // Receive Channel Number LSB
- pduUserData[4U] = m_adjServiceClass; // System Service Class
- pduUserData[5U] = (m_siteData.netId() >> 12) & 0xFFU; // Network ID (b19-12)
- pduUserData[6U] = (m_siteData.netId() >> 4) & 0xFFU; // Network ID (b11-b4)
- pduUserData[7U] = (m_siteData.netId() & 0x0FU) << 4; // Network ID (b3-b0)
- }
- else {
- LogError(LOG_P25, "TSBK::encodeMBT(), invalid values for OSP_ADJ_STS_BCAST, adjRfssId = $%02X, adjSiteId = $%02X, adjChannelId = %u, adjChannelNo = $%02X, adjSvcClass = $%02X",
- m_adjRfssId, m_adjSiteId, m_adjChannelId, m_adjChannelNo, m_adjServiceClass);
- return; // blatently ignore creating this TSBK
- }
- }
- break;
- default:
- LogError(LOG_P25, "TSBK::encodeMBT(), unknown TSBK LCO value, mfId = $%02X, lco = $%02X", m_mfId, m_lco);
- break;
- }
+ // split ulong64_t (8 byte) value into bytes
+ tsbk[2U] = (uint8_t)((tsbkValue >> 56) & 0xFFU);
+ tsbk[3U] = (uint8_t)((tsbkValue >> 48) & 0xFFU);
+ tsbk[4U] = (uint8_t)((tsbkValue >> 40) & 0xFFU);
+ tsbk[5U] = (uint8_t)((tsbkValue >> 32) & 0xFFU);
+ tsbk[6U] = (uint8_t)((tsbkValue >> 24) & 0xFFU);
+ tsbk[7U] = (uint8_t)((tsbkValue >> 16) & 0xFFU);
+ tsbk[8U] = (uint8_t)((tsbkValue >> 8) & 0xFFU);
+ tsbk[9U] = (uint8_t)((tsbkValue >> 0) & 0xFFU);
- // generate packet CRC-32 and set data blocks
- if (dataHeader.getBlocksToFollow() > 1U) {
- edac::CRC::addCRC32(pduUserData, P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow());
- } else {
- edac::CRC::addCRC32(pduUserData, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
- }
+ return tsbk;
}
///
-/// Decode a trunking signalling block.
+/// Internal helper to decode a trunking signalling block.
///
///
+///
///
/// True, if TSBK was decoded, otherwise false.
-bool TSBK::decode(const uint8_t* data, bool rawTSBK)
+bool TSBK::decode(const uint8_t* data, uint8_t* tsbk, bool rawTSBK)
{
assert(data != NULL);
+ assert(tsbk != NULL);
- uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
if (rawTSBK) {
::memcpy(tsbk, data, P25_TSBK_LENGTH_BYTES);
@@ -542,232 +259,6 @@ bool TSBK::decode(const uint8_t* data, bool rawTSBK)
m_lastBlock = (tsbk[0U] & 0x80U) == 0x80U; // Last Block Marker
m_mfId = tsbk[1U]; // Mfg Id.
- ulong64_t tsbkValue = 0U;
-
- // combine bytes into ulong64_t (8 byte) value
- tsbkValue = tsbk[2U];
- tsbkValue = (tsbkValue << 8) + tsbk[3U];
- tsbkValue = (tsbkValue << 8) + tsbk[4U];
- tsbkValue = (tsbkValue << 8) + tsbk[5U];
- tsbkValue = (tsbkValue << 8) + tsbk[6U];
- tsbkValue = (tsbkValue << 8) + tsbk[7U];
- tsbkValue = (tsbkValue << 8) + tsbk[8U];
- tsbkValue = (tsbkValue << 8) + tsbk[9U];
-
- // Motorola P25 vendor opcodes
- if (m_mfId == P25_MFG_MOT) {
- switch (m_lco) {
- case TSBK_IOSP_GRP_VCH:
- case TSBK_IOSP_UU_VCH:
- case TSBK_IOSP_UU_ANS:
- case TSBK_IOSP_TELE_INT_ANS:
- case TSBK_IOSP_STS_UPDT:
- case TSBK_IOSP_STS_Q:
- case TSBK_IOSP_MSG_UPDT:
- case TSBK_IOSP_CALL_ALRT:
- case TSBK_IOSP_ACK_RSP:
- case TSBK_IOSP_GRP_AFF:
- case TSBK_IOSP_U_REG:
- case TSBK_ISP_CAN_SRV_REQ:
- case TSBK_ISP_GRP_AFF_Q_RSP:
- case TSBK_OSP_DENY_RSP:
- case TSBK_OSP_QUE_RSP:
- case TSBK_ISP_U_DEREG_REQ:
- case TSBK_OSP_U_DEREG_ACK:
- case TSBK_ISP_LOC_REG_REQ:
- m_mfId = P25_MFG_STANDARD;
- break;
- default:
- LogError(LOG_P25, "TSBK::decode(), unknown TSBK LCO value, mfId = $%02X, lco = $%02X", m_mfId, m_lco);
- break;
- }
-
- if (m_mfId == P25_MFG_MOT) {
- return true;
- }
- else {
- m_mfId = tsbk[1U];
- }
- }
-
- // internal P25 vendor opcodes
- if (m_mfId == P25_MFG_DVM) {
- switch (m_lco) {
- case LC_CALL_TERM:
- m_grpVchId = ((tsbkValue >> 52) & 0x0FU); // Channel ID
- m_grpVchNo = ((tsbkValue >> 40) & 0xFFFU); // Channel Number
- m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFU); // Target Radio Address
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- default:
- m_mfId = P25_MFG_STANDARD;
- break;
- }
-
- if (m_mfId == P25_MFG_DVM) {
- return true;
- }
- else {
- m_mfId = tsbk[1U];
- }
- }
-
- // standard P25 reference opcodes
- switch (m_lco) {
- case TSBK_IOSP_GRP_VCH:
- m_emergency = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Emergency Flag
- m_encrypted = (((tsbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Encryption Flag
- m_priority = (((tsbkValue >> 56) & 0xFFU) & 0x07U); // Priority
- m_grpVchId = ((tsbkValue >> 52) & 0x0FU); // Channel ID
- m_grpVchNo = ((tsbkValue >> 40) & 0xFFFU); // Channel Number
- m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFU); // Target Radio Address
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_IOSP_UU_VCH:
- m_emergency = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Emergency Flag
- m_encrypted = (((tsbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Encryption Flag
- m_priority = (((tsbkValue >> 56) & 0xFFU) & 0x07U); // Priority
- m_grpVchId = ((tsbkValue >> 52) & 0x0FU); // Channel ID
- m_grpVchNo = ((tsbkValue >> 40) & 0xFFFU); // Channel Number
- m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_IOSP_UU_ANS:
- m_emergency = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Emergency Flag
- m_encrypted = (((tsbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Encryption Flag
- m_priority = (((tsbkValue >> 56) & 0xFFU) & 0x07U); // Priority
- m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Answer Response
- m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_IOSP_TELE_INT_ANS:
- m_emergency = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Emergency Flag
- m_encrypted = (((tsbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Encryption Flag
- m_priority = (((tsbkValue >> 56) & 0xFFU) & 0x07U); // Priority
- m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Answer Response
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_ISP_SNDCP_CH_REQ:
- m_dataServiceOptions = (uint8_t)((tsbkValue >> 56) & 0xFFU); // Data Service Options
- m_dataAccessControl = (uint32_t)((tsbkValue >> 40) & 0xFFFFFFFFU); // Data Access Control
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_IOSP_STS_UPDT:
- m_statusValue = (uint8_t)((tsbkValue >> 56) & 0xFFU); // Status Value
- m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_IOSP_MSG_UPDT:
- m_messageValue = (uint32_t)((tsbkValue >> 48) & 0xFFFFU); // Message Value
- m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_ISP_RAD_MON_REQ:
- m_txMult = (uint8_t)((tsbkValue >> 48) & 0x3U); // TX Multiplier
- m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_IOSP_CALL_ALRT:
- m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_IOSP_ACK_RSP:
- m_aivFlag = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Additional Info. Flag
- m_service = (uint8_t)((tsbkValue >> 56) & 0x3FU); // Service Type
- m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_ISP_EMERG_ALRM_REQ: // TSBK_OSP_DENY_RSP
- /*
- ** these are used by TSBK_OSP_DENY_RSP; best way to check is for m_response > 0
- */
- m_aivFlag = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Additional Info. Flag
- m_service = (uint8_t)((tsbkValue >> 56) & 0x3FU); // Service Type
- m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Reason
-
- if (m_response == 0U) {
- m_emergency = true;
- } else {
- m_emergency = false;
- }
-
- m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFU); // Target Radio Address
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_IOSP_EXT_FNCT:
- m_extendedFunction = (uint32_t)((tsbkValue >> 48) & 0xFFFFU); // Extended Function
- m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Argument
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Target Radio Address
- break;
- case TSBK_IOSP_GRP_AFF:
- m_sysId = (uint32_t)((tsbkValue >> 40) & 0xFFFU); // System ID
- m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFU); // Talkgroup Address
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_IOSP_U_REG:
- m_netId = (uint32_t)((tsbkValue >> 36) & 0xFFFFFU); // Network ID
- m_sysId = (uint32_t)((tsbkValue >> 24) & 0xFFFU); // System ID
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_ISP_CAN_SRV_REQ:
- m_aivFlag = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Additional Info. Flag
- m_service = (uint8_t)((tsbkValue >> 56) & 0x3FU); // Service Type
- m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Reason
- m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_ISP_GRP_AFF_Q_RSP:
- m_patchSuperGroupId = (uint32_t)((tsbkValue >> 40) & 0xFFFFU); // Announcement Group Address
- m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFU); // Talkgroup Address
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_OSP_QUE_RSP:
- m_aivFlag = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Additional Info. Flag
- m_service = (uint8_t)((tsbkValue >> 56) & 0x3FU); // Service Type
- m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Reason
- m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_ISP_U_DEREG_REQ:
- case TSBK_OSP_U_DEREG_ACK:
- m_netId = (uint32_t)((tsbkValue >> 36) & 0xFFFFFU); // Network ID
- m_sysId = (uint32_t)((tsbkValue >> 24) & 0xFFFU); // System ID
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_ISP_LOC_REG_REQ:
- m_lra = (uint8_t)((tsbkValue >> 40) & 0xFFU); // LRA
- m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFU); // Talkgroup Address
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_ISP_AUTH_RESP:
- m_authStandalone = (((tsbkValue >> 56) & 0xFFU) & 0x01U) == 0x01U; // Authentication Standalone Flag
- m_authRes[3U] = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Result b3
- m_authRes[2U] = (uint8_t)((tsbkValue >> 40) & 0xFFU); // Result b2
- m_authRes[1U] = (uint8_t)((tsbkValue >> 32) & 0xFFU); // Result b1
- m_authRes[0U] = (uint8_t)((tsbkValue >> 24) & 0xFFU); // Result b0
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_ISP_AUTH_FNE_RST:
- m_authSuccess = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Authentication Success Flag
- m_authStandalone = (((tsbkValue >> 56) & 0xFFU) & 0x01U) == 0x01U; // Authentication Standalone Flag
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_ISP_AUTH_SU_DMD:
- m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
- break;
- case TSBK_OSP_ADJ_STS_BCAST:
- 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
- m_adjChannelId = (uint8_t)((tsbkValue >> 20) & 0xFU); // Site Channel ID
- m_adjChannelNo = (uint32_t)((tsbkValue >> 8) & 0xFFFU); // Site Channel Number
- m_adjServiceClass = (uint8_t)(tsbkValue & 0xFFU); // Site Service Class
- break;
- default:
- LogError(LOG_P25, "TSBK::decode(), unknown TSBK LCO value, mfId = $%02X, lco = $%02X", m_mfId, m_lco);
- break;
- }
-
return true;
}
@@ -775,582 +266,40 @@ bool TSBK::decode(const uint8_t* data, bool rawTSBK)
/// Encode a trunking signalling block.
///
///
+///
///
///
-void TSBK::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+void TSBK::encode(uint8_t* data, const uint8_t* tsbk, bool rawTSBK, bool noTrellis)
{
assert(data != NULL);
+ assert(tsbk != NULL);
- const uint32_t services = (m_siteData.netActive()) ? P25_SYS_SRV_NET_ACTIVE : 0U | P25_SYS_SRV_DEFAULT;
- std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
- time_t tt = std::chrono::system_clock::to_time_t(now);
-
- uint8_t tsbk[P25_TSBK_LENGTH_BYTES];
- ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
-
- ulong64_t tsbkValue = 0U;
- tsbk[0U] = m_lco; // LCO
- tsbk[0U] |= (m_lastBlock) ? 0x80U : 0x00U; // Last Block Marker
-
- tsbk[1U] = m_mfId;
-
- // standard P25 reference opcodes
- switch (m_lco) {
- case TSBK_IOSP_GRP_VCH:
- tsbkValue =
- (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
- (m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag
- (m_priority & 0x07U); // Priority
- tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID
- tsbkValue = (tsbkValue << 12) + m_grpVchNo; // Channel Number
- tsbkValue = (tsbkValue << 16) + m_dstId; // Talkgroup Address
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- break;
- case TSBK_IOSP_UU_VCH:
- tsbkValue =
- (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
- (m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag
- (m_priority & 0x07U); // Priority
- tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID
- tsbkValue = (tsbkValue << 12) + m_grpVchNo; // Channel Number
- tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- break;
- case TSBK_IOSP_UU_ANS:
- tsbkValue =
- (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
- (m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag
- (m_priority & 0x07U); // Priority
- tsbkValue = (tsbkValue << 32) + m_dstId; // Target Radio Address
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- break;
- case TSBK_OSP_SNDCP_CH_GNT:
- {
- uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125);
- float calcTxOffset = m_siteIdenEntry.txOffsetMhz() * 1000000;
-
- uint32_t txFrequency = (uint32_t)((m_siteIdenEntry.baseFrequency() + ((calcSpace * 125) * m_dataChannelNo)));
- uint32_t rxFrequency = (uint32_t)(txFrequency + calcTxOffset);
-
- uint32_t rootFreq = rxFrequency - m_siteIdenEntry.baseFrequency();
- uint32_t rxChNo = rootFreq / (m_siteIdenEntry.chSpaceKhz() * 1000);
-
- tsbkValue = 0U;
- tsbkValue = (tsbkValue << 8) + m_dataServiceOptions; // Data Service Options
- tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel (T) ID
- tsbkValue = (tsbkValue << 12) + m_dataChannelNo; // Channel (T) Number
- tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel (R) ID
- tsbkValue = (tsbkValue << 12) + (rxChNo & 0xFFFU); // Channel (R) Number
- tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
- }
- break;
- case TSBK_OSP_SNDCP_CH_ANN:
- {
- uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125);
- float calcTxOffset = m_siteIdenEntry.txOffsetMhz() * 1000000;
+ uint8_t outTsbk[P25_TSBK_LENGTH_BYTES];
+ ::memset(outTsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+ ::memcpy(outTsbk, tsbk, P25_TSBK_LENGTH_BYTES);
- uint32_t txFrequency = (uint32_t)((m_siteIdenEntry.baseFrequency() + ((calcSpace * 125) * m_siteData.channelNo())));
- uint32_t rxFrequency = (uint32_t)(txFrequency + calcTxOffset);
+ outTsbk[0U] = m_lco; // LCO
+ outTsbk[0U] |= (m_lastBlock) ? 0x80U : 0x00U; // Last Block Marker
- uint32_t rootFreq = rxFrequency - m_siteIdenEntry.baseFrequency();
- uint32_t rxChNo = rootFreq / (m_siteIdenEntry.chSpaceKhz() * 1000);
-
- tsbkValue = 0U; //
- tsbkValue = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
- (m_encrypted ? 0x40U : 0x00U); // Encrypted Flag
- tsbkValue = (tsbkValue << 8) +
- (m_sndcpAutoAccess ? 0x80U : 0x00U) + // Autonomous Access
- (m_sndcpAutoAccess ? 0x40U : 0x00U); // Requested Access
- tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel (T) ID
- tsbkValue = (tsbkValue << 12) + m_siteData.channelNo(); // Channel (T) Number
- tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel (R) ID
- tsbkValue = (tsbkValue << 12) + (rxChNo & 0xFFFU); // Channel (R) Number
- tsbkValue = (tsbkValue << 16) + m_sndcpDAC; // Data Access Control
- }
- break;
- case TSBK_IOSP_STS_UPDT:
- tsbkValue = 0U;
- tsbkValue = (tsbkValue << 16) + m_statusValue; // Status Value
- tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- break;
- case TSBK_IOSP_MSG_UPDT:
- tsbkValue = 0U;
- tsbkValue = (tsbkValue << 16) + m_messageValue; // Message Value
- tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- break;
- case TSBK_OSP_RAD_MON_CMD:
- tsbkValue = (tsbkValue << 48) + (m_txMult & 0x3U); // TX Multiplier
- tsbkValue = (tsbkValue << 24) + (m_srcId & 0xFFFFFFU); // Source Radio Address
- tsbkValue = tsbkValue + (m_dstId & 0xFFFFFFU); // Target Radio Address
- break;
- case TSBK_IOSP_CALL_ALRT:
- tsbkValue = 0U;
- tsbkValue = (tsbkValue << 40) + m_dstId; // Target Radio Address
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- break;
- case TSBK_IOSP_ACK_RSP:
- tsbkValue = (m_service & 0x3F); // Service Type
- tsbkValue |= (m_aivFlag) ? 0x80U : 0x00U; // Additional Info. Valid Flag
- tsbkValue |= (m_extendedAddrFlag) ? 0x40U : 0x00U; // Extended Addressing Flag
- if (m_aivFlag && m_extendedAddrFlag) {
- tsbkValue = (tsbkValue << 20) + m_siteData.netId(); // Network ID
- tsbkValue = (tsbkValue << 12) + m_siteData.sysId(); // System ID
- }
- else {
- tsbkValue = (tsbkValue << 32) + m_dstId; // Target Radio Address
- }
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- break;
- case TSBK_IOSP_EXT_FNCT:
- tsbkValue = 0U;
- tsbkValue = (tsbkValue << 16) + m_extendedFunction; // Extended Function
- tsbkValue = (tsbkValue << 24) + m_srcId; // Argument
- tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
- break;
- case TSBK_IOSP_GRP_AFF:
- tsbkValue = 1U; // Local/Global Affiliation Flag (0 = Local, 1 = Global)
- tsbkValue = (tsbkValue << 7) + (m_response & 0x3U); // Affiliation Response
- tsbkValue = (tsbkValue << 16) + (m_patchSuperGroupId & 0xFFFFU); // Announcement Group Address
- tsbkValue = (tsbkValue << 16) + (m_dstId & 0xFFFFU); // Talkgroup Address
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- break;
- case TSBK_IOSP_U_REG:
- tsbkValue = 0U;
- tsbkValue = (tsbkValue << 2) + (m_response & 0x3U); // Unit Registration Response
- tsbkValue = (tsbkValue << 12) + m_siteData.sysId(); // System ID
- tsbkValue = (tsbkValue << 24) + m_dstId; // Source ID
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- break;
- case TSBK_OSP_GRP_VCH_GRANT_UPD:
- tsbkValue = 0U;
- tsbkValue = m_siteData.channelId(); // Channel ID
- tsbkValue = (tsbkValue << 12) + m_grpVchNo; // Channel Number
- tsbkValue = (tsbkValue << 16) + m_dstId; // Talkgroup Address
- tsbkValue = (tsbkValue << 32) + 0;
- break;
- case TSBK_OSP_DENY_RSP: // TSBK_ISP_EMERG_ALRM_REQ
- case TSBK_OSP_QUE_RSP:
- {
- if (m_response == 0U) {
- if (m_lco == TSBK_OSP_QUE_RSP) {
- LogError(LOG_P25, "TSBK::encode(), invalid values for TSBK_OSP_QUE_RSP, reason = %u", m_response);
- }
- else {
- LogError(LOG_P25, "TSBK::encode(), invalid values for TSBK_OSP_DENY_RSP, reason = %u", m_response);
- }
- return; // blatently ignore creating this TSBK
- }
-
- tsbkValue = (m_aivFlag) ? 0x80U : 0x00U; // Additional Info Flag
- tsbkValue = (tsbkValue << 6) + m_service; // Service Type
- tsbkValue = (tsbkValue << 8) + m_response; // Deny/Queue Reason
-
- if (m_group) {
- // group deny/queue
- tsbkValue = (tsbkValue << 8) + 0U; // Call Options
- tsbkValue = (tsbkValue << 16) + m_dstId; // Talkgroup Address
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- }
- else {
- // private/individual deny/queue
- tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- }
- }
- break;
- case TSBK_OSP_SCCB_EXP:
- tsbkValue = m_siteData.rfssId(); // RF Sub-System ID
- tsbkValue = (tsbkValue << 8) + m_siteData.siteId(); // 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
-
- if (m_sccbChannelId1 > 0) {
- tsbkValue = (tsbkValue << 8) + m_siteData.serviceClass(); // System Service Class
- }
- else {
- tsbkValue = (tsbkValue << 8) + (P25_SVC_CLS_INVALID); // System Service Class
- }
- break;
- case TSBK_OSP_GRP_AFF_Q:
- tsbkValue = 0U;
- tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- break;
- case TSBK_OSP_LOC_REG_RSP:
- tsbkValue = 0U;
- tsbkValue = (tsbkValue << 6) + (m_response & 0x3U); // Registration Response
- tsbkValue = (tsbkValue << 16) + (m_dstId & 0xFFFFU); // Talkgroup Address
- tsbkValue = (tsbkValue << 8) + m_siteData.rfssId(); // RF Sub-System ID
- tsbkValue = (tsbkValue << 8) + m_siteData.sysId(); // Site ID
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- break;
- case TSBK_OSP_U_REG_CMD:
- tsbkValue = 0U;
- tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- break;
- case TSBK_OSP_U_DEREG_ACK:
- tsbkValue = 0U;
- tsbkValue = (tsbkValue << 8) + m_siteData.netId(); // Network ID
- tsbkValue = (tsbkValue << 12) + m_siteData.sysId(); // System ID
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- break;
- case TSBK_OSP_SYNC_BCAST:
- {
- tm local_tm = *gmtime(&tt);
-
- uint32_t tmM = (local_tm.tm_mon + 1);
- uint32_t tmY = (local_tm.tm_year + 1900) - 2000;
-
-#if DEBUG_P25_TSBK
- LogDebug(LOG_P25, "TSBK_OSP_SYNC_BCAST, tmM = %u / %u, tmY = %u / %u", local_tm.tm_mon, tmM, local_tm.tm_year, tmY);
-#endif
-
- // determine LTO and direction (positive or negative)
- bool negativeLTO = false;
- uint8_t lto = fabs(m_siteData.lto()) * 2U; // this will cause a bug for half-hour timezone intervals...
- if (m_siteData.lto() < 0)
- negativeLTO = true;
-
- // mark the LTO as valid if its non-zero
- bool vl = false;
- if (lto > 0U)
- vl = true;
-
- uint8_t mc = 0U;
-
- // wrap microslot count if necessary
- if (m_microslotCount > 7999U)
- m_microslotCount = 0U;
-
- tsbkValue = 0x0AU + // US - Unsynced Flag Set / MMU - Microslot/Minute Unlock Flag Set
- ((mc & 0x03U) >> 1); // Minute Correction MSB
- tsbkValue = (tsbkValue << 8) +
- ((mc & 0x01U) << 7) + // Minute Correction LSB
- (vl ? 0x40U : 0x00U) + // Valid LTO Flag
- (negativeLTO ? 0x20U : 0x00U) + // Add/Subtract LTO Flag
- (lto & 0x1F); // LTO
-
- // Date
- tsbkValue = (tsbkValue << 7) + (tmY & 0x7FU); // Number of Years Past 2000
- tsbkValue = (tsbkValue << 4) + (tmM & 0x0FU); // Month
- tsbkValue = (tsbkValue << 5) + (local_tm.tm_mday & 0x1FU); // Day of Month
-
- // Time
- tsbkValue = (tsbkValue << 5) + (local_tm.tm_hour & 0x1FU); // Hour
- tsbkValue = (tsbkValue << 6) + (local_tm.tm_min & 0x3FU); // Minute
-
- tsbkValue = (tsbkValue << 13) + (m_microslotCount & 0x1FFFU); // Microslot Count
- }
- break;
- case TSBK_OSP_AUTH_FNE_RESP:
- tsbkValue = 0U;
- tsbkValue = (tsbkValue << 8) + m_authRes[3U]; // Result b3
- tsbkValue = (tsbkValue << 8) + m_authRes[2U]; // Result b2
- tsbkValue = (tsbkValue << 8) + m_authRes[1U]; // Result b1
- tsbkValue = (tsbkValue << 8) + m_authRes[0U]; // Result b0
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- break;
- case TSBK_OSP_IDEN_UP_VU:
- {
- if ((m_siteIdenEntry.chBandwidthKhz() != 0.0F) && (m_siteIdenEntry.chSpaceKhz() != 0.0F) &&
- (m_siteIdenEntry.txOffsetMhz() != 0.0F) && (m_siteIdenEntry.baseFrequency() != 0U)) {
- uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125);
-
- float fCalcTxOffset = (fabs(m_siteIdenEntry.txOffsetMhz()) / m_siteIdenEntry.chSpaceKhz()) * 1000.0F;
- uint32_t uCalcTxOffset = (uint32_t)fCalcTxOffset;
- if (m_siteIdenEntry.txOffsetMhz() > 0.0F)
- uCalcTxOffset |= 0x2000U; // this sets a positive offset ...
-
- uint32_t calcBaseFreq = (uint32_t)(m_siteIdenEntry.baseFrequency() / 5);
- uint8_t chanBw = (m_siteIdenEntry.chBandwidthKhz() >= 12.5F) ? P25_IDEN_UP_VU_BW_125K : P25_IDEN_UP_VU_BW_625K;
-
- tsbkValue = m_siteIdenEntry.channelId(); // Channel ID
- tsbkValue = (tsbkValue << 4) + chanBw; // Channel Bandwidth
- tsbkValue = (tsbkValue << 14) + uCalcTxOffset; // Transmit Offset
- tsbkValue = (tsbkValue << 10) + calcSpace; // Channel Spacing
- tsbkValue = (tsbkValue << 32) + calcBaseFreq; // Base Frequency
- }
- else {
- LogError(LOG_P25, "TSBK::encode(), invalid values for TSBK_OSP_IDEN_UP_VU, baseFrequency = %uHz, txOffsetMhz = %fMHz, chBandwidthKhz = %fKHz, chSpaceKhz = %fKHz",
- m_siteIdenEntry.baseFrequency(), m_siteIdenEntry.txOffsetMhz(), m_siteIdenEntry.chBandwidthKhz(),
- m_siteIdenEntry.chSpaceKhz());
- return; // blatently ignore creating this TSBK
- }
- }
- break;
- case TSBK_OSP_SYS_SRV_BCAST:
- tsbkValue = 0U; //
- tsbkValue = (tsbkValue << 16) + services; // System Services Available
- tsbkValue = (tsbkValue << 24) + services; // System Services Supported
- break;
- case TSBK_OSP_SCCB:
- tsbkValue = m_siteData.rfssId(); // RF Sub-System ID
- tsbkValue = (tsbkValue << 8) + m_siteData.siteId(); // Site ID
- tsbkValue = (tsbkValue << 16) + m_sccbChannelId1; // SCCB Channel ID 1
- if (m_sccbChannelId1 > 0) {
- tsbkValue = (tsbkValue << 8) + m_siteData.serviceClass(); // System Service Class
- }
- else {
- tsbkValue = (tsbkValue << 8) + (P25_SVC_CLS_INVALID); // System Service Class
- }
- tsbkValue = (tsbkValue << 16) + m_sccbChannelId2; // SCCB Channel ID 2
- if (m_sccbChannelId2 > 0) {
- tsbkValue = (tsbkValue << 8) + m_siteData.serviceClass(); // System Service Class
- }
- else {
- tsbkValue = (tsbkValue << 8) + (P25_SVC_CLS_INVALID); // System Service Class
- }
- break;
- case TSBK_OSP_RFSS_STS_BCAST:
- tsbkValue = m_siteData.lra(); // Location Registration Area
- tsbkValue = (tsbkValue << 4) +
- (m_siteData.netActive()) ? P25_CFVA_NETWORK : 0U; // CFVA
- tsbkValue = (tsbkValue << 12) + m_siteData.sysId(); // System ID
- tsbkValue = (tsbkValue << 8) + m_siteData.rfssId(); // RF Sub-System ID
- tsbkValue = (tsbkValue << 8) + m_siteData.siteId(); // Site ID
- tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID
- tsbkValue = (tsbkValue << 12) + m_siteData.channelNo(); // Channel Number
- tsbkValue = (tsbkValue << 8) + m_siteData.serviceClass(); // System Service Class
- break;
- case TSBK_OSP_NET_STS_BCAST:
- tsbkValue = m_siteData.lra(); // Location Registration Area
- tsbkValue = (tsbkValue << 20) + m_siteData.netId(); // Network ID
- tsbkValue = (tsbkValue << 12) + m_siteData.sysId(); // System ID
- tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID
- tsbkValue = (tsbkValue << 12) + m_siteData.channelNo(); // Channel Number
- tsbkValue = (tsbkValue << 8) + m_siteData.serviceClass(); // System Service Class
- break;
- case TSBK_OSP_ADJ_STS_BCAST:
- {
- if ((m_adjRfssId != 0U) && (m_adjSiteId != 0U) && (m_adjChannelNo != 0U)) {
- if (m_adjSysId == 0U) {
- m_adjSysId = m_siteData.sysId();
- }
-
- tsbkValue = m_siteData.lra(); // Location Registration Area
- tsbkValue = (tsbkValue << 8) + m_adjCFVA; // CFVA
- 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
- tsbkValue = (tsbkValue << 12) + m_adjChannelNo; // Channel Number
- tsbkValue = (tsbkValue << 8) + m_adjServiceClass; // System Service Class
- }
- else {
- LogError(LOG_P25, "TSBK::encode(), invalid values for OSP_ADJ_STS_BCAST, adjRfssId = $%02X, adjSiteId = $%02X, adjChannelId = %u, adjChannelNo = $%02X, adjSvcClass = $%02X",
- m_adjRfssId, m_adjSiteId, m_adjChannelId, m_adjChannelNo, m_adjServiceClass);
- return; // blatently ignore creating this TSBK
- }
- }
- break;
- case TSBK_OSP_IDEN_UP:
- {
- if ((m_siteIdenEntry.chBandwidthKhz() != 0.0F) && (m_siteIdenEntry.chSpaceKhz() != 0.0F) &&
- (m_siteIdenEntry.txOffsetMhz() != 0.0F) && (m_siteIdenEntry.baseFrequency() != 0U)) {
- if (m_siteIdenEntry.baseFrequency() < 762000000U) {
- LogError(LOG_P25, "TSBK::encode(), invalid values for TSBK_OSP_IDEN_UP, baseFrequency = %uHz",
- m_siteIdenEntry.baseFrequency());
- return; // blatently ignore creating this TSBK
- }
-
- uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125);
-
- float fCalcTxOffset = (fabs(m_siteIdenEntry.txOffsetMhz()) * 1000000.0F) / 250000.0F;
- uint32_t uCalcTxOffset = (uint32_t)fCalcTxOffset;
- if (m_siteIdenEntry.txOffsetMhz() > 0.0F)
- uCalcTxOffset |= 0x2000U; // this sets a positive offset ...
-
- uint32_t calcBaseFreq = (uint32_t)(m_siteIdenEntry.baseFrequency() / 5);
- uint16_t chanBw = (uint16_t)((m_siteIdenEntry.chBandwidthKhz() * 1000) / 125);
-
- tsbkValue = m_siteIdenEntry.channelId(); // Channel ID
- tsbkValue = (tsbkValue << 9) + chanBw; // Channel Bandwidth
- tsbkValue = (tsbkValue << 9) + uCalcTxOffset; // Transmit Offset
- tsbkValue = (tsbkValue << 10) + calcSpace; // Channel Spacing
- tsbkValue = (tsbkValue << 32) + calcBaseFreq; // Base Frequency
- }
- else {
- LogError(LOG_P25, "TSBK::encode(), invalid values for TSBK_OSP_IDEN_UP, baseFrequency = %uHz, txOffsetMhz = %fMHz, chBandwidthKhz = %fKHz, chSpaceKhz = %fKHz",
- m_siteIdenEntry.baseFrequency(), m_siteIdenEntry.txOffsetMhz(), m_siteIdenEntry.chBandwidthKhz(),
- m_siteIdenEntry.chSpaceKhz());
- return; // blatently ignore creating this TSBK
- }
- }
- break;
- default:
- if (m_mfId == P25_MFG_STANDARD) {
- LogError(LOG_P25, "TSBK::encode(), unknown TSBK LCO value, mfId = $%02X, lco = $%02X", m_mfId, m_lco);
- }
- break;
- }
-
- if (!m_vendorSkip) {
- // Motorola P25 vendor opcodes
- if (m_mfId == P25_MFG_MOT) {
- switch (m_lco) {
- case TSBK_OSP_MOT_GRG_ADD:
- {
- if ((m_patchSuperGroupId != 0U)) {
- tsbkValue = m_patchSuperGroupId; // Patch Super Group Address
- tsbkValue = (tsbkValue << 16) + m_patchGroup1Id; // Patch Group 1 Address
-
- if (m_patchGroup2Id != 0U) {
- tsbkValue = (tsbkValue << 16) + m_patchGroup2Id; // Patch Group 2 Address
- }
- else {
- tsbkValue = (tsbkValue << 16) + m_patchGroup1Id; // Patch Group 1 Address
- }
-
- if (m_patchGroup3Id != 0U) {
- tsbkValue = (tsbkValue << 16) + m_patchGroup3Id; // Patch Group 3 Address
- }
- else {
- tsbkValue = (tsbkValue << 16) + m_patchGroup1Id; // Patch Group 1 Address
- }
- } // otherwise handled as a TSBK_OSP_MOT_GRG_ADD
- }
- break;
- case TSBK_OSP_MOT_GRG_DEL:
- {
- if ((m_patchSuperGroupId != 0U) && (m_patchGroup1Id != 0U)) {
- tsbkValue = m_patchSuperGroupId; // Patch Super Group Address
- tsbkValue = (tsbkValue << 16) + m_patchGroup1Id; // Patch Group 1 Address
-
- if (m_patchGroup2Id != 0U) {
- tsbkValue = (tsbkValue << 16) + m_patchGroup2Id; // Patch Group 2 Address
- }
- else {
- tsbkValue = (tsbkValue << 16) + m_patchGroup1Id; // Patch Group 1 Address
- }
-
- if (m_patchGroup3Id != 0U) {
- tsbkValue = (tsbkValue << 16) + m_patchGroup3Id; // Patch Group 3 Address
- }
- else {
- tsbkValue = (tsbkValue << 16) + m_patchGroup1Id; // Patch Group 1 Address
- }
- }
- else {
- LogError(LOG_P25, "TSBK::encode(), invalid values for TSBK_OSP_MOT_GRG_DEL, patchSuperGroupId = $%02X, patchGroup1Id = $%02X",
- m_patchSuperGroupId, m_patchGroup1Id);
- return; // blatently ignore creating this TSBK
- }
- }
- break;
- case TSBK_OSP_MOT_GRG_VCH_GRANT:
- {
- if (m_patchSuperGroupId != 0U) {
- tsbkValue = 0U; // Priority
- tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID
- tsbkValue = (tsbkValue << 12) + m_siteData.channelNo(); // Channel Number
- tsbkValue = (tsbkValue << 16) + m_patchSuperGroupId; // Patch Supergroup Address
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- }
- else {
- LogError(LOG_P25, "TSBK::encode(), invalid values for TSBK_OSP_MOT_GRG_VCH_GRANT, patchSuperGroupId = $%02X", m_patchSuperGroupId);
- return; // blatently ignore creating this TSBK
- }
- }
- break;
- case TSBK_OSP_MOT_GRG_VCH_UPD:
- tsbkValue = m_siteData.channelId(); // Channel ID
- tsbkValue = (tsbkValue << 4) + m_siteData.channelNo(); // Channel Number
- tsbkValue = (tsbkValue << 12) + m_patchGroup1Id; // Patch Group 1
- tsbkValue = (tsbkValue << 16) + m_siteData.channelId(); // Channel ID
- tsbkValue = (tsbkValue << 4) + m_siteData.channelNo(); // Channel Number
- tsbkValue = (tsbkValue << 12) + m_patchGroup2Id; // Patch Group 2
- break;
- break;
- case TSBK_OSP_MOT_CC_BSI:
- tsbkValue = (m_siteCallsign[0] - 43U) & 0x3F; // Character 0
- for (uint8_t i = 1; i < P25_MOT_CALLSIGN_LENGTH_BYTES; i++) {
- tsbkValue = (tsbkValue << 6) + ((m_siteCallsign[i] - 43U) & 0x3F); // Character 1 - 7
- }
- tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID
- tsbkValue = (tsbkValue << 12) + m_siteData.channelNo(); // Channel Number
- break;
- case TSBK_OSP_MOT_PSH_CCH:
- tsbkValue = 0U;
- break;
- // because of how MFId is handled; we have to skip these opcodes
- case TSBK_IOSP_UU_VCH:
- case TSBK_IOSP_STS_UPDT:
- case TSBK_IOSP_STS_Q:
- case TSBK_IOSP_MSG_UPDT:
- case TSBK_IOSP_CALL_ALRT:
- case TSBK_IOSP_GRP_AFF:
- case TSBK_IOSP_ACK_RSP:
- case TSBK_IOSP_U_REG:
- case TSBK_OSP_DENY_RSP:
- case TSBK_OSP_QUE_RSP:
- case TSBK_OSP_GRP_AFF_Q:
- case TSBK_OSP_U_REG_CMD:
- case TSBK_OSP_U_DEREG_ACK:
- break;
- default:
- LogError(LOG_P25, "TSBK::encode(), unknown TSBK LCO value, mfId = $%02X, lco = $%02X", m_mfId, m_lco);
- break;
- }
- }
-
- // internal P25 vendor opcodes
- if (m_mfId == P25_MFG_DVM) {
- switch (m_lco) {
- case TSBK_OSP_DVM_GIT_HASH:
- tsbkValue = g_gitHashBytes[0]; // ...
- tsbkValue = (tsbkValue << 8) + (g_gitHashBytes[1U]); // ...
- tsbkValue = (tsbkValue << 8) + (g_gitHashBytes[2U]); // ...
- tsbkValue = (tsbkValue << 8) + (g_gitHashBytes[3U]); // ...
- tsbkValue = (tsbkValue << 16) + 0U;
- tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID
- tsbkValue = (tsbkValue << 12) + m_siteData.channelNo(); // Channel Number
- break;
- case LC_CALL_TERM:
- tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID
- tsbkValue = (tsbkValue << 12) + m_grpVchNo; // Channel Number
- tsbkValue = (tsbkValue << 16) + m_dstId; // Talkgroup Address
- tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
- break;
- default:
- LogError(LOG_P25, "TSBK::encode(), unknown TSBK LCO value, mfId = $%02X, lco = $%02X", m_mfId, m_lco);
- break;
- }
- }
- }
-
- // split ulong64_t (8 byte) value into bytes
- tsbk[2U] = (uint8_t)((tsbkValue >> 56) & 0xFFU);
- tsbk[3U] = (uint8_t)((tsbkValue >> 48) & 0xFFU);
- tsbk[4U] = (uint8_t)((tsbkValue >> 40) & 0xFFU);
- tsbk[5U] = (uint8_t)((tsbkValue >> 32) & 0xFFU);
- tsbk[6U] = (uint8_t)((tsbkValue >> 24) & 0xFFU);
- tsbk[7U] = (uint8_t)((tsbkValue >> 16) & 0xFFU);
- tsbk[8U] = (uint8_t)((tsbkValue >> 8) & 0xFFU);
- tsbk[9U] = (uint8_t)((tsbkValue >> 0) & 0xFFU);
+ outTsbk[1U] = m_mfId;
// compute CRC-CCITT 16
- edac::CRC::addCCITT162(tsbk, P25_TSBK_LENGTH_BYTES);
+ edac::CRC::addCCITT162(outTsbk, P25_TSBK_LENGTH_BYTES);
if (m_verbose) {
- Utils::dump(2U, "TSBK::encode(), TSBK Value", tsbk, P25_TSBK_LENGTH_BYTES);
+ Utils::dump(2U, "TSBK::encode(), TSBK Value", outTsbk, P25_TSBK_LENGTH_BYTES);
}
uint8_t raw[P25_TSBK_FEC_LENGTH_BYTES];
::memset(raw, 0x00U, P25_TSBK_FEC_LENGTH_BYTES);
// encode 1/2 rate Trellis
- m_trellis.encode12(tsbk, raw);
+ m_trellis.encode12(outTsbk, raw);
// are we encoding a raw TSBK?
if (rawTSBK) {
if (noTrellis) {
- ::memcpy(data, tsbk, P25_TSBK_LENGTH_BYTES);
+ ::memcpy(data, outTsbk, P25_TSBK_LENGTH_BYTES);
}
else {
::memcpy(data, raw, P25_TSBK_FEC_LENGTH_BYTES);
@@ -1366,169 +315,6 @@ void TSBK::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
}
}
-///
-/// Sets the flag to skip vendor opcode processing.
-///
-/// Flag indicating to skip vendor opcode processing.
-void TSBK::setVendorSkip(bool skip)
-{
- m_vendorSkip = skip;
-}
-
-///
-/// Sets the callsign.
-///
-/// Callsign.
-void TSBK::setCallsign(std::string callsign)
-{
- uint32_t idLength = callsign.length();
- if (idLength > 0) {
- ::memset(m_siteCallsign, 0x20U, P25_MOT_CALLSIGN_LENGTH_BYTES);
-
- if (idLength > P25_MOT_CALLSIGN_LENGTH_BYTES)
- idLength = P25_MOT_CALLSIGN_LENGTH_BYTES;
- for (uint32_t i = 0; i < idLength; i++)
- m_siteCallsign[i] = callsign[i];
- }
-}
-
-/** Authentication data */
-/// Gets the authentication result.
-///
-void TSBK::getAuthRes(uint8_t* res) const
-{
- assert(res != NULL);
-
- ::memcpy(res, m_authRes, P25_AUTH_RES_LENGTH_BYTES);
-}
-
-/// Sets the authentication random seed.
-///
-void TSBK::setAuthRS(const uint8_t* rs)
-{
- assert(rs != NULL);
-
- ::memcpy(m_authRS, rs, P25_AUTH_RAND_SEED_LENGTH_BYTES);
-}
-
-/// Gets the authentication random seed.
-///
-void TSBK::getAuthRS(uint8_t* rs) const
-{
- assert(rs != NULL);
-
- ::memcpy(rs, m_authRS, P25_AUTH_RAND_SEED_LENGTH_BYTES);
-}
-
-/// Sets the authentication random challenge.
-///
-void TSBK::setAuthRC(const uint8_t* rc)
-{
- assert(rc != NULL);
-
- ::memcpy(m_authRC, rc, P25_AUTH_RAND_CHLNG_LENGTH_BYTES);
-}
-
-/// Gets the authentication random challenge.
-///
-void TSBK::getAuthRC(uint8_t* rc) const
-{
- assert(rc != NULL);
-
- ::memcpy(rc, m_authRC, P25_AUTH_RAND_CHLNG_LENGTH_BYTES);
-}
-
-// ---------------------------------------------------------------------------
-// Private Class Members
-// ---------------------------------------------------------------------------
-
-///
-/// Initializes a new instance of the TSBK class.
-///
-/// This should never be used.
-TSBK::TSBK() : TSBK(SiteData())
-{
- /* stub */
-}
-
-///
-/// Initializes a new instance of the TSBK class.
-///
-///
-TSBK::TSBK(SiteData siteData) :
- m_verbose(false),
-#if FORCE_TSBK_CRC_WARN
- m_warnCRC(true),
-#else
- m_warnCRC(false),
-#endif
- m_protect(false),
- m_lco(LC_GROUP),
- m_mfId(P25_MFG_STANDARD),
- m_srcId(0U),
- m_dstId(0U),
- m_lastBlock(false),
- m_aivFlag(true),
- m_extendedAddrFlag(false),
- m_service(0U),
- m_response(P25_RSP_ACCEPT),
- m_netId(P25_WACN_STD_DEFAULT),
- m_sysId(P25_SID_STD_DEFAULT),
- m_grpVchId(0U),
- m_grpVchNo(0U),
- m_messageValue(0U),
- m_statusValue(0U),
- m_extendedFunction(P25_EXT_FNCT_CHECK),
- m_microslotCount(0U),
- m_dataServiceOptions(0U),
- m_dataAccessControl(0U),
- m_dataChannelNo(0U),
- m_adjCFVA(P25_CFVA_FAILURE),
- m_adjRfssId(0U),
- m_adjSiteId(0U),
- m_adjChannelId(0U),
- m_adjChannelNo(0U),
- m_adjServiceClass(P25_SVC_CLS_INVALID),
- m_sccbChannelId1(0U),
- m_sccbChannelId2(0U),
- m_sccbChannelNo(0U),
- m_lra(0U),
- m_patchSuperGroupId(0U),
- m_patchGroup1Id(0U),
- m_patchGroup2Id(0U),
- m_patchGroup3Id(0U),
- m_emergency(false),
- m_encrypted(false),
- m_priority(4U),
- m_group(true),
- m_txMult(0U),
- m_authSuccess(false),
- m_authStandalone(false),
- m_siteData(siteData),
- m_siteIdenEntry(),
- m_rs(),
- m_trellis(),
- m_vendorSkip(false),
- m_sndcpAutoAccess(true),
- m_sndcpReqAccess(false),
- m_sndcpDAC(1U),
- m_authRes(NULL),
- m_authRS(NULL),
- m_authRC(NULL),
- m_siteCallsign(NULL)
-{
- m_siteCallsign = new uint8_t[P25_MOT_CALLSIGN_LENGTH_BYTES];
- ::memset(m_siteCallsign, 0x00U, P25_MOT_CALLSIGN_LENGTH_BYTES);
- setCallsign(siteData.callsign());
-
- m_authRes = new uint8_t[P25_AUTH_RES_LENGTH_BYTES];
- ::memset(m_authRes, 0x00U, P25_AUTH_RES_LENGTH_BYTES);
- m_authRS = new uint8_t[P25_AUTH_RAND_SEED_LENGTH_BYTES];
- ::memset(m_authRS, 0x00U, P25_AUTH_RAND_SEED_LENGTH_BYTES);
- m_authRC = new uint8_t[P25_AUTH_RAND_CHLNG_LENGTH_BYTES];
- ::memset(m_authRC, 0x00U, P25_AUTH_RAND_CHLNG_LENGTH_BYTES);
-}
-
///
/// Internal helper to copy the the class.
///
@@ -1548,80 +334,17 @@ void TSBK::copy(const TSBK& data)
m_aivFlag = data.m_aivFlag;
m_extendedAddrFlag = data.m_extendedAddrFlag;
- m_service = data.m_service;
m_response = data.m_response;
+ m_service = data.m_service;
m_netId = data.m_netId;
m_sysId = data.m_sysId;
m_grpVchNo = data.m_grpVchNo;
- m_messageValue = data.m_messageValue;
- m_statusValue = data.m_statusValue;
-
- m_extendedFunction = data.m_extendedFunction;
-
- m_microslotCount = data.m_microslotCount;
-
- m_dataChannelNo = data.m_dataChannelNo;
-
- m_adjCFVA = data.m_adjCFVA;
- m_adjRfssId = data.m_adjRfssId;
- m_adjSiteId = data.m_adjSiteId;
- m_adjChannelId = data.m_adjChannelId;
- m_adjChannelNo = data.m_adjChannelNo;
- m_adjServiceClass = data.m_adjServiceClass;
-
- m_sccbChannelId1 = data.m_sccbChannelId1;
- m_sccbChannelId2 = data.m_sccbChannelId2;
- m_sccbChannelNo = data.m_sccbChannelNo;
-
- m_lra = data.m_lra;
-
- m_patchSuperGroupId = data.m_patchSuperGroupId;
- m_patchGroup1Id = data.m_patchGroup1Id;
- m_patchGroup2Id = data.m_patchGroup2Id;
- m_patchGroup3Id = data.m_patchGroup3Id;
-
m_emergency = data.m_emergency;
m_encrypted = data.m_encrypted;
m_priority = data.m_priority;
m_group = data.m_group;
-
- m_txMult = data.m_txMult;
-
- m_authSuccess = data.m_authSuccess;
- m_authStandalone = data.m_authStandalone;
-
- m_siteData = data.m_siteData;
- m_siteIdenEntry = data.m_siteIdenEntry;
-
- if (m_authRes != NULL) {
- delete[] m_authRes;
- }
-
- m_authRes = new uint8_t[P25_AUTH_RES_LENGTH_BYTES];
- ::memcpy(m_authRes, data.m_authRes, P25_AUTH_RES_LENGTH_BYTES);
-
- if (m_authRS != NULL) {
- delete[] m_authRS;
- }
-
- m_authRS = new uint8_t[P25_AUTH_RAND_SEED_LENGTH_BYTES];
- ::memcpy(m_authRS, data.m_authRS, P25_AUTH_RAND_SEED_LENGTH_BYTES);
-
- if (m_authRC != NULL) {
- delete[] m_authRC;
- }
-
- m_authRC = new uint8_t[P25_AUTH_RAND_CHLNG_LENGTH_BYTES];
- ::memcpy(m_authRC, data.m_authRC, P25_AUTH_RAND_CHLNG_LENGTH_BYTES);
-
- delete[] m_siteCallsign;
-
- uint8_t* callsign = new uint8_t[P25_MOT_CALLSIGN_LENGTH_BYTES];
- ::memcpy(callsign, data.m_siteCallsign, P25_MOT_CALLSIGN_LENGTH_BYTES);
-
- m_siteCallsign = callsign;
}
diff --git a/p25/lc/TSBK.h b/p25/lc/TSBK.h
index d2680dba..74153ffb 100644
--- a/p25/lc/TSBK.h
+++ b/p25/lc/TSBK.h
@@ -7,7 +7,7 @@
*
*/
/*
-* Copyright (C) 2017-2022 by Bryan Biedenkapp N2PLL
+* 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
@@ -27,8 +27,6 @@
#define __P25_LC__TSBK_H__
#include "Defines.h"
-#include "p25/data/DataHeader.h"
-#include "p25/data/DataBlock.h"
#include "p25/edac/Trellis.h"
#include "p25/lc/LC.h"
#include "p25/lc/TDULC.h"
@@ -68,201 +66,106 @@ namespace p25
/// Initializes a copy instance of the TSBK class.
TSBK(const TSBK& data);
/// Initializes a new instance of the TSBK class.
- TSBK(SiteData siteData, ::lookups::IdenTable entry);
- /// Initializes a new instance of the TSBK class.
- TSBK(SiteData siteData, ::lookups::IdenTable entry, bool verbose);
- /// Initializes a new instance of the TSBK class.
- TSBK(SiteData siteData, ::lookups::IdenTable entry, bool verbose, bool warnCRC);
- /// Initializes a new instance of the TSBK class.
TSBK(LC* lc);
+ /// Initializes a new instance of the TSBK class.
+ TSBK();
/// Finalizes a instance of the TSBK class.
- ~TSBK();
-
- /// Equals operator.
- TSBK& operator=(const TSBK& data);
-
- /// Decode a alternate trunking signalling block.
- bool decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks);
- /// Encode a alternate trunking signalling block.
- void encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData);
-
+ virtual ~TSBK();
+
/// Decode a trunking signalling block.
- bool decode(const uint8_t* data, bool rawTSBK = false);
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false) = 0;
/// Encode a trunking signalling block.
- void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false) = 0;
- /// Sets the flag to skip vendor opcode processing.
- void setVendorSkip(bool skip);
+ /// Sets the flag indicating verbose log output.
+ static void setVerbose(bool verbose) { m_verbose = verbose; }
+ /// Sets the flag indicating CRC-errors should be warnings and not errors.
+ static void setWarnCRC(bool warnCRC) { m_warnCRC = warnCRC; }
+ /** Local Site data */
/// Sets the callsign.
- void setCallsign(std::string callsign);
-
- /** Authentication data */
- /// Gets the authentication result.
- void getAuthRes(uint8_t* res) const;
+ static void setCallsign(std::string callsign);
- /// Sets the authentication random seed.
- void setAuthRS(const uint8_t* rs);
- /// Gets the authentication random seed.
- void getAuthRS(uint8_t* rs) const;
-
- /// Sets the authentication random challenge.
- void setAuthRC(const uint8_t* rc);
- /// Gets the authentication random challenge.
- void getAuthRC(uint8_t* rc) const;
+ /// Gets the local site data.
+ static SiteData getSiteData() { return m_siteData; }
+ /// Sets the local site data.
+ static void setSiteData(SiteData siteData) { m_siteData = siteData; }
public:
- /// Flag indicating verbose log output.
- __PROPERTY(bool, verbose, Verbose);
- /// Flag indicating CRC-errors should be warnings and not errors.
- __PROPERTY(bool, warnCRC, WarnCRC);
-
/** Common Data */
/// Flag indicating the link control data is protected.
- __PROPERTY(bool, protect, Protect);
+ __PROTECTED_PROPERTY(bool, protect, Protect);
/// Link control opcode.
- __PROPERTY(uint8_t, lco, LCO);
+ __PROTECTED_PROPERTY(uint8_t, lco, LCO);
/// Manufacturer ID.
- __PROPERTY(uint8_t, mfId, MFId);
+ __PROTECTED_PROPERTY(uint8_t, mfId, MFId);
/// Source ID.
- __PROPERTY(uint32_t, srcId, SrcId);
+ __PROTECTED_PROPERTY(uint32_t, srcId, SrcId);
/// Destination ID.
- __PROPERTY(uint32_t, dstId, DstId);
+ __PROTECTED_PROPERTY(uint32_t, dstId, DstId);
/// Flag indicating this is the last TSBK in a sequence of TSBKs.
- __PROPERTY(bool, lastBlock, LastBlock);
+ __PROTECTED_PROPERTY(bool, lastBlock, LastBlock);
/// Flag indicating this TSBK contains additional information.
- __PROPERTY(bool, aivFlag, AIV);
+ __PROTECTED_PROPERTY(bool, aivFlag, AIV);
/// Flag indicating this TSBK contains extended addressing.
- __PROPERTY(bool, extendedAddrFlag, EX);
+ __PROTECTED_PROPERTY(bool, extendedAddrFlag, EX);
/// Service type.
- __PROPERTY(uint8_t, service, Service);
+ __PROTECTED_PROPERTY(uint8_t, service, Service);
/// Response type.
- __PROPERTY(uint8_t, response, Response);
+ __PROTECTED_PROPERTY(uint8_t, response, Response);
/// Configured network ID.
- __READONLY_PROPERTY(uint32_t, netId, NetId);
+ __PROTECTED_READONLY_PROPERTY(uint32_t, netId, NetId);
/// Configured system ID.
- __READONLY_PROPERTY(uint32_t, sysId, SysId);
+ __PROTECTED_READONLY_PROPERTY(uint32_t, sysId, SysId);
/// Voice channel ID.
- __PROPERTY(uint32_t, grpVchId, GrpVchId);
+ __PROTECTED_PROPERTY(uint32_t, grpVchId, GrpVchId);
/// Voice channel number.
- __PROPERTY(uint32_t, grpVchNo, GrpVchNo);
-
- /// Message value.
- __PROPERTY(uint32_t, messageValue, Message);
- /// Status value.
- __PROPERTY(uint8_t, statusValue, Status);
-
- /// Extended function opcode.
- __PROPERTY(uint32_t, extendedFunction, ExtendedFunction);
-
- /// Microslot count.
- __PROPERTY(uint16_t, microslotCount, MicroslotCount);
+ __PROTECTED_PROPERTY(uint32_t, grpVchNo, GrpVchNo);
- /** SNDCP Channel Request */
- /// SNDCP Data Service Options
- __PROPERTY(uint8_t, dataServiceOptions, DataServiceOptions);
- /// SNDCP Data Access Control
- __PROPERTY(uint32_t, dataAccessControl, DataAccessControl);
-
- /// SNDCP grant channel number.
- __PROPERTY(uint32_t, dataChannelNo, DataChnNo);
-
- /** Adjacent Site Data */
- /// Adjacent site CFVA flags.
- __PROPERTY(uint8_t, adjCFVA, AdjSiteCFVA);
- /// Adjacent site system ID.
- __PROPERTY(uint32_t, adjSysId, AdjSiteSysId);
- /// Adjacent site RFSS ID.
- __PROPERTY(uint8_t, adjRfssId, AdjSiteRFSSId);
- /// Adjacent site ID.
- __PROPERTY(uint8_t, adjSiteId, AdjSiteId);
- /// Adjacent site channel ID.
- __PROPERTY(uint8_t, adjChannelId, AdjSiteChnId);
- /// Adjacent site channel number.
- __PROPERTY(uint32_t, adjChannelNo, AdjSiteChnNo);
- /// Adjacent site service class.
- __PROPERTY(uint8_t, adjServiceClass, AdjSiteSvcClass);
-
- /** SCCB Data */
- /// SCCB channel ID 1.
- __PROPERTY(uint8_t, sccbChannelId1, SCCBChnId1);
- /// SCCB channel ID 2.
- __PROPERTY(uint8_t, sccbChannelId2, SCCBChnId2);
- /// Explicit SCCB channel number.
- __PROPERTY(uint32_t, sccbChannelNo, SCCBChnNo);
-
- /** Location Data */
- /// Location registration area.
- __PROPERTY(uint8_t, lra, LRA);
-
- /** Patch Group data */
- /// Patch super group ID.
- __PROPERTY(uint32_t, patchSuperGroupId, PatchSuperGroupId);
- /// 1st patch group ID.
- __PROPERTY(uint32_t, patchGroup1Id, PatchGroup1Id);
- /// 2nd patch group ID.
- __PROPERTY(uint32_t, patchGroup2Id, PatchGroup2Id);
- /// 3rd patch group ID.
- __PROPERTY(uint32_t, patchGroup3Id, PatchGroup3Id);
-
- /** Service Options */
+ /** Common Service Options */
/// Flag indicating the emergency bits are set.
- __PROPERTY(bool, emergency, Emergency);
+ __PROTECTED_PROPERTY(bool, emergency, Emergency);
/// Flag indicating that encryption is enabled.
- __PROPERTY(bool, encrypted, Encrypted);
+ __PROTECTED_PROPERTY(bool, encrypted, Encrypted);
/// Priority level for the traffic.
- __PROPERTY(uint8_t, priority, Priority);
+ __PROTECTED_PROPERTY(uint8_t, priority, Priority);
/// Flag indicating a group/talkgroup operation.
- __PROPERTY(bool, group, Group);
-
- /** Radio Unit Monitor */
- /// Radio Unit Monitor.
- __PROPERTY(uint8_t, txMult, TxMult);
-
- /** Authentication Handshake */
- /// Flag indicating authentication was successful.
- __PROPERTY(bool, authSuccess, AuthSuccess);
- /// Flag indicating authentication is standalone.
- __PROPERTY(bool, authStandalone, AuthStandalone);
+ __PROTECTED_PROPERTY(bool, group, Group);
/** Local Site data */
- /// Local Site Data.
- __PROPERTY_PLAIN(SiteData, siteData, siteData);
/// Local Site Identity Entry.
- __PROPERTY_PLAIN(::lookups::IdenTable, siteIdenEntry, siteIdenEntry);
-
- private:
- /// Initializes a new instance of the TSBK class.
- TSBK();
- /// Initializes a new instance of the TSBK class.
- TSBK(SiteData siteData);
+ __PROTECTED_PROPERTY_PLAIN(::lookups::IdenTable, siteIdenEntry, siteIdenEntry);
+ protected:
friend class dfsi::LC;
friend class LC;
friend class TDULC;
edac::RS634717 m_rs;
edac::Trellis m_trellis;
- bool m_vendorSkip;
- bool m_sndcpAutoAccess;
- bool m_sndcpReqAccess;
- uint16_t m_sndcpDAC;
-
- /** Authentication data */
- uint8_t* m_authRes;
- uint8_t* m_authRS;
- uint8_t* m_authRC;
+ static bool m_verbose;
+ static bool m_warnCRC;
/** Local Site data */
- uint8_t* m_siteCallsign;
+ static uint8_t* m_siteCallsign;
+ static SiteData m_siteData;
+
+ /// Internal helper to convert TSBK bytes to a 64-bit long value.
+ static ulong64_t tsbkValue(const uint8_t* tsbk);
+ /// Internal helper to convert a 64-bit long value to TSBK bytes.
+ static uint8_t* tsbkValue(const ulong64_t tsbkValue);
+
+ /// Internal helper to decode a trunking signalling block.
+ bool decode(const uint8_t* data, uint8_t* tsbk, bool rawTSBK = false);
+ /// Internal helper to encode a trunking signalling block.
+ void encode(uint8_t* data, const uint8_t* tsbk, bool rawTSBK = false, bool noTrellis = false);
- /// Internal helper to copy the class.
- void copy(const TSBK& data);
+ __PROTECTED_COPY(TSBK);
};
} // namespace lc
} // namespace p25
diff --git a/p25/lc/tsbk/IOSP_ACK_RSP.cpp b/p25/lc/tsbk/IOSP_ACK_RSP.cpp
new file mode 100644
index 00000000..bfc8c201
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_ACK_RSP.cpp
@@ -0,0 +1,104 @@
+/**
+* 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 "p25/lc/tsbk/IOSP_ACK_RSP.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the IOSP_ACK_RSP class.
+///
+IOSP_ACK_RSP::IOSP_ACK_RSP() : TSBK()
+{
+ m_lco = TSBK_IOSP_ACK_RSP;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool IOSP_ACK_RSP::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_aivFlag = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Additional Info. Flag
+ m_service = (uint8_t)((tsbkValue >> 56) & 0x3FU); // Service Type
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void IOSP_ACK_RSP::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = (m_service & 0x3F); // Service Type
+ tsbkValue |= (m_aivFlag) ? 0x80U : 0x00U; // Additional Info. Valid Flag
+ tsbkValue |= (m_extendedAddrFlag) ? 0x40U : 0x00U; // Extended Addressing Flag
+ if (m_aivFlag && m_extendedAddrFlag) {
+ tsbkValue = (tsbkValue << 20) + m_siteData.netId(); // Network ID
+ tsbkValue = (tsbkValue << 12) + m_siteData.sysId(); // System ID
+ }
+ else {
+ tsbkValue = (tsbkValue << 32) + m_dstId; // Target Radio Address
+ }
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/IOSP_ACK_RSP.h b/p25/lc/tsbk/IOSP_ACK_RSP.h
new file mode 100644
index 00000000..45583c1c
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_ACK_RSP.h
@@ -0,0 +1,58 @@
+/**
+* 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(__P25_LC_TSBK__IOSP_ACK_RSP_H__)
+#define __P25_LC_TSBK__IOSP_ACK_RSP_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements ACK RSP U - Acknowledge Response - Unit (ISP) and
+ // ACK RSP FNE - Acknowledge Response - FNE (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API IOSP_ACK_RSP : public TSBK {
+ public:
+ /// Initializes a new instance of the IOSP_ACK_RSP class.
+ IOSP_ACK_RSP();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__IOSP_ACK_RSP_H__
diff --git a/p25/lc/tsbk/IOSP_CALL_ALRT.cpp b/p25/lc/tsbk/IOSP_CALL_ALRT.cpp
new file mode 100644
index 00000000..0ca46009
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_CALL_ALRT.cpp
@@ -0,0 +1,93 @@
+/**
+* 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 "p25/lc/tsbk/IOSP_CALL_ALRT.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the IOSP_CALL_ALRT class.
+///
+IOSP_CALL_ALRT::IOSP_CALL_ALRT() : TSBK()
+{
+ m_lco = TSBK_IOSP_CALL_ALRT;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool IOSP_CALL_ALRT::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void IOSP_CALL_ALRT::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = (tsbkValue << 40) + m_dstId; // Target Radio Address
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/IOSP_CALL_ALRT.h b/p25/lc/tsbk/IOSP_CALL_ALRT.h
new file mode 100644
index 00000000..93b52c4a
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_CALL_ALRT.h
@@ -0,0 +1,58 @@
+/**
+* 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(__P25_LC_TSBK__IOSP_CALL_ALRT_H__)
+#define __P25_LC_TSBK__IOSP_CALL_ALRT_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements CALL ALRT REQ - Call Alert Request (ISP) and
+ // CALL ALRT - Call Alert (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API IOSP_CALL_ALRT : public TSBK {
+ public:
+ /// Initializes a new instance of the IOSP_CALL_ALRT class.
+ IOSP_CALL_ALRT();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__IOSP_CALL_ALRT_H__
diff --git a/p25/lc/tsbk/IOSP_EXT_FNCT.cpp b/p25/lc/tsbk/IOSP_EXT_FNCT.cpp
new file mode 100644
index 00000000..c94fe438
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_EXT_FNCT.cpp
@@ -0,0 +1,111 @@
+/**
+* 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 "p25/lc/tsbk/IOSP_EXT_FNCT.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the IOSP_EXT_FNCT class.
+///
+IOSP_EXT_FNCT::IOSP_EXT_FNCT() : TSBK(),
+ m_extendedFunction(P25_EXT_FNCT_CHECK)
+{
+ m_lco = TSBK_IOSP_EXT_FNCT;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool IOSP_EXT_FNCT::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_extendedFunction = (uint32_t)((tsbkValue >> 48) & 0xFFFFU); // Extended Function
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Argument
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Target Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void IOSP_EXT_FNCT::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = (tsbkValue << 16) + m_extendedFunction; // Extended Function
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Argument
+ tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void IOSP_EXT_FNCT::copy(const IOSP_EXT_FNCT& data)
+{
+ TSBK::copy(data);
+
+ m_extendedFunction = data.m_extendedFunction;
+}
diff --git a/p25/lc/tsbk/IOSP_EXT_FNCT.h b/p25/lc/tsbk/IOSP_EXT_FNCT.h
new file mode 100644
index 00000000..4a96d962
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_EXT_FNCT.h
@@ -0,0 +1,64 @@
+/**
+* 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(__P25_LC_TSBK__IOSP_EXT_FNCT_H__)
+#define __P25_LC_TSBK__IOSP_EXT_FNCT_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements EXT FNCT RSP - Extended Function Response (ISP) and
+ // EXT FNCT CMD - Extended Function Command (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API IOSP_EXT_FNCT : public TSBK {
+ public:
+ /// Initializes a new instance of the IOSP_EXT_FNCT class.
+ IOSP_EXT_FNCT();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /// Extended function opcode.
+ __PROPERTY(uint32_t, extendedFunction, ExtendedFunction);
+
+ __COPY(IOSP_EXT_FNCT);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__IOSP_EXT_FNCT_H__
diff --git a/p25/lc/tsbk/IOSP_GRP_AFF.cpp b/p25/lc/tsbk/IOSP_GRP_AFF.cpp
new file mode 100644
index 00000000..45ba92f1
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_GRP_AFF.cpp
@@ -0,0 +1,113 @@
+/**
+* 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 "p25/lc/tsbk/IOSP_GRP_AFF.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the IOSP_GRP_AFF class.
+///
+IOSP_GRP_AFF::IOSP_GRP_AFF() : TSBK(),
+ m_announceGroup(P25_WUID_ALL)
+{
+ m_lco = TSBK_IOSP_GRP_AFF;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool IOSP_GRP_AFF::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_sysId = (uint32_t)((tsbkValue >> 40) & 0xFFFU); // System ID
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFU); // Talkgroup Address
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void IOSP_GRP_AFF::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = 1U; // Local/Global Affiliation Flag (0 = Local, 1 = Global)
+ tsbkValue = (tsbkValue << 7) + (m_response & 0x3U); // Affiliation Response
+ tsbkValue = (tsbkValue << 16) + (m_announceGroup & 0xFFFFU); // Announcement Group Address
+ tsbkValue = (tsbkValue << 16) + (m_dstId & 0xFFFFU); // Talkgroup Address
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void IOSP_GRP_AFF::copy(const IOSP_GRP_AFF& data)
+{
+ TSBK::copy(data);
+
+ m_announceGroup = data.m_announceGroup;
+}
diff --git a/p25/lc/tsbk/IOSP_GRP_AFF.h b/p25/lc/tsbk/IOSP_GRP_AFF.h
new file mode 100644
index 00000000..68075fa3
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_GRP_AFF.h
@@ -0,0 +1,64 @@
+/**
+* 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(__P25_LC_TSBK__IOSP_GRP_AFF_H__)
+#define __P25_LC_TSBK__IOSP_GRP_AFF_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements GRP AFF REQ - Group Affiliation Request (ISP) and
+ // GRP AFF RSP - Group Affiliation Response (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API IOSP_GRP_AFF : public TSBK {
+ public:
+ /// Initializes a new instance of the IOSP_GRP_AFF class.
+ IOSP_GRP_AFF();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /// Announcement group.
+ __PROPERTY(uint32_t, announceGroup, AnnounceGroup);
+
+ __COPY(IOSP_GRP_AFF);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__IOSP_GRP_AFF_H__
diff --git a/p25/lc/tsbk/IOSP_GRP_VCH.cpp b/p25/lc/tsbk/IOSP_GRP_VCH.cpp
new file mode 100644
index 00000000..02be0ef0
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_GRP_VCH.cpp
@@ -0,0 +1,104 @@
+/**
+* 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 "p25/lc/tsbk/IOSP_GRP_VCH.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the IOSP_GRP_VCH class.
+///
+IOSP_GRP_VCH::IOSP_GRP_VCH() : TSBK()
+{
+ m_lco = TSBK_IOSP_GRP_VCH;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool IOSP_GRP_VCH::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_emergency = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Emergency Flag
+ m_encrypted = (((tsbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Encryption Flag
+ m_priority = (((tsbkValue >> 56) & 0xFFU) & 0x07U); // Priority
+ m_grpVchId = ((tsbkValue >> 52) & 0x0FU); // Channel ID
+ m_grpVchNo = ((tsbkValue >> 40) & 0xFFFU); // Channel Number
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFU); // Target Radio Address
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void IOSP_GRP_VCH::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue =
+ (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
+ (m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag
+ (m_priority & 0x07U); // Priority
+ tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID
+ tsbkValue = (tsbkValue << 12) + m_grpVchNo; // Channel Number
+ tsbkValue = (tsbkValue << 16) + m_dstId; // Talkgroup Address
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/IOSP_GRP_VCH.h b/p25/lc/tsbk/IOSP_GRP_VCH.h
new file mode 100644
index 00000000..ac848786
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_GRP_VCH.h
@@ -0,0 +1,58 @@
+/**
+* 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(__P25_LC_TSBK__IOSP_GRP_VCH_H__)
+#define __P25_LC_TSBK__IOSP_GRP_VCH_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements GRP VCH REQ - Group Voice Channel Request (ISP) and
+ // GRP VCH GRANT - Group Voice Channel Grant (OSP).
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API IOSP_GRP_VCH : public TSBK {
+ public:
+ /// Initializes a new instance of the IOSP_GRP_VCH class.
+ IOSP_GRP_VCH();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__IOSP_GRP_VCH_H__
diff --git a/p25/lc/tsbk/IOSP_MSG_UPDT.cpp b/p25/lc/tsbk/IOSP_MSG_UPDT.cpp
new file mode 100644
index 00000000..b534e280
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_MSG_UPDT.cpp
@@ -0,0 +1,111 @@
+/**
+* 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 "p25/lc/tsbk/IOSP_MSG_UPDT.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the IOSP_MSG_UPDT class.
+///
+IOSP_MSG_UPDT::IOSP_MSG_UPDT() : TSBK(),
+ m_messageValue(0U)
+{
+ m_lco = TSBK_IOSP_MSG_UPDT;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool IOSP_MSG_UPDT::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_messageValue = (uint8_t)((tsbkValue >> 56) & 0xFFU); // Message Value
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void IOSP_MSG_UPDT::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = (tsbkValue << 16) + m_messageValue; // Message Value
+ tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void IOSP_MSG_UPDT::copy(const IOSP_MSG_UPDT& data)
+{
+ TSBK::copy(data);
+
+ m_messageValue = data.m_messageValue;
+}
diff --git a/p25/lc/tsbk/IOSP_MSG_UPDT.h b/p25/lc/tsbk/IOSP_MSG_UPDT.h
new file mode 100644
index 00000000..78304ed1
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_MSG_UPDT.h
@@ -0,0 +1,64 @@
+/**
+* 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(__P25_LC_TSBK__IOSP_MSG_UPDT_H__)
+#define __P25_LC_TSBK__IOSP_MSG_UPDT_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements MSG UPDT REQ - Message Update Request (ISP) and
+ // MSG UPDT - Message Update (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API IOSP_MSG_UPDT : public TSBK {
+ public:
+ /// Initializes a new instance of the IOSP_MSG_UPDT class.
+ IOSP_MSG_UPDT();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /// Status value.
+ __PROPERTY(uint8_t, messageValue, Message);
+
+ __COPY(IOSP_MSG_UPDT);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__IOSP_MSG_UPDT_H__
diff --git a/p25/lc/tsbk/IOSP_RAD_MON.cpp b/p25/lc/tsbk/IOSP_RAD_MON.cpp
new file mode 100644
index 00000000..c8782889
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_RAD_MON.cpp
@@ -0,0 +1,112 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+* Copyright (C) 2022 by Jason- UWU - TIME_DATE_ANN & RAD_MON_CMD
+*
+* 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 "p25/lc/tsbk/IOSP_RAD_MON.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the IOSP_RAD_MON class.
+///
+IOSP_RAD_MON::IOSP_RAD_MON() : TSBK(),
+ m_txMult(0U)
+{
+ m_lco = TSBK_IOSP_RAD_MON;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool IOSP_RAD_MON::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_txMult = (uint8_t)((tsbkValue >> 48) & 0x3U); // TX Multiplier
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void IOSP_RAD_MON::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = (tsbkValue << 48) + (m_txMult & 0x3U); // TX Multiplier
+ tsbkValue = (tsbkValue << 24) + (m_srcId & 0xFFFFFFU); // Source Radio Address
+ tsbkValue = tsbkValue + (m_dstId & 0xFFFFFFU); // Target Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void IOSP_RAD_MON::copy(const IOSP_RAD_MON& data)
+{
+ TSBK::copy(data);
+
+ m_txMult = data.m_txMult;
+}
diff --git a/p25/lc/tsbk/IOSP_RAD_MON.h b/p25/lc/tsbk/IOSP_RAD_MON.h
new file mode 100644
index 00000000..12e07021
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_RAD_MON.h
@@ -0,0 +1,65 @@
+/**
+* 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
+* Copyright (C) 2022 by Jason- UWU - TIME_DATE_ANN & RAD_MON_CMD
+*
+* 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(__P25_LC_TSBK__IOSP_RAD_MON_H__)
+#define __P25_LC_TSBK__IOSP_RAD_MON_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements RAD MON REQ - Radio Unit Monitor Request (ISP) and
+ // RAD MON CMD - Radio Monitor Command (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API IOSP_RAD_MON : public TSBK {
+ public:
+ /// Initializes a new instance of the IOSP_RAD_MON class.
+ IOSP_RAD_MON();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /// Radio Unit Monitor.
+ __PROPERTY(uint8_t, txMult, TxMult);
+
+ __COPY(IOSP_RAD_MON);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__IOSP_RAD_MON_H__
diff --git a/p25/lc/tsbk/IOSP_STS_UPDT.cpp b/p25/lc/tsbk/IOSP_STS_UPDT.cpp
new file mode 100644
index 00000000..1e3d3682
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_STS_UPDT.cpp
@@ -0,0 +1,111 @@
+/**
+* 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 "p25/lc/tsbk/IOSP_STS_UPDT.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the IOSP_STS_UPDT class.
+///
+IOSP_STS_UPDT::IOSP_STS_UPDT() : TSBK(),
+ m_statusValue(0U)
+{
+ m_lco = TSBK_IOSP_STS_UPDT;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool IOSP_STS_UPDT::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_statusValue = (uint8_t)((tsbkValue >> 56) & 0xFFU); // Status Value
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void IOSP_STS_UPDT::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = (tsbkValue << 16) + m_statusValue; // Status Value
+ tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void IOSP_STS_UPDT::copy(const IOSP_STS_UPDT& data)
+{
+ TSBK::copy(data);
+
+ m_statusValue = data.m_statusValue;
+}
diff --git a/p25/lc/tsbk/IOSP_STS_UPDT.h b/p25/lc/tsbk/IOSP_STS_UPDT.h
new file mode 100644
index 00000000..f7772bb4
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_STS_UPDT.h
@@ -0,0 +1,64 @@
+/**
+* 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(__P25_LC_TSBK__IOSP_STS_UPDT_H__)
+#define __P25_LC_TSBK__IOSP_STS_UPDT_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements STS UPDT REQ - Status Update Request (ISP) and
+ // STS UPDT - Status Update (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API IOSP_STS_UPDT : public TSBK {
+ public:
+ /// Initializes a new instance of the IOSP_STS_UPDT class.
+ IOSP_STS_UPDT();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /// Status value.
+ __PROPERTY(uint8_t, statusValue, Status);
+
+ __COPY(IOSP_STS_UPDT);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__IOSP_STS_UPDT_H__
diff --git a/p25/lc/tsbk/IOSP_UU_ANS.cpp b/p25/lc/tsbk/IOSP_UU_ANS.cpp
new file mode 100644
index 00000000..ccc4666a
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_UU_ANS.cpp
@@ -0,0 +1,101 @@
+/**
+* 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 "p25/lc/tsbk/IOSP_UU_ANS.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the IOSP_UU_ANS class.
+///
+IOSP_UU_ANS::IOSP_UU_ANS() : TSBK()
+{
+ m_lco = TSBK_IOSP_UU_ANS;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool IOSP_UU_ANS::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_emergency = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Emergency Flag
+ m_encrypted = (((tsbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Encryption Flag
+ m_priority = (((tsbkValue >> 56) & 0xFFU) & 0x07U); // Priority
+ m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Answer Response
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void IOSP_UU_ANS::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue =
+ (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
+ (m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag
+ (m_priority & 0x07U); // Priority
+ tsbkValue = (tsbkValue << 32) + m_dstId; // Target Radio Address
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/IOSP_UU_ANS.h b/p25/lc/tsbk/IOSP_UU_ANS.h
new file mode 100644
index 00000000..c5afaac1
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_UU_ANS.h
@@ -0,0 +1,61 @@
+/**
+* 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(__P25_LC_TSBK__IOSP_UU_ANS_H__)
+#define __P25_LC_TSBK__IOSP_UU_ANS_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements UU ANS RSP - Unit-to-Unit Answer Response (ISP) and
+ // UU ANS REQ - Unit-to-Unit Answer Request (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API IOSP_UU_ANS : public TSBK {
+ public:
+ /// Initializes a new instance of the IOSP_UU_ANS class.
+ IOSP_UU_ANS();
+
+ /// Equals operator.
+ IOSP_UU_ANS& operator=(const IOSP_UU_ANS& data);
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__IOSP_UU_ANS_H__
diff --git a/p25/lc/tsbk/IOSP_UU_VCH.cpp b/p25/lc/tsbk/IOSP_UU_VCH.cpp
new file mode 100644
index 00000000..c8c34ce7
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_UU_VCH.cpp
@@ -0,0 +1,104 @@
+/**
+* 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 "p25/lc/tsbk/IOSP_UU_VCH.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the IOSP_UU_VCH class.
+///
+IOSP_UU_VCH::IOSP_UU_VCH() : TSBK()
+{
+ m_lco = TSBK_IOSP_UU_VCH;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool IOSP_UU_VCH::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_emergency = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Emergency Flag
+ m_encrypted = (((tsbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Encryption Flag
+ m_priority = (((tsbkValue >> 56) & 0xFFU) & 0x07U); // Priority
+ m_grpVchId = ((tsbkValue >> 52) & 0x0FU); // Channel ID
+ m_grpVchNo = ((tsbkValue >> 40) & 0xFFFU); // Channel Number
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFU); // Target Radio Address
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void IOSP_UU_VCH::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue =
+ (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
+ (m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag
+ (m_priority & 0x07U); // Priority
+ tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID
+ tsbkValue = (tsbkValue << 12) + m_grpVchNo; // Channel Number
+ tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/IOSP_UU_VCH.h b/p25/lc/tsbk/IOSP_UU_VCH.h
new file mode 100644
index 00000000..a6d098ef
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_UU_VCH.h
@@ -0,0 +1,58 @@
+/**
+* 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(__P25_LC_TSBK__IOSP_UU_VCH_H__)
+#define __P25_LC_TSBK__IOSP_UU_VCH_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements UU VCH REQ - Unit-to-Unit Voice Channel Request (ISP) and
+ // UU VCH GRANT - Unit-to-Unit Voice Channel Grant (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API IOSP_UU_VCH : public TSBK {
+ public:
+ /// Initializes a new instance of the IOSP_UU_VCH class.
+ IOSP_UU_VCH();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__IOSP_UU_VCH_H__
diff --git a/p25/lc/tsbk/IOSP_U_REG.cpp b/p25/lc/tsbk/IOSP_U_REG.cpp
new file mode 100644
index 00000000..bb7496d2
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_U_REG.cpp
@@ -0,0 +1,96 @@
+/**
+* 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 "p25/lc/tsbk/IOSP_U_REG.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the IOSP_U_REG class.
+///
+IOSP_U_REG::IOSP_U_REG() : TSBK()
+{
+ m_lco = TSBK_IOSP_U_REG;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool IOSP_U_REG::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_netId = (uint32_t)((tsbkValue >> 36) & 0xFFFFFU); // Network ID
+ m_sysId = (uint32_t)((tsbkValue >> 24) & 0xFFFU); // System ID
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void IOSP_U_REG::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = (tsbkValue << 2) + (m_response & 0x3U); // Unit Registration Response
+ tsbkValue = (tsbkValue << 12) + m_siteData.sysId(); // System ID
+ tsbkValue = (tsbkValue << 24) + m_dstId; // Source ID
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/IOSP_U_REG.h b/p25/lc/tsbk/IOSP_U_REG.h
new file mode 100644
index 00000000..3d7edaa8
--- /dev/null
+++ b/p25/lc/tsbk/IOSP_U_REG.h
@@ -0,0 +1,58 @@
+/**
+* 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(__P25_LC_TSBK__IOSP_U_REG_H__)
+#define __P25_LC_TSBK__IOSP_U_REG_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements U REG REQ - Unit Registration Request (ISP) and
+ // U REG RSP - Unit Registration Response (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API IOSP_U_REG : public TSBK {
+ public:
+ /// Initializes a new instance of the IOSP_U_REG class.
+ IOSP_U_REG();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__IOSP_U_REG_H__
diff --git a/p25/lc/tsbk/ISP_AUTH_FNE_RST.cpp b/p25/lc/tsbk/ISP_AUTH_FNE_RST.cpp
new file mode 100644
index 00000000..7faef8a1
--- /dev/null
+++ b/p25/lc/tsbk/ISP_AUTH_FNE_RST.cpp
@@ -0,0 +1,105 @@
+/**
+* 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 "p25/lc/tsbk/ISP_AUTH_FNE_RST.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the ISP_AUTH_FNE_RST class.
+///
+ISP_AUTH_FNE_RST::ISP_AUTH_FNE_RST() : TSBK(),
+ m_authSuccess(false),
+ m_authStandalone(false)
+{
+ m_lco = TSBK_ISP_AUTH_FNE_RST;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool ISP_AUTH_FNE_RST::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_authSuccess = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Authentication Success Flag
+ m_authStandalone = (((tsbkValue >> 56) & 0xFFU) & 0x01U) == 0x01U; // Authentication Standalone Flag
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void ISP_AUTH_FNE_RST::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ /* stub */
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void ISP_AUTH_FNE_RST::copy(const ISP_AUTH_FNE_RST& data)
+{
+ TSBK::copy(data);
+
+ m_authSuccess = data.m_authSuccess;
+ m_authStandalone = data.m_authStandalone;
+}
diff --git a/p25/lc/tsbk/ISP_AUTH_FNE_RST.h b/p25/lc/tsbk/ISP_AUTH_FNE_RST.h
new file mode 100644
index 00000000..3ca48b5b
--- /dev/null
+++ b/p25/lc/tsbk/ISP_AUTH_FNE_RST.h
@@ -0,0 +1,65 @@
+/**
+* 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(__P25_LC_TSBK__ISP_AUTH_FNE_RST_H__)
+#define __P25_LC_TSBK__ISP_AUTH_FNE_RST_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements AUTH FNE RST - Authentication FNE Result
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API ISP_AUTH_FNE_RST : public TSBK {
+ public:
+ /// Initializes a new instance of the ISP_AUTH_FNE_RST class.
+ ISP_AUTH_FNE_RST();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /// Flag indicating authentication was successful.
+ __PROPERTY(bool, authSuccess, AuthSuccess);
+ /// Flag indicating authentication is standalone.
+ __PROPERTY(bool, authStandalone, AuthStandalone);
+
+ __COPY(ISP_AUTH_FNE_RST);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__ISP_AUTH_FNE_RST_H__
diff --git a/p25/lc/tsbk/ISP_AUTH_RESP.cpp b/p25/lc/tsbk/ISP_AUTH_RESP.cpp
new file mode 100644
index 00000000..965fab7a
--- /dev/null
+++ b/p25/lc/tsbk/ISP_AUTH_RESP.cpp
@@ -0,0 +1,136 @@
+/**
+* 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 "p25/lc/tsbk/ISP_AUTH_RESP.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the ISP_AUTH_RESP class.
+///
+ISP_AUTH_RESP::ISP_AUTH_RESP() : TSBK(),
+ m_authStandalone(false),
+ m_authRes(NULL)
+{
+ m_lco = TSBK_ISP_AUTH_RESP;
+
+ m_authRes = new uint8_t[P25_AUTH_RES_LENGTH_BYTES];
+ ::memset(m_authRes, 0x00U, P25_AUTH_RES_LENGTH_BYTES);
+}
+
+///
+/// Finalizes a instance of ISP_AUTH_RESP class.
+///
+ISP_AUTH_RESP::~ISP_AUTH_RESP()
+{
+ if (m_authRes != NULL) {
+ delete[] m_authRes;
+ m_authRes = NULL;
+ }
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool ISP_AUTH_RESP::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_aivFlag = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Additional Info. Flag
+ m_service = (uint8_t)((tsbkValue >> 56) & 0x3FU); // Service Type
+ m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Reason
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void ISP_AUTH_RESP::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ /* stub */
+}
+
+/// Gets the authentication result.
+///
+void ISP_AUTH_RESP::getAuthRes(uint8_t* res) const
+{
+ assert(res != NULL);
+
+ ::memcpy(res, m_authRes, P25_AUTH_RES_LENGTH_BYTES);
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void ISP_AUTH_RESP::copy(const ISP_AUTH_RESP& data)
+{
+ TSBK::copy(data);
+
+ m_authStandalone = data.m_authStandalone;
+
+ if (m_authRes != NULL) {
+ delete[] m_authRes;
+ }
+
+ m_authRes = new uint8_t[P25_AUTH_RES_LENGTH_BYTES];
+ ::memcpy(m_authRes, data.m_authRes, P25_AUTH_RES_LENGTH_BYTES);
+}
diff --git a/p25/lc/tsbk/ISP_AUTH_RESP.h b/p25/lc/tsbk/ISP_AUTH_RESP.h
new file mode 100644
index 00000000..cdbcafee
--- /dev/null
+++ b/p25/lc/tsbk/ISP_AUTH_RESP.h
@@ -0,0 +1,73 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__ISP_AUTH_RESP_H__)
+#define __P25_LC_TSBK__ISP_AUTH_RESP_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements AUTH RESP - Authentication Response
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API ISP_AUTH_RESP : public TSBK {
+ public:
+ /// Initializes a new instance of the ISP_AUTH_RESP class.
+ ISP_AUTH_RESP();
+ /// Finalizes a instance of the ISP_AUTH_RESP class.
+ ~ISP_AUTH_RESP();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ /** Authentication data */
+ /// Gets the authentication result.
+ void getAuthRes(uint8_t* res) const;
+
+ public:
+ /// Flag indicating authentication is standalone.
+ __PROPERTY(bool, authStandalone, AuthStandalone);
+
+ private:
+ /** Authentication data */
+ uint8_t* m_authRes;
+
+ __COPY(ISP_AUTH_RESP);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__ISP_AUTH_RESP_H__
diff --git a/p25/lc/tsbk/ISP_AUTH_SU_DMD.cpp b/p25/lc/tsbk/ISP_AUTH_SU_DMD.cpp
new file mode 100644
index 00000000..4d5dc7eb
--- /dev/null
+++ b/p25/lc/tsbk/ISP_AUTH_SU_DMD.cpp
@@ -0,0 +1,85 @@
+/**
+* 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 "p25/lc/tsbk/ISP_AUTH_SU_DMD.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the ISP_AUTH_SU_DMD class.
+///
+ISP_AUTH_SU_DMD::ISP_AUTH_SU_DMD() : TSBK()
+{
+ m_lco = TSBK_ISP_AUTH_SU_DMD;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool ISP_AUTH_SU_DMD::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void ISP_AUTH_SU_DMD::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ /* stub */
+}
diff --git a/p25/lc/tsbk/ISP_AUTH_SU_DMD.h b/p25/lc/tsbk/ISP_AUTH_SU_DMD.h
new file mode 100644
index 00000000..8ead4ce7
--- /dev/null
+++ b/p25/lc/tsbk/ISP_AUTH_SU_DMD.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__ISP_AUTH_SU_DMD_H__)
+#define __P25_LC_TSBK__ISP_AUTH_SU_DMD_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements AUTH SU DMD - Authentication SU Demand
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API ISP_AUTH_SU_DMD : public TSBK {
+ public:
+ /// Initializes a new instance of the ISP_AUTH_SU_DMD class.
+ ISP_AUTH_SU_DMD();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__ISP_AUTH_SU_DMD_H__
diff --git a/p25/lc/tsbk/ISP_CAN_SRV_REQ.cpp b/p25/lc/tsbk/ISP_CAN_SRV_REQ.cpp
new file mode 100644
index 00000000..8c44df94
--- /dev/null
+++ b/p25/lc/tsbk/ISP_CAN_SRV_REQ.cpp
@@ -0,0 +1,89 @@
+/**
+* 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 "p25/lc/tsbk/ISP_CAN_SRV_REQ.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the ISP_CAN_SRV_REQ class.
+///
+ISP_CAN_SRV_REQ::ISP_CAN_SRV_REQ() : TSBK()
+{
+ m_lco = TSBK_ISP_CAN_SRV_REQ;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool ISP_CAN_SRV_REQ::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_aivFlag = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Additional Info. Flag
+ m_service = (uint8_t)((tsbkValue >> 56) & 0x3FU); // Service Type
+ m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Reason
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void ISP_CAN_SRV_REQ::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ /* stub */
+}
diff --git a/p25/lc/tsbk/ISP_CAN_SRV_REQ.h b/p25/lc/tsbk/ISP_CAN_SRV_REQ.h
new file mode 100644
index 00000000..b54f9814
--- /dev/null
+++ b/p25/lc/tsbk/ISP_CAN_SRV_REQ.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__ISP_CAN_SRV_REQ_H__)
+#define __P25_LC_TSBK__ISP_CAN_SRV_REQ_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements CAN SRV REQ - Cancel Service Request
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API ISP_CAN_SRV_REQ : public TSBK {
+ public:
+ /// Initializes a new instance of the ISP_CAN_SRV_REQ class.
+ ISP_CAN_SRV_REQ();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__ISP_CAN_SRV_REQ_H__
diff --git a/p25/lc/tsbk/ISP_EMERG_ALRM_REQ.cpp b/p25/lc/tsbk/ISP_EMERG_ALRM_REQ.cpp
new file mode 100644
index 00000000..18412775
--- /dev/null
+++ b/p25/lc/tsbk/ISP_EMERG_ALRM_REQ.cpp
@@ -0,0 +1,100 @@
+/**
+* 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 "p25/lc/tsbk/ISP_EMERG_ALRM_REQ.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the ISP_EMERG_ALRM_REQ class.
+///
+ISP_EMERG_ALRM_REQ::ISP_EMERG_ALRM_REQ() : TSBK()
+{
+ m_lco = TSBK_ISP_EMERG_ALRM_REQ;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool ISP_EMERG_ALRM_REQ::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ /*
+ ** bryanb: this is a bit of a hack -- because the EMERG ALRM and DENY have the same
+ ** opcode; the following are used by TSBK_OSP_DENY_RSP; best way to check is for m_response > 0
+ */
+ m_aivFlag = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Additional Info. Flag
+ m_service = (uint8_t)((tsbkValue >> 56) & 0x3FU); // Service Type
+ m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Reason
+
+ if (m_response == 0U) {
+ m_emergency = true;
+ } else {
+ m_emergency = false;
+ }
+
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFU); // Target Radio Address
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void ISP_EMERG_ALRM_REQ::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ /* stub */
+}
diff --git a/p25/lc/tsbk/ISP_EMERG_ALRM_REQ.h b/p25/lc/tsbk/ISP_EMERG_ALRM_REQ.h
new file mode 100644
index 00000000..fab0c0b2
--- /dev/null
+++ b/p25/lc/tsbk/ISP_EMERG_ALRM_REQ.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__ISP_EMERG_ALRM_REQ_H__)
+#define __P25_LC_TSBK__ISP_EMERG_ALRM_REQ_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements EMERG ALRM REQ - Emergency Alarm Request
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API ISP_EMERG_ALRM_REQ : public TSBK {
+ public:
+ /// Initializes a new instance of the ISP_EMERG_ALRM_REQ class.
+ ISP_EMERG_ALRM_REQ();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__ISP_EMERG_ALRM_REQ_H__
diff --git a/p25/lc/tsbk/ISP_GRP_AFF_Q_RSP.cpp b/p25/lc/tsbk/ISP_GRP_AFF_Q_RSP.cpp
new file mode 100644
index 00000000..a13fb0c3
--- /dev/null
+++ b/p25/lc/tsbk/ISP_GRP_AFF_Q_RSP.cpp
@@ -0,0 +1,103 @@
+/**
+* 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 "p25/lc/tsbk/ISP_GRP_AFF_Q_RSP.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the ISP_GRP_AFF_Q_RSP class.
+///
+ISP_GRP_AFF_Q_RSP::ISP_GRP_AFF_Q_RSP() : TSBK(),
+ m_announceGroup(P25_WUID_ALL)
+{
+ m_lco = TSBK_ISP_GRP_AFF_Q_RSP;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool ISP_GRP_AFF_Q_RSP::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_announceGroup = (uint32_t)((tsbkValue >> 40) & 0xFFFFU); // Announcement Group Address
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFU); // Talkgroup Address
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void ISP_GRP_AFF_Q_RSP::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ /* stub */
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void ISP_GRP_AFF_Q_RSP::copy(const ISP_GRP_AFF_Q_RSP& data)
+{
+ TSBK::copy(data);
+
+ m_announceGroup = data.m_announceGroup;
+}
diff --git a/p25/lc/tsbk/ISP_GRP_AFF_Q_RSP.h b/p25/lc/tsbk/ISP_GRP_AFF_Q_RSP.h
new file mode 100644
index 00000000..e67c3532
--- /dev/null
+++ b/p25/lc/tsbk/ISP_GRP_AFF_Q_RSP.h
@@ -0,0 +1,63 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__ISP_GRP_AFF_Q_RSP_H__)
+#define __P25_LC_TSBK__ISP_GRP_AFF_Q_RSP_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements GRP AFF Q RSP - Group Affiliation Query Response
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API ISP_GRP_AFF_Q_RSP : public TSBK {
+ public:
+ /// Initializes a new instance of the ISP_GRP_AFF_Q_RSP class.
+ ISP_GRP_AFF_Q_RSP();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /// Announcement group.
+ __PROPERTY(uint32_t, announceGroup, AnnounceGroup);
+
+ __COPY(ISP_GRP_AFF_Q_RSP);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__ISP_GRP_AFF_Q_RSP_H__
diff --git a/p25/lc/tsbk/ISP_LOC_REG_REQ.cpp b/p25/lc/tsbk/ISP_LOC_REG_REQ.cpp
new file mode 100644
index 00000000..ff7a6e2b
--- /dev/null
+++ b/p25/lc/tsbk/ISP_LOC_REG_REQ.cpp
@@ -0,0 +1,103 @@
+/**
+* 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 "p25/lc/tsbk/ISP_LOC_REG_REQ.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the ISP_LOC_REG_REQ class.
+///
+ISP_LOC_REG_REQ::ISP_LOC_REG_REQ() : TSBK(),
+ m_lra(0U)
+{
+ m_lco = TSBK_ISP_LOC_REG_REQ;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool ISP_LOC_REG_REQ::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_lra = (uint8_t)((tsbkValue >> 40) & 0xFFU); // LRA
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFU); // Talkgroup Address
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void ISP_LOC_REG_REQ::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ /* stub */
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void ISP_LOC_REG_REQ::copy(const ISP_LOC_REG_REQ& data)
+{
+ TSBK::copy(data);
+
+ m_lra = data.m_lra;
+}
diff --git a/p25/lc/tsbk/ISP_LOC_REG_REQ.h b/p25/lc/tsbk/ISP_LOC_REG_REQ.h
new file mode 100644
index 00000000..08327923
--- /dev/null
+++ b/p25/lc/tsbk/ISP_LOC_REG_REQ.h
@@ -0,0 +1,63 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__ISP_LOC_REG_REQ_H__)
+#define __P25_LC_TSBK__ISP_LOC_REG_REQ_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements LOC REG REQ - Location Registration Request
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API ISP_LOC_REG_REQ : public TSBK {
+ public:
+ /// Initializes a new instance of the ISP_LOC_REG_REQ class.
+ ISP_LOC_REG_REQ();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /// Location registration area.
+ __PROPERTY(uint8_t, lra, LRA);
+
+ __COPY(ISP_LOC_REG_REQ);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__ISP_LOC_REG_REQ_H__
diff --git a/p25/lc/tsbk/ISP_SNDCP_CH_REQ.cpp b/p25/lc/tsbk/ISP_SNDCP_CH_REQ.cpp
new file mode 100644
index 00000000..abfa11e0
--- /dev/null
+++ b/p25/lc/tsbk/ISP_SNDCP_CH_REQ.cpp
@@ -0,0 +1,105 @@
+/**
+* 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 "p25/lc/tsbk/ISP_SNDCP_CH_REQ.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the ISP_SNDCP_CH_REQ class.
+///
+ISP_SNDCP_CH_REQ::ISP_SNDCP_CH_REQ() : TSBK(),
+ m_dataServiceOptions(0U),
+ m_dataAccessControl(0U)
+{
+ m_lco = TSBK_ISP_SNDCP_CH_REQ;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool ISP_SNDCP_CH_REQ::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_dataServiceOptions = (uint8_t)((tsbkValue >> 56) & 0xFFU); // Data Service Options
+ m_dataAccessControl = (uint32_t)((tsbkValue >> 40) & 0xFFFFFFFFU); // Data Access Control
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void ISP_SNDCP_CH_REQ::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ /* stub */
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void ISP_SNDCP_CH_REQ::copy(const ISP_SNDCP_CH_REQ& data)
+{
+ TSBK::copy(data);
+
+ m_dataServiceOptions = data.m_dataServiceOptions;
+ m_dataAccessControl = data.m_dataAccessControl;
+}
diff --git a/p25/lc/tsbk/ISP_SNDCP_CH_REQ.h b/p25/lc/tsbk/ISP_SNDCP_CH_REQ.h
new file mode 100644
index 00000000..5dac1cf6
--- /dev/null
+++ b/p25/lc/tsbk/ISP_SNDCP_CH_REQ.h
@@ -0,0 +1,65 @@
+/**
+* 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(__P25_LC_TSBK__ISP_SNDCP_CH_REQ_H__)
+#define __P25_LC_TSBK__ISP_SNDCP_CH_REQ_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements SNDCP CH REQ - SNDCP Data Channel Request (ISP).
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API ISP_SNDCP_CH_REQ : public TSBK {
+ public:
+ /// Initializes a new instance of the ISP_SNDCP_CH_REQ class.
+ ISP_SNDCP_CH_REQ();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /// SNDCP Data Service Options
+ __PROPERTY(uint8_t, dataServiceOptions, DataServiceOptions);
+ /// SNDCP Data Access Control
+ __PROPERTY(uint32_t, dataAccessControl, DataAccessControl);
+
+ __COPY(ISP_SNDCP_CH_REQ);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__ISP_SNDCP_CH_REQ_H__
diff --git a/p25/lc/tsbk/ISP_U_DEREG_REQ.cpp b/p25/lc/tsbk/ISP_U_DEREG_REQ.cpp
new file mode 100644
index 00000000..0ef5beda
--- /dev/null
+++ b/p25/lc/tsbk/ISP_U_DEREG_REQ.cpp
@@ -0,0 +1,87 @@
+/**
+* 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 "p25/lc/tsbk/ISP_U_DEREG_REQ.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the ISP_U_DEREG_REQ class.
+///
+ISP_U_DEREG_REQ::ISP_U_DEREG_REQ() : TSBK()
+{
+ m_lco = TSBK_ISP_U_DEREG_REQ;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool ISP_U_DEREG_REQ::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_netId = (uint32_t)((tsbkValue >> 36) & 0xFFFFFU); // Network ID
+ m_sysId = (uint32_t)((tsbkValue >> 24) & 0xFFFU); // System ID
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void ISP_U_DEREG_REQ::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ /* stub */
+}
diff --git a/p25/lc/tsbk/ISP_U_DEREG_REQ.h b/p25/lc/tsbk/ISP_U_DEREG_REQ.h
new file mode 100644
index 00000000..4b5d3a3f
--- /dev/null
+++ b/p25/lc/tsbk/ISP_U_DEREG_REQ.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__ISP_U_DEREG_REQ_H__)
+#define __P25_LC_TSBK__ISP_U_DEREG_REQ_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements U DE REG REQ - Unit De-Registration Request
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API ISP_U_DEREG_REQ : public TSBK {
+ public:
+ /// Initializes a new instance of the ISP_U_DEREG_REQ class.
+ ISP_U_DEREG_REQ();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__ISP_U_DEREG_REQ_H__
diff --git a/p25/lc/tsbk/MBT_IOSP_ACK_RSP.cpp b/p25/lc/tsbk/MBT_IOSP_ACK_RSP.cpp
new file mode 100644
index 00000000..7db23d5f
--- /dev/null
+++ b/p25/lc/tsbk/MBT_IOSP_ACK_RSP.cpp
@@ -0,0 +1,91 @@
+/**
+* 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 "p25/lc/tsbk/MBT_IOSP_ACK_RSP.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MBT_IOSP_ACK_RSP class.
+///
+MBT_IOSP_ACK_RSP::MBT_IOSP_ACK_RSP() : AMBT()
+{
+ m_lco = TSBK_IOSP_ACK_RSP;
+}
+
+///
+/// Decode a alternate trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool MBT_IOSP_ACK_RSP::decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks)
+{
+ assert(blocks != NULL);
+
+ uint8_t pduUserData[P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow()];
+ ::memset(pduUserData, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow());
+
+ bool ret = AMBT::decode(dataHeader, blocks, pduUserData);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = AMBT::tsbkValue(dataHeader, pduUserData);
+
+ m_aivFlag = false;
+ m_service = (uint8_t)((tsbkValue >> 56) & 0x3FU); // Service Type
+ m_netId = (uint32_t)((tsbkValue >> 36) & 0xFFFFFU); // Network ID
+ m_sysId = (uint32_t)((tsbkValue >> 24) & 0xFFFU); // System ID
+ m_dstId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Target Radio Address
+ m_srcId = dataHeader.getLLId(); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a alternate trunking signalling block.
+///
+///
+///
+void MBT_IOSP_ACK_RSP::encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData)
+{
+ assert(pduUserData != NULL);
+
+ /* stub */
+
+ return;
+}
diff --git a/p25/lc/tsbk/MBT_IOSP_ACK_RSP.h b/p25/lc/tsbk/MBT_IOSP_ACK_RSP.h
new file mode 100644
index 00000000..f984b124
--- /dev/null
+++ b/p25/lc/tsbk/MBT_IOSP_ACK_RSP.h
@@ -0,0 +1,58 @@
+/**
+* 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(__P25_LC_TSBK__MBT_IOSP_ACK_RSP_H__)
+#define __P25_LC_TSBK__MBT_IOSP_ACK_RSP_H__
+
+#include "Defines.h"
+#include "p25/lc/AMBT.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements ACK RSP U - Acknowledge Response - Unit (ISP) and
+ // ACK RSP FNE - Acknowledge Response - FNE (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MBT_IOSP_ACK_RSP : public AMBT {
+ public:
+ /// Initializes a new instance of the MBT_IOSP_ACK_RSP class.
+ MBT_IOSP_ACK_RSP();
+
+ /// Decode a alternate trunking signalling block.
+ virtual bool decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks);
+ /// Encode a alternate trunking signalling block.
+ virtual void encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__MBT_IOSP_ACK_RSP_H__
diff --git a/p25/lc/tsbk/MBT_IOSP_CALL_ALRT.cpp b/p25/lc/tsbk/MBT_IOSP_CALL_ALRT.cpp
new file mode 100644
index 00000000..82eb89bb
--- /dev/null
+++ b/p25/lc/tsbk/MBT_IOSP_CALL_ALRT.cpp
@@ -0,0 +1,89 @@
+/**
+* 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 "p25/lc/tsbk/MBT_IOSP_CALL_ALRT.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MBT_IOSP_CALL_ALRT class.
+///
+MBT_IOSP_CALL_ALRT::MBT_IOSP_CALL_ALRT() : AMBT()
+{
+ m_lco = TSBK_IOSP_CALL_ALRT;
+}
+
+///
+/// Decode a alternate trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool MBT_IOSP_CALL_ALRT::decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks)
+{
+ assert(blocks != NULL);
+
+ uint8_t pduUserData[P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow()];
+ ::memset(pduUserData, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow());
+
+ bool ret = AMBT::decode(dataHeader, blocks, pduUserData);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = AMBT::tsbkValue(dataHeader, pduUserData);
+
+ m_netId = (uint32_t)((tsbkValue >> 44) & 0xFFFFFU); // Network ID
+ m_sysId = (uint32_t)((tsbkValue >> 32) & 0xFFFU); // System ID
+ m_dstId = (uint32_t)((tsbkValue >> 8) & 0xFFFFFFU); // Target Radio Address
+ m_srcId = dataHeader.getLLId(); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a alternate trunking signalling block.
+///
+///
+///
+void MBT_IOSP_CALL_ALRT::encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData)
+{
+ assert(pduUserData != NULL);
+
+ /* stub */
+
+ return;
+}
diff --git a/p25/lc/tsbk/MBT_IOSP_CALL_ALRT.h b/p25/lc/tsbk/MBT_IOSP_CALL_ALRT.h
new file mode 100644
index 00000000..b2971347
--- /dev/null
+++ b/p25/lc/tsbk/MBT_IOSP_CALL_ALRT.h
@@ -0,0 +1,58 @@
+/**
+* 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(__P25_LC_TSBK__MBT_IOSP_CALL_ALRT_H__)
+#define __P25_LC_TSBK__MBT_IOSP_CALL_ALRT_H__
+
+#include "Defines.h"
+#include "p25/lc/AMBT.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements CALL ALRT REQ - Call Alert Request (ISP) and
+ // CALL ALRT - Call Alert (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MBT_IOSP_CALL_ALRT : public AMBT {
+ public:
+ /// Initializes a new instance of the MBT_IOSP_CALL_ALRT class.
+ MBT_IOSP_CALL_ALRT();
+
+ /// Decode a alternate trunking signalling block.
+ virtual bool decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks);
+ /// Encode a alternate trunking signalling block.
+ virtual void encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__MBT_IOSP_CALL_ALRT_H__
diff --git a/p25/lc/tsbk/MBT_IOSP_EXT_FNCT.cpp b/p25/lc/tsbk/MBT_IOSP_EXT_FNCT.cpp
new file mode 100644
index 00000000..37cfc0b1
--- /dev/null
+++ b/p25/lc/tsbk/MBT_IOSP_EXT_FNCT.cpp
@@ -0,0 +1,106 @@
+/**
+* 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 "p25/lc/tsbk/MBT_IOSP_EXT_FNCT.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MBT_IOSP_EXT_FNCT class.
+///
+MBT_IOSP_EXT_FNCT::MBT_IOSP_EXT_FNCT() : AMBT(),
+ m_extendedFunction(P25_EXT_FNCT_CHECK)
+{
+ m_lco = TSBK_IOSP_EXT_FNCT;
+}
+
+///
+/// Decode a alternate trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool MBT_IOSP_EXT_FNCT::decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks)
+{
+ assert(blocks != NULL);
+
+ uint8_t pduUserData[P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow()];
+ ::memset(pduUserData, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow());
+
+ bool ret = AMBT::decode(dataHeader, blocks, pduUserData);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = AMBT::tsbkValue(dataHeader, pduUserData);
+
+ m_netId = (uint32_t)((tsbkValue >> 44) & 0xFFFFFU); // Network ID
+ m_sysId = (uint32_t)((tsbkValue >> 32) & 0xFFFU); // System ID
+ m_extendedFunction = (uint32_t)(((tsbkValue) & 0xFFFFU) << 8) + // Extended Function
+ pduUserData[6U];
+ m_srcId = dataHeader.getLLId(); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a alternate trunking signalling block.
+///
+///
+///
+void MBT_IOSP_EXT_FNCT::encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData)
+{
+ assert(pduUserData != NULL);
+
+ /* stub */
+
+ return;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void MBT_IOSP_EXT_FNCT::copy(const MBT_IOSP_EXT_FNCT& data)
+{
+ TSBK::copy(data);
+
+ m_extendedFunction = data.m_extendedFunction;
+}
diff --git a/p25/lc/tsbk/MBT_IOSP_EXT_FNCT.h b/p25/lc/tsbk/MBT_IOSP_EXT_FNCT.h
new file mode 100644
index 00000000..5941fe28
--- /dev/null
+++ b/p25/lc/tsbk/MBT_IOSP_EXT_FNCT.h
@@ -0,0 +1,64 @@
+/**
+* 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(__P25_LC_TSBK__MBT_IOSP_EXT_FNCT_H__)
+#define __P25_LC_TSBK__MBT_IOSP_EXT_FNCT_H__
+
+#include "Defines.h"
+#include "p25/lc/AMBT.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements EXT FNCT RSP - Extended Function Response (ISP) and
+ // EXT FNCT CMD - Extended Function Command (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MBT_IOSP_EXT_FNCT : public AMBT {
+ public:
+ /// Initializes a new instance of the MBT_IOSP_EXT_FNCT class.
+ MBT_IOSP_EXT_FNCT();
+
+ /// Decode a alternate trunking signalling block.
+ virtual bool decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks);
+ /// Encode a alternate trunking signalling block.
+ virtual void encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData);
+
+ public:
+ /// Extended function opcode.
+ __PROPERTY(uint32_t, extendedFunction, ExtendedFunction);
+
+ __COPY(MBT_IOSP_EXT_FNCT);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__MBT_IOSP_EXT_FNCT_H__
diff --git a/p25/lc/tsbk/MBT_IOSP_GRP_AFF.cpp b/p25/lc/tsbk/MBT_IOSP_GRP_AFF.cpp
new file mode 100644
index 00000000..6ff33a5e
--- /dev/null
+++ b/p25/lc/tsbk/MBT_IOSP_GRP_AFF.cpp
@@ -0,0 +1,89 @@
+/**
+* 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 "p25/lc/tsbk/MBT_IOSP_GRP_AFF.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MBT_IOSP_GRP_AFF class.
+///
+MBT_IOSP_GRP_AFF::MBT_IOSP_GRP_AFF() : AMBT()
+{
+ m_lco = TSBK_IOSP_GRP_AFF;
+}
+
+///
+/// Decode a alternate trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool MBT_IOSP_GRP_AFF::decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks)
+{
+ assert(blocks != NULL);
+
+ uint8_t pduUserData[P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow()];
+ ::memset(pduUserData, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow());
+
+ bool ret = AMBT::decode(dataHeader, blocks, pduUserData);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = AMBT::tsbkValue(dataHeader, pduUserData);
+
+ m_netId = (uint32_t)((tsbkValue >> 44) & 0xFFFFFU); // Network ID
+ m_sysId = (uint32_t)((tsbkValue >> 32) & 0xFFFU); // System ID
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFU); // Talkgroup Address
+ m_srcId = dataHeader.getLLId(); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a alternate trunking signalling block.
+///
+///
+///
+void MBT_IOSP_GRP_AFF::encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData)
+{
+ assert(pduUserData != NULL);
+
+ /* stub */
+
+ return;
+}
diff --git a/p25/lc/tsbk/MBT_IOSP_GRP_AFF.h b/p25/lc/tsbk/MBT_IOSP_GRP_AFF.h
new file mode 100644
index 00000000..8970ab94
--- /dev/null
+++ b/p25/lc/tsbk/MBT_IOSP_GRP_AFF.h
@@ -0,0 +1,58 @@
+/**
+* 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(__P25_LC_TSBK__MBT_IOSP_GRP_AFF_H__)
+#define __P25_LC_TSBK__MBT_IOSP_GRP_AFF_H__
+
+#include "Defines.h"
+#include "p25/lc/AMBT.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements GRP AFF REQ - Group Affiliation Request (ISP) and
+ // GRP AFF RSP - Group Affiliation Response (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MBT_IOSP_GRP_AFF : public AMBT {
+ public:
+ /// Initializes a new instance of the MBT_IOSP_GRP_AFF class.
+ MBT_IOSP_GRP_AFF();
+
+ /// Decode a alternate trunking signalling block.
+ virtual bool decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks);
+ /// Encode a alternate trunking signalling block.
+ virtual void encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__MBT_IOSP_GRP_AFF_H__
diff --git a/p25/lc/tsbk/MBT_IOSP_MSG_UPDT.cpp b/p25/lc/tsbk/MBT_IOSP_MSG_UPDT.cpp
new file mode 100644
index 00000000..28a42262
--- /dev/null
+++ b/p25/lc/tsbk/MBT_IOSP_MSG_UPDT.cpp
@@ -0,0 +1,106 @@
+/**
+* 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 "p25/lc/tsbk/MBT_IOSP_MSG_UPDT.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MBT_IOSP_MSG_UPDT class.
+///
+MBT_IOSP_MSG_UPDT::MBT_IOSP_MSG_UPDT() : AMBT(),
+ m_messageValue(0U)
+{
+ m_lco = TSBK_IOSP_MSG_UPDT;
+}
+
+///
+/// Decode a alternate trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool MBT_IOSP_MSG_UPDT::decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks)
+{
+ assert(blocks != NULL);
+
+ uint8_t pduUserData[P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow()];
+ ::memset(pduUserData, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow());
+
+ bool ret = AMBT::decode(dataHeader, blocks, pduUserData);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = AMBT::tsbkValue(dataHeader, pduUserData);
+
+ m_messageValue = (uint8_t)((tsbkValue >> 48) & 0xFFFFU); // Message Value
+ m_netId = (uint32_t)((tsbkValue >> 28) & 0xFFFFFU); // Network ID
+ m_sysId = (uint32_t)((tsbkValue >> 16) & 0xFFFU); // System ID
+ m_dstId = (uint32_t)(((tsbkValue) & 0xFFFFU) << 8) + pduUserData[6U]; // Target Radio Address
+ m_srcId = dataHeader.getLLId(); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a alternate trunking signalling block.
+///
+///
+///
+void MBT_IOSP_MSG_UPDT::encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData)
+{
+ assert(pduUserData != NULL);
+
+ /* stub */
+
+ return;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void MBT_IOSP_MSG_UPDT::copy(const MBT_IOSP_MSG_UPDT& data)
+{
+ TSBK::copy(data);
+
+ m_messageValue = data.m_messageValue;
+}
diff --git a/p25/lc/tsbk/MBT_IOSP_MSG_UPDT.h b/p25/lc/tsbk/MBT_IOSP_MSG_UPDT.h
new file mode 100644
index 00000000..ca48ee18
--- /dev/null
+++ b/p25/lc/tsbk/MBT_IOSP_MSG_UPDT.h
@@ -0,0 +1,64 @@
+/**
+* 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(__P25_LC_TSBK__MBT_IOSP_MSG_UPDT_H__)
+#define __P25_LC_TSBK__MBT_IOSP_MSG_UPDT_H__
+
+#include "Defines.h"
+#include "p25/lc/AMBT.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements MSG UPDT REQ - Message Update Request (ISP) and
+ // MSG UPDT - Message Update (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MBT_IOSP_MSG_UPDT : public AMBT {
+ public:
+ /// Initializes a new instance of the MBT_IOSP_MSG_UPDT class.
+ MBT_IOSP_MSG_UPDT();
+
+ /// Decode a alternate trunking signalling block.
+ virtual bool decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks);
+ /// Encode a alternate trunking signalling block.
+ virtual void encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData);
+
+ public:
+ /// Message value.
+ __PROPERTY(uint8_t, messageValue, Message);
+
+ __COPY(MBT_IOSP_MSG_UPDT);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__MBT_IOSP_MSG_UPDT_H__
diff --git a/p25/lc/tsbk/MBT_IOSP_STS_UPDT.cpp b/p25/lc/tsbk/MBT_IOSP_STS_UPDT.cpp
new file mode 100644
index 00000000..fcb41214
--- /dev/null
+++ b/p25/lc/tsbk/MBT_IOSP_STS_UPDT.cpp
@@ -0,0 +1,106 @@
+/**
+* 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 "p25/lc/tsbk/MBT_IOSP_STS_UPDT.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MBT_IOSP_STS_UPDT class.
+///
+MBT_IOSP_STS_UPDT::MBT_IOSP_STS_UPDT() : AMBT(),
+ m_statusValue(0U)
+{
+ m_lco = TSBK_IOSP_STS_UPDT;
+}
+
+///
+/// Decode a alternate trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool MBT_IOSP_STS_UPDT::decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks)
+{
+ assert(blocks != NULL);
+
+ uint8_t pduUserData[P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow()];
+ ::memset(pduUserData, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow());
+
+ bool ret = AMBT::decode(dataHeader, blocks, pduUserData);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = AMBT::tsbkValue(dataHeader, pduUserData);
+
+ m_statusValue = (uint8_t)((tsbkValue >> 48) & 0xFFFFU); // Message Value
+ m_netId = (uint32_t)((tsbkValue >> 28) & 0xFFFFFU); // Network ID
+ m_sysId = (uint32_t)((tsbkValue >> 16) & 0xFFFU); // System ID
+ m_dstId = (uint32_t)(((tsbkValue) & 0xFFFFU) << 8) + pduUserData[6U]; // Target Radio Address
+ m_srcId = dataHeader.getLLId(); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a alternate trunking signalling block.
+///
+///
+///
+void MBT_IOSP_STS_UPDT::encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData)
+{
+ assert(pduUserData != NULL);
+
+ /* stub */
+
+ return;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void MBT_IOSP_STS_UPDT::copy(const MBT_IOSP_STS_UPDT& data)
+{
+ TSBK::copy(data);
+
+ m_statusValue = data.m_statusValue;
+}
diff --git a/p25/lc/tsbk/MBT_IOSP_STS_UPDT.h b/p25/lc/tsbk/MBT_IOSP_STS_UPDT.h
new file mode 100644
index 00000000..0f5c00a6
--- /dev/null
+++ b/p25/lc/tsbk/MBT_IOSP_STS_UPDT.h
@@ -0,0 +1,64 @@
+/**
+* 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(__P25_LC_TSBK__MBT_IOSP_STS_UPDT_H__)
+#define __P25_LC_TSBK__MBT_IOSP_STS_UPDT_H__
+
+#include "Defines.h"
+#include "p25/lc/AMBT.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements STS UPDT REQ - Status Update Request (ISP) and
+ // STS UPDT - Status Update (OSP)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MBT_IOSP_STS_UPDT : public AMBT {
+ public:
+ /// Initializes a new instance of the MBT_IOSP_STS_UPDT class.
+ MBT_IOSP_STS_UPDT();
+
+ /// Decode a alternate trunking signalling block.
+ virtual bool decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks);
+ /// Encode a alternate trunking signalling block.
+ virtual void encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData);
+
+ public:
+ /// Status value.
+ __PROPERTY(uint8_t, statusValue, Status);
+
+ __COPY(MBT_IOSP_STS_UPDT);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__MBT_IOSP_STS_UPDT_H__
diff --git a/p25/lc/tsbk/MBT_ISP_AUTH_RESP_M.cpp b/p25/lc/tsbk/MBT_ISP_AUTH_RESP_M.cpp
new file mode 100644
index 00000000..8751a080
--- /dev/null
+++ b/p25/lc/tsbk/MBT_ISP_AUTH_RESP_M.cpp
@@ -0,0 +1,184 @@
+/**
+* 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 "p25/lc/tsbk/MBT_ISP_AUTH_RESP_M.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MBT_ISP_AUTH_RESP_M class.
+///
+MBT_ISP_AUTH_RESP_M::MBT_ISP_AUTH_RESP_M() : AMBT()
+{
+ m_lco = TSBK_ISP_AUTH_RESP_M;
+
+ m_authRes = new uint8_t[P25_AUTH_RES_LENGTH_BYTES];
+ ::memset(m_authRes, 0x00U, P25_AUTH_RES_LENGTH_BYTES);
+ m_authRC = new uint8_t[P25_AUTH_RAND_CHLNG_LENGTH_BYTES];
+ ::memset(m_authRC, 0x00U, P25_AUTH_RAND_CHLNG_LENGTH_BYTES);
+}
+
+///
+/// Finalizes a instance of MBT_ISP_AUTH_RESP_M class.
+///
+MBT_ISP_AUTH_RESP_M::~MBT_ISP_AUTH_RESP_M()
+{
+ if (m_authRes != NULL) {
+ delete[] m_authRes;
+ m_authRes = NULL;
+ }
+
+ if (m_authRC != NULL) {
+ delete[] m_authRC;
+ m_authRC = NULL;
+ }
+}
+
+///
+/// Decode a alternate trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool MBT_ISP_AUTH_RESP_M::decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks)
+{
+ assert(blocks != NULL);
+
+ uint8_t pduUserData[P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow()];
+ ::memset(pduUserData, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow());
+
+ bool ret = AMBT::decode(dataHeader, blocks, pduUserData);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = AMBT::tsbkValue(dataHeader, pduUserData);
+
+ if (dataHeader.getBlocksToFollow() != 2) {
+ LogError(LOG_P25, "TSBK::decodeMBT(), PDU does not contain the appropriate amount of data blocks");
+ return false;
+ }
+
+ m_netId = (uint32_t)((tsbkValue >> 44) & 0xFFFFFU); // Network ID
+ m_sysId = (uint32_t)((tsbkValue >> 32) & 0xFFFU); // System ID
+ m_srcId = dataHeader.getLLId(); // Source Radio Address
+
+ /** Block 1 */
+ m_authRC[4U] = (uint8_t)pduUserData[5U] & 0xFFU; // Random Challenge b4
+ m_authRC[3U] = (uint8_t)pduUserData[6U] & 0xFFU; // Random Challenge b3
+ m_authRC[2U] = (uint8_t)pduUserData[7U] & 0xFFU; // Random Challenge b2
+ m_authRC[1U] = (uint8_t)pduUserData[8U] & 0xFFU; // Random Challenge b1
+ m_authRC[0U] = (uint8_t)pduUserData[9U] & 0xFFU; // Random Challenge b0
+ m_authRes[3U] = (uint8_t)pduUserData[10U] & 0xFFU; // Result b3
+ m_authRes[2U] = (uint8_t)pduUserData[11U] & 0xFFU; // Result b2
+
+ /** Block 2 */
+ m_authRes[1U] = (uint8_t)pduUserData[12U] & 0xFFU; // Result b1
+ m_authRes[0U] = (uint8_t)pduUserData[13U] & 0xFFU; // Result b0
+ m_authStandalone = ((pduUserData[14U] & 0xFFU) & 0x01U) == 0x01U; // Authentication Standalone Flag
+
+ return true;
+}
+
+///
+/// Encode a alternate trunking signalling block.
+///
+///
+///
+void MBT_ISP_AUTH_RESP_M::encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData)
+{
+ assert(pduUserData != NULL);
+
+ /* stub */
+
+ return;
+}
+
+/// Gets the authentication result.
+///
+void MBT_ISP_AUTH_RESP_M::getAuthRes(uint8_t* res) const
+{
+ assert(res != NULL);
+
+ ::memcpy(res, m_authRes, P25_AUTH_RES_LENGTH_BYTES);
+}
+
+/// Sets the authentication random challenge.
+///
+void MBT_ISP_AUTH_RESP_M::setAuthRC(const uint8_t* rc)
+{
+ assert(rc != NULL);
+
+ ::memcpy(m_authRC, rc, P25_AUTH_RAND_CHLNG_LENGTH_BYTES);
+}
+
+/// Gets the authentication random challenge.
+///
+void MBT_ISP_AUTH_RESP_M::getAuthRC(uint8_t* rc) const
+{
+ assert(rc != NULL);
+
+ ::memcpy(rc, m_authRC, P25_AUTH_RAND_CHLNG_LENGTH_BYTES);
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void MBT_ISP_AUTH_RESP_M::copy(const MBT_ISP_AUTH_RESP_M& data)
+{
+ TSBK::copy(data);
+
+ m_authStandalone = data.m_authStandalone;
+
+ if (m_authRes != NULL) {
+ delete[] m_authRes;
+ }
+
+ m_authRes = new uint8_t[P25_AUTH_RES_LENGTH_BYTES];
+ ::memcpy(m_authRes, data.m_authRes, P25_AUTH_RES_LENGTH_BYTES);
+
+ if (m_authRC != NULL) {
+ delete[] m_authRC;
+ }
+
+ m_authRC = new uint8_t[P25_AUTH_RAND_CHLNG_LENGTH_BYTES];
+ ::memcpy(m_authRC, data.m_authRC, P25_AUTH_RAND_CHLNG_LENGTH_BYTES);
+}
diff --git a/p25/lc/tsbk/MBT_ISP_AUTH_RESP_M.h b/p25/lc/tsbk/MBT_ISP_AUTH_RESP_M.h
new file mode 100644
index 00000000..c3047b68
--- /dev/null
+++ b/p25/lc/tsbk/MBT_ISP_AUTH_RESP_M.h
@@ -0,0 +1,79 @@
+/**
+* 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(__P25_LC_TSBK__MBT_ISP_AUTH_RESP_M_H__)
+#define __P25_LC_TSBK__MBT_ISP_AUTH_RESP_M_H__
+
+#include "Defines.h"
+#include "p25/lc/AMBT.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements AUTH RESP M - Authentication Response Mutual
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MBT_ISP_AUTH_RESP_M : public AMBT {
+ public:
+ /// Initializes a new instance of the MBT_ISP_AUTH_RESP_M class.
+ MBT_ISP_AUTH_RESP_M();
+ /// Finalizes a instance of the MBT_ISP_AUTH_RESP_M class.
+ ~MBT_ISP_AUTH_RESP_M();
+
+ /// Decode a alternate trunking signalling block.
+ virtual bool decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks);
+ /// Encode a alternate trunking signalling block.
+ virtual void encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData);
+
+ /** Authentication data */
+ /// Gets the authentication result.
+ void getAuthRes(uint8_t* res) const;
+
+ /// Sets the authentication random challenge.
+ void setAuthRC(const uint8_t* rc);
+ /// Gets the authentication random challenge.
+ void getAuthRC(uint8_t* rc) const;
+
+ public:
+ /// Flag indicating authentication is standalone.
+ __PROPERTY(bool, authStandalone, AuthStandalone);
+
+ private:
+ /** Authentication data */
+ uint8_t* m_authRes;
+ uint8_t* m_authRC;
+
+ __COPY(MBT_ISP_AUTH_RESP_M);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__MBT_ISP_AUTH_RESP_M_H__
diff --git a/p25/lc/tsbk/MBT_ISP_AUTH_SU_DMD.cpp b/p25/lc/tsbk/MBT_ISP_AUTH_SU_DMD.cpp
new file mode 100644
index 00000000..b62da96d
--- /dev/null
+++ b/p25/lc/tsbk/MBT_ISP_AUTH_SU_DMD.cpp
@@ -0,0 +1,88 @@
+/**
+* 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 "p25/lc/tsbk/MBT_ISP_AUTH_SU_DMD.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MBT_ISP_AUTH_SU_DMD class.
+///
+MBT_ISP_AUTH_SU_DMD::MBT_ISP_AUTH_SU_DMD() : AMBT()
+{
+ m_lco = TSBK_IOSP_GRP_AFF;
+}
+
+///
+/// Decode a alternate trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool MBT_ISP_AUTH_SU_DMD::decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks)
+{
+ assert(blocks != NULL);
+
+ uint8_t pduUserData[P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow()];
+ ::memset(pduUserData, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow());
+
+ bool ret = AMBT::decode(dataHeader, blocks, pduUserData);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = AMBT::tsbkValue(dataHeader, pduUserData);
+
+ m_netId = (uint32_t)((tsbkValue >> 44) & 0xFFFFFU); // Network ID
+ m_sysId = (uint32_t)((tsbkValue >> 32) & 0xFFFU); // System ID
+ m_srcId = dataHeader.getLLId(); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a alternate trunking signalling block.
+///
+///
+///
+void MBT_ISP_AUTH_SU_DMD::encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData)
+{
+ assert(pduUserData != NULL);
+
+ /* stub */
+
+ return;
+}
diff --git a/p25/lc/tsbk/MBT_ISP_AUTH_SU_DMD.h b/p25/lc/tsbk/MBT_ISP_AUTH_SU_DMD.h
new file mode 100644
index 00000000..53b3dafa
--- /dev/null
+++ b/p25/lc/tsbk/MBT_ISP_AUTH_SU_DMD.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__MBT_ISP_AUTH_SU_DMD_H__)
+#define __P25_LC_TSBK__MBT_ISP_AUTH_SU_DMD_H__
+
+#include "Defines.h"
+#include "p25/lc/AMBT.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements AUTH SU DMD - Authentication SU Demand
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MBT_ISP_AUTH_SU_DMD : public AMBT {
+ public:
+ /// Initializes a new instance of the MBT_ISP_AUTH_SU_DMD class.
+ MBT_ISP_AUTH_SU_DMD();
+
+ /// Decode a alternate trunking signalling block.
+ virtual bool decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks);
+ /// Encode a alternate trunking signalling block.
+ virtual void encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__MBT_ISP_AUTH_SU_DMD_H__
diff --git a/p25/lc/tsbk/MBT_ISP_CAN_SRV_REQ.cpp b/p25/lc/tsbk/MBT_ISP_CAN_SRV_REQ.cpp
new file mode 100644
index 00000000..7971655a
--- /dev/null
+++ b/p25/lc/tsbk/MBT_ISP_CAN_SRV_REQ.cpp
@@ -0,0 +1,93 @@
+/**
+* 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 "p25/lc/tsbk/MBT_ISP_CAN_SRV_REQ.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MBT_ISP_CAN_SRV_REQ class.
+///
+MBT_ISP_CAN_SRV_REQ::MBT_ISP_CAN_SRV_REQ() : AMBT()
+{
+ m_lco = TSBK_ISP_CAN_SRV_REQ;
+}
+
+///
+/// Decode a alternate trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool MBT_ISP_CAN_SRV_REQ::decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks)
+{
+ assert(blocks != NULL);
+
+ uint8_t pduUserData[P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow()];
+ ::memset(pduUserData, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow());
+
+ bool ret = AMBT::decode(dataHeader, blocks, pduUserData);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = AMBT::tsbkValue(dataHeader, pduUserData);
+
+ m_aivFlag = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Additional Info. Flag
+ m_service = (uint8_t)((tsbkValue >> 56) & 0x3FU); // Service Type
+ m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Reason
+ m_netId = (uint32_t)((tsbkValue >> 20) & 0xFFFFFU); // Network ID
+ m_sysId = (uint32_t)((tsbkValue >> 8) & 0xFFFU); // System ID
+ m_dstId = (uint32_t)((((tsbkValue) & 0xFFU) << 16) + // Target Radio Address
+ (pduUserData[6U] << 8) + (pduUserData[7U]));
+ m_srcId = dataHeader.getLLId(); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a alternate trunking signalling block.
+///
+///
+///
+void MBT_ISP_CAN_SRV_REQ::encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData)
+{
+ assert(pduUserData != NULL);
+
+ /* stub */
+
+ return;
+}
diff --git a/p25/lc/tsbk/MBT_ISP_CAN_SRV_REQ.h b/p25/lc/tsbk/MBT_ISP_CAN_SRV_REQ.h
new file mode 100644
index 00000000..07e500d5
--- /dev/null
+++ b/p25/lc/tsbk/MBT_ISP_CAN_SRV_REQ.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__MBT_ISP_CAN_SRV_REQ_H__)
+#define __P25_LC_TSBK__MBT_ISP_CAN_SRV_REQ_H__
+
+#include "Defines.h"
+#include "p25/lc/AMBT.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements CAN SRV REQ - Cancel Service Request
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MBT_ISP_CAN_SRV_REQ : public AMBT {
+ public:
+ /// Initializes a new instance of the MBT_ISP_CAN_SRV_REQ class.
+ MBT_ISP_CAN_SRV_REQ();
+
+ /// Decode a alternate trunking signalling block.
+ virtual bool decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks);
+ /// Encode a alternate trunking signalling block.
+ virtual void encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__MBT_ISP_CAN_SRV_REQ_H__
diff --git a/p25/lc/tsbk/MBT_OSP_ADJ_STS_BCAST.cpp b/p25/lc/tsbk/MBT_OSP_ADJ_STS_BCAST.cpp
new file mode 100644
index 00000000..c9a14213
--- /dev/null
+++ b/p25/lc/tsbk/MBT_OSP_ADJ_STS_BCAST.cpp
@@ -0,0 +1,133 @@
+/**
+* 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 "p25/lc/tsbk/MBT_OSP_ADJ_STS_BCAST.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MBT_OSP_ADJ_STS_BCAST class.
+///
+MBT_OSP_ADJ_STS_BCAST::MBT_OSP_ADJ_STS_BCAST() : AMBT(),
+ m_adjCFVA(P25_CFVA_FAILURE),
+ m_adjRfssId(0U),
+ m_adjSiteId(0U),
+ m_adjChannelId(0U),
+ m_adjChannelNo(0U),
+ m_adjServiceClass(P25_SVC_CLS_INVALID)
+{
+ m_lco = TSBK_OSP_ADJ_STS_BCAST;
+}
+
+///
+/// Decode a alternate trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool MBT_OSP_ADJ_STS_BCAST::decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks)
+{
+ assert(blocks != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a alternate trunking signalling block.
+///
+///
+///
+void MBT_OSP_ADJ_STS_BCAST::encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData)
+{
+ assert(pduUserData != NULL);
+
+ if ((m_adjRfssId != 0U) && (m_adjSiteId != 0U) && (m_adjChannelNo != 0U)) {
+ if (m_adjSysId == 0U) {
+ m_adjSysId = m_siteData.sysId();
+ }
+
+ // pack LRA, CFVA and system ID into LLID
+ uint32_t llId = m_siteData.lra(); // Location Registration Area
+ llId = (llId << 8) + m_adjCFVA; // CFVA
+ llId = (llId << 4) + m_siteData.siteId(); // System ID
+ dataHeader.setLLId(llId);
+
+ dataHeader.setAMBTField8(m_adjRfssId); // RF Sub-System ID
+ dataHeader.setAMBTField9(m_adjSiteId); // Site ID
+
+ /** Block 1 */
+ pduUserData[0U] = ((m_adjChannelId & 0x0FU) << 4) + // Transmit Channel ID & Channel Number MSB
+ ((m_adjChannelNo >> 8) & 0xFFU);
+ pduUserData[1U] = (m_adjChannelNo >> 0) & 0xFFU; // Transmit Channel Number LSB
+ pduUserData[2U] = ((m_adjChannelId & 0x0FU) << 4) + // Receive Channel ID & Channel Number MSB
+ ((m_adjChannelNo >> 8) & 0xFFU);
+ pduUserData[3U] = (m_adjChannelNo >> 0) & 0xFFU; // Receive Channel Number LSB
+ pduUserData[4U] = m_adjServiceClass; // System Service Class
+ pduUserData[5U] = (m_siteData.netId() >> 12) & 0xFFU; // Network ID (b19-12)
+ pduUserData[6U] = (m_siteData.netId() >> 4) & 0xFFU; // Network ID (b11-b4)
+ pduUserData[7U] = (m_siteData.netId() & 0x0FU) << 4; // Network ID (b3-b0)
+ }
+ else {
+ LogError(LOG_P25, "TSBK::encodeMBT(), invalid values for OSP_ADJ_STS_BCAST, adjRfssId = $%02X, adjSiteId = $%02X, adjChannelId = %u, adjChannelNo = $%02X, adjSvcClass = $%02X",
+ m_adjRfssId, m_adjSiteId, m_adjChannelId, m_adjChannelNo, m_adjServiceClass);
+ return; // blatently ignore creating this TSBK
+ }
+
+ AMBT::encode(dataHeader, pduUserData);
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void MBT_OSP_ADJ_STS_BCAST::copy(const MBT_OSP_ADJ_STS_BCAST& data)
+{
+ TSBK::copy(data);
+
+ m_adjCFVA = data.m_adjCFVA;
+ m_adjRfssId = data.m_adjRfssId;
+ m_adjSiteId = data.m_adjSiteId;
+ m_adjChannelId = data.m_adjChannelId;
+ m_adjChannelNo = data.m_adjChannelNo;
+ m_adjServiceClass = data.m_adjServiceClass;
+}
diff --git a/p25/lc/tsbk/MBT_OSP_ADJ_STS_BCAST.h b/p25/lc/tsbk/MBT_OSP_ADJ_STS_BCAST.h
new file mode 100644
index 00000000..6949a359
--- /dev/null
+++ b/p25/lc/tsbk/MBT_OSP_ADJ_STS_BCAST.h
@@ -0,0 +1,76 @@
+/**
+* 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(__P25_LC_TSBK__MBT_OSP_ADJ_STS_BCAST_H__)
+#define __P25_LC_TSBK__MBT_OSP_ADJ_STS_BCAST_H__
+
+#include "Defines.h"
+#include "p25/lc/AMBT.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements ADJ STS BCAST - Adjacent Site Status Broadcast
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MBT_OSP_ADJ_STS_BCAST : public AMBT {
+ public:
+ /// Initializes a new instance of the MBT_OSP_ADJ_STS_BCAST class.
+ MBT_OSP_ADJ_STS_BCAST();
+
+ /// Decode a alternate trunking signalling block.
+ virtual bool decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks);
+ /// Encode a alternate trunking signalling block.
+ virtual void encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData);
+
+ public:
+ /** Adjacent Site Data */
+ /// Adjacent site CFVA flags.
+ __PROPERTY(uint8_t, adjCFVA, AdjSiteCFVA);
+ /// Adjacent site system ID.
+ __PROPERTY(uint32_t, adjSysId, AdjSiteSysId);
+ /// Adjacent site RFSS ID.
+ __PROPERTY(uint8_t, adjRfssId, AdjSiteRFSSId);
+ /// Adjacent site ID.
+ __PROPERTY(uint8_t, adjSiteId, AdjSiteId);
+ /// Adjacent site channel ID.
+ __PROPERTY(uint8_t, adjChannelId, AdjSiteChnId);
+ /// Adjacent site channel number.
+ __PROPERTY(uint32_t, adjChannelNo, AdjSiteChnNo);
+ /// Adjacent site service class.
+ __PROPERTY(uint8_t, adjServiceClass, AdjSiteSvcClass);
+
+ __COPY(MBT_OSP_ADJ_STS_BCAST);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__MBT_OSP_ADJ_STS_BCAST_H__
diff --git a/p25/lc/tsbk/MBT_OSP_AUTH_DMD.cpp b/p25/lc/tsbk/MBT_OSP_AUTH_DMD.cpp
new file mode 100644
index 00000000..77d55eb4
--- /dev/null
+++ b/p25/lc/tsbk/MBT_OSP_AUTH_DMD.cpp
@@ -0,0 +1,188 @@
+/**
+* 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 "p25/lc/tsbk/MBT_OSP_AUTH_DMD.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MBT_OSP_AUTH_DMD class.
+///
+MBT_OSP_AUTH_DMD::MBT_OSP_AUTH_DMD() : AMBT()
+{
+ m_lco = TSBK_OSP_AUTH_DMD;
+
+ m_authRS = new uint8_t[P25_AUTH_RAND_SEED_LENGTH_BYTES];
+ ::memset(m_authRS, 0x00U, P25_AUTH_RAND_SEED_LENGTH_BYTES);
+ m_authRC = new uint8_t[P25_AUTH_RAND_CHLNG_LENGTH_BYTES];
+ ::memset(m_authRC, 0x00U, P25_AUTH_RAND_CHLNG_LENGTH_BYTES);
+}
+
+///
+/// Finalizes a instance of MBT_OSP_AUTH_DMD class.
+///
+MBT_OSP_AUTH_DMD::~MBT_OSP_AUTH_DMD()
+{
+ if (m_authRS != NULL) {
+ delete[] m_authRS;
+ m_authRS = NULL;
+ }
+
+ if (m_authRC != NULL) {
+ delete[] m_authRC;
+ m_authRC = NULL;
+ }
+}
+
+///
+/// Decode a alternate trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool MBT_OSP_AUTH_DMD::decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks)
+{
+ assert(blocks != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a alternate trunking signalling block.
+///
+///
+///
+void MBT_OSP_AUTH_DMD::encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData)
+{
+ assert(pduUserData != NULL);
+
+ dataHeader.setBlocksToFollow(2U);
+
+ dataHeader.setAMBTField8((m_netId >> 12) & 0xFFU); // Network ID (b19-12)
+ dataHeader.setAMBTField9((m_netId >> 4) & 0xFFU); // Network ID (b11-b4)
+
+ /** Block 1 */
+ pduUserData[0U] = ((m_netId & 0x0FU) << 4) + ((m_sysId >> 8) & 0xFFU); // Network ID (b3-b0) + System ID (b11-b8)
+ pduUserData[1U] = (m_sysId & 0xFFU); // System ID (b7-b0)
+
+ __SET_UINT16(m_dstId, pduUserData, 2U); // Target Radio Address
+
+ pduUserData[5U] = m_authRS[9U]; // Random Salt b9
+ pduUserData[6U] = m_authRS[8U]; // Random Salt b8
+ pduUserData[7U] = m_authRS[7U]; // Random Salt b7
+ pduUserData[8U] = m_authRS[6U]; // Random Salt b6
+ pduUserData[9U] = m_authRS[5U]; // Random Salt b5
+ pduUserData[10U] = m_authRS[4U]; // Random Salt b4
+ pduUserData[11U] = m_authRS[3U]; // Random Salt b3
+
+ /** Block 2 */
+ pduUserData[12U] = m_authRS[2U]; // Random Salt b2
+ pduUserData[13U] = m_authRS[1U]; // Random Salt b1
+ pduUserData[14U] = m_authRS[0U]; // Random Salt b0
+ pduUserData[15U] = m_authRC[4U]; // Random Challenge b4
+ pduUserData[16U] = m_authRC[3U]; // Random Challenge b3
+ pduUserData[17U] = m_authRC[2U]; // Random Challenge b2
+ pduUserData[18U] = m_authRC[1U]; // Random Challenge b1
+ pduUserData[19U] = m_authRC[0U]; // Random Challenge b0
+
+ AMBT::encode(dataHeader, pduUserData);
+}
+
+/// Sets the authentication random seed.
+///
+void MBT_OSP_AUTH_DMD::setAuthRS(const uint8_t* rs)
+{
+ assert(rs != NULL);
+
+ ::memcpy(m_authRS, rs, P25_AUTH_RAND_SEED_LENGTH_BYTES);
+}
+
+/// Gets the authentication random seed.
+///
+void MBT_OSP_AUTH_DMD::getAuthRS(uint8_t* rs) const
+{
+ assert(rs != NULL);
+
+ ::memcpy(rs, m_authRS, P25_AUTH_RAND_SEED_LENGTH_BYTES);
+}
+
+/// Sets the authentication random challenge.
+///
+void MBT_OSP_AUTH_DMD::setAuthRC(const uint8_t* rc)
+{
+ assert(rc != NULL);
+
+ ::memcpy(m_authRC, rc, P25_AUTH_RAND_CHLNG_LENGTH_BYTES);
+}
+
+/// Gets the authentication random challenge.
+///
+void MBT_OSP_AUTH_DMD::getAuthRC(uint8_t* rc) const
+{
+ assert(rc != NULL);
+
+ ::memcpy(rc, m_authRC, P25_AUTH_RAND_CHLNG_LENGTH_BYTES);
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void MBT_OSP_AUTH_DMD::copy(const MBT_OSP_AUTH_DMD& data)
+{
+ TSBK::copy(data);
+
+ if (m_authRS != NULL) {
+ delete[] m_authRS;
+ }
+
+ m_authRS = new uint8_t[P25_AUTH_RAND_SEED_LENGTH_BYTES];
+ ::memcpy(m_authRS, data.m_authRS, P25_AUTH_RAND_SEED_LENGTH_BYTES);
+
+ if (m_authRC != NULL) {
+ delete[] m_authRC;
+ }
+
+ m_authRC = new uint8_t[P25_AUTH_RAND_CHLNG_LENGTH_BYTES];
+ ::memcpy(m_authRC, data.m_authRC, P25_AUTH_RAND_CHLNG_LENGTH_BYTES);
+}
diff --git a/p25/lc/tsbk/MBT_OSP_AUTH_DMD.h b/p25/lc/tsbk/MBT_OSP_AUTH_DMD.h
new file mode 100644
index 00000000..88917ecd
--- /dev/null
+++ b/p25/lc/tsbk/MBT_OSP_AUTH_DMD.h
@@ -0,0 +1,76 @@
+/**
+* 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(__P25_LC_TSBK__MBT_OSP_AUTH_DMD_H__)
+#define __P25_LC_TSBK__MBT_OSP_AUTH_DMD_H__
+
+#include "Defines.h"
+#include "p25/lc/AMBT.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements AUTH DMD - Authentication Demand
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MBT_OSP_AUTH_DMD : public AMBT {
+ public:
+ /// Initializes a new instance of the MBT_OSP_AUTH_DMD class.
+ MBT_OSP_AUTH_DMD();
+ /// Finalizes a instance of the MBT_OSP_AUTH_DMD class.
+ ~MBT_OSP_AUTH_DMD();
+
+ /// Decode a alternate trunking signalling block.
+ virtual bool decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks);
+ /// Encode a alternate trunking signalling block.
+ virtual void encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData);
+
+ /// Sets the authentication random seed.
+ void setAuthRS(const uint8_t* rs);
+ /// Gets the authentication random seed.
+ void getAuthRS(uint8_t* rs) const;
+
+ /// Sets the authentication random challenge.
+ void setAuthRC(const uint8_t* rc);
+ /// Gets the authentication random challenge.
+ void getAuthRC(uint8_t* rc) const;
+
+ private:
+ /** Authentication data */
+ uint8_t* m_authRS;
+ uint8_t* m_authRC;
+
+ __COPY(MBT_OSP_AUTH_DMD);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__MBT_OSP_AUTH_DMD_H__
diff --git a/p25/lc/tsbk/MBT_OSP_NET_STS_BCAST.cpp b/p25/lc/tsbk/MBT_OSP_NET_STS_BCAST.cpp
new file mode 100644
index 00000000..22cdceac
--- /dev/null
+++ b/p25/lc/tsbk/MBT_OSP_NET_STS_BCAST.cpp
@@ -0,0 +1,92 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "Defines.h"
+#include "p25/lc/tsbk/MBT_OSP_NET_STS_BCAST.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MBT_OSP_NET_STS_BCAST class.
+///
+MBT_OSP_NET_STS_BCAST::MBT_OSP_NET_STS_BCAST() : AMBT()
+{
+ m_lco = TSBK_OSP_NET_STS_BCAST;
+}
+
+///
+/// Decode a alternate trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool MBT_OSP_NET_STS_BCAST::decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks)
+{
+ assert(blocks != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a alternate trunking signalling block.
+///
+///
+///
+void MBT_OSP_NET_STS_BCAST::encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData)
+{
+ assert(pduUserData != NULL);
+
+ // pack LRA and system ID into LLID
+ uint32_t llId = m_siteData.lra(); // Location Registration Area
+ llId = (llId << 12) + m_siteData.siteId(); // System ID
+ dataHeader.setLLId(llId);
+
+ /** Block 1 */
+ pduUserData[0U] = (m_siteData.netId() >> 12) & 0xFFU; // Network ID (b19-12)
+ pduUserData[1U] = (m_siteData.netId() >> 4) & 0xFFU; // Network ID (b11-b4)
+ pduUserData[2U] = (m_siteData.netId() & 0x0FU) << 4; // Network ID (b3-b0)
+ pduUserData[3U] = ((m_siteData.channelId() & 0x0FU) << 4) + // Transmit Channel ID & Channel Number MSB
+ ((m_siteData.channelNo() >> 8) & 0xFFU);
+ pduUserData[4U] = (m_siteData.channelNo() >> 0) & 0xFFU; // Transmit Channel Number LSB
+ pduUserData[5U] = ((m_siteData.channelId() & 0x0FU) << 4) + // Receive Channel ID & Channel Number MSB
+ ((m_siteData.channelNo() >> 8) & 0xFFU);
+ pduUserData[6U] = (m_siteData.channelNo() >> 0) & 0xFFU; // Receive Channel Number LSB
+ pduUserData[7U] = m_siteData.serviceClass(); // System Service Class
+
+ AMBT::encode(dataHeader, pduUserData);
+}
diff --git a/p25/lc/tsbk/MBT_OSP_NET_STS_BCAST.h b/p25/lc/tsbk/MBT_OSP_NET_STS_BCAST.h
new file mode 100644
index 00000000..a296ec22
--- /dev/null
+++ b/p25/lc/tsbk/MBT_OSP_NET_STS_BCAST.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__MBT_OSP_NET_STS_BCAST_H__)
+#define __P25_LC_TSBK__MBT_OSP_NET_STS_BCAST_H__
+
+#include "Defines.h"
+#include "p25/lc/AMBT.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements NET STS BCAST - Network Status Broadcast
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MBT_OSP_NET_STS_BCAST : public AMBT {
+ public:
+ /// Initializes a new instance of the MBT_OSP_NET_STS_BCAST class.
+ MBT_OSP_NET_STS_BCAST();
+
+ /// Decode a alternate trunking signalling block.
+ virtual bool decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks);
+ /// Encode a alternate trunking signalling block.
+ virtual void encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__MBT_OSP_NET_STS_BCAST_H__
diff --git a/p25/lc/tsbk/MBT_OSP_RFSS_STS_BCAST.cpp b/p25/lc/tsbk/MBT_OSP_RFSS_STS_BCAST.cpp
new file mode 100644
index 00000000..0122882d
--- /dev/null
+++ b/p25/lc/tsbk/MBT_OSP_RFSS_STS_BCAST.cpp
@@ -0,0 +1,94 @@
+/**
+* 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 "p25/lc/tsbk/MBT_OSP_RFSS_STS_BCAST.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the MBT_OSP_RFSS_STS_BCAST class.
+///
+MBT_OSP_RFSS_STS_BCAST::MBT_OSP_RFSS_STS_BCAST() : AMBT()
+{
+ m_lco = TSBK_OSP_RFSS_STS_BCAST;
+}
+
+///
+/// Decode a alternate trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool MBT_OSP_RFSS_STS_BCAST::decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks)
+{
+ assert(blocks != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a alternate trunking signalling block.
+///
+///
+///
+void MBT_OSP_RFSS_STS_BCAST::encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData)
+{
+ assert(pduUserData != NULL);
+
+ // pack LRA and system ID into LLID
+ uint32_t llId = m_siteData.lra(); // Location Registration Area
+ llId = (llId << 12) + m_siteData.siteId(); // System ID
+ if (m_siteData.netActive()) {
+ llId |= 0x1000U; // Network Active Flag
+ }
+ dataHeader.setLLId(llId);
+
+ /** Block 1 */
+ pduUserData[0U] = (m_siteData.rfssId()) & 0xFFU; // RF Sub-System ID
+ pduUserData[1U] = (m_siteData.siteId()) & 0xFFU; // Site ID
+ pduUserData[2U] = ((m_siteData.channelId() & 0x0FU) << 4) + // Transmit Channel ID & Channel Number MSB
+ ((m_siteData.channelNo() >> 8) & 0xFFU);
+ pduUserData[3U] = (m_siteData.channelNo() >> 0) & 0xFFU; // Transmit Channel Number LSB
+ pduUserData[4U] = ((m_siteData.channelId() & 0x0FU) << 4) + // Receive Channel ID & Channel Number MSB
+ ((m_siteData.channelNo() >> 8) & 0xFFU);
+ pduUserData[5U] = (m_siteData.channelNo() >> 0) & 0xFFU; // Receive Channel Number LSB
+ pduUserData[6U] = m_siteData.serviceClass(); // System Service Class
+
+ AMBT::encode(dataHeader, pduUserData);
+}
diff --git a/p25/lc/tsbk/MBT_OSP_RFSS_STS_BCAST.h b/p25/lc/tsbk/MBT_OSP_RFSS_STS_BCAST.h
new file mode 100644
index 00000000..72880f03
--- /dev/null
+++ b/p25/lc/tsbk/MBT_OSP_RFSS_STS_BCAST.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__MBT_OSP_RFSS_STS_BCAST_H__)
+#define __P25_LC_TSBK__MBT_OSP_RFSS_STS_BCAST_H__
+
+#include "Defines.h"
+#include "p25/lc/AMBT.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements RFSS STS BCAST - RFSS Status Broadcast
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API MBT_OSP_RFSS_STS_BCAST : public AMBT {
+ public:
+ /// Initializes a new instance of the MBT_OSP_RFSS_STS_BCAST class.
+ MBT_OSP_RFSS_STS_BCAST();
+
+ /// Decode a alternate trunking signalling block.
+ virtual bool decodeMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks);
+ /// Encode a alternate trunking signalling block.
+ virtual void encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__MBT_OSP_RFSS_STS_BCAST_H__
diff --git a/p25/lc/tsbk/OSP_ADJ_STS_BCAST.cpp b/p25/lc/tsbk/OSP_ADJ_STS_BCAST.cpp
new file mode 100644
index 00000000..bdbbf17d
--- /dev/null
+++ b/p25/lc/tsbk/OSP_ADJ_STS_BCAST.cpp
@@ -0,0 +1,130 @@
+/**
+* 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 "p25/lc/tsbk/OSP_ADJ_STS_BCAST.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_ADJ_STS_BCAST class.
+///
+OSP_ADJ_STS_BCAST::OSP_ADJ_STS_BCAST() : TSBK(),
+ m_adjCFVA(P25_CFVA_FAILURE),
+ m_adjRfssId(0U),
+ m_adjSiteId(0U),
+ m_adjChannelId(0U),
+ m_adjChannelNo(0U),
+ m_adjServiceClass(P25_SVC_CLS_INVALID)
+{
+ m_lco = TSBK_OSP_ADJ_STS_BCAST;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_ADJ_STS_BCAST::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ 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
+ m_adjChannelId = (uint8_t)((tsbkValue >> 20) & 0xFU); // Site Channel ID
+ m_adjChannelNo = (uint32_t)((tsbkValue >> 8) & 0xFFFU); // Site Channel Number
+ m_adjServiceClass = (uint8_t)(tsbkValue & 0xFFU); // Site Service Class
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_ADJ_STS_BCAST::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = m_siteData.lra(); // Location Registration Area
+ tsbkValue = (tsbkValue << 4) +
+ (m_siteData.netActive()) ? P25_CFVA_NETWORK : 0U; // CFVA
+ tsbkValue = (tsbkValue << 12) + m_siteData.sysId(); // System ID
+ tsbkValue = (tsbkValue << 8) + m_siteData.rfssId(); // RF Sub-System ID
+ tsbkValue = (tsbkValue << 8) + m_siteData.siteId(); // Site ID
+ tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID
+ tsbkValue = (tsbkValue << 12) + m_siteData.channelNo(); // Channel Number
+ tsbkValue = (tsbkValue << 8) + m_siteData.serviceClass(); // System Service Class
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void OSP_ADJ_STS_BCAST::copy(const OSP_ADJ_STS_BCAST& data)
+{
+ TSBK::copy(data);
+
+ m_adjCFVA = data.m_adjCFVA;
+ m_adjRfssId = data.m_adjRfssId;
+ m_adjSiteId = data.m_adjSiteId;
+ m_adjChannelId = data.m_adjChannelId;
+ m_adjChannelNo = data.m_adjChannelNo;
+ m_adjServiceClass = data.m_adjServiceClass;
+}
diff --git a/p25/lc/tsbk/OSP_ADJ_STS_BCAST.h b/p25/lc/tsbk/OSP_ADJ_STS_BCAST.h
new file mode 100644
index 00000000..beb6cd13
--- /dev/null
+++ b/p25/lc/tsbk/OSP_ADJ_STS_BCAST.h
@@ -0,0 +1,76 @@
+/**
+* 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(__P25_LC_TSBK__OSP_ADJ_STS_BCAST_H__)
+#define __P25_LC_TSBK__OSP_ADJ_STS_BCAST_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements ADJ STS BCAST - Adjacent Site Status Broadcast.
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_ADJ_STS_BCAST : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_ADJ_STS_BCAST class.
+ OSP_ADJ_STS_BCAST();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /** Adjacent Site Data */
+ /// Adjacent site CFVA flags.
+ __PROPERTY(uint8_t, adjCFVA, AdjSiteCFVA);
+ /// Adjacent site system ID.
+ __PROPERTY(uint32_t, adjSysId, AdjSiteSysId);
+ /// Adjacent site RFSS ID.
+ __PROPERTY(uint8_t, adjRfssId, AdjSiteRFSSId);
+ /// Adjacent site ID.
+ __PROPERTY(uint8_t, adjSiteId, AdjSiteId);
+ /// Adjacent site channel ID.
+ __PROPERTY(uint8_t, adjChannelId, AdjSiteChnId);
+ /// Adjacent site channel number.
+ __PROPERTY(uint32_t, adjChannelNo, AdjSiteChnNo);
+ /// Adjacent site service class.
+ __PROPERTY(uint8_t, adjServiceClass, AdjSiteSvcClass);
+
+ __COPY(OSP_ADJ_STS_BCAST);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_ADJ_STS_BCAST_H__
diff --git a/p25/lc/tsbk/OSP_AUTH_FNE_RESP.cpp b/p25/lc/tsbk/OSP_AUTH_FNE_RESP.cpp
new file mode 100644
index 00000000..7d1f1346
--- /dev/null
+++ b/p25/lc/tsbk/OSP_AUTH_FNE_RESP.cpp
@@ -0,0 +1,135 @@
+/**
+* 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 "p25/lc/tsbk/OSP_AUTH_FNE_RESP.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_AUTH_FNE_RESP class.
+///
+OSP_AUTH_FNE_RESP::OSP_AUTH_FNE_RESP() : TSBK(),
+ m_authRes(NULL)
+{
+ m_lco = TSBK_OSP_AUTH_FNE_RESP;
+
+ m_authRes = new uint8_t[P25_AUTH_RES_LENGTH_BYTES];
+ ::memset(m_authRes, 0x00U, P25_AUTH_RES_LENGTH_BYTES);
+}
+
+///
+/// Finalizes a instance of OSP_AUTH_FNE_RESP class.
+///
+OSP_AUTH_FNE_RESP::~OSP_AUTH_FNE_RESP()
+{
+ if (m_authRes != NULL) {
+ delete[] m_authRes;
+ m_authRes = NULL;
+ }
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_AUTH_FNE_RESP::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_AUTH_FNE_RESP::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = (tsbkValue << 8) + m_authRes[3U]; // Result b3
+ tsbkValue = (tsbkValue << 8) + m_authRes[2U]; // Result b2
+ tsbkValue = (tsbkValue << 8) + m_authRes[1U]; // Result b1
+ tsbkValue = (tsbkValue << 8) + m_authRes[0U]; // Result b0
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
+
+/// Sets the authentication result.
+///
+void OSP_AUTH_FNE_RESP::setAuthRes(const uint8_t* res)
+{
+ assert(res != NULL);
+
+ if (m_authRes != NULL) {
+ delete[] m_authRes;
+ }
+
+ m_authRes = new uint8_t[P25_AUTH_RES_LENGTH_BYTES];
+ ::memcpy(m_authRes, res, P25_AUTH_RES_LENGTH_BYTES);
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void OSP_AUTH_FNE_RESP::copy(const OSP_AUTH_FNE_RESP& data)
+{
+ TSBK::copy(data);
+
+ if (m_authRes != NULL) {
+ delete[] m_authRes;
+ }
+
+ m_authRes = new uint8_t[P25_AUTH_RES_LENGTH_BYTES];
+ ::memcpy(m_authRes, data.m_authRes, P25_AUTH_RES_LENGTH_BYTES);
+}
diff --git a/p25/lc/tsbk/OSP_AUTH_FNE_RESP.h b/p25/lc/tsbk/OSP_AUTH_FNE_RESP.h
new file mode 100644
index 00000000..b6683ef5
--- /dev/null
+++ b/p25/lc/tsbk/OSP_AUTH_FNE_RESP.h
@@ -0,0 +1,69 @@
+/**
+* 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(__P25_LC_TSBK__OSP_AUTH_FNE_RESP_H__)
+#define __P25_LC_TSBK__OSP_AUTH_FNE_RESP_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements AUTH FNE RESP - Authentication FNE Response
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_AUTH_FNE_RESP : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_AUTH_FNE_RESP class.
+ OSP_AUTH_FNE_RESP();
+ /// Finalizes a instance of the OSP_AUTH_FNE_RESP class.
+ ~OSP_AUTH_FNE_RESP();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ /** Authentication data */
+ /// Sets the authentication result.
+ void setAuthRes(const uint8_t* res);
+
+ private:
+ /** Authentication data */
+ uint8_t* m_authRes;
+
+ __COPY(OSP_AUTH_FNE_RESP);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_AUTH_FNE_RESP_H__
diff --git a/p25/lc/tsbk/OSP_DENY_RSP.cpp b/p25/lc/tsbk/OSP_DENY_RSP.cpp
new file mode 100644
index 00000000..25ac86e4
--- /dev/null
+++ b/p25/lc/tsbk/OSP_DENY_RSP.cpp
@@ -0,0 +1,114 @@
+/**
+* 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 "p25/lc/tsbk/OSP_DENY_RSP.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_DENY_RSP class.
+///
+OSP_DENY_RSP::OSP_DENY_RSP() : TSBK()
+{
+ m_lco = TSBK_OSP_DENY_RSP;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_DENY_RSP::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_aivFlag = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Additional Info. Flag
+ m_service = (uint8_t)((tsbkValue >> 56) & 0x3FU); // Service Type
+ m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Reason
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_DENY_RSP::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ if (m_response == 0U) {
+ LogError(LOG_P25, "TSBK::encode(), invalid values for TSBK_OSP_DENY_RSP, reason = %u", m_response);
+ return; // blatently ignore creating this TSBK
+ }
+
+ tsbkValue = (m_aivFlag) ? 0x80U : 0x00U; // Additional Info Flag
+ tsbkValue = (tsbkValue << 6) + m_service; // Service Type
+ tsbkValue = (tsbkValue << 8) + m_response; // Deny/Queue Reason
+
+ if (m_group) {
+ // group deny/queue
+ tsbkValue = (tsbkValue << 8) + 0U; // Call Options
+ tsbkValue = (tsbkValue << 16) + m_dstId; // Talkgroup Address
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+ }
+ else {
+ // private/individual deny/queue
+ tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+ }
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/OSP_DENY_RSP.h b/p25/lc/tsbk/OSP_DENY_RSP.h
new file mode 100644
index 00000000..6a44bbb0
--- /dev/null
+++ b/p25/lc/tsbk/OSP_DENY_RSP.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_DENY_RSP_H__)
+#define __P25_LC_TSBK__OSP_DENY_RSP_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements DENY RSP - Queued Response
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_DENY_RSP : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_DENY_RSP class.
+ OSP_DENY_RSP();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_DENY_RSP_H__
diff --git a/p25/lc/tsbk/OSP_DVM_GIT_HASH.cpp b/p25/lc/tsbk/OSP_DVM_GIT_HASH.cpp
new file mode 100644
index 00000000..3afa4c06
--- /dev/null
+++ b/p25/lc/tsbk/OSP_DVM_GIT_HASH.cpp
@@ -0,0 +1,90 @@
+/**
+* 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 "p25/lc/tsbk/OSP_DVM_GIT_HASH.h"
+#include "HostMain.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_DVM_GIT_HASH class.
+///
+OSP_DVM_GIT_HASH::OSP_DVM_GIT_HASH() : TSBK()
+{
+ m_lco = TSBK_OSP_DVM_GIT_HASH;
+ m_mfId = P25_MFG_DVM;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_DVM_GIT_HASH::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_DVM_GIT_HASH::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = g_gitHashBytes[0]; // ...
+ tsbkValue = (tsbkValue << 8) + (g_gitHashBytes[1U]); // ...
+ tsbkValue = (tsbkValue << 8) + (g_gitHashBytes[2U]); // ...
+ tsbkValue = (tsbkValue << 8) + (g_gitHashBytes[3U]); // ...
+ tsbkValue = (tsbkValue << 16) + 0U;
+ tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID
+ tsbkValue = (tsbkValue << 12) + m_siteData.channelNo(); // Channel Number
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/OSP_DVM_GIT_HASH.h b/p25/lc/tsbk/OSP_DVM_GIT_HASH.h
new file mode 100644
index 00000000..57a969ff
--- /dev/null
+++ b/p25/lc/tsbk/OSP_DVM_GIT_HASH.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_DVM_GIT_HASH_H__)
+#define __P25_LC_TSBK__OSP_DVM_GIT_HASH_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements DVM GIT Hash Identification
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_DVM_GIT_HASH : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_DVM_GIT_HASH class.
+ OSP_DVM_GIT_HASH();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_DVM_GIT_HASH_H__
diff --git a/p25/lc/tsbk/OSP_DVM_LC_CALL_TERM.cpp b/p25/lc/tsbk/OSP_DVM_LC_CALL_TERM.cpp
new file mode 100644
index 00000000..8c6dbaa6
--- /dev/null
+++ b/p25/lc/tsbk/OSP_DVM_LC_CALL_TERM.cpp
@@ -0,0 +1,98 @@
+/**
+* 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 "p25/lc/tsbk/OSP_DVM_LC_CALL_TERM.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_DVM_LC_CALL_TERM class.
+///
+OSP_DVM_LC_CALL_TERM::OSP_DVM_LC_CALL_TERM() : TSBK()
+{
+ m_lco = LC_CALL_TERM;
+ m_mfId = P25_MFG_DVM;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_DVM_LC_CALL_TERM::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_grpVchId = ((tsbkValue >> 52) & 0x0FU); // Channel ID
+ m_grpVchNo = ((tsbkValue >> 40) & 0xFFFU); // Channel Number
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFU); // Target Radio Address
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_DVM_LC_CALL_TERM::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID
+ tsbkValue = (tsbkValue << 12) + m_grpVchNo; // Channel Number
+ tsbkValue = (tsbkValue << 16) + m_dstId; // Talkgroup Address
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/OSP_DVM_LC_CALL_TERM.h b/p25/lc/tsbk/OSP_DVM_LC_CALL_TERM.h
new file mode 100644
index 00000000..5c3ce70c
--- /dev/null
+++ b/p25/lc/tsbk/OSP_DVM_LC_CALL_TERM.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_LC_CALL_TERM_H__)
+#define __P25_LC_TSBK__OSP_LC_CALL_TERM_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements CALL TERM - Call Termination or Cancellation
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_DVM_LC_CALL_TERM : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_DVM_LC_CALL_TERM class.
+ OSP_DVM_LC_CALL_TERM();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_LC_CALL_TERM_H__
diff --git a/p25/lc/tsbk/OSP_GRP_AFF_Q.cpp b/p25/lc/tsbk/OSP_GRP_AFF_Q.cpp
new file mode 100644
index 00000000..21dd8771
--- /dev/null
+++ b/p25/lc/tsbk/OSP_GRP_AFF_Q.cpp
@@ -0,0 +1,83 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "Defines.h"
+#include "p25/lc/tsbk/OSP_GRP_AFF_Q.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_GRP_AFF_Q class.
+///
+OSP_GRP_AFF_Q::OSP_GRP_AFF_Q() : TSBK()
+{
+ m_lco = TSBK_OSP_GRP_AFF_Q;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_GRP_AFF_Q::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_GRP_AFF_Q::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/OSP_GRP_AFF_Q.h b/p25/lc/tsbk/OSP_GRP_AFF_Q.h
new file mode 100644
index 00000000..15be99a4
--- /dev/null
+++ b/p25/lc/tsbk/OSP_GRP_AFF_Q.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_GRP_AFF_Q_H__)
+#define __P25_LC_TSBK__OSP_GRP_AFF_Q_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements GRP AFF Q - Group Affiliation Query
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_GRP_AFF_Q : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_GRP_AFF_Q class.
+ OSP_GRP_AFF_Q();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_GRP_AFF_Q_H__
diff --git a/p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.cpp b/p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.cpp
new file mode 100644
index 00000000..186200b7
--- /dev/null
+++ b/p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.cpp
@@ -0,0 +1,85 @@
+/**
+* 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 "p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_GRP_VCH_GRANT_UPD class.
+///
+OSP_GRP_VCH_GRANT_UPD::OSP_GRP_VCH_GRANT_UPD() : TSBK()
+{
+ m_lco = TSBK_OSP_GRP_VCH_GRANT_UPD;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_GRP_VCH_GRANT_UPD::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_GRP_VCH_GRANT_UPD::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = m_siteData.channelId(); // Channel ID
+ tsbkValue = (tsbkValue << 12) + m_grpVchNo; // Channel Number
+ tsbkValue = (tsbkValue << 16) + m_dstId; // Talkgroup Address
+ tsbkValue = (tsbkValue << 32) + 0;
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.h b/p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.h
new file mode 100644
index 00000000..9cc03211
--- /dev/null
+++ b/p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_GRP_VCH_GRANT_UPD_H__)
+#define __P25_LC_TSBK__OSP_GRP_VCH_GRANT_UPD_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements GRP VCH GRANT UPD - Group Voice Channel Grant Update.
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_GRP_VCH_GRANT_UPD : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_GRP_VCH_GRANT_UPD class.
+ OSP_GRP_VCH_GRANT_UPD();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_GRP_VCH_GRANT_UPD_H__
diff --git a/p25/lc/tsbk/OSP_IDEN_UP.cpp b/p25/lc/tsbk/OSP_IDEN_UP.cpp
new file mode 100644
index 00000000..98748f2d
--- /dev/null
+++ b/p25/lc/tsbk/OSP_IDEN_UP.cpp
@@ -0,0 +1,111 @@
+/**
+* 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 "p25/lc/tsbk/OSP_IDEN_UP.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_IDEN_UP class.
+///
+OSP_IDEN_UP::OSP_IDEN_UP() : TSBK()
+{
+ m_lco = TSBK_OSP_IDEN_UP;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_IDEN_UP::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_IDEN_UP::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ if ((m_siteIdenEntry.chBandwidthKhz() != 0.0F) && (m_siteIdenEntry.chSpaceKhz() != 0.0F) &&
+ (m_siteIdenEntry.txOffsetMhz() != 0.0F) && (m_siteIdenEntry.baseFrequency() != 0U)) {
+ if (m_siteIdenEntry.baseFrequency() < 762000000U) {
+ LogError(LOG_P25, "TSBK::encode(), invalid values for TSBK_OSP_IDEN_UP, baseFrequency = %uHz",
+ m_siteIdenEntry.baseFrequency());
+ return; // blatently ignore creating this TSBK
+ }
+
+ uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125);
+
+ float fCalcTxOffset = (fabs(m_siteIdenEntry.txOffsetMhz()) * 1000000.0F) / 250000.0F;
+ uint32_t uCalcTxOffset = (uint32_t)fCalcTxOffset;
+ if (m_siteIdenEntry.txOffsetMhz() > 0.0F)
+ uCalcTxOffset |= 0x2000U; // this sets a positive offset ...
+
+ uint32_t calcBaseFreq = (uint32_t)(m_siteIdenEntry.baseFrequency() / 5);
+ uint16_t chanBw = (uint16_t)((m_siteIdenEntry.chBandwidthKhz() * 1000) / 125);
+
+ tsbkValue = m_siteIdenEntry.channelId(); // Channel ID
+ tsbkValue = (tsbkValue << 9) + chanBw; // Channel Bandwidth
+ tsbkValue = (tsbkValue << 9) + uCalcTxOffset; // Transmit Offset
+ tsbkValue = (tsbkValue << 10) + calcSpace; // Channel Spacing
+ tsbkValue = (tsbkValue << 32) + calcBaseFreq; // Base Frequency
+ }
+ else {
+ LogError(LOG_P25, "TSBK::encode(), invalid values for TSBK_OSP_IDEN_UP, baseFrequency = %uHz, txOffsetMhz = %fMHz, chBandwidthKhz = %fKHz, chSpaceKhz = %fKHz",
+ m_siteIdenEntry.baseFrequency(), m_siteIdenEntry.txOffsetMhz(), m_siteIdenEntry.chBandwidthKhz(),
+ m_siteIdenEntry.chSpaceKhz());
+ return; // blatently ignore creating this TSBK
+ }
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/OSP_IDEN_UP.h b/p25/lc/tsbk/OSP_IDEN_UP.h
new file mode 100644
index 00000000..ddafaeae
--- /dev/null
+++ b/p25/lc/tsbk/OSP_IDEN_UP.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_IDEN_UP_H__)
+#define __P25_LC_TSBK__OSP_IDEN_UP_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements IDEN UP - Channel Identifier Update.
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_IDEN_UP : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_IDEN_UP class.
+ OSP_IDEN_UP();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_IDEN_UP_H__
diff --git a/p25/lc/tsbk/OSP_IDEN_UP_VU.cpp b/p25/lc/tsbk/OSP_IDEN_UP_VU.cpp
new file mode 100644
index 00000000..8c42fc98
--- /dev/null
+++ b/p25/lc/tsbk/OSP_IDEN_UP_VU.cpp
@@ -0,0 +1,105 @@
+/**
+* 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 "p25/lc/tsbk/OSP_IDEN_UP_VU.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_IDEN_UP_VU class.
+///
+OSP_IDEN_UP_VU::OSP_IDEN_UP_VU() : TSBK()
+{
+ m_lco = TSBK_OSP_IDEN_UP_VU;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_IDEN_UP_VU::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_IDEN_UP_VU::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ if ((m_siteIdenEntry.chBandwidthKhz() != 0.0F) && (m_siteIdenEntry.chSpaceKhz() != 0.0F) &&
+ (m_siteIdenEntry.txOffsetMhz() != 0.0F) && (m_siteIdenEntry.baseFrequency() != 0U)) {
+ uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125);
+
+ float fCalcTxOffset = (fabs(m_siteIdenEntry.txOffsetMhz()) / m_siteIdenEntry.chSpaceKhz()) * 1000.0F;
+ uint32_t uCalcTxOffset = (uint32_t)fCalcTxOffset;
+ if (m_siteIdenEntry.txOffsetMhz() > 0.0F)
+ uCalcTxOffset |= 0x2000U; // this sets a positive offset ...
+
+ uint32_t calcBaseFreq = (uint32_t)(m_siteIdenEntry.baseFrequency() / 5);
+ uint8_t chanBw = (m_siteIdenEntry.chBandwidthKhz() >= 12.5F) ? P25_IDEN_UP_VU_BW_125K : P25_IDEN_UP_VU_BW_625K;
+
+ tsbkValue = m_siteIdenEntry.channelId(); // Channel ID
+ tsbkValue = (tsbkValue << 4) + chanBw; // Channel Bandwidth
+ tsbkValue = (tsbkValue << 14) + uCalcTxOffset; // Transmit Offset
+ tsbkValue = (tsbkValue << 10) + calcSpace; // Channel Spacing
+ tsbkValue = (tsbkValue << 32) + calcBaseFreq; // Base Frequency
+ }
+ else {
+ LogError(LOG_P25, "TSBK::encode(), invalid values for TSBK_OSP_IDEN_UP_VU, baseFrequency = %uHz, txOffsetMhz = %fMHz, chBandwidthKhz = %fKHz, chSpaceKhz = %fKHz",
+ m_siteIdenEntry.baseFrequency(), m_siteIdenEntry.txOffsetMhz(), m_siteIdenEntry.chBandwidthKhz(),
+ m_siteIdenEntry.chSpaceKhz());
+ return; // blatently ignore creating this TSBK
+ }
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/OSP_IDEN_UP_VU.h b/p25/lc/tsbk/OSP_IDEN_UP_VU.h
new file mode 100644
index 00000000..c6532c64
--- /dev/null
+++ b/p25/lc/tsbk/OSP_IDEN_UP_VU.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_IDEN_UP_VU_H__)
+#define __P25_LC_TSBK__OSP_IDEN_UP_VU_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements IDEN UP VU - Channel Identifier Update for VHF/UHF Bands.
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_IDEN_UP_VU : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_IDEN_UP_VU class.
+ OSP_IDEN_UP_VU();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_IDEN_UP_VU_H__
diff --git a/p25/lc/tsbk/OSP_LOC_REG_RSP.cpp b/p25/lc/tsbk/OSP_LOC_REG_RSP.cpp
new file mode 100644
index 00000000..aae31f4c
--- /dev/null
+++ b/p25/lc/tsbk/OSP_LOC_REG_RSP.cpp
@@ -0,0 +1,86 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "Defines.h"
+#include "p25/lc/tsbk/OSP_LOC_REG_RSP.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_LOC_REG_RSP class.
+///
+OSP_LOC_REG_RSP::OSP_LOC_REG_RSP() : TSBK()
+{
+ m_lco = TSBK_OSP_LOC_REG_RSP;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_LOC_REG_RSP::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_LOC_REG_RSP::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = (tsbkValue << 6) + (m_response & 0x3U); // Registration Response
+ tsbkValue = (tsbkValue << 16) + (m_dstId & 0xFFFFU); // Talkgroup Address
+ tsbkValue = (tsbkValue << 8) + m_siteData.rfssId(); // RF Sub-System ID
+ tsbkValue = (tsbkValue << 8) + m_siteData.sysId(); // Site ID
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/OSP_LOC_REG_RSP.h b/p25/lc/tsbk/OSP_LOC_REG_RSP.h
new file mode 100644
index 00000000..5064c369
--- /dev/null
+++ b/p25/lc/tsbk/OSP_LOC_REG_RSP.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_LOC_REG_RSP_H__)
+#define __P25_LC_TSBK__OSP_LOC_REG_RSP_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements LOC REG RSP - Location Registration Response
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_LOC_REG_RSP : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_LOC_REG_RSP class.
+ OSP_LOC_REG_RSP();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_LOC_REG_RSP_H__
diff --git a/p25/lc/tsbk/OSP_MOT_CC_BSI.cpp b/p25/lc/tsbk/OSP_MOT_CC_BSI.cpp
new file mode 100644
index 00000000..41f6d021
--- /dev/null
+++ b/p25/lc/tsbk/OSP_MOT_CC_BSI.cpp
@@ -0,0 +1,88 @@
+/**
+* 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 "p25/lc/tsbk/OSP_MOT_CC_BSI.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_MOT_CC_BSI class.
+///
+OSP_MOT_CC_BSI::OSP_MOT_CC_BSI() : TSBK()
+{
+ m_lco = TSBK_OSP_MOT_CC_BSI;
+ m_mfId = P25_MFG_MOT;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_MOT_CC_BSI::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_MOT_CC_BSI::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = (m_siteCallsign[0] - 43U) & 0x3F; // Character 0
+ for (uint8_t i = 1; i < P25_MOT_CALLSIGN_LENGTH_BYTES; i++) {
+ tsbkValue = (tsbkValue << 6) + ((m_siteCallsign[i] - 43U) & 0x3F); // Character 1 - 7
+ }
+ tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID
+ tsbkValue = (tsbkValue << 12) + m_siteData.channelNo(); // Channel Number
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/OSP_MOT_CC_BSI.h b/p25/lc/tsbk/OSP_MOT_CC_BSI.h
new file mode 100644
index 00000000..98d5996f
--- /dev/null
+++ b/p25/lc/tsbk/OSP_MOT_CC_BSI.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_MOT_CC_BSI_H__)
+#define __P25_LC_TSBK__OSP_MOT_CC_BSI_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements MOT CC BSI - Motorola / Control Channel Base Station Identifier
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_MOT_CC_BSI : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_MOT_CC_BSI class.
+ OSP_MOT_CC_BSI();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_MOT_CC_BSI_H__
diff --git a/p25/lc/tsbk/OSP_MOT_GRG_ADD.cpp b/p25/lc/tsbk/OSP_MOT_GRG_ADD.cpp
new file mode 100644
index 00000000..54d0e883
--- /dev/null
+++ b/p25/lc/tsbk/OSP_MOT_GRG_ADD.cpp
@@ -0,0 +1,119 @@
+/**
+* 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 "p25/lc/tsbk/OSP_MOT_GRG_ADD.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_MOT_GRG_ADD class.
+///
+OSP_MOT_GRG_ADD::OSP_MOT_GRG_ADD() : TSBK()
+{
+ m_lco = TSBK_OSP_MOT_GRG_ADD;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_MOT_GRG_ADD::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_MOT_GRG_ADD::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ m_mfId = P25_MFG_MOT;
+
+ if ((m_patchSuperGroupId != 0U)) {
+ tsbkValue = m_patchSuperGroupId; // Patch Super Group Address
+ tsbkValue = (tsbkValue << 16) + m_patchGroup1Id; // Patch Group 1 Address
+
+ if (m_patchGroup2Id != 0U) {
+ tsbkValue = (tsbkValue << 16) + m_patchGroup2Id; // Patch Group 2 Address
+ }
+ else {
+ tsbkValue = (tsbkValue << 16) + m_patchGroup1Id; // Patch Group 1 Address
+ }
+
+ if (m_patchGroup3Id != 0U) {
+ tsbkValue = (tsbkValue << 16) + m_patchGroup3Id; // Patch Group 3 Address
+ }
+ else {
+ tsbkValue = (tsbkValue << 16) + m_patchGroup1Id; // Patch Group 1 Address
+ }
+ }
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void OSP_MOT_GRG_ADD::copy(const OSP_MOT_GRG_ADD& data)
+{
+ TSBK::copy(data);
+
+ m_patchSuperGroupId = data.m_patchSuperGroupId;
+ m_patchGroup1Id = data.m_patchGroup1Id;
+ m_patchGroup2Id = data.m_patchGroup2Id;
+ m_patchGroup3Id = data.m_patchGroup3Id;
+}
diff --git a/p25/lc/tsbk/OSP_MOT_GRG_ADD.h b/p25/lc/tsbk/OSP_MOT_GRG_ADD.h
new file mode 100644
index 00000000..97d46f14
--- /dev/null
+++ b/p25/lc/tsbk/OSP_MOT_GRG_ADD.h
@@ -0,0 +1,69 @@
+/**
+* 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(__P25_LC_TSBK__OSP_MOT_GRG_ADD_H__)
+#define __P25_LC_TSBK__OSP_MOT_GRG_ADD_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements MOT GRG ADD - Motorola / Group Regroup Add (Patch Supergroup)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_MOT_GRG_ADD : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_MOT_GRG_ADD class.
+ OSP_MOT_GRG_ADD();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /// Patch super group ID.
+ __PROPERTY(uint32_t, patchSuperGroupId, PatchSuperGroupId);
+ /// 1st patch group ID.
+ __PROPERTY(uint32_t, patchGroup1Id, PatchGroup1Id);
+ /// 2nd patch group ID.
+ __PROPERTY(uint32_t, patchGroup2Id, PatchGroup2Id);
+ /// 3rd patch group ID.
+ __PROPERTY(uint32_t, patchGroup3Id, PatchGroup3Id);
+
+ __COPY(OSP_MOT_GRG_ADD);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_MOT_GRG_ADD_H__
diff --git a/p25/lc/tsbk/OSP_MOT_GRG_DEL.cpp b/p25/lc/tsbk/OSP_MOT_GRG_DEL.cpp
new file mode 100644
index 00000000..911e93eb
--- /dev/null
+++ b/p25/lc/tsbk/OSP_MOT_GRG_DEL.cpp
@@ -0,0 +1,124 @@
+/**
+* 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 "p25/lc/tsbk/OSP_MOT_GRG_DEL.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_MOT_GRG_DEL class.
+///
+OSP_MOT_GRG_DEL::OSP_MOT_GRG_DEL() : TSBK()
+{
+ m_lco = TSBK_OSP_MOT_GRG_DEL;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_MOT_GRG_DEL::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_MOT_GRG_DEL::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ m_mfId = P25_MFG_MOT;
+
+ if ((m_patchSuperGroupId != 0U) && (m_patchGroup1Id != 0U)) {
+ tsbkValue = m_patchSuperGroupId; // Patch Super Group Address
+ tsbkValue = (tsbkValue << 16) + m_patchGroup1Id; // Patch Group 1 Address
+
+ if (m_patchGroup2Id != 0U) {
+ tsbkValue = (tsbkValue << 16) + m_patchGroup2Id; // Patch Group 2 Address
+ }
+ else {
+ tsbkValue = (tsbkValue << 16) + m_patchGroup1Id; // Patch Group 1 Address
+ }
+
+ if (m_patchGroup3Id != 0U) {
+ tsbkValue = (tsbkValue << 16) + m_patchGroup3Id; // Patch Group 3 Address
+ }
+ else {
+ tsbkValue = (tsbkValue << 16) + m_patchGroup1Id; // Patch Group 1 Address
+ }
+ }
+ else {
+ LogError(LOG_P25, "TSBK::encode(), invalid values for TSBK_OSP_MOT_GRG_DEL, patchSuperGroupId = $%02X, patchGroup1Id = $%02X",
+ m_patchSuperGroupId, m_patchGroup1Id);
+ return; // blatently ignore creating this TSBK
+ }
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void OSP_MOT_GRG_DEL::copy(const OSP_MOT_GRG_DEL& data)
+{
+ TSBK::copy(data);
+
+ m_patchSuperGroupId = data.m_patchSuperGroupId;
+ m_patchGroup1Id = data.m_patchGroup1Id;
+ m_patchGroup2Id = data.m_patchGroup2Id;
+ m_patchGroup3Id = data.m_patchGroup3Id;
+}
diff --git a/p25/lc/tsbk/OSP_MOT_GRG_DEL.h b/p25/lc/tsbk/OSP_MOT_GRG_DEL.h
new file mode 100644
index 00000000..6a58d039
--- /dev/null
+++ b/p25/lc/tsbk/OSP_MOT_GRG_DEL.h
@@ -0,0 +1,69 @@
+/**
+* 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(__P25_LC_TSBK__OSP_MOT_GRG_DEL_H__)
+#define __P25_LC_TSBK__OSP_MOT_GRG_DEL_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements MOT GRG DEL - Motorola / Group Regroup Delete (Unpatch Supergroup)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_MOT_GRG_DEL : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_MOT_GRG_DEL class.
+ OSP_MOT_GRG_DEL();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /// Patch super group ID.
+ __PROPERTY(uint32_t, patchSuperGroupId, PatchSuperGroupId);
+ /// 1st patch group ID.
+ __PROPERTY(uint32_t, patchGroup1Id, PatchGroup1Id);
+ /// 2nd patch group ID.
+ __PROPERTY(uint32_t, patchGroup2Id, PatchGroup2Id);
+ /// 3rd patch group ID.
+ __PROPERTY(uint32_t, patchGroup3Id, PatchGroup3Id);
+
+ __COPY(OSP_MOT_GRG_DEL);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_MOT_GRG_DEL_H__
diff --git a/p25/lc/tsbk/OSP_MOT_GRG_VCH_GRANT.cpp b/p25/lc/tsbk/OSP_MOT_GRG_VCH_GRANT.cpp
new file mode 100644
index 00000000..7e86267c
--- /dev/null
+++ b/p25/lc/tsbk/OSP_MOT_GRG_VCH_GRANT.cpp
@@ -0,0 +1,109 @@
+/**
+* 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 "p25/lc/tsbk/OSP_MOT_GRG_VCH_GRANT.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_MOT_GRG_VCH_GRANT class.
+///
+OSP_MOT_GRG_VCH_GRANT::OSP_MOT_GRG_VCH_GRANT() : TSBK()
+{
+ m_lco = TSBK_OSP_MOT_GRG_VCH_GRANT;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_MOT_GRG_VCH_GRANT::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_MOT_GRG_VCH_GRANT::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ m_mfId = P25_MFG_MOT;
+
+ if (m_patchSuperGroupId != 0U) {
+ tsbkValue = 0U; // Priority
+ tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID
+ tsbkValue = (tsbkValue << 12) + m_siteData.channelNo(); // Channel Number
+ tsbkValue = (tsbkValue << 16) + m_patchSuperGroupId; // Patch Supergroup Address
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+ }
+ else {
+ LogError(LOG_P25, "TSBK::encode(), invalid values for TSBK_OSP_MOT_GRG_VCH_GRANT, patchSuperGroupId = $%02X", m_patchSuperGroupId);
+ return; // blatently ignore creating this TSBK
+ }
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void OSP_MOT_GRG_VCH_GRANT::copy(const OSP_MOT_GRG_VCH_GRANT& data)
+{
+ TSBK::copy(data);
+
+ m_patchSuperGroupId = data.m_patchSuperGroupId;
+}
diff --git a/p25/lc/tsbk/OSP_MOT_GRG_VCH_GRANT.h b/p25/lc/tsbk/OSP_MOT_GRG_VCH_GRANT.h
new file mode 100644
index 00000000..fd389469
--- /dev/null
+++ b/p25/lc/tsbk/OSP_MOT_GRG_VCH_GRANT.h
@@ -0,0 +1,63 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_MOT_GRG_VCH_GRANT_H__)
+#define __P25_LC_TSBK__OSP_MOT_GRG_VCH_GRANT_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements MOT GRG GROUP VCH GRANT / Group Regroup Voice Channel Grant
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_MOT_GRG_VCH_GRANT : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_MOT_GRG_VCH_GRANT class.
+ OSP_MOT_GRG_VCH_GRANT();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /// Patch super group ID.
+ __PROPERTY(uint32_t, patchSuperGroupId, PatchSuperGroupId);
+
+ __COPY(OSP_MOT_GRG_VCH_GRANT);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_MOT_GRG_VCH_GRANT_H__
diff --git a/p25/lc/tsbk/OSP_MOT_GRG_VCH_UPD.cpp b/p25/lc/tsbk/OSP_MOT_GRG_VCH_UPD.cpp
new file mode 100644
index 00000000..d328470b
--- /dev/null
+++ b/p25/lc/tsbk/OSP_MOT_GRG_VCH_UPD.cpp
@@ -0,0 +1,105 @@
+/**
+* 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 "p25/lc/tsbk/OSP_MOT_GRG_VCH_UPD.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_MOT_GRG_VCH_UPD class.
+///
+OSP_MOT_GRG_VCH_UPD::OSP_MOT_GRG_VCH_UPD() : TSBK()
+{
+ m_lco = TSBK_OSP_MOT_GRG_VCH_UPD;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_MOT_GRG_VCH_UPD::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_MOT_GRG_VCH_UPD::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ m_mfId = P25_MFG_MOT;
+
+ tsbkValue = m_siteData.channelId(); // Channel ID
+ tsbkValue = (tsbkValue << 4) + m_siteData.channelNo(); // Channel Number
+ tsbkValue = (tsbkValue << 12) + m_patchGroup1Id; // Patch Group 1
+ tsbkValue = (tsbkValue << 16) + m_siteData.channelId(); // Channel ID
+ tsbkValue = (tsbkValue << 4) + m_siteData.channelNo(); // Channel Number
+ tsbkValue = (tsbkValue << 12) + m_patchGroup2Id; // Patch Group 2
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void OSP_MOT_GRG_VCH_UPD::copy(const OSP_MOT_GRG_VCH_UPD& data)
+{
+ TSBK::copy(data);
+
+ m_patchGroup1Id = data.m_patchGroup1Id;
+ m_patchGroup2Id = data.m_patchGroup2Id;
+}
diff --git a/p25/lc/tsbk/OSP_MOT_GRG_VCH_UPD.h b/p25/lc/tsbk/OSP_MOT_GRG_VCH_UPD.h
new file mode 100644
index 00000000..f20eef09
--- /dev/null
+++ b/p25/lc/tsbk/OSP_MOT_GRG_VCH_UPD.h
@@ -0,0 +1,65 @@
+/**
+* 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(__P25_LC_TSBK__OSP_MOT_GRG_VCH_UPD_H__)
+#define __P25_LC_TSBK__OSP_MOT_GRG_VCH_UPD_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements MOT GRG DEL - Motorola / Group Regroup Delete (Unpatch Supergroup)
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_MOT_GRG_VCH_UPD : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_MOT_GRG_VCH_UPD class.
+ OSP_MOT_GRG_VCH_UPD();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /// 1st patch group ID.
+ __PROPERTY(uint32_t, patchGroup1Id, PatchGroup1Id);
+ /// 2nd patch group ID.
+ __PROPERTY(uint32_t, patchGroup2Id, PatchGroup2Id);
+
+ __COPY(OSP_MOT_GRG_VCH_UPD);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_MOT_GRG_VCH_UPD_H__
diff --git a/p25/lc/tsbk/OSP_MOT_PSH_CCH.cpp b/p25/lc/tsbk/OSP_MOT_PSH_CCH.cpp
new file mode 100644
index 00000000..1510ad3f
--- /dev/null
+++ b/p25/lc/tsbk/OSP_MOT_PSH_CCH.cpp
@@ -0,0 +1,81 @@
+/**
+* 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 "p25/lc/tsbk/OSP_MOT_PSH_CCH.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_MOT_PSH_CCH class.
+///
+OSP_MOT_PSH_CCH::OSP_MOT_PSH_CCH() : TSBK()
+{
+ m_lco = TSBK_OSP_MOT_PSH_CCH;
+ m_mfId = P25_MFG_MOT;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_MOT_PSH_CCH::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_MOT_PSH_CCH::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/OSP_MOT_PSH_CCH.h b/p25/lc/tsbk/OSP_MOT_PSH_CCH.h
new file mode 100644
index 00000000..d0cdffd8
--- /dev/null
+++ b/p25/lc/tsbk/OSP_MOT_PSH_CCH.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_MOT_PSH_CCH_H__)
+#define __P25_LC_TSBK__OSP_MOT_PSH_CCH_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements MOT PSH CCH - Motorola / Planned Control Channel Shutdown
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_MOT_PSH_CCH : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_MOT_PSH_CCH class.
+ OSP_MOT_PSH_CCH();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_MOT_PSH_CCH_H__
diff --git a/p25/lc/tsbk/OSP_NET_STS_BCAST.cpp b/p25/lc/tsbk/OSP_NET_STS_BCAST.cpp
new file mode 100644
index 00000000..6fd8e41f
--- /dev/null
+++ b/p25/lc/tsbk/OSP_NET_STS_BCAST.cpp
@@ -0,0 +1,87 @@
+/**
+* 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 "p25/lc/tsbk/OSP_NET_STS_BCAST.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_NET_STS_BCAST class.
+///
+OSP_NET_STS_BCAST::OSP_NET_STS_BCAST() : TSBK()
+{
+ m_lco = TSBK_OSP_NET_STS_BCAST;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_NET_STS_BCAST::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_NET_STS_BCAST::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = m_siteData.lra(); // Location Registration Area
+ tsbkValue = (tsbkValue << 20) + m_siteData.netId(); // Network ID
+ tsbkValue = (tsbkValue << 12) + m_siteData.sysId(); // System ID
+ tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID
+ tsbkValue = (tsbkValue << 12) + m_siteData.channelNo(); // Channel Number
+ tsbkValue = (tsbkValue << 8) + m_siteData.serviceClass(); // System Service Class
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/OSP_NET_STS_BCAST.h b/p25/lc/tsbk/OSP_NET_STS_BCAST.h
new file mode 100644
index 00000000..f40794d0
--- /dev/null
+++ b/p25/lc/tsbk/OSP_NET_STS_BCAST.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_NET_STS_BCAST_H__)
+#define __P25_LC_TSBK__OSP_NET_STS_BCAST_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements NET STS BCAST - Network Status Broadcast.
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_NET_STS_BCAST : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_NET_STS_BCAST class.
+ OSP_NET_STS_BCAST();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_NET_STS_BCAST_H__
diff --git a/p25/lc/tsbk/OSP_QUE_RSP.cpp b/p25/lc/tsbk/OSP_QUE_RSP.cpp
new file mode 100644
index 00000000..898c7ce8
--- /dev/null
+++ b/p25/lc/tsbk/OSP_QUE_RSP.cpp
@@ -0,0 +1,114 @@
+/**
+* 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 "p25/lc/tsbk/OSP_QUE_RSP.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_QUE_RSP class.
+///
+OSP_QUE_RSP::OSP_QUE_RSP() : TSBK()
+{
+ m_lco = TSBK_OSP_QUE_RSP;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_QUE_RSP::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_aivFlag = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Additional Info. Flag
+ m_service = (uint8_t)((tsbkValue >> 56) & 0x3FU); // Service Type
+ m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Reason
+ m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_QUE_RSP::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ if (m_response == 0U) {
+ LogError(LOG_P25, "TSBK::encode(), invalid values for TSBK_OSP_QUE_RSP, reason = %u", m_response);
+ return; // blatently ignore creating this TSBK
+ }
+
+ tsbkValue = (m_aivFlag) ? 0x80U : 0x00U; // Additional Info Flag
+ tsbkValue = (tsbkValue << 6) + m_service; // Service Type
+ tsbkValue = (tsbkValue << 8) + m_response; // Deny/Queue Reason
+
+ if (m_group) {
+ // group deny/queue
+ tsbkValue = (tsbkValue << 8) + 0U; // Call Options
+ tsbkValue = (tsbkValue << 16) + m_dstId; // Talkgroup Address
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+ }
+ else {
+ // private/individual deny/queue
+ tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+ }
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/OSP_QUE_RSP.h b/p25/lc/tsbk/OSP_QUE_RSP.h
new file mode 100644
index 00000000..7e1b3424
--- /dev/null
+++ b/p25/lc/tsbk/OSP_QUE_RSP.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_QUE_RSP_H__)
+#define __P25_LC_TSBK__OSP_QUE_RSP_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements QUE RSP - Queued Response
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_QUE_RSP : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_QUE_RSP class.
+ OSP_QUE_RSP();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_QUE_RSP_H__
diff --git a/p25/lc/tsbk/OSP_RFSS_STS_BCAST.cpp b/p25/lc/tsbk/OSP_RFSS_STS_BCAST.cpp
new file mode 100644
index 00000000..59d2b7a1
--- /dev/null
+++ b/p25/lc/tsbk/OSP_RFSS_STS_BCAST.cpp
@@ -0,0 +1,90 @@
+/**
+* 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 "p25/lc/tsbk/OSP_RFSS_STS_BCAST.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_RFSS_STS_BCAST class.
+///
+OSP_RFSS_STS_BCAST::OSP_RFSS_STS_BCAST() : TSBK()
+{
+ m_lco = TSBK_OSP_RFSS_STS_BCAST;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_RFSS_STS_BCAST::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_RFSS_STS_BCAST::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = m_siteData.lra(); // Location Registration Area
+ tsbkValue = (tsbkValue << 4) +
+ (m_siteData.netActive()) ? P25_CFVA_NETWORK : 0U; // CFVA
+ tsbkValue = (tsbkValue << 12) + m_siteData.sysId(); // System ID
+ tsbkValue = (tsbkValue << 8) + m_siteData.rfssId(); // RF Sub-System ID
+ tsbkValue = (tsbkValue << 8) + m_siteData.siteId(); // Site ID
+ tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID
+ tsbkValue = (tsbkValue << 12) + m_siteData.channelNo(); // Channel Number
+ tsbkValue = (tsbkValue << 8) + m_siteData.serviceClass(); // System Service Class
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/OSP_RFSS_STS_BCAST.h b/p25/lc/tsbk/OSP_RFSS_STS_BCAST.h
new file mode 100644
index 00000000..03c75335
--- /dev/null
+++ b/p25/lc/tsbk/OSP_RFSS_STS_BCAST.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_RFSS_STS_BCAST_H__)
+#define __P25_LC_TSBK__OSP_RFSS_STS_BCAST_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements RFSS STS BCAST - RFSS Status Broadcast.
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_RFSS_STS_BCAST : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_RFSS_STS_BCAST class.
+ OSP_RFSS_STS_BCAST();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_RFSS_STS_BCAST_H__
diff --git a/p25/lc/tsbk/OSP_SCCB.cpp b/p25/lc/tsbk/OSP_SCCB.cpp
new file mode 100644
index 00000000..4a0bc461
--- /dev/null
+++ b/p25/lc/tsbk/OSP_SCCB.cpp
@@ -0,0 +1,115 @@
+/**
+* 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 "p25/lc/tsbk/OSP_SCCB.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_SCCB class.
+///
+OSP_SCCB::OSP_SCCB() : TSBK(),
+ m_sccbChannelId1(0U),
+ m_sccbChannelId2(0U)
+{
+ m_lco = TSBK_OSP_SCCB;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_SCCB::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_SCCB::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = m_siteData.rfssId(); // RF Sub-System ID
+ tsbkValue = (tsbkValue << 8) + m_siteData.siteId(); // Site ID
+ tsbkValue = (tsbkValue << 16) + m_sccbChannelId1; // SCCB Channel ID 1
+ if (m_sccbChannelId1 > 0) {
+ tsbkValue = (tsbkValue << 8) + m_siteData.serviceClass(); // System Service Class
+ }
+ else {
+ tsbkValue = (tsbkValue << 8) + (P25_SVC_CLS_INVALID); // System Service Class
+ }
+ tsbkValue = (tsbkValue << 16) + m_sccbChannelId2; // SCCB Channel ID 2
+ if (m_sccbChannelId2 > 0) {
+ tsbkValue = (tsbkValue << 8) + m_siteData.serviceClass(); // System Service Class
+ }
+ else {
+ tsbkValue = (tsbkValue << 8) + (P25_SVC_CLS_INVALID); // System Service Class
+ }
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void OSP_SCCB::copy(const OSP_SCCB& data)
+{
+ TSBK::copy(data);
+
+ m_sccbChannelId1 = data.m_sccbChannelId1;
+ m_sccbChannelId2 = data.m_sccbChannelId2;
+}
diff --git a/p25/lc/tsbk/OSP_SCCB.h b/p25/lc/tsbk/OSP_SCCB.h
new file mode 100644
index 00000000..440a61f6
--- /dev/null
+++ b/p25/lc/tsbk/OSP_SCCB.h
@@ -0,0 +1,65 @@
+/**
+* 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(__P25_LC_TSBK__OSP_SCCB_H__)
+#define __P25_LC_TSBK__OSP_SCCB_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements SCCB - Secondary Control Channel Broadcast.
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_SCCB : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_SCCB class.
+ OSP_SCCB();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /// SCCB channel ID 1.
+ __PROPERTY(uint8_t, sccbChannelId1, SCCBChnId1);
+ /// SCCB channel ID 2.
+ __PROPERTY(uint8_t, sccbChannelId2, SCCBChnId2);
+
+ __COPY(OSP_SCCB);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_SCCB_H__
diff --git a/p25/lc/tsbk/OSP_SCCB_EXP.cpp b/p25/lc/tsbk/OSP_SCCB_EXP.cpp
new file mode 100644
index 00000000..83f10b41
--- /dev/null
+++ b/p25/lc/tsbk/OSP_SCCB_EXP.cpp
@@ -0,0 +1,113 @@
+/**
+* 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 "p25/lc/tsbk/OSP_SCCB_EXP.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_SCCB_EXP class.
+///
+OSP_SCCB_EXP::OSP_SCCB_EXP() : TSBK(),
+ m_sccbChannelId1(0U),
+ m_sccbChannelNo(0U)
+{
+ m_lco = TSBK_OSP_SCCB_EXP;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_SCCB_EXP::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_SCCB_EXP::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = m_siteData.rfssId(); // RF Sub-System ID
+ tsbkValue = (tsbkValue << 8) + m_siteData.siteId(); // 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
+
+ if (m_sccbChannelId1 > 0) {
+ tsbkValue = (tsbkValue << 8) + m_siteData.serviceClass(); // System Service Class
+ }
+ else {
+ tsbkValue = (tsbkValue << 8) + (P25_SVC_CLS_INVALID); // System Service Class
+ }
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void OSP_SCCB_EXP::copy(const OSP_SCCB_EXP& data)
+{
+ TSBK::copy(data);
+
+ m_sccbChannelId1 = data.m_sccbChannelId1;
+ m_sccbChannelNo = data.m_sccbChannelNo;
+}
diff --git a/p25/lc/tsbk/OSP_SCCB_EXP.h b/p25/lc/tsbk/OSP_SCCB_EXP.h
new file mode 100644
index 00000000..1a07aaca
--- /dev/null
+++ b/p25/lc/tsbk/OSP_SCCB_EXP.h
@@ -0,0 +1,65 @@
+/**
+* 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(__P25_LC_TSBK__OSP_SCCB_EXP_H__)
+#define __P25_LC_TSBK__OSP_SCCB_EXP_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements SCCB - Secondary Control Channel Broadcast - Explicit.
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_SCCB_EXP : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_SCCB_EXP class.
+ OSP_SCCB_EXP();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /// SCCB channel ID 1.
+ __PROPERTY(uint8_t, sccbChannelId1, SCCBChnId1);
+ /// Explicit SCCB channel number.
+ __PROPERTY(uint32_t, sccbChannelNo, SCCBChnNo);
+
+ __COPY(OSP_SCCB_EXP);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_SCCB_EXP_H__
diff --git a/p25/lc/tsbk/OSP_SNDCP_CH_ANN.cpp b/p25/lc/tsbk/OSP_SNDCP_CH_ANN.cpp
new file mode 100644
index 00000000..47aab8f5
--- /dev/null
+++ b/p25/lc/tsbk/OSP_SNDCP_CH_ANN.cpp
@@ -0,0 +1,119 @@
+/**
+* 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 "p25/lc/tsbk/OSP_SNDCP_CH_ANN.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_SNDCP_CH_ANN class.
+///
+OSP_SNDCP_CH_ANN::OSP_SNDCP_CH_ANN() : TSBK(),
+ m_sndcpAutoAccess(true),
+ m_sndcpDAC(1U)
+{
+ m_lco = TSBK_OSP_SNDCP_CH_ANN;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_SNDCP_CH_ANN::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_SNDCP_CH_ANN::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125);
+ float calcTxOffset = m_siteIdenEntry.txOffsetMhz() * 1000000;
+
+ uint32_t txFrequency = (uint32_t)((m_siteIdenEntry.baseFrequency() + ((calcSpace * 125) * m_siteData.channelNo())));
+ uint32_t rxFrequency = (uint32_t)(txFrequency + calcTxOffset);
+
+ uint32_t rootFreq = rxFrequency - m_siteIdenEntry.baseFrequency();
+ uint32_t rxChNo = rootFreq / (m_siteIdenEntry.chSpaceKhz() * 1000);
+
+ tsbkValue = 0U; //
+ tsbkValue = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
+ (m_encrypted ? 0x40U : 0x00U); // Encrypted Flag
+ tsbkValue = (tsbkValue << 8) +
+ (m_sndcpAutoAccess ? 0x80U : 0x00U) + // Autonomous Access
+ (m_sndcpAutoAccess ? 0x40U : 0x00U); // Requested Access
+ tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel (T) ID
+ tsbkValue = (tsbkValue << 12) + m_siteData.channelNo(); // Channel (T) Number
+ tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel (R) ID
+ tsbkValue = (tsbkValue << 12) + (rxChNo & 0xFFFU); // Channel (R) Number
+ tsbkValue = (tsbkValue << 16) + m_sndcpDAC; // Data Access Control
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void OSP_SNDCP_CH_ANN::copy(const OSP_SNDCP_CH_ANN& data)
+{
+ TSBK::copy(data);
+
+ m_sndcpAutoAccess = data.m_sndcpAutoAccess;
+ m_sndcpDAC = data.m_sndcpDAC;
+}
diff --git a/p25/lc/tsbk/OSP_SNDCP_CH_ANN.h b/p25/lc/tsbk/OSP_SNDCP_CH_ANN.h
new file mode 100644
index 00000000..4cb039b0
--- /dev/null
+++ b/p25/lc/tsbk/OSP_SNDCP_CH_ANN.h
@@ -0,0 +1,63 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_SNDCP_CH_ANN_H__)
+#define __P25_LC_TSBK__OSP_SNDCP_CH_ANN_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements SNDCP CH ANN - SNDCP Data Channel Announcement.
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_SNDCP_CH_ANN : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_SNDCP_CH_ANN class.
+ OSP_SNDCP_CH_ANN();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ private:
+ bool m_sndcpAutoAccess;
+ uint16_t m_sndcpDAC;
+
+ __COPY(OSP_SNDCP_CH_ANN);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_SNDCP_CH_ANN_H__
diff --git a/p25/lc/tsbk/OSP_SNDCP_CH_GNT.cpp b/p25/lc/tsbk/OSP_SNDCP_CH_GNT.cpp
new file mode 100644
index 00000000..7f5dd161
--- /dev/null
+++ b/p25/lc/tsbk/OSP_SNDCP_CH_GNT.cpp
@@ -0,0 +1,115 @@
+/**
+* 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 "p25/lc/tsbk/OSP_SNDCP_CH_GNT.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_SNDCP_CH_GNT class.
+///
+OSP_SNDCP_CH_GNT::OSP_SNDCP_CH_GNT() : TSBK(),
+ m_dataServiceOptions(0U),
+ m_dataChannelNo(0U)
+{
+ m_lco = TSBK_OSP_SNDCP_CH_GNT;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_SNDCP_CH_GNT::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_SNDCP_CH_GNT::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125);
+ float calcTxOffset = m_siteIdenEntry.txOffsetMhz() * 1000000;
+
+ uint32_t txFrequency = (uint32_t)((m_siteIdenEntry.baseFrequency() + ((calcSpace * 125) * m_dataChannelNo)));
+ uint32_t rxFrequency = (uint32_t)(txFrequency + calcTxOffset);
+
+ uint32_t rootFreq = rxFrequency - m_siteIdenEntry.baseFrequency();
+ uint32_t rxChNo = rootFreq / (m_siteIdenEntry.chSpaceKhz() * 1000);
+
+ tsbkValue = 0U;
+ tsbkValue = (tsbkValue << 8) + m_dataServiceOptions; // Data Service Options
+ tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel (T) ID
+ tsbkValue = (tsbkValue << 12) + m_dataChannelNo; // Channel (T) Number
+ tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel (R) ID
+ tsbkValue = (tsbkValue << 12) + (rxChNo & 0xFFFU); // Channel (R) Number
+ tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void OSP_SNDCP_CH_GNT::copy(const OSP_SNDCP_CH_GNT& data)
+{
+ TSBK::copy(data);
+
+ m_dataServiceOptions = data.m_dataServiceOptions;
+ m_dataChannelNo = data.m_dataChannelNo;
+}
diff --git a/p25/lc/tsbk/OSP_SNDCP_CH_GNT.h b/p25/lc/tsbk/OSP_SNDCP_CH_GNT.h
new file mode 100644
index 00000000..0f86a0b8
--- /dev/null
+++ b/p25/lc/tsbk/OSP_SNDCP_CH_GNT.h
@@ -0,0 +1,65 @@
+/**
+* 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(__P25_LC_TSBK__OSP_SNDCP_CH_GNT_H__)
+#define __P25_LC_TSBK__OSP_SNDCP_CH_GNT_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements SNDCP CH GNT - SNDCP Data Channel Grant.
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_SNDCP_CH_GNT : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_SNDCP_CH_GNT class.
+ OSP_SNDCP_CH_GNT();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /// SNDCP Data Service Options
+ __PROPERTY(uint8_t, dataServiceOptions, DataServiceOptions);
+ /// SNDCP grant channel number.
+ __PROPERTY(uint32_t, dataChannelNo, DataChnNo);
+
+ __COPY(OSP_SNDCP_CH_GNT);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_SNDCP_CH_GNT_H__
diff --git a/p25/lc/tsbk/OSP_SYNC_BCAST.cpp b/p25/lc/tsbk/OSP_SYNC_BCAST.cpp
new file mode 100644
index 00000000..b5cbde08
--- /dev/null
+++ b/p25/lc/tsbk/OSP_SYNC_BCAST.cpp
@@ -0,0 +1,145 @@
+/**
+* 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 "p25/lc/tsbk/OSP_SYNC_BCAST.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_SYNC_BCAST class.
+///
+OSP_SYNC_BCAST::OSP_SYNC_BCAST() : TSBK(),
+ m_microslotCount(0U)
+{
+ m_lco = TSBK_OSP_SYNC_BCAST;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_SYNC_BCAST::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_SYNC_BCAST::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
+ time_t tt = std::chrono::system_clock::to_time_t(now);
+ tm local_tm = *gmtime(&tt);
+
+ uint32_t tmM = (local_tm.tm_mon + 1);
+ uint32_t tmY = (local_tm.tm_year + 1900) - 2000;
+
+#if DEBUG_P25_TSBK
+ LogDebug(LOG_P25, "TSBK_OSP_SYNC_BCAST, tmM = %u / %u, tmY = %u / %u", local_tm.tm_mon, tmM, local_tm.tm_year, tmY);
+#endif
+
+ // determine LTO and direction (positive or negative)
+ bool negativeLTO = false;
+ uint8_t lto = fabs(m_siteData.lto()) * 2U; // this will cause a bug for half-hour timezone intervals...
+ if (m_siteData.lto() < 0)
+ negativeLTO = true;
+
+ // mark the LTO as valid if its non-zero
+ bool vl = false;
+ if (lto > 0U)
+ vl = true;
+
+ uint8_t mc = 0U;
+
+ // wrap microslot count if necessary
+ if (m_microslotCount > 7999U)
+ m_microslotCount = 0U;
+
+ tsbkValue = 0x0AU + // US - Unsynced Flag Set / MMU - Microslot/Minute Unlock Flag Set
+ ((mc & 0x03U) >> 1); // Minute Correction MSB
+ tsbkValue = (tsbkValue << 8) +
+ ((mc & 0x01U) << 7) + // Minute Correction LSB
+ (vl ? 0x40U : 0x00U) + // Valid LTO Flag
+ (negativeLTO ? 0x20U : 0x00U) + // Add/Subtract LTO Flag
+ (lto & 0x1F); // LTO
+
+ // Date
+ tsbkValue = (tsbkValue << 7) + (tmY & 0x7FU); // Number of Years Past 2000
+ tsbkValue = (tsbkValue << 4) + (tmM & 0x0FU); // Month
+ tsbkValue = (tsbkValue << 5) + (local_tm.tm_mday & 0x1FU); // Day of Month
+
+ // Time
+ tsbkValue = (tsbkValue << 5) + (local_tm.tm_hour & 0x1FU); // Hour
+ tsbkValue = (tsbkValue << 6) + (local_tm.tm_min & 0x3FU); // Minute
+
+ tsbkValue = (tsbkValue << 13) + (m_microslotCount & 0x1FFFU); // Microslot Count
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Internal helper to copy the the class.
+///
+///
+void OSP_SYNC_BCAST::copy(const OSP_SYNC_BCAST& data)
+{
+ TSBK::copy(data);
+
+ m_microslotCount = data.m_microslotCount;
+}
diff --git a/p25/lc/tsbk/OSP_SYNC_BCAST.h b/p25/lc/tsbk/OSP_SYNC_BCAST.h
new file mode 100644
index 00000000..63ea125a
--- /dev/null
+++ b/p25/lc/tsbk/OSP_SYNC_BCAST.h
@@ -0,0 +1,63 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_SYNC_BCAST_H__)
+#define __P25_LC_TSBK__OSP_SYNC_BCAST_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements SYNC BCAST - Synchronization Broadcast
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_SYNC_BCAST : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_SYNC_BCAST class.
+ OSP_SYNC_BCAST();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+
+ public:
+ /// Microslot count.
+ __PROPERTY(uint16_t, microslotCount, MicroslotCount);
+
+ __COPY(OSP_SYNC_BCAST);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_SYNC_BCAST_H__
diff --git a/p25/lc/tsbk/OSP_SYS_SRV_BCAST.cpp b/p25/lc/tsbk/OSP_SYS_SRV_BCAST.cpp
new file mode 100644
index 00000000..420a459c
--- /dev/null
+++ b/p25/lc/tsbk/OSP_SYS_SRV_BCAST.cpp
@@ -0,0 +1,85 @@
+/**
+* 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 "p25/lc/tsbk/OSP_SYS_SRV_BCAST.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_SYS_SRV_BCAST class.
+///
+OSP_SYS_SRV_BCAST::OSP_SYS_SRV_BCAST() : TSBK()
+{
+ m_lco = TSBK_OSP_SYS_SRV_BCAST;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_SYS_SRV_BCAST::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_SYS_SRV_BCAST::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ const uint32_t services = (m_siteData.netActive()) ? P25_SYS_SRV_NET_ACTIVE : 0U | P25_SYS_SRV_DEFAULT;
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = (tsbkValue << 16) + services; // System Services Available
+ tsbkValue = (tsbkValue << 24) + services; // System Services Supported
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/OSP_SYS_SRV_BCAST.h b/p25/lc/tsbk/OSP_SYS_SRV_BCAST.h
new file mode 100644
index 00000000..9a533489
--- /dev/null
+++ b/p25/lc/tsbk/OSP_SYS_SRV_BCAST.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_SYS_SRV_BCAST_H__)
+#define __P25_LC_TSBK__OSP_SYS_SRV_BCAST_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements SYS SRV BCAST - System Service Broadcast
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_SYS_SRV_BCAST : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_SYS_SRV_BCAST class.
+ OSP_SYS_SRV_BCAST();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_SYS_SRV_BCAST_H__
diff --git a/p25/lc/tsbk/OSP_U_DEREG_ACK.cpp b/p25/lc/tsbk/OSP_U_DEREG_ACK.cpp
new file mode 100644
index 00000000..f93b71a6
--- /dev/null
+++ b/p25/lc/tsbk/OSP_U_DEREG_ACK.cpp
@@ -0,0 +1,95 @@
+/**
+* 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 "p25/lc/tsbk/OSP_U_DEREG_ACK.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_U_DEREG_ACK class.
+///
+OSP_U_DEREG_ACK::OSP_U_DEREG_ACK() : TSBK()
+{
+ m_lco = TSBK_OSP_U_DEREG_ACK;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_U_DEREG_ACK::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = TSBK::decode(data, tsbk, rawTSBK);
+ if (!ret)
+ return false;
+
+ ulong64_t tsbkValue = TSBK::tsbkValue(tsbk);
+
+ m_netId = (uint32_t)((tsbkValue >> 36) & 0xFFFFFU); // Network ID
+ m_sysId = (uint32_t)((tsbkValue >> 24) & 0xFFFU); // System ID
+ m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_U_DEREG_ACK::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = (tsbkValue << 8) + m_siteData.netId(); // Network ID
+ tsbkValue = (tsbkValue << 12) + m_siteData.sysId(); // System ID
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/OSP_U_DEREG_ACK.h b/p25/lc/tsbk/OSP_U_DEREG_ACK.h
new file mode 100644
index 00000000..64448741
--- /dev/null
+++ b/p25/lc/tsbk/OSP_U_DEREG_ACK.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_U_DEREG_ACK_H__)
+#define __P25_LC_TSBK__OSP_U_DEREG_ACK_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements U DE REG ACK - Unit De-Registration Acknowledge
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_U_DEREG_ACK : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_U_DEREG_ACK class.
+ OSP_U_DEREG_ACK();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_U_DEREG_ACK_H__
diff --git a/p25/lc/tsbk/OSP_U_REG_CMD.cpp b/p25/lc/tsbk/OSP_U_REG_CMD.cpp
new file mode 100644
index 00000000..9354974a
--- /dev/null
+++ b/p25/lc/tsbk/OSP_U_REG_CMD.cpp
@@ -0,0 +1,83 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "Defines.h"
+#include "p25/lc/tsbk/OSP_U_REG_CMD.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+#include
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the OSP_U_REG_CMD class.
+///
+OSP_U_REG_CMD::OSP_U_REG_CMD() : TSBK()
+{
+ m_lco = TSBK_OSP_U_REG_CMD;
+}
+
+///
+/// Decode a trunking signalling block.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+bool OSP_U_REG_CMD::decode(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ /* stub */
+
+ return true;
+}
+
+///
+/// Encode a trunking signalling block.
+///
+///
+///
+///
+void OSP_U_REG_CMD::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
+{
+ assert(data != NULL);
+
+ ulong64_t tsbkValue = 0U;
+
+ tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
+ tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
+
+ uint8_t* tsbk = TSBK::tsbkValue(tsbkValue);
+ TSBK::encode(data, tsbk, rawTSBK, noTrellis);
+ delete[] tsbk;
+}
diff --git a/p25/lc/tsbk/OSP_U_REG_CMD.h b/p25/lc/tsbk/OSP_U_REG_CMD.h
new file mode 100644
index 00000000..ac38b7d4
--- /dev/null
+++ b/p25/lc/tsbk/OSP_U_REG_CMD.h
@@ -0,0 +1,57 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+/*
+* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#if !defined(__P25_LC_TSBK__OSP_U_REG_CMD_H__)
+#define __P25_LC_TSBK__OSP_U_REG_CMD_H__
+
+#include "Defines.h"
+#include "p25/lc/TSBK.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements U DE REG ACK - Unit De-Registration Acknowledge
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API OSP_U_REG_CMD : public TSBK {
+ public:
+ /// Initializes a new instance of the OSP_U_REG_CMD class.
+ OSP_U_REG_CMD();
+
+ /// Decode a trunking signalling block.
+ virtual bool decode(const uint8_t* data, bool rawTSBK = false);
+ /// Encode a trunking signalling block.
+ virtual void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC_TSBK__OSP_U_REG_CMD_H__
diff --git a/p25/lc/tsbk/TSBKFactory.cpp b/p25/lc/tsbk/TSBKFactory.cpp
new file mode 100644
index 00000000..610124ac
--- /dev/null
+++ b/p25/lc/tsbk/TSBKFactory.cpp
@@ -0,0 +1,371 @@
+/**
+* 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 "p25/lc/tsbk/TSBKFactory.h"
+#include "edac/CRC.h"
+#include "Log.h"
+#include "Utils.h"
+
+using namespace p25::lc::tsbk;
+using namespace p25::lc;
+using namespace p25;
+
+#include
+
+// ---------------------------------------------------------------------------
+// Static Class Members
+// ---------------------------------------------------------------------------
+
+#if FORCE_TSBK_CRC_WARN
+bool TSBKFactory::m_warnCRC = true;
+#else
+bool TSBKFactory::m_warnCRC = false;
+#endif
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the TSBKFactory class.
+///
+TSBKFactory::TSBKFactory()
+{
+ /* stub */
+}
+
+///
+/// Finalizes a instance of TSBKFactory class.
+///
+TSBKFactory::~TSBKFactory()
+{
+ /* stub */
+}
+
+///
+/// Create an instance of a TSBK.
+///
+///
+///
+/// True, if TSBK was decoded, otherwise false.
+TSBK* TSBKFactory::createTSBK(const uint8_t* data, bool rawTSBK)
+{
+ assert(data != NULL);
+
+ uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
+ ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
+
+ edac::Trellis trellis = edac::Trellis();
+
+ if (rawTSBK) {
+ ::memcpy(tsbk, data, P25_TSBK_LENGTH_BYTES);
+
+ bool ret = edac::CRC::checkCCITT162(tsbk, P25_TSBK_LENGTH_BYTES);
+ if (!ret) {
+ if (m_warnCRC) {
+ LogWarning(LOG_P25, "TSBK::decode(), failed CRC CCITT-162 check");
+ ret = true; // ignore CRC error
+ }
+ else {
+ LogError(LOG_P25, "TSBK::decode(), failed CRC CCITT-162 check");
+ }
+ }
+ }
+ else {
+ // deinterleave
+ uint8_t raw[P25_TSBK_FEC_LENGTH_BYTES];
+ P25Utils::decode(data, raw, 114U, 318U);
+
+ // decode 1/2 rate Trellis & check CRC-CCITT 16
+ try {
+ bool ret = trellis.decode12(raw, tsbk);
+ if (!ret) {
+ LogError(LOG_P25, "TSBK::decode(), failed to decode Trellis 1/2 rate coding");
+ }
+
+ if (ret) {
+ ret = edac::CRC::checkCCITT162(tsbk, P25_TSBK_LENGTH_BYTES);
+ if (!ret) {
+ if (m_warnCRC) {
+ LogWarning(LOG_P25, "TSBK::decode(), failed CRC CCITT-162 check");
+ ret = true; // ignore CRC error
+ }
+ else {
+ LogError(LOG_P25, "TSBK::decode(), failed CRC CCITT-162 check");
+ }
+ }
+ }
+
+ if (!ret)
+ return NULL;
+ }
+ catch (...) {
+ Utils::dump(2U, "P25, decoding excepted with input data", tsbk, P25_TSBK_LENGTH_BYTES);
+ return NULL;
+ }
+ }
+
+ uint8_t lco = tsbk[0U] & 0x3F; // LCO
+ uint8_t mfId = tsbk[1U]; // Mfg Id.
+
+ // Motorola P25 vendor opcodes
+ if (mfId == P25_MFG_MOT) {
+ switch (lco) {
+ case TSBK_IOSP_GRP_VCH:
+ case TSBK_IOSP_UU_VCH:
+ case TSBK_IOSP_UU_ANS:
+ case TSBK_IOSP_TELE_INT_ANS:
+ case TSBK_IOSP_STS_UPDT:
+ case TSBK_IOSP_STS_Q:
+ case TSBK_IOSP_MSG_UPDT:
+ case TSBK_IOSP_CALL_ALRT:
+ case TSBK_IOSP_ACK_RSP:
+ case TSBK_IOSP_GRP_AFF:
+ case TSBK_IOSP_U_REG:
+ case TSBK_ISP_CAN_SRV_REQ:
+ case TSBK_ISP_GRP_AFF_Q_RSP:
+ case TSBK_OSP_DENY_RSP:
+ case TSBK_OSP_QUE_RSP:
+ case TSBK_ISP_U_DEREG_REQ:
+ case TSBK_OSP_U_DEREG_ACK:
+ case TSBK_ISP_LOC_REG_REQ:
+ mfId = P25_MFG_STANDARD;
+ break;
+ default:
+ LogError(LOG_P25, "TSBK::decode(), unknown TSBK LCO value, mfId = $%02X, lco = $%02X", mfId, lco);
+ break;
+ }
+
+ if (mfId == P25_MFG_MOT) {
+ return NULL;
+ }
+ else {
+ mfId = tsbk[1U];
+ }
+ }
+
+ // internal P25 vendor opcodes
+ if (mfId == P25_MFG_DVM) {
+ switch (lco) {
+ case LC_CALL_TERM:
+ return decode(new OSP_DVM_LC_CALL_TERM(), data, rawTSBK);
+ default:
+ mfId = P25_MFG_STANDARD;
+ break;
+ }
+
+ if (mfId == P25_MFG_DVM) {
+ return NULL;
+ }
+ else {
+ mfId = tsbk[1U];
+ }
+ }
+
+ // standard P25 reference opcodes
+ switch (lco) {
+ case TSBK_IOSP_GRP_VCH:
+ return decode(new IOSP_GRP_VCH(), data, rawTSBK);
+ case TSBK_IOSP_UU_VCH:
+ return decode(new IOSP_UU_VCH(), data, rawTSBK);
+ case TSBK_IOSP_UU_ANS:
+ return decode(new IOSP_UU_ANS(), data, rawTSBK);
+ case TSBK_ISP_SNDCP_CH_REQ:
+ return decode(new ISP_SNDCP_CH_REQ(), data, rawTSBK);
+ case TSBK_IOSP_STS_UPDT:
+ return decode(new IOSP_STS_UPDT(), data, rawTSBK);
+ case TSBK_IOSP_MSG_UPDT:
+ return decode(new IOSP_MSG_UPDT(), data, rawTSBK);
+ case TSBK_IOSP_RAD_MON:
+ return decode(new IOSP_RAD_MON(), data, rawTSBK);
+ case TSBK_IOSP_CALL_ALRT:
+ return decode(new IOSP_CALL_ALRT(), data, rawTSBK);
+ case TSBK_IOSP_ACK_RSP:
+ return decode(new IOSP_ACK_RSP(), data, rawTSBK);
+ case TSBK_ISP_EMERG_ALRM_REQ:
+ return decode(new ISP_EMERG_ALRM_REQ(), data, rawTSBK);
+ case TSBK_IOSP_EXT_FNCT:
+ return decode(new IOSP_EXT_FNCT(), data, rawTSBK);
+ case TSBK_IOSP_GRP_AFF:
+ return decode(new IOSP_GRP_AFF(), data, rawTSBK);
+ case TSBK_IOSP_U_REG:
+ return decode(new IOSP_U_REG(), data, rawTSBK);
+ case TSBK_ISP_CAN_SRV_REQ:
+ return decode(new ISP_CAN_SRV_REQ(), data, rawTSBK);
+ case TSBK_ISP_GRP_AFF_Q_RSP:
+ return decode(new ISP_GRP_AFF_Q_RSP(), data, rawTSBK);
+ case TSBK_OSP_QUE_RSP:
+ return decode(new OSP_QUE_RSP(), data, rawTSBK);
+ case TSBK_ISP_U_DEREG_REQ:
+ return decode(new ISP_U_DEREG_REQ(), data, rawTSBK);
+ case TSBK_OSP_U_DEREG_ACK:
+ return decode(new OSP_U_DEREG_ACK(), data, rawTSBK);
+ case TSBK_ISP_LOC_REG_REQ:
+ return decode(new ISP_LOC_REG_REQ(), data, rawTSBK);
+ case TSBK_ISP_AUTH_RESP:
+ return decode(new ISP_AUTH_RESP(), data, rawTSBK);
+ case TSBK_ISP_AUTH_FNE_RST:
+ return decode(new ISP_AUTH_FNE_RST(), data, rawTSBK);
+ case TSBK_ISP_AUTH_SU_DMD:
+ return decode(new ISP_AUTH_SU_DMD(), data, rawTSBK);
+ case TSBK_OSP_ADJ_STS_BCAST:
+ return decode(new OSP_ADJ_STS_BCAST(), data, rawTSBK);
+ default:
+ LogError(LOG_P25, "TSBKFactory::create(), unknown TSBK LCO value, mfId = $%02X, lco = $%02X", mfId, lco);
+ break;
+ }
+
+ return NULL;
+}
+
+///
+/// Create an instance of a AMBT.
+///
+///
+///
+///
+AMBT* TSBKFactory::createAMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks)
+{
+ assert(blocks != NULL);
+
+ if (dataHeader.getFormat() != PDU_FMT_AMBT) {
+ LogError(LOG_P25, "TSBKFactory::createAMBT(), PDU is not a AMBT PDU");
+ return NULL;
+ }
+
+ if (dataHeader.getBlocksToFollow() == 0U) {
+ LogError(LOG_P25, "TSBKFactory::createAMBT(), PDU contains no data blocks");
+ return NULL;
+ }
+
+ uint8_t lco = dataHeader.getAMBTOpcode(); // LCO
+ uint8_t mfId = dataHeader.getMFId(); // Mfg Id.
+
+ // Motorola P25 vendor opcodes
+ if (mfId == P25_MFG_MOT) {
+ switch (lco) {
+ case TSBK_IOSP_GRP_VCH:
+ case TSBK_IOSP_UU_VCH:
+ case TSBK_IOSP_UU_ANS:
+ case TSBK_IOSP_TELE_INT_ANS:
+ case TSBK_IOSP_STS_UPDT:
+ case TSBK_IOSP_STS_Q:
+ case TSBK_IOSP_MSG_UPDT:
+ case TSBK_IOSP_CALL_ALRT:
+ case TSBK_IOSP_ACK_RSP:
+ case TSBK_IOSP_GRP_AFF:
+ case TSBK_IOSP_U_REG:
+ case TSBK_ISP_CAN_SRV_REQ:
+ case TSBK_ISP_GRP_AFF_Q_RSP:
+ case TSBK_OSP_DENY_RSP:
+ case TSBK_OSP_QUE_RSP:
+ case TSBK_ISP_U_DEREG_REQ:
+ case TSBK_OSP_U_DEREG_ACK:
+ case TSBK_ISP_LOC_REG_REQ:
+ mfId = P25_MFG_STANDARD;
+ break;
+ default:
+ LogError(LOG_P25, "TSBKFactory::createAMBT(), unknown TSBK LCO value, mfId = $%02X, lco = $%02X", mfId, lco);
+ break;
+ }
+
+ if (mfId == P25_MFG_MOT) {
+ return NULL;
+ }
+ else {
+ mfId = dataHeader.getMFId();
+ }
+ }
+
+ // standard P25 reference opcodes
+ switch (lco) {
+ case TSBK_IOSP_STS_UPDT:
+ return decode(new MBT_IOSP_STS_UPDT(), dataHeader, blocks);
+ case TSBK_IOSP_MSG_UPDT:
+ return decode(new MBT_IOSP_MSG_UPDT(), dataHeader, blocks);
+ case TSBK_IOSP_CALL_ALRT:
+ return decode(new MBT_IOSP_CALL_ALRT(), dataHeader, blocks);
+ case TSBK_IOSP_ACK_RSP:
+ return decode(new MBT_IOSP_ACK_RSP(), dataHeader, blocks);
+ case TSBK_IOSP_GRP_AFF:
+ return decode(new MBT_IOSP_GRP_AFF(), dataHeader, blocks);
+ case TSBK_ISP_CAN_SRV_REQ:
+ return decode(new MBT_ISP_CAN_SRV_REQ(), dataHeader, blocks);
+ case TSBK_IOSP_EXT_FNCT:
+ return decode(new MBT_IOSP_EXT_FNCT(), dataHeader, blocks);
+ case TSBK_ISP_AUTH_RESP_M:
+ return decode(new MBT_ISP_AUTH_RESP_M(), dataHeader, blocks);
+ case TSBK_ISP_AUTH_SU_DMD:
+ return decode(new MBT_ISP_AUTH_SU_DMD(), dataHeader, blocks);
+ default:
+ LogError(LOG_P25, "TSBKFactory::createAMBT(), unknown TSBK LCO value, mfId = $%02X, lco = $%02X", mfId, lco);
+ break;
+ }
+
+ return NULL;
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+///
+///
+///
+///
+///
+///
+TSBK* TSBKFactory::decode(TSBK* tsbk, const uint8_t* data, bool rawTSBK)
+{
+ assert(tsbk != NULL);
+ assert(data != NULL);
+
+ if (!tsbk->decode(data, rawTSBK)) {
+ return NULL;
+ }
+
+ return tsbk;
+}
+
+///
+///
+///
+///
+///
+///
+///
+AMBT* TSBKFactory::decode(AMBT* ambt, const data::DataHeader dataHeader, const data::DataBlock* blocks)
+{
+ assert(ambt != NULL);
+ assert(blocks != NULL);
+
+ if (!ambt->decodeMBT(dataHeader, blocks)) {
+ return NULL;
+ }
+
+ return ambt;
+}
diff --git a/p25/lc/tsbk/TSBKFactory.h b/p25/lc/tsbk/TSBKFactory.h
new file mode 100644
index 00000000..04a4693e
--- /dev/null
+++ b/p25/lc/tsbk/TSBKFactory.h
@@ -0,0 +1,134 @@
+/**
+* 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(__P25_LC__TSBK_FACTORY_H__)
+#define __P25_LC__TSBK_FACTORY_H__
+
+#include "Defines.h"
+
+#include "p25/edac/Trellis.h"
+#include "p25/lc/TSBK.h"
+#include "p25/lc/tsbk/IOSP_ACK_RSP.h"
+#include "p25/lc/tsbk/IOSP_CALL_ALRT.h"
+#include "p25/lc/tsbk/IOSP_EXT_FNCT.h"
+#include "p25/lc/tsbk/IOSP_GRP_AFF.h"
+#include "p25/lc/tsbk/IOSP_GRP_VCH.h"
+#include "p25/lc/tsbk/IOSP_MSG_UPDT.h"
+#include "p25/lc/tsbk/IOSP_RAD_MON.h"
+#include "p25/lc/tsbk/IOSP_STS_UPDT.h"
+#include "p25/lc/tsbk/IOSP_U_REG.h"
+#include "p25/lc/tsbk/IOSP_UU_ANS.h"
+#include "p25/lc/tsbk/IOSP_UU_VCH.h"
+#include "p25/lc/tsbk/ISP_AUTH_FNE_RST.h"
+#include "p25/lc/tsbk/ISP_AUTH_RESP.h"
+#include "p25/lc/tsbk/ISP_AUTH_SU_DMD.h"
+#include "p25/lc/tsbk/ISP_CAN_SRV_REQ.h"
+#include "p25/lc/tsbk/ISP_EMERG_ALRM_REQ.h"
+#include "p25/lc/tsbk/ISP_GRP_AFF_Q_RSP.h"
+#include "p25/lc/tsbk/ISP_LOC_REG_REQ.h"
+#include "p25/lc/tsbk/ISP_SNDCP_CH_REQ.h"
+#include "p25/lc/tsbk/ISP_U_DEREG_REQ.h"
+#include "p25/lc/tsbk/OSP_ADJ_STS_BCAST.h"
+#include "p25/lc/tsbk/OSP_AUTH_FNE_RESP.h"
+#include "p25/lc/tsbk/OSP_DENY_RSP.h"
+#include "p25/lc/tsbk/OSP_DVM_GIT_HASH.h"
+#include "p25/lc/tsbk/OSP_DVM_LC_CALL_TERM.h"
+#include "p25/lc/tsbk/OSP_GRP_AFF_Q.h"
+#include "p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.h"
+#include "p25/lc/tsbk/OSP_IDEN_UP_VU.h"
+#include "p25/lc/tsbk/OSP_IDEN_UP.h"
+#include "p25/lc/tsbk/OSP_LOC_REG_RSP.h"
+#include "p25/lc/tsbk/OSP_MOT_CC_BSI.h"
+#include "p25/lc/tsbk/OSP_MOT_GRG_ADD.h"
+#include "p25/lc/tsbk/OSP_MOT_GRG_DEL.h"
+#include "p25/lc/tsbk/OSP_MOT_GRG_VCH_GRANT.h"
+#include "p25/lc/tsbk/OSP_MOT_GRG_VCH_UPD.h"
+#include "p25/lc/tsbk/OSP_MOT_PSH_CCH.h"
+#include "p25/lc/tsbk/OSP_NET_STS_BCAST.h"
+#include "p25/lc/tsbk/OSP_QUE_RSP.h"
+#include "p25/lc/tsbk/OSP_RFSS_STS_BCAST.h"
+#include "p25/lc/tsbk/OSP_SCCB_EXP.h"
+#include "p25/lc/tsbk/OSP_SCCB.h"
+#include "p25/lc/tsbk/OSP_SNDCP_CH_ANN.h"
+#include "p25/lc/tsbk/OSP_SNDCP_CH_GNT.h"
+#include "p25/lc/tsbk/OSP_SYNC_BCAST.h"
+#include "p25/lc/tsbk/OSP_SYS_SRV_BCAST.h"
+#include "p25/lc/tsbk/OSP_U_DEREG_ACK.h"
+#include "p25/lc/tsbk/OSP_U_REG_CMD.h"
+
+#include "p25/lc/AMBT.h"
+#include "p25/lc/tsbk/MBT_IOSP_ACK_RSP.h"
+#include "p25/lc/tsbk/MBT_IOSP_CALL_ALRT.h"
+#include "p25/lc/tsbk/MBT_IOSP_EXT_FNCT.h"
+#include "p25/lc/tsbk/MBT_IOSP_GRP_AFF.h"
+#include "p25/lc/tsbk/MBT_IOSP_MSG_UPDT.h"
+#include "p25/lc/tsbk/MBT_IOSP_STS_UPDT.h"
+#include "p25/lc/tsbk/MBT_ISP_AUTH_RESP_M.h"
+#include "p25/lc/tsbk/MBT_ISP_AUTH_SU_DMD.h"
+#include "p25/lc/tsbk/MBT_ISP_CAN_SRV_REQ.h"
+#include "p25/lc/tsbk/MBT_OSP_ADJ_STS_BCAST.h"
+#include "p25/lc/tsbk/MBT_OSP_AUTH_DMD.h"
+#include "p25/lc/tsbk/MBT_OSP_NET_STS_BCAST.h"
+#include "p25/lc/tsbk/MBT_OSP_RFSS_STS_BCAST.h"
+
+namespace p25
+{
+ namespace lc
+ {
+ namespace tsbk
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Helper class to instantiate an instance of a TSBK.
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API TSBKFactory {
+ public:
+ /// Initializes a new instance of the TSBKFactory class.
+ TSBKFactory();
+ /// Finalizes a instance of the TSBKFactory class.
+ ~TSBKFactory();
+
+ /// Create an instance of a TSBK.
+ static TSBK* createTSBK(const uint8_t* data, bool rawTSBK = false);
+ /// Create an instance of a AMBT.
+ static AMBT* createAMBT(const data::DataHeader dataHeader, const data::DataBlock* blocks);
+
+ /// Sets the flag indicating CRC-errors should be warnings and not errors.
+ static void setWarnCRC(bool warnCRC) { m_warnCRC = warnCRC; }
+
+ private:
+ static bool m_warnCRC;
+
+ ///
+ static TSBK* decode(TSBK* tsbk, const uint8_t* data, bool rawTSBK = false);
+ ///
+ static AMBT* decode(AMBT* ambt, const data::DataHeader dataHeader, const data::DataBlock* blocks);
+ };
+ } // namespace tsbk
+ } // namespace lc
+} // namespace p25
+
+#endif // __P25_LC__TSBK_FACTORY_H__
diff --git a/p25/packet/Trunk.cpp b/p25/packet/Trunk.cpp
index 920a5df8..bb5d963a 100644
--- a/p25/packet/Trunk.cpp
+++ b/p25/packet/Trunk.cpp
@@ -29,6 +29,7 @@
#include "p25/packet/Voice.h"
#include "p25/packet/Trunk.h"
#include "p25/acl/AccessControl.h"
+#include "p25/lc/tsbk/TSBKFactory.h"
#include "p25/lookups/P25AffiliationLookup.h"
#include "p25/P25Utils.h"
#include "p25/Sync.h"
@@ -53,7 +54,7 @@ using namespace p25::packet;
#define IS_SUPPORT_CONTROL_CHECK(_PCKT_STR, _PCKT, _SRCID) \
if (!m_p25->m_control) { \
LogWarning(LOG_RF, P25_TSDU_STR ", " _PCKT_STR " denial, unsupported service, srcId = %u", _SRCID); \
- writeRF_TSDU_Deny(P25_DENY_RSN_SYS_UNSUPPORTED_SVC, _PCKT); \
+ writeRF_TSDU_Deny(_SRCID, P25_DENY_RSN_SYS_UNSUPPORTED_SVC, _PCKT); \
m_p25->m_rfState = RS_RF_REJECTED; \
return false; \
}
@@ -62,26 +63,26 @@ using namespace p25::packet;
#define VALID_SRCID(_PCKT_STR, _PCKT, _SRCID) \
if (!acl::AccessControl::validateSrcId(_SRCID)) { \
LogWarning(LOG_RF, P25_TSDU_STR ", " _PCKT_STR " denial, RID rejection, srcId = %u", _SRCID); \
- writeRF_TSDU_Deny(P25_DENY_RSN_REQ_UNIT_NOT_VALID, _PCKT); \
+ writeRF_TSDU_Deny(_SRCID, P25_DENY_RSN_REQ_UNIT_NOT_VALID, _PCKT); \
denialInhibit(_SRCID); \
m_p25->m_rfState = RS_RF_REJECTED; \
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, P25_TSDU_STR ", " _PCKT_STR " denial, RID rejection, dstId = %u", _DSTID); \
- writeRF_TSDU_Deny(P25_DENY_RSN_TGT_UNIT_NOT_VALID, _PCKT); \
+ writeRF_TSDU_Deny(_SRCID, P25_DENY_RSN_TGT_UNIT_NOT_VALID, _PCKT); \
m_p25->m_rfState = RS_RF_REJECTED; \
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(_DSTID)) { \
LogWarning(LOG_RF, P25_TSDU_STR ", " _PCKT_STR " denial, TGID rejection, dstId = %u", _DSTID); \
- writeRF_TSDU_Deny(P25_DENY_RSN_TGT_GROUP_NOT_VALID, _PCKT); \
+ writeRF_TSDU_Deny(_SRCID, P25_DENY_RSN_TGT_GROUP_NOT_VALID, _PCKT); \
m_p25->m_rfState = RS_RF_REJECTED; \
return false; \
}
@@ -90,7 +91,7 @@ using namespace p25::packet;
#define VERIFY_SRCID_REG(_PCKT_STR, _PCKT, _SRCID) \
if (!m_p25->m_affiliations.isUnitReg(_SRCID) && m_verifyReg) { \
LogWarning(LOG_RF, P25_TSDU_STR ", " _PCKT_STR " denial, RID not registered, srcId = %u", _SRCID); \
- writeRF_TSDU_Deny(P25_DENY_RSN_REQ_UNIT_NOT_AUTH, _PCKT); \
+ writeRF_TSDU_Deny(_SRCID, P25_DENY_RSN_REQ_UNIT_NOT_AUTH, _PCKT); \
writeRF_TSDU_U_Reg_Cmd(_SRCID); \
m_p25->m_rfState = RS_RF_REJECTED; \
return false; \
@@ -100,7 +101,7 @@ using namespace p25::packet;
#define VERIFY_SRCID_AFF(_PCKT_STR, _PCKT, _SRCID, _DSTID) \
if (!m_p25->m_affiliations.isGroupAff(_SRCID, _DSTID) && m_verifyAff) { \
LogWarning(LOG_RF, P25_TSDU_STR ", " _PCKT_STR " denial, RID not affiliated to TGID, srcId = %u, dstId = %u", _SRCID, _DSTID); \
- writeRF_TSDU_Deny(P25_DENY_RSN_REQ_UNIT_NOT_AUTH, _PCKT); \
+ writeRF_TSDU_Deny(_SRCID, P25_DENY_RSN_REQ_UNIT_NOT_AUTH, _PCKT); \
writeRF_TSDU_U_Reg_Cmd(_SRCID); \
m_p25->m_rfState = RS_RF_REJECTED; \
return false; \
@@ -120,11 +121,11 @@ using namespace p25::packet;
return false; \
}
-#define RF_TO_WRITE_NET() \
+#define RF_TO_WRITE_NET(OSP) \
if (m_network != NULL) { \
uint8_t _buf[P25_TSDU_FRAME_LENGTH_BYTES]; \
- writeNet_TSDU_From_RF(_buf); \
- writeNetworkRF(_buf, true); \
+ writeNet_TSDU_From_RF(OSP, _buf); \
+ writeNetworkRF(OSP, _buf, true); \
}
// ---------------------------------------------------------------------------
@@ -142,32 +143,14 @@ const uint8_t CONV_FALLBACK_PACKET_DELAY = 8U;
// Public Class Members
// ---------------------------------------------------------------------------
-///
-/// Resets the data states for the RF interface.
-///
-void Trunk::resetRF()
-{
- lc::TSBK tsbk = lc::TSBK(m_p25->m_siteData, m_p25->m_idenEntry, m_dumpTSBK);
- m_rfTSBK = tsbk;
-}
-
-///
-/// Resets the data states for the network.
-///
-void Trunk::resetNet()
-{
- lc::TSBK tsbk = lc::TSBK(m_p25->m_siteData, m_p25->m_idenEntry, m_dumpTSBK);
- m_netTSBK = tsbk;
-}
-
///
/// Process a data frame from the RF interface.
///
/// Buffer containing data frame.
/// Length of data frame.
-/// Flag indicating the TSBK data is pre-decoded TSBK data.
+/// Pre-decoded TSBK.
///
-bool Trunk::process(uint8_t* data, uint32_t len, bool preDecoded)
+bool Trunk::process(uint8_t* data, uint32_t len, lc::TSBK* preDecodedTSBK)
{
assert(data != NULL);
@@ -175,7 +158,7 @@ bool Trunk::process(uint8_t* data, uint32_t len, bool preDecoded)
return false;
uint8_t duid = 0U;
- if (!preDecoded) {
+ if (preDecodedTSBK == NULL) {
// Decode the NID
bool valid = m_p25->m_nid.decode(data + 2U);
@@ -188,6 +171,7 @@ bool Trunk::process(uint8_t* data, uint32_t len, bool preDecoded)
}
RPT_RF_STATE prevRfState = m_p25->m_rfState;
+ lc::TSBK *tsbk = NULL;
// handle individual DUIDs
if (duid == P25_DUID_TSDU) {
@@ -197,28 +181,24 @@ bool Trunk::process(uint8_t* data, uint32_t len, bool preDecoded)
m_p25->m_queue.clear();
- if (!preDecoded) {
- resetRF();
- resetNet();
-
- bool ret = m_rfTSBK.decode(data + 2U);
- if (!ret) {
+ if (preDecodedTSBK == NULL) {
+ tsbk = lc::tsbk::TSBKFactory::createTSBK(data + 2U);
+ if (tsbk == NULL) {
LogWarning(LOG_RF, P25_TSDU_STR ", undecodable LC");
m_p25->m_rfState = prevRfState;
return false;
}
- }
- else {
- resetNet();
+ } else {
+ tsbk = preDecodedTSBK;
}
- uint32_t srcId = m_rfTSBK.getSrcId();
- uint32_t dstId = m_rfTSBK.getDstId();
- uint8_t txMult = m_rfTSBK.getTxMult();
+ uint32_t srcId = tsbk->getSrcId();
+ uint32_t dstId = tsbk->getDstId();
// handle standard P25 reference opcodes
- switch (m_rfTSBK.getLCO()) {
+ switch (tsbk->getLCO()) {
case TSBK_IOSP_GRP_VCH:
+ {
// make sure control data is supported
IS_SUPPORT_CONTROL_CHECK("TSBK_IOSP_GRP_VCH (Group Voice Channel Request)", TSBK_IOSP_GRP_VCH, srcId);
@@ -226,7 +206,7 @@ bool Trunk::process(uint8_t* data, uint32_t len, bool preDecoded)
VALID_SRCID("TSBK_IOSP_GRP_VCH (Group Voice Channel Request)", TSBK_IOSP_GRP_VCH, srcId);
// validate the talkgroup ID
- VALID_TGID("TSBK_IOSP_GRP_VCH (Group Voice Channel Request)", TSBK_IOSP_GRP_VCH, dstId);
+ VALID_TGID("TSBK_IOSP_GRP_VCH (Group Voice Channel Request)", TSBK_IOSP_GRP_VCH, srcId, dstId);
// verify the source RID is affiliated
VERIFY_SRCID_AFF("TSBK_IOSP_GRP_VCH (Group Voice Channel Request)", TSBK_IOSP_GRP_VCH, srcId, dstId);
@@ -235,9 +215,15 @@ bool Trunk::process(uint8_t* data, uint32_t len, bool preDecoded)
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_VCH (Group Voice Channel Request), srcId = %u, dstId = %u", srcId, dstId);
}
- writeRF_TSDU_Grant(true);
- break;
+ uint8_t serviceOptions = (tsbk->getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
+ (tsbk->getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
+ (tsbk->getPriority() & 0x07U); // Priority
+
+ writeRF_TSDU_Grant(srcId, dstId, serviceOptions, true);
+ }
+ break;
case TSBK_IOSP_UU_VCH:
+ {
// make sure control data is supported
IS_SUPPORT_CONTROL_CHECK("TSBK_IOSP_UU_VCH (Unit-to-Unit Voice Channel Request)", TSBK_IOSP_UU_VCH, srcId);
@@ -245,7 +231,7 @@ bool Trunk::process(uint8_t* data, uint32_t len, bool preDecoded)
VALID_SRCID("TSBK_IOSP_UU_VCH (Unit-to-Unit Voice Channel Request)", TSBK_IOSP_UU_VCH, srcId);
// validate the target RID
- VALID_DSTID("TSBK_IOSP_UU_VCH (Unit-to-Unit Voice Channel Request)", TSBK_IOSP_UU_VCH, dstId);
+ VALID_DSTID("TSBK_IOSP_UU_VCH (Unit-to-Unit Voice Channel Request)", TSBK_IOSP_UU_VCH, srcId, dstId);
// verify the source RID is registered
VERIFY_SRCID_REG("TSBK_IOSP_UU_VCH (Unit-to-Unit Voice Channel Request)", TSBK_IOSP_UU_VCH, srcId);
@@ -258,10 +244,16 @@ bool Trunk::process(uint8_t* data, uint32_t len, bool preDecoded)
writeRF_TSDU_UU_Ans_Req(srcId, dstId);
}
else {
- writeRF_TSDU_Grant(false);
+ uint8_t serviceOptions = (tsbk->getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
+ (tsbk->getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
+ (tsbk->getPriority() & 0x07U); // Priority
+
+ writeRF_TSDU_Grant(srcId, dstId, serviceOptions, false);
}
- break;
+ }
+ break;
case TSBK_IOSP_UU_ANS:
+ {
// make sure control data is supported
IS_SUPPORT_CONTROL_CHECK("TSBK_IOSP_UU_ANS (Unit-to-Unit Answer Response)", TSBK_IOSP_UU_ANS, srcId);
@@ -269,99 +261,130 @@ bool Trunk::process(uint8_t* data, uint32_t len, bool preDecoded)
VALID_SRCID("TSBK_IOSP_UU_ANS (Unit-to-Unit Answer Response)", TSBK_IOSP_UU_ANS, srcId);
// validate the target RID
- VALID_DSTID("TSBK_IOSP_UU_ANS (Unit-to-Unit Answer Response)", TSBK_IOSP_UU_ANS, dstId);
+ VALID_DSTID("TSBK_IOSP_UU_ANS (Unit-to-Unit Answer Response)", TSBK_IOSP_UU_ANS, srcId, dstId);
+ lc::tsbk::IOSP_UU_ANS* iosp = (lc::tsbk::IOSP_UU_ANS*)tsbk;
if (m_verbose) {
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_UU_ANS (Unit-to-Unit Answer Response), response = $%02X, srcId = %u, dstId = %u",
- m_rfTSBK.getResponse(), srcId, dstId);
+ iosp->getResponse(), srcId, dstId);
}
- if (m_rfTSBK.getResponse() == P25_ANS_RSP_PROCEED) {
+ if (iosp->getResponse() == P25_ANS_RSP_PROCEED) {
if (m_p25->m_ackTSBKRequests) {
writeRF_TSDU_ACK_FNE(dstId, TSBK_IOSP_UU_ANS, false, true);
}
- writeRF_TSDU_Grant(false);
+ uint8_t serviceOptions = (tsbk->getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
+ (tsbk->getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
+ (tsbk->getPriority() & 0x07U); // Priority
+
+ writeRF_TSDU_Grant(srcId, dstId, serviceOptions, false);
}
- else if (m_rfTSBK.getResponse() == P25_ANS_RSP_DENY) {
- writeRF_TSDU_Deny(P25_DENY_RSN_TGT_UNIT_REFUSED, TSBK_IOSP_UU_ANS);
+ else if (iosp->getResponse() == P25_ANS_RSP_DENY) {
+ writeRF_TSDU_Deny(srcId, P25_DENY_RSN_TGT_UNIT_REFUSED, TSBK_IOSP_UU_ANS);
}
- else if (m_rfTSBK.getResponse() == P25_ANS_RSP_WAIT) {
- writeRF_TSDU_Queue(P25_QUE_RSN_TGT_UNIT_QUEUED, TSBK_IOSP_UU_ANS);
+ else if (iosp->getResponse() == P25_ANS_RSP_WAIT) {
+ writeRF_TSDU_Queue(srcId, P25_QUE_RSN_TGT_UNIT_QUEUED, TSBK_IOSP_UU_ANS);
}
- break;
+ }
+ break;
case TSBK_IOSP_TELE_INT_ANS:
+ {
// make sure control data is supported
IS_SUPPORT_CONTROL_CHECK("TSBK_IOSP_TELE_INT_ANS (Telephone Interconnect Answer Response)", TSBK_IOSP_TELE_INT_ANS, srcId);
// validate the source RID
VALID_SRCID("TSBK_IOSP_TELE_INT_ANS (Telephone Interconnect Answer Response)", TSBK_IOSP_TELE_INT_ANS, srcId);
- if (m_verbose) {
- LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_TELE_INT_ANS (Telephone Interconnect Answer Response), response = $%02X, srcId = %u",
- m_rfTSBK.getResponse(), srcId);
- }
-
- writeRF_TSDU_Deny(P25_DENY_RSN_SYS_UNSUPPORTED_SVC, TSBK_IOSP_TELE_INT_ANS);
- break;
+ writeRF_TSDU_Deny(srcId, P25_DENY_RSN_SYS_UNSUPPORTED_SVC, TSBK_IOSP_TELE_INT_ANS);
+ }
+ break;
case TSBK_ISP_SNDCP_CH_REQ:
+ {
// make sure control data is supported
IS_SUPPORT_CONTROL_CHECK("TSBK_ISP_SNDCP_CH_REQ (SNDCP Channel Request)", TSBK_ISP_SNDCP_CH_REQ, srcId);
// validate the source RID
VALID_SRCID("TSBK_ISP_SNDCP_CH_REQ (SNDCP Channel Request)", TSBK_ISP_SNDCP_CH_REQ, srcId);
+ lc::tsbk::ISP_SNDCP_CH_REQ* isp = (lc::tsbk::ISP_SNDCP_CH_REQ*)data;
if (m_verbose) {
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_ISP_SNDCP_CH_REQ (SNDCP Channel Request), dataServiceOptions = $%02X, dataAccessControl = %u, srcId = %u",
- m_rfTSBK.getDataServiceOptions(), m_rfTSBK.getDataAccessControl(), srcId);
+ isp->getDataServiceOptions(), isp->getDataAccessControl(), srcId);
}
if (m_sndcpChGrant) {
writeRF_TSDU_SNDCP_Grant(false, false);
}
else {
- writeRF_TSDU_Deny(P25_DENY_RSN_SYS_UNSUPPORTED_SVC, TSBK_ISP_SNDCP_CH_REQ);
+ writeRF_TSDU_Deny(srcId, P25_DENY_RSN_SYS_UNSUPPORTED_SVC, TSBK_ISP_SNDCP_CH_REQ);
}
- break;
+ }
+ break;
case TSBK_IOSP_STS_UPDT:
+ {
// validate the source RID
VALID_SRCID("TSBK_IOSP_STS_UPDT (Status Update)", TSBK_IOSP_STS_UPDT, srcId);
- RF_TO_WRITE_NET();
-
+ lc::tsbk::IOSP_STS_UPDT* iosp = (lc::tsbk::IOSP_STS_UPDT*)data;
if (m_verbose) {
- LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_STS_UPDT (Status Update), status = $%02X, srcId = %u", m_rfTSBK.getStatus(), srcId);
+ LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_STS_UPDT (Status Update), status = $%02X, srcId = %u", iosp->getStatus(), srcId);
}
+ RF_TO_WRITE_NET(iosp);
+
if (!m_noStatusAck) {
writeRF_TSDU_ACK_FNE(srcId, TSBK_IOSP_STS_UPDT, false, false);
}
::ActivityLog("P25", true, "status update from %u", srcId);
- break;
+ }
+ break;
case TSBK_IOSP_MSG_UPDT:
+ {
// validate the source RID
VALID_SRCID("TSBK_IOSP_MSG_UPDT (Message Update)", TSBK_IOSP_MSG_UPDT, srcId);
- RF_TO_WRITE_NET();
-
+ lc::tsbk::IOSP_MSG_UPDT* iosp = (lc::tsbk::IOSP_MSG_UPDT*)data;
if (m_verbose) {
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_MSG_UPDT (Message Update), message = $%02X, srcId = %u, dstId = %u",
- m_rfTSBK.getMessage(), srcId, dstId);
+ iosp->getMessage(), srcId, dstId);
}
+ RF_TO_WRITE_NET(iosp);
+
if (!m_noMessageAck) {
writeRF_TSDU_ACK_FNE(srcId, TSBK_IOSP_MSG_UPDT, false, false);
}
::ActivityLog("P25", true, "message update from %u", srcId);
- break;
+ }
+ break;
+ case TSBK_IOSP_RAD_MON:
+ {
+ // validate the source RID
+ VALID_SRCID("TSBK_IOSP_RAD_MON (Radio Monitor)", TSBK_IOSP_RAD_MON, srcId);
+
+ // validate the target RID
+ VALID_DSTID("TSBK_IOSP_RAD_MON (Radio Monitor)", TSBK_IOSP_RAD_MON, srcId, dstId);
+
+ lc::tsbk::IOSP_RAD_MON* iosp = (lc::tsbk::IOSP_RAD_MON*)tsbk;
+ if (m_verbose) {
+ LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_ISP_RAD_MON_REQ (Radio Monitor), srcId = %u, dstId = %u", srcId, dstId);
+ }
+
+ ::ActivityLog("P25" , true , "radio monitor request from %u to %u" , srcId , dstId);
+
+ writeRF_TSDU_Radio_Mon(srcId, dstId, iosp->getTxMult());
+ }
+ break;
case TSBK_IOSP_CALL_ALRT:
+ {
// validate the source RID
VALID_SRCID("TSBK_IOSP_CALL_ALRT (Call Alert)", TSBK_IOSP_CALL_ALRT, srcId);
// validate the target RID
- VALID_DSTID("TSBK_IOSP_CALL_ALRT (Call Alert)", TSBK_IOSP_CALL_ALRT, dstId);
+ VALID_DSTID("TSBK_IOSP_CALL_ALRT (Call Alert)", TSBK_IOSP_CALL_ALRT, srcId, dstId);
if (m_verbose) {
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_CALL_ALRT (Call Alert), srcId = %u, dstId = %u", srcId, dstId);
@@ -370,63 +393,75 @@ bool Trunk::process(uint8_t* data, uint32_t len, bool preDecoded)
::ActivityLog("P25", true, "call alert request from %u to %u", srcId, dstId);
writeRF_TSDU_Call_Alrt(srcId, dstId);
- break;
+ }
+ break;
case TSBK_IOSP_ACK_RSP:
+ {
// validate the source RID
VALID_SRCID("TSBK_IOSP_ACK_RSP (Acknowledge Response)", TSBK_IOSP_ACK_RSP, srcId);
// validate the target RID
- VALID_DSTID("TSBK_IOSP_ACK_RSP (Acknowledge Response)", TSBK_IOSP_ACK_RSP, dstId);
+ VALID_DSTID("TSBK_IOSP_ACK_RSP (Acknowledge Response)", TSBK_IOSP_ACK_RSP, srcId, dstId);
+ lc::tsbk::IOSP_ACK_RSP* iosp = (lc::tsbk::IOSP_ACK_RSP*)tsbk;
if (m_verbose) {
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_ACK_RSP (Acknowledge Response), AIV = %u, serviceType = $%02X, srcId = %u, dstId = %u",
- m_rfTSBK.getAIV(), m_rfTSBK.getService(), srcId, dstId);
+ iosp->getAIV(), iosp->getService(), srcId, dstId);
}
::ActivityLog("P25", true, "ack response from %u to %u", srcId, dstId);
// bryanb: HACK -- for some reason, if the AIV is false and we have a dstId
// its very likely srcId and dstId are swapped so we'll swap them
- if (!m_rfTSBK.getAIV() && dstId != 0U) {
- m_rfTSBK.setAIV(true);
- m_rfTSBK.setSrcId(dstId);
- m_rfTSBK.setDstId(srcId);
+ if (!iosp->getAIV() && dstId != 0U) {
+ iosp->setAIV(true);
+ iosp->setSrcId(dstId);
+ iosp->setDstId(srcId);
}
- writeRF_TSDU_SBF(false);
- break;
+ writeRF_TSDU_SBF(iosp, false);
+ }
+ break;
case TSBK_ISP_CAN_SRV_REQ:
+ {
+ lc::tsbk::ISP_CAN_SRV_REQ* isp = (lc::tsbk::ISP_CAN_SRV_REQ*)tsbk;
if (m_verbose) {
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_ISP_CAN_SRV_REQ (Cancel Service Request), AIV = %u, serviceType = $%02X, reason = $%02X, srcId = %u, dstId = %u",
- m_rfTSBK.getAIV(), m_rfTSBK.getService(), m_rfTSBK.getResponse(), srcId, dstId);
+ isp->getAIV(), isp->getService(), isp->getResponse(), srcId, dstId);
}
::ActivityLog("P25", true, "cancel service request from %u", srcId);
writeRF_TSDU_ACK_FNE(srcId, TSBK_ISP_CAN_SRV_REQ, false, true);
- break;
+ }
+ break;
case TSBK_IOSP_EXT_FNCT:
+ {
+ lc::tsbk::IOSP_EXT_FNCT* iosp = (lc::tsbk::IOSP_EXT_FNCT*)tsbk;
if (m_verbose) {
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_EXT_FNCT (Extended Function), op = $%02X, arg = %u, tgt = %u",
- m_rfTSBK.getExtendedFunction(), dstId, srcId);
+ iosp->getExtendedFunction(), dstId, srcId);
}
// generate activity log entry
- if (m_rfTSBK.getExtendedFunction() == P25_EXT_FNCT_CHECK_ACK) {
+ if (iosp->getExtendedFunction() == P25_EXT_FNCT_CHECK_ACK) {
::ActivityLog("P25", true, "radio check response from %u to %u", dstId, srcId);
}
- else if (m_rfTSBK.getExtendedFunction() == P25_EXT_FNCT_INHIBIT_ACK) {
+ else if (iosp->getExtendedFunction() == P25_EXT_FNCT_INHIBIT_ACK) {
::ActivityLog("P25", true, "radio inhibit response from %u to %u", dstId, srcId);
}
- else if (m_rfTSBK.getExtendedFunction() == P25_EXT_FNCT_UNINHIBIT_ACK) {
+ else if (iosp->getExtendedFunction() == P25_EXT_FNCT_UNINHIBIT_ACK) {
::ActivityLog("P25", true, "radio uninhibit response from %u to %u", dstId, srcId);
}
- writeRF_TSDU_SBF(true);
- break;
+ writeRF_TSDU_SBF(iosp, true);
+ }
+ break;
case TSBK_ISP_EMERG_ALRM_REQ:
+ {
if (!m_p25->m_emergDisabled) {
- if (m_rfTSBK.getEmergency()) {
+ lc::tsbk::ISP_EMERG_ALRM_REQ* isp = (lc::tsbk::ISP_EMERG_ALRM_REQ*)tsbk;
+ if (isp->getEmergency()) {
if (m_verbose) {
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_ISP_EMERG_ALRM_REQ (Emergency Alarm Request), srcId = %u, dstId = %u",
srcId, dstId);
@@ -442,8 +477,10 @@ bool Trunk::process(uint8_t* data, uint32_t len, bool preDecoded)
} else {
LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_ISP_EMERG_ALRM_REQ (Emergency Alarm Request) denial, emergency while emergency disabled, srcId = %u", srcId);
}
- break;
+ }
+ break;
case TSBK_IOSP_GRP_AFF:
+ {
// make sure control data is supported
IS_SUPPORT_CONTROL_CHECK("TSBK_IOSP_GRP_AFF (Group Affiliation Request)", TSBK_IOSP_GRP_AFF, srcId);
@@ -456,28 +493,33 @@ bool Trunk::process(uint8_t* data, uint32_t len, bool preDecoded)
}
writeRF_TSDU_Grp_Aff_Rsp(srcId, dstId);
- break;
+ }
+ break;
case TSBK_ISP_GRP_AFF_Q_RSP:
+ {
// make sure control data is supported
IS_SUPPORT_CONTROL_CHECK("TSBK_IOSP_GRP_AFF (Group Affiliation Query Response)", TSBK_ISP_GRP_AFF_Q_RSP, srcId);
+ lc::tsbk::ISP_GRP_AFF_Q_RSP* isp = (lc::tsbk::ISP_GRP_AFF_Q_RSP*)tsbk;
if (m_verbose) {
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_AFF (Group Affiliation Query Response), srcId = %u, dstId = %u, anncId = %u", srcId, dstId,
- m_rfTSBK.getPatchSuperGroupId());
+ isp->getAnnounceGroup());
}
::ActivityLog("P25", true, "group affiliation query response from %u to %s %u", srcId, "TG ", dstId);
- break;
+ }
+ break;
case TSBK_ISP_U_DEREG_REQ:
+ {
// make sure control data is supported
IS_SUPPORT_CONTROL_CHECK("TSBK_ISP_U_DEREG_REQ (Unit Deregistration Request)", TSBK_ISP_U_DEREG_REQ, srcId);
// validate the source RID
VALID_SRCID("TSBK_ISP_U_DEREG_REQ (Unit Deregistration Request)", TSBK_ISP_U_DEREG_REQ, srcId);
- // HACK: ensure the DEREG_REQ transmits something ...
- if (dstId == 0U) {
- dstId = P25_WUID_FNE;
+ if (m_verbose) {
+ LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_ISP_U_DEREG_REQ (Unit Deregistration Request) srcId = %u, sysId = $%03X, netId = $%05X",
+ srcId, tsbk->getSysId(), tsbk->getNetId());
}
if (m_p25->m_ackTSBKRequests) {
@@ -485,22 +527,27 @@ bool Trunk::process(uint8_t* data, uint32_t len, bool preDecoded)
}
writeRF_TSDU_U_Dereg_Ack(srcId);
- break;
+ }
+ break;
case TSBK_IOSP_U_REG:
+ {
// make sure control data is supported
IS_SUPPORT_CONTROL_CHECK("TSBK_ISP_U_REG_REQ (Unit Registration Request)", TSBK_IOSP_U_REG, srcId);
if (m_verbose) {
- LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_ISP_U_REG_REQ (Unit Registration Request), srcId = %u", srcId);
+ LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_ISP_U_REG_REQ (Unit Registration Request), srcId = %u, sysId = $%03X, netId = $%05X",
+ srcId, tsbk->getSysId(), tsbk->getNetId());
}
if (m_p25->m_ackTSBKRequests) {
writeRF_TSDU_ACK_FNE(srcId, TSBK_IOSP_U_REG, true, true);
}
- writeRF_TSDU_U_Reg_Rsp(srcId);
- break;
+ writeRF_TSDU_U_Reg_Rsp(srcId, tsbk->getSysId());
+ }
+ break;
case TSBK_ISP_LOC_REG_REQ:
+ {
// make sure control data is supported
IS_SUPPORT_CONTROL_CHECK("TSBK_ISP_LOC_REG_REQ (Location Registration Request)", TSBK_ISP_LOC_REG_REQ, srcId);
@@ -508,27 +555,13 @@ bool Trunk::process(uint8_t* data, uint32_t len, bool preDecoded)
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_ISP_LOC_REG_REQ (Location Registration Request), srcId = %u, dstId = %u", srcId, dstId);
}
- writeRF_TSDU_Loc_Reg_Rsp(srcId, dstId);
- break;
- case TSBK_ISP_RAD_MON_REQ:
- // validate the source RID
- VALID_SRCID("TSBK_ISP_RAD_MON_REQ (Radio Monitor)" , TSBK_ISP_RAD_MON_REQ , srcId);
-
- // validate the target RID
- VALID_DSTID("TSBK_ISP_RAD_MON_REQ (Radio monitor)" , TSBK_ISP_RAD_MON_REQ , dstId);
-
- if ( m_verbose ) {
- LogMessage(LOG_RF , P25_TSDU_STR ", TSBK_ISP_RAD_MON_REQ (Radio Monitor), srcId = %u, dstId = %u" , srcId , dstId);
- }
-
- ::ActivityLog("P25" , true , "radio monitor request from %u to %u" , srcId , dstId);
-
- writeRF_TSDU_Radio_Mon(srcId , dstId, txMult);
- break;
+ writeRF_TSDU_Loc_Reg_Rsp(srcId, dstId, tsbk->getGroup());
+ }
+ break;
default:
- LogError(LOG_RF, P25_TSDU_STR ", unhandled LCO, mfId = $%02X, lco = $%02X", m_rfTSBK.getMFId(), m_rfTSBK.getLCO());
+ LogError(LOG_RF, P25_TSDU_STR ", unhandled LCO, mfId = $%02X, lco = $%02X", tsbk->getMFId(), tsbk->getLCO());
break;
- } // switch (m_rfTSBK.getLCO())
+ } // switch (tsbk->getLCO())
// add trailing null pad; only if control data isn't being transmitted
if (!m_p25->m_ccRunning) {
@@ -536,6 +569,7 @@ bool Trunk::process(uint8_t* data, uint32_t len, bool preDecoded)
}
m_p25->m_rfState = prevRfState;
+ delete tsbk;
return true;
}
else {
@@ -564,36 +598,34 @@ bool Trunk::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::L
switch (duid) {
case P25_DUID_TSDU:
if (m_p25->m_netState == RS_NET_IDLE) {
- resetRF();
- resetNet();
-
- bool ret = m_netTSBK.decode(data);
- if (!ret) {
+ lc::TSBK *tsbk = lc::tsbk::TSBKFactory::createTSBK(data);
+ if (tsbk == NULL) {
return false;
}
// handle updating internal adjacent site information
- if (m_netTSBK.getLCO() == TSBK_OSP_ADJ_STS_BCAST) {
+ if (tsbk->getLCO() == TSBK_OSP_ADJ_STS_BCAST) {
if (!m_p25->m_control) {
+ delete tsbk;
return false;
}
- if (m_netTSBK.getAdjSiteId() != m_p25->m_siteData.siteId()) {
+ lc::tsbk::OSP_ADJ_STS_BCAST* osp = (lc::tsbk::OSP_ADJ_STS_BCAST*)tsbk;
+ if (osp->getAdjSiteId() != m_p25->m_siteData.siteId()) {
// update site table data
SiteData site;
try {
- site = m_adjSiteTable.at(m_netTSBK.getAdjSiteId());
+ site = m_adjSiteTable.at(osp->getAdjSiteId());
} catch (...) {
site = SiteData();
}
if (m_verbose) {
LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_OSP_ADJ_STS_BCAST (Adjacent Site Status Broadcast), sysId = $%03X, rfss = $%02X, site = $%02X, chId = %u, chNo = %u, svcClass = $%02X",
- m_netTSBK.getAdjSiteSysId(), m_netTSBK.getAdjSiteRFSSId(), m_netTSBK.getAdjSiteId(), m_netTSBK.getAdjSiteChnId(), m_netTSBK.getAdjSiteChnNo(), m_netTSBK.getAdjSiteSvcClass());
+ osp->getAdjSiteSysId(), osp->getAdjSiteRFSSId(), osp->getAdjSiteId(), osp->getAdjSiteChnId(), osp->getAdjSiteChnNo(), osp->getAdjSiteSvcClass());
}
- site.setAdjSite(m_netTSBK.getAdjSiteSysId(), m_netTSBK.getAdjSiteRFSSId(),
- m_netTSBK.getAdjSiteId(), m_netTSBK.getAdjSiteChnId(), m_netTSBK.getAdjSiteChnNo(), m_netTSBK.getAdjSiteSvcClass());
+ site.setAdjSite(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;
@@ -604,7 +636,7 @@ bool Trunk::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::L
// update site table data
SiteData site;
try {
- site = m_sccbTable.at(m_netTSBK.getAdjSiteRFSSId());
+ site = m_sccbTable.at(osp->getAdjSiteRFSSId());
}
catch (...) {
site = SiteData();
@@ -612,29 +644,29 @@ bool Trunk::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::L
if (m_verbose) {
LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_OSP_SCCB_EXP (Secondary Control Channel Broadcast), sysId = $%03X, rfss = $%02X, site = $%02X, chId = %u, chNo = %u, svcClass = $%02X",
- m_netTSBK.getAdjSiteSysId(), m_netTSBK.getAdjSiteRFSSId(), m_netTSBK.getAdjSiteId(), m_netTSBK.getAdjSiteChnId(), m_netTSBK.getAdjSiteChnNo(), m_netTSBK.getAdjSiteSvcClass());
+ osp->getAdjSiteSysId(), osp->getAdjSiteRFSSId(), osp->getAdjSiteId(), osp->getAdjSiteChnId(), osp->getAdjSiteChnNo(), osp->getAdjSiteSvcClass());
}
- site.setAdjSite(m_netTSBK.getAdjSiteSysId(), m_netTSBK.getAdjSiteRFSSId(),
- m_netTSBK.getAdjSiteId(), m_netTSBK.getAdjSiteChnId(), m_netTSBK.getAdjSiteChnNo(), m_netTSBK.getAdjSiteSvcClass());
+ site.setAdjSite(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;
}
+ delete tsbk;
return true;
}
- uint32_t srcId = m_netTSBK.getSrcId();
- uint32_t dstId = m_netTSBK.getDstId();
- uint8_t txMult = m_rfTSBK.getTxMult();
+ uint32_t srcId = tsbk->getSrcId();
+ uint32_t dstId = tsbk->getDstId();
// handle internal DVM TSDUs
- if (m_netTSBK.getMFId() == P25_MFG_DVM) {
- switch (m_netTSBK.getLCO()) {
+ if (tsbk->getMFId() == P25_MFG_DVM) {
+ switch (tsbk->getLCO()) {
case LC_CALL_TERM:
+ {
if (m_p25->m_dedicatedControl) {
- uint32_t chNo = m_netTSBK.getGrpVchNo();
+ uint32_t chNo = tsbk->getGrpVchNo();
if (m_verbose) {
LogMessage(LOG_NET, P25_TSDU_STR ", LC_CALL_TERM (Call Termination), chNo = %u, srcId = %u, dstId = %u", chNo, srcId, dstId);
@@ -645,62 +677,67 @@ bool Trunk::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::L
m_p25->m_affiliations.releaseGrant(dstId, false);
}
}
- break;
+ }
+ break;
default:
- LogError(LOG_NET, P25_TSDU_STR ", unhandled LCO, mfId = $%02X, lco = $%02X", m_netTSBK.getMFId(), m_netTSBK.getLCO());
+ LogError(LOG_NET, P25_TSDU_STR ", unhandled LCO, mfId = $%02X, lco = $%02X", tsbk->getMFId(), tsbk->getLCO());
+ delete tsbk;
return false;
}
- writeNet_TSDU();
-
+ writeNet_TSDU(tsbk);
+
+ delete tsbk;
return true;
}
// handle standard P25 reference opcodes
- switch (m_netTSBK.getLCO()) {
+ switch (tsbk->getLCO()) {
case TSBK_IOSP_GRP_VCH:
+ {
if (m_verbose) {
LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_IOSP_GRP_VCH (Group Voice Channel Grant), emerg = %u, encrypt = %u, prio = %u, chNo = %u, srcId = %u, dstId = %u",
- m_netTSBK.getEmergency(), m_netTSBK.getEncrypted(), m_netTSBK.getPriority(), m_netTSBK.getGrpVchNo(), srcId, dstId);
+ tsbk->getEmergency(), tsbk->getEncrypted(), tsbk->getPriority(), tsbk->getGrpVchNo(), srcId, dstId);
}
+ uint8_t serviceOptions = (tsbk->getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
+ (tsbk->getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
+ (tsbk->getPriority() & 0x07U); // Priority
+
// workaround for single channel dedicated sites to pass network traffic on a lone VC
if (m_p25->m_dedicatedControl && !m_p25->m_voiceOnControl && m_p25->m_affiliations.getRFChCnt() == 1U) {
- m_rfTSBK.setSrcId(srcId);
- m_rfTSBK.setDstId(dstId);
-
- m_rfTSBK.setEmergency(m_netTSBK.getEmergency());
- m_rfTSBK.setEncrypted(m_netTSBK.getEncrypted());
- m_rfTSBK.setPriority(m_netTSBK.getPriority());
-
- writeRF_TSDU_Grant(true);
+ writeRF_TSDU_Grant(srcId, dstId, serviceOptions, true);
}
- return true; // don't allow this to write to the air
+ delete tsbk;
+ }
+ return true; // don't allow this to write to the air
case TSBK_IOSP_UU_VCH:
+ {
if (m_verbose) {
LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_IOSP_UU_VCH (Unit-to-Unit Voice Channel Grant), emerg = %u, encrypt = %u, prio = %u, chNo = %u, srcId = %u, dstId = %u",
- m_netTSBK.getEmergency(), m_netTSBK.getEncrypted(), m_netTSBK.getPriority(), m_netTSBK.getGrpVchNo(), srcId, dstId);
+ tsbk->getEmergency(), tsbk->getEncrypted(), tsbk->getPriority(), tsbk->getGrpVchNo(), srcId, dstId);
}
+ uint8_t serviceOptions = (tsbk->getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
+ (tsbk->getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
+ (tsbk->getPriority() & 0x07U); // Priority
+
// workaround for single channel dedicated sites to pass network traffic on a lone VC
if (m_p25->m_dedicatedControl && !m_p25->m_voiceOnControl && m_p25->m_affiliations.getRFChCnt() == 1U) {
- m_rfTSBK.setSrcId(srcId);
- m_rfTSBK.setDstId(dstId);
-
- m_rfTSBK.setEmergency(m_netTSBK.getEmergency());
- m_rfTSBK.setEncrypted(m_netTSBK.getEncrypted());
- m_rfTSBK.setPriority(m_netTSBK.getPriority());
-
- writeRF_TSDU_Grant(false);
+ writeRF_TSDU_Grant(srcId, dstId, serviceOptions, false);
}
- return true; // don't allow this to write to the air
+ delete tsbk;
+ }
+ return true; // don't allow this to write to the air
case TSBK_IOSP_UU_ANS:
- if (m_netTSBK.getResponse() > 0U) {
+ {
+ lc::tsbk::IOSP_UU_ANS* iosp = (lc::tsbk::IOSP_UU_ANS*)tsbk;
+ if (iosp->getResponse() > 0U) {
if (m_verbose) {
LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_IOSP_UU_ANS (Unit-to-Unit Answer Response), response = $%02X, srcId = %u, dstId = %u",
- m_netTSBK.getResponse(), srcId, dstId);
+ iosp->getResponse(), srcId, dstId);
}
}
else {
@@ -708,45 +745,56 @@ bool Trunk::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::L
LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_IOSP_UU_ANS (Unit-to-Unit Answer Request), srcId = %u, dstId = %u", srcId, dstId);
}
}
- break;
+ }
+ break;
case TSBK_IOSP_STS_UPDT:
+ {
// validate the source RID
VALID_SRCID_NET("TSBK_IOSP_STS_UPDT (Status Update)", srcId);
+ lc::tsbk::IOSP_STS_UPDT* iosp = (lc::tsbk::IOSP_STS_UPDT*)tsbk;
if (m_verbose) {
LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_IOSP_STS_UPDT (Status Update), status = $%02X, srcId = %u",
- m_netTSBK.getStatus(), srcId);
+ iosp->getStatus(), srcId);
}
::ActivityLog("P25", false, "status update from %u", srcId);
- break;
+ }
+ break;
case TSBK_IOSP_MSG_UPDT:
+ {
// validate the source RID
VALID_SRCID_NET("TSBK_IOSP_MSG_UPDT (Message Update)", srcId);
+ lc::tsbk::IOSP_MSG_UPDT* iosp = (lc::tsbk::IOSP_MSG_UPDT*)tsbk;
if (m_verbose) {
LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_IOSP_MSG_UPDT (Message Update), message = $%02X, srcId = %u, dstId = %u",
- m_netTSBK.getMessage(), srcId, dstId);
+ iosp->getMessage(), srcId, dstId);
}
::ActivityLog("P25", false, "message update from %u", srcId);
- break;
- case TSBK_ISP_RAD_MON_REQ:
+ }
+ break;
+ case TSBK_IOSP_RAD_MON:
+ {
// validate the source RID
- VALID_SRCID("TSBK_ISP_RAD_MON_REQ (Radio Monitor)" , TSBK_ISP_RAD_MON_REQ , srcId);
+ VALID_SRCID("TSBK_ISP_RAD_MON_REQ (Radio Monitor)", TSBK_IOSP_RAD_MON, srcId);
// validate the target RID
- VALID_DSTID("TSBK_ISP_RAD_MON_REQ (Radio monitor)" , TSBK_ISP_RAD_MON_REQ , dstId);
+ VALID_DSTID("TSBK_ISP_RAD_MON_REQ (Radio monitor)", TSBK_IOSP_RAD_MON, srcId, dstId);
- if ( m_verbose ) {
+ lc::tsbk::IOSP_RAD_MON* iosp = (lc::tsbk::IOSP_RAD_MON*)tsbk;
+ if (m_verbose) {
LogMessage(LOG_RF , P25_TSDU_STR ", TSBK_ISP_RAD_MON_REQ (Radio Monitor), srcId = %u, dstId = %u" , srcId , dstId);
}
::ActivityLog("P25" , true , "radio monitor request from %u to %u" , srcId , dstId);
- writeRF_TSDU_Radio_Mon(srcId , dstId , txMult);
- break;
+ writeRF_TSDU_Radio_Mon(srcId , dstId , iosp->getTxMult());
+ }
+ break;
case TSBK_IOSP_CALL_ALRT:
+ {
// validate the source RID
VALID_SRCID_NET("TSBK_IOSP_CALL_ALRT (Call Alert)", srcId);
@@ -764,33 +812,43 @@ bool Trunk::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::L
}
::ActivityLog("P25", false, "call alert request from %u to %u", srcId, dstId);
- break;
+ }
+ break;
case TSBK_IOSP_ACK_RSP:
+ {
// validate the source RID
VALID_SRCID_NET("TSBK_IOSP_ACK_RSP (Acknowledge Response)", srcId);
// validate the target RID
VALID_DSTID_NET("TSBK_IOSP_ACK_RSP (Acknowledge Response)", dstId);
+ lc::tsbk::IOSP_ACK_RSP* iosp = (lc::tsbk::IOSP_ACK_RSP*)tsbk;
if (m_verbose) {
LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_IOSP_ACK_RSP (Acknowledge Response), AIV = %u, serviceType = $%02X, srcId = %u, dstId = %u",
- m_netTSBK.getAIV(), m_netTSBK.getService(), dstId, srcId);
+ iosp->getAIV(), iosp->getService(), dstId, srcId);
}
::ActivityLog("P25", false, "ack response from %u to %u", srcId, dstId);
- break;
+ }
+ break;
case TSBK_IOSP_EXT_FNCT:
+ {
// validate the target RID
VALID_DSTID_NET("TSBK_IOSP_EXT_FNCT (Extended Function)", dstId);
+ lc::tsbk::IOSP_EXT_FNCT* iosp = (lc::tsbk::IOSP_EXT_FNCT*)tsbk;
if (m_verbose) {
LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_IOSP_EXT_FNCT (Extended Function), serviceType = $%02X, arg = %u, tgt = %u",
- m_netTSBK.getService(), srcId, dstId);
+ iosp->getService(), srcId, dstId);
}
- break;
+ }
+ break;
case TSBK_ISP_EMERG_ALRM_REQ:
+ {
+ lc::tsbk::ISP_EMERG_ALRM_REQ* isp = (lc::tsbk::ISP_EMERG_ALRM_REQ*)tsbk;
+
// non-emergency mode is a TSBK_OSP_DENY_RSP
- if (!m_netTSBK.getEmergency()) {
+ if (!isp->getEmergency()) {
// ignore a network deny command
return true; // don't allow this to write to the air
} else {
@@ -804,25 +862,32 @@ bool Trunk::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::L
return true; // don't allow this to write to the air
}
}
- break;
+ }
+ break;
case TSBK_IOSP_GRP_AFF:
// ignore a network group affiliation command
+ delete tsbk;
return true; // don't allow this to write to the air
case TSBK_OSP_U_DEREG_ACK:
// ignore a network user deregistration command
+ delete tsbk;
return true; // don't allow this to write to the air
case TSBK_OSP_LOC_REG_RSP:
// ignore a network location registration command
+ delete tsbk;
return true; // don't allow this to write to the air
case TSBK_OSP_QUE_RSP:
// ignore a network queue command
+ delete tsbk;
return true; // don't allow this to write to the air
default:
- LogError(LOG_NET, P25_TSDU_STR ", unhandled LCO, mfId = $%02X, lco = $%02X", m_netTSBK.getMFId(), m_netTSBK.getLCO());
+ LogError(LOG_NET, P25_TSDU_STR ", unhandled LCO, mfId = $%02X, lco = $%02X", tsbk->getMFId(), tsbk->getLCO());
+ delete tsbk;
return false;
- } // switch (m_netTSBK.getLCO())
+ } // switch (tsbk->getLCO())
- writeNet_TSDU();
+ writeNet_TSDU(tsbk);
+ delete tsbk;
}
break;
default:
@@ -842,9 +907,9 @@ bool Trunk::processMBT(DataHeader dataHeader, DataBlock* blocks)
uint8_t data[1U];
::memset(data, 0x00U, 1U);
- bool mbtDecode = m_rfTSBK.decodeMBT(dataHeader, blocks);
- if (mbtDecode) {
- return process(data, 1U, true);
+ lc::AMBT* ambt = lc::tsbk::TSBKFactory::createAMBT(dataHeader, blocks);
+ if (ambt != NULL) {
+ return process(data, 1U, ambt);
} else {
return false;
}
@@ -859,9 +924,6 @@ void Trunk::writeAdjSSNetwork()
return;
}
- resetRF();
- resetNet();
-
if (m_network != NULL) {
if (m_verbose) {
LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_OSP_ADJ_STS_BCAST (Adjacent Site Status Broadcast), network announce, sysId = $%03X, rfss = $%02X, site = $%02X, chId = %u, chNo = %u, svcClass = $%02X",
@@ -874,16 +936,18 @@ void Trunk::writeAdjSSNetwork()
}
// transmit adjacent site broadcast
- m_rfTSBK.setLCO(TSBK_OSP_ADJ_STS_BCAST);
- m_rfTSBK.setAdjSiteCFVA(cfva);
- m_rfTSBK.setAdjSiteSysId(m_p25->m_siteData.sysId());
- m_rfTSBK.setAdjSiteRFSSId(m_p25->m_siteData.rfssId());
- m_rfTSBK.setAdjSiteId(m_p25->m_siteData.siteId());
- m_rfTSBK.setAdjSiteChnId(m_p25->m_siteData.channelId());
- m_rfTSBK.setAdjSiteChnNo(m_p25->m_siteData.channelNo());
- m_rfTSBK.setAdjSiteSvcClass(m_p25->m_siteData.serviceClass());
-
- RF_TO_WRITE_NET();
+ lc::tsbk::OSP_ADJ_STS_BCAST *osp = new lc::tsbk::OSP_ADJ_STS_BCAST();
+ osp->setSrcId(P25_WUID_FNE);
+ osp->setAdjSiteCFVA(cfva);
+ osp->setAdjSiteSysId(m_p25->m_siteData.sysId());
+ osp->setAdjSiteRFSSId(m_p25->m_siteData.rfssId());
+ osp->setAdjSiteId(m_p25->m_siteData.siteId());
+ osp->setAdjSiteChnId(m_p25->m_siteData.channelId());
+ osp->setAdjSiteChnNo(m_p25->m_siteData.channelNo());
+ osp->setAdjSiteSvcClass(m_p25->m_siteData.serviceClass());
+
+ RF_TO_WRITE_NET(osp);
+ delete osp;
}
}
@@ -903,11 +967,7 @@ void Trunk::clock(uint32_t ms)
// do we have a grant response?
if (m_p25->m_network->readGrantRsp(grp, srcId, dstId, grpVchNo)) {
- m_rfTSBK.setSrcId(srcId);
- m_rfTSBK.setDstId(dstId);
- m_rfTSBK.setGrpVchNo(grpVchNo);
-
- writeRF_TSDU_Grant(grp, true, true, true);
+ writeRF_TSDU_Grant(srcId, dstId, 4U, grp, true, grpVchNo, true, true);
}
}
}
@@ -973,10 +1033,12 @@ void Trunk::writeRF_TSDU_Call_Alrt(uint32_t srcId, uint32_t dstId)
::ActivityLog("P25", true, "call alert request from %u to %u", srcId, dstId);
- m_rfTSBK.setLCO(TSBK_IOSP_CALL_ALRT);
- m_rfTSBK.setSrcId(srcId);
- m_rfTSBK.setDstId(dstId);
- writeRF_TSDU_SBF(false);
+ lc::tsbk::IOSP_CALL_ALRT *iosp = new lc::tsbk::IOSP_CALL_ALRT();
+ iosp->setSrcId(srcId);
+ iosp->setDstId(dstId);
+
+ writeRF_TSDU_SBF(iosp, false);
+ delete iosp;
}
///
@@ -984,20 +1046,22 @@ void Trunk::writeRF_TSDU_Call_Alrt(uint32_t srcId, uint32_t dstId)
///
///
///
-///
-void Trunk::writeRF_TSDU_Radio_Mon(uint32_t srcId, uint32_t dstId, uint8_t txmult)
+///
+void Trunk::writeRF_TSDU_Radio_Mon(uint32_t srcId, uint32_t dstId, uint8_t txMult)
{
if (m_verbose) {
- LogMessage(LOG_RF , P25_TSDU_STR ", TSBK_OSP_RAD_MON_CMD (Radio monitor), srcId = %u, dstId = %u, txmult = %u" , srcId, dstId, txmult);
+ LogMessage(LOG_RF , P25_TSDU_STR ", TSBK_OSP_RAD_MON_CMD (Radio monitor), srcId = %u, dstId = %u, txMult = %u" , srcId, dstId, txMult);
}
::ActivityLog("P25" , true , "Radio Unit Monitor request from %u to %u" , srcId , dstId);
- m_rfTSBK.setLCO(TSBK_OSP_RAD_MON_CMD);
- m_rfTSBK.setSrcId(srcId);
- m_rfTSBK.setDstId(dstId);
- m_rfTSBK.setTxMult(txmult);
- writeRF_TSDU_SBF(false);
+ lc::tsbk::IOSP_RAD_MON *iosp = new lc::tsbk::IOSP_RAD_MON();
+ iosp->setSrcId(srcId);
+ iosp->setDstId(dstId);
+ iosp->setTxMult(txMult);
+
+ writeRF_TSDU_SBF(iosp, false);
+ delete iosp;
}
///
@@ -1008,19 +1072,14 @@ void Trunk::writeRF_TSDU_Radio_Mon(uint32_t srcId, uint32_t dstId, uint8_t txmul
///
void Trunk::writeRF_TSDU_Ext_Func(uint32_t func, uint32_t arg, uint32_t dstId)
{
- uint8_t lco = m_rfTSBK.getLCO();
- uint8_t mfId = m_rfTSBK.getMFId();
-
- m_rfTSBK.setMFId(P25_MFG_STANDARD);
-
- m_rfTSBK.setLCO(TSBK_IOSP_EXT_FNCT);
- m_rfTSBK.setExtendedFunction(func);
- m_rfTSBK.setSrcId(arg);
- m_rfTSBK.setDstId(dstId);
+ lc::tsbk::IOSP_EXT_FNCT *iosp = new lc::tsbk::IOSP_EXT_FNCT();
+ iosp->setExtendedFunction(func);
+ iosp->setSrcId(arg);
+ iosp->setDstId(dstId);
if (m_verbose) {
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_EXT_FNCT (Extended Function), op = $%02X, arg = %u, tgt = %u",
- m_rfTSBK.getExtendedFunction(), m_rfTSBK.getSrcId(), m_rfTSBK.getDstId());
+ iosp->getExtendedFunction(), iosp->getSrcId(), iosp->getDstId());
}
// generate activity log entry
@@ -1034,10 +1093,8 @@ void Trunk::writeRF_TSDU_Ext_Func(uint32_t func, uint32_t arg, uint32_t dstId)
::ActivityLog("P25", true, "radio uninhibit request from %u to %u", arg, dstId);
}
- writeRF_TSDU_SBF(false);
-
- m_rfTSBK.setLCO(lco);
- m_rfTSBK.setMFId(mfId);
+ writeRF_TSDU_SBF(iosp, false);
+ delete iosp;
}
///
@@ -1052,10 +1109,12 @@ void Trunk::writeRF_TSDU_Grp_Aff_Q(uint32_t dstId)
::ActivityLog("P25", true, "group affiliation query command from %u to %u", P25_WUID_FNE, dstId);
- m_rfTSBK.setLCO(TSBK_OSP_GRP_AFF_Q);
- m_rfTSBK.setSrcId(P25_WUID_FNE);
- m_rfTSBK.setDstId(dstId);
- writeRF_TSDU_SBF(true);
+ lc::tsbk::OSP_GRP_AFF_Q *osp = new lc::tsbk::OSP_GRP_AFF_Q();
+ osp->setSrcId(P25_WUID_FNE);
+ osp->setDstId(dstId);
+
+ writeRF_TSDU_SBF(osp, true);
+ delete osp;
}
///
@@ -1070,10 +1129,12 @@ void Trunk::writeRF_TSDU_U_Reg_Cmd(uint32_t dstId)
::ActivityLog("P25", true, "unit registration command from %u to %u", P25_WUID_FNE, dstId);
- m_rfTSBK.setLCO(TSBK_OSP_U_REG_CMD);
- m_rfTSBK.setSrcId(P25_WUID_FNE);
- m_rfTSBK.setDstId(dstId);
- writeRF_TSDU_SBF(true);
+ lc::tsbk::OSP_U_REG_CMD *osp = new lc::tsbk::OSP_U_REG_CMD();
+ osp->setSrcId(P25_WUID_FNE);
+ osp->setDstId(dstId);
+
+ writeRF_TSDU_SBF(osp, true);
+ delete osp;
}
///
@@ -1087,53 +1148,17 @@ void Trunk::writeRF_TSDU_Emerg_Alrm(uint32_t srcId, uint32_t dstId)
return;
}
- uint8_t lco = m_rfTSBK.getLCO();
- uint32_t _srcId = m_rfTSBK.getSrcId();
-
- m_rfTSBK.setLCO(TSBK_ISP_EMERG_ALRM_REQ);
- m_rfTSBK.setSrcId(P25_WUID_FNE);
- m_rfTSBK.setService(0U);
- m_rfTSBK.setResponse(0U);
-
- m_rfTSBK.setSrcId(srcId);
- m_rfTSBK.setDstId(dstId);
+ lc::tsbk::ISP_EMERG_ALRM_REQ *isp = new lc::tsbk::ISP_EMERG_ALRM_REQ();
+ isp->setSrcId(srcId);
+ isp->setDstId(dstId);
if (m_verbose) {
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_ISP_EMERG_ALRM_REQ (Emergency Alarm Request), srcId = %u, dstId = %u",
srcId, dstId);
}
- writeRF_TSDU_SBF(true);
-
- m_rfTSBK.setLCO(lco);
- m_rfTSBK.setSrcId(_srcId);
-}
-
-///
-/// Helper to write a Motorola patch packet.
-///
-///
-///
-///
-void Trunk::writeRF_TSDU_Mot_Patch(uint32_t group1, uint32_t group2, uint32_t group3)
-{
- uint8_t lco = m_rfTSBK.getLCO();
-
- if (m_verbose) {
- LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_OSP_MOT_GRG_ADD (Group Regroup Add - Patch Supergroup), superGrp = %u, group1 = %u, group2 = %u, group3 = %u",
- m_patchSuperGroup, group1, group2, group3);
- }
-
- m_rfTSBK.setLCO(TSBK_OSP_MOT_GRG_ADD);
- m_rfTSBK.setMFId(P25_MFG_MOT);
- m_rfTSBK.setPatchSuperGroupId(m_patchSuperGroup);
- m_rfTSBK.setPatchGroup1Id(group1);
- m_rfTSBK.setPatchGroup2Id(group2);
- m_rfTSBK.setPatchGroup3Id(group3);
- writeRF_TSDU_SBF(true);
-
- m_rfTSBK.setLCO(lco);
- m_rfTSBK.setMFId(P25_MFG_STANDARD);
+ writeRF_TSDU_SBF(isp, true);
+ delete isp;
}
///
@@ -1145,17 +1170,14 @@ void Trunk::setConvFallback(bool fallback)
m_convFallback = fallback;
if (m_convFallback && m_p25->m_control) {
m_convFallbackPacketDelay = 0U;
- uint8_t lco = m_rfTSBK.getLCO();
- m_rfTSBK.setLCO(TSBK_OSP_MOT_PSH_CCH);
- m_rfTSBK.setMFId(P25_MFG_MOT);
+ lc::tsbk::OSP_MOT_PSH_CCH *osp = new lc::tsbk::OSP_MOT_PSH_CCH();
for (uint8_t i = 0U; i < 3U; i++) {
- writeRF_TSDU_SBF(true);
+ writeRF_TSDU_SBF(osp, true);
}
- m_rfTSBK.setLCO(lco);
- m_rfTSBK.setMFId(P25_MFG_STANDARD);
+ delete osp;
}
}
@@ -1166,6 +1188,7 @@ void Trunk::setConvFallback(bool fallback)
void Trunk::setTSBKVerbose(bool verbose)
{
m_dumpTSBK = verbose;
+ lc::TSBK::setVerbose(verbose);
}
// ---------------------------------------------------------------------------
@@ -1186,8 +1209,6 @@ Trunk::Trunk(Control* p25, network::BaseNetwork* network, bool dumpTSBKData, boo
m_patchSuperGroup(0xFFFFU),
m_verifyAff(false),
m_verifyReg(false),
- m_rfTSBK(SiteData(), ::lookups::IdenTable()),
- m_netTSBK(SiteData(), ::lookups::IdenTable()),
m_rfMBF(NULL),
m_mbfCnt(0U),
m_mbfIdenCnt(0U),
@@ -1238,9 +1259,38 @@ Trunk::~Trunk()
///
/// Write data processed from RF to the network.
///
+///
+///
+///
+void Trunk::writeNetworkRF(lc::TSBK* tsbk, const uint8_t* data, bool autoReset)
+{
+ assert(tsbk != NULL);
+ assert(data != NULL);
+
+ if (m_network == NULL)
+ return;
+
+ if (m_p25->m_rfTimeout.isRunning() && m_p25->m_rfTimeout.hasExpired())
+ return;
+
+ lc::LC lc = lc::LC();
+ lc.setLCO(tsbk->getLCO());
+ lc.setMFId(tsbk->getMFId());
+ lc.setSrcId(tsbk->getSrcId());
+ lc.setDstId(tsbk->getDstId());
+
+ m_network->writeP25TSDU(lc, data);
+ if (autoReset)
+ m_network->resetP25();
+}
+
+///
+/// Write data processed from RF to the network.
+///
+///
///
///
-void Trunk::writeNetworkRF(const uint8_t* data, bool autoReset)
+void Trunk::writeNetworkRF(lc::TDULC& tduLc, const uint8_t* data, bool autoReset)
{
assert(data != NULL);
@@ -1250,7 +1300,13 @@ void Trunk::writeNetworkRF(const uint8_t* data, bool autoReset)
if (m_p25->m_rfTimeout.isRunning() && m_p25->m_rfTimeout.hasExpired())
return;
- m_network->writeP25TSDU(m_rfTSBK, data);
+ lc::LC lc = lc::LC();
+ lc.setLCO(tduLc.getLCO());
+ lc.setMFId(tduLc.getMFId());
+ lc.setSrcId(tduLc.getSrcId());
+ lc.setDstId(tduLc.getDstId());
+
+ m_network->writeP25TSDU(lc, data);
if (autoReset)
m_network->resetP25();
}
@@ -1266,13 +1322,11 @@ void Trunk::writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adjSS)
if (!m_p25->m_control)
return;
- resetRF();
-
if (m_convFallback) {
bool fallbackTx = (frameCnt % 253U) == 0U;
if (fallbackTx && n == 7U) {
if (m_convFallbackPacketDelay >= CONV_FALLBACK_PACKET_DELAY) {
- lc::TDULC lc = lc::TDULC(m_p25->m_siteData, m_p25->m_idenEntry, m_dumpTSBK);
+ lc::TDULC lc = lc::TDULC();
lc.setLCO(LC_CONV_FALLBACK);
for (uint8_t i = 0U; i < 3U; i++) {
@@ -1425,7 +1479,7 @@ void Trunk::writeRF_TDULC(lc::TDULC lc, bool noNetwork)
m_p25->m_rfTimeout.stop();
if (!noNetwork)
- writeNetworkRF(data + 2U, P25_DUID_TDULC);
+ writeNetworkRF(lc, data + 2U, P25_DUID_TDULC);
if (m_p25->m_duplex) {
data[0U] = modem::TAG_EOT;
@@ -1439,6 +1493,53 @@ void Trunk::writeRF_TDULC(lc::TDULC lc, bool noNetwork)
//}
}
+///
+/// Helper to write a network P25 TDU w/ link control packet.
+///
+///
+void Trunk::writeNet_TDULC(lc::TDULC lc)
+{
+ uint8_t buffer[P25_TDULC_FRAME_LENGTH_BYTES + 2U];
+ ::memset(buffer, 0x00U, P25_TDULC_FRAME_LENGTH_BYTES + 2U);
+
+ buffer[0U] = modem::TAG_EOT;
+ buffer[1U] = 0x00U;
+
+ // Generate Sync
+ Sync::addP25Sync(buffer + 2U);
+
+ // Generate NID
+ m_p25->m_nid.encode(buffer + 2U, P25_DUID_TDULC);
+
+ // Regenerate TDULC Data
+ lc.encode(buffer + 2U);
+
+ // Add busy bits
+ m_p25->addBusyBits(buffer + 2U, P25_TDULC_FRAME_LENGTH_BITS, true, true);
+
+ m_p25->addFrame(buffer, P25_TDULC_FRAME_LENGTH_BYTES + 2U, true);
+
+ if (m_verbose) {
+ LogMessage(LOG_NET, P25_TDULC_STR ", lc = $%02X, srcId = %u", lc.getLCO(), lc.getSrcId());
+ }
+
+ if (m_p25->m_voice->m_netFrames > 0) {
+ ::ActivityLog("P25", false, "network end of transmission, %.1f seconds, %u%% packet loss",
+ float(m_p25->m_voice->m_netFrames) / 50.0F, (m_p25->m_voice->m_netLost * 100U) / m_p25->m_voice->m_netFrames);
+ }
+ else {
+ ::ActivityLog("P25", false, "network end of transmission, %u frames", m_p25->m_voice->m_netFrames);
+ }
+
+ if (m_network != NULL)
+ m_network->resetP25();
+
+ m_p25->m_netTimeout.stop();
+ m_p25->m_networkWatchdog.stop();
+ m_p25->m_netState = RS_NET_IDLE;
+ m_p25->m_tailOnIdle = true;
+}
+
///
/// Helper to write a P25 TDU w/ link control channel release packet.
///
@@ -1452,7 +1553,7 @@ void Trunk::writeRF_TDULC_ChanRelease(bool grp, uint32_t srcId, uint32_t dstId)
}
uint32_t count = m_p25->m_hangCount / 2;
- lc::TDULC lc = lc::TDULC(m_p25->m_siteData, m_p25->m_idenEntry, m_dumpTSBK);
+ lc::TDULC lc = lc::TDULC();
if (m_p25->m_control) {
for (uint32_t i = 0; i < count; i++) {
@@ -1493,14 +1594,17 @@ void Trunk::writeRF_TDULC_ChanRelease(bool grp, uint32_t srcId, uint32_t dstId)
///
/// Helper to write a single-block P25 TSDU packet.
///
+///
///
///
///
-void Trunk::writeRF_TSDU_SBF(bool noNetwork, bool clearBeforeWrite, bool force)
+void Trunk::writeRF_TSDU_SBF(lc::TSBK* tsbk, bool noNetwork, bool clearBeforeWrite, bool force)
{
if (!m_p25->m_control)
return;
+ assert(tsbk != NULL);
+
uint8_t data[P25_TSDU_FRAME_LENGTH_BYTES + 2U];
::memset(data + 2U, 0x00U, P25_TSDU_FRAME_LENGTH_BYTES);
@@ -1511,13 +1615,13 @@ void Trunk::writeRF_TSDU_SBF(bool noNetwork, bool clearBeforeWrite, bool force)
m_p25->m_nid.encode(data + 2U, P25_DUID_TSDU);
// Generate TSBK block
- m_rfTSBK.setLastBlock(true); // always set last block -- this a Single Block TSDU
- m_rfTSBK.encode(data + 2U);
+ tsbk->setLastBlock(true); // always set last block -- this a Single Block TSDU
+ tsbk->encode(data + 2U);
if (m_debug) {
LogDebug(LOG_RF, P25_TSDU_STR ", lco = $%02X, mfId = $%02X, lastBlock = %u, AIV = %u, EX = %u, srcId = %u, dstId = %u, sysId = $%03X, netId = $%05X",
- m_rfTSBK.getLCO(), m_rfTSBK.getMFId(), m_rfTSBK.getLastBlock(), m_rfTSBK.getAIV(), m_rfTSBK.getEX(), m_rfTSBK.getSrcId(), m_rfTSBK.getDstId(),
- m_rfTSBK.getSysId(), m_rfTSBK.getNetId());
+ tsbk->getLCO(), tsbk->getMFId(), tsbk->getLastBlock(), tsbk->getAIV(), tsbk->getEX(), tsbk->getSrcId(), tsbk->getDstId(),
+ tsbk->getSysId(), tsbk->getNetId());
Utils::dump(1U, "!!! *TSDU (SBF) TSBK Block Data", data + P25_PREAMBLE_LENGTH_BYTES + 2U, P25_TSBK_FEC_LENGTH_BYTES);
}
@@ -1529,16 +1633,16 @@ void Trunk::writeRF_TSDU_SBF(bool noNetwork, bool clearBeforeWrite, bool force)
m_p25->setBusyBits(data + 2U, P25_SS0_START, true, true);
if (!noNetwork)
- writeNetworkRF(data + 2U, true);
+ writeNetworkRF(tsbk, data + 2U, true);
if (!force) {
if (m_p25->m_dedicatedControl && m_ctrlTSDUMBF) {
- writeRF_TSDU_MBF(clearBeforeWrite);
+ writeRF_TSDU_MBF(tsbk, clearBeforeWrite);
return;
}
if (m_p25->m_ccRunning && m_ctrlTSDUMBF) {
- writeRF_TSDU_MBF(clearBeforeWrite);
+ writeRF_TSDU_MBF(tsbk, clearBeforeWrite);
return;
}
@@ -1556,11 +1660,49 @@ void Trunk::writeRF_TSDU_SBF(bool noNetwork, bool clearBeforeWrite, bool force)
}
}
+
+///
+/// Helper to write a network single-block P25 TSDU packet.
+///
+///
+void Trunk::writeNet_TSDU(lc::TSBK* tsbk)
+{
+ assert(tsbk != NULL);
+
+ uint8_t buffer[P25_TSDU_FRAME_LENGTH_BYTES + 2U];
+ ::memset(buffer, 0x00U, P25_TSDU_FRAME_LENGTH_BYTES + 2U);
+
+ buffer[0U] = modem::TAG_DATA;
+ buffer[1U] = 0x00U;
+
+ // Generate Sync
+ Sync::addP25Sync(buffer + 2U);
+
+ // Generate NID
+ m_p25->m_nid.encode(buffer + 2U, P25_DUID_TSDU);
+
+ // Regenerate TSDU Data
+ tsbk->setLastBlock(true); // always set last block -- this a Single Block TSDU
+ tsbk->encode(buffer + 2U);
+
+ // Add busy bits
+ m_p25->addBusyBits(buffer + 2U, P25_TSDU_FRAME_LENGTH_BYTES, true, false);
+
+ // Set first busy bits to 1,1
+ m_p25->setBusyBits(buffer + 2U, P25_SS0_START, true, true);
+
+ m_p25->addFrame(buffer, P25_TSDU_FRAME_LENGTH_BYTES + 2U, true);
+
+ if (m_network != NULL)
+ m_network->resetP25();
+}
+
///
/// Helper to write a multi-block (3-block) P25 TSDU packet.
///
+///
///
-void Trunk::writeRF_TSDU_MBF(bool clearBeforeWrite)
+void Trunk::writeRF_TSDU_MBF(lc::TSBK* tsbk, bool clearBeforeWrite)
{
if (!m_p25->m_control) {
::memset(m_rfMBF, 0x00U, P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U);
@@ -1568,8 +1710,10 @@ void Trunk::writeRF_TSDU_MBF(bool clearBeforeWrite)
return;
}
- uint8_t tsbk[P25_TSBK_FEC_LENGTH_BYTES];
- ::memset(tsbk, 0x00U, P25_TSBK_FEC_LENGTH_BYTES);
+ assert(tsbk != NULL);
+
+ uint8_t frame[P25_TSBK_FEC_LENGTH_BYTES];
+ ::memset(frame, 0x00U, P25_TSBK_FEC_LENGTH_BYTES);
// LogDebug(LOG_P25, "writeRF_TSDU_MBF, mbfCnt = %u", m_mbfCnt);
@@ -1587,18 +1731,18 @@ void Trunk::writeRF_TSDU_MBF(bool clearBeforeWrite)
// trigger encoding of last block and write to queue
if (m_mbfCnt + 1U == TSBK_MBF_CNT) {
// Generate TSBK block
- m_rfTSBK.setLastBlock(true); // set last block
- m_rfTSBK.encode(tsbk, true);
+ tsbk->setLastBlock(true); // set last block
+ tsbk->encode(frame, true);
if (m_debug) {
LogDebug(LOG_RF, P25_TSDU_STR " (MBF), lco = $%02X, mfId = $%02X, lastBlock = %u, AIV = %u, EX = %u, srcId = %u, dstId = %u, sysId = $%03X, netId = $%05X",
- m_rfTSBK.getLCO(), m_rfTSBK.getMFId(), m_rfTSBK.getLastBlock(), m_rfTSBK.getAIV(), m_rfTSBK.getEX(), m_rfTSBK.getSrcId(), m_rfTSBK.getDstId(),
- m_rfTSBK.getSysId(), m_rfTSBK.getNetId());
+ tsbk->getLCO(), tsbk->getMFId(), tsbk->getLastBlock(), tsbk->getAIV(), tsbk->getEX(), tsbk->getSrcId(), tsbk->getDstId(),
+ tsbk->getSysId(), tsbk->getNetId());
- Utils::dump(1U, "!!! *TSDU MBF Last TSBK Block", tsbk, P25_TSBK_FEC_LENGTH_BYTES);
+ Utils::dump(1U, "!!! *TSDU MBF Last TSBK Block", frame, P25_TSBK_FEC_LENGTH_BYTES);
}
- Utils::setBitRange(tsbk, m_rfMBF, (m_mbfCnt * P25_TSBK_FEC_LENGTH_BITS), P25_TSBK_FEC_LENGTH_BITS);
+ Utils::setBitRange(frame, m_rfMBF, (m_mbfCnt * P25_TSBK_FEC_LENGTH_BITS), P25_TSBK_FEC_LENGTH_BITS);
// Generate TSDU frame
uint8_t tsdu[P25_TSDU_TRIPLE_FRAME_LENGTH_BYTES];
@@ -1606,19 +1750,19 @@ void Trunk::writeRF_TSDU_MBF(bool clearBeforeWrite)
uint32_t offset = 0U;
for (uint8_t i = 0U; i < m_mbfCnt + 1U; i++) {
- ::memset(tsbk, 0x00U, P25_TSBK_FEC_LENGTH_BYTES);
- Utils::getBitRange(m_rfMBF, tsbk, offset, P25_TSBK_FEC_LENGTH_BITS);
+ ::memset(frame, 0x00U, P25_TSBK_FEC_LENGTH_BYTES);
+ Utils::getBitRange(m_rfMBF, frame, offset, P25_TSBK_FEC_LENGTH_BITS);
if (m_debug) {
LogDebug(LOG_RF, P25_TSDU_STR " (MBF), lco = $%02X, mfId = $%02X, lastBlock = %u, AIV = %u, EX = %u, srcId = %u, dstId = %u, sysId = $%03X, netId = $%05X",
- m_rfTSBK.getLCO(), m_rfTSBK.getMFId(), m_rfTSBK.getLastBlock(), m_rfTSBK.getAIV(), m_rfTSBK.getEX(), m_rfTSBK.getSrcId(), m_rfTSBK.getDstId(),
- m_rfTSBK.getSysId(), m_rfTSBK.getNetId());
+ tsbk->getLCO(), tsbk->getMFId(), tsbk->getLastBlock(), tsbk->getAIV(), tsbk->getEX(), tsbk->getSrcId(), tsbk->getDstId(),
+ tsbk->getSysId(), tsbk->getNetId());
- Utils::dump(1U, "!!! *TSDU (MBF) TSBK Block", tsbk, P25_TSBK_FEC_LENGTH_BYTES);
+ Utils::dump(1U, "!!! *TSDU (MBF) TSBK Block", frame, P25_TSBK_FEC_LENGTH_BYTES);
}
// Add TSBK data
- Utils::setBitRange(tsbk, tsdu, offset, P25_TSBK_FEC_LENGTH_BITS);
+ Utils::setBitRange(frame, tsdu, offset, P25_TSBK_FEC_LENGTH_BITS);
offset += P25_TSBK_FEC_LENGTH_BITS;
}
@@ -1659,37 +1803,40 @@ void Trunk::writeRF_TSDU_MBF(bool clearBeforeWrite)
}
// Generate TSBK block
- m_rfTSBK.setLastBlock(false); // clear last block
- m_rfTSBK.encode(tsbk, true);
+ tsbk->setLastBlock(false); // clear last block
+ tsbk->encode(frame, true);
if (m_debug) {
LogDebug(LOG_RF, P25_TSDU_STR " (MBF), lco = $%02X, mfId = $%02X, lastBlock = %u, AIV = %u, EX = %u, srcId = %u, dstId = %u, sysId = $%03X, netId = $%05X",
- m_rfTSBK.getLCO(), m_rfTSBK.getMFId(), m_rfTSBK.getLastBlock(), m_rfTSBK.getAIV(), m_rfTSBK.getEX(), m_rfTSBK.getSrcId(), m_rfTSBK.getDstId(),
- m_rfTSBK.getSysId(), m_rfTSBK.getNetId());
+ tsbk->getLCO(), tsbk->getMFId(), tsbk->getLastBlock(), tsbk->getAIV(), tsbk->getEX(), tsbk->getSrcId(), tsbk->getDstId(),
+ tsbk->getSysId(), tsbk->getNetId());
- Utils::dump(1U, "!!! *TSDU MBF Block Data", tsbk, P25_TSBK_FEC_LENGTH_BYTES);
+ Utils::dump(1U, "!!! *TSDU MBF Block Data", frame, P25_TSBK_FEC_LENGTH_BYTES);
}
- Utils::setBitRange(tsbk, m_rfMBF, (m_mbfCnt * P25_TSBK_FEC_LENGTH_BITS), P25_TSBK_FEC_LENGTH_BITS);
+ Utils::setBitRange(frame, m_rfMBF, (m_mbfCnt * P25_TSBK_FEC_LENGTH_BITS), P25_TSBK_FEC_LENGTH_BITS);
m_mbfCnt++;
}
///
/// Helper to write a alternate multi-block trunking PDU packet.
///
+///
///
-void Trunk::writeRF_TSDU_AMBT(bool clearBeforeWrite)
+void Trunk::writeRF_TSDU_AMBT(lc::AMBT* ambt, bool clearBeforeWrite)
{
if (!m_p25->m_control)
return;
+ assert(ambt != NULL);
+
DataHeader header = DataHeader();
uint8_t pduUserData[P25_PDU_UNCONFIRMED_LENGTH_BYTES * P25_MAX_PDU_COUNT];
::memset(pduUserData, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES * P25_MAX_PDU_COUNT);
// Generate TSBK block
- m_rfTSBK.setLastBlock(true); // always set last block -- this a Single Block TSDU
- m_rfTSBK.encodeMBT(header, pduUserData);
+ ambt->setLastBlock(true); // always set last block -- this a Single Block TSDU
+ ambt->encodeMBT(header, pduUserData);
if (m_debug) {
LogDebug(LOG_RF, P25_PDU_STR ", ack = %u, outbound = %u, fmt = $%02X, sap = $%02X, fullMessage = %u, blocksToFollow = %u, padCount = %u, n = %u, seqNo = %u, hdrOffset = %u",
@@ -1697,8 +1844,8 @@ void Trunk::writeRF_TSDU_AMBT(bool clearBeforeWrite)
header.getBlocksToFollow(), header.getPadCount(), header.getNs(), header.getFSN(),
header.getHeaderOffset());
LogDebug(LOG_RF, P25_PDU_STR " AMBT, lco = $%02X, mfId = $%02X, lastBlock = %u, AIV = %u, EX = %u, srcId = %u, dstId = %u, sysId = $%03X, netId = $%05X",
- m_rfTSBK.getLCO(), m_rfTSBK.getMFId(), m_rfTSBK.getLastBlock(), m_rfTSBK.getAIV(), m_rfTSBK.getEX(), m_rfTSBK.getSrcId(), m_rfTSBK.getDstId(),
- m_rfTSBK.getSysId(), m_rfTSBK.getNetId());
+ ambt->getLCO(), ambt->getMFId(), ambt->getLastBlock(), ambt->getAIV(), ambt->getEX(), ambt->getSrcId(), ambt->getDstId(),
+ ambt->getSysId(), ambt->getNetId());
Utils::dump(1U, "!!! *PDU (AMBT) TSBK Block Data", pduUserData, P25_PDU_UNCONFIRMED_LENGTH_BYTES * header.getBlocksToFollow());
}
@@ -1715,7 +1862,7 @@ void Trunk::queueRF_TSBK_Ctrl(uint8_t lco)
if (!m_p25->m_control)
return;
- resetRF();
+ lc::TSBK* tsbk = NULL;
switch (lco) {
case TSBK_OSP_GRP_VCH_GRANT_UPD:
@@ -1728,11 +1875,12 @@ void Trunk::queueRF_TSBK_Ctrl(uint8_t lco)
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_OSP_GRP_VCH_GRANT_UPD (Group Voice Channel Grant Update)");
}
+ lc::tsbk::OSP_GRP_VCH_GRANT_UPD* osp = new lc::tsbk::OSP_GRP_VCH_GRANT_UPD();
+
bool noData = false;
uint8_t i = 0U;
std::unordered_map grantTable = m_p25->m_affiliations.grantTable();
- for (auto it = grantTable.begin(); it != grantTable.end(); ++it)
- {
+ for (auto it = grantTable.begin(); it != grantTable.end(); ++it) {
// no good very bad way of skipping entries...
if (i != m_mbfGrpGrntCnt) {
i++;
@@ -1749,9 +1897,9 @@ void Trunk::queueRF_TSBK_Ctrl(uint8_t lco)
}
else {
// transmit group voice grant update
- m_rfTSBK.setLCO(TSBK_OSP_GRP_VCH_GRANT_UPD);
- m_rfTSBK.setDstId(dstId);
- m_rfTSBK.setGrpVchNo(chNo);
+ osp->setLCO(TSBK_OSP_GRP_VCH_GRANT_UPD);
+ osp->setDstId(dstId);
+ osp->setGrpVchNo(chNo);
m_mbfGrpGrntCnt++;
break;
@@ -1760,7 +1908,10 @@ void Trunk::queueRF_TSBK_Ctrl(uint8_t lco)
}
if (noData) {
+ delete osp;
return; // don't create anything
+ } else {
+ tsbk = osp;
}
}
else {
@@ -1792,17 +1943,18 @@ void Trunk::queueRF_TSBK_Ctrl(uint8_t lco)
// handle 700/800/900 identities
if (entry.baseFrequency() >= 762000000U) {
- m_rfTSBK.siteIdenEntry(entry);
+ lc::tsbk::OSP_IDEN_UP* osp = new lc::tsbk::OSP_IDEN_UP();
+ osp->siteIdenEntry(entry);
// transmit channel ident broadcast
- m_rfTSBK.setLCO(TSBK_OSP_IDEN_UP);
+ tsbk = osp;
}
else {
- // handle as a VHF/UHF identity
- m_rfTSBK.siteIdenEntry(entry);
+ lc::tsbk::OSP_IDEN_UP_VU* osp = new lc::tsbk::OSP_IDEN_UP_VU();
+ osp->siteIdenEntry(entry);
// transmit channel ident broadcast
- m_rfTSBK.setLCO(TSBK_OSP_IDEN_UP_VU);
+ tsbk = osp;
}
m_mbfIdenCnt++;
@@ -1817,7 +1969,7 @@ void Trunk::queueRF_TSBK_Ctrl(uint8_t lco)
}
// transmit net status burst
- m_rfTSBK.setLCO(TSBK_OSP_NET_STS_BCAST);
+ tsbk = new lc::tsbk::OSP_NET_STS_BCAST();
break;
case TSBK_OSP_RFSS_STS_BCAST:
if (m_debug) {
@@ -1825,7 +1977,7 @@ void Trunk::queueRF_TSBK_Ctrl(uint8_t lco)
}
// transmit rfss status burst
- m_rfTSBK.setLCO(TSBK_OSP_RFSS_STS_BCAST);
+ tsbk = new lc::tsbk::OSP_RFSS_STS_BCAST();
break;
case TSBK_OSP_ADJ_STS_BCAST:
// write ADJSS
@@ -1837,6 +1989,8 @@ void Trunk::queueRF_TSBK_Ctrl(uint8_t lco)
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_OSP_ADJ_STS_BCAST (Adjacent Site Broadcast)");
}
+ lc::tsbk::OSP_ADJ_STS_BCAST* osp = new lc::tsbk::OSP_ADJ_STS_BCAST();
+
uint8_t i = 0U;
for (auto it = m_adjSiteTable.begin(); it != m_adjSiteTable.end(); ++it) {
// no good very bad way of skipping entries...
@@ -1856,15 +2010,15 @@ void Trunk::queueRF_TSBK_Ctrl(uint8_t lco)
}
// transmit adjacent site broadcast
- m_rfTSBK.setLCO(TSBK_OSP_ADJ_STS_BCAST);
- m_rfTSBK.setAdjSiteCFVA(cfva);
- m_rfTSBK.setAdjSiteSysId(site.sysId());
- m_rfTSBK.setAdjSiteRFSSId(site.rfssId());
- m_rfTSBK.setAdjSiteId(site.siteId());
- m_rfTSBK.setAdjSiteChnId(site.channelId());
- m_rfTSBK.setAdjSiteChnNo(site.channelNo());
- m_rfTSBK.setAdjSiteSvcClass(site.serviceClass());
-
+ osp->setAdjSiteCFVA(cfva);
+ osp->setAdjSiteSysId(site.sysId());
+ osp->setAdjSiteRFSSId(site.rfssId());
+ osp->setAdjSiteId(site.siteId());
+ osp->setAdjSiteChnId(site.channelId());
+ osp->setAdjSiteChnNo(site.channelNo());
+ osp->setAdjSiteSvcClass(site.serviceClass());
+
+ tsbk = osp;
m_mbfAdjSSCnt++;
break;
}
@@ -1884,6 +2038,8 @@ void Trunk::queueRF_TSBK_Ctrl(uint8_t lco)
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_OSP_SCCB_EXP (Secondary Control Channel Broadcast)");
}
+ lc::tsbk::OSP_SCCB_EXP* osp = new lc::tsbk::OSP_SCCB_EXP();
+
uint8_t i = 0U;
for (auto it = m_sccbTable.begin(); it != m_sccbTable.end(); ++it) {
// no good very bad way of skipping entries...
@@ -1895,10 +2051,11 @@ void Trunk::queueRF_TSBK_Ctrl(uint8_t lco)
SiteData site = it->second;
// transmit SCCB broadcast
- m_rfTSBK.setLCO(TSBK_OSP_SCCB_EXP);
- m_rfTSBK.setSCCBChnId1(site.channelId());
- m_rfTSBK.setSCCBChnNo(site.channelNo());
+ osp->setLCO(TSBK_OSP_SCCB_EXP);
+ osp->setSCCBChnId1(site.channelId());
+ osp->setSCCBChnNo(site.channelNo());
+ tsbk = osp;
m_mbfSCCBCnt++;
break;
}
@@ -1914,17 +2071,19 @@ void Trunk::queueRF_TSBK_Ctrl(uint8_t lco)
}
// transmit SNDCP announcement
- m_rfTSBK.setLCO(TSBK_OSP_SNDCP_CH_ANN);
+ tsbk = new lc::tsbk::OSP_SNDCP_CH_ANN();
break;
case TSBK_OSP_SYNC_BCAST:
+ {
if (m_debug) {
LogMessage(LOG_RF , P25_TSDU_STR ", TSBK_OSP_SYNC_BCAST (Synchronization Broadcast)");
}
- m_rfTSBK.setLCO(TSBK_OSP_SYNC_BCAST);
- m_rfTSBK.setMicroslotCount(m_microslotCount);
- m_rfTSBK.setMFId(P25_MFG_STANDARD);
- break;
+ // transmit sync broadcast
+ lc::tsbk::OSP_SYNC_BCAST* osp = new lc::tsbk::OSP_SYNC_BCAST();
+ osp->setMicroslotCount(m_microslotCount);
+ }
+ break;
/** Motorola CC data */
case TSBK_OSP_MOT_PSH_CCH:
@@ -1933,8 +2092,7 @@ void Trunk::queueRF_TSBK_Ctrl(uint8_t lco)
}
// transmit motorola PSH CCH burst
- m_rfTSBK.setLCO(TSBK_OSP_MOT_PSH_CCH);
- m_rfTSBK.setMFId(P25_MFG_MOT);
+ tsbk = new lc::tsbk::OSP_MOT_PSH_CCH();
break;
case TSBK_OSP_MOT_CC_BSI:
@@ -1943,8 +2101,7 @@ void Trunk::queueRF_TSBK_Ctrl(uint8_t lco)
}
// transmit motorola CC BSI burst
- m_rfTSBK.setLCO(TSBK_OSP_MOT_CC_BSI);
- m_rfTSBK.setMFId(P25_MFG_MOT);
+ tsbk = new lc::tsbk::OSP_MOT_CC_BSI();
break;
/** DVM CC data */
@@ -1954,42 +2111,50 @@ void Trunk::queueRF_TSBK_Ctrl(uint8_t lco)
}
// transmit git hash burst
- m_rfTSBK.setLCO(TSBK_OSP_DVM_GIT_HASH);
- m_rfTSBK.setMFId(P25_MFG_DVM);
+ tsbk = new lc::tsbk::OSP_DVM_GIT_HASH();
break;
}
- m_rfTSBK.setLastBlock(true); // always set last block
+ if (tsbk != NULL) {
+ tsbk->setLastBlock(true); // always set last block
- // are we transmitting CC as a multi-block?
- if (m_ctrlTSDUMBF) {
- writeRF_TSDU_MBF();
- }
- else {
- writeRF_TSDU_SBF(true);
+ // are we transmitting CC as a multi-block?
+ if (m_ctrlTSDUMBF) {
+ writeRF_TSDU_MBF(tsbk);
+ }
+ else {
+ writeRF_TSDU_SBF(tsbk, true);
+ }
+
+ delete tsbk;
}
}
///
/// Helper to write a grant packet.
///
+///
+///
+///
///
///
///
///
///
-bool Trunk::writeRF_TSDU_Grant(bool grp, bool skip, bool net, bool skipNetCheck)
+bool Trunk::writeRF_TSDU_Grant(uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp, bool skip, uint32_t chNo, bool net, bool skipNetCheck)
{
- uint8_t lco = m_rfTSBK.getLCO();
+ bool emergency = ((serviceOptions & 0xFFU) & 0x80U) == 0x80U; // Emergency Flag
+ bool encryption = ((serviceOptions & 0xFFU) & 0x40U) == 0x40U; // Encryption Flag
+ uint8_t priority = ((serviceOptions & 0xFFU) & 0x07U); // Priority
- if (m_rfTSBK.getDstId() == P25_TGID_ALL) {
+ if (dstId == P25_TGID_ALL) {
return true; // do not generate grant packets for $FFFF (All Call) TGID
}
// do we have a network connection and are we handling grants at the network?
if (m_p25->m_network != NULL) {
if (m_p25->m_network->isHandlingChGrants() && m_p25->m_siteData.netActive() && !skipNetCheck) {
- return m_p25->m_network->writeGrantReq(grp, m_rfTSBK.getSrcId(), m_rfTSBK.getDstId());
+ return m_p25->m_network->writeGrantReq(grp, srcId, dstId);
}
}
@@ -1997,134 +2162,145 @@ bool Trunk::writeRF_TSDU_Grant(bool grp, bool skip, bool net, bool skipNetCheck)
if (!skip) {
if (m_p25->m_rfState != RS_RF_LISTENING && m_p25->m_rfState != RS_RF_DATA) {
if (!net) {
- LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_VCH (Group Voice Channel Request) denied, traffic in progress, dstId = %u", m_rfTSBK.getDstId());
- writeRF_TSDU_Deny(P25_DENY_RSN_PTT_COLLIDE, (grp) ? TSBK_IOSP_GRP_VCH : TSBK_IOSP_UU_VCH);
+ LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_VCH (Group Voice Channel Request) denied, traffic in progress, dstId = %u", dstId);
+ writeRF_TSDU_Deny(srcId, P25_DENY_RSN_PTT_COLLIDE, (grp) ? TSBK_IOSP_GRP_VCH : TSBK_IOSP_UU_VCH);
- ::ActivityLog("P25", true, "group grant request from %u to TG %u denied", m_rfTSBK.getSrcId(), m_rfTSBK.getDstId());
+ ::ActivityLog("P25", true, "group grant request from %u to TG %u denied", srcId, dstId);
m_p25->m_rfState = RS_RF_REJECTED;
}
- m_rfTSBK.setLCO(lco);
return false;
}
- if (m_p25->m_netState != RS_NET_IDLE && m_rfTSBK.getDstId() == m_p25->m_netLastDstId) {
+ if (m_p25->m_netState != RS_NET_IDLE && dstId == m_p25->m_netLastDstId) {
if (!net) {
- LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_VCH (Group Voice Channel Request) denied, traffic in progress, dstId = %u", m_rfTSBK.getDstId());
- writeRF_TSDU_Deny(P25_DENY_RSN_PTT_COLLIDE, (grp) ? TSBK_IOSP_GRP_VCH : TSBK_IOSP_UU_VCH);
+ LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_VCH (Group Voice Channel Request) denied, traffic in progress, dstId = %u", dstId);
+ writeRF_TSDU_Deny(srcId, P25_DENY_RSN_PTT_COLLIDE, (grp) ? TSBK_IOSP_GRP_VCH : TSBK_IOSP_UU_VCH);
- ::ActivityLog("P25", true, "group grant request from %u to TG %u denied", m_rfTSBK.getSrcId(), m_rfTSBK.getDstId());
+ ::ActivityLog("P25", true, "group grant request from %u to TG %u denied", srcId, dstId);
m_p25->m_rfState = RS_RF_REJECTED;
}
- m_rfTSBK.setLCO(lco);
return false;
}
// don't transmit grants if the destination ID's don't match and the network TG hang timer is running
if (m_p25->m_rfLastDstId != 0U) {
- if (m_p25->m_rfLastDstId != m_rfTSBK.getDstId() && (m_p25->m_rfTGHang.isRunning() && !m_p25->m_rfTGHang.hasExpired())) {
+ if (m_p25->m_rfLastDstId != dstId && (m_p25->m_rfTGHang.isRunning() && !m_p25->m_rfTGHang.hasExpired())) {
if (!net) {
- writeRF_TSDU_Deny(P25_DENY_RSN_PTT_BONK, (grp) ? TSBK_IOSP_GRP_VCH : TSBK_IOSP_UU_VCH);
+ writeRF_TSDU_Deny(srcId, P25_DENY_RSN_PTT_BONK, (grp) ? TSBK_IOSP_GRP_VCH : TSBK_IOSP_UU_VCH);
m_p25->m_rfState = RS_RF_REJECTED;
}
- m_rfTSBK.setLCO(lco);
return false;
}
}
- if (!m_p25->m_affiliations.isGranted(m_rfTSBK.getDstId())) {
+ if (!m_p25->m_affiliations.isGranted(dstId)) {
if (!m_p25->m_affiliations.isRFChAvailable()) {
if (grp) {
if (!net) {
- LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_VCH (Group Voice Channel Request) queued, no channels available, dstId = %u", m_rfTSBK.getDstId());
- writeRF_TSDU_Queue(P25_QUE_RSN_CHN_RESOURCE_NOT_AVAIL, TSBK_IOSP_GRP_VCH);
+ LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_VCH (Group Voice Channel Request) queued, no channels available, dstId = %u", dstId);
+ writeRF_TSDU_Queue(srcId, P25_QUE_RSN_CHN_RESOURCE_NOT_AVAIL, TSBK_IOSP_GRP_VCH);
- ::ActivityLog("P25", true, "group grant request from %u to TG %u queued", m_rfTSBK.getSrcId(), m_rfTSBK.getDstId());
+ ::ActivityLog("P25", true, "group grant request from %u to TG %u queued", srcId, dstId);
m_p25->m_rfState = RS_RF_REJECTED;
}
- m_rfTSBK.setLCO(lco);
return false;
}
else {
if (!net) {
- LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_UU_VCH (Unit-to-Unit Voice Channel Request) queued, no channels available, dstId = %u", m_rfTSBK.getDstId());
- writeRF_TSDU_Queue(P25_QUE_RSN_CHN_RESOURCE_NOT_AVAIL, TSBK_IOSP_UU_VCH);
+ LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_UU_VCH (Unit-to-Unit Voice Channel Request) queued, no channels available, dstId = %u", dstId);
+ writeRF_TSDU_Queue(srcId, P25_QUE_RSN_CHN_RESOURCE_NOT_AVAIL, TSBK_IOSP_UU_VCH);
- ::ActivityLog("P25", true, "unit-to-unit grant request from %u to %u queued", m_rfTSBK.getSrcId(), m_rfTSBK.getDstId());
+ ::ActivityLog("P25", true, "unit-to-unit grant request from %u to %u queued", srcId, dstId);
m_p25->m_rfState = RS_RF_REJECTED;
}
- m_rfTSBK.setLCO(lco);
return false;
}
}
else {
- if (m_p25->m_affiliations.grantCh(m_rfTSBK.getDstId(), GRANT_TIMER_TIMEOUT)) {
- uint32_t chNo = m_p25->m_affiliations.getGrantedCh(m_rfTSBK.getDstId());
- m_rfTSBK.setGrpVchNo(chNo);
- m_rfTSBK.setDataChnNo(chNo);
+ if (m_p25->m_affiliations.grantCh(dstId, GRANT_TIMER_TIMEOUT)) {
+ chNo = m_p25->m_affiliations.getGrantedCh(dstId);
m_p25->m_siteData.setChCnt(m_p25->m_affiliations.getRFChCnt() + m_p25->m_affiliations.getGrantedRFChCnt());
}
}
}
else {
- uint32_t chNo = m_p25->m_affiliations.getGrantedCh(m_rfTSBK.getDstId());
- m_rfTSBK.setGrpVchNo(chNo);
- m_rfTSBK.setDataChnNo(chNo);
-
- m_p25->m_affiliations.touchGrant(m_rfTSBK.getDstId());
+ chNo = m_p25->m_affiliations.getGrantedCh(dstId);
+ m_p25->m_affiliations.touchGrant(dstId);
}
}
- if (grp) {
- if (!net) {
- ::ActivityLog("P25", true, "group grant request from %u to TG %u", m_rfTSBK.getSrcId(), m_rfTSBK.getDstId());
- }
+ if (chNo > 0U) {
+ if (grp) {
+ if (!net) {
+ ::ActivityLog("P25", true, "group grant request from %u to TG %u", srcId, dstId);
+ }
- if (m_verbose) {
- LogMessage((net) ? LOG_NET : LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_VCH (Group Voice Channel Grant), emerg = %u, encrypt = %u, prio = %u, chNo = %u, srcId = %u, dstId = %u",
- m_rfTSBK.getEmergency(), m_rfTSBK.getEncrypted(), m_rfTSBK.getPriority(), m_rfTSBK.getGrpVchNo(), m_rfTSBK.getSrcId(), m_rfTSBK.getDstId());
- }
+ lc::tsbk::IOSP_GRP_VCH *iosp = new lc::tsbk::IOSP_GRP_VCH();
+ iosp->setSrcId(srcId);
+ iosp->setDstId(dstId);
+ iosp->setGrpVchNo(chNo);
+ iosp->setEmergency(emergency);
+ iosp->setEncrypted(encryption);
+ iosp->setPriority(priority);
+
+ if (m_verbose) {
+ LogMessage((net) ? LOG_NET : LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_VCH (Group Voice Channel Grant), emerg = %u, encrypt = %u, prio = %u, chNo = %u, srcId = %u, dstId = %u",
+ iosp->getEmergency(), iosp->getEncrypted(), iosp->getPriority(), iosp->getGrpVchNo(), iosp->getSrcId(), iosp->getDstId());
+ }
- // transmit group grant
- m_rfTSBK.setLCO(TSBK_IOSP_GRP_VCH);
-// m_p25->m_writeImmediate = true;
- writeRF_TSDU_SBF(false, true, net);
- }
- else {
- if (!net) {
- ::ActivityLog("P25", true, "unit-to-unit grant request from %u to %u", m_rfTSBK.getSrcId(), m_rfTSBK.getDstId());
+ // transmit group grant
+// m_p25->m_writeImmediate = true;
+ writeRF_TSDU_SBF(iosp, false, true, net);
+ delete iosp;
}
+ else {
+ if (!net) {
+ ::ActivityLog("P25", true, "unit-to-unit grant request from %u to %u", srcId, dstId);
+ }
- if (m_verbose) {
- LogMessage((net) ? LOG_NET : LOG_RF, P25_TSDU_STR ", TSBK_IOSP_UU_VCH (Unit-to-Unit Voice Channel Grant), emerg = %u, encrypt = %u, prio = %u, chNo = %u, srcId = %u, dstId = %u",
- m_rfTSBK.getEmergency(), m_rfTSBK.getEncrypted(), m_rfTSBK.getPriority(), m_rfTSBK.getGrpVchNo(), m_rfTSBK.getSrcId(), m_rfTSBK.getDstId());
- }
+ lc::tsbk::IOSP_UU_VCH *iosp = new lc::tsbk::IOSP_UU_VCH();
+ iosp->setSrcId(srcId);
+ iosp->setDstId(dstId);
+ iosp->setGrpVchNo(chNo);
+ iosp->setEmergency(emergency);
+ iosp->setEncrypted(encryption);
+ iosp->setPriority(priority);
+
+ if (m_verbose) {
+ LogMessage((net) ? LOG_NET : LOG_RF, P25_TSDU_STR ", TSBK_IOSP_UU_VCH (Unit-to-Unit Voice Channel Grant), emerg = %u, encrypt = %u, prio = %u, chNo = %u, srcId = %u, dstId = %u",
+ iosp->getEmergency(), iosp->getEncrypted(), iosp->getPriority(), iosp->getGrpVchNo(), iosp->getSrcId(), iosp->getDstId());
+ }
- // transmit private grant
- m_rfTSBK.setLCO(TSBK_IOSP_UU_VCH);
-// m_p25->m_writeImmediate = true;
- writeRF_TSDU_SBF(false, true, net);
+ // transmit private grant
+// m_p25->m_writeImmediate = true;
+ writeRF_TSDU_SBF(iosp, false, true, net);
+ delete iosp;
+ }
}
- m_rfTSBK.setLCO(lco);
return true;
}
///
/// Helper to write a SNDCP grant packet.
///
+///
+///
///
///
///
-bool Trunk::writeRF_TSDU_SNDCP_Grant(bool skip, bool net)
+bool Trunk::writeRF_TSDU_SNDCP_Grant(uint32_t srcId, uint32_t dstId, bool skip, bool net)
{
- uint8_t lco = m_rfTSBK.getLCO();
+ lc::tsbk::OSP_SNDCP_CH_GNT *osp = new lc::tsbk::OSP_SNDCP_CH_GNT();
+ osp->setSrcId(srcId);
+ osp->setDstId(dstId);
- if (m_rfTSBK.getDstId() == P25_TGID_ALL) {
+ if (dstId == P25_TGID_ALL) {
return true; // do not generate grant packets for $FFFF (All Call) TGID
}
@@ -2132,62 +2308,60 @@ bool Trunk::writeRF_TSDU_SNDCP_Grant(bool skip, bool net)
if (!skip) {
if (m_p25->m_rfState != RS_RF_LISTENING && m_p25->m_rfState != RS_RF_DATA) {
if (!net) {
- LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_ISP_SNDCP_CH_REQ (SNDCP Data Channel Request) denied, traffic in progress, srcId = %u", m_rfTSBK.getSrcId());
- writeRF_TSDU_Queue(P25_QUE_RSN_CHN_RESOURCE_NOT_AVAIL, TSBK_ISP_SNDCP_CH_REQ);
+ LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_ISP_SNDCP_CH_REQ (SNDCP Data Channel Request) denied, traffic in progress, srcId = %u", srcId);
+ writeRF_TSDU_Queue(srcId, P25_QUE_RSN_CHN_RESOURCE_NOT_AVAIL, TSBK_ISP_SNDCP_CH_REQ);
- ::ActivityLog("P25", true, "SNDCP grant request from %u queued", m_rfTSBK.getSrcId());
+ ::ActivityLog("P25", true, "SNDCP grant request from %u queued", srcId);
m_p25->m_rfState = RS_RF_REJECTED;
}
- m_rfTSBK.setLCO(lco);
+ delete osp;
return false;
}
- if (!m_p25->m_affiliations.isGranted(m_rfTSBK.getSrcId())) {
+ if (!m_p25->m_affiliations.isGranted(srcId)) {
if (!m_p25->m_affiliations.isRFChAvailable()) {
if (!net) {
- LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_ISP_SNDCP_CH_REQ (SNDCP Data Channel Request) queued, no channels available, srcId = %u", m_rfTSBK.getSrcId());
- writeRF_TSDU_Queue(P25_QUE_RSN_CHN_RESOURCE_NOT_AVAIL, TSBK_ISP_SNDCP_CH_REQ);
+ LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_ISP_SNDCP_CH_REQ (SNDCP Data Channel Request) queued, no channels available, srcId = %u", srcId);
+ writeRF_TSDU_Queue(srcId, P25_QUE_RSN_CHN_RESOURCE_NOT_AVAIL, TSBK_ISP_SNDCP_CH_REQ);
- ::ActivityLog("P25", true, "SNDCP grant request from %u queued", m_rfTSBK.getSrcId());
+ ::ActivityLog("P25", true, "SNDCP grant request from %u queued", srcId);
m_p25->m_rfState = RS_RF_REJECTED;
}
- m_rfTSBK.setLCO(lco);
+ delete osp;
return false;
}
else {
- if (m_p25->m_affiliations.grantCh(m_rfTSBK.getSrcId(), GRANT_TIMER_TIMEOUT)) {
- uint32_t chNo = m_p25->m_affiliations.getGrantedCh(m_rfTSBK.getSrcId());
- m_rfTSBK.setGrpVchNo(chNo);
- m_rfTSBK.setDataChnNo(chNo);
+ if (m_p25->m_affiliations.grantCh(srcId, GRANT_TIMER_TIMEOUT)) {
+ uint32_t chNo = m_p25->m_affiliations.getGrantedCh(srcId);
+ osp->setGrpVchNo(chNo);
+ osp->setDataChnNo(chNo);
m_p25->m_siteData.setChCnt(m_p25->m_affiliations.getRFChCnt() + m_p25->m_affiliations.getGrantedRFChCnt());
}
}
}
else {
- uint32_t chNo = m_p25->m_affiliations.getGrantedCh(m_rfTSBK.getSrcId());
- m_rfTSBK.setGrpVchNo(chNo);
- m_rfTSBK.setDataChnNo(chNo);
+ uint32_t chNo = m_p25->m_affiliations.getGrantedCh(srcId);
+ osp->setGrpVchNo(chNo);
+ osp->setDataChnNo(chNo);
- m_p25->m_affiliations.touchGrant(m_rfTSBK.getSrcId());
+ m_p25->m_affiliations.touchGrant(srcId);
}
}
if (!net) {
- ::ActivityLog("P25", true, "SNDCP grant request from %u", m_rfTSBK.getSrcId());
+ ::ActivityLog("P25", true, "SNDCP grant request from %u", srcId);
}
if (m_verbose) {
LogMessage((net) ? LOG_NET : LOG_RF, P25_TSDU_STR ", TSBK_OSP_SNDCP_CH_GNT (SNDCP Data Channel Grant), chNo = %u, dstId = %u",
- m_rfTSBK.getDataChnNo(), m_rfTSBK.getSrcId());
+ osp->getDataChnNo(), osp->getSrcId());
}
// transmit SNDCP grant
- m_rfTSBK.setLCO(TSBK_OSP_SNDCP_CH_GNT);
- writeRF_TSDU_SBF(false, true, net);
-
- m_rfTSBK.setLCO(lco);
+ writeRF_TSDU_SBF(osp, false, true, net);
+ delete osp;
return true;
}
@@ -2198,20 +2372,16 @@ bool Trunk::writeRF_TSDU_SNDCP_Grant(bool skip, bool net)
///
void Trunk::writeRF_TSDU_UU_Ans_Req(uint32_t srcId, uint32_t dstId)
{
- uint8_t lco = m_rfTSBK.getLCO();
+ lc::tsbk::IOSP_UU_ANS *iosp = new lc::tsbk::IOSP_UU_ANS();
+ iosp->setSrcId(srcId);
+ iosp->setDstId(dstId);
if (m_verbose) {
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_UU_ANS (Unit-to-Unit Answer Request), srcId = %u, dstId = %u", srcId, dstId);
}
- m_rfTSBK.setLCO(TSBK_IOSP_UU_ANS);
- m_rfTSBK.setSrcId(srcId);
- m_rfTSBK.setDstId(dstId);
- m_rfTSBK.setVendorSkip(true);
- writeRF_TSDU_SBF(false);
-
- m_rfTSBK.setLCO(lco);
- m_rfTSBK.setVendorSkip(false);
+ writeRF_TSDU_SBF(iosp, false);
+ delete iosp;
}
///
@@ -2222,56 +2392,47 @@ void Trunk::writeRF_TSDU_UU_Ans_Req(uint32_t srcId, uint32_t dstId)
///
void Trunk::writeRF_TSDU_ACK_FNE(uint32_t srcId, uint32_t service, bool extended, bool noNetwork)
{
- uint8_t lco = m_rfTSBK.getLCO();
- uint8_t mfId = m_rfTSBK.getMFId();
- uint32_t _srcId = m_rfTSBK.getSrcId();
-
- m_rfTSBK.setLCO(TSBK_IOSP_ACK_RSP);
- m_rfTSBK.setMFId(P25_MFG_STANDARD);
- m_rfTSBK.setSrcId(srcId);
- m_rfTSBK.setService(service);
+ lc::tsbk::IOSP_ACK_RSP *iosp = new lc::tsbk::IOSP_ACK_RSP();
+ iosp->setSrcId(srcId);
+ iosp->setService(service);
if (extended) {
- m_rfTSBK.setAIV(true);
- m_rfTSBK.setEX(true);
+ iosp->setAIV(true);
+ iosp->setEX(true);
}
if (m_verbose) {
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_ACK_RSP (Acknowledge Response), AIV = %u, EX = %u, serviceType = $%02X, srcId = %u",
- m_rfTSBK.getAIV(), m_rfTSBK.getEX(), m_rfTSBK.getService(), srcId);
+ iosp->getAIV(), iosp->getEX(), iosp->getService(), srcId);
}
- writeRF_TSDU_SBF(noNetwork);
-
- m_rfTSBK.setLCO(lco);
- m_rfTSBK.setMFId(mfId);
- m_rfTSBK.setSrcId(_srcId);
+ writeRF_TSDU_SBF(iosp, noNetwork);
+ delete iosp;
}
///
/// Helper to write a deny packet.
///
+///
///
///
-void Trunk::writeRF_TSDU_Deny(uint8_t reason, uint8_t service)
+///
+void Trunk::writeRF_TSDU_Deny(uint32_t dstId, uint8_t reason, uint8_t service, bool aiv)
{
- uint8_t lco = m_rfTSBK.getLCO();
- uint32_t srcId = m_rfTSBK.getSrcId();
-
- m_rfTSBK.setLCO(TSBK_OSP_DENY_RSP);
- m_rfTSBK.setSrcId(P25_WUID_FNE);
- m_rfTSBK.setService(service);
- m_rfTSBK.setResponse(reason);
+ lc::tsbk::OSP_DENY_RSP* osp = new lc::tsbk::OSP_DENY_RSP();
+ osp->setAIV(aiv);
+ osp->setSrcId(P25_WUID_FNE);
+ osp->setDstId(dstId);
+ osp->setService(service);
+ osp->setResponse(reason);
if (m_verbose) {
- LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_OSP_DENY_RSP (Deny Response), AIV = %u, reason = $%02X, service = $%02X, srcId = %u, dstId = %u",
- m_rfTSBK.getAIV(), reason, service, m_rfTSBK.getSrcId(), m_rfTSBK.getDstId());
+ LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_OSP_DENY_RSP (Deny Response), AIV = %u, reason = $%02X, srcId = %u, dstId = %u",
+ osp->getAIV(), reason, osp->getSrcId(), osp->getDstId());
}
- writeRF_TSDU_SBF(false);
-
- m_rfTSBK.setLCO(lco);
- m_rfTSBK.setSrcId(srcId);
+ writeRF_TSDU_SBF(osp, false);
+ delete osp;
}
///
@@ -2283,39 +2444,39 @@ bool Trunk::writeRF_TSDU_Grp_Aff_Rsp(uint32_t srcId, uint32_t dstId)
{
bool ret = false;
- m_rfTSBK.setLCO(TSBK_IOSP_GRP_AFF);
- m_rfTSBK.setResponse(P25_RSP_ACCEPT);
- m_rfTSBK.setPatchSuperGroupId(m_patchSuperGroup);
+ lc::tsbk::IOSP_GRP_AFF *iosp = new lc::tsbk::IOSP_GRP_AFF();
+ iosp->setAnnounceGroup(m_patchSuperGroup); // this isn't right...
+ iosp->setSrcId(srcId);
+ iosp->setDstId(dstId);
+ iosp->setResponse(P25_RSP_ACCEPT);
// validate the source RID
if (!acl::AccessControl::validateSrcId(srcId)) {
LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_AFF (Group Affiliation Response) denial, RID rejection, srcId = %u", srcId);
::ActivityLog("P25", true, "group affiliation request from %u to %s %u denied", srcId, "TG ", dstId);
- m_rfTSBK.setResponse(P25_RSP_REFUSED);
+ iosp->setResponse(P25_RSP_REFUSED);
}
// validate the source RID is registered
if (!m_p25->m_affiliations.isUnitReg(srcId) && m_verifyReg) {
LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_AFF (Group Affiliation Response) denial, RID not registered, srcId = %u", srcId);
::ActivityLog("P25", true, "group affiliation request from %u to %s %u denied", srcId, "TG ", dstId);
- m_rfTSBK.setResponse(P25_RSP_REFUSED);
+ iosp->setResponse(P25_RSP_REFUSED);
}
// validate the talkgroup ID
- if (m_rfTSBK.getGroup()) {
- if (dstId == 0U) {
- LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_AFF (Group Affiliation Response), TGID 0, dstId = %u", dstId);
- }
- else {
- if (!acl::AccessControl::validateTGId(dstId)) {
- LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_AFF (Group Affiliation Response) denial, TGID rejection, dstId = %u", dstId);
- ::ActivityLog("P25", true, "group affiliation request from %u to %s %u denied", srcId, "TG ", dstId);
- m_rfTSBK.setResponse(P25_RSP_DENY);
- }
+ if (dstId == 0U) {
+ LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_AFF (Group Affiliation Response), TGID 0, dstId = %u", dstId);
+ }
+ else {
+ if (!acl::AccessControl::validateTGId(dstId)) {
+ LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_AFF (Group Affiliation Response) denial, TGID rejection, dstId = %u", dstId);
+ ::ActivityLog("P25", true, "group affiliation request from %u to %s %u denied", srcId, "TG ", dstId);
+ iosp->setResponse(P25_RSP_DENY);
}
}
- if (m_rfTSBK.getResponse() == P25_RSP_ACCEPT) {
+ if (iosp->getResponse() == P25_RSP_ACCEPT) {
if (m_verbose) {
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_GRP_AFF (Group Affiliation Response), anncId = %u, srcId = %u, dstId = %u",
m_patchSuperGroup, srcId, dstId);
@@ -2328,7 +2489,8 @@ bool Trunk::writeRF_TSDU_Grp_Aff_Rsp(uint32_t srcId, uint32_t dstId)
m_p25->m_affiliations.groupAff(srcId, dstId);
}
- writeRF_TSDU_SBF(false);
+ writeRF_TSDU_SBF(iosp, false);
+ delete iosp;
return ret;
}
@@ -2336,29 +2498,31 @@ bool Trunk::writeRF_TSDU_Grp_Aff_Rsp(uint32_t srcId, uint32_t dstId)
/// Helper to write a unit registration response packet.
///
///
-void Trunk::writeRF_TSDU_U_Reg_Rsp(uint32_t srcId)
+///
+void Trunk::writeRF_TSDU_U_Reg_Rsp(uint32_t srcId, uint32_t sysId)
{
- m_rfTSBK.setLCO(TSBK_IOSP_U_REG);
- m_rfTSBK.setResponse(P25_RSP_ACCEPT);
+ lc::tsbk::IOSP_U_REG *iosp = new lc::tsbk::IOSP_U_REG();
+ iosp->setResponse(P25_RSP_ACCEPT);
+ iosp->setSrcId(srcId);
+ iosp->setDstId(srcId);
// validate the system ID
- if (m_rfTSBK.getSysId() != m_p25->m_siteData.sysId()) {
- LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_U_REG (Unit Registration Response) denial, SYSID rejection, sysId = $%03X", m_rfTSBK.getSysId());
+ if (sysId != m_p25->m_siteData.sysId()) {
+ LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_U_REG (Unit Registration Response) denial, SYSID rejection, sysId = $%03X", sysId);
::ActivityLog("P25", true, "unit registration request from %u denied", srcId);
- m_rfTSBK.setResponse(P25_RSP_DENY);
+ iosp->setResponse(P25_RSP_DENY);
}
// validate the source RID
if (!acl::AccessControl::validateSrcId(srcId)) {
LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_U_REG (Unit Registration Response) denial, RID rejection, srcId = %u", srcId);
::ActivityLog("P25", true, "unit registration request from %u denied", srcId);
- m_rfTSBK.setResponse(P25_RSP_REFUSED);
+ iosp->setResponse(P25_RSP_REFUSED);
}
- if (m_rfTSBK.getResponse() == P25_RSP_ACCEPT) {
+ if (iosp->getResponse() == P25_RSP_ACCEPT) {
if (m_verbose) {
- LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_U_REG (Unit Registration Response), srcId = %u, sysId = $%03X, netId = $%05X", srcId,
- m_rfTSBK.getSysId(), m_rfTSBK.getNetId());
+ LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_U_REG (Unit Registration Response), srcId = %u, sysId = $%03X", srcId, sysId);
}
::ActivityLog("P25", true, "unit registration request from %u", srcId);
@@ -2369,10 +2533,8 @@ void Trunk::writeRF_TSDU_U_Reg_Rsp(uint32_t srcId)
}
}
- m_rfTSBK.setSrcId(srcId);
- m_rfTSBK.setDstId(srcId);
-
- writeRF_TSDU_SBF(true);
+ writeRF_TSDU_SBF(iosp, true);
+ delete iosp;
// validate the source RID
if (!acl::AccessControl::validateSrcId(srcId)) {
@@ -2388,23 +2550,22 @@ void Trunk::writeRF_TSDU_U_Dereg_Ack(uint32_t srcId)
{
bool dereged = false;
- m_rfTSBK.setLCO(TSBK_OSP_U_DEREG_ACK);
-
- if (m_verbose) {
- LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_ISP_U_DEREG_REQ (Unit Deregistration Request) srcId = %u, sysId = $%03X, netId = $%05X",
- srcId, m_rfTSBK.getSysId(), m_rfTSBK.getNetId());
- }
-
// remove dynamic unit registration table entry
dereged = m_p25->m_affiliations.unitDereg(srcId);
if (dereged) {
+ if (m_verbose) {
+ LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_ISP_U_DEREG_REQ (Unit Deregistration Ack) srcId = %u", srcId);
+ }
+
::ActivityLog("P25", true, "unit deregistration request from %u", srcId);
- m_rfTSBK.setSrcId(P25_WUID_FNE);
- m_rfTSBK.setDstId(srcId);
+ lc::tsbk::OSP_U_DEREG_ACK *osp = new lc::tsbk::OSP_U_DEREG_ACK();
+ osp->setSrcId(P25_WUID_FNE);
+ osp->setDstId(srcId);
- writeRF_TSDU_SBF(false);
+ writeRF_TSDU_SBF(osp, false);
+ delete osp;
}
else {
::ActivityLog("P25", true, "unit deregistration request from %u denied", srcId);
@@ -2414,27 +2575,26 @@ void Trunk::writeRF_TSDU_U_Dereg_Ack(uint32_t srcId)
///
/// Helper to write a queue packet.
///
+///
///
///
-void Trunk::writeRF_TSDU_Queue(uint8_t reason, uint8_t service)
+///
+void Trunk::writeRF_TSDU_Queue(uint32_t dstId, uint8_t reason, uint8_t service, bool aiv)
{
- uint8_t lco = m_rfTSBK.getLCO();
- uint32_t srcId = m_rfTSBK.getSrcId();
-
- m_rfTSBK.setLCO(TSBK_OSP_QUE_RSP);
- m_rfTSBK.setSrcId(P25_WUID_FNE);
- m_rfTSBK.setService(service);
- m_rfTSBK.setResponse(reason);
+ lc::tsbk::OSP_QUE_RSP *osp = new lc::tsbk::OSP_QUE_RSP();
+ osp->setAIV(aiv);
+ osp->setSrcId(P25_WUID_FNE);
+ osp->setDstId(dstId);
+ osp->setService(service);
+ osp->setResponse(reason);
if (m_verbose) {
LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_OSP_QUE_RSP (Queue Response), AIV = %u, reason = $%02X, srcId = %u, dstId = %u",
- m_rfTSBK.getAIV(), reason, m_rfTSBK.getSrcId(), m_rfTSBK.getDstId());
+ osp->getAIV(), reason, osp->getSrcId(), osp->getDstId());
}
- writeRF_TSDU_SBF(false);
-
- m_rfTSBK.setLCO(lco);
- m_rfTSBK.setSrcId(srcId);
+ writeRF_TSDU_SBF(osp, false);
+ delete osp;
}
///
@@ -2442,20 +2602,21 @@ void Trunk::writeRF_TSDU_Queue(uint8_t reason, uint8_t service)
///
///
///
-bool Trunk::writeRF_TSDU_Loc_Reg_Rsp(uint32_t srcId, uint32_t dstId)
+///
+bool Trunk::writeRF_TSDU_Loc_Reg_Rsp(uint32_t srcId, uint32_t dstId, bool grp)
{
bool ret = false;
- m_rfTSBK.setLCO(TSBK_OSP_LOC_REG_RSP);
- m_rfTSBK.setResponse(P25_RSP_ACCEPT);
- m_rfTSBK.setDstId(dstId);
- m_rfTSBK.setSrcId(srcId);
+ lc::tsbk::OSP_LOC_REG_RSP *osp = new lc::tsbk::OSP_LOC_REG_RSP();
+ osp->setResponse(P25_RSP_ACCEPT);
+ osp->setDstId(dstId);
+ osp->setSrcId(srcId);
// validate the source RID
if (!acl::AccessControl::validateSrcId(srcId)) {
LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_OSP_LOC_REG_RSP (Location Registration Response) denial, RID rejection, srcId = %u", srcId);
::ActivityLog("P25", true, "location registration request from %u denied", srcId);
- m_rfTSBK.setResponse(P25_RSP_REFUSED);
+ osp->setResponse(P25_RSP_REFUSED);
}
// validate the source RID is registered
@@ -2467,30 +2628,30 @@ bool Trunk::writeRF_TSDU_Loc_Reg_Rsp(uint32_t srcId, uint32_t dstId)
}
// validate the talkgroup ID
- if (m_rfTSBK.getGroup()) {
- if (dstId == 0U) {
+ if (grp) {
+ if (dstId == 0U) {
LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_OSP_LOC_REG_RSP (Location Registration Response), TGID 0, dstId = %u", dstId);
}
else {
if (!acl::AccessControl::validateTGId(dstId)) {
LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_OSP_LOC_REG_RSP (Location Registration Response) denial, TGID rejection, dstId = %u", dstId);
::ActivityLog("P25", true, "location registration request from %u to %s %u denied", srcId, "TG ", dstId);
- m_rfTSBK.setResponse(P25_RSP_DENY);
+ osp->setResponse(P25_RSP_DENY);
}
}
}
- if (m_rfTSBK.getResponse() == P25_RSP_ACCEPT) {
+ if (osp->getResponse() == P25_RSP_ACCEPT) {
if (m_verbose) {
- LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_OSP_LOC_REG_RSP (Location Registration Response), lra = %u, srcId = %u, dstId = %u",
- m_rfTSBK.getLRA(), srcId, dstId);
+ LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_OSP_LOC_REG_RSP (Location Registration Response), srcId = %u, dstId = %u", srcId, dstId);
}
::ActivityLog("P25", true, "location registration request from %u", srcId);
ret = true;
}
- writeRF_TSDU_SBF(false);
+ writeRF_TSDU_SBF(osp, false);
+ delete osp;
return ret;
}
@@ -2501,25 +2662,27 @@ bool Trunk::writeRF_TSDU_Loc_Reg_Rsp(uint32_t srcId, uint32_t dstId)
///
bool Trunk::writeNet_TSDU_Call_Term(uint32_t srcId, uint32_t dstId)
{
- bool ret = false;
-
- m_rfTSBK.setLCO(LC_CALL_TERM);
- m_rfTSBK.setMFId(P25_MFG_DVM);
- m_rfTSBK.setGrpVchId(m_p25->m_siteData.channelId());
- m_rfTSBK.setGrpVchNo(m_p25->m_siteData.channelNo());
- m_rfTSBK.setDstId(dstId);
- m_rfTSBK.setSrcId(srcId);
-
- writeRF_TSDU_SBF(false); // the problem with this is the vendor code going over the air!
- return ret;
+ lc::tsbk::OSP_DVM_LC_CALL_TERM* osp = new lc::tsbk::OSP_DVM_LC_CALL_TERM();
+ osp->setGrpVchId(m_p25->m_siteData.channelId());
+ osp->setGrpVchNo(m_p25->m_siteData.channelNo());
+ osp->setDstId(dstId);
+ osp->setSrcId(srcId);
+
+ writeRF_TSDU_SBF(osp, false);
+ delete osp;
+ return true;
}
///
/// Helper to write a network TSDU from the RF data queue.
///
+///
///
-void Trunk::writeNet_TSDU_From_RF(uint8_t* data)
+void Trunk::writeNet_TSDU_From_RF(lc::TSBK* tsbk, uint8_t* data)
{
+ assert(tsbk != NULL);
+ assert(data != NULL);
+
::memset(data, 0x00U, P25_TSDU_FRAME_LENGTH_BYTES);
// Generate Sync
@@ -2529,8 +2692,8 @@ void Trunk::writeNet_TSDU_From_RF(uint8_t* data)
m_p25->m_nid.encode(data, P25_DUID_TSDU);
// Regenerate TSDU Data
- m_rfTSBK.setLastBlock(true); // always set last block -- this a Single Block TSDU
- m_rfTSBK.encode(data);
+ tsbk->setLastBlock(true); // always set last block -- this a Single Block TSDU
+ tsbk->encode(data);
// Add busy bits
m_p25->addBusyBits(data, P25_TSDU_FRAME_LENGTH_BYTES, true, false);
@@ -2539,86 +2702,6 @@ void Trunk::writeNet_TSDU_From_RF(uint8_t* data)
m_p25->setBusyBits(data, P25_SS0_START, true, true);
}
-///
-/// Helper to write a network P25 TDU w/ link control packet.
-///
-///
-void Trunk::writeNet_TDULC(lc::TDULC lc)
-{
- uint8_t buffer[P25_TDULC_FRAME_LENGTH_BYTES + 2U];
- ::memset(buffer, 0x00U, P25_TDULC_FRAME_LENGTH_BYTES + 2U);
-
- buffer[0U] = modem::TAG_EOT;
- buffer[1U] = 0x00U;
-
- // Generate Sync
- Sync::addP25Sync(buffer + 2U);
-
- // Generate NID
- m_p25->m_nid.encode(buffer + 2U, P25_DUID_TDULC);
-
- // Regenerate TDULC Data
- lc.encode(buffer + 2U);
-
- // Add busy bits
- m_p25->addBusyBits(buffer + 2U, P25_TDULC_FRAME_LENGTH_BITS, true, true);
-
- m_p25->addFrame(buffer, P25_TDULC_FRAME_LENGTH_BYTES + 2U, true);
-
- if (m_verbose) {
- LogMessage(LOG_NET, P25_TDULC_STR ", lc = $%02X, srcId = %u", lc.getLCO(), lc.getSrcId());
- }
-
- if (m_p25->m_voice->m_netFrames > 0) {
- ::ActivityLog("P25", false, "network end of transmission, %.1f seconds, %u%% packet loss",
- float(m_p25->m_voice->m_netFrames) / 50.0F, (m_p25->m_voice->m_netLost * 100U) / m_p25->m_voice->m_netFrames);
- }
- else {
- ::ActivityLog("P25", false, "network end of transmission, %u frames", m_p25->m_voice->m_netFrames);
- }
-
- if (m_network != NULL)
- m_network->resetP25();
-
- m_p25->m_netTimeout.stop();
- m_p25->m_networkWatchdog.stop();
- m_p25->m_netState = RS_NET_IDLE;
- m_p25->m_tailOnIdle = true;
-}
-
-///
-/// Helper to write a network single-block P25 TSDU packet.
-///
-void Trunk::writeNet_TSDU()
-{
- uint8_t buffer[P25_TSDU_FRAME_LENGTH_BYTES + 2U];
- ::memset(buffer, 0x00U, P25_TSDU_FRAME_LENGTH_BYTES + 2U);
-
- buffer[0U] = modem::TAG_DATA;
- buffer[1U] = 0x00U;
-
- // Generate Sync
- Sync::addP25Sync(buffer + 2U);
-
- // Generate NID
- m_p25->m_nid.encode(buffer + 2U, P25_DUID_TSDU);
-
- // Regenerate TSDU Data
- m_netTSBK.setLastBlock(true); // always set last block -- this a Single Block TSDU
- m_netTSBK.encode(buffer + 2U);
-
- // Add busy bits
- m_p25->addBusyBits(buffer + 2U, P25_TSDU_FRAME_LENGTH_BYTES, true, false);
-
- // Set first busy bits to 1,1
- m_p25->setBusyBits(buffer + 2U, P25_SS0_START, true, true);
-
- m_p25->addFrame(buffer, P25_TSDU_FRAME_LENGTH_BYTES + 2U, true);
-
- if (m_network != NULL)
- m_network->resetP25();
-}
-
///
/// Helper to automatically inhibit a source ID on a denial.
///
diff --git a/p25/packet/Trunk.h b/p25/packet/Trunk.h
index c44ce465..47a59147 100644
--- a/p25/packet/Trunk.h
+++ b/p25/packet/Trunk.h
@@ -30,6 +30,7 @@
#include "p25/data/DataHeader.h"
#include "p25/data/DataBlock.h"
#include "p25/lc/TSBK.h"
+#include "p25/lc/AMBT.h"
#include "p25/lc/TDULC.h"
#include "p25/Control.h"
#include "network/BaseNetwork.h"
@@ -62,13 +63,8 @@ namespace p25
class HOST_SW_API Trunk {
public:
- /// Resets the data states for the RF interface.
- virtual void resetRF();
- /// Resets the data states for the network.
- virtual void resetNet();
-
/// Process a data frame from the RF interface.
- virtual bool process(uint8_t* data, uint32_t len, bool preDecoded = false);
+ virtual bool process(uint8_t* data, uint32_t len, lc::TSBK* preDecodedTSBK = NULL);
/// Process a data frame from the network.
virtual bool processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::LowSpeedData& lsd, uint8_t& duid);
@@ -81,13 +77,10 @@ namespace p25
/// Updates the processor by the passed number of milliseconds.
void clock(uint32_t ms);
- /// Helper to set the TSBK manufacturer ID.
- void setMFId(uint8_t val) { m_rfTSBK.setMFId(val); }
-
/// Helper to write a call alert packet.
void writeRF_TSDU_Call_Alrt(uint32_t srcId, uint32_t dstId);
- /// Helper to write a call alert packet.
- void writeRF_TSDU_Radio_Mon(uint32_t srcId, uint32_t dstId, uint8_t txmult);
+ /// Helper to write a radio monitor packet.
+ void writeRF_TSDU_Radio_Mon(uint32_t srcId, uint32_t dstId, uint8_t txMult);
/// Helper to write a extended function packet.
void writeRF_TSDU_Ext_Func(uint32_t func, uint32_t arg, uint32_t dstId);
/// Helper to write a group affiliation query packet.
@@ -97,9 +90,6 @@ namespace p25
/// Helper to write a emergency alarm packet.
void writeRF_TSDU_Emerg_Alrm(uint32_t srcId, uint32_t dstId);
- /// Helper to write a Motorola patch packet.
- void writeRF_TSDU_Mot_Patch(uint32_t group1, uint32_t group2, uint32_t group3);
-
/// Helper to change the conventional fallback state.
void setConvFallback(bool fallback);
@@ -123,8 +113,6 @@ namespace p25
bool m_verifyAff;
bool m_verifyReg;
- lc::TSBK m_rfTSBK;
- lc::TSBK m_netTSBK;
uint8_t* m_rfMBF;
uint8_t m_mbfCnt;
@@ -167,57 +155,58 @@ namespace p25
virtual ~Trunk();
/// Write data processed from RF to the network.
- void writeNetworkRF(const uint8_t* data, bool autoReset);
+ void writeNetworkRF(lc::TSBK* tsbk, const uint8_t* data, bool autoReset);
+ /// Write data processed from RF to the network.
+ void writeNetworkRF(lc::TDULC& tduLc, const uint8_t* data, bool autoReset);
/// Helper to write control channel packet data.
void writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adjSS);
/// Helper to write a P25 TDU w/ link control packet.
void writeRF_TDULC(lc::TDULC lc, bool noNetwork);
+ /// Helper to write a network P25 TDU w/ link control packet.
+ virtual void writeNet_TDULC(lc::TDULC lc);
/// Helper to write a P25 TDU w/ link control channel release packet.
void writeRF_TDULC_ChanRelease(bool grp, uint32_t srcId, uint32_t dstId);
/// Helper to write a single-block P25 TSDU packet.
- virtual void writeRF_TSDU_SBF(bool noNetwork, bool clearBeforeWrite = false, bool force = false);
+ virtual void writeRF_TSDU_SBF(lc::TSBK* tsbk, bool noNetwork, bool clearBeforeWrite = false, bool force = false);
+ /// Helper to write a network single-block P25 TSDU packet.
+ virtual void writeNet_TSDU(lc::TSBK* tsbk);
/// Helper to write a multi-block (3-block) P25 TSDU packet.
- void writeRF_TSDU_MBF(bool clearBeforeWrite = false);
+ void writeRF_TSDU_MBF(lc::TSBK* tsbk, bool clearBeforeWrite = false);
/// Helper to write a alternate multi-block trunking PDU packet.
- virtual void writeRF_TSDU_AMBT(bool clearBeforeWrite = false);
+ virtual void writeRF_TSDU_AMBT(lc::AMBT* ambt, bool clearBeforeWrite = false);
/// Helper to generate the given control TSBK into the TSDU frame queue.
void queueRF_TSBK_Ctrl(uint8_t lco);
/// Helper to write a grant packet.
- bool writeRF_TSDU_Grant(bool grp, bool skip = false, bool net = false, bool skipNetCheck = false);
+ bool writeRF_TSDU_Grant(uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp, bool skip = false, uint32_t chNo = 0U, bool net = false, bool skipNetCheck = false);
/// Helper to write a SNDCP grant packet.
- bool writeRF_TSDU_SNDCP_Grant(bool skip = false, bool net = false);
+ bool writeRF_TSDU_SNDCP_Grant(uint32_t srcId, uint32_t dstId, bool skip = false, bool net = false);
/// Helper to write a unit to unit answer request packet.
void writeRF_TSDU_UU_Ans_Req(uint32_t srcId, uint32_t dstId);
/// Helper to write a acknowledge packet.
void writeRF_TSDU_ACK_FNE(uint32_t srcId, uint32_t service, bool extended, bool noActivityLog);
/// Helper to write a deny packet.
- void writeRF_TSDU_Deny(uint8_t reason, uint8_t service);
+ void writeRF_TSDU_Deny(uint32_t dstId, uint8_t reason, uint8_t service, bool aiv = false);
/// Helper to write a group affiliation response packet.
bool writeRF_TSDU_Grp_Aff_Rsp(uint32_t srcId, uint32_t dstId);
/// Helper to write a unit registration response packet.
- void writeRF_TSDU_U_Reg_Rsp(uint32_t srcId);
+ void writeRF_TSDU_U_Reg_Rsp(uint32_t srcId, uint32_t sysId);
/// Helper to write a unit de-registration acknowledge packet.
void writeRF_TSDU_U_Dereg_Ack(uint32_t srcId);
/// Helper to write a queue packet.
- void writeRF_TSDU_Queue(uint8_t reason, uint8_t service);
+ void writeRF_TSDU_Queue(uint32_t dstId, uint8_t reason, uint8_t service, bool aiv = false);
/// Helper to write a location registration response packet.
- bool writeRF_TSDU_Loc_Reg_Rsp(uint32_t srcId, uint32_t dstId);
+ bool writeRF_TSDU_Loc_Reg_Rsp(uint32_t srcId, uint32_t dstId, bool grp);
/// Helper to write a call termination packet.
bool writeNet_TSDU_Call_Term(uint32_t srcId, uint32_t dstId);
/// Helper to write a network TSDU from the RF data queue.
- void writeNet_TSDU_From_RF(uint8_t* data);
-
- /// Helper to write a network P25 TDU w/ link control packet.
- virtual void writeNet_TDULC(lc::TDULC lc);
- /// Helper to write a network single-block P25 TSDU packet.
- virtual void writeNet_TSDU();
+ void writeNet_TSDU_From_RF(lc::TSBK* tsbk, uint8_t * data);
/// Helper to automatically inhibit a source ID on a denial.
void denialInhibit(uint32_t srcId);
diff --git a/p25/packet/Voice.cpp b/p25/packet/Voice.cpp
index 14955144..c754f56c 100644
--- a/p25/packet/Voice.cpp
+++ b/p25/packet/Voice.cpp
@@ -64,7 +64,7 @@ const uint32_t VOC_LDU1_COUNT = 3U;
///
void Voice::resetRF()
{
- lc::LC lc = lc::LC(m_p25->m_siteData);
+ lc::LC lc = lc::LC();
m_rfLC = lc;
//m_rfLastHDU = lc;
@@ -83,7 +83,7 @@ void Voice::resetRF()
///
void Voice::resetNet()
{
- lc::LC lc = lc::LC(m_p25->m_siteData);
+ lc::LC lc = lc::LC();
m_netLC = lc;
m_netLastLDU1 = lc;
@@ -154,7 +154,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
resetRF();
resetNet();
- lc::LC lc = lc::LC(m_p25->m_siteData);
+ lc::LC lc = lc::LC();
bool ret = lc.decodeHDU(data + 2U);
if (!ret) {
LogWarning(LOG_RF, P25_HDU_STR ", undecodable LC");
@@ -217,7 +217,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
}
}
- lc::LC lc = lc::LC(m_p25->m_siteData);
+ lc::LC lc = lc::LC();
bool ret = lc.decodeLDU1(data + 2U);
if (!ret) {
return false;
@@ -252,15 +252,12 @@ bool Voice::process(uint8_t* data, uint32_t len)
}
}
- m_p25->m_trunk->m_rfTSBK = lc::TSBK(&lc);
- m_p25->m_trunk->m_rfTSBK.setVerbose(m_p25->m_trunk->m_dumpTSBK);
-
// validate the source RID
if (!acl::AccessControl::validateSrcId(srcId)) {
if (m_lastRejectId == 0U || m_lastRejectId != srcId) {
LogWarning(LOG_RF, P25_HDU_STR " denial, RID rejection, srcId = %u", srcId);
if (m_p25->m_control) {
- m_p25->m_trunk->writeRF_TSDU_Deny(P25_DENY_RSN_REQ_UNIT_NOT_VALID, (group ? TSBK_IOSP_GRP_VCH : TSBK_IOSP_UU_VCH));
+ m_p25->m_trunk->writeRF_TSDU_Deny(srcId, P25_DENY_RSN_REQ_UNIT_NOT_VALID, (group ? TSBK_IOSP_GRP_VCH : TSBK_IOSP_UU_VCH));
m_p25->m_trunk->denialInhibit(srcId);
}
@@ -281,7 +278,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
if (m_lastRejectId == 0 || m_lastRejectId != dstId) {
LogWarning(LOG_RF, P25_HDU_STR " denial, RID rejection, dstId = %u", dstId);
if (m_p25->m_control) {
- m_p25->m_trunk->writeRF_TSDU_Deny(P25_DENY_RSN_TGT_UNIT_NOT_VALID, TSBK_IOSP_UU_VCH);
+ m_p25->m_trunk->writeRF_TSDU_Deny(srcId, P25_DENY_RSN_TGT_UNIT_NOT_VALID, TSBK_IOSP_UU_VCH);
}
::ActivityLog("P25", true, "RF voice rejection from %u to %s%u ", srcId, group ? "TG " : "", dstId);
@@ -300,7 +297,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
if (m_lastRejectId == 0 || m_lastRejectId != dstId) {
LogWarning(LOG_RF, P25_HDU_STR " denial, TGID rejection, dstId = %u", dstId);
if (m_p25->m_control) {
- m_p25->m_trunk->writeRF_TSDU_Deny(P25_DENY_RSN_TGT_GROUP_NOT_VALID, TSBK_IOSP_GRP_VCH);
+ m_p25->m_trunk->writeRF_TSDU_Deny(srcId, P25_DENY_RSN_TGT_GROUP_NOT_VALID, TSBK_IOSP_GRP_VCH);
}
::ActivityLog("P25", true, "RF voice rejection from %u to %s%u ", srcId, group ? "TG " : "", dstId);
@@ -320,7 +317,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
if (!m_p25->m_affiliations.isGroupAff(srcId, dstId) && m_p25->m_trunk->m_verifyAff) {
if (m_lastRejectId == 0 || m_lastRejectId != srcId) {
LogWarning(LOG_RF, P25_HDU_STR " denial, RID not affiliated to TGID, srcId = %u, dstId = %u", srcId, dstId);
- m_p25->m_trunk->writeRF_TSDU_Deny(P25_DENY_RSN_REQ_UNIT_NOT_AUTH, TSBK_IOSP_GRP_VCH);
+ m_p25->m_trunk->writeRF_TSDU_Deny(srcId, P25_DENY_RSN_REQ_UNIT_NOT_AUTH, TSBK_IOSP_GRP_VCH);
m_p25->m_trunk->writeRF_TSDU_U_Reg_Cmd(srcId);
::ActivityLog("P25", true, "RF voice rejection from %u to %s%u ", srcId, group ? "TG " : "", dstId);
@@ -340,6 +337,10 @@ bool Voice::process(uint8_t* data, uint32_t len)
m_lastRejectId = 0U;
::ActivityLog("P25", true, "RF %svoice transmission from %u to %s%u", encrypted ? "encrypted ": "", srcId, group ? "TG " : "", dstId);
+ uint8_t serviceOptions = (m_rfLC.getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
+ (m_rfLC.getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
+ (m_rfLC.getPriority() & 0x07U); // Priority
+
if (m_p25->m_control) {
// if the group wasn't granted out -- explicitly grant the group
if (!m_p25->m_affiliations.isGranted(dstId)) {
@@ -353,7 +354,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
}
}
- if (!m_p25->m_trunk->writeRF_TSDU_Grant(group)) {
+ if (!m_p25->m_trunk->writeRF_TSDU_Grant(srcId, dstId, serviceOptions, group)) {
return false;
}
}
@@ -365,7 +366,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
// single-channel trunking or voice on control support?
if (m_p25->m_control && m_p25->m_voiceOnControl) {
- m_p25->m_trunk->writeRF_TSDU_Grant(group, true);
+ m_p25->m_trunk->writeRF_TSDU_Grant(srcId, dstId, serviceOptions, group, true);
}
m_hadVoice = true;
@@ -429,7 +430,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
m_p25->m_rfTimeout.start();
m_lastDUID = P25_DUID_HDU;
- m_rfLastHDU = lc::LC(m_p25->m_siteData);
+ m_rfLastHDU = lc::LC();
}
if (m_p25->m_rfState == RS_RF_AUDIO) {
@@ -639,7 +640,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
m_p25->m_rfTimeout.stop();
}
else {
- lc::TDULC tdulc = lc::TDULC(m_p25->m_siteData, m_p25->m_idenEntry, m_p25->m_trunk->m_dumpTSBK);
+ lc::TDULC tdulc = lc::TDULC();
bool ret = tdulc.decode(data + 2U);
if (!ret) {
LogWarning(LOG_RF, P25_LDU2_STR ", undecodable TDULC");
@@ -807,9 +808,6 @@ bool Voice::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::L
resetRF();
resetNet();
- m_p25->m_trunk->m_rfTSBK = lc::TSBK(m_p25->m_siteData, m_p25->m_idenEntry, m_p25->m_trunk->m_dumpTSBK);
- m_p25->m_trunk->m_netTSBK = lc::TSBK(m_p25->m_siteData, m_p25->m_idenEntry, m_p25->m_trunk->m_dumpTSBK);
-
writeNet_LDU1();
}
else {
@@ -866,12 +864,12 @@ Voice::Voice(Control* p25, network::BaseNetwork* network, bool debug, bool verbo
m_netFrames(0U),
m_netLost(0U),
m_audio(),
- m_rfLC(SiteData()),
- m_rfLastHDU(SiteData()),
- m_rfLastLDU1(SiteData()),
- m_rfLastLDU2(SiteData()),
- m_netLC(SiteData()),
- m_netLastLDU1(SiteData()),
+ m_rfLC(),
+ m_rfLastHDU(),
+ m_rfLastLDU1(),
+ m_rfLastLDU2(),
+ m_netLC(),
+ m_netLastLDU1(),
m_rfLSD(),
m_netLSD(),
m_dfsiLC(),
@@ -1101,7 +1099,7 @@ void Voice::writeNet_LDU1()
}
// set network and RF link control states
- m_netLC = lc::LC(m_p25->m_siteData);
+ m_netLC = lc::LC();
m_netLC.setLCO(control.getLCO());
m_netLC.setMFId(control.getMFId());
m_netLC.setSrcId(srcId);
@@ -1111,7 +1109,7 @@ void Voice::writeNet_LDU1()
m_netLC.setEncrypted(control.getEncrypted());
m_netLC.setPriority(control.getPriority());
- m_rfLC = lc::LC(m_p25->m_siteData);
+ m_rfLC = lc::LC();
m_rfLC.setLCO(control.getLCO());
m_rfLC.setMFId(control.getMFId());
m_rfLC.setSrcId(srcId);
@@ -1137,11 +1135,6 @@ void Voice::writeNet_LDU1()
m_netLC.setKId(control.getKId());
m_rfLC.setKId(control.getKId());
- m_p25->m_trunk->m_rfTSBK = lc::TSBK(&m_rfLC);
- m_p25->m_trunk->m_rfTSBK.setVerbose(m_p25->m_trunk->m_dumpTSBK);
- m_p25->m_trunk->m_netTSBK = lc::TSBK(&m_netLC);
- m_p25->m_trunk->m_netTSBK.setVerbose(m_p25->m_trunk->m_dumpTSBK);
-
// validate source RID
if (!acl::AccessControl::validateSrcId(srcId)) {
LogWarning(LOG_NET, P25_HDU_STR " denial, RID rejection, srcId = %u", srcId);
@@ -1170,7 +1163,11 @@ void Voice::writeNet_LDU1()
// single-channel trunking or voice on control support?
if (m_p25->m_control && m_p25->m_voiceOnControl) {
- if (!m_p25->m_trunk->writeRF_TSDU_Grant(group, false, true)) {
+ uint8_t serviceOptions = (m_netLC.getEmergency() ? 0x80U : 0x00U) + // Emergency Flag
+ (m_netLC.getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag
+ (m_netLC.getPriority() & 0x07U); // Priority
+
+ if (!m_p25->m_trunk->writeRF_TSDU_Grant(srcId, dstId, serviceOptions, group, false, true)) {
if (m_network != NULL)
m_network->resetP25();
@@ -1180,8 +1177,8 @@ void Voice::writeNet_LDU1()
m_p25->m_netTimeout.stop();
m_p25->m_networkWatchdog.stop();
- m_netLC = lc::LC(m_p25->m_siteData);
- m_netLastLDU1 = lc::LC(m_p25->m_siteData);
+ m_netLC = lc::LC();
+ m_netLastLDU1 = lc::LC();
m_p25->m_netState = RS_NET_IDLE;
m_p25->m_netLastDstId = 0U;