diff --git a/Conf.cpp b/Conf.cpp index b6868b7..bdbb610 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -36,6 +36,7 @@ enum SECTION { SECTION_DMRID_LOOKUP, SECTION_NXDNID_LOOKUP, SECTION_MODEM, + SECTION_TRANSPARENT, SECTION_UMP, SECTION_DSTAR, SECTION_DMR, @@ -104,6 +105,10 @@ m_modemNXDNTXLevel(50.0F), m_modemRSSIMappingFile(), m_modemTrace(false), m_modemDebug(false), +m_transparentEnabled(false), +m_transparentRemoteAddress(), +m_transparentRemotePort(0U), +m_transparentLocalPort(0U), m_umpEnabled(false), m_umpPort(), m_dstarEnabled(false), @@ -253,6 +258,8 @@ bool CConf::read() section = SECTION_NXDNID_LOOKUP; else if (::strncmp(buffer, "[Modem]", 7U) == 0) section = SECTION_MODEM; + else if (::strncmp(buffer, "[Transparent Data]", 18U) == 0) + section = SECTION_TRANSPARENT; else if (::strncmp(buffer, "[UMP]", 5U) == 0) section = SECTION_UMP; else if (::strncmp(buffer, "[D-Star]", 8U) == 0) @@ -423,6 +430,15 @@ bool CConf::read() m_modemTrace = ::atoi(value) == 1; else if (::strcmp(key, "Debug") == 0) m_modemDebug = ::atoi(value) == 1; + } else if (section == SECTION_TRANSPARENT) { + if (::strcmp(key, "Enable") == 0) + m_transparentEnabled = ::atoi(value) == 1; + else if (::strcmp(key, "RemoteAddress") == 0) + m_transparentRemoteAddress = value; + else if (::strcmp(key, "RemotePort") == 0) + m_transparentRemotePort = (unsigned int)::atoi(value); + else if (::strcmp(key, "LocalPort") == 0) + m_transparentLocalPort = (unsigned int)::atoi(value); } else if (section == SECTION_UMP) { if (::strcmp(key, "Enable") == 0) m_umpEnabled = ::atoi(value) == 1; @@ -956,6 +972,26 @@ bool CConf::getModemDebug() const return m_modemDebug; } +bool CConf::getTransparentEnabled() const +{ + return m_transparentEnabled; +} + +std::string CConf::getTransparentRemoteAddress() const +{ + return m_transparentRemoteAddress; +} + +unsigned int CConf::getTransparentRemotePort() const +{ + return m_transparentRemotePort; +} + +unsigned int CConf::getTransparentLocalPort() const +{ + return m_transparentLocalPort; +} + bool CConf::getUMPEnabled() const { return m_umpEnabled; diff --git a/Conf.h b/Conf.h index 016f77c..05cd530 100644 --- a/Conf.h +++ b/Conf.h @@ -91,6 +91,12 @@ public: bool getModemTrace() const; bool getModemDebug() const; + // The Transparent Data section + bool getTransparentEnabled() const; + std::string getTransparentRemoteAddress() const; + unsigned int getTransparentRemotePort() const; + unsigned int getTransparentLocalPort() const; + // The UMP section bool getUMPEnabled() const; std::string getUMPPort() const; @@ -292,6 +298,11 @@ private: bool m_modemTrace; bool m_modemDebug; + bool m_transparentEnabled; + std::string m_transparentRemoteAddress; + unsigned int m_transparentRemotePort; + unsigned int m_transparentLocalPort; + bool m_umpEnabled; std::string m_umpPort; diff --git a/MMDVM.ini b/MMDVM.ini index 49f6599..d43e1d9 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -66,6 +66,12 @@ RSSIMappingFile=RSSI.dat Trace=0 Debug=0 +[Transparent Data] +Enable=0 +RemoteAddress=127.0.0.1 +RemotePort=40094 +LocalPort=40095 + [UMP] Enable=0 # Port=\\.\COM4 diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index d9a7b03..668ed3c 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -308,6 +308,32 @@ int CMMDVMHost::run() return 1; } + in_addr transparentAddress; + unsigned int transparentPort = 0U; + CUDPSocket* transparentSocket = NULL; + + if (m_conf.getTransparentEnabled()) { + std::string remoteAddress = m_conf.getTransparentRemoteAddress(); + unsigned int remotePort = m_conf.getTransparentRemotePort(); + unsigned int localPort = m_conf.getTransparentLocalPort(); + + LogInfo("Transparent Data"); + LogInfo(" Remote Address: %s", remoteAddress.c_str()); + LogInfo(" Remote Port: %u", remotePort); + LogInfo(" Local Port: %u", localPort); + + transparentAddress = CUDPSocket::lookup(remoteAddress); + transparentPort = remotePort; + + transparentSocket = new CUDPSocket(localPort); + ret = transparentSocket->open(); + if (!ret) { + LogWarning("Could not open the Transparent data socket, disabling"); + delete transparentSocket; + transparentSocket = NULL; + } + } + if (m_conf.getCWIdEnabled()) { unsigned int time = m_conf.getCWIdTime(); m_cwCallsign = m_conf.getCWIdCallsign(); @@ -686,6 +712,10 @@ int CMMDVMHost::run() } } + len = m_modem->readTransparentData(data); + if (transparentSocket != NULL && len > 0U) + transparentSocket->write(data, len, transparentAddress, transparentPort); + if (m_modeTimer.isRunning() && m_modeTimer.hasExpired()) setMode(MODE_IDLE); @@ -811,6 +841,14 @@ int CMMDVMHost::run() } } + if (transparentSocket != NULL) { + in_addr address; + unsigned int port = 0U; + len = transparentSocket->read(data, 200U, address, port); + if (len > 0U) + m_modem->writeTransparentData(data, len); + } + unsigned int ms = stopWatch.elapsed(); stopWatch.start(); @@ -925,6 +963,11 @@ int CMMDVMHost::run() delete m_nxdnNetwork; } + if (transparentSocket != NULL) { + transparentSocket->close(); + delete transparentSocket; + } + delete dstar; delete dmr; delete ysf; diff --git a/Modem.cpp b/Modem.cpp index 8f6c56d..540241b 100644 --- a/Modem.cpp +++ b/Modem.cpp @@ -76,6 +76,8 @@ const unsigned char MMDVM_NAK = 0x7FU; const unsigned char MMDVM_SERIAL = 0x80U; +const unsigned char MMDVM_TRANSPARENT = 0x90U; + const unsigned char MMDVM_DEBUG1 = 0xF1U; const unsigned char MMDVM_DEBUG2 = 0xF2U; const unsigned char MMDVM_DEBUG3 = 0xF3U; @@ -131,6 +133,8 @@ m_rxP25Data(1000U, "Modem RX P25"), m_txP25Data(1000U, "Modem TX P25"), m_rxNXDNData(1000U, "Modem RX NXDN"), m_txNXDNData(1000U, "Modem TX NXDN"), +m_rxTransparentData(1000U, "Modem RX Transparent"), +m_txTransparentData(1000U, "Modem TX Transparent"), m_statusTimer(1000U, 0U, 250U), m_inactivityTimer(1000U, 2U), m_playoutTimer(1000U, 0U, 10U), @@ -504,6 +508,17 @@ void CModem::clock(unsigned int ms) } break; + case MMDVM_TRANSPARENT: { + if (m_trace) + CUtils::dump(1U, "RX Transparent Data", m_buffer, m_length); + + unsigned char data = m_length - 3U; + m_rxTransparentData.addData(&data, 1U); + + m_rxTransparentData.addData(m_buffer + 3U, m_length - 3U); + } + break; + // These should not be received, but don't complain if we do case MMDVM_GET_VERSION: case MMDVM_ACK: @@ -658,6 +673,19 @@ void CModem::clock(unsigned int ms) m_nxdnSpace--; } + + if (!m_txTransparentData.isEmpty()) { + unsigned char len = 0U; + m_txTransparentData.getData(&len, 1U); + m_txTransparentData.getData(m_buffer, len); + + if (m_trace) + CUtils::dump(1U, "TX Transparent Data", m_buffer, len); + + int ret = m_serial.write(m_buffer, len); + if (ret != int(len)) + LogWarning("Error when writing Transparent data to the MMDVM"); + } } void CModem::close() @@ -751,6 +779,20 @@ unsigned int CModem::readNXDNData(unsigned char* data) return len; } +unsigned int CModem::readTransparentData(unsigned char* data) +{ + assert(data != NULL); + + if (m_rxTransparentData.isEmpty()) + return 0U; + + unsigned char len = 0U; + m_rxTransparentData.getData(&len, 1U); + m_rxTransparentData.getData(data, len); + + return len; +} + // To be implemented later if needed unsigned int CModem::readSerial(unsigned char* data, unsigned int length) { @@ -951,6 +993,26 @@ bool CModem::writeNXDNData(const unsigned char* data, unsigned int length) return true; } +bool CModem::writeTransparentData(const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length > 0U); + + unsigned char buffer[250U]; + + buffer[0U] = MMDVM_FRAME_START; + buffer[1U] = length + 3U; + buffer[2U] = MMDVM_TRANSPARENT; + + ::memcpy(buffer + 3U, data, length); + + unsigned char len = length + 3U; + m_txTransparentData.addData(&len, 1U); + m_txTransparentData.addData(buffer, len); + + return true; +} + bool CModem::writeSerial(const unsigned char* data, unsigned int length) { assert(data != NULL); diff --git a/Modem.h b/Modem.h index e335fbb..b527373 100644 --- a/Modem.h +++ b/Modem.h @@ -51,6 +51,7 @@ public: unsigned int readYSFData(unsigned char* data); unsigned int readP25Data(unsigned char* data); unsigned int readNXDNData(unsigned char* data); + unsigned int readTransparentData(unsigned char* data); unsigned int readSerial(unsigned char* data, unsigned int length); @@ -73,6 +74,7 @@ public: bool writeYSFData(const unsigned char* data, unsigned int length); bool writeP25Data(const unsigned char* data, unsigned int length); bool writeNXDNData(const unsigned char* data, unsigned int length); + bool writeTransparentData(const unsigned char* data, unsigned int length); bool writeDMRStart(bool tx); bool writeDMRShortLC(const unsigned char* lc); @@ -135,6 +137,8 @@ private: CRingBuffer m_txP25Data; CRingBuffer m_rxNXDNData; CRingBuffer m_txNXDNData; + CRingBuffer m_rxTransparentData; + CRingBuffer m_txTransparentData; CTimer m_statusTimer; CTimer m_inactivityTimer; CTimer m_playoutTimer;