diff --git a/AX25Control.cpp b/AX25Control.cpp index d9f9a2f..a6b89ea 100644 --- a/AX25Control.cpp +++ b/AX25Control.cpp @@ -27,8 +27,9 @@ const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04 #define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) #define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) -CAX25Control::CAX25Control(CAX25Network* network) : +CAX25Control::CAX25Control(CAX25Network* network, bool trace) : m_network(network), +m_trace(trace), m_enabled(true), m_fp(NULL) { @@ -45,7 +46,15 @@ bool CAX25Control::writeModem(unsigned char *data, unsigned int len) if (!m_enabled) return false; - CUtils::dump(1U, "AX.25 raw packet", data, len); + if (m_trace) + decode(data, len); + + CUtils::dump(1U, "AX.25 raw packet", data, len); + + if (m_network != NULL) { + if (isUI(data, len)) + m_network->writeAX25(data, len); + } return true; } @@ -95,3 +104,144 @@ void CAX25Control::enable(bool enabled) { m_enabled = enabled; } + +void CAX25Control::decode(const unsigned char* data, unsigned int length) +{ + assert(data != NULL); + assert(length >= 15U); + + std::string text; + + bool more = decodeAddress(data + 7U, text); + + text += '>'; + + decodeAddress(data + 0U, text); + + unsigned int n = 14U; + while (more && n < length) { + text += ','; + more = decodeAddress(data + n, text, true); + n += 7U; + } + + text += ' '; + + if ((data[n] & 0x01U) == 0x00U) { + // I frame + char t[20U]; + ::sprintf(t, "", (data[n] >> 1) & 0x07U, (data[n] >> 5) & 0x07U); + text += t; + } else { + if ((data[n] & 0x02U) == 0x00U) { + // S frame + char t[20U]; + switch (data[n] & 0x0FU) { + case 0x01U: + sprintf(t, "", (data[n] >> 5) & 0x07U); + break; + case 0x05U: + sprintf(t, "", (data[n] >> 5) & 0x07U); + break; + case 0x09U: + sprintf(t, "", (data[n] >> 5) & 0x07U); + break; + case 0x0DU: + sprintf(t, "", (data[n] >> 5) & 0x07U); + break; + default: + sprintf(t, "", (data[n] >> 5) & 0x07U); + break; + } + + text += t; + LogMessage("AX.25, %s", text.c_str()); + return; + } else { + // U frame + switch (data[n] & 0xEFU) { + case 0x6FU: + text += ""; + break; + case 0x2FU: + text += ""; + break; + case 0x43U: + text += ""; + break; + case 0x0FU: + text += ""; + break; + case 0x63U: + text += ""; + break; + case 0x87U: + text += ""; + break; + case 0x03U: + text += ""; + break; + case 0xAFU: + text += ""; + break; + case 0xE3U: + text += ""; + break; + default: + text += ""; + break; + } + + if ((data[n] & 0xEFU) != 0x03U) { + LogMessage("AX.25, %s", text.c_str()); + return; + } + } + } + + n += 2U; + + LogMessage("AX.25, %s %.*s", text.c_str(), length - n, data + n); +} + +bool CAX25Control::decodeAddress(const unsigned char* data, std::string& text, bool isDigi) const +{ + assert(data != NULL); + + for (unsigned int i = 0U; i < 6U; i++) { + char c = data[i] >> 1; + if (c != ' ') + text += c; + } + + unsigned char ssid = (data[6U] >> 1) & 0x0FU; + if (ssid > 0U) { + text += '-'; + if (ssid >= 10U) { + text += '1'; + text += '0' + ssid - 10U; + } + else { + text += '0' + ssid; + } + } + + if (isDigi) { + if ((data[6U] & 0x80U) == 0x80U) + text += '*'; + } + + return (data[6U] & 0x01U) == 0x00U; +} + +bool CAX25Control::isUI(const unsigned char* data, unsigned int length) const +{ + assert(data != NULL); + assert(length >= 15U); + + unsigned int n = 13U; + while ((data[n] & 0x01U) == 0x00U && n < length) + n += 7U; + + return (data[n + 1U] & 0xEFU) == 0x03U; +} diff --git a/AX25Control.h b/AX25Control.h index 2f73874..59b5688 100644 --- a/AX25Control.h +++ b/AX25Control.h @@ -25,7 +25,7 @@ class CAX25Control { public: - CAX25Control(CAX25Network* network); + CAX25Control(CAX25Network* network, bool trace); ~CAX25Control(); bool writeModem(unsigned char* data, unsigned int len); @@ -34,9 +34,13 @@ public: private: CAX25Network* m_network; + bool m_trace; bool m_enabled; FILE* m_fp; + bool isUI(const unsigned char* data, unsigned int length) const; + void decode(const unsigned char* data, unsigned int length); + bool decodeAddress(const unsigned char* data, std::string& text, bool isDigi = false) const; bool openFile(); bool writeFile(const unsigned char* data, unsigned int length); void closeFile(); diff --git a/AX25Network.cpp b/AX25Network.cpp index 8123c51..3f5ac49 100644 --- a/AX25Network.cpp +++ b/AX25Network.cpp @@ -74,26 +74,6 @@ bool CAX25Network::writeAX25(const unsigned char* data, unsigned int length) return m_socket.write(buffer, length + 4U, m_address, m_port); } -bool CAX25Network::writeMICE(const unsigned char* data, unsigned int length) -{ - assert(data != NULL); - - unsigned char buffer[110U]; - ::memset(buffer, 0x00U, 110U); - - buffer[0U] = 'M'; - buffer[1U] = 'I'; - buffer[2U] = 'C'; - buffer[3U] = 'E'; - - ::memcpy(buffer + 4U, data, length); - - if (m_debug) - CUtils::dump(1U, "AX25 Network Data Sent", buffer, length + 4U); - - return m_socket.write(buffer, length + 4U, m_address, m_port); -} - void CAX25Network::reset() { } diff --git a/AX25Network.h b/AX25Network.h index b171e6a..866ae7e 100644 --- a/AX25Network.h +++ b/AX25Network.h @@ -34,7 +34,6 @@ public: void enable(bool enabled); bool writeAX25(const unsigned char* data, unsigned int length); - bool writeMICE(const unsigned char* data, unsigned int length); void reset(); diff --git a/Conf.cpp b/Conf.cpp index 5e10a9f..1e14523 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -208,6 +208,7 @@ m_fmRFAudioBoost(1U), m_fmMaxDevLevel(90.0F), m_fmExtAudioBoost(1U), m_ax25Enabled(false), +m_ax25Trace(false), m_dstarNetworkEnabled(false), m_dstarGatewayAddress(), m_dstarGatewayPort(0U), @@ -789,8 +790,10 @@ bool CConf::read() else if (::strcmp(key, "ExtAudioBoost") == 0) m_fmExtAudioBoost = (unsigned int)::atoi(value); } else if (section == SECTION_AX25) { - if (::strcmp(key, "Enable") == 0) - m_ax25Enabled = ::atoi(value) == 1; + if (::strcmp(key, "Enable") == 0) + m_ax25Enabled = ::atoi(value) == 1; + else if (::strcmp(key, "Trace") == 0) + m_ax25Trace = ::atoi(value) == 1; } else if (section == SECTION_DSTAR_NETWORK) { if (::strcmp(key, "Enable") == 0) m_dstarNetworkEnabled = ::atoi(value) == 1; @@ -1713,6 +1716,11 @@ bool CConf::getAX25Enabled() const return m_ax25Enabled; } +bool CConf::getAX25Trace() const +{ + return m_ax25Trace; +} + bool CConf::getDStarNetworkEnabled() const { return m_dstarNetworkEnabled; diff --git a/Conf.h b/Conf.h index ef584c7..0d340f9 100644 --- a/Conf.h +++ b/Conf.h @@ -173,6 +173,7 @@ public: // The AX.25 section bool getAX25Enabled() const; + bool getAX25Trace() const; // The FM Section bool getFMEnabled() const; @@ -455,6 +456,7 @@ private: unsigned int m_pocsagFrequency; bool m_ax25Enabled; + bool m_ax25Trace; bool m_fmEnabled; std::string m_fmCallsign; diff --git a/MMDVM.ini b/MMDVM.ini index e6de0fb..de6408d 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -177,6 +177,7 @@ ExtAudioBoost=1 [AX.25] Enable=1 +Trace=1 [D-Star Network] Enable=1 diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index ebc5613..9c452dc 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -626,10 +626,13 @@ int CMMDVMHost::run() } if (m_ax25Enabled) { + bool trace = m_conf.getAX25Trace(); + LogInfo("AX.25 RF Parameters"); LogInfo(" RXOnly: yes"); + LogInfo(" Trace: %s", trace ? "yes" : "no"); - m_ax25 = new CAX25Control(m_ax25Network); + m_ax25 = new CAX25Control(m_ax25Network, trace); } bool remoteControlEnabled = m_conf.getRemoteControlEnabled(); diff --git a/Version.h b/Version.h index 6b25bcc..279ecfd 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200609"; +const char* VERSION = "20200618"; #endif