diff --git a/NXDNControl.cpp b/NXDNControl.cpp index a612475..74627fd 100644 --- a/NXDNControl.cpp +++ b/NXDNControl.cpp @@ -158,16 +158,16 @@ bool CNXDNControl::writeModem(unsigned char *data, unsigned int len) if (usc == NXDN_LICH_USC_UDCH) ret = processData(option, data); else - ret = processVoice(usc, option, data); + ret = processVoice(valid, usc, option, data); return ret; } -bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigned char *data) +bool CNXDNControl::processVoice(bool validLICH, unsigned char usc, unsigned char option, unsigned char *data) { CNXDNSACCH sacch; - bool valid = sacch.decode(data + 2U); - if (valid) { + bool validSACCH = sacch.decode(data + 2U); + if (validSACCH) { unsigned char ran = sacch.getRAN(); if (ran != m_ran && ran != 0U) return false; @@ -175,7 +175,21 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne return false; } - // XXX Reconstruct invalid LICH + // Reconstruct invalid LICH + if (!validLICH) { + if (usc == NXDN_LICH_USC_SACCH_NS) { + option = NXDN_LICH_STEAL_NONE; + usc = NXDN_LICH_USC_SACCH_SS; + } else { + if (option == NXDN_LICH_STEAL_FACCH) + option = NXDN_LICH_STEAL_NONE; + else if (option == NXDN_LICH_STEAL_NONE) + option = NXDN_LICH_STEAL_FACCH; + } + + m_rfLastLICH.setFCT(usc); + m_rfLastLICH.setOption(option); + } if (usc == NXDN_LICH_USC_SACCH_NS) { // The SACCH on a non-superblock frame is usually an idle and not interesting apart from the RAN. @@ -425,10 +439,16 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne lich.setDirection(m_remoteGateway ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND); lich.encode(data + 2U); - // XXX Regenerate SACCH here + // Regenerate SACCH if it's valid + CNXDNSACCH sacch; + bool validSACCH = sacch.decode(data + 2U); + if (validSACCH) { + sacch.setRAN(m_ran); + sacch.encode(data + 2U); + } // Regenerate the audio and interpret the FACCH1 data - unsigned char voiceMode = m_rfLayer3.getCallOptions() & 0x07U; + unsigned char voiceMode = m_rfLayer3.getVoiceMode(); if (option == NXDN_LICH_STEAL_NONE) { CAMBEFEC ambe; @@ -531,11 +551,11 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne bool CNXDNControl::processData(unsigned char option, unsigned char *data) { CNXDNUDCH udch; - bool valid = udch.decode(data + 2U); - if (m_rfState == RS_RF_LISTENING && !valid) + bool validUDCH = udch.decode(data + 2U); + if (m_rfState == RS_RF_LISTENING && !validUDCH) return false; - if (valid) { + if (validUDCH) { unsigned char ran = udch.getRAN(); if (ran != m_ran && ran != 0U) return false; @@ -593,7 +613,7 @@ bool CNXDNControl::processData(unsigned char option, unsigned char *data) lich.setDirection(m_remoteGateway ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND); lich.encode(data + 2U); - if (valid) { + if (validUDCH) { udch.setRAN(m_ran); udch.encode(data + 2U); } @@ -609,7 +629,7 @@ bool CNXDNControl::processData(unsigned char option, unsigned char *data) writeFile(data + 2U); #endif - if (valid) { + if (validUDCH) { unsigned char type = layer3.getMessageType(); if (type == NXDN_MESSAGE_TYPE_TX_REL) { LogMessage("NXDN, ended RF data transmission"); diff --git a/NXDNControl.h b/NXDNControl.h index 5f000e7..8dfaedd 100644 --- a/NXDNControl.h +++ b/NXDNControl.h @@ -81,7 +81,7 @@ private: unsigned int m_rssiCount; FILE* m_fp; - bool processVoice(unsigned char usc, unsigned char option, unsigned char *data); + bool processVoice(bool validLICH, unsigned char usc, unsigned char option, unsigned char *data); bool processData(unsigned char option, unsigned char *data); void writeQueueRF(const unsigned char* data); diff --git a/NXDNLayer3.cpp b/NXDNLayer3.cpp index f1b98f3..72b938a 100644 --- a/NXDNLayer3.cpp +++ b/NXDNLayer3.cpp @@ -87,9 +87,9 @@ bool CNXDNLayer3::getIsGroup() const return (m_data[2U] & 0x80U) != 0x80U; } -unsigned char CNXDNLayer3::getCallOptions() const +unsigned char CNXDNLayer3::getVoiceMode() const { - return m_data[2U] & 0x1FU; + return m_data[2U] & 0x07U; } unsigned char CNXDNLayer3::getDataBlocks() const diff --git a/NXDNLayer3.h b/NXDNLayer3.h index d39a41b..b0749a2 100644 --- a/NXDNLayer3.h +++ b/NXDNLayer3.h @@ -33,7 +33,7 @@ public: unsigned short getSourceUnitId() const; unsigned short getDestinationGroupId() const; bool getIsGroup() const; - unsigned char getCallOptions() const; + unsigned char getVoiceMode() const; unsigned char getDataBlocks() const; void getData(unsigned char* data) const;