diff --git a/configs/dfsi-config.example.yml b/configs/dfsi-config.example.yml index c2a286e5..9c8aa3f7 100644 --- a/configs/dfsi-config.example.yml +++ b/configs/dfsi-config.example.yml @@ -60,8 +60,11 @@ dfsi: remoteRtpPort: 27500 serial: + # Modem port type. + portType: "uart" # Valid values are "null", and "uart" # Serial configuration for serial DFSI port: "/dev/ttyACM0" + # baudrate: 115200 # RT/RT flag enabled (0x02) or disabled (0x04) rtrt: false diff --git a/src/dfsi/Dfsi.cpp b/src/dfsi/Dfsi.cpp index 5936a1fc..64846bc1 100644 --- a/src/dfsi/Dfsi.cpp +++ b/src/dfsi/Dfsi.cpp @@ -225,49 +225,11 @@ int Dfsi::run() UInt8Array p25Buffer = m_network->readP25(netReadRet, length); if (netReadRet) { - uint8_t duid = p25Buffer[22U]; - uint8_t MFId = p25Buffer[15U]; - - uint8_t lco = p25Buffer[4U]; - - uint32_t srcId = __GET_UINT16(p25Buffer, 5U); - uint32_t dstId = __GET_UINT16(p25Buffer, 8U); - - if (!g_hideMessages) - LogMessage(LOG_NET, "P25, duid = $%02X, lco = $%02X, MFId = $%02X, srcId = %u, dstId = %u, len = %u", duid, lco, MFId, srcId, dstId, length); - // Send the data to the serial handler if serial is up if (m_serial != nullptr) m_serial->processP25FromNet(std::move(p25Buffer), length); } - // We keep DMR & NXDN in so nothing breaks, even though DFSI doesn't do DMR or NXDN - UInt8Array dmrBuffer = m_network->readDMR(netReadRet, length); - if (netReadRet) { - uint8_t seqNo = dmrBuffer[4U]; - - uint32_t srcId = __GET_UINT16(dmrBuffer, 5U); - uint32_t dstId = __GET_UINT16(dmrBuffer, 8U); - - uint8_t flco = (dmrBuffer[15U] & 0x40U) == 0x40U ? dmr::FLCO_PRIVATE : dmr::FLCO_GROUP; - - uint32_t slotNo = (dmrBuffer[15U] & 0x80U) == 0x80U ? 2U : 1U; - - if (!g_hideMessages) - LogMessage(LOG_NET, "DMR, slotNo = %u, seqNo = %u, flco = $%02X, srcId = %u, dstId = %u, len = %u", slotNo, seqNo, flco, srcId, dstId, length); - } - - UInt8Array nxdnBuffer = m_network->readNXDN(netReadRet, length); - if (netReadRet) { - uint8_t messageType = nxdnBuffer[4U]; - - uint32_t srcId = __GET_UINT16(nxdnBuffer, 5U); - uint32_t dstId = __GET_UINT16(nxdnBuffer, 8U); - - if (!g_hideMessages) - LogMessage(LOG_NET, "NXDN, messageType = $%02X, srcId = %u, dstId = %u, len = %u", messageType, srcId, dstId, length); - } - // ------------------------------------------------------ // -- Network TX Clocking -- // ------------------------------------------------------ @@ -414,11 +376,18 @@ bool Dfsi::createPeerNetwork() return true; } +/// +/// Initializes serial V24 network. +/// +/// +/// +/// bool Dfsi::createSerialNetwork(uint32_t p25BufferSize, uint16_t callTimeout) { // Read serial config yaml::Node dfsi_conf = m_conf["dfsi"]; yaml::Node serial_conf = dfsi_conf["serial"]; + std::string portType = serial_conf["portType"].as("null"); std::string port = serial_conf["port"].as(); uint32_t baudrate = serial_conf["baudrate"].as(); bool rtrt = serial_conf["rtrt"].as(); @@ -428,6 +397,7 @@ bool Dfsi::createSerialNetwork(uint32_t p25BufferSize, uint16_t callTimeout) bool serial_trace = serial_conf["trace"].as(); LogInfo("Serial Parameters"); + LogInfo(" Port Type: %s", portType.c_str()); LogInfo(" Port: %s", port.c_str()); LogInfo(" Baudrate: %u", baudrate); LogInfo(" RT/RT: %s", rtrt ? "Enabled" : "Disabled"); @@ -437,7 +407,7 @@ bool Dfsi::createSerialNetwork(uint32_t p25BufferSize, uint16_t callTimeout) LogInfo(" Trace: %s", serial_trace ? "Enabled" : "Disabled"); // Create serial service - m_serial = new SerialService(port, baudrate, rtrt, diu, jitter, m_network, p25BufferSize, p25BufferSize, callTimeout, serial_debug, serial_trace); + m_serial = new SerialService(portType, port, baudrate, rtrt, diu, jitter, m_network, p25BufferSize, p25BufferSize, callTimeout, serial_debug, serial_trace); // Open serial bool ret = m_serial->open(); diff --git a/src/dfsi/DfsiMain.cpp b/src/dfsi/DfsiMain.cpp index 4a963d75..3fdcc15e 100644 --- a/src/dfsi/DfsiMain.cpp +++ b/src/dfsi/DfsiMain.cpp @@ -152,9 +152,6 @@ int checkArgs(int argc, char* argv[]) else if (IS("--syslog")) { g_useSyslog = true; } - else if (IS("-s")) { - g_hideMessages = true; - } else if (IS("-c")) { if (argc-- <= 0) usage("error: %s", "must specify the configuration file to use"); diff --git a/src/dfsi/DfsiMain.h b/src/dfsi/DfsiMain.h index 60e2a8b1..83ad38bd 100644 --- a/src/dfsi/DfsiMain.h +++ b/src/dfsi/DfsiMain.h @@ -29,7 +29,6 @@ extern std::string g_lockFile; extern bool g_foreground; extern bool g_killed; -extern bool g_hideMessages; extern std::string g_masterAddress; extern uint16_t g_masterPort; diff --git a/src/dfsi/frames/BlockHeader.cpp b/src/dfsi/frames/BlockHeader.cpp new file mode 100644 index 00000000..47a557b8 --- /dev/null +++ b/src/dfsi/frames/BlockHeader.cpp @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0-only +/** +* Digital Voice Modem - DFSI Peer Application +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / DFSI Peer Application +* @derivedfrom MMDVMHost (https://github.com/g4klx/MMDVMHost) +* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) +* +* Copyright (C) 2024 Bryan Biedenkapp, N2PLL +* +*/ + +#include "frames/BlockHeader.h" +#include "common/p25/dfsi/DFSIDefines.h" +#include "common/Utils.h" +#include "common/Log.h" + +#include +#include + +using namespace p25; +using namespace dfsi; + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a instance of the BlockHeader class. +/// +BlockHeader::BlockHeader() : + m_payloadType(false), + m_blockLength(UNDEFINED) +{ + /* stub */ +} + +/// +/// Initializes a instance of the BlockHeader class. +/// +/// +/// +BlockHeader::BlockHeader(uint8_t* data, bool verbose) : + m_payloadType(false), + m_blockLength(UNDEFINED) +{ + decode(data, verbose); +} + +/// +/// Decode a block header frame. +/// +/// +/// +/// +bool BlockHeader::decode(const uint8_t* data, bool verbose) +{ + assert(data != nullptr); + + uint64_t value = 0U; + + // combine bytes into ulong (8 byte) value + value = data[0U]; + value = (value << 8) + data[1U]; + value = (value << 8) + data[2U]; + value = (value << 8) + data[3U]; + + m_payloadType = (data[0U] & 0x80U) == 0x80U; // Payload Type + m_blockType = (BlockType)(data[0U] & 0x7FU); // Block Type + + if (verbose) { + m_timestampOffset = (uint32_t)((value >> 10) & 0x3FFU); // Timestamp Offset + m_blockLength = (uint32_t)(value & 0x3FFU); // Block Length + } + + return true; +} + +/// +/// Encode a block header frame. +/// +/// +/// +void BlockHeader::encode(uint8_t* data, bool verbose) +{ + assert(data != nullptr); + + if (!verbose) { + data[0U] = (uint8_t)((m_payloadType ? 0x80U : 0x00U) + // Payload Type + ((uint8_t)m_blockType & 0x7FU)); // Block Type + } + else { + uint64_t value = 0; + + value = (uint8_t)((m_payloadType ? 0x80U : 0x00U) + // Payload Type + ((uint8_t)m_blockType & 0x7FU)); // Block Type + value = (value << 24) + (m_timestampOffset & 0x3FFU); // Timestamp Offset + value = (value << 10) + (m_blockLength & 0x3FFU); // Block Length + + // split ulong (8 byte) value into bytes + data[0U] = (uint8_t)((value >> 24) & 0xFFU); + data[1U] = (uint8_t)((value >> 16) & 0xFFU); + data[2U] = (uint8_t)((value >> 8) & 0xFFU); + data[3U] = (uint8_t)((value >> 0) & 0xFFU); + } +} diff --git a/src/dfsi/frames/BlockHeader.h b/src/dfsi/frames/BlockHeader.h new file mode 100644 index 00000000..cdab1824 --- /dev/null +++ b/src/dfsi/frames/BlockHeader.h @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0-only +/** +* Digital Voice Modem - DFSI Peer Application +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / DFSI Peer Application +* @derivedfrom MMDVMHost (https://github.com/g4klx/MMDVMHost) +* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) +* +* Copyright (C) 2024 Bryan Biedenkapp, N2PLL +* +*/ +#if !defined(__BLOCK_HEADER_H__) +#define __BLOCK_HEADER_H__ + +#include "Defines.h" +#include "common/Defines.h" +#include "common/Log.h" +#include "common/Utils.h" +#include "frames/FrameDefines.h" + +namespace p25 +{ + namespace dfsi + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements a DFSI block header packet. + // + // Compact Form + // Byte 0 + // Bit 0 1 2 3 4 5 6 7 + // +-+-+-+-+-+-+-+-+ + // |E| BT | + // +-+-+-+-+-+-+-+-+ + // + // Verbose Form + // Byte 0 1 2 3 + // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // |E| BT | TSO | BL | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // --------------------------------------------------------------------------- + + class HOST_SW_API BlockHeader { + public: + static const uint8_t LENGTH = 1; + static const uint8_t VERBOSE_LENGTH = 4; + + /// Initializes a copy instance of the BlockHeader class. + BlockHeader(); + /// Initializes a copy instance of the BlockHeader class. + BlockHeader(uint8_t* data, bool verbose = false); + + /// Decode a block header frame. + bool decode(const uint8_t* data, bool verbose = false); + /// Encode a block header frame. + void encode(uint8_t *data, bool verbose = false); + + public: + /// Payload type. + /// This simple boolean marks this header as either IANA standard, or profile specific. + __PROPERTY(bool, payloadType, PayloadType); + /// Block type. + __PROPERTY(BlockType, blockType, BlockType); + /// Timestamp Offset. + __PROPERTY(uint16_t, timestampOffset, TimestampOffset); + /// Block length. + __PROPERTY(uint16_t, blockLength, BlockLength); + }; + } // namespace dfsi +} // namespace p25 + +#endif // __BLOCK_HEADER_H__ \ No newline at end of file diff --git a/src/dfsi/frames/ControlOctet.cpp b/src/dfsi/frames/ControlOctet.cpp new file mode 100644 index 00000000..b93fcc78 --- /dev/null +++ b/src/dfsi/frames/ControlOctet.cpp @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0-only +/** +* Digital Voice Modem - DFSI Peer Application +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / DFSI Peer Application +* @derivedfrom MMDVMHost (https://github.com/g4klx/MMDVMHost) +* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) +* +* Copyright (C) 2024 Bryan Biedenkapp, N2PLL +* +*/ + +#include "frames/ControlOctet.h" +#include "common/p25/dfsi/DFSIDefines.h" +#include "common/Utils.h" +#include "common/Log.h" + +#include +#include + +using namespace p25; +using namespace dfsi; + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a instance of the ControlOctet class. +/// +ControlOctet::ControlOctet() : + m_signal(false), + m_compact(true), + m_blockHeaderCnt(0U) +{ + /* stub */ +} + +/// +/// Initializes a instance of the ControlOctet class. +/// +/// +ControlOctet::ControlOctet(uint8_t* data) : + m_signal(false), + m_compact(true), + m_blockHeaderCnt(0U) +{ + decode(data); +} + +/// +/// Decode a control octet frame. +/// +/// +/// +bool ControlOctet::decode(const uint8_t* data) +{ + assert(data != nullptr); + + m_signal = (data[0U] & 0x07U) == 0x07U; // Signal Flag + m_compact = (data[0U] & 0x06U) == 0x06U; // Compact Flag + m_blockHeaderCnt = (uint8_t)(data[0U] & 0x3FU); // Block Header Count + + return true; +} + +/// +/// Encode a control octet frame. +/// +/// +void ControlOctet::encode(uint8_t* data) +{ + assert(data != nullptr); + + data[0U] = (uint8_t)((m_signal ? 0x07U : 0x00U) + // Signal Flag + (m_compact ? 0x06U : 0x00U) + // Control Flag + (m_blockHeaderCnt & 0x3F)); +} diff --git a/src/dfsi/frames/ControlOctet.h b/src/dfsi/frames/ControlOctet.h new file mode 100644 index 00000000..524a9623 --- /dev/null +++ b/src/dfsi/frames/ControlOctet.h @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0-only +/** +* Digital Voice Modem - DFSI Peer Application +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / DFSI Peer Application +* @derivedfrom MMDVMHost (https://github.com/g4klx/MMDVMHost) +* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) +* +* Copyright (C) 2024 Bryan Biedenkapp, N2PLL +* +*/ +#if !defined(__CONTROL_OCTET_H__) +#define __CONTROL_OCTET_H__ + +#include "Defines.h" +#include "common/Defines.h" +#include "common/Log.h" +#include "common/Utils.h" +#include "frames/FrameDefines.h" + +namespace p25 +{ + namespace dfsi + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements a DFSI control octet packet. + // + // Byte 0 + // Bit 0 1 2 3 4 5 6 7 + // +-+-+-+-+-+-+-+-+ + // |S|C| BHC | + // +-+-+-+-+-+-+-+-+ + // --------------------------------------------------------------------------- + + class HOST_SW_API ControlOctet { + public: + static const uint8_t LENGTH = 1; + + /// Initializes a copy instance of the ControlOctet class. + ControlOctet(); + /// Initializes a copy instance of the ControlOctet class. + ControlOctet(uint8_t* data); + + /// Decode a control octet frame. + bool decode(const uint8_t* data); + /// Encode a control octet frame. + void encode(uint8_t* data); + + public: + /// + __PROPERTY(bool, signal, Signal); + /// Indicates a compact (1) or verbose (0) block header. + __PROPERTY(bool, compact, Compact); + /// Number of block headers following this control octet. + __PROPERTY(uint8_t, blockHeaderCnt, BlockHeaderCnt); + }; + } // namespace dfsi +} // namespace p25 + +#endif // __CONTROL_OCTET_H__ \ No newline at end of file diff --git a/src/dfsi/frames/FrameDefines.h b/src/dfsi/frames/FrameDefines.h index be9d94f9..f9e56a40 100644 --- a/src/dfsi/frames/FrameDefines.h +++ b/src/dfsi/frames/FrameDefines.h @@ -25,6 +25,21 @@ namespace p25 // Constants // --------------------------------------------------------------------------- + /// + /// DFSI Block Types + /// + enum BlockType { + FULL_RATE_VOICE = 0, + + VOICE_HEADER_P1 = 6, + VOICE_HEADER_P2 = 7, + + START_OF_STREAM = 9, + END_OF_STREAM = 10, + + UNDEFINED = 127 + }; + /// /// /// diff --git a/src/dfsi/frames/Frames.h b/src/dfsi/frames/Frames.h index bfca6372..33a98d1a 100644 --- a/src/dfsi/frames/Frames.h +++ b/src/dfsi/frames/Frames.h @@ -17,8 +17,13 @@ #include "Defines.h" +// TIA #include "frames/StartOfStream.h" +#include "frames/ControlOctet.h" +#include "frames/BlockHeader.h" +#include "frames/FullRateVoice.h" +// "The" Manufacturer #include "frames/MotFullRateVoice.h" #include "frames/MotStartOfStream.h" #include "frames/MotStartVoiceFrame.h" diff --git a/src/dfsi/frames/FullRateVoice.cpp b/src/dfsi/frames/FullRateVoice.cpp new file mode 100644 index 00000000..ef3d53c0 --- /dev/null +++ b/src/dfsi/frames/FullRateVoice.cpp @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: GPL-2.0-only +/** +* Digital Voice Modem - DFSI Peer Application +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / DFSI Peer Application +* @derivedfrom MMDVMHost (https://github.com/g4klx/MMDVMHost) +* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) +* +* Copyright (C) 2024 Bryan Biedenkapp, N2PLL +* +*/ + +#include "frames/FullRateVoice.h" +#include "common/p25/dfsi/DFSIDefines.h" +#include "common/Utils.h" +#include "common/Log.h" + +#include +#include + +using namespace p25; +using namespace dfsi; + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a instance of the FullRateVoice class. +/// +FullRateVoice::FullRateVoice() : + imbeData(nullptr), + additionalData(nullptr), + m_frameType(P25_DFSI_LDU1_VOICE1), + m_totalErrors(0U), + m_muteFrame(false), + m_lostFrame(false), + m_superframeCnt(0U), + m_busy(0U) +{ + imbeData = new uint8_t[IMBE_BUF_LEN]; + ::memset(imbeData, 0x00U, IMBE_BUF_LEN); +} + +/// +/// Initializes a instance of the FullRateVoice class. +/// +/// +FullRateVoice::FullRateVoice(uint8_t* data) : + imbeData(nullptr), + additionalData(nullptr), + m_frameType(P25_DFSI_LDU1_VOICE1), + m_totalErrors(0U), + m_muteFrame(false), + m_lostFrame(false), + m_superframeCnt(0U), + m_busy(0U) +{ + decode(data); +} + +/// +/// Finalizes a instance of the FullRateVoice class. +/// +FullRateVoice::~FullRateVoice() +{ + if (imbeData != nullptr) + delete[] imbeData; + if (additionalData != nullptr) + delete[] additionalData; +} + +/// +/// Decode a full rate voice frame. +/// +/// +/// +bool FullRateVoice::decode(const uint8_t* data) +{ + assert(data != nullptr); + + if (imbeData != nullptr) + delete imbeData; + imbeData = new uint8_t[IMBE_BUF_LEN]; + ::memset(imbeData, 0x00U, IMBE_BUF_LEN); + + m_frameType = data[0U]; // Frame Type + ::memcpy(imbeData, data + 1U, IMBE_BUF_LEN); // IMBE + + m_totalErrors = (uint8_t)((data[12U] >> 5) & 0x07U); // Total Errors + m_muteFrame = (data[12U] & 0x02U) == 0x02U; // Mute Frame Flag + m_lostFrame = (data[12U] & 0x01U) == 0x01U; // Lost Frame Flag + m_superframeCnt = (uint8_t)((data[13U] >> 2) & 0x03U); // Superframe Counter + m_busy = (uint8_t)(data[13U] & 0x03U); + + if (isVoice3thru8() || isVoice12thru17() || isVoice9or10()) { + if (additionalData != nullptr) + delete additionalData; + additionalData = new uint8_t[ADDITIONAL_LENGTH]; + ::memset(additionalData, 0x00U, ADDITIONAL_LENGTH); + + if (isVoice9or10()) { + // CAI 9 and 10 are 3 bytes of additional data not 4 + ::memcpy(additionalData, data + 14U, ADDITIONAL_LENGTH - 1U); + } else { + ::memcpy(additionalData, data + 14U, ADDITIONAL_LENGTH); + } + } else { + if (additionalData != nullptr) + delete additionalData; + additionalData = nullptr; + } + + return true; +} + +/// +/// Encode a full rate voice frame. +/// +/// +void FullRateVoice::encode(uint8_t* data) +{ + assert(data != nullptr); + assert(imbeData != nullptr); + + data[0U] = m_frameType; // Frame Type + ::memcpy(data + 1U, imbeData, IMBE_BUF_LEN); // IMBE + + data[12U] = (uint8_t)(((m_totalErrors & 0x07U) << 5) + // Total Errors + (m_muteFrame ? 0x02U : 0x00U) + // Mute Frame Flag + (m_lostFrame ? 0x01U : 0x00U)); // Lost Frame Flag + data[13U] = (uint8_t)(((m_superframeCnt & 0x03U) << 2) + // Superframe Count + (m_busy & 0x03U)); // Busy Status + + if ((isVoice3thru8() || isVoice12thru17() || isVoice9or10()) && + additionalData != nullptr) { + if (isVoice9or10()) { + // CAI 9 and 10 are 3 bytes of additional data not 4 + ::memcpy(data + 14U, additionalData, ADDITIONAL_LENGTH - 1U); + } else { + ::memcpy(data + 14U, additionalData, ADDITIONAL_LENGTH); + } + } +} + +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- + +/// +/// +/// +/// +bool FullRateVoice::isVoice3thru8() +{ + if ( (m_frameType == P25_DFSI_LDU1_VOICE3) || (m_frameType == P25_DFSI_LDU1_VOICE4) || (m_frameType == P25_DFSI_LDU1_VOICE5) || + (m_frameType == P25_DFSI_LDU1_VOICE6) || (m_frameType == P25_DFSI_LDU1_VOICE7) || (m_frameType == P25_DFSI_LDU1_VOICE8) ) { + return true; + } else { + return false; + } +} + +/// +/// +/// +/// +bool FullRateVoice::isVoice12thru17() +{ + if ( (m_frameType == P25_DFSI_LDU2_VOICE12) || (m_frameType == P25_DFSI_LDU2_VOICE13) || (m_frameType == P25_DFSI_LDU2_VOICE14) || + (m_frameType == P25_DFSI_LDU2_VOICE15) || (m_frameType == P25_DFSI_LDU2_VOICE16) || (m_frameType == P25_DFSI_LDU2_VOICE17) ) { + return true; + } else { + return false; + } +} + +/// +/// +/// +/// +bool FullRateVoice::isVoice9or10() +{ + if ( (m_frameType == P25_DFSI_LDU1_VOICE9) || (m_frameType == P25_DFSI_LDU2_VOICE10) ) { + return true; + } else { + return false; + } +} diff --git a/src/dfsi/frames/FullRateVoice.h b/src/dfsi/frames/FullRateVoice.h new file mode 100644 index 00000000..e662851d --- /dev/null +++ b/src/dfsi/frames/FullRateVoice.h @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: GPL-2.0-only +/** +* Digital Voice Modem - DFSI Peer Application +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / DFSI Peer Application +* @derivedfrom MMDVMHost (https://github.com/g4klx/MMDVMHost) +* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) +* +* Copyright (C) 2024 Bryan Biedenkapp, N2PLL +* +*/ +#if !defined(__FULL_RATE_VOICE_H__) +#define __FULL_RATE_VOICE_H__ + +#include "Defines.h" +#include "common/Defines.h" +#include "common/Log.h" +#include "common/Utils.h" +#include "frames/FrameDefines.h" + +namespace p25 +{ + namespace dfsi + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements a P25 full rate voice packet. + // + // CAI Frames 1, 2, 10 and 11. + // + // Byte 0 1 2 3 + // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | FT | U0(b11-0) | U1(b11-0) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | U2(b10-0) | U3(b11-0) | U4(b10-3) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | U4 | U5(b10-0) | U6(b10-0) | U7(b6-0) | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // | Et | Er |M|L|E| E1 |SF | B | + // | | | | |4| | | | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // + // CAI Frames 3 - 8. + // + // Byte 0 1 2 3 + // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | FT | U0(b11-0) | U1(b11-0) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | U2(b10-0) | U3(b11-0) | U4(b10-3) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | U4 | U5(b10-0) | U6(b10-0) | U7(b6-0) | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // | Et | Er |M|L|E| E1 |SF | B | LC0,4,8 | LC1,5,9 | LC2, | + // | | | | |4| | | | | | 6,10 | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // | | LC3,7,11 |R| Status | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // + // CAI Frames 12 - 17. + // + // Byte 0 1 2 3 + // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | FT | U0(b11-0) | U1(b11-0) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | U2(b10-0) | U3(b11-0) | U4(b10-3) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | U4 | U5(b10-0) | U6(b10-0) | U7(b6-0) | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // | Et | Er |M|L|E| E1 |SF | B | ES0,4,8 | ES1,5,9 | ES2, | + // | | | | |4| | | | | | 6,10 | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // | | ES3,7,11 |R| Status | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // + // CAI Frames 9 and 10. + // + // Byte 0 1 2 3 + // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | FT | U0(b11-0) | U1(b11-0) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | U2(b10-0) | U3(b11-0) | U4(b10-3) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | U4 | U5(b10-0) | U6(b10-0) | U7(b6-0) | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // | Et | Er |M|L|E| E1 |SF | B | LSD0,2 | LSD1,3 | + // | | | | |4| | | | | | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // | Rsvd |Si |Sj | + // +=+=+=+=+=+=+=+=+ + // + // Because the TIA.102-BAHA spec represents the "message vectors" as + // 16-bit units (U0 - U7) this makes understanding the layout of the + // buffer ... difficult for the 8-bit aligned minded. The following is + // the layout with 8-bit aligned IMBE blocks instead of message vectors: + // + // CAI Frames 1, 2, 10 and 11. + // + // Byte 0 1 2 3 + // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | FT | IMBE 1 | IMBE 2 | IMBE 3 | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | IMBE 4 | IMBE 5 | IMBE 6 | IMBE 7 | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | IMBE 8 | IMBE 9 | IMBE 10 | IMBE 11 | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // | Et | Er |M|L|E| E1 |SF | B | + // | | | | |4| | | | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // + // CAI Frames 3 - 8. + // + // Byte 0 1 2 3 + // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | FT | IMBE 1 | IMBE 2 | IMBE 3 | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | IMBE 4 | IMBE 5 | IMBE 6 | IMBE 7 | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | IMBE 8 | IMBE 9 | IMBE 10 | IMBE 11 | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // | Et | Er |M|L|E| E1 |SF | B | Link Ctrl | Link Ctrl | + // | | | | |4| | | | | | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // | Link Ctrl |R| Status | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // + // CAI Frames 12 - 17. + // + // Byte 0 1 2 3 + // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | FT | IMBE 1 | IMBE 2 | IMBE 3 | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | IMBE 4 | IMBE 5 | IMBE 6 | IMBE 7 | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | IMBE 8 | IMBE 9 | IMBE 10 | IMBE 11 | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // | Et | Er |M|L|E| E1 |SF | B | Enc Sync | Enc Sync | + // | | | | |4| | | | | | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // | Enc Sync |R| Status | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // + // CAI Frames 9 and 10. + // + // Byte 0 1 2 3 + // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | FT | IMBE 1 | IMBE 2 | IMBE 3 | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | IMBE 4 | IMBE 5 | IMBE 6 | IMBE 7 | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | IMBE 8 | IMBE 9 | IMBE 10 | IMBE 11 | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // | Et | Er |M|L|E| E1 |SF | B | LSD0,2 | LSD1,3 | + // | | | | |4| | | | | | + // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + // | Rsvd |Si |Sj | + // +=+=+=+=+=+=+=+=+ + // --------------------------------------------------------------------------- + + class HOST_SW_API FullRateVoice { + public: + static const uint8_t LENGTH = 18; + static const uint8_t ADDITIONAL_LENGTH = 4; + static const uint8_t IMBE_BUF_LEN = 11; + + /// Initializes a copy instance of the FullRateVoice class. + FullRateVoice(); + /// Initializes a copy instance of the FullRateVoice class. + FullRateVoice(uint8_t* data); + /// Finalizes a instance of the FullRateVoice class. + ~FullRateVoice(); + + /// Decode a full rate voice frame. + bool decode(const uint8_t* data); + /// Encode a full rate voice frame. + void encode(uint8_t* data); + + public: + uint8_t* imbeData; // ?? - this should probably be private with getters/setters + uint8_t* additionalData; // ?? - this should probably be private with getters/setters + + /// Frame Type. + __PROPERTY(uint8_t, frameType, FrameType); + /// Total errors detected in the frame. + __PROPERTY(uint8_t, totalErrors, TotalErrors); + /// Flag indicating the frame should be muted. + __PROPERTY(bool, muteFrame, MuteFrame); + /// Flag indicating the frame was lost. + __PROPERTY(bool, lostFrame, LostFrame); + /// Superframe Counter. + __PROPERTY(uint8_t, superframeCnt, SuperframeCnt); + /// Busy Status. + __PROPERTY(uint8_t, busy, Busy); + + private: + /// + bool isVoice3thru8(); + /// + bool isVoice12thru17(); + /// + bool isVoice9or10(); + }; + } // namespace dfsi +} // namespace p25 + +#endif // __FULL_RATE_VOICE_H__ \ No newline at end of file diff --git a/src/dfsi/frames/MotFullRateVoice.cpp b/src/dfsi/frames/MotFullRateVoice.cpp index a1e14da6..4671c546 100644 --- a/src/dfsi/frames/MotFullRateVoice.cpp +++ b/src/dfsi/frames/MotFullRateVoice.cpp @@ -179,7 +179,7 @@ void MotFullRateVoice::encode(uint8_t* data, bool shortened) } // --------------------------------------------------------------------------- -// Protected Class Members +// Private Class Members // --------------------------------------------------------------------------- /// diff --git a/src/dfsi/frames/MotFullRateVoice.h b/src/dfsi/frames/MotFullRateVoice.h index 2d7bc928..68b9dbd3 100644 --- a/src/dfsi/frames/MotFullRateVoice.h +++ b/src/dfsi/frames/MotFullRateVoice.h @@ -46,7 +46,6 @@ namespace p25 class HOST_SW_API MotFullRateVoice { public: - // Frame information static const uint8_t LENGTH = 17; static const uint8_t SHORTENED_LENGTH = 13; static const uint8_t ADDITIONAL_LENGTH = 4; @@ -70,7 +69,7 @@ namespace p25 uint8_t* imbeData; // ?? - this should probably be private with getters/setters uint8_t* additionalData; // ?? - this should probably be private with getters/setters - /// + /// Frame Type. __PROPERTY(uint8_t, frameType, FrameType); /// __PROPERTY(uint8_t, source, Source); diff --git a/src/dfsi/frames/MotStartOfStream.cpp b/src/dfsi/frames/MotStartOfStream.cpp index aa992d74..8971f076 100644 --- a/src/dfsi/frames/MotStartOfStream.cpp +++ b/src/dfsi/frames/MotStartOfStream.cpp @@ -44,7 +44,11 @@ MotStartOfStream::MotStartOfStream() : /// Initializes a instance of the MotStartOfStream class. /// /// -MotStartOfStream::MotStartOfStream(uint8_t* data) +MotStartOfStream::MotStartOfStream(uint8_t* data) : + m_marker(FIXED_MARKER), + m_rt(DISABLED), + m_startStop(START), + m_streamType(VOICE) { decode(data); } diff --git a/src/dfsi/frames/MotStartVoiceFrame.cpp b/src/dfsi/frames/MotStartVoiceFrame.cpp index 66482883..7f641687 100644 --- a/src/dfsi/frames/MotStartVoiceFrame.cpp +++ b/src/dfsi/frames/MotStartVoiceFrame.cpp @@ -48,12 +48,15 @@ MotStartVoiceFrame::MotStartVoiceFrame() : /// Initializes a instance of the MotStartVoiceFrame class. /// /// -MotStartVoiceFrame::MotStartVoiceFrame(uint8_t* data) +MotStartVoiceFrame::MotStartVoiceFrame(uint8_t* data) : + startOfStream(nullptr), + fullRateVoice(nullptr), + m_icw(ICW_DIU), + m_rssi(0U), + m_rssiValidity(INVALID), + m_nRssi(0U), + m_adjMM(0U) { - // set our pointers to null since we don't initialize them anywhere else - startOfStream = nullptr; - fullRateVoice = nullptr; - // decode decode(data); } diff --git a/src/dfsi/frames/MotVoiceHeader1.cpp b/src/dfsi/frames/MotVoiceHeader1.cpp index e8315b6b..261011d3 100644 --- a/src/dfsi/frames/MotVoiceHeader1.cpp +++ b/src/dfsi/frames/MotVoiceHeader1.cpp @@ -49,12 +49,14 @@ MotVoiceHeader1::MotVoiceHeader1() : /// Initializes a instance of the MotVoiceHeader1 class. /// /// -MotVoiceHeader1::MotVoiceHeader1(uint8_t* data) +MotVoiceHeader1::MotVoiceHeader1(uint8_t* data) : + header(nullptr), + startOfStream(nullptr), + m_icw(ICW_DIU), + m_rssi(0U), + m_rssiValidity(INVALID), + m_nRssi(0U) { - // set our pointers to null since we haven't initialized them yet - startOfStream = nullptr; - header = nullptr; - // decode decode(data); } diff --git a/src/dfsi/frames/MotVoiceHeader2.cpp b/src/dfsi/frames/MotVoiceHeader2.cpp index fed1e1fc..5dafc009 100644 --- a/src/dfsi/frames/MotVoiceHeader2.cpp +++ b/src/dfsi/frames/MotVoiceHeader2.cpp @@ -43,11 +43,10 @@ MotVoiceHeader2::MotVoiceHeader2() : /// Initializes a instance of the MotVoiceHeader2 class. /// /// -MotVoiceHeader2::MotVoiceHeader2(uint8_t* data) +MotVoiceHeader2::MotVoiceHeader2(uint8_t* data) : + header(nullptr), + m_source(SOURCE_QUANTAR) { - // set pointer to null since it hasn't been initialized yet - header = nullptr; - // decode decode(data); } diff --git a/src/dfsi/frames/StartOfStream.cpp b/src/dfsi/frames/StartOfStream.cpp index b339f5cb..14bc98fd 100644 --- a/src/dfsi/frames/StartOfStream.cpp +++ b/src/dfsi/frames/StartOfStream.cpp @@ -57,8 +57,8 @@ bool StartOfStream::decode(const uint8_t* data) { assert(data != nullptr); - m_nid = __GET_UINT16(data, 0U); // Network Identifier - m_errorCount = (data[2U] & 0x0FU); // Error Count + m_nid = __GET_UINT16(data, 0U); // Network Identifier + m_errorCount = (data[2U] & 0x0FU); // Error Count return true; } @@ -71,6 +71,6 @@ void StartOfStream::encode(uint8_t* data) { assert(data != nullptr); - __SET_UINT16(m_nid, data, 0U); // Network Identifier - data[2U] = m_errorCount & 0x0FU; // Error Count + __SET_UINT16(m_nid, data, 0U); // Network Identifier + data[2U] = m_errorCount & 0x0FU; // Error Count } diff --git a/src/dfsi/frames/StartOfStream.h b/src/dfsi/frames/StartOfStream.h index 002af9c5..6a41bc63 100644 --- a/src/dfsi/frames/StartOfStream.h +++ b/src/dfsi/frames/StartOfStream.h @@ -27,7 +27,6 @@ namespace p25 // --------------------------------------------------------------------------- // Class Declaration // Implements a P25 DFSI start of stream packet. - // // // Byte 0 1 2 // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 @@ -51,9 +50,9 @@ namespace p25 void encode(uint8_t* data); public: - /// + /// Network Identifier. __PROPERTY(uint16_t, nid, NID); - /// + /// Error count. __PROPERTY(uint8_t, errorCount, ErrorCount); }; } // namespace dfsi diff --git a/src/dfsi/network/SerialService.cpp b/src/dfsi/network/SerialService.cpp index a41b711a..2f5fc9d0 100644 --- a/src/dfsi/network/SerialService.cpp +++ b/src/dfsi/network/SerialService.cpp @@ -23,7 +23,27 @@ using namespace modem; using namespace p25; using namespace dfsi; -SerialService::SerialService(const std::string& portName, uint32_t baudrate, bool rtrt, bool diu, uint16_t jitter, DfsiPeerNetwork* network, uint32_t p25TxQueueSize, uint32_t p25RxQueueSize, uint16_t callTimeout, bool debug, bool trace) : +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the SerialService class. +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +SerialService::SerialService(std::string& portType, const std::string& portName, uint32_t baudrate, bool rtrt, bool diu, uint16_t jitter, DfsiPeerNetwork* network, + uint32_t p25TxQueueSize, uint32_t p25RxQueueSize, uint16_t callTimeout, bool debug, bool trace) : m_portName(portName), m_baudrate(baudrate), m_rtrt(rtrt), @@ -62,7 +82,13 @@ SerialService::SerialService(const std::string& portName, uint32_t baudrate, boo // Setup serial port::SERIAL_SPEED serialSpeed = port::SERIAL_115200; - m_port = new port::UARTPort(portName, serialSpeed, false); + std::transform(portType.begin(), portType.end(), portType.begin(), ::tolower); + if (portType == NULL_PORT) { + m_port = new port::ModemNullPort(); + } + else { + m_port = new port::UARTPort(portName, serialSpeed, false); + } m_lastIMBE = new uint8_t[11U]; ::memcpy(m_lastIMBE, P25_NULL_IMBE, 11U); @@ -70,6 +96,9 @@ SerialService::SerialService(const std::string& portName, uint32_t baudrate, boo m_msgBuffer = new uint8_t[BUFFER_LENGTH]; } +/// +/// Finalizes a instance of the SerialService class. +/// SerialService::~SerialService() { if (m_port != nullptr) { @@ -86,6 +115,10 @@ SerialService::~SerialService() delete m_rxVoiceCallData; } +/// +/// Updates the timer by the passed number of milliseconds. +/// +/// void SerialService::clock(uint32_t ms) { // Get now @@ -193,6 +226,10 @@ void SerialService::clock(uint32_t ms) } } +/// +/// Opens connection to the serial interface. +/// +/// True, if connection is established, otherwise false. bool SerialService::open() { LogInfoEx(LOG_SERIAL, "Opening port %s at %u baud", m_portName.c_str(), m_baudrate); @@ -209,6 +246,9 @@ bool SerialService::open() return true; } +/// +/// Closes connection to the serial interface. +/// void SerialService::close() { LogInfoEx(LOG_SERIAL, "Closing port"); @@ -916,6 +956,10 @@ void SerialService::processP25ToNet() } } +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- + /// Read a data message from the serial port /// This is borrowed from the Modem::getResponse() function /// Response type diff --git a/src/dfsi/network/SerialService.h b/src/dfsi/network/SerialService.h index 1cb9e6df..86881fc5 100644 --- a/src/dfsi/network/SerialService.h +++ b/src/dfsi/network/SerialService.h @@ -33,6 +33,7 @@ #include "host/modem/Modem.h" #include "host/modem/port/IModemPort.h" #include "host/modem/port/UARTPort.h" +#include "host/modem/port/ModemNullPort.h" // System Includes #include @@ -48,7 +49,6 @@ using namespace dfsi; namespace network { - // DFSI serial tx flags used to determine proper jitter handling of data in ringbuffer enum SERIAL_TX_TYPE { NONIMBE, @@ -56,20 +56,24 @@ namespace network }; // --------------------------------------------------------------------------- - // Class Declaration + // Class Declaration // Serial V24 service // --------------------------------------------------------------------------- class HOST_SW_API SerialService { public: - SerialService(const std::string& portName, uint32_t baudrate, bool rtrt, bool diu, uint16_t jitter, DfsiPeerNetwork* network, uint32_t p25TxQueueSize, uint32_t p25RxQueueSize, uint16_t callTimeout, bool debug, bool trace); - + /// Initializes an instance of the SerialService class. + SerialService(std::string& portType, const std::string& portName, uint32_t baudrate, bool rtrt, bool diu, uint16_t jitter, DfsiPeerNetwork* network, uint32_t p25TxQueueSize, uint32_t p25RxQueueSize, uint16_t callTimeout, bool debug, bool trace); + /// Finalizes an instance of the SerialService class. ~SerialService(); + /// Updates the serial interface by the passed number of milliseconds. void clock(uint32_t ms); + /// Opens connection to the serial interface. bool open(); + /// Closes connection to the serial interface. void close(); // Handle P25 data from network to V24 @@ -156,10 +160,6 @@ namespace network void printDebug(const uint8_t* buffer, uint16_t length); }; - - // Defines for Mot DFSI - - } // namespace network #endif // __SERIAL_SERVICE_H__ \ No newline at end of file