From 3254122c4d6f29edd57078317c36144920ca411e Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Sat, 15 Oct 2022 02:31:48 -0400 Subject: [PATCH] P25 code refactor to move TSBK handling to a "factory-based paradigm"; --- CMakeLists.txt | 4 +- Defines.h | 42 +- host/calibrate/HostCal.cpp | 18 +- network/BaseNetwork.cpp | 20 +- network/BaseNetwork.h | 5 +- network/RemoteControl.cpp | 40 +- p25/Control.cpp | 20 +- p25/P25Defines.h | 22 +- p25/dfsi/LC.cpp | 21 +- p25/dfsi/LC.h | 2 +- p25/dfsi/packet/DFSITrunk.cpp | 63 +- p25/dfsi/packet/DFSITrunk.h | 13 +- p25/dfsi/packet/DFSIVoice.cpp | 43 +- p25/lc/AMBT.cpp | 178 +++ p25/lc/AMBT.h | 70 ++ p25/lc/LC.cpp | 17 +- p25/lc/LC.h | 15 +- p25/lc/TDULC.cpp | 100 +- p25/lc/TDULC.h | 41 +- p25/lc/TSBK.cpp | 1495 ++---------------------- p25/lc/TSBK.h | 203 +--- p25/lc/tsbk/IOSP_ACK_RSP.cpp | 104 ++ p25/lc/tsbk/IOSP_ACK_RSP.h | 58 + p25/lc/tsbk/IOSP_CALL_ALRT.cpp | 93 ++ p25/lc/tsbk/IOSP_CALL_ALRT.h | 58 + p25/lc/tsbk/IOSP_EXT_FNCT.cpp | 111 ++ p25/lc/tsbk/IOSP_EXT_FNCT.h | 64 + p25/lc/tsbk/IOSP_GRP_AFF.cpp | 113 ++ p25/lc/tsbk/IOSP_GRP_AFF.h | 64 + p25/lc/tsbk/IOSP_GRP_VCH.cpp | 104 ++ p25/lc/tsbk/IOSP_GRP_VCH.h | 58 + p25/lc/tsbk/IOSP_MSG_UPDT.cpp | 111 ++ p25/lc/tsbk/IOSP_MSG_UPDT.h | 64 + p25/lc/tsbk/IOSP_RAD_MON.cpp | 112 ++ p25/lc/tsbk/IOSP_RAD_MON.h | 65 ++ p25/lc/tsbk/IOSP_STS_UPDT.cpp | 111 ++ p25/lc/tsbk/IOSP_STS_UPDT.h | 64 + p25/lc/tsbk/IOSP_UU_ANS.cpp | 101 ++ p25/lc/tsbk/IOSP_UU_ANS.h | 61 + p25/lc/tsbk/IOSP_UU_VCH.cpp | 104 ++ p25/lc/tsbk/IOSP_UU_VCH.h | 58 + p25/lc/tsbk/IOSP_U_REG.cpp | 96 ++ p25/lc/tsbk/IOSP_U_REG.h | 58 + p25/lc/tsbk/ISP_AUTH_FNE_RST.cpp | 105 ++ p25/lc/tsbk/ISP_AUTH_FNE_RST.h | 65 ++ p25/lc/tsbk/ISP_AUTH_RESP.cpp | 136 +++ p25/lc/tsbk/ISP_AUTH_RESP.h | 73 ++ p25/lc/tsbk/ISP_AUTH_SU_DMD.cpp | 85 ++ p25/lc/tsbk/ISP_AUTH_SU_DMD.h | 57 + p25/lc/tsbk/ISP_CAN_SRV_REQ.cpp | 89 ++ p25/lc/tsbk/ISP_CAN_SRV_REQ.h | 57 + p25/lc/tsbk/ISP_EMERG_ALRM_REQ.cpp | 100 ++ p25/lc/tsbk/ISP_EMERG_ALRM_REQ.h | 57 + p25/lc/tsbk/ISP_GRP_AFF_Q_RSP.cpp | 103 ++ p25/lc/tsbk/ISP_GRP_AFF_Q_RSP.h | 63 + p25/lc/tsbk/ISP_LOC_REG_REQ.cpp | 103 ++ p25/lc/tsbk/ISP_LOC_REG_REQ.h | 63 + p25/lc/tsbk/ISP_SNDCP_CH_REQ.cpp | 105 ++ p25/lc/tsbk/ISP_SNDCP_CH_REQ.h | 65 ++ p25/lc/tsbk/ISP_U_DEREG_REQ.cpp | 87 ++ p25/lc/tsbk/ISP_U_DEREG_REQ.h | 57 + p25/lc/tsbk/MBT_IOSP_ACK_RSP.cpp | 91 ++ p25/lc/tsbk/MBT_IOSP_ACK_RSP.h | 58 + p25/lc/tsbk/MBT_IOSP_CALL_ALRT.cpp | 89 ++ p25/lc/tsbk/MBT_IOSP_CALL_ALRT.h | 58 + p25/lc/tsbk/MBT_IOSP_EXT_FNCT.cpp | 106 ++ p25/lc/tsbk/MBT_IOSP_EXT_FNCT.h | 64 + p25/lc/tsbk/MBT_IOSP_GRP_AFF.cpp | 89 ++ p25/lc/tsbk/MBT_IOSP_GRP_AFF.h | 58 + p25/lc/tsbk/MBT_IOSP_MSG_UPDT.cpp | 106 ++ p25/lc/tsbk/MBT_IOSP_MSG_UPDT.h | 64 + p25/lc/tsbk/MBT_IOSP_STS_UPDT.cpp | 106 ++ p25/lc/tsbk/MBT_IOSP_STS_UPDT.h | 64 + p25/lc/tsbk/MBT_ISP_AUTH_RESP_M.cpp | 184 +++ p25/lc/tsbk/MBT_ISP_AUTH_RESP_M.h | 79 ++ p25/lc/tsbk/MBT_ISP_AUTH_SU_DMD.cpp | 88 ++ p25/lc/tsbk/MBT_ISP_AUTH_SU_DMD.h | 57 + p25/lc/tsbk/MBT_ISP_CAN_SRV_REQ.cpp | 93 ++ p25/lc/tsbk/MBT_ISP_CAN_SRV_REQ.h | 57 + p25/lc/tsbk/MBT_OSP_ADJ_STS_BCAST.cpp | 133 +++ p25/lc/tsbk/MBT_OSP_ADJ_STS_BCAST.h | 76 ++ p25/lc/tsbk/MBT_OSP_AUTH_DMD.cpp | 188 +++ p25/lc/tsbk/MBT_OSP_AUTH_DMD.h | 76 ++ p25/lc/tsbk/MBT_OSP_NET_STS_BCAST.cpp | 92 ++ p25/lc/tsbk/MBT_OSP_NET_STS_BCAST.h | 57 + p25/lc/tsbk/MBT_OSP_RFSS_STS_BCAST.cpp | 94 ++ p25/lc/tsbk/MBT_OSP_RFSS_STS_BCAST.h | 57 + p25/lc/tsbk/OSP_ADJ_STS_BCAST.cpp | 130 +++ p25/lc/tsbk/OSP_ADJ_STS_BCAST.h | 76 ++ p25/lc/tsbk/OSP_AUTH_FNE_RESP.cpp | 135 +++ p25/lc/tsbk/OSP_AUTH_FNE_RESP.h | 69 ++ p25/lc/tsbk/OSP_DENY_RSP.cpp | 114 ++ p25/lc/tsbk/OSP_DENY_RSP.h | 57 + p25/lc/tsbk/OSP_DVM_GIT_HASH.cpp | 90 ++ p25/lc/tsbk/OSP_DVM_GIT_HASH.h | 57 + p25/lc/tsbk/OSP_DVM_LC_CALL_TERM.cpp | 98 ++ p25/lc/tsbk/OSP_DVM_LC_CALL_TERM.h | 57 + p25/lc/tsbk/OSP_GRP_AFF_Q.cpp | 83 ++ p25/lc/tsbk/OSP_GRP_AFF_Q.h | 57 + p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.cpp | 85 ++ p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.h | 57 + p25/lc/tsbk/OSP_IDEN_UP.cpp | 111 ++ p25/lc/tsbk/OSP_IDEN_UP.h | 57 + p25/lc/tsbk/OSP_IDEN_UP_VU.cpp | 105 ++ p25/lc/tsbk/OSP_IDEN_UP_VU.h | 57 + p25/lc/tsbk/OSP_LOC_REG_RSP.cpp | 86 ++ p25/lc/tsbk/OSP_LOC_REG_RSP.h | 57 + p25/lc/tsbk/OSP_MOT_CC_BSI.cpp | 88 ++ p25/lc/tsbk/OSP_MOT_CC_BSI.h | 57 + p25/lc/tsbk/OSP_MOT_GRG_ADD.cpp | 119 ++ p25/lc/tsbk/OSP_MOT_GRG_ADD.h | 69 ++ p25/lc/tsbk/OSP_MOT_GRG_DEL.cpp | 124 ++ p25/lc/tsbk/OSP_MOT_GRG_DEL.h | 69 ++ p25/lc/tsbk/OSP_MOT_GRG_VCH_GRANT.cpp | 109 ++ p25/lc/tsbk/OSP_MOT_GRG_VCH_GRANT.h | 63 + p25/lc/tsbk/OSP_MOT_GRG_VCH_UPD.cpp | 105 ++ p25/lc/tsbk/OSP_MOT_GRG_VCH_UPD.h | 65 ++ p25/lc/tsbk/OSP_MOT_PSH_CCH.cpp | 81 ++ p25/lc/tsbk/OSP_MOT_PSH_CCH.h | 57 + p25/lc/tsbk/OSP_NET_STS_BCAST.cpp | 87 ++ p25/lc/tsbk/OSP_NET_STS_BCAST.h | 57 + p25/lc/tsbk/OSP_QUE_RSP.cpp | 114 ++ p25/lc/tsbk/OSP_QUE_RSP.h | 57 + p25/lc/tsbk/OSP_RFSS_STS_BCAST.cpp | 90 ++ p25/lc/tsbk/OSP_RFSS_STS_BCAST.h | 57 + p25/lc/tsbk/OSP_SCCB.cpp | 115 ++ p25/lc/tsbk/OSP_SCCB.h | 65 ++ p25/lc/tsbk/OSP_SCCB_EXP.cpp | 113 ++ p25/lc/tsbk/OSP_SCCB_EXP.h | 65 ++ p25/lc/tsbk/OSP_SNDCP_CH_ANN.cpp | 119 ++ p25/lc/tsbk/OSP_SNDCP_CH_ANN.h | 63 + p25/lc/tsbk/OSP_SNDCP_CH_GNT.cpp | 115 ++ p25/lc/tsbk/OSP_SNDCP_CH_GNT.h | 65 ++ p25/lc/tsbk/OSP_SYNC_BCAST.cpp | 145 +++ p25/lc/tsbk/OSP_SYNC_BCAST.h | 63 + p25/lc/tsbk/OSP_SYS_SRV_BCAST.cpp | 85 ++ p25/lc/tsbk/OSP_SYS_SRV_BCAST.h | 57 + p25/lc/tsbk/OSP_U_DEREG_ACK.cpp | 95 ++ p25/lc/tsbk/OSP_U_DEREG_ACK.h | 57 + p25/lc/tsbk/OSP_U_REG_CMD.cpp | 83 ++ p25/lc/tsbk/OSP_U_REG_CMD.h | 57 + p25/lc/tsbk/TSBKFactory.cpp | 371 ++++++ p25/lc/tsbk/TSBKFactory.h | 134 +++ p25/packet/Trunk.cpp | 1421 +++++++++++----------- p25/packet/Trunk.h | 53 +- p25/packet/Voice.cpp | 65 +- 146 files changed, 12008 insertions(+), 2522 deletions(-) create mode 100644 p25/lc/AMBT.cpp create mode 100644 p25/lc/AMBT.h create mode 100644 p25/lc/tsbk/IOSP_ACK_RSP.cpp create mode 100644 p25/lc/tsbk/IOSP_ACK_RSP.h create mode 100644 p25/lc/tsbk/IOSP_CALL_ALRT.cpp create mode 100644 p25/lc/tsbk/IOSP_CALL_ALRT.h create mode 100644 p25/lc/tsbk/IOSP_EXT_FNCT.cpp create mode 100644 p25/lc/tsbk/IOSP_EXT_FNCT.h create mode 100644 p25/lc/tsbk/IOSP_GRP_AFF.cpp create mode 100644 p25/lc/tsbk/IOSP_GRP_AFF.h create mode 100644 p25/lc/tsbk/IOSP_GRP_VCH.cpp create mode 100644 p25/lc/tsbk/IOSP_GRP_VCH.h create mode 100644 p25/lc/tsbk/IOSP_MSG_UPDT.cpp create mode 100644 p25/lc/tsbk/IOSP_MSG_UPDT.h create mode 100644 p25/lc/tsbk/IOSP_RAD_MON.cpp create mode 100644 p25/lc/tsbk/IOSP_RAD_MON.h create mode 100644 p25/lc/tsbk/IOSP_STS_UPDT.cpp create mode 100644 p25/lc/tsbk/IOSP_STS_UPDT.h create mode 100644 p25/lc/tsbk/IOSP_UU_ANS.cpp create mode 100644 p25/lc/tsbk/IOSP_UU_ANS.h create mode 100644 p25/lc/tsbk/IOSP_UU_VCH.cpp create mode 100644 p25/lc/tsbk/IOSP_UU_VCH.h create mode 100644 p25/lc/tsbk/IOSP_U_REG.cpp create mode 100644 p25/lc/tsbk/IOSP_U_REG.h create mode 100644 p25/lc/tsbk/ISP_AUTH_FNE_RST.cpp create mode 100644 p25/lc/tsbk/ISP_AUTH_FNE_RST.h create mode 100644 p25/lc/tsbk/ISP_AUTH_RESP.cpp create mode 100644 p25/lc/tsbk/ISP_AUTH_RESP.h create mode 100644 p25/lc/tsbk/ISP_AUTH_SU_DMD.cpp create mode 100644 p25/lc/tsbk/ISP_AUTH_SU_DMD.h create mode 100644 p25/lc/tsbk/ISP_CAN_SRV_REQ.cpp create mode 100644 p25/lc/tsbk/ISP_CAN_SRV_REQ.h create mode 100644 p25/lc/tsbk/ISP_EMERG_ALRM_REQ.cpp create mode 100644 p25/lc/tsbk/ISP_EMERG_ALRM_REQ.h create mode 100644 p25/lc/tsbk/ISP_GRP_AFF_Q_RSP.cpp create mode 100644 p25/lc/tsbk/ISP_GRP_AFF_Q_RSP.h create mode 100644 p25/lc/tsbk/ISP_LOC_REG_REQ.cpp create mode 100644 p25/lc/tsbk/ISP_LOC_REG_REQ.h create mode 100644 p25/lc/tsbk/ISP_SNDCP_CH_REQ.cpp create mode 100644 p25/lc/tsbk/ISP_SNDCP_CH_REQ.h create mode 100644 p25/lc/tsbk/ISP_U_DEREG_REQ.cpp create mode 100644 p25/lc/tsbk/ISP_U_DEREG_REQ.h create mode 100644 p25/lc/tsbk/MBT_IOSP_ACK_RSP.cpp create mode 100644 p25/lc/tsbk/MBT_IOSP_ACK_RSP.h create mode 100644 p25/lc/tsbk/MBT_IOSP_CALL_ALRT.cpp create mode 100644 p25/lc/tsbk/MBT_IOSP_CALL_ALRT.h create mode 100644 p25/lc/tsbk/MBT_IOSP_EXT_FNCT.cpp create mode 100644 p25/lc/tsbk/MBT_IOSP_EXT_FNCT.h create mode 100644 p25/lc/tsbk/MBT_IOSP_GRP_AFF.cpp create mode 100644 p25/lc/tsbk/MBT_IOSP_GRP_AFF.h create mode 100644 p25/lc/tsbk/MBT_IOSP_MSG_UPDT.cpp create mode 100644 p25/lc/tsbk/MBT_IOSP_MSG_UPDT.h create mode 100644 p25/lc/tsbk/MBT_IOSP_STS_UPDT.cpp create mode 100644 p25/lc/tsbk/MBT_IOSP_STS_UPDT.h create mode 100644 p25/lc/tsbk/MBT_ISP_AUTH_RESP_M.cpp create mode 100644 p25/lc/tsbk/MBT_ISP_AUTH_RESP_M.h create mode 100644 p25/lc/tsbk/MBT_ISP_AUTH_SU_DMD.cpp create mode 100644 p25/lc/tsbk/MBT_ISP_AUTH_SU_DMD.h create mode 100644 p25/lc/tsbk/MBT_ISP_CAN_SRV_REQ.cpp create mode 100644 p25/lc/tsbk/MBT_ISP_CAN_SRV_REQ.h create mode 100644 p25/lc/tsbk/MBT_OSP_ADJ_STS_BCAST.cpp create mode 100644 p25/lc/tsbk/MBT_OSP_ADJ_STS_BCAST.h create mode 100644 p25/lc/tsbk/MBT_OSP_AUTH_DMD.cpp create mode 100644 p25/lc/tsbk/MBT_OSP_AUTH_DMD.h create mode 100644 p25/lc/tsbk/MBT_OSP_NET_STS_BCAST.cpp create mode 100644 p25/lc/tsbk/MBT_OSP_NET_STS_BCAST.h create mode 100644 p25/lc/tsbk/MBT_OSP_RFSS_STS_BCAST.cpp create mode 100644 p25/lc/tsbk/MBT_OSP_RFSS_STS_BCAST.h create mode 100644 p25/lc/tsbk/OSP_ADJ_STS_BCAST.cpp create mode 100644 p25/lc/tsbk/OSP_ADJ_STS_BCAST.h create mode 100644 p25/lc/tsbk/OSP_AUTH_FNE_RESP.cpp create mode 100644 p25/lc/tsbk/OSP_AUTH_FNE_RESP.h create mode 100644 p25/lc/tsbk/OSP_DENY_RSP.cpp create mode 100644 p25/lc/tsbk/OSP_DENY_RSP.h create mode 100644 p25/lc/tsbk/OSP_DVM_GIT_HASH.cpp create mode 100644 p25/lc/tsbk/OSP_DVM_GIT_HASH.h create mode 100644 p25/lc/tsbk/OSP_DVM_LC_CALL_TERM.cpp create mode 100644 p25/lc/tsbk/OSP_DVM_LC_CALL_TERM.h create mode 100644 p25/lc/tsbk/OSP_GRP_AFF_Q.cpp create mode 100644 p25/lc/tsbk/OSP_GRP_AFF_Q.h create mode 100644 p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.cpp create mode 100644 p25/lc/tsbk/OSP_GRP_VCH_GRANT_UPD.h create mode 100644 p25/lc/tsbk/OSP_IDEN_UP.cpp create mode 100644 p25/lc/tsbk/OSP_IDEN_UP.h create mode 100644 p25/lc/tsbk/OSP_IDEN_UP_VU.cpp create mode 100644 p25/lc/tsbk/OSP_IDEN_UP_VU.h create mode 100644 p25/lc/tsbk/OSP_LOC_REG_RSP.cpp create mode 100644 p25/lc/tsbk/OSP_LOC_REG_RSP.h create mode 100644 p25/lc/tsbk/OSP_MOT_CC_BSI.cpp create mode 100644 p25/lc/tsbk/OSP_MOT_CC_BSI.h create mode 100644 p25/lc/tsbk/OSP_MOT_GRG_ADD.cpp create mode 100644 p25/lc/tsbk/OSP_MOT_GRG_ADD.h create mode 100644 p25/lc/tsbk/OSP_MOT_GRG_DEL.cpp create mode 100644 p25/lc/tsbk/OSP_MOT_GRG_DEL.h create mode 100644 p25/lc/tsbk/OSP_MOT_GRG_VCH_GRANT.cpp create mode 100644 p25/lc/tsbk/OSP_MOT_GRG_VCH_GRANT.h create mode 100644 p25/lc/tsbk/OSP_MOT_GRG_VCH_UPD.cpp create mode 100644 p25/lc/tsbk/OSP_MOT_GRG_VCH_UPD.h create mode 100644 p25/lc/tsbk/OSP_MOT_PSH_CCH.cpp create mode 100644 p25/lc/tsbk/OSP_MOT_PSH_CCH.h create mode 100644 p25/lc/tsbk/OSP_NET_STS_BCAST.cpp create mode 100644 p25/lc/tsbk/OSP_NET_STS_BCAST.h create mode 100644 p25/lc/tsbk/OSP_QUE_RSP.cpp create mode 100644 p25/lc/tsbk/OSP_QUE_RSP.h create mode 100644 p25/lc/tsbk/OSP_RFSS_STS_BCAST.cpp create mode 100644 p25/lc/tsbk/OSP_RFSS_STS_BCAST.h create mode 100644 p25/lc/tsbk/OSP_SCCB.cpp create mode 100644 p25/lc/tsbk/OSP_SCCB.h create mode 100644 p25/lc/tsbk/OSP_SCCB_EXP.cpp create mode 100644 p25/lc/tsbk/OSP_SCCB_EXP.h create mode 100644 p25/lc/tsbk/OSP_SNDCP_CH_ANN.cpp create mode 100644 p25/lc/tsbk/OSP_SNDCP_CH_ANN.h create mode 100644 p25/lc/tsbk/OSP_SNDCP_CH_GNT.cpp create mode 100644 p25/lc/tsbk/OSP_SNDCP_CH_GNT.h create mode 100644 p25/lc/tsbk/OSP_SYNC_BCAST.cpp create mode 100644 p25/lc/tsbk/OSP_SYNC_BCAST.h create mode 100644 p25/lc/tsbk/OSP_SYS_SRV_BCAST.cpp create mode 100644 p25/lc/tsbk/OSP_SYS_SRV_BCAST.h create mode 100644 p25/lc/tsbk/OSP_U_DEREG_ACK.cpp create mode 100644 p25/lc/tsbk/OSP_U_DEREG_ACK.h create mode 100644 p25/lc/tsbk/OSP_U_REG_CMD.cpp create mode 100644 p25/lc/tsbk/OSP_U_REG_CMD.h create mode 100644 p25/lc/tsbk/TSBKFactory.cpp create mode 100644 p25/lc/tsbk/TSBKFactory.h 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;