diff --git a/p25/P25Defines.h b/p25/P25Defines.h
index c84b4adb..a35377fc 100644
--- a/p25/P25Defines.h
+++ b/p25/P25Defines.h
@@ -304,12 +304,14 @@ namespace p25
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_STS_Q_REQ = 0x1CU; // STS_Q_REQ - Status Query Request
- const uint8_t TSBK_ISP_AUTH_Q = 0x2EU; // AUTH_Q - Authentication Query
- const uint8_t TSBK_ISP_AUTH_RSP = 0x2FU; // AUTH_RSP - Authentication 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_AUTH_FNE_RST = 0x3AU; // AUTH_FNE_RST - Authentication FNE Result
+ 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_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
@@ -331,8 +333,12 @@ namespace p25
const uint8_t TSBK_OSP_ADJ_STS_BCAST = 0x3CU; // ADJ STS BCAST - Adjacent Site Status Broadcast
const uint8_t TSBK_OSP_IDEN_UP = 0x3DU; // IDEN UP - Channel Identifier Update
const uint8_t TSBK_OSP_STS_Q = 0x1AU; // STS_Q - Status Query
- const uint8_t TSBK_OSP_AUTH_CMD = 0x2EU; // AUTH_CMD - Authentication Command
-
+ 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_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
+
+
// TSBK Motorola Outbound Signalling Packet (OSP) Opcode(s)
const uint8_t TSBK_OSP_MOT_GRG_ADD = 0x00U; // MOT GRG ADD - Motorola / Group Regroup Add (Patch Supergroup)
const uint8_t TSBK_OSP_MOT_GRG_DEL = 0x01U; // MOT GRG DEL - Motorola / Group Regroup Delete (Unpatch Supergroup)
diff --git a/p25/lc/LC.h b/p25/lc/LC.h
index d08f6e0e..f6175f6b 100644
--- a/p25/lc/LC.h
+++ b/p25/lc/LC.h
@@ -46,7 +46,7 @@ namespace p25
// ---------------------------------------------------------------------------
// Class Prototypes
// ---------------------------------------------------------------------------
-
+
class HOST_SW_API TSBK;
class HOST_SW_API TDULC;
diff --git a/p25/lc/TSBK.cpp b/p25/lc/TSBK.cpp
index bb7bfbaf..94f20e30 100644
--- a/p25/lc/TSBK.cpp
+++ b/p25/lc/TSBK.cpp
@@ -8,6 +8,7 @@
*/
/*
* Copyright (C) 2017-2022 by Bryan Biedenkapp N2PLL
+* Copyright (C) 2022 by Rosesam N5UWU
*
* 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
@@ -535,6 +536,11 @@ bool TSBK::decode(const uint8_t* data, bool rawTSBK)
m_adjChannelNo = (uint32_t)((tsbkValue >> 8) & 0xFFFU); // Site Channel Number
m_adjServiceClass = (uint8_t)(tsbkValue & 0xFFU); // Site Service Class
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;
default:
LogError(LOG_P25, "TSBK::decode(), unknown TSBK LCO value, mfId = $%02X, lco = $%02X", m_mfId, m_lco);
break;
@@ -945,6 +951,12 @@ void TSBK::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
#endif
}
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;
default:
if (m_mfId == P25_MFG_STANDARD) {
LogError(LOG_P25, "TSBK::encode(), unknown TSBK LCO value, mfId = $%02X, lco = $%02X", m_mfId, m_lco);
diff --git a/p25/lc/TSBK.h b/p25/lc/TSBK.h
index 6e1afbb4..dfff6904 100644
--- a/p25/lc/TSBK.h
+++ b/p25/lc/TSBK.h
@@ -54,7 +54,7 @@ namespace p25
// ---------------------------------------------------------------------------
// Class Prototypes
// ---------------------------------------------------------------------------
-
+
class HOST_SW_API LC;
class HOST_SW_API TDULC;
@@ -207,6 +207,10 @@ namespace p25
/// Local Site Identity Entry.
__PROPERTY_PLAIN(::lookups::IdenTable, siteIdenEntry, siteIdenEntry);
+ /** Radio Unit Monitor */
+ /// Radio Unit Monitor.
+ __PROPERTY(uint8_t, txMult, TxMult);
+
private:
/// Initializes a new instance of the TSBK class.
TSBK();
diff --git a/p25/packet/Trunk.cpp b/p25/packet/Trunk.cpp
index e62d4d9f..e6ced07f 100644
--- a/p25/packet/Trunk.cpp
+++ b/p25/packet/Trunk.cpp
@@ -8,6 +8,7 @@
*/
/*
* Copyright (C) 2017-2022 by Bryan Biedenkapp N2PLL
+* Copyright (C) 2022 by Rosesam N5UWU
*
* 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
@@ -213,6 +214,7 @@ bool Trunk::process(uint8_t* data, uint32_t len, bool preDecoded)
uint32_t srcId = m_rfTSBK.getSrcId();
uint32_t dstId = m_rfTSBK.getDstId();
+ uint8_t txMult = m_rfTSBK.getTxMult();
// handle standard P25 reference opcodes
switch (m_rfTSBK.getLCO()) {
@@ -504,6 +506,21 @@ bool Trunk::process(uint8_t* data, uint32_t len, bool preDecoded)
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;
default:
LogError(LOG_RF, P25_TSDU_STR ", unhandled LCO, mfId = $%02X, lco = $%02X", m_rfTSBK.getMFId(), m_rfTSBK.getLCO());
break;
@@ -606,6 +623,7 @@ bool Trunk::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::L
uint32_t srcId = m_netTSBK.getSrcId();
uint32_t dstId = m_netTSBK.getDstId();
+ uint8_t txMult = m_rfTSBK.getTxMult();
// handle internal DVM TSDUs
if (m_netTSBK.getMFId() == P25_MFG_DVM) {
@@ -780,6 +798,21 @@ bool Trunk::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::L
m_netTSBK.getAIV(), m_netTSBK.getResponse(), m_netTSBK.getSrcId(), m_netTSBK.getDstId());
}
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;
default:
LogError(LOG_NET, P25_TSDU_STR ", unhandled LCO, mfId = $%02X, lco = $%02X", m_netTSBK.getMFId(), m_netTSBK.getLCO());
return false;
@@ -959,6 +992,27 @@ void Trunk::writeRF_TSDU_Call_Alrt(uint32_t srcId, uint32_t dstId)
writeRF_TSDU_SBF(false);
}
+///
+/// Helper to write a radio monitor packet.
+///
+///
+///
+///
+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);
+ }
+
+ ::ActivityLog("P25" , true , "call alert 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);
+}
+
///
/// Helper to write a extended function packet.
///
@@ -1838,7 +1892,7 @@ void Trunk::queueRF_TSBK_Ctrl(uint8_t lco)
if (m_debug) {
LogMessage(LOG_RF , P25_TSDU_STR ", TSBK_OSP_TIME_DATE_ANN (Time Date Announce)");
}
-
+
m_rfTSBK.setLCO(TSBK_OSP_TIME_DATE_ANN);
m_rfTSBK.setMFId(P25_MFG_STANDARD);
break;
diff --git a/p25/packet/Trunk.h b/p25/packet/Trunk.h
index 904177c7..41401a44 100644
--- a/p25/packet/Trunk.h
+++ b/p25/packet/Trunk.h
@@ -46,7 +46,7 @@ namespace p25
// ---------------------------------------------------------------------------
// Class Prototypes
// ---------------------------------------------------------------------------
-
+
namespace packet { class HOST_SW_API Voice; }
namespace dfsi { namespace packet { class HOST_SW_API DFSIVoice; } }
namespace packet { class HOST_SW_API Data; }
@@ -85,6 +85,8 @@ namespace p25
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 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.
@@ -137,7 +139,7 @@ namespace p25
bool m_noStatusAck;
bool m_noMessageAck;
bool m_unitToUnitAvailCheck;
-
+
uint8_t m_convFallbackPacketDelay;
bool m_convFallback;