diff --git a/YSFGateway/Conf.cpp b/YSFGateway/Conf.cpp index 7cb71ca..fa4378e 100644 --- a/YSFGateway/Conf.cpp +++ b/YSFGateway/Conf.cpp @@ -48,6 +48,7 @@ m_rptPort(0U), m_myAddress(), m_myPort(0U), m_wiresXMakeUpper(true), +m_wiresXCommandPassthrough(false), m_daemon(false), m_rxFrequency(0U), m_txFrequency(0U), @@ -162,6 +163,8 @@ bool CConf::read() m_myPort = (unsigned int)::atoi(value); else if (::strcmp(key, "WiresXMakeUpper") == 0) m_wiresXMakeUpper = ::atoi(value) == 1; + else if (::strcmp(key, "WiresXCommandPassthrough") == 0) + m_wiresXCommandPassthrough = ::atoi(value) == 1; else if (::strcmp(key, "Daemon") == 0) m_daemon = ::atoi(value) == 1; } else if (section == SECTION_INFO) { @@ -299,6 +302,11 @@ bool CConf::getWiresXMakeUpper() const return m_wiresXMakeUpper; } +bool CConf::getWiresXCommandPassthrough() const +{ + return m_wiresXCommandPassthrough; +} + bool CConf::getDaemon() const { return m_daemon; diff --git a/YSFGateway/Conf.h b/YSFGateway/Conf.h index 7ab7ea6..3a588ab 100644 --- a/YSFGateway/Conf.h +++ b/YSFGateway/Conf.h @@ -38,6 +38,7 @@ public: std::string getMyAddress() const; unsigned int getMyPort() const; bool getWiresXMakeUpper() const; + bool getWiresXCommandPassthrough() const; bool getDaemon() const; // The Info section @@ -104,6 +105,7 @@ private: std::string m_myAddress; unsigned int m_myPort; bool m_wiresXMakeUpper; + bool m_wiresXCommandPassthrough; bool m_daemon; unsigned int m_rxFrequency; diff --git a/YSFGateway/WiresX.cpp b/YSFGateway/WiresX.cpp index f50226f..14e1c97 100644 --- a/YSFGateway/WiresX.cpp +++ b/YSFGateway/WiresX.cpp @@ -31,6 +31,7 @@ const unsigned char DX_REQ[] = {0x5DU, 0x71U, 0x5FU}; const unsigned char CONN_REQ[] = {0x5DU, 0x23U, 0x5FU}; const unsigned char DISC_REQ[] = {0x5DU, 0x2AU, 0x5FU}; +const unsigned char DISC_REQ2[] = {0x5DU, 0x63U, 0x5FU}; const unsigned char ALL_REQ[] = {0x5DU, 0x66U, 0x5FU}; const unsigned char CAT_REQ[] = {0x5DU, 0x67U, 0x5FU}; @@ -180,7 +181,7 @@ bool CWiresX::start() return true; } -WX_STATUS CWiresX::process(const unsigned char* data, const unsigned char* source, unsigned char fi, unsigned char dt, unsigned char fn, unsigned char ft) +WX_STATUS CWiresX::process(const unsigned char* data, const unsigned char* source, unsigned char fi, unsigned char dt, unsigned char fn, unsigned char ft, bool wiresXCommandPassthrough) { assert(data != NULL); assert(source != NULL); @@ -227,23 +228,50 @@ WX_STATUS CWiresX::process(const unsigned char* data, const unsigned char* sourc if (!valid) return WXS_NONE; - if (::memcmp(m_command + 1U, DX_REQ, 3U) == 0) { - processDX(source); - return WXS_NONE; - } else if (::memcmp(m_command + 1U, ALL_REQ, 3U) == 0) { - processAll(source, m_command + 5U); - return WXS_NONE; - } else if (::memcmp(m_command + 1U, CONN_REQ, 3U) == 0) { - return processConnect(source, m_command + 5U); - } else if (::memcmp(m_command + 1U, DISC_REQ, 3U) == 0) { - processDisconnect(source); - return WXS_DISCONNECT; - } else if (::memcmp(m_command + 1U, CAT_REQ, 3U) == 0) { - processCategory(source, m_command + 5U); - return WXS_NONE; - } else { - CUtils::dump("Unknown Wires-X command", m_command, cmd_len); - return WXS_NONE; + // If we are using WiresX Passthrough (we already know we are on a YSF2xxx room from YSFGateway + if (wiresXCommandPassthrough) { + if (::memcmp(m_command + 1U, DX_REQ, 3U) == 0) { + return WXS_NONE; + } else if (::memcmp(m_command + 1U, ALL_REQ, 3U) == 0) { + return WXS_NONE; + } else if (::memcmp(m_command + 1U, CONN_REQ, 3U) == 0) { + return WXS_NONE; + } else if (::memcmp(m_command + 1U, DISC_REQ, 3U) == 0) { + processDisconnect(source); + return WXS_DISCONNECT; + } else if (::memcmp(m_command + 1U, DISC_REQ2, 3U) == 0) { + processDisconnect(source); + return WXS_DISCONNECT; + } else if (::memcmp(m_command + 1U, CAT_REQ, 3U) == 0) { + return WXS_NONE; + } else { + CUtils::dump("Unknown Wires-X command", m_command, cmd_len); + return WXS_NONE; + } + } + // Origional Code Here + else { + if (::memcmp(m_command + 1U, DX_REQ, 3U) == 0) { + processDX(source); + return WXS_NONE; + } else if (::memcmp(m_command + 1U, ALL_REQ, 3U) == 0) { + processAll(source, m_command + 5U); + return WXS_NONE; + } else if (::memcmp(m_command + 1U, CONN_REQ, 3U) == 0) { + return processConnect(source, m_command + 5U); + } else if (::memcmp(m_command + 1U, DISC_REQ, 3U) == 0) { + processDisconnect(source); + return WXS_DISCONNECT; + } else if (::memcmp(m_command + 1U, DISC_REQ2, 3U) == 0) { + processDisconnect(source); + return WXS_DISCONNECT; + } else if (::memcmp(m_command + 1U, CAT_REQ, 3U) == 0) { + processCategory(source, m_command + 5U); + return WXS_NONE; + } else { + CUtils::dump("Unknown Wires-X command", m_command, cmd_len); + return WXS_NONE; + } } } @@ -408,11 +436,15 @@ void CWiresX::clock(unsigned int ms) } } -void CWiresX::createReply(const unsigned char* data, unsigned int length) +void CWiresX::createReply(const unsigned char* data, unsigned int length, CYSFNetwork* network) { assert(data != NULL); assert(length > 0U); + // If we don't explicitly pass a network, use the default one. + if (network == NULL) + network = m_network; + unsigned char bt = 0U; if (length > 260U) { @@ -454,7 +486,7 @@ void CWiresX::createReply(const unsigned char* data, unsigned int length) buffer[34U] = seqNo; seqNo += 2U; - m_network->write(buffer); + network->write(buffer); fich.setFI(YSF_FI_COMMUNICATIONS); @@ -501,7 +533,7 @@ void CWiresX::createReply(const unsigned char* data, unsigned int length) buffer[34U] = seqNo; seqNo += 2U; - m_network->write(buffer); + network->write(buffer); fn++; if (fn >= 8U) { @@ -521,7 +553,7 @@ void CWiresX::createReply(const unsigned char* data, unsigned int length) buffer[34U] = seqNo | 0x01U; - m_network->write(buffer); + network->write(buffer); } unsigned char CWiresX::calculateFT(unsigned int length, unsigned int offset) const @@ -616,6 +648,27 @@ void CWiresX::sendDXReply() m_seqNo++; } +void CWiresX::sendConnect(CYSFNetwork* network) +{ + unsigned char data[20U]; + ::memset(data, 0x00U, 20U); + ::memset(data, ' ', 16U); + + data[0U] = m_seqNo; + + for (unsigned int i = 0U; i < 3U; i++) + data[i + 1U] = DX_REQ[i]; + + data[15U] = 0x03U; // End of data marker + data[16U] = CCRC::addCRC(data, 16U); + + CUtils::dump(1U, "CONNECT", data, 20U); + + createReply(data, 20U, network); + + m_seqNo++; +} + void CWiresX::sendConnectReply() { assert(m_reflector != NULL); diff --git a/YSFGateway/WiresX.h b/YSFGateway/WiresX.h index 0116762..201b197 100644 --- a/YSFGateway/WiresX.h +++ b/YSFGateway/WiresX.h @@ -56,7 +56,7 @@ public: bool start(); - WX_STATUS process(const unsigned char* data, const unsigned char* source, unsigned char fi, unsigned char dt, unsigned char fn, unsigned char ft); + WX_STATUS process(const unsigned char* data, const unsigned char* source, unsigned char fi, unsigned char dt, unsigned char fn, unsigned char ft, bool wiresXCommandPassthrough); CYSFReflector* getReflector() const; void setReflector(CYSFReflector* reflector); @@ -64,6 +64,8 @@ public: void processConnect(CYSFReflector* reflector); void processDisconnect(const unsigned char* source = NULL); + void sendConnect(CYSFNetwork* network); + void clock(unsigned int ms); private: @@ -87,6 +89,7 @@ private: unsigned int m_start; std::string m_search; std::vector m_category; + bool m_wiresXCommandPassthrough; WX_STATUS processConnect(const unsigned char* source, const unsigned char* data); void processDX(const unsigned char* source); @@ -101,7 +104,7 @@ private: void sendSearchNotFoundReply(); void sendCategoryReply(); - void createReply(const unsigned char* data, unsigned int length); + void createReply(const unsigned char* data, unsigned int length, CYSFNetwork* network = NULL); unsigned char calculateFT(unsigned int length, unsigned int offset) const; }; diff --git a/YSFGateway/YSFGateway.cpp b/YSFGateway/YSFGateway.cpp index fe50af0..4cd6eee 100644 --- a/YSFGateway/YSFGateway.cpp +++ b/YSFGateway/YSFGateway.cpp @@ -244,6 +244,7 @@ int CYSFGateway::run() m_startup = m_conf.getNetworkStartup(); bool revert = m_conf.getNetworkRevert(); + bool wiresXCommandPassthrough = m_conf.getWiresXCommandPassthrough(); startupLinking(); @@ -266,12 +267,25 @@ int CYSFGateway::run() unsigned char fn = fich.getFN(); unsigned char ft = fich.getFT(); - // Don't send out control data - m_exclude = (dt == YSF_DT_DATA_FR_MODE); - - processWiresX(buffer, fi, dt, fn, ft); - - processDTMF(buffer, dt); + CYSFReflector* reflector = m_wiresX->getReflector(); + if (m_ysfNetwork != NULL && m_linkType == LINK_YSF && wiresXCommandPassthrough) { + if (reflector->m_wiresX) { + processDTMF(buffer, dt); + processWiresX(buffer, fi, dt, fn, ft, true, wiresXCommandPassthrough); + } else { + m_exclude = (dt == YSF_DT_DATA_FR_MODE); + processDTMF(buffer, dt); + processWiresX(buffer, fi, dt, fn, ft, false, wiresXCommandPassthrough); + } + } else if (wiresXCommandPassthrough) { + m_exclude = (dt == YSF_DT_DATA_FR_MODE); + processDTMF(buffer, dt); + processWiresX(buffer, fi, dt, fn, ft, false, wiresXCommandPassthrough); + } else { + m_exclude = (dt == YSF_DT_DATA_FR_MODE); + processDTMF(buffer, dt); + processWiresX(buffer, fi, dt, fn, ft, false, wiresXCommandPassthrough); + } if (m_gps != NULL) m_gps->data(buffer + 14U, buffer + 35U, fi, dt, fn, ft); @@ -507,11 +521,11 @@ void CYSFGateway::createWiresX(CYSFNetwork* rptNetwork) m_wiresX->start(); } -void CYSFGateway::processWiresX(const unsigned char* buffer, unsigned char fi, unsigned char dt, unsigned char fn, unsigned char ft) +void CYSFGateway::processWiresX(const unsigned char* buffer, unsigned char fi, unsigned char dt, unsigned char fn, unsigned char ft, bool dontProcessWiresXLocal, bool wiresXCommandPassthrough) { assert(buffer != NULL); - WX_STATUS status = m_wiresX->process(buffer + 35U, buffer + 14U, fi, dt, fn, ft); + WX_STATUS status = m_wiresX->process(buffer + 35U, buffer + 14U, fi, dt, fn, ft, dontProcessWiresXLocal); switch (status) { case WXS_CONNECT_YSF: { if (m_linkType == LINK_YSF) @@ -532,6 +546,12 @@ void CYSFGateway::processWiresX(const unsigned char* buffer, unsigned char fi, u m_inactivityTimer.start(); m_lostTimer.start(); m_linkType = LINK_YSF; + + // If we are linking to a YSF2xxx mode, send the YSF2xxx gateway the link command too + if (reflector->m_wiresX && wiresXCommandPassthrough) { + LogMessage("Forward WiresX Connect to \"%s\"", reflector->m_name.c_str()); + m_wiresX->sendConnect(m_ysfNetwork); + } } break; case WXS_CONNECT_FCS: { @@ -567,6 +587,10 @@ void CYSFGateway::processWiresX(const unsigned char* buffer, unsigned char fi, u case WXS_DISCONNECT: if (m_linkType == LINK_YSF) { LogMessage("Disconnect has been requested by %10.10s", buffer + 14U); + if ( (wiresXCommandPassthrough) && (::memcmp(buffer + 0U, "YSFD", 4U) == 0) ) { + // Send the disconnect to the YSF2xxx gateway too + m_ysfNetwork->write(buffer); + } m_ysfNetwork->writeUnlink(3U); m_ysfNetwork->clearDestination(); diff --git a/YSFGateway/YSFGateway.h b/YSFGateway/YSFGateway.h index e25b3e6..aad13b9 100644 --- a/YSFGateway/YSFGateway.h +++ b/YSFGateway/YSFGateway.h @@ -66,7 +66,7 @@ private: void startupLinking(); std::string calculateLocator(); - void processWiresX(const unsigned char* buffer, unsigned char fi, unsigned char dt, unsigned char fn, unsigned char ft); + void processWiresX(const unsigned char* buffer, unsigned char fi, unsigned char dt, unsigned char fn, unsigned char ft, bool dontProcessWiresXLocal, bool wiresXCommandPassthrough); void processDTMF(unsigned char* buffer, unsigned char dt); void createWiresX(CYSFNetwork* rptNetwork); void createGPS(); diff --git a/YSFGateway/YSFGateway.ini b/YSFGateway/YSFGateway.ini index e83a3bb..5352edd 100644 --- a/YSFGateway/YSFGateway.ini +++ b/YSFGateway/YSFGateway.ini @@ -8,6 +8,7 @@ RptPort=3200 LocalAddress=127.0.0.1 LocalPort=4200 WiresXMakeUpper=1 +WiresXCommandPassthrough=0 Daemon=0 [Info] diff --git a/YSFGateway/YSFReflectors.cpp b/YSFGateway/YSFReflectors.cpp index cbfd54b..893307c 100644 --- a/YSFGateway/YSFReflectors.cpp +++ b/YSFGateway/YSFReflectors.cpp @@ -139,6 +139,7 @@ bool CYSFReflectors::load() refl->m_port = (unsigned int)::atoi(p5); refl->m_count = std::string(p6); refl->m_type = YT_YSF; + refl->m_wiresX = false; refl->m_name.resize(16U, ' '); refl->m_desc.resize(14U, ' '); @@ -164,6 +165,7 @@ bool CYSFReflectors::load() refl->m_port = m_parrotPort; refl->m_count = "000"; refl->m_type = YT_YSF; + refl->m_wiresX = false; m_newReflectors.push_back(refl); @@ -180,6 +182,7 @@ bool CYSFReflectors::load() refl->m_port = m_YSF2DMRPort; refl->m_count = "000"; refl->m_type = YT_YSF; + refl->m_wiresX = true; m_newReflectors.push_back(refl); @@ -196,6 +199,7 @@ bool CYSFReflectors::load() refl->m_port = m_YSF2NXDNPort; refl->m_count = "000"; refl->m_type = YT_YSF; + refl->m_wiresX = true; m_newReflectors.push_back(refl); @@ -212,6 +216,7 @@ bool CYSFReflectors::load() refl->m_port = m_YSF2P25Port; refl->m_count = "000"; refl->m_type = YT_YSF; + refl->m_wiresX = true; m_newReflectors.push_back(refl); @@ -227,12 +232,13 @@ bool CYSFReflectors::load() std::string desc = it->second; CYSFReflector* refl = new CYSFReflector; - refl->m_id = text; - refl->m_name = name; - refl->m_desc = desc; - refl->m_port = 0U; - refl->m_count = "000"; - refl->m_type = YT_FCS; + refl->m_id = text; + refl->m_name = name; + refl->m_desc = desc; + refl->m_port = 0U; + refl->m_count = "000"; + refl->m_type = YT_FCS; + refl->m_wiresX = false; refl->m_name.resize(16U, ' '); refl->m_desc.resize(14U, ' '); diff --git a/YSFGateway/YSFReflectors.h b/YSFGateway/YSFReflectors.h index b52092b..1bc5c05 100644 --- a/YSFGateway/YSFReflectors.h +++ b/YSFGateway/YSFReflectors.h @@ -39,7 +39,8 @@ public: m_count("000"), m_address(), m_port(0U), - m_type(YT_YSF) + m_type(YT_YSF), + m_wiresX(false) { } @@ -50,6 +51,7 @@ public: in_addr m_address; unsigned int m_port; YSF_TYPE m_type; + bool m_wiresX; }; class CYSFReflectors {