diff --git a/ambed/WinTypes.h b/ambed/WinTypes.h old mode 100755 new mode 100644 index 88e500e..df4c16f --- a/ambed/WinTypes.h +++ b/ambed/WinTypes.h @@ -36,24 +36,28 @@ typedef void VOID; typedef USHORT *PUSHORT; typedef unsigned long long int ULONGLONG; -typedef struct _OVERLAPPED { - DWORD Internal; - DWORD InternalHigh; - union { - struct{ - DWORD Offset; - DWORD OffsetHigh; - }; - PVOID Pointer; - }; - HANDLE hEvent; +typedef struct _OVERLAPPED +{ + DWORD Internal; + DWORD InternalHigh; + union + { + struct + { + DWORD Offset; + DWORD OffsetHigh; + }; + PVOID Pointer; + }; + HANDLE hEvent; } OVERLAPPED, *LPOVERLAPPED; -typedef struct _SECURITY_ATTRIBUTES { - DWORD nLength; - LPVOID lpSecurityDescriptor; - BOOL bInheritHandle; -} SECURITY_ATTRIBUTES , *LPSECURITY_ATTRIBUTES; +typedef struct _SECURITY_ATTRIBUTES +{ + DWORD nLength; + LPVOID lpSecurityDescriptor; + BOOL bInheritHandle; +} SECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES; #include // Substitute for HANDLE returned by Windows CreateEvent API. @@ -61,9 +65,9 @@ typedef struct _SECURITY_ATTRIBUTES { // of one of these structures. typedef struct _EVENT_HANDLE { - pthread_cond_t eCondVar; - pthread_mutex_t eMutex; - int iVar; + pthread_cond_t eCondVar; + pthread_mutex_t eMutex; + int iVar; } EVENT_HANDLE; typedef struct timeval SYSTEMTIME; diff --git a/ambed/cagc.cpp b/ambed/cagc.cpp index 880323d..119bfee 100644 --- a/ambed/cagc.cpp +++ b/ambed/cagc.cpp @@ -34,21 +34,21 @@ CAGC::CAGC(float initialLeveldB) { - // set internal gain appropriately - m_Gain = pow(10.0f, initialLeveldB/20.0f); - //+- 10dB Margin, TODO Move margin to constant - m_GainMax = pow(10.0f, (initialLeveldB + AGC_CLAMPING)/20.0f); - m_GainMin = pow(10.0f, (initialLeveldB - AGC_CLAMPING)/20.0f); - - m_EnergyPrime = 1.0f; + // set internal gain appropriately + m_Gain = pow(10.0f, initialLeveldB/20.0f); + //+- 10dB Margin, TODO Move margin to constant + m_GainMax = pow(10.0f, (initialLeveldB + AGC_CLAMPING)/20.0f); + m_GainMin = pow(10.0f, (initialLeveldB - AGC_CLAMPING)/20.0f); - // We do not target full scale to avoid stauration - m_targetEnergy = 32767.0f * pow(10.0f, (initialLeveldB - 25.0)/20.0f);//25 dB below saturation as stated in docs - //we also substract our target gain + m_EnergyPrime = 1.0f; - //this is the time constant of our AGC... - m_Bandwidth = 1e-2f;//TODO : Move to parameter ? - m_Alpha = m_Bandwidth; + // We do not target full scale to avoid stauration + m_targetEnergy = 32767.0f * pow(10.0f, (initialLeveldB - 25.0)/20.0f);//25 dB below saturation as stated in docs + //we also substract our target gain + + //this is the time constant of our AGC... + m_Bandwidth = 1e-2f;//TODO : Move to parameter ? + m_Alpha = m_Bandwidth; } //////////////////////////////////////////////////////////////////////////////////////// @@ -56,39 +56,39 @@ CAGC::CAGC(float initialLeveldB) float CAGC::GetGain() { - return 20.0f*log10(m_Gain); + return 20.0f*log10(m_Gain); } //////////////////////////////////////////////////////////////////////////////////////// // process -inline void CAGC::ProcessSampleBlock(uint8* voice, int length) +inline void CAGC::ProcessSampleBlock(uint8* voice, int length) { - for(int i = 0; i < length; i += 2) - { - float input = (float)(short)MAKEWORD(voice[i+1], voice[i]); - //apply AGC - // apply gain to input sample - float output = input * m_Gain; + for(int i = 0; i < length; i += 2) + { + float input = (float)(short)MAKEWORD(voice[i+1], voice[i]); + //apply AGC + // apply gain to input sample + float output = input * m_Gain; - // compute output signal energy, scaled to 0 to 1 - float instantEnergy = abs(output) / m_targetEnergy; + // compute output signal energy, scaled to 0 to 1 + float instantEnergy = abs(output) / m_targetEnergy; - // smooth energy estimate using single-pole low-pass filter - m_EnergyPrime = (1.0f - m_Alpha) * m_EnergyPrime + m_Alpha * instantEnergy; + // smooth energy estimate using single-pole low-pass filter + m_EnergyPrime = (1.0f - m_Alpha) * m_EnergyPrime + m_Alpha * instantEnergy; - // update gain according to output energy - if (m_EnergyPrime > 1e-6f) - m_Gain *= exp( -0.5f * m_Alpha * log(m_EnergyPrime) ); + // update gain according to output energy + if (m_EnergyPrime > 1e-6f) + m_Gain *= exp( -0.5f * m_Alpha * log(m_EnergyPrime) ); - // clamp gain - if (m_Gain > m_GainMax) - m_Gain = m_GainMax; - else if(m_Gain < m_GainMin) - m_Gain = m_GainMin; + // clamp gain + if (m_Gain > m_GainMax) + m_Gain = m_GainMax; + else if(m_Gain < m_GainMin) + m_Gain = m_GainMin; - //write processed sample back - voice[i] = HIBYTE((short)output); - voice[i+1] = LOBYTE((short)output); - } + //write processed sample back + voice[i] = HIBYTE((short)output); + voice[i+1] = LOBYTE((short)output); + } } diff --git a/ambed/cagc.h b/ambed/cagc.h index f0ebf75..1ab4a5a 100644 --- a/ambed/cagc.h +++ b/ambed/cagc.h @@ -23,7 +23,7 @@ // ---------------------------------------------------------------------------- // Geoffrey Merck F4FXL / KC3FRA AGC code largely inspired by Liquid DSP // Only took the parts we need qnd recoeded it to be close the XLX coding style -// https://github.com/jgaeddert/liquid-dsp/blob/master/src/agc/src/agc.c +// https://github.com/jgaeddert/liquid-dsp/blob/master/src/agc/src/agc.c #ifndef cagc_h #define cagc_h @@ -33,24 +33,24 @@ class CAGC : CSampleBlockProcessor { public: - //Constructor - CAGC(float initialLeveldB); + //Constructor + CAGC(float initialLeveldB); + + //methods + void ProcessSampleBlock(uint8* voice, int length) ; + float GetGain();//gets current gain - //methods - void ProcessSampleBlock(uint8* voice, int length) ; - float GetGain();//gets current gain - private: - float m_Gain; // current gain value - float m_GainMax, m_GainMin; //gain clamping - float m_targetEnergy; // scale value for target energy + float m_Gain; // current gain value + float m_GainMax, m_GainMin; //gain clamping + float m_targetEnergy; // scale value for target energy - // gain control loop filter parameters - float m_Bandwidth; // bandwidth-time constant - float m_Alpha; // feed-back gain + // gain control loop filter parameters + float m_Bandwidth; // bandwidth-time constant + float m_Alpha; // feed-back gain - // signal level estimate - float m_EnergyPrime; // filtered output signal energy estimate + // signal level estimate + float m_EnergyPrime; // filtered output signal energy estimate }; #endif /* cgc_h */ \ No newline at end of file diff --git a/ambed/cambepacket.cpp b/ambed/cambepacket.cpp index e5fe175..4fefe53 100644 --- a/ambed/cambepacket.cpp +++ b/ambed/cambepacket.cpp @@ -35,22 +35,22 @@ CAmbePacket::CAmbePacket() { - m_uiCodec = CODEC_NONE; - ::memset(m_uiAmbe, 0, AMBE_SIZE); + m_uiCodec = CODEC_NONE; + ::memset(m_uiAmbe, 0, AMBE_SIZE); } CAmbePacket::CAmbePacket(uint8 uiPid, uint8 uiCodec, const uint8 *Ambe) - : CPacket(uiPid) + : CPacket(uiPid) { - m_uiCodec = uiCodec; - ::memcpy(m_uiAmbe, Ambe, AMBE_SIZE); + m_uiCodec = uiCodec; + ::memcpy(m_uiAmbe, Ambe, AMBE_SIZE); } CAmbePacket::CAmbePacket(const CAmbePacket &packet) - : CPacket(packet) + : CPacket(packet) { - m_uiCodec = packet.m_uiCodec; - ::memcpy(m_uiAmbe, packet.m_uiAmbe, sizeof(m_uiAmbe)); + m_uiCodec = packet.m_uiCodec; + ::memcpy(m_uiAmbe, packet.m_uiAmbe, sizeof(m_uiAmbe)); } @@ -66,6 +66,6 @@ CAmbePacket::~CAmbePacket() void CAmbePacket::SetAmbe(const uint8 *p) { - ::memcpy(m_uiAmbe, p, AMBE_SIZE); + ::memcpy(m_uiAmbe, p, AMBE_SIZE); } diff --git a/ambed/cambepacket.h b/ambed/cambepacket.h index f6ae00a..0dccadb 100644 --- a/ambed/cambepacket.h +++ b/ambed/cambepacket.h @@ -40,30 +40,30 @@ class CAmbePacket : public CPacket { public: - // constructors - CAmbePacket(); - CAmbePacket(uint8, uint8, const uint8 *); - CAmbePacket(const CAmbePacket &); - - // destructor - virtual ~CAmbePacket(); - - // identity - bool IsAmbe(void) const { return true; } - - // get - uint8 GetCodec(void) const { return m_uiCodec; } - uint8 *GetAmbe(void) { return m_uiAmbe; } - int GetAmbeSize(void) const { return AMBE_SIZE; } - - // set - void SetCodec(uint8 c) { m_uiCodec = c; } - void SetAmbe(const uint8 *); - + // constructors + CAmbePacket(); + CAmbePacket(uint8, uint8, const uint8 *); + CAmbePacket(const CAmbePacket &); + + // destructor + virtual ~CAmbePacket(); + + // identity + bool IsAmbe(void) const { return true; } + + // get + uint8 GetCodec(void) const { return m_uiCodec; } + uint8 *GetAmbe(void) { return m_uiAmbe; } + int GetAmbeSize(void) const { return AMBE_SIZE; } + + // set + void SetCodec(uint8 c) { m_uiCodec = c; } + void SetAmbe(const uint8 *); + protected: - // data - uint8 m_uiCodec; - uint8 m_uiAmbe[AMBE_SIZE]; + // data + uint8 m_uiCodec; + uint8 m_uiAmbe[AMBE_SIZE]; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/ambed/cambeserver.cpp b/ambed/cambeserver.cpp index a1ba9d5..f50a5d2 100644 --- a/ambed/cambeserver.cpp +++ b/ambed/cambeserver.cpp @@ -40,20 +40,20 @@ CAmbeServer g_AmbeServer; bool CAmbeServer::Start(void) { - // init interfaces & controller - std::cout << "Initializing vocodecs:" << std::endl; - if (! g_Vocodecs.Init()) + // init interfaces & controller + std::cout << "Initializing vocodecs:" << std::endl; + if (! g_Vocodecs.Init()) return false; - std::cout << "Initializing controller" << std::endl; - if (! m_Controller.Init()) + std::cout << "Initializing controller" << std::endl; + if (! m_Controller.Init()) return false; - return true; + return true; } void CAmbeServer::Stop(void) { - // stop controller - m_Controller.Close(); + // stop controller + m_Controller.Close(); } diff --git a/ambed/cambeserver.h b/ambed/cambeserver.h index 8a010b9..0e3fb8f 100644 --- a/ambed/cambeserver.h +++ b/ambed/cambeserver.h @@ -35,27 +35,27 @@ class CAmbeServer { public: - // operation - bool Start(void); - void Stop(void); + // operation + bool Start(void); + void Stop(void); - // task - static void Thread(CAmbeServer *); - void Task(void); + // task + static void Thread(CAmbeServer *); + void Task(void); - // get - const char *GetListenIp(void) const { return m_Controller.GetListenIp(); } + // get + const char *GetListenIp(void) const { return m_Controller.GetListenIp(); } - // set - void SetListenIp(const char *ip) { m_Controller.SetListenIp(ip); } + // set + void SetListenIp(const char *ip) { m_Controller.SetListenIp(ip); } protected: - // objects - CController m_Controller; + // objects + CController m_Controller; public: #ifdef DEBUG_DUMPFILE - std::ofstream m_DebugFile; + std::ofstream m_DebugFile; #endif }; diff --git a/ambed/ccallsign.cpp b/ambed/ccallsign.cpp index d44c769..a9cf00f 100644 --- a/ambed/ccallsign.cpp +++ b/ambed/ccallsign.cpp @@ -32,14 +32,14 @@ CCallsign::CCallsign() { - // blank all - ::memset(m_Callsign, ' ', sizeof(m_Callsign)); + // blank all + ::memset(m_Callsign, ' ', sizeof(m_Callsign)); } CCallsign::CCallsign(const char *sz) { - ::memset(m_Callsign, ' ', sizeof(m_Callsign)); - ::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign))); + ::memset(m_Callsign, ' ', sizeof(m_Callsign)); + ::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign))); } //////////////////////////////////////////////////////////////////////////////////////// @@ -47,29 +47,29 @@ CCallsign::CCallsign(const char *sz) bool CCallsign::IsValid(void) const { - bool valid = true; - int i; - - // callsign - // first 3 chars are letter or number but cannot be all number - int iNum = 0; - for ( i = 0; i < 3; i++ ) - { - valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]); - if ( IsNumber(m_Callsign[i]) ) - { - iNum++; - } - } - valid &= (iNum < 3); - // all remaining char are letter, number or space - for ( ; i < CALLSIGN_LEN; i++) - { - valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]) || IsSpace(m_Callsign[i]); - } - - // done - return valid; + bool valid = true; + int i; + + // callsign + // first 3 chars are letter or number but cannot be all number + int iNum = 0; + for ( i = 0; i < 3; i++ ) + { + valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]); + if ( IsNumber(m_Callsign[i]) ) + { + iNum++; + } + } + valid &= (iNum < 3); + // all remaining char are letter, number or space + for ( ; i < CALLSIGN_LEN; i++) + { + valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]) || IsSpace(m_Callsign[i]); + } + + // done + return valid; } @@ -78,23 +78,23 @@ bool CCallsign::IsValid(void) const void CCallsign::SetCallsign(const char *sz) { - // set callsign - ::memset(m_Callsign, ' ', sizeof(m_Callsign)); - ::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign))); + // set callsign + ::memset(m_Callsign, ' ', sizeof(m_Callsign)); + ::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign))); } void CCallsign::SetCallsign(const uint8 *buffer, int len) { - // set callsign - ::memset(m_Callsign, ' ', sizeof(m_Callsign)); - ::memcpy(m_Callsign, buffer, MIN(len, sizeof(m_Callsign))); - for ( unsigned i = 0; i < sizeof(m_Callsign); i++ ) - { - if ( m_Callsign[i] == 0 ) - { - m_Callsign[i] = ' '; - } - } + // set callsign + ::memset(m_Callsign, ' ', sizeof(m_Callsign)); + ::memcpy(m_Callsign, buffer, MIN(len, sizeof(m_Callsign))); + for ( unsigned i = 0; i < sizeof(m_Callsign); i++ ) + { + if ( m_Callsign[i] == 0 ) + { + m_Callsign[i] = ' '; + } + } } @@ -103,10 +103,10 @@ void CCallsign::SetCallsign(const uint8 *buffer, int len) void CCallsign::PatchCallsign(int off, const uint8 *patch, int len) { - if ( off < int(sizeof(m_Callsign)) ) - { - ::memcpy(m_Callsign, patch, MIN(len, sizeof(m_Callsign) - off)); - } + if ( off < int(sizeof(m_Callsign)) ) + { + ::memcpy(m_Callsign, patch, MIN(len, sizeof(m_Callsign) - off)); + } } @@ -115,17 +115,17 @@ void CCallsign::PatchCallsign(int off, const uint8 *patch, int len) void CCallsign::GetCallsign(uint8 *buffer) const { - ::memcpy(buffer, m_Callsign, sizeof(m_Callsign)); + ::memcpy(buffer, m_Callsign, sizeof(m_Callsign)); } void CCallsign::GetCallsignString(char *sz) const { - unsigned i; - for ( i = 0; (i < sizeof(m_Callsign)) && (m_Callsign[i] != ' '); i++ ) - { - sz[i] = m_Callsign[i]; - } - sz[i] = 0; + unsigned i; + for ( i = 0; (i < sizeof(m_Callsign)) && (m_Callsign[i] != ' '); i++ ) + { + sz[i] = m_Callsign[i]; + } + sz[i] = 0; } //////////////////////////////////////////////////////////////////////////////////////// @@ -133,22 +133,22 @@ void CCallsign::GetCallsignString(char *sz) const bool CCallsign::HasSameCallsign(const CCallsign &Callsign) const { - return (::memcmp(m_Callsign, Callsign.m_Callsign, sizeof(m_Callsign)) == 0); + return (::memcmp(m_Callsign, Callsign.m_Callsign, sizeof(m_Callsign)) == 0); } bool CCallsign::HasSameCallsignWithWildcard(const CCallsign &callsign) const { - bool same = true; - bool done = false; - - for ( unsigned i = 0; (i < sizeof(m_Callsign)) && same && !done; i++ ) - { - if ( !(done = ((m_Callsign[i] == '*') || (callsign[i] == '*'))) ) - { - same &= (m_Callsign[i] == callsign[i]); - } - } - return same; + bool same = true; + bool done = false; + + for ( unsigned i = 0; (i < sizeof(m_Callsign)) && same && !done; i++ ) + { + if ( !(done = ((m_Callsign[i] == '*') || (callsign[i] == '*'))) ) + { + same &= (m_Callsign[i] == callsign[i]); + } + } + return same; } @@ -157,7 +157,7 @@ bool CCallsign::HasSameCallsignWithWildcard(const CCallsign &callsign) const bool CCallsign::operator ==(const CCallsign &callsign) const { - return (::memcmp(callsign.m_Callsign, m_Callsign, sizeof(m_Callsign)) == 0); + return (::memcmp(callsign.m_Callsign, m_Callsign, sizeof(m_Callsign)) == 0); } CCallsign::operator const char *() const @@ -166,12 +166,12 @@ CCallsign::operator const char *() const // empty ::memset(sz, 0, sizeof(m_sz)); - // callsign - sz[CALLSIGN_LEN] = 0; - ::memcpy(sz, m_Callsign, sizeof(m_Callsign)); + // callsign + sz[CALLSIGN_LEN] = 0; + ::memcpy(sz, m_Callsign, sizeof(m_Callsign)); - // done - return m_sz; + // done + return m_sz; } //////////////////////////////////////////////////////////////////////////////////////// @@ -179,15 +179,15 @@ CCallsign::operator const char *() const bool CCallsign::IsNumber(char c) const { - return ((c >= '0') && (c <= '9')); + return ((c >= '0') && (c <= '9')); } bool CCallsign::IsLetter(char c) const { - return ((c >= 'A') && (c <= 'Z')); + return ((c >= 'A') && (c <= 'Z')); } bool CCallsign::IsSpace(char c) const { - return (c == ' '); + return (c == ' '); } diff --git a/ambed/ccallsign.h b/ambed/ccallsign.h index 1af9051..449c75a 100644 --- a/ambed/ccallsign.h +++ b/ambed/ccallsign.h @@ -37,42 +37,42 @@ class CCallsign { public: - // contructors - CCallsign(); - CCallsign(const char *); + // contructors + CCallsign(); + CCallsign(const char *); - // status - bool IsValid(void) const; + // status + bool IsValid(void) const; - // set - void SetCallsign(const char *); - void SetCallsign(const uint8 *, int); + // set + void SetCallsign(const char *); + void SetCallsign(const uint8 *, int); - // modify - void PatchCallsign(int, const uint8 *, int); + // modify + void PatchCallsign(int, const uint8 *, int); - // get - void GetCallsign(uint8 *) const; - void GetCallsignString(char *) const; + // get + void GetCallsign(uint8 *) const; + void GetCallsignString(char *) const; - // compare - bool HasSameCallsign(const CCallsign &) const; - bool HasSameCallsignWithWildcard(const CCallsign &) const; + // compare + bool HasSameCallsign(const CCallsign &) const; + bool HasSameCallsignWithWildcard(const CCallsign &) const; - // operators - bool operator ==(const CCallsign &) const; - operator const char *() const; + // operators + bool operator ==(const CCallsign &) const; + operator const char *() const; protected: - // helper - bool IsNumber(char) const; - bool IsLetter(char) const; - bool IsSpace(char) const; + // helper + bool IsNumber(char) const; + bool IsLetter(char) const; + bool IsSpace(char) const; protected: - // data - char m_Callsign[CALLSIGN_LEN]; - char m_sz[CALLSIGN_LEN+1]; + // data + char m_Callsign[CALLSIGN_LEN]; + char m_sz[CALLSIGN_LEN+1]; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/ambed/ccontroller.cpp b/ambed/ccontroller.cpp index 691d102..e81f4b9 100644 --- a/ambed/ccontroller.cpp +++ b/ambed/ccontroller.cpp @@ -34,9 +34,9 @@ CController::CController() { - m_bStopThread = false; - m_pThread = NULL; - m_uiLastStreamId = 0; + m_bStopThread = false; + m_pThread = NULL; + m_uiLastStreamId = 0; } //////////////////////////////////////////////////////////////////////////////////////// @@ -44,27 +44,27 @@ CController::CController() CController::~CController() { - // close socket - m_Socket.Close(); - - // close all streams - m_Mutex.lock(); - { - for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ ) - { - delete *it; - } - m_Streams.clear(); - - } - - m_Mutex.unlock(); - m_bStopThread = true; - if ( m_pThread != NULL ) - { - m_pThread->join(); - delete m_pThread; - } + // close socket + m_Socket.Close(); + + // close all streams + m_Mutex.lock(); + { + for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ ) + { + delete *it; + } + m_Streams.clear(); + + } + + m_Mutex.unlock(); + m_bStopThread = true; + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -72,35 +72,36 @@ CController::~CController() bool CController::Init(void) { - // reset stop flag - m_bStopThread = false; + // reset stop flag + m_bStopThread = false; - // create our socket + // create our socket CIp ip(strchr(m_addr, ':') ? AF_INET6 : AF_INET, TRANSCODER_PORT, m_addr); - if (! ip.IsSet()) { + if (! ip.IsSet()) + { std::cerr << "IP initialization failed for " << m_addr << std::endl; return false; } - if (! m_Socket.Open(ip)) - { - std::cout << "Error opening socket on port UDP" << TRANSCODER_PORT << " on ip " << ip.GetAddress() << std::endl; + if (! m_Socket.Open(ip)) + { + std::cout << "Error opening socket on port UDP" << TRANSCODER_PORT << " on ip " << ip.GetAddress() << std::endl; return false; - } - // start thread; - m_pThread = new std::thread(CController::Thread, this); + } + // start thread; + m_pThread = new std::thread(CController::Thread, this); - return true; + return true; } void CController::Close(void) { - m_bStopThread = true; - if ( m_pThread != NULL ) - { - m_pThread->join(); - delete m_pThread; - m_pThread = NULL; - } + m_bStopThread = true; + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + m_pThread = NULL; + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -108,10 +109,10 @@ void CController::Close(void) void CController::Thread(CController *This) { - while ( !This->m_bStopThread ) - { - This->Task(); - } + while ( !This->m_bStopThread ) + { + This->Task(); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -119,51 +120,51 @@ void CController::Thread(CController *This) void CController::Task(void) { - CBuffer Buffer; - CIp Ip; - CCallsign Callsign; - uint8 CodecIn; - uint8 CodecOut; - uint16 StreamId; - CStream *Stream; - - // anything coming in from codec client ? - if ( m_Socket.Receive(Buffer, Ip, 20) ) - { - // crack packet - if ( IsValidOpenstreamPacket(Buffer, &Callsign, &CodecIn, &CodecOut) ) - { - std::cout << "Stream Open from " << Callsign << std::endl; - - // try create the stream - Stream = OpenStream(Callsign, Ip, CodecIn, CodecOut); - - // send back details - if ( Stream != NULL ) - { - EncodeStreamDescrPacket(&Buffer, *Stream); - } - else - { - EncodeNoStreamAvailablePacket(&Buffer); - } - m_Socket.Send(Buffer, Ip); - } - else if ( IsValidClosestreamPacket(Buffer, &StreamId) ) - { - // close the stream - CloseStream(StreamId); - - std::cout << "Stream " << (int)StreamId << " closed" << std::endl; - } - else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) - { - //std::cout << "ping - " << Callsign << std::endl; - // pong back - EncodeKeepAlivePacket(&Buffer); - m_Socket.Send(Buffer, Ip); - } - } + CBuffer Buffer; + CIp Ip; + CCallsign Callsign; + uint8 CodecIn; + uint8 CodecOut; + uint16 StreamId; + CStream *Stream; + + // anything coming in from codec client ? + if ( m_Socket.Receive(Buffer, Ip, 20) ) + { + // crack packet + if ( IsValidOpenstreamPacket(Buffer, &Callsign, &CodecIn, &CodecOut) ) + { + std::cout << "Stream Open from " << Callsign << std::endl; + + // try create the stream + Stream = OpenStream(Callsign, Ip, CodecIn, CodecOut); + + // send back details + if ( Stream != NULL ) + { + EncodeStreamDescrPacket(&Buffer, *Stream); + } + else + { + EncodeNoStreamAvailablePacket(&Buffer); + } + m_Socket.Send(Buffer, Ip); + } + else if ( IsValidClosestreamPacket(Buffer, &StreamId) ) + { + // close the stream + CloseStream(StreamId); + + std::cout << "Stream " << (int)StreamId << " closed" << std::endl; + } + else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) + { + //std::cout << "ping - " << Callsign << std::endl; + // pong back + EncodeKeepAlivePacket(&Buffer); + m_Socket.Send(Buffer, Ip); + } + } // any inactive streams? Lock(); @@ -189,34 +190,34 @@ void CController::Task(void) CStream *CController::OpenStream(const CCallsign &Callsign, const CIp &Ip, uint8 CodecIn, uint8 CodecOut) { - CStream *stream = NULL; - - // create a new stream - m_uiLastStreamId = (m_uiLastStreamId + 1); - m_uiLastStreamId = (m_uiLastStreamId == NB_MAX_STREAMS+1) ? 1 : m_uiLastStreamId; - stream = new CStream(m_uiLastStreamId, Callsign, Ip, CodecIn, CodecOut); - if ( stream->Init(TRANSCODER_PORT+m_uiLastStreamId) ) - { - std::cout << "Opened stream " << m_uiLastStreamId << std::endl; - // and store it - Lock(); - m_Streams.push_back(stream); - Unlock(); - } - else - { - delete stream; - stream = NULL; - } - - // done - return stream; + CStream *stream = NULL; + + // create a new stream + m_uiLastStreamId = (m_uiLastStreamId + 1); + m_uiLastStreamId = (m_uiLastStreamId == NB_MAX_STREAMS+1) ? 1 : m_uiLastStreamId; + stream = new CStream(m_uiLastStreamId, Callsign, Ip, CodecIn, CodecOut); + if ( stream->Init(TRANSCODER_PORT+m_uiLastStreamId) ) + { + std::cout << "Opened stream " << m_uiLastStreamId << std::endl; + // and store it + Lock(); + m_Streams.push_back(stream); + Unlock(); + } + else + { + delete stream; + stream = NULL; + } + + // done + return stream; } void CController::CloseStream(uint16 StreamId) { - Lock(); - // look for the stream + Lock(); + // look for the stream for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ ) { // compare object pointers @@ -231,7 +232,7 @@ void CController::CloseStream(uint16 StreamId) break; } } - Unlock(); + Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -239,48 +240,48 @@ void CController::CloseStream(uint16 StreamId) bool CController::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *Callsign) { - uint8 tag[] = { 'A','M','B','E','D','P','I','N','G' }; - - bool valid = false; - if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - // get callsign here - Callsign->SetCallsign(&(Buffer.data()[9]), 8); - valid = Callsign->IsValid(); - } - return valid; + uint8 tag[] = { 'A','M','B','E','D','P','I','N','G' }; + + bool valid = false; + if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + // get callsign here + Callsign->SetCallsign(&(Buffer.data()[9]), 8); + valid = Callsign->IsValid(); + } + return valid; } bool CController::IsValidOpenstreamPacket(const CBuffer &Buffer, CCallsign *Callsign, uint8 *CodecIn, uint8 *CodecOut) { - uint8 tag[] = { 'A','M','B','E','D','O','S' }; - - bool valid = false; - if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - // get callsign here - Callsign->SetCallsign(&(Buffer.data()[7]), 8); - *CodecIn = Buffer.data()[15]; - *CodecOut = Buffer.data()[16]; - - // valid ? - valid = Callsign->IsValid() && IsValidCodecIn(*CodecIn) && IsValidCodecOut(*CodecOut); - } - return valid; + uint8 tag[] = { 'A','M','B','E','D','O','S' }; + + bool valid = false; + if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + // get callsign here + Callsign->SetCallsign(&(Buffer.data()[7]), 8); + *CodecIn = Buffer.data()[15]; + *CodecOut = Buffer.data()[16]; + + // valid ? + valid = Callsign->IsValid() && IsValidCodecIn(*CodecIn) && IsValidCodecOut(*CodecOut); + } + return valid; } bool CController::IsValidClosestreamPacket(const CBuffer &Buffer, uint16 *StreamId) { - uint8 tag[] = { 'A','M','B','E','D','C','S' }; - - bool valid = false; - if ( /*(Buffer.size() == 16) &&*/ (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - // get stream id - *StreamId = *(uint16 *)(&Buffer.data()[7]); - valid = true; - } - return valid; + uint8 tag[] = { 'A','M','B','E','D','C','S' }; + + bool valid = false; + if ( /*(Buffer.size() == 16) &&*/ (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + // get stream id + *StreamId = *(uint16 *)(&Buffer.data()[7]); + valid = true; + } + return valid; } //////////////////////////////////////////////////////////////////////////////////////// @@ -288,31 +289,31 @@ bool CController::IsValidClosestreamPacket(const CBuffer &Buffer, uint16 *Stream void CController::EncodeKeepAlivePacket(CBuffer *Buffer) { - uint8 tag[] = { 'A','M','B','E','D','P','O','N','G' }; + uint8 tag[] = { 'A','M','B','E','D','P','O','N','G' }; - Buffer->Set(tag, sizeof(tag)); + Buffer->Set(tag, sizeof(tag)); } void CController::EncodeStreamDescrPacket(CBuffer *Buffer, const CStream &Stream) { - uint8 tag[] = { 'A','M','B','E','D','S','T','D' }; - - Buffer->Set(tag, sizeof(tag)); - // id - Buffer->Append((uint16)Stream.GetId()); - // port - Buffer->Append((uint16)Stream.GetPort()); - // codecin - Buffer->Append((uint8)Stream.GetCodecIn()); - // codecout - Buffer->Append((uint8)Stream.GetCodecOut()); + uint8 tag[] = { 'A','M','B','E','D','S','T','D' }; + + Buffer->Set(tag, sizeof(tag)); + // id + Buffer->Append((uint16)Stream.GetId()); + // port + Buffer->Append((uint16)Stream.GetPort()); + // codecin + Buffer->Append((uint8)Stream.GetCodecIn()); + // codecout + Buffer->Append((uint8)Stream.GetCodecOut()); } void CController::EncodeNoStreamAvailablePacket(CBuffer *Buffer) { - uint8 tag[] = { 'A','M','B','E','D','B','U','S','Y' }; + uint8 tag[] = { 'A','M','B','E','D','B','U','S','Y' }; - Buffer->Set(tag, sizeof(tag)); + Buffer->Set(tag, sizeof(tag)); } @@ -321,10 +322,10 @@ void CController::EncodeNoStreamAvailablePacket(CBuffer *Buffer) bool CController::IsValidCodecIn(uint8 codec) { - return ((codec == CODEC_AMBEPLUS) || (codec == CODEC_AMBE2PLUS) ); + return ((codec == CODEC_AMBEPLUS) || (codec == CODEC_AMBE2PLUS) ); } bool CController::IsValidCodecOut(uint8 codec) { - return ((codec == CODEC_AMBEPLUS) || (codec == CODEC_AMBE2PLUS) ); + return ((codec == CODEC_AMBEPLUS) || (codec == CODEC_AMBE2PLUS) ); } diff --git a/ambed/ccontroller.h b/ambed/ccontroller.h index cbbfd85..f4c9c90 100644 --- a/ambed/ccontroller.h +++ b/ambed/ccontroller.h @@ -35,61 +35,61 @@ class CController { public: - // constructors - CController(); + // constructors + CController(); - // destructor - virtual ~CController(); + // destructor + virtual ~CController(); - // initialization - bool Init(void); - void Close(void); + // initialization + bool Init(void); + void Close(void); - // locks - void Lock(void) { m_Mutex.lock(); } - void Unlock(void) { m_Mutex.unlock(); } + // locks + void Lock(void) { m_Mutex.lock(); } + void Unlock(void) { m_Mutex.unlock(); } - // get - const char *GetListenIp(void) const { return m_addr; } + // get + const char *GetListenIp(void) const { return m_addr; } - // set - void SetListenIp(const char *str) { memset(m_addr, 0, INET6_ADDRSTRLEN); strncpy(m_addr, str, INET6_ADDRSTRLEN-1); } + // set + void SetListenIp(const char *str) { memset(m_addr, 0, INET6_ADDRSTRLEN); strncpy(m_addr, str, INET6_ADDRSTRLEN-1); } - // task - static void Thread(CController *); - void Task(void); + // task + static void Thread(CController *); + void Task(void); protected: - // streams management - CStream *OpenStream(const CCallsign &, const CIp &, uint8, uint8); - void CloseStream(uint16); + // streams management + CStream *OpenStream(const CCallsign &, const CIp &, uint8, uint8); + void CloseStream(uint16); - // packet decoding helpers - bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); - bool IsValidOpenstreamPacket(const CBuffer &, CCallsign *, uint8 *, uint8 *); - bool IsValidClosestreamPacket(const CBuffer &, uint16 *); + // packet decoding helpers + bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); + bool IsValidOpenstreamPacket(const CBuffer &, CCallsign *, uint8 *, uint8 *); + bool IsValidClosestreamPacket(const CBuffer &, uint16 *); - // packet encoding helpers - void EncodeKeepAlivePacket(CBuffer *); - void EncodeStreamDescrPacket(CBuffer *, const CStream &); - void EncodeNoStreamAvailablePacket(CBuffer *); + // packet encoding helpers + void EncodeKeepAlivePacket(CBuffer *); + void EncodeStreamDescrPacket(CBuffer *, const CStream &); + void EncodeNoStreamAvailablePacket(CBuffer *); - // codec helpers - bool IsValidCodecIn(uint8); - bool IsValidCodecOut(uint8); + // codec helpers + bool IsValidCodecIn(uint8); + bool IsValidCodecOut(uint8); - // control socket + // control socket char m_addr[INET6_ADDRSTRLEN]; - CUdpSocket m_Socket; + CUdpSocket m_Socket; - // streams - uint16 m_uiLastStreamId; - std::mutex m_Mutex; - std::list m_Streams; + // streams + uint16 m_uiLastStreamId; + std::mutex m_Mutex; + std::list m_Streams; - // thread - bool m_bStopThread; - std::thread *m_pThread; + // thread + bool m_bStopThread; + std::thread *m_pThread; }; diff --git a/ambed/cfirfilter.cpp b/ambed/cfirfilter.cpp index 67a0fb1..46b00c6 100644 --- a/ambed/cfirfilter.cpp +++ b/ambed/cfirfilter.cpp @@ -28,48 +28,48 @@ CFIRFilter::CFIRFilter(const float* taps, int tapsLength) { - m_taps = new float[tapsLength]; - m_buffer = new float[tapsLength]; - m_tapsLength = tapsLength; + m_taps = new float[tapsLength]; + m_buffer = new float[tapsLength]; + m_tapsLength = tapsLength; - ::memcpy(m_taps, taps, tapsLength * sizeof(float)); - ::memset(m_buffer, 0, tapsLength * sizeof(float)); - m_currentBufferPosition = 0; + ::memcpy(m_taps, taps, tapsLength * sizeof(float)); + ::memset(m_buffer, 0, tapsLength * sizeof(float)); + m_currentBufferPosition = 0; } CFIRFilter::~CFIRFilter() { - delete[] m_taps; - delete[] m_buffer; + delete[] m_taps; + delete[] m_buffer; } inline void CFIRFilter::ProcessSampleBlock(uint8* voice, int length) { - for(int i = 0; i < length; i += 2) - { - float input = (float)(short)MAKEWORD(voice[i+1], voice[i]); - float output = 0.0f; - int iTaps = 0; + for(int i = 0; i < length; i += 2) + { + float input = (float)(short)MAKEWORD(voice[i+1], voice[i]); + float output = 0.0f; + int iTaps = 0; - // Buffer latest sample into delay line - m_buffer[m_currentBufferPosition] = input; + // Buffer latest sample into delay line + m_buffer[m_currentBufferPosition] = input; - for(int i = m_currentBufferPosition; i >= 0; i--) - { - output += m_taps[iTaps++] * m_buffer[i]; - } + for(int i = m_currentBufferPosition; i >= 0; i--) + { + output += m_taps[iTaps++] * m_buffer[i]; + } - for(int i = m_tapsLength - 1; i > m_currentBufferPosition; i--) - { - output += m_taps[iTaps++] * m_buffer[i]; - } - - m_currentBufferPosition = (m_currentBufferPosition + 1) % m_tapsLength; + for(int i = m_tapsLength - 1; i > m_currentBufferPosition; i--) + { + output += m_taps[iTaps++] * m_buffer[i]; + } - //write processed sample back - voice[i] = HIBYTE((short)output); - voice[i+1] = LOBYTE((short)output); - } + m_currentBufferPosition = (m_currentBufferPosition + 1) % m_tapsLength; + + //write processed sample back + voice[i] = HIBYTE((short)output); + voice[i+1] = LOBYTE((short)output); + } } diff --git a/ambed/cfirfilter.h b/ambed/cfirfilter.h index 32b9c8d..a0ac0c2 100644 --- a/ambed/cfirfilter.h +++ b/ambed/cfirfilter.h @@ -31,20 +31,20 @@ class CFIRFilter : CSampleBlockProcessor { public : - //Constructor - CFIRFilter(const float* taps, int tapsLength); + //Constructor + CFIRFilter(const float* taps, int tapsLength); - // Destructor - ~CFIRFilter(); + // Destructor + ~CFIRFilter(); - // Processing - void ProcessSampleBlock(uint8* voice, int length); + // Processing + void ProcessSampleBlock(uint8* voice, int length); private: - float* m_taps; - int m_tapsLength; - float* m_buffer; - int m_currentBufferPosition; + float* m_taps; + int m_tapsLength; + float* m_buffer; + int m_currentBufferPosition; }; #endif //cfirfilter_h diff --git a/ambed/cfixedgain.cpp b/ambed/cfixedgain.cpp index 600df13..35ea877 100644 --- a/ambed/cfixedgain.cpp +++ b/ambed/cfixedgain.cpp @@ -31,23 +31,23 @@ CFixedGain::CFixedGain(float gaindB) { - m_gaindB = gaindB; - m_gainLinear = pow(10.0f, m_gaindB/20.0f); + m_gaindB = gaindB; + m_gainLinear = pow(10.0f, m_gaindB/20.0f); } //////////////////////////////////////////////////////////////////////////////////////// // processing - + inline void CFixedGain::ProcessSampleBlock(uint8* voice, int length) { - for(int i = 0; i < length; i += 2) - { - float input = (float)(short)MAKEWORD(voice[i+1], voice[i]); - //apply gain - float output = input * m_gainLinear; + for(int i = 0; i < length; i += 2) + { + float input = (float)(short)MAKEWORD(voice[i+1], voice[i]); + //apply gain + float output = input * m_gainLinear; - //write processed sample back - voice[i] = HIBYTE((short)output); - voice[i+1] = LOBYTE((short)output); - } + //write processed sample back + voice[i] = HIBYTE((short)output); + voice[i+1] = LOBYTE((short)output); + } } \ No newline at end of file diff --git a/ambed/cfixedgain.h b/ambed/cfixedgain.h index eadac47..7951694 100644 --- a/ambed/cfixedgain.h +++ b/ambed/cfixedgain.h @@ -31,15 +31,15 @@ class CFixedGain : CSampleBlockProcessor { public: - //Constructor - CFixedGain(float gaindB); + //Constructor + CFixedGain(float gaindB); - //processing - void ProcessSampleBlock(uint8* voice, int length); + //processing + void ProcessSampleBlock(uint8* voice, int length); private: - float m_gaindB; //gain in dB - float m_gainLinear; //linearized gain + float m_gaindB; //gain in dB + float m_gainLinear; //linearized gain }; #endif /* cfixedgain_h */ \ No newline at end of file diff --git a/ambed/cftdidevicedescr.cpp b/ambed/cftdidevicedescr.cpp index e17f4e8..a9174ef 100644 --- a/ambed/cftdidevicedescr.cpp +++ b/ambed/cftdidevicedescr.cpp @@ -36,29 +36,29 @@ CFtdiDeviceDescr::CFtdiDeviceDescr(void) { - m_bUsed = false; - m_uiVid = 0; - m_uiPid = 0; - ::memset(m_szDescription, 0, sizeof(m_szDescription)); - ::memset(m_szSerial, 0, sizeof(m_szSerial)); + m_bUsed = false; + m_uiVid = 0; + m_uiPid = 0; + ::memset(m_szDescription, 0, sizeof(m_szDescription)); + ::memset(m_szSerial, 0, sizeof(m_szSerial)); } CFtdiDeviceDescr::CFtdiDeviceDescr(uint32 uiVid, uint32 uiPid, const char *szDescription, const char *szSerial) { - m_bUsed = false; - m_uiVid = uiVid; - m_uiPid = uiPid; - ::strcpy(m_szDescription, szDescription); - ::strcpy(m_szSerial, szSerial); + m_bUsed = false; + m_uiVid = uiVid; + m_uiPid = uiPid; + ::strcpy(m_szDescription, szDescription); + ::strcpy(m_szSerial, szSerial); } CFtdiDeviceDescr::CFtdiDeviceDescr(const CFtdiDeviceDescr &descr) { - m_bUsed = descr.m_bUsed; - m_uiVid = descr.m_uiVid; - m_uiPid = descr.m_uiPid; - ::memcpy(m_szDescription, descr.m_szDescription, sizeof(m_szDescription)); - ::memcpy(m_szSerial, descr.m_szSerial, sizeof(m_szSerial)); + m_bUsed = descr.m_bUsed; + m_uiVid = descr.m_uiVid; + m_uiPid = descr.m_uiPid; + ::memcpy(m_szDescription, descr.m_szDescription, sizeof(m_szDescription)); + ::memcpy(m_szSerial, descr.m_szSerial, sizeof(m_szSerial)); } //////////////////////////////////////////////////////////////////////////////////////// @@ -66,67 +66,67 @@ CFtdiDeviceDescr::CFtdiDeviceDescr(const CFtdiDeviceDescr &descr) int CFtdiDeviceDescr::CreateInterface(CFtdiDeviceDescr *descr, std::vector*channels) { - int iNbChs = 0; - - // single channel devices cannot be created alone - // three channels devices - if ( (::strcmp(descr->GetDescription(), "USB-3003") == 0) || // DVSI's USB-3003 - (::strcmp(descr->GetDescription(), "DF2ET-3003") == 0) || // DF2ET's USB-3003 opensource device - (::strcmp(descr->GetDescription(), "DVstick-33") == 0) || // DVMEGA USB-3003 device - (::strcmp(descr->GetDescription(), "ThumbDV-3") == 0) ) // ThumbDV-3 - { - iNbChs = CreateUsb3003(descr, channels); - } - // six channels devices - else if ( (::strcmp(descr->GetDescription(), "USB-3006 A") == 0) ) // LX3JL's USB-3006 opensource device - { - iNbChs = CreateUsb3006(descr, channels); - } - // twelves channels devices - else if ( (::strcmp(descr->GetDescription(), "USB-3012 A") == 0) ) // DVSI's USB-3012 - { - iNbChs = CreateUsb3012(descr, channels); - } - // done - return iNbChs; + int iNbChs = 0; + + // single channel devices cannot be created alone + // three channels devices + if ( (::strcmp(descr->GetDescription(), "USB-3003") == 0) || // DVSI's USB-3003 + (::strcmp(descr->GetDescription(), "DF2ET-3003") == 0) || // DF2ET's USB-3003 opensource device + (::strcmp(descr->GetDescription(), "DVstick-33") == 0) || // DVMEGA USB-3003 device + (::strcmp(descr->GetDescription(), "ThumbDV-3") == 0) ) // ThumbDV-3 + { + iNbChs = CreateUsb3003(descr, channels); + } + // six channels devices + else if ( (::strcmp(descr->GetDescription(), "USB-3006 A") == 0) ) // LX3JL's USB-3006 opensource device + { + iNbChs = CreateUsb3006(descr, channels); + } + // twelves channels devices + else if ( (::strcmp(descr->GetDescription(), "USB-3012 A") == 0) ) // DVSI's USB-3012 + { + iNbChs = CreateUsb3012(descr, channels); + } + // done + return iNbChs; } int CFtdiDeviceDescr::CreateInterfacePair(CFtdiDeviceDescr *descr1, CFtdiDeviceDescr *descr2, std::vector*channels) { - int iNbChs = 0; - - // create interface objects - if ( (descr1->GetNbChannels() == 1) && (descr2->GetNbChannels() == 1) ) - { - // create 3000-3000 pair - CUsb3000Interface *Usb3000A = InstantiateUsb3000(descr1); - CUsb3000Interface *Usb3000B = InstantiateUsb3000(descr2); - iNbChs = CreatePair(Usb3000A, Usb3000B, channels); - } - else if ( (descr1->GetNbChannels() == 3) && (descr2->GetNbChannels() == 1) ) - { - // create 3003-3000 pair - CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr1); - CUsb3000Interface *Usb3000 = InstantiateUsb3000(descr2); - iNbChs = CreatePair(Usb3003, Usb3000, channels); - } - else if ( (descr1->GetNbChannels() == 1) && (descr2->GetNbChannels() == 3) ) - { - // create 3000-3003 pair - CUsb3000Interface *Usb3000 = InstantiateUsb3000(descr1); - CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr2); - iNbChs = CreatePair(Usb3003, Usb3000, channels); - } - else if ( (descr1->GetNbChannels() == 3) && (descr2->GetNbChannels() == 3) ) - { - // create 3003-3003 pair - CUsb3003Interface *Usb3003A = InstantiateUsb3003(descr1); - CUsb3003Interface *Usb3003B = InstantiateUsb3003(descr2); - iNbChs = CreatePair(Usb3003A, Usb3003B, channels); - } - - // done - return iNbChs; + int iNbChs = 0; + + // create interface objects + if ( (descr1->GetNbChannels() == 1) && (descr2->GetNbChannels() == 1) ) + { + // create 3000-3000 pair + CUsb3000Interface *Usb3000A = InstantiateUsb3000(descr1); + CUsb3000Interface *Usb3000B = InstantiateUsb3000(descr2); + iNbChs = CreatePair(Usb3000A, Usb3000B, channels); + } + else if ( (descr1->GetNbChannels() == 3) && (descr2->GetNbChannels() == 1) ) + { + // create 3003-3000 pair + CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr1); + CUsb3000Interface *Usb3000 = InstantiateUsb3000(descr2); + iNbChs = CreatePair(Usb3003, Usb3000, channels); + } + else if ( (descr1->GetNbChannels() == 1) && (descr2->GetNbChannels() == 3) ) + { + // create 3000-3003 pair + CUsb3000Interface *Usb3000 = InstantiateUsb3000(descr1); + CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr2); + iNbChs = CreatePair(Usb3003, Usb3000, channels); + } + else if ( (descr1->GetNbChannels() == 3) && (descr2->GetNbChannels() == 3) ) + { + // create 3003-3003 pair + CUsb3003Interface *Usb3003A = InstantiateUsb3003(descr1); + CUsb3003Interface *Usb3003B = InstantiateUsb3003(descr2); + iNbChs = CreatePair(Usb3003A, Usb3003B, channels); + } + + // done + return iNbChs; } //////////////////////////////////////////////////////////////////////////////////////// @@ -134,63 +134,63 @@ int CFtdiDeviceDescr::CreateInterfacePair(CFtdiDeviceDescr *descr1, CFtdiDeviceD const char * CFtdiDeviceDescr::GetChannelDescription(int ch) const { - static char descr[FTDI_MAX_STRINGLENGTH]; - char tag[3] = "_X"; - - ::strcpy(descr, GetDescription()); - if ( ::strlen(descr) >= 2 ) - { - descr[::strlen(descr)-2] = 0x00; - tag[1] = (char)ch + 'A'; - ::strcat(descr, tag); - } - return descr; + static char descr[FTDI_MAX_STRINGLENGTH]; + char tag[3] = "_X"; + + ::strcpy(descr, GetDescription()); + if ( ::strlen(descr) >= 2 ) + { + descr[::strlen(descr)-2] = 0x00; + tag[1] = (char)ch + 'A'; + ::strcat(descr, tag); + } + return descr; } const char * CFtdiDeviceDescr::GetChannelSerialNumber(int ch) const { - static char serial[FTDI_MAX_STRINGLENGTH]; - - ::strcpy(serial, GetSerialNumber()); - if ( ::strlen(serial) >= 1 ) - { - serial[::strlen(serial)-1] = (char)ch + 'A'; - } - return serial; + static char serial[FTDI_MAX_STRINGLENGTH]; + + ::strcpy(serial, GetSerialNumber()); + if ( ::strlen(serial) >= 1 ) + { + serial[::strlen(serial)-1] = (char)ch + 'A'; + } + return serial; } int CFtdiDeviceDescr::GetNbChannels(void) const { - int iNbChs = 0; - - // single channel devices - if ( (::strcmp(m_szDescription, "USB-3000") == 0) || // DVSI's USB-3000 - (::strcmp(m_szDescription, "DVstick-30") == 0) || // DVMEGA AMBE3000 device - (::strcmp(m_szDescription, "ThumbDV") == 0) ) // ThumbDV - { - iNbChs = 1; - } - // three channels devices - else if ( (::strcmp(m_szDescription, "USB-3003") == 0) || // DVSI's USB-3003 - (::strcmp(m_szDescription, "DF2ET-3003") == 0) || // DF2ET's USB-3003 opensource device - (::strcmp(m_szDescription, "DVstick-33") == 0) || // DVMEGA AMBE 3003 device - (::strcmp(m_szDescription, "ThumbDV-3") == 0) ) // ThumbDV-3 - { - iNbChs = 3; - } - // six channels devices - else if ( (::strcmp(m_szDescription, "USB-3006 A") == 0) ) // LX3JL's USB-3006 opensource device - { - iNbChs = 6; - } - // twelves channels devices - else if ( (::strcmp(m_szDescription, "USB-3012 A") == 0) ) // DVSI's USB-3012 - { - iNbChs = 12; - } - - // done - return iNbChs; + int iNbChs = 0; + + // single channel devices + if ( (::strcmp(m_szDescription, "USB-3000") == 0) || // DVSI's USB-3000 + (::strcmp(m_szDescription, "DVstick-30") == 0) || // DVMEGA AMBE3000 device + (::strcmp(m_szDescription, "ThumbDV") == 0) ) // ThumbDV + { + iNbChs = 1; + } + // three channels devices + else if ( (::strcmp(m_szDescription, "USB-3003") == 0) || // DVSI's USB-3003 + (::strcmp(m_szDescription, "DF2ET-3003") == 0) || // DF2ET's USB-3003 opensource device + (::strcmp(m_szDescription, "DVstick-33") == 0) || // DVMEGA AMBE 3003 device + (::strcmp(m_szDescription, "ThumbDV-3") == 0) ) // ThumbDV-3 + { + iNbChs = 3; + } + // six channels devices + else if ( (::strcmp(m_szDescription, "USB-3006 A") == 0) ) // LX3JL's USB-3006 opensource device + { + iNbChs = 6; + } + // twelves channels devices + else if ( (::strcmp(m_szDescription, "USB-3012 A") == 0) ) // DVSI's USB-3012 + { + iNbChs = 12; + } + + // done + return iNbChs; } //////////////////////////////////////////////////////////////////////////////////////// @@ -203,92 +203,92 @@ int CFtdiDeviceDescr::GetNbChannels(void) const int CFtdiDeviceDescr::CreateUsb3012(CFtdiDeviceDescr *descr, std::vector*channels) { - int nStreams = 0; - - // create the interfaces for the four 3003 chips - CUsb3003HRInterface *Usb3003A = - new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(0), descr->GetChannelSerialNumber(0)); - CUsb3003HRInterface *Usb3003B = - new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(1), descr->GetChannelSerialNumber(1)); - CUsb3003HRInterface *Usb3003C = - new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(2), descr->GetChannelSerialNumber(2)); - CUsb3003HRInterface *Usb3003D = - new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(3), descr->GetChannelSerialNumber(3)); - - // init the interfaces - if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) && - Usb3003C->Init(CODEC_AMBEPLUS) && Usb3003D->Init(CODEC_AMBE2PLUS) ) - { - CVocodecChannel *Channel; - // create all channels - { - // ch1 - Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS); - channels->push_back(Channel); - Usb3003A->AddChannel(Channel); - // ch2 - Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS); - channels->push_back(Channel); - Usb3003A->AddChannel(Channel); - // ch3 - Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS); - channels->push_back(Channel); - Usb3003B->AddChannel(Channel); - // ch4 - Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS); - channels->push_back(Channel); - Usb3003B->AddChannel(Channel); - // ch5 - Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS); - channels->push_back(Channel); - Usb3003A->AddChannel(Channel); - Usb3003B->AddChannel(Channel); - // ch6 - Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS); - channels->push_back(Channel); - Usb3003A->AddChannel(Channel); - Usb3003B->AddChannel(Channel); - // ch7 - Channel = new CVocodecChannel(Usb3003C, 0, Usb3003C, 1, CODECGAIN_AMBEPLUS); - channels->push_back(Channel); - Usb3003C->AddChannel(Channel); - // ch8 - Channel = new CVocodecChannel(Usb3003C, 1, Usb3003C, 0, CODECGAIN_AMBE2PLUS); - channels->push_back(Channel); - Usb3003C->AddChannel(Channel); - // ch9 - Channel = new CVocodecChannel(Usb3003D, 0, Usb3003D, 1, CODECGAIN_AMBEPLUS); - channels->push_back(Channel); - Usb3003D->AddChannel(Channel); - // ch10 - Channel = new CVocodecChannel(Usb3003D, 1, Usb3003D, 0, CODECGAIN_AMBE2PLUS); - channels->push_back(Channel); - Usb3003D->AddChannel(Channel); - // ch11 - Channel = new CVocodecChannel(Usb3003C, 2, Usb3003D, 2, CODECGAIN_AMBEPLUS); - channels->push_back(Channel); - Usb3003C->AddChannel(Channel); - Usb3003D->AddChannel(Channel); - // ch12 - Channel = new CVocodecChannel(Usb3003D, 2, Usb3003C, 2, CODECGAIN_AMBE2PLUS); - channels->push_back(Channel); - Usb3003C->AddChannel(Channel); - Usb3003D->AddChannel(Channel); - //done - nStreams = 12; - } - } - else - { - // cleanup - delete Usb3003A; - delete Usb3003B; - delete Usb3003C; - delete Usb3003D; - } - - // done - return nStreams; + int nStreams = 0; + + // create the interfaces for the four 3003 chips + CUsb3003HRInterface *Usb3003A = + new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(0), descr->GetChannelSerialNumber(0)); + CUsb3003HRInterface *Usb3003B = + new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(1), descr->GetChannelSerialNumber(1)); + CUsb3003HRInterface *Usb3003C = + new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(2), descr->GetChannelSerialNumber(2)); + CUsb3003HRInterface *Usb3003D = + new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(3), descr->GetChannelSerialNumber(3)); + + // init the interfaces + if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) && + Usb3003C->Init(CODEC_AMBEPLUS) && Usb3003D->Init(CODEC_AMBE2PLUS) ) + { + CVocodecChannel *Channel; + // create all channels + { + // ch1 + Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS); + channels->push_back(Channel); + Usb3003A->AddChannel(Channel); + // ch2 + Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS); + channels->push_back(Channel); + Usb3003A->AddChannel(Channel); + // ch3 + Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS); + channels->push_back(Channel); + Usb3003B->AddChannel(Channel); + // ch4 + Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS); + channels->push_back(Channel); + Usb3003B->AddChannel(Channel); + // ch5 + Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS); + channels->push_back(Channel); + Usb3003A->AddChannel(Channel); + Usb3003B->AddChannel(Channel); + // ch6 + Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS); + channels->push_back(Channel); + Usb3003A->AddChannel(Channel); + Usb3003B->AddChannel(Channel); + // ch7 + Channel = new CVocodecChannel(Usb3003C, 0, Usb3003C, 1, CODECGAIN_AMBEPLUS); + channels->push_back(Channel); + Usb3003C->AddChannel(Channel); + // ch8 + Channel = new CVocodecChannel(Usb3003C, 1, Usb3003C, 0, CODECGAIN_AMBE2PLUS); + channels->push_back(Channel); + Usb3003C->AddChannel(Channel); + // ch9 + Channel = new CVocodecChannel(Usb3003D, 0, Usb3003D, 1, CODECGAIN_AMBEPLUS); + channels->push_back(Channel); + Usb3003D->AddChannel(Channel); + // ch10 + Channel = new CVocodecChannel(Usb3003D, 1, Usb3003D, 0, CODECGAIN_AMBE2PLUS); + channels->push_back(Channel); + Usb3003D->AddChannel(Channel); + // ch11 + Channel = new CVocodecChannel(Usb3003C, 2, Usb3003D, 2, CODECGAIN_AMBEPLUS); + channels->push_back(Channel); + Usb3003C->AddChannel(Channel); + Usb3003D->AddChannel(Channel); + // ch12 + Channel = new CVocodecChannel(Usb3003D, 2, Usb3003C, 2, CODECGAIN_AMBE2PLUS); + channels->push_back(Channel); + Usb3003C->AddChannel(Channel); + Usb3003D->AddChannel(Channel); + //done + nStreams = 12; + } + } + else + { + // cleanup + delete Usb3003A; + delete Usb3003B; + delete Usb3003C; + delete Usb3003D; + } + + // done + return nStreams; } //////////////////////////////////////////////////////////////////////////////////////// @@ -300,59 +300,59 @@ int CFtdiDeviceDescr::CreateUsb3012(CFtdiDeviceDescr *descr, std::vector*channels) { - int nStreams = 0; - - // create the interfaces for the two 3003 chips - CUsb3003Interface *Usb3003A = - new CUsb3003Interface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(0), descr->GetChannelSerialNumber(0)); - CUsb3003Interface *Usb3003B = - new CUsb3003Interface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(1), descr->GetChannelSerialNumber(1)); - - // init the interfaces - if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) ) - { - CVocodecChannel *Channel; - // create all channels - { - // ch1 - Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS); - channels->push_back(Channel); - Usb3003A->AddChannel(Channel); - // ch2 - Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS); - channels->push_back(Channel); - Usb3003A->AddChannel(Channel); - // ch3 - Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS); - channels->push_back(Channel); - Usb3003B->AddChannel(Channel); - // ch4 - Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS); - channels->push_back(Channel); - Usb3003B->AddChannel(Channel); - // ch5 - Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS); - channels->push_back(Channel); - Usb3003A->AddChannel(Channel); - Usb3003B->AddChannel(Channel); - // ch6 - Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS); - channels->push_back(Channel); - Usb3003A->AddChannel(Channel); - Usb3003B->AddChannel(Channel); - //done - nStreams = 6; - } - } - else - { - // cleanup - delete Usb3003A; - delete Usb3003B; - } - - // done - return nStreams; + int nStreams = 0; + + // create the interfaces for the two 3003 chips + CUsb3003Interface *Usb3003A = + new CUsb3003Interface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(0), descr->GetChannelSerialNumber(0)); + CUsb3003Interface *Usb3003B = + new CUsb3003Interface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(1), descr->GetChannelSerialNumber(1)); + + // init the interfaces + if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) ) + { + CVocodecChannel *Channel; + // create all channels + { + // ch1 + Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS); + channels->push_back(Channel); + Usb3003A->AddChannel(Channel); + // ch2 + Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS); + channels->push_back(Channel); + Usb3003A->AddChannel(Channel); + // ch3 + Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS); + channels->push_back(Channel); + Usb3003B->AddChannel(Channel); + // ch4 + Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS); + channels->push_back(Channel); + Usb3003B->AddChannel(Channel); + // ch5 + Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS); + channels->push_back(Channel); + Usb3003A->AddChannel(Channel); + Usb3003B->AddChannel(Channel); + // ch6 + Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS); + channels->push_back(Channel); + Usb3003A->AddChannel(Channel); + Usb3003B->AddChannel(Channel); + //done + nStreams = 6; + } + } + else + { + // cleanup + delete Usb3003A; + delete Usb3003B; + } + + // done + return nStreams; } //////////////////////////////////////////////////////////////////////////////////////// @@ -368,37 +368,37 @@ int CFtdiDeviceDescr::CreateUsb3006(CFtdiDeviceDescr *descr, std::vector*channels) { - int nStreams = 0; - - // create the interfaces for the 3003 chip - CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr); - - // init the interface - if ( (Usb3003 != NULL) && Usb3003->Init(CODEC_NONE) ) - { - CVocodecChannel *Channel; - // create all channels - { - // ch1 - Channel = new CVocodecChannel(Usb3003, 0, Usb3003, 1, CODECGAIN_AMBEPLUS); - channels->push_back(Channel); - Usb3003->AddChannel(Channel); - // ch2 - Channel = new CVocodecChannel(Usb3003, 1, Usb3003, 0, CODECGAIN_AMBE2PLUS); - channels->push_back(Channel); - Usb3003->AddChannel(Channel); - // done - nStreams = 2; - } - } - else - { - // cleanup - delete Usb3003; - } - - // done - return nStreams; + int nStreams = 0; + + // create the interfaces for the 3003 chip + CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr); + + // init the interface + if ( (Usb3003 != NULL) && Usb3003->Init(CODEC_NONE) ) + { + CVocodecChannel *Channel; + // create all channels + { + // ch1 + Channel = new CVocodecChannel(Usb3003, 0, Usb3003, 1, CODECGAIN_AMBEPLUS); + channels->push_back(Channel); + Usb3003->AddChannel(Channel); + // ch2 + Channel = new CVocodecChannel(Usb3003, 1, Usb3003, 0, CODECGAIN_AMBE2PLUS); + channels->push_back(Channel); + Usb3003->AddChannel(Channel); + // done + nStreams = 2; + } + } + else + { + // cleanup + delete Usb3003; + } + + // done + return nStreams; } @@ -407,38 +407,38 @@ int CFtdiDeviceDescr::CreateUsb3003(CFtdiDeviceDescr *descr, std::vector*channels) { - int nStreams = 0; - - // init the interfaces - if ( Usb3000A->Init(CODEC_AMBEPLUS) && Usb3000B->Init(CODEC_AMBE2PLUS) ) - { - CVocodecChannel *Channel; - // create all channels - { - // ch1 - Channel = new CVocodecChannel(Usb3000A, 0, Usb3000B, 0, CODECGAIN_AMBEPLUS); - channels->push_back(Channel); - Usb3000A->AddChannel(Channel); - Usb3000B->AddChannel(Channel); - // ch2 - Channel = new CVocodecChannel(Usb3000B, 0, Usb3000A, 0, CODECGAIN_AMBE2PLUS); - channels->push_back(Channel); - Usb3000A->AddChannel(Channel); - Usb3000B->AddChannel(Channel); - // done - nStreams = 2; - } - } - else - { - // cleanup - delete Usb3000A; - delete Usb3000B; - } - - // done - return nStreams; - + int nStreams = 0; + + // init the interfaces + if ( Usb3000A->Init(CODEC_AMBEPLUS) && Usb3000B->Init(CODEC_AMBE2PLUS) ) + { + CVocodecChannel *Channel; + // create all channels + { + // ch1 + Channel = new CVocodecChannel(Usb3000A, 0, Usb3000B, 0, CODECGAIN_AMBEPLUS); + channels->push_back(Channel); + Usb3000A->AddChannel(Channel); + Usb3000B->AddChannel(Channel); + // ch2 + Channel = new CVocodecChannel(Usb3000B, 0, Usb3000A, 0, CODECGAIN_AMBE2PLUS); + channels->push_back(Channel); + Usb3000A->AddChannel(Channel); + Usb3000B->AddChannel(Channel); + // done + nStreams = 2; + } + } + else + { + // cleanup + delete Usb3000A; + delete Usb3000B; + } + + // done + return nStreams; + } //////////////////////////////////////////////////////////////////////////////////////// @@ -446,53 +446,53 @@ int CFtdiDeviceDescr::CreatePair(CUsb3000Interface *Usb3000A, CUsb3000Interface int CFtdiDeviceDescr::CreatePair(CUsb3003Interface *Usb3003A, CUsb3003Interface *Usb3003B, std::vector*channels) { - int nStreams = 0; - - // init the interfaces - if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) ) - { - CVocodecChannel *Channel; - // create all channels - { - // ch1 - Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS); - channels->push_back(Channel); - Usb3003A->AddChannel(Channel); - // ch2 - Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS); - channels->push_back(Channel); - Usb3003A->AddChannel(Channel); - // ch3 - Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS); - channels->push_back(Channel); - Usb3003B->AddChannel(Channel); - // ch4 - Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS); - channels->push_back(Channel); - Usb3003B->AddChannel(Channel); - // ch5 - Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS); - channels->push_back(Channel); - Usb3003A->AddChannel(Channel); - Usb3003B->AddChannel(Channel); - // ch6 - Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS); - channels->push_back(Channel); - Usb3003A->AddChannel(Channel); - Usb3003B->AddChannel(Channel); - // done - nStreams = 6; - } - } - else - { - // cleanup - delete Usb3003A; - delete Usb3003B; - } - - // done - return nStreams; + int nStreams = 0; + + // init the interfaces + if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) ) + { + CVocodecChannel *Channel; + // create all channels + { + // ch1 + Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS); + channels->push_back(Channel); + Usb3003A->AddChannel(Channel); + // ch2 + Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS); + channels->push_back(Channel); + Usb3003A->AddChannel(Channel); + // ch3 + Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS); + channels->push_back(Channel); + Usb3003B->AddChannel(Channel); + // ch4 + Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS); + channels->push_back(Channel); + Usb3003B->AddChannel(Channel); + // ch5 + Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS); + channels->push_back(Channel); + Usb3003A->AddChannel(Channel); + Usb3003B->AddChannel(Channel); + // ch6 + Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS); + channels->push_back(Channel); + Usb3003A->AddChannel(Channel); + Usb3003B->AddChannel(Channel); + // done + nStreams = 6; + } + } + else + { + // cleanup + delete Usb3003A; + delete Usb3003B; + } + + // done + return nStreams; } //////////////////////////////////////////////////////////////////////////////////////// @@ -500,45 +500,45 @@ int CFtdiDeviceDescr::CreatePair(CUsb3003Interface *Usb3003A, CUsb3003Interface int CFtdiDeviceDescr::CreatePair(CUsb3003Interface *Usb3003A, CUsb3000Interface *Usb3000B, std::vector*channels) { - int nStreams = 0; - - // init the interfaces - if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3000B->Init(CODEC_AMBE2PLUS) ) - { - CVocodecChannel *Channel; - // create all channels - { - // ch1 - Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS); - channels->push_back(Channel); - Usb3003A->AddChannel(Channel); - // ch2 - Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS); - channels->push_back(Channel); - Usb3003A->AddChannel(Channel); - // ch3 - Channel = new CVocodecChannel(Usb3003A, 2, Usb3000B, 0, CODECGAIN_AMBEPLUS); - channels->push_back(Channel); - Usb3003A->AddChannel(Channel); - Usb3000B->AddChannel(Channel); - // ch4 - Channel = new CVocodecChannel(Usb3000B, 0, Usb3003A, 2, CODECGAIN_AMBE2PLUS); - channels->push_back(Channel); - Usb3003A->AddChannel(Channel); - Usb3000B->AddChannel(Channel); - // done - nStreams = 4; - } - } - else - { - // cleanup - delete Usb3003A; - delete Usb3000B; - } - - // done - return nStreams; + int nStreams = 0; + + // init the interfaces + if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3000B->Init(CODEC_AMBE2PLUS) ) + { + CVocodecChannel *Channel; + // create all channels + { + // ch1 + Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS); + channels->push_back(Channel); + Usb3003A->AddChannel(Channel); + // ch2 + Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS); + channels->push_back(Channel); + Usb3003A->AddChannel(Channel); + // ch3 + Channel = new CVocodecChannel(Usb3003A, 2, Usb3000B, 0, CODECGAIN_AMBEPLUS); + channels->push_back(Channel); + Usb3003A->AddChannel(Channel); + Usb3000B->AddChannel(Channel); + // ch4 + Channel = new CVocodecChannel(Usb3000B, 0, Usb3003A, 2, CODECGAIN_AMBE2PLUS); + channels->push_back(Channel); + Usb3003A->AddChannel(Channel); + Usb3000B->AddChannel(Channel); + // done + nStreams = 4; + } + } + else + { + // cleanup + delete Usb3003A; + delete Usb3000B; + } + + // done + return nStreams; } @@ -547,50 +547,50 @@ int CFtdiDeviceDescr::CreatePair(CUsb3003Interface *Usb3003A, CUsb3000Interface CUsb3003Interface *CFtdiDeviceDescr::InstantiateUsb3003(CFtdiDeviceDescr *descr) { - CUsb3003Interface *Usb3003 = NULL; - - // intstantiate the proper version of USB-3003 - if ( (::strcmp(descr->GetDescription(), "USB-3003") == 0) ) // DVSI's USB-3003 - { - // hardware reset, 921600 bps - Usb3003 = new CUsb3003HRInterface - (descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber()); - } - else if ( (::strcmp(descr->GetDescription(), "DF2ET-3003") == 0) ) // DF2ET's USB-3003 opensource device - { - // specific hardware reset, 921600 bps - Usb3003 = new CUsb3003DF2ETInterface - (descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber()); - } - else if ( (::strcmp(descr->GetDescription(), "ThumbDV-3") == 0) ) // ThumbDV-3 - { - // software reset, 921600 bps - Usb3003 = new CUsb3003Interface - (descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber()); - } - else if ( (::strcmp(descr->GetDescription(), "DVstick-33") == 0) ) // DVMEGA AMBE3003 device - { - // specific fardware reset, 921600 bps - Usb3003 = new CUsb3003DF2ETInterface - (descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber()); - } - - // done - return Usb3003; + CUsb3003Interface *Usb3003 = NULL; + + // intstantiate the proper version of USB-3003 + if ( (::strcmp(descr->GetDescription(), "USB-3003") == 0) ) // DVSI's USB-3003 + { + // hardware reset, 921600 bps + Usb3003 = new CUsb3003HRInterface + (descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber()); + } + else if ( (::strcmp(descr->GetDescription(), "DF2ET-3003") == 0) ) // DF2ET's USB-3003 opensource device + { + // specific hardware reset, 921600 bps + Usb3003 = new CUsb3003DF2ETInterface + (descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber()); + } + else if ( (::strcmp(descr->GetDescription(), "ThumbDV-3") == 0) ) // ThumbDV-3 + { + // software reset, 921600 bps + Usb3003 = new CUsb3003Interface + (descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber()); + } + else if ( (::strcmp(descr->GetDescription(), "DVstick-33") == 0) ) // DVMEGA AMBE3003 device + { + // specific fardware reset, 921600 bps + Usb3003 = new CUsb3003DF2ETInterface + (descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber()); + } + + // done + return Usb3003; } CUsb3000Interface *CFtdiDeviceDescr::InstantiateUsb3000(CFtdiDeviceDescr *descr) { - CUsb3000Interface *Usb3000 = NULL; - - // intstantiate the proper version of USB-3000 - if ( (::strcmp(descr->GetDescription(), "USB-3000") == 0) || // DVSI's USB-3000 - (::strcmp(descr->GetDescription(), "DVstick-30")== 0) || // DVMEGA AMBE3000 device - (::strcmp(descr->GetDescription(), "ThumbDV") == 0) ) // ThumbDV - { - Usb3000 = new CUsb3000Interface - (descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber()); - } - // done - return Usb3000; + CUsb3000Interface *Usb3000 = NULL; + + // intstantiate the proper version of USB-3000 + if ( (::strcmp(descr->GetDescription(), "USB-3000") == 0) || // DVSI's USB-3000 + (::strcmp(descr->GetDescription(), "DVstick-30")== 0) || // DVMEGA AMBE3000 device + (::strcmp(descr->GetDescription(), "ThumbDV") == 0) ) // ThumbDV + { + Usb3000 = new CUsb3000Interface + (descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber()); + } + // done + return Usb3000; } diff --git a/ambed/cftdidevicedescr.h b/ambed/cftdidevicedescr.h index 15fa362..31ef310 100644 --- a/ambed/cftdidevicedescr.h +++ b/ambed/cftdidevicedescr.h @@ -45,52 +45,52 @@ class CUsb3003Interface; class CFtdiDeviceDescr { public: - // constructors - CFtdiDeviceDescr(void); - CFtdiDeviceDescr(uint32, uint32, const char *, const char *); - CFtdiDeviceDescr(const CFtdiDeviceDescr &); - - // destructor - virtual ~CFtdiDeviceDescr() {} - - // interface factory - static int CreateInterface(CFtdiDeviceDescr *, std::vector*); - static int CreateInterfacePair(CFtdiDeviceDescr *, CFtdiDeviceDescr *, std::vector*); - - // get - bool IsUsed(void) const { return m_bUsed; } - int GetNbChannels(void) const; - uint32 GetVid(void) const { return m_uiVid; } - uint32 GetPid(void) const { return m_uiPid; } - const char *GetDescription(void) const { return m_szDescription; } - const char *GetSerialNumber(void) const { return m_szSerial; } - const char * GetChannelDescription(int) const; - const char * GetChannelSerialNumber(int) const; - - - // set - void SetUsed(bool used) { m_bUsed = used; } + // constructors + CFtdiDeviceDescr(void); + CFtdiDeviceDescr(uint32, uint32, const char *, const char *); + CFtdiDeviceDescr(const CFtdiDeviceDescr &); + + // destructor + virtual ~CFtdiDeviceDescr() {} + + // interface factory + static int CreateInterface(CFtdiDeviceDescr *, std::vector*); + static int CreateInterfacePair(CFtdiDeviceDescr *, CFtdiDeviceDescr *, std::vector*); + + // get + bool IsUsed(void) const { return m_bUsed; } + int GetNbChannels(void) const; + uint32 GetVid(void) const { return m_uiVid; } + uint32 GetPid(void) const { return m_uiPid; } + const char *GetDescription(void) const { return m_szDescription; } + const char *GetSerialNumber(void) const { return m_szSerial; } + const char * GetChannelDescription(int) const; + const char * GetChannelSerialNumber(int) const; + + + // set + void SetUsed(bool used) { m_bUsed = used; } protected: - // factory helper - static int CreateUsb3012(CFtdiDeviceDescr *, std::vector*); - static int CreateUsb3006(CFtdiDeviceDescr *, std::vector*); - static int CreateUsb3003(CFtdiDeviceDescr *, std::vector*); - static int CreatePair(CUsb3003Interface *, CUsb3003Interface *, std::vector*); - static int CreatePair(CUsb3003Interface *, CUsb3000Interface *, std::vector*); - static int CreatePair(CUsb3000Interface *, CUsb3000Interface *, std::vector*); - static CUsb3003Interface *InstantiateUsb3003(CFtdiDeviceDescr *); - static CUsb3000Interface *InstantiateUsb3000(CFtdiDeviceDescr *); - + // factory helper + static int CreateUsb3012(CFtdiDeviceDescr *, std::vector*); + static int CreateUsb3006(CFtdiDeviceDescr *, std::vector*); + static int CreateUsb3003(CFtdiDeviceDescr *, std::vector*); + static int CreatePair(CUsb3003Interface *, CUsb3003Interface *, std::vector*); + static int CreatePair(CUsb3003Interface *, CUsb3000Interface *, std::vector*); + static int CreatePair(CUsb3000Interface *, CUsb3000Interface *, std::vector*); + static CUsb3003Interface *InstantiateUsb3003(CFtdiDeviceDescr *); + static CUsb3000Interface *InstantiateUsb3000(CFtdiDeviceDescr *); + protected: - // status - bool m_bUsed; - - // data - uint32 m_uiVid; - uint32 m_uiPid; - char m_szDescription[FTDI_MAX_STRINGLENGTH]; - char m_szSerial[FTDI_MAX_STRINGLENGTH]; + // status + bool m_bUsed; + + // data + uint32 m_uiVid; + uint32 m_uiPid; + char m_szDescription[FTDI_MAX_STRINGLENGTH]; + char m_szSerial[FTDI_MAX_STRINGLENGTH]; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/ambed/cpacket.cpp b/ambed/cpacket.cpp index a661984..735ed32 100644 --- a/ambed/cpacket.cpp +++ b/ambed/cpacket.cpp @@ -31,19 +31,19 @@ CPacket::CPacket() { - m_iCh = 0; - m_uiPid = 0; + m_iCh = 0; + m_uiPid = 0; }; CPacket::CPacket(uint8 uiPid) { - m_iCh = 0; - m_uiPid = uiPid; + m_iCh = 0; + m_uiPid = uiPid; } CPacket::CPacket(const CPacket &packet) { - m_iCh = packet.m_iCh; - m_uiPid = packet.m_uiPid; + m_iCh = packet.m_iCh; + m_uiPid = packet.m_uiPid; }; diff --git a/ambed/cpacket.h b/ambed/cpacket.h index a7768c0..d74c507 100644 --- a/ambed/cpacket.h +++ b/ambed/cpacket.h @@ -32,30 +32,30 @@ class CPacket { public: - // constructors - CPacket(); - CPacket(uint8); - CPacket(const CPacket &); - - // destructor - virtual ~CPacket() {}; - - // identity - virtual bool IsVoice(void) const { return false; } - virtual bool IsAmbe(void) const { return false; } - - // get - int GetChannel(void) const { return m_iCh; } - uint8 GetPid(void) const { return m_uiPid; } - - // set - void SetChannel(int i) { m_iCh = i; } - void SetPid(uint8 ui) { m_uiPid = ui; } - + // constructors + CPacket(); + CPacket(uint8); + CPacket(const CPacket &); + + // destructor + virtual ~CPacket() {}; + + // identity + virtual bool IsVoice(void) const { return false; } + virtual bool IsAmbe(void) const { return false; } + + // get + int GetChannel(void) const { return m_iCh; } + uint8 GetPid(void) const { return m_uiPid; } + + // set + void SetChannel(int i) { m_iCh = i; } + void SetPid(uint8 ui) { m_uiPid = ui; } + protected: - // data - int m_iCh; - uint8 m_uiPid; + // data + int m_iCh; + uint8 m_uiPid; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/ambed/cpacketqueue.cpp b/ambed/cpacketqueue.cpp index ff14dcb..849357b 100644 --- a/ambed/cpacketqueue.cpp +++ b/ambed/cpacketqueue.cpp @@ -38,12 +38,12 @@ CPacketQueue::CPacketQueue() CPacketQueue::~CPacketQueue() { - // empty codec queue - while ( !empty() ) - { - delete front(); - pop(); - } + // empty codec queue + while ( !empty() ) + { + delete front(); + pop(); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -51,10 +51,10 @@ CPacketQueue::~CPacketQueue() void CPacketQueue::Purge(void) { - // this assume queue is already locked - while ( !empty() ) - { - delete front(); - pop(); - } + // this assume queue is already locked + while ( !empty() ) + { + delete front(); + pop(); + } } diff --git a/ambed/cpacketqueue.h b/ambed/cpacketqueue.h index cb7144d..e609871 100644 --- a/ambed/cpacketqueue.h +++ b/ambed/cpacketqueue.h @@ -33,22 +33,22 @@ class CPacketQueue : public std::queue { public: - // constructor - CPacketQueue(); - - // destructor - ~CPacketQueue(); - - // lock - void Lock() { m_Mutex.lock(); } - void Unlock() { m_Mutex.unlock(); } - - // purge - void Purge(void); - + // constructor + CPacketQueue(); + + // destructor + ~CPacketQueue(); + + // lock + void Lock() { m_Mutex.lock(); } + void Unlock() { m_Mutex.unlock(); } + + // purge + void Purge(void); + protected: - // status - std::mutex m_Mutex; + // status + std::mutex m_Mutex; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/ambed/csampleblockprocessor.h b/ambed/csampleblockprocessor.h index 1356553..838ab29 100644 --- a/ambed/csampleblockprocessor.h +++ b/ambed/csampleblockprocessor.h @@ -32,8 +32,8 @@ class CSampleBlockProcessor { public: virtual ~CSampleBlockProcessor() {} - //processing - virtual void ProcessSampleBlock(uint8* voice, int length) = 0; + //processing + virtual void ProcessSampleBlock(uint8* voice, int length) = 0; }; #endif /* csampleprocessor_h */ diff --git a/ambed/csignalprocessor.cpp b/ambed/csignalprocessor.cpp index cfbfc30..6121380 100644 --- a/ambed/csignalprocessor.cpp +++ b/ambed/csignalprocessor.cpp @@ -43,12 +43,12 @@ CSignalProcessor::CSignalProcessor(float gaindB) { #if USE_BANDPASSFILTER - m_sampleProcessors.push_back((CSampleBlockProcessor*)new CFIRFilter(FILTER_TAPS, FILTER_TAPS_LENGTH)); + m_sampleProcessors.push_back((CSampleBlockProcessor*)new CFIRFilter(FILTER_TAPS, FILTER_TAPS_LENGTH)); #endif #if USE_AGC == 1 - m_sampleProcessors.push_back((CSampleBlockProcessor*)new CAGC(gaindB)); + m_sampleProcessors.push_back((CSampleBlockProcessor*)new CAGC(gaindB)); #else - m_sampleProcessors.push_back((CSampleBlockProcessor*)new CFixedGain(gaindB)); + m_sampleProcessors.push_back((CSampleBlockProcessor*)new CFixedGain(gaindB)); #endif } @@ -57,10 +57,10 @@ CSignalProcessor::CSignalProcessor(float gaindB) CSignalProcessor::~CSignalProcessor() { - for(auto it=m_sampleProcessors.begin(); it!=m_sampleProcessors.end(); it++) - { - delete *it; - } + for(auto it=m_sampleProcessors.begin(); it!=m_sampleProcessors.end(); it++) + { + delete *it; + } m_sampleProcessors.clear(); } @@ -69,26 +69,26 @@ CSignalProcessor::~CSignalProcessor() void CSignalProcessor::Process(uint8* voice, int length) { - /*float sample; - int j;*/ + /*float sample; + int j;*/ - for(auto it=m_sampleProcessors.begin(); it!=m_sampleProcessors.end(); it++) - { - (*it)->ProcessSampleBlock(voice, length); - } + for(auto it=m_sampleProcessors.begin(); it!=m_sampleProcessors.end(); it++) + { + (*it)->ProcessSampleBlock(voice, length); + } - /*for(int i = 0; i < length; i += 2) - { - //Get the sample - sample = (float)(short)MAKEWORD(voice[i+1], voice[i]); + /*for(int i = 0; i < length; i += 2) + { + //Get the sample + sample = (float)(short)MAKEWORD(voice[i+1], voice[i]); - for(j = 0; j < processorsSize; j++) - { - sample = m_sampleProcessors[j]->ProcessSample(sample); - } + for(j = 0; j < processorsSize; j++) + { + sample = m_sampleProcessors[j]->ProcessSample(sample); + } - //write processed sample back - voice[i] = HIBYTE((short)sample); - voice[i+1] = LOBYTE((short)sample); - }*/ + //write processed sample back + voice[i] = HIBYTE((short)sample); + voice[i+1] = LOBYTE((short)sample); + }*/ } diff --git a/ambed/csignalprocessor.h b/ambed/csignalprocessor.h index 8ef4390..0af6e23 100644 --- a/ambed/csignalprocessor.h +++ b/ambed/csignalprocessor.h @@ -32,17 +32,17 @@ class CSignalProcessor { public: - //Constructor - CSignalProcessor(float gaindB); + //Constructor + CSignalProcessor(float gaindB); - //Destructor - ~CSignalProcessor(); + //Destructor + ~CSignalProcessor(); - //Processing - void Process(uint8* voice, int length); + //Processing + void Process(uint8* voice, int length); private: - std::list m_sampleProcessors; + std::list m_sampleProcessors; }; #endif /* csignalprocessor_h */ diff --git a/ambed/cstream.cpp b/ambed/cstream.cpp index b9c8fea..fe8e037 100644 --- a/ambed/cstream.cpp +++ b/ambed/cstream.cpp @@ -41,30 +41,30 @@ CStream::CStream() { - m_uiId = 0; - m_uiPort = 0; - m_bStopThread = false; - m_pThread = NULL; - m_VocodecChannel = NULL; - m_LastActivity.Now(); - m_iTotalPackets = 0; - m_iLostPackets = 0; + m_uiId = 0; + m_uiPort = 0; + m_bStopThread = false; + m_pThread = NULL; + m_VocodecChannel = NULL; + m_LastActivity.Now(); + m_iTotalPackets = 0; + m_iLostPackets = 0; } CStream::CStream(uint16 uiId, const CCallsign &Callsign, const CIp &Ip, uint8 uiCodecIn, uint8 uiCodecOut) { - m_uiId = uiId; - m_Callsign = Callsign; - m_Ip = Ip; - m_uiPort = 0; - m_uiCodecIn = uiCodecIn; - m_uiCodecOut = uiCodecOut; - m_bStopThread = false; - m_pThread = NULL; - m_VocodecChannel = NULL; - m_LastActivity.Now(); - m_iTotalPackets = 0; - m_iLostPackets = 0; + m_uiId = uiId; + m_Callsign = Callsign; + m_Ip = Ip; + m_uiPort = 0; + m_uiCodecIn = uiCodecIn; + m_uiCodecOut = uiCodecOut; + m_bStopThread = false; + m_pThread = NULL; + m_VocodecChannel = NULL; + m_LastActivity.Now(); + m_iTotalPackets = 0; + m_iLostPackets = 0; } //////////////////////////////////////////////////////////////////////////////////////// @@ -72,21 +72,21 @@ CStream::CStream(uint16 uiId, const CCallsign &Callsign, const CIp &Ip, uint8 ui CStream::~CStream() { - // stop thread first - m_bStopThread = true; - if ( m_pThread != NULL ) - { - m_pThread->join(); - delete m_pThread; - m_pThread = NULL; - } - - // then close everything - m_Socket.Close(); - if ( m_VocodecChannel != NULL ) - { - m_VocodecChannel->Close(); - } + // stop thread first + m_bStopThread = true; + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + m_pThread = NULL; + } + + // then close everything + m_Socket.Close(); + if ( m_VocodecChannel != NULL ) + { + m_VocodecChannel->Close(); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -94,10 +94,10 @@ CStream::~CStream() bool CStream::Init(uint16 uiPort) { - // reset stop flag - m_bStopThread = false; + // reset stop flag + m_bStopThread = false; - // create our socket + // create our socket auto s = g_AmbeServer.GetListenIp(); CIp ip(strchr(s, ':') ? AF_INET6 : AF_INET, uiPort, s); if (! ip.IsSet()) @@ -106,7 +106,7 @@ bool CStream::Init(uint16 uiPort) return false; } - if (! m_Socket.Open(ip)) + if (! m_Socket.Open(ip)) { std::cout << "Error opening stream stream socket on " << ip << std::endl; return false; @@ -133,32 +133,32 @@ bool CStream::Init(uint16 uiPort) m_iLostPackets = 0; - // done - return true; + // done + return true; } void CStream::Close(void) { - // stop thread first - m_bStopThread = true; - if ( m_pThread != NULL ) - { - m_pThread->join(); - delete m_pThread; - m_pThread = NULL; - } - - // then close everything - m_Socket.Close(); - if ( m_VocodecChannel != NULL ) - { - m_VocodecChannel->Close(); - } - - - // report - std::cout << m_iLostPackets << " of " << m_iTotalPackets << " packets lost" << std::endl; + // stop thread first + m_bStopThread = true; + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + m_pThread = NULL; + } + + // then close everything + m_Socket.Close(); + if ( m_VocodecChannel != NULL ) + { + m_VocodecChannel->Close(); + } + + + // report + std::cout << m_iLostPackets << " of " << m_iTotalPackets << " packets lost" << std::endl; } //////////////////////////////////////////////////////////////////////////////////////// @@ -166,10 +166,10 @@ void CStream::Close(void) void CStream::Thread(CStream *This) { - while ( !This->m_bStopThread ) - { - This->Task(); - } + while ( !This->m_bStopThread ) + { + This->Task(); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -177,45 +177,45 @@ void CStream::Thread(CStream *This) void CStream::Task(void) { - CBuffer Buffer; - static CIp Ip; - uint8 uiPid; - uint8 Ambe[AMBE_FRAME_SIZE]; - CAmbePacket *packet; - CPacketQueue *queue; - - // anything coming in from codec client ? - if ( m_Socket.Receive(Buffer, Ip, 1) ) - { - // crack packet - if ( IsValidDvFramePacket(Buffer, &uiPid, Ambe) ) - { - // transcode AMBE here - m_LastActivity.Now(); - m_iTotalPackets++; - - // post packet to VocoderChannel - packet = new CAmbePacket(uiPid, m_uiCodecIn, Ambe); - queue = m_VocodecChannel->GetPacketQueueIn(); - queue->push(packet); - m_VocodecChannel->ReleasePacketQueueIn(); - } - } - - // anything in our queue ? - queue = m_VocodecChannel->GetPacketQueueOut(); - while ( !queue->empty() ) - { - // get the packet - packet = (CAmbePacket *)queue->front(); - queue->pop(); - // send it to client - EncodeDvFramePacket(&Buffer, packet->GetPid(), packet->GetAmbe()); - m_Socket.Send(Buffer, Ip, m_uiPort); - // and done - delete packet; - } - m_VocodecChannel->ReleasePacketQueueOut(); + CBuffer Buffer; + static CIp Ip; + uint8 uiPid; + uint8 Ambe[AMBE_FRAME_SIZE]; + CAmbePacket *packet; + CPacketQueue *queue; + + // anything coming in from codec client ? + if ( m_Socket.Receive(Buffer, Ip, 1) ) + { + // crack packet + if ( IsValidDvFramePacket(Buffer, &uiPid, Ambe) ) + { + // transcode AMBE here + m_LastActivity.Now(); + m_iTotalPackets++; + + // post packet to VocoderChannel + packet = new CAmbePacket(uiPid, m_uiCodecIn, Ambe); + queue = m_VocodecChannel->GetPacketQueueIn(); + queue->push(packet); + m_VocodecChannel->ReleasePacketQueueIn(); + } + } + + // anything in our queue ? + queue = m_VocodecChannel->GetPacketQueueOut(); + while ( !queue->empty() ) + { + // get the packet + packet = (CAmbePacket *)queue->front(); + queue->pop(); + // send it to client + EncodeDvFramePacket(&Buffer, packet->GetPid(), packet->GetAmbe()); + m_Socket.Send(Buffer, Ip, m_uiPort); + // and done + delete packet; + } + m_VocodecChannel->ReleasePacketQueueOut(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -223,17 +223,17 @@ void CStream::Task(void) bool CStream::IsValidDvFramePacket(const CBuffer &Buffer, uint8 *pid, uint8 *ambe) { - bool valid = false; + bool valid = false; - if ( Buffer.size() == 11 ) - { - uint8 codec = Buffer.data()[0]; - *pid = Buffer.data()[1]; - ::memcpy(ambe, &(Buffer.data()[2]), 9); - valid = (codec == GetCodecIn()); - } + if ( Buffer.size() == 11 ) + { + uint8 codec = Buffer.data()[0]; + *pid = Buffer.data()[1]; + ::memcpy(ambe, &(Buffer.data()[2]), 9); + valid = (codec == GetCodecIn()); + } - return valid; + return valid; } //////////////////////////////////////////////////////////////////////////////////////// @@ -241,8 +241,8 @@ bool CStream::IsValidDvFramePacket(const CBuffer &Buffer, uint8 *pid, uint8 *amb void CStream::EncodeDvFramePacket(CBuffer *Buffer, uint8 Pid, uint8 *Ambe) { - Buffer->clear(); - Buffer->Append((uint8)GetCodecOut()); - Buffer->Append((uint8)Pid); - Buffer->Append(Ambe, 9); + Buffer->clear(); + Buffer->Append((uint8)GetCodecOut()); + Buffer->Append((uint8)Pid); + Buffer->Append(Ambe, 9); } diff --git a/ambed/cstream.h b/ambed/cstream.h index 2abc0f9..8bf44b6 100644 --- a/ambed/cstream.h +++ b/ambed/cstream.h @@ -35,61 +35,61 @@ class CStream { public: - // constructors - CStream(); - CStream(uint16, const CCallsign &, const CIp &, uint8, uint8); - - // destructor - virtual ~CStream(); - - // initialization - bool Init(uint16); - void Close(void); - - // get - uint16 GetId(void) const { return m_uiId; } - uint16 GetPort(void) const { return m_uiPort; } - uint8 GetCodecIn(void) const { return m_uiCodecIn; } - uint8 GetCodecOut(void) const { return m_uiCodecOut; } - - // activity timer - bool IsActive(void) const { return m_LastActivity.DurationSinceNow() <= STREAM_ACTIVITY_TIMEOUT; } - - // task - static void Thread(CStream *); - void Task(void); + // constructors + CStream(); + CStream(uint16, const CCallsign &, const CIp &, uint8, uint8); + + // destructor + virtual ~CStream(); + + // initialization + bool Init(uint16); + void Close(void); + + // get + uint16 GetId(void) const { return m_uiId; } + uint16 GetPort(void) const { return m_uiPort; } + uint8 GetCodecIn(void) const { return m_uiCodecIn; } + uint8 GetCodecOut(void) const { return m_uiCodecOut; } + + // activity timer + bool IsActive(void) const { return m_LastActivity.DurationSinceNow() <= STREAM_ACTIVITY_TIMEOUT; } + + // task + static void Thread(CStream *); + void Task(void); protected: - // packet decoding helpers - bool IsValidDvFramePacket(const CBuffer &, uint8 *, uint8 *); - - // packet encodeing helpers - void EncodeDvFramePacket(CBuffer *, uint8, uint8 *); - - + // packet decoding helpers + bool IsValidDvFramePacket(const CBuffer &, uint8 *, uint8 *); + + // packet encodeing helpers + void EncodeDvFramePacket(CBuffer *, uint8, uint8 *); + + protected: - // data - uint16 m_uiId; - CUdpSocket m_Socket; - uint16 m_uiPort; - uint8 m_uiCodecIn; - uint8 m_uiCodecOut; - CVocodecChannel *m_VocodecChannel; - - // client details - CCallsign m_Callsign; - CIp m_Ip; - - // counters - int m_iTotalPackets; - int m_iLostPackets; - - // activity timer - CTimePoint m_LastActivity; - - // thread - bool m_bStopThread; - std::thread *m_pThread; + // data + uint16 m_uiId; + CUdpSocket m_Socket; + uint16 m_uiPort; + uint8 m_uiCodecIn; + uint8 m_uiCodecOut; + CVocodecChannel *m_VocodecChannel; + + // client details + CCallsign m_Callsign; + CIp m_Ip; + + // counters + int m_iTotalPackets; + int m_iLostPackets; + + // activity timer + CTimePoint m_LastActivity; + + // thread + bool m_bStopThread; + std::thread *m_pThread; }; diff --git a/ambed/ctimepoint.cpp b/ambed/ctimepoint.cpp index 41b59f0..bf69c22 100644 --- a/ambed/ctimepoint.cpp +++ b/ambed/ctimepoint.cpp @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- #include "main.h" @@ -30,7 +30,7 @@ CTimePoint::CTimePoint() { - m_TimePoint = std::chrono::steady_clock::now(); + m_TimePoint = std::chrono::steady_clock::now(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -38,9 +38,9 @@ CTimePoint::CTimePoint() double CTimePoint::DurationSinceNow(void) const { - std::chrono::steady_clock::time_point Now = std::chrono::steady_clock::now(); - std::chrono::steady_clock::duration time_span = (Now - m_TimePoint); - return double(time_span.count()) * std::chrono::steady_clock::period::num / std::chrono::steady_clock::period::den; + std::chrono::steady_clock::time_point Now = std::chrono::steady_clock::now(); + std::chrono::steady_clock::duration time_span = (Now - m_TimePoint); + return double(time_span.count()) * std::chrono::steady_clock::period::num / std::chrono::steady_clock::period::den; } //////////////////////////////////////////////////////////////////////////////////////// @@ -48,6 +48,6 @@ double CTimePoint::DurationSinceNow(void) const void CTimePoint::TaskSleepFor(uint ms) { - std::chrono::milliseconds timespan(ms); - std::this_thread::sleep_for(timespan); + std::chrono::milliseconds timespan(ms); + std::this_thread::sleep_for(timespan); } diff --git a/ambed/ctimepoint.h b/ambed/ctimepoint.h index 9a9e5a2..6adebb1 100644 --- a/ambed/ctimepoint.h +++ b/ambed/ctimepoint.h @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- #ifndef ctimepoint_h @@ -32,22 +32,22 @@ class CTimePoint : public std::chrono::steady_clock::time_point { public: - // constructor - CTimePoint(); - - // destructor - virtual ~CTimePoint() {} - - // operation - void Now(void) { m_TimePoint = std::chrono::steady_clock::now(); } - double DurationSinceNow(void) const; - - // task - static void TaskSleepFor(uint); - + // constructor + CTimePoint(); + + // destructor + virtual ~CTimePoint() {} + + // operation + void Now(void) { m_TimePoint = std::chrono::steady_clock::now(); } + double DurationSinceNow(void) const; + + // task + static void TaskSleepFor(uint); + protected: - // data - std::chrono::steady_clock::time_point m_TimePoint; + // data + std::chrono::steady_clock::time_point m_TimePoint; }; diff --git a/ambed/cusb3000interface.cpp b/ambed/cusb3000interface.cpp index 22e13d6..0e93ae2 100644 --- a/ambed/cusb3000interface.cpp +++ b/ambed/cusb3000interface.cpp @@ -38,9 +38,9 @@ // constructor CUsb3000Interface::CUsb3000Interface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial) -: CUsb3xxxInterface(uiVid, uiPid, szDeviceName, szDeviceSerial) + : CUsb3xxxInterface(uiVid, uiPid, szDeviceName, szDeviceSerial) { - m_uiChCodec = CODEC_NONE; + m_uiChCodec = CODEC_NONE; } //////////////////////////////////////////////////////////////////////////////////////// @@ -48,20 +48,20 @@ CUsb3000Interface::CUsb3000Interface(uint32 uiVid, uint32 uiPid, const char *szD bool CUsb3000Interface::Init(uint8 uiOddCodec) { - bool ok = true; + bool ok = true; - // init the odd channel - m_uiChCodec = uiOddCodec; + // init the odd channel + m_uiChCodec = uiOddCodec; - // base class - ok &= CUsb3xxxInterface::Init(); + // base class + ok &= CUsb3xxxInterface::Init(); - // do not create our channels now - // this is delegated to caller (CVocodecs) as our channel - // may be hybrids between 2 interfaces in case of odd n' of channel device) + // do not create our channels now + // this is delegated to caller (CVocodecs) as our channel + // may be hybrids between 2 interfaces in case of odd n' of channel device) - // done - return ok; + // done + return ok; } //////////////////////////////////////////////////////////////////////////////////////// @@ -69,7 +69,7 @@ bool CUsb3000Interface::Init(uint8 uiOddCodec) uint8 CUsb3000Interface::GetChannelCodec(int iCh) const { - return (iCh == 0) ? m_uiChCodec : CODEC_NONE; + return (iCh == 0) ? m_uiChCodec : CODEC_NONE; } //////////////////////////////////////////////////////////////////////////////////////// @@ -77,35 +77,35 @@ uint8 CUsb3000Interface::GetChannelCodec(int iCh) const CVocodecChannel *CUsb3000Interface::GetChannelWithChannelIn(int iCh) { - CVocodecChannel *Channel = NULL; - bool done = false; - for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ ) - { - if ( iCh == 0 ) - { - if ( (m_Channels[i]->GetChannelIn() == iCh) && !(m_Channels[i]->IsInterfaceOut(this)) ) - { - Channel = m_Channels[i]; - done = true; - } - } - } - return Channel; + CVocodecChannel *Channel = NULL; + bool done = false; + for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ ) + { + if ( iCh == 0 ) + { + if ( (m_Channels[i]->GetChannelIn() == iCh) && !(m_Channels[i]->IsInterfaceOut(this)) ) + { + Channel = m_Channels[i]; + done = true; + } + } + } + return Channel; } CVocodecChannel *CUsb3000Interface::GetChannelWithChannelOut(int iCh) { - CVocodecChannel *Channel = NULL; - bool done = false; - for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ ) - { - if ( (m_Channels[i]->GetChannelOut() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) ) - { - Channel = m_Channels[i]; - done = true; - } - } - return Channel; + CVocodecChannel *Channel = NULL; + bool done = false; + for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ ) + { + if ( (m_Channels[i]->GetChannelOut() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) ) + { + Channel = m_Channels[i]; + done = true; + } + } + return Channel; } @@ -114,34 +114,34 @@ CVocodecChannel *CUsb3000Interface::GetChannelWithChannelOut(int iCh) bool CUsb3000Interface::IsValidChannelPacket(const CBuffer &buffer, int *ch, CAmbePacket *packet) { - bool valid = false; - uint8 tag[] = { PKT_HEADER,0x00,0x0B,PKT_CHANNEL }; - - if ( (buffer.size() == 15) && (buffer.Compare(tag, sizeof(tag)) == 0)) - { - *ch = 0; - packet->SetCodec(m_uiChCodec); - packet->SetAmbe(&(buffer.data()[6])); - valid = (*ch < GetNbChannels()); - //std::cout << "CHAN " << *ch << " " << buffer.size() << " " << (int)buffer[6] << std::endl; - } - return valid; + bool valid = false; + uint8 tag[] = { PKT_HEADER,0x00,0x0B,PKT_CHANNEL }; + + if ( (buffer.size() == 15) && (buffer.Compare(tag, sizeof(tag)) == 0)) + { + *ch = 0; + packet->SetCodec(m_uiChCodec); + packet->SetAmbe(&(buffer.data()[6])); + valid = (*ch < GetNbChannels()); + //std::cout << "CHAN " << *ch << " " << buffer.size() << " " << (int)buffer[6] << std::endl; + } + return valid; } bool CUsb3000Interface::IsValidSpeechPacket(const CBuffer &buffer, int *ch, CVoicePacket *packet) { - bool valid = false; - - if ( (buffer.size() > 6) && - (buffer.data()[0] == PKT_HEADER) && (buffer.data()[3] == PKT_SPEECH) && - (buffer.data()[4] == PKT_SPEECHD) ) - { - *ch = 0; - packet->SetVoice(&(buffer.data()[6]), buffer.data()[5] * 2); - valid = (*ch < GetNbChannels()); - //std::cout << "SPCH " << *ch << " " << buffer.size() << std::endl; - } - return valid; + bool valid = false; + + if ( (buffer.size() > 6) && + (buffer.data()[0] == PKT_HEADER) && (buffer.data()[3] == PKT_SPEECH) && + (buffer.data()[4] == PKT_SPEECHD) ) + { + *ch = 0; + packet->SetVoice(&(buffer.data()[6]), buffer.data()[5] * 2); + valid = (*ch < GetNbChannels()); + //std::cout << "SPCH " << *ch << " " << buffer.size() << std::endl; + } + return valid; } //////////////////////////////////////////////////////////////////////////////////////// @@ -149,28 +149,28 @@ bool CUsb3000Interface::IsValidSpeechPacket(const CBuffer &buffer, int *ch, CVoi void CUsb3000Interface::EncodeChannelPacket(CBuffer *buffer, int ch, CAmbePacket *packet) { - uint size = (uint16)packet->GetAmbeSize() + 2; - buffer->clear(); - buffer->Append((uint8)PKT_HEADER); - buffer->Append((uint8)HIBYTE(size)); - buffer->Append((uint8)LOBYTE(size)); - buffer->Append((uint8)PKT_CHANNEL); - buffer->Append((uint8)(PKT_CHAND)); - buffer->Append((uint8)(packet->GetAmbeSize()*8)); - buffer->Append(packet->GetAmbe(), packet->GetAmbeSize()); + uint size = (uint16)packet->GetAmbeSize() + 2; + buffer->clear(); + buffer->Append((uint8)PKT_HEADER); + buffer->Append((uint8)HIBYTE(size)); + buffer->Append((uint8)LOBYTE(size)); + buffer->Append((uint8)PKT_CHANNEL); + buffer->Append((uint8)(PKT_CHAND)); + buffer->Append((uint8)(packet->GetAmbeSize()*8)); + buffer->Append(packet->GetAmbe(), packet->GetAmbeSize()); } void CUsb3000Interface::EncodeSpeechPacket(CBuffer *buffer, int ch, CVoicePacket *packet) { - uint16 size = (uint16)packet->GetVoiceSize() + 2; - buffer->clear(); - buffer->Append((uint8)PKT_HEADER); - buffer->Append((uint8)HIBYTE(size)); - buffer->Append((uint8)LOBYTE(size)); - buffer->Append((uint8)PKT_SPEECH); - buffer->Append((uint8)PKT_SPEECHD); - buffer->Append((uint8)(packet->GetVoiceSize()/2)); - buffer->Append(packet->GetVoice(), packet->GetVoiceSize()); + uint16 size = (uint16)packet->GetVoiceSize() + 2; + buffer->clear(); + buffer->Append((uint8)PKT_HEADER); + buffer->Append((uint8)HIBYTE(size)); + buffer->Append((uint8)LOBYTE(size)); + buffer->Append((uint8)PKT_SPEECH); + buffer->Append((uint8)PKT_SPEECHD); + buffer->Append((uint8)(packet->GetVoiceSize()/2)); + buffer->Append(packet->GetVoice(), packet->GetVoiceSize()); } @@ -179,119 +179,119 @@ void CUsb3000Interface::EncodeSpeechPacket(CBuffer *buffer, int ch, CVoicePacket bool CUsb3000Interface::OpenDevice(void) { - FT_STATUS ftStatus; - int baudrate = 460800; + FT_STATUS ftStatus; + int baudrate = 460800; - //sets serial VID/PID for a Standard Device NOTE: This is for legacy purposes only. This can be ommitted. - ftStatus = FT_SetVIDPID(m_uiVid, m_uiPid); - if (ftStatus != FT_OK) {FTDI_Error((char *)"FT_SetVIDPID", ftStatus ); return false; } + //sets serial VID/PID for a Standard Device NOTE: This is for legacy purposes only. This can be ommitted. + ftStatus = FT_SetVIDPID(m_uiVid, m_uiPid); + if (ftStatus != FT_OK) {FTDI_Error((char *)"FT_SetVIDPID", ftStatus ); return false; } - ftStatus = FT_OpenEx((PVOID)m_szDeviceSerial, FT_OPEN_BY_SERIAL_NUMBER, &m_FtdiHandle); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_OpenEx", ftStatus ); return false; } + ftStatus = FT_OpenEx((PVOID)m_szDeviceSerial, FT_OPEN_BY_SERIAL_NUMBER, &m_FtdiHandle); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_OpenEx", ftStatus ); return false; } - CTimePoint::TaskSleepFor(50); - FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX ); - CTimePoint::TaskSleepFor(50); + CTimePoint::TaskSleepFor(50); + FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX ); + CTimePoint::TaskSleepFor(50); - ftStatus = FT_SetDataCharacteristics(m_FtdiHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE); - if ( ftStatus != FT_OK ) { FTDI_Error((char *)"FT_SetDataCharacteristics", ftStatus ); return false; } + ftStatus = FT_SetDataCharacteristics(m_FtdiHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE); + if ( ftStatus != FT_OK ) { FTDI_Error((char *)"FT_SetDataCharacteristics", ftStatus ); return false; } - ftStatus = FT_SetFlowControl(m_FtdiHandle, FT_FLOW_RTS_CTS, 0x11, 0x13); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetFlowControl", ftStatus ); return false; } + ftStatus = FT_SetFlowControl(m_FtdiHandle, FT_FLOW_RTS_CTS, 0x11, 0x13); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetFlowControl", ftStatus ); return false; } - ftStatus = FT_SetRts (m_FtdiHandle); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetRts", ftStatus ); return false; } + ftStatus = FT_SetRts (m_FtdiHandle); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetRts", ftStatus ); return false; } - //for usb-3012 pull DTR high to take AMBE3003 out of reset. - //for other devices noting is connected to DTR so it is a dont care - ftStatus = FT_ClrDtr(m_FtdiHandle); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_ClrDtr", ftStatus); return false; } + //for usb-3012 pull DTR high to take AMBE3003 out of reset. + //for other devices noting is connected to DTR so it is a dont care + ftStatus = FT_ClrDtr(m_FtdiHandle); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_ClrDtr", ftStatus); return false; } - ftStatus = FT_SetBaudRate(m_FtdiHandle, baudrate ); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetBaudRate", ftStatus ); return false; } + ftStatus = FT_SetBaudRate(m_FtdiHandle, baudrate ); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetBaudRate", ftStatus ); return false; } - ftStatus = FT_SetLatencyTimer(m_FtdiHandle, 4); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetLatencyTimer", ftStatus ); return false; } + ftStatus = FT_SetLatencyTimer(m_FtdiHandle, 4); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetLatencyTimer", ftStatus ); return false; } - ftStatus = FT_SetUSBParameters(m_FtdiHandle, USB3XXX_MAXPACKETSIZE, 0); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetUSBParameters", ftStatus ); return false; } + ftStatus = FT_SetUSBParameters(m_FtdiHandle, USB3XXX_MAXPACKETSIZE, 0); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetUSBParameters", ftStatus ); return false; } - ftStatus = FT_SetTimeouts(m_FtdiHandle, 200, 200 ); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetTimeouts", ftStatus ); return false; } + ftStatus = FT_SetTimeouts(m_FtdiHandle, 200, 200 ); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetTimeouts", ftStatus ); return false; } - // done - return true; + // done + return true; } bool CUsb3000Interface::ResetDevice(void) { - bool ok = false; - int len; - char rxpacket[100]; - char zeropacket[10] = - { - 0,0,0,0,0,0,0,0,0,0 - }; - char txpacket[7] = - { - PKT_HEADER, - 0, - 3, - 0, - PKT_RESET, - PKT_PARITYBYTE, - 3 ^ PKT_RESET ^ PKT_PARITYBYTE - }; - - - //the chip might be in a state where it is waiting to receive bytes from a prior incomplete packet. - //first send 350 zeros in case, the chip's receive state is still waiting for characters - //if we send more than needed, the exta characters will just get discarded since they do not match the header byte - //after that we send PKT_RESET to reset the device - //As long as the AMBE3000 is able to receive via uart, this method will succeed in resetting it. - - for ( int i = 0; i < 35 ; i++ ) - { - FTDI_write_packet(m_FtdiHandle, zeropacket, sizeof(zeropacket)); - } - - - // write soft-reset packet - if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) - { - // read reply - len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ); - ok = ((len == 5) && (rxpacket[4] == PKT_READY)); - if ( !ok ) - { - std::cout << "USB-3000 soft reset failed" << std::endl; - } - } - - // done - return ok; + bool ok = false; + int len; + char rxpacket[100]; + char zeropacket[10] = + { + 0,0,0,0,0,0,0,0,0,0 + }; + char txpacket[7] = + { + PKT_HEADER, + 0, + 3, + 0, + PKT_RESET, + PKT_PARITYBYTE, + 3 ^ PKT_RESET ^ PKT_PARITYBYTE + }; + + + //the chip might be in a state where it is waiting to receive bytes from a prior incomplete packet. + //first send 350 zeros in case, the chip's receive state is still waiting for characters + //if we send more than needed, the exta characters will just get discarded since they do not match the header byte + //after that we send PKT_RESET to reset the device + //As long as the AMBE3000 is able to receive via uart, this method will succeed in resetting it. + + for ( int i = 0; i < 35 ; i++ ) + { + FTDI_write_packet(m_FtdiHandle, zeropacket, sizeof(zeropacket)); + } + + + // write soft-reset packet + if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) + { + // read reply + len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ); + ok = ((len == 5) && (rxpacket[4] == PKT_READY)); + if ( !ok ) + { + std::cout << "USB-3000 soft reset failed" << std::endl; + } + } + + // done + return ok; } bool CUsb3000Interface::ConfigureDevice(void) { - bool ok = true; - uint8 pkt_ratep_ambeplus[] = { 0x01,0x30,0x07,0x63,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x48 }; - uint8 pkt_ratep_ambe2plus[] = { 0x04,0x31,0x07,0x54,0x24,0x00,0x00,0x00,0x00,0x00,0x6F,0x48 }; - - // configure the channel for desired codec - switch ( m_uiChCodec ) - { - case CODEC_AMBEPLUS: - ok &= ConfigureChannel(PKT_CHANNEL0, pkt_ratep_ambeplus, 0, 0); - break; - case CODEC_AMBE2PLUS: - ok &= ConfigureChannel(PKT_CHANNEL0, pkt_ratep_ambe2plus, 0, 0); - break; - case CODEC_NONE: - default: - break; - } - - // done - return ok; + bool ok = true; + uint8 pkt_ratep_ambeplus[] = { 0x01,0x30,0x07,0x63,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x48 }; + uint8 pkt_ratep_ambe2plus[] = { 0x04,0x31,0x07,0x54,0x24,0x00,0x00,0x00,0x00,0x00,0x6F,0x48 }; + + // configure the channel for desired codec + switch ( m_uiChCodec ) + { + case CODEC_AMBEPLUS: + ok &= ConfigureChannel(PKT_CHANNEL0, pkt_ratep_ambeplus, 0, 0); + break; + case CODEC_AMBE2PLUS: + ok &= ConfigureChannel(PKT_CHANNEL0, pkt_ratep_ambe2plus, 0, 0); + break; + case CODEC_NONE: + default: + break; + } + + // done + return ok; } diff --git a/ambed/cusb3000interface.h b/ambed/cusb3000interface.h index 1968b7b..70068e3 100644 --- a/ambed/cusb3000interface.h +++ b/ambed/cusb3000interface.h @@ -41,39 +41,39 @@ class CUsb3000Interface : public CUsb3xxxInterface { public: - // constructors - CUsb3000Interface(uint32, uint32, const char *, const char *); - - // destructor - virtual ~CUsb3000Interface() {} - - // initialization - bool Init(uint8); - - // manage channels - int GetNbChannels(void) const { return USB3000_NB_CH; } - uint8 GetChannelCodec(int) const; - - // manage vocodec channels - CVocodecChannel *GetChannelWithChannelIn(int); - CVocodecChannel *GetChannelWithChannelOut(int); - + // constructors + CUsb3000Interface(uint32, uint32, const char *, const char *); + + // destructor + virtual ~CUsb3000Interface() {} + + // initialization + bool Init(uint8); + + // manage channels + int GetNbChannels(void) const { return USB3000_NB_CH; } + uint8 GetChannelCodec(int) const; + + // manage vocodec channels + CVocodecChannel *GetChannelWithChannelIn(int); + CVocodecChannel *GetChannelWithChannelOut(int); + protected: - // decoder helper - bool IsValidChannelPacket(const CBuffer &, int *, CAmbePacket *); - bool IsValidSpeechPacket(const CBuffer &, int *, CVoicePacket *); - - // encoder helpers - void EncodeChannelPacket(CBuffer *, int, CAmbePacket *); - void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *); - - // low level - bool OpenDevice(void); - bool ResetDevice(void); - bool ConfigureDevice(void); - - // data - uint8 m_uiChCodec; + // decoder helper + bool IsValidChannelPacket(const CBuffer &, int *, CAmbePacket *); + bool IsValidSpeechPacket(const CBuffer &, int *, CVoicePacket *); + + // encoder helpers + void EncodeChannelPacket(CBuffer *, int, CAmbePacket *); + void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *); + + // low level + bool OpenDevice(void); + bool ResetDevice(void); + bool ConfigureDevice(void); + + // data + uint8 m_uiChCodec; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/ambed/cusb3003df2etinterface.cpp b/ambed/cusb3003df2etinterface.cpp index 94cd357..bbcc5e5 100644 --- a/ambed/cusb3003df2etinterface.cpp +++ b/ambed/cusb3003df2etinterface.cpp @@ -35,7 +35,7 @@ // constructor CUsb3003DF2ETInterface::CUsb3003DF2ETInterface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial) -: CUsb3003Interface(uiVid, uiPid, szDeviceName, szDeviceSerial) + : CUsb3003Interface(uiVid, uiPid, szDeviceName, szDeviceSerial) { } @@ -44,121 +44,123 @@ CUsb3003DF2ETInterface::CUsb3003DF2ETInterface(uint32 uiVid, uint32 uiPid, const bool CUsb3003DF2ETInterface::OpenDevice(void) { - FT_STATUS ftStatus; - int baudrate = 921600; - - //sets serial VID/PID for a Standard Device NOTE: This is for legacy purposes only. This can be ommitted. - ftStatus = FT_SetVIDPID(m_uiVid, m_uiPid); - if (ftStatus != FT_OK) {FTDI_Error((char *)"FT_SetVIDPID", ftStatus ); return false; } - - ftStatus = FT_OpenEx((PVOID)m_szDeviceSerial, FT_OPEN_BY_SERIAL_NUMBER, &m_FtdiHandle); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_OpenEx", ftStatus ); return false; } - - CTimePoint::TaskSleepFor(50); - FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX ); - CTimePoint::TaskSleepFor(50); - - ftStatus = FT_SetDataCharacteristics(m_FtdiHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE); - if ( ftStatus != FT_OK ) { FTDI_Error((char *)"FT_SetDataCharacteristics", ftStatus ); return false; } - - ftStatus = FT_SetFlowControl(m_FtdiHandle, FT_FLOW_RTS_CTS, 0x11, 0x13); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetFlowControl", ftStatus ); return false; } - - ftStatus = FT_SetRts (m_FtdiHandle); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetRts", ftStatus ); return false; } - - // for DF2ET-3003 interface pull DTR low to take AMBE3003 out of reset. - ftStatus = FT_SetDtr( m_FtdiHandle ); - CTimePoint::TaskSleepFor(50); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetDtr", ftStatus); return false; } - - ftStatus = FT_SetBaudRate(m_FtdiHandle, baudrate ); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetBaudRate", ftStatus ); return false; } - - ftStatus = FT_SetLatencyTimer(m_FtdiHandle, 4); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetLatencyTimer", ftStatus ); return false; } - - ftStatus = FT_SetUSBParameters(m_FtdiHandle, USB3XXX_MAXPACKETSIZE, 0); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetUSBParameters", ftStatus ); return false; } - - ftStatus = FT_SetTimeouts(m_FtdiHandle, 200, 200 ); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetTimeouts", ftStatus ); return false; } - - // done - return true; + FT_STATUS ftStatus; + int baudrate = 921600; + + //sets serial VID/PID for a Standard Device NOTE: This is for legacy purposes only. This can be ommitted. + ftStatus = FT_SetVIDPID(m_uiVid, m_uiPid); + if (ftStatus != FT_OK) {FTDI_Error((char *)"FT_SetVIDPID", ftStatus ); return false; } + + ftStatus = FT_OpenEx((PVOID)m_szDeviceSerial, FT_OPEN_BY_SERIAL_NUMBER, &m_FtdiHandle); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_OpenEx", ftStatus ); return false; } + + CTimePoint::TaskSleepFor(50); + FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX ); + CTimePoint::TaskSleepFor(50); + + ftStatus = FT_SetDataCharacteristics(m_FtdiHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE); + if ( ftStatus != FT_OK ) { FTDI_Error((char *)"FT_SetDataCharacteristics", ftStatus ); return false; } + + ftStatus = FT_SetFlowControl(m_FtdiHandle, FT_FLOW_RTS_CTS, 0x11, 0x13); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetFlowControl", ftStatus ); return false; } + + ftStatus = FT_SetRts (m_FtdiHandle); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetRts", ftStatus ); return false; } + + // for DF2ET-3003 interface pull DTR low to take AMBE3003 out of reset. + ftStatus = FT_SetDtr( m_FtdiHandle ); + CTimePoint::TaskSleepFor(50); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetDtr", ftStatus); return false; } + + ftStatus = FT_SetBaudRate(m_FtdiHandle, baudrate ); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetBaudRate", ftStatus ); return false; } + + ftStatus = FT_SetLatencyTimer(m_FtdiHandle, 4); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetLatencyTimer", ftStatus ); return false; } + + ftStatus = FT_SetUSBParameters(m_FtdiHandle, USB3XXX_MAXPACKETSIZE, 0); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetUSBParameters", ftStatus ); return false; } + + ftStatus = FT_SetTimeouts(m_FtdiHandle, 200, 200 ); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetTimeouts", ftStatus ); return false; } + + // done + return true; } bool CUsb3003DF2ETInterface::ResetDevice(void) { - bool ok = false; - FT_STATUS ftStatus; - int len, i; - char rxpacket[100]; - - std::cout << "Trying DF2ET-3003 soft reset" << std::endl; - - DWORD n, b; - char txpacket[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - char reset_packet[7] = { PKT_HEADER, 0, 3, 0, PKT_RESET, PKT_PARITYBYTE, 3 ^ PKT_RESET ^ PKT_PARITYBYTE }; - char *p; - - for (i = 0; i < 35; i++) - { - p = &txpacket[0]; - n = 10; - do - { - ftStatus = FT_Write( m_FtdiHandle, p, n, &b); - if (FT_OK != ftStatus) - { - return 1; - } - n -= b; - p += b; - } while (n > 0); - } - - p = &reset_packet[0]; - n = 7; - do - { - ftStatus = FT_Write( m_FtdiHandle, p, n, &b); - if (FT_OK != ftStatus) - { - return 1; - } - n -= b; - p += b; - } while (n > 0); - - len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ); - ok = ((len == 7) && (rxpacket[4] == PKT_READY)); - if ( ok ) - { - std::cout << "DF2ET-3003 soft reset succeeded" << std::endl; - } - else - { - std::cout << "DF2ET-3003 soft reset failed" << std::endl; - - std::cout << "Trying DF2ET-3003 hard reset" << std::endl; - - ftStatus = FT_ClrDtr( m_FtdiHandle ); - CTimePoint::TaskSleepFor(10); - ftStatus = FT_SetDtr( m_FtdiHandle ); - CTimePoint::TaskSleepFor(10); - - len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ); - ok = ((len == 7) && (rxpacket[4] == PKT_READY)); - if ( ok ) - { - std::cout << "DF2ET-3003 hard reset succeeded" << std::endl; - } - else - { - std::cout << "DF2ET-3003 hard reset failed" << std::endl; - } - } - return ok; + bool ok = false; + FT_STATUS ftStatus; + int len, i; + char rxpacket[100]; + + std::cout << "Trying DF2ET-3003 soft reset" << std::endl; + + DWORD n, b; + char txpacket[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + char reset_packet[7] = { PKT_HEADER, 0, 3, 0, PKT_RESET, PKT_PARITYBYTE, 3 ^ PKT_RESET ^ PKT_PARITYBYTE }; + char *p; + + for (i = 0; i < 35; i++) + { + p = &txpacket[0]; + n = 10; + do + { + ftStatus = FT_Write( m_FtdiHandle, p, n, &b); + if (FT_OK != ftStatus) + { + return 1; + } + n -= b; + p += b; + } + while (n > 0); + } + + p = &reset_packet[0]; + n = 7; + do + { + ftStatus = FT_Write( m_FtdiHandle, p, n, &b); + if (FT_OK != ftStatus) + { + return 1; + } + n -= b; + p += b; + } + while (n > 0); + + len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ); + ok = ((len == 7) && (rxpacket[4] == PKT_READY)); + if ( ok ) + { + std::cout << "DF2ET-3003 soft reset succeeded" << std::endl; + } + else + { + std::cout << "DF2ET-3003 soft reset failed" << std::endl; + + std::cout << "Trying DF2ET-3003 hard reset" << std::endl; + + ftStatus = FT_ClrDtr( m_FtdiHandle ); + CTimePoint::TaskSleepFor(10); + ftStatus = FT_SetDtr( m_FtdiHandle ); + CTimePoint::TaskSleepFor(10); + + len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ); + ok = ((len == 7) && (rxpacket[4] == PKT_READY)); + if ( ok ) + { + std::cout << "DF2ET-3003 hard reset succeeded" << std::endl; + } + else + { + std::cout << "DF2ET-3003 hard reset failed" << std::endl; + } + } + return ok; } diff --git a/ambed/cusb3003df2etinterface.h b/ambed/cusb3003df2etinterface.h index ad11cc3..429f01c 100644 --- a/ambed/cusb3003df2etinterface.h +++ b/ambed/cusb3003df2etinterface.h @@ -41,16 +41,16 @@ class CUsb3003DF2ETInterface : public CUsb3003Interface { public: - // constructors - CUsb3003DF2ETInterface(uint32, uint32, const char *, const char *); - - // destructor - virtual ~CUsb3003DF2ETInterface() {} - + // constructors + CUsb3003DF2ETInterface(uint32, uint32, const char *, const char *); + + // destructor + virtual ~CUsb3003DF2ETInterface() {} + protected: - // low level - bool OpenDevice(void); - bool ResetDevice(void); + // low level + bool OpenDevice(void); + bool ResetDevice(void); }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/ambed/cusb3003hrinterface.cpp b/ambed/cusb3003hrinterface.cpp index 0228e2f..e808828 100644 --- a/ambed/cusb3003hrinterface.cpp +++ b/ambed/cusb3003hrinterface.cpp @@ -32,7 +32,7 @@ // constructor CUsb3003HRInterface::CUsb3003HRInterface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial) -: CUsb3003Interface(uiVid, uiPid, szDeviceName, szDeviceSerial) + : CUsb3003Interface(uiVid, uiPid, szDeviceName, szDeviceSerial) { } @@ -41,24 +41,24 @@ CUsb3003HRInterface::CUsb3003HRInterface(uint32 uiVid, uint32 uiPid, const char bool CUsb3003HRInterface::ResetDevice(void) { - bool ok = false; - int len; - char rxpacket[100]; + bool ok = false; + int len; + char rxpacket[100]; - //if the device is a USB-3003, it supports reset via UART break signal - //printf("reset via uart break...\n"); - FT_SetBreakOn( m_FtdiHandle ); - CTimePoint::TaskSleepFor(10); - FT_SetBreakOff( m_FtdiHandle ); - //CTimePoint::TaskSleepFor(10); + //if the device is a USB-3003, it supports reset via UART break signal + //printf("reset via uart break...\n"); + FT_SetBreakOn( m_FtdiHandle ); + CTimePoint::TaskSleepFor(10); + FT_SetBreakOff( m_FtdiHandle ); + //CTimePoint::TaskSleepFor(10); - len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ); - ok = ((len == 7) && (rxpacket[4] == PKT_READY)); - if ( !ok ) - { - std::cout << "USB-3003 hard reset failed" << std::endl; - } + len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ); + ok = ((len == 7) && (rxpacket[4] == PKT_READY)); + if ( !ok ) + { + std::cout << "USB-3003 hard reset failed" << std::endl; + } - // done - return ok; + // done + return ok; } diff --git a/ambed/cusb3003hrinterface.h b/ambed/cusb3003hrinterface.h index b045e14..60b1646 100644 --- a/ambed/cusb3003hrinterface.h +++ b/ambed/cusb3003hrinterface.h @@ -40,15 +40,15 @@ class CUsb3003HRInterface : public CUsb3003Interface { public: - // constructors - CUsb3003HRInterface(uint32, uint32, const char *, const char *); - - // destructor - virtual ~CUsb3003HRInterface() {} - + // constructors + CUsb3003HRInterface(uint32, uint32, const char *, const char *); + + // destructor + virtual ~CUsb3003HRInterface() {} + protected: - // low level - bool ResetDevice(void); + // low level + bool ResetDevice(void); }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/ambed/cusb3003interface.cpp b/ambed/cusb3003interface.cpp index d530d8d..b019b07 100644 --- a/ambed/cusb3003interface.cpp +++ b/ambed/cusb3003interface.cpp @@ -40,11 +40,11 @@ // constructor CUsb3003Interface::CUsb3003Interface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial) -: CUsb3xxxInterface(uiVid, uiPid, szDeviceName, szDeviceSerial) + : CUsb3xxxInterface(uiVid, uiPid, szDeviceName, szDeviceSerial) { - m_uiChCodecs[0]= CODEC_AMBEPLUS; - m_uiChCodecs[1]= CODEC_AMBE2PLUS; - m_uiChCodecs[2]= CODEC_NONE; + m_uiChCodecs[0]= CODEC_AMBEPLUS; + m_uiChCodecs[1]= CODEC_AMBE2PLUS; + m_uiChCodecs[2]= CODEC_NONE; } //////////////////////////////////////////////////////////////////////////////////////// @@ -52,20 +52,20 @@ CUsb3003Interface::CUsb3003Interface(uint32 uiVid, uint32 uiPid, const char *szD bool CUsb3003Interface::Init(uint8 uiOddCodec) { - bool ok = true; + bool ok = true; - // init the odd channel - m_uiChCodecs[2] = uiOddCodec; + // init the odd channel + m_uiChCodecs[2] = uiOddCodec; - // base class - ok &= CUsb3xxxInterface::Init(); + // base class + ok &= CUsb3xxxInterface::Init(); - // do not create our channels now - // this is delegated to caller (CVocodecs) as our channel - // may be hybrids between 2 interfaces in case of odd n' of channel device) + // do not create our channels now + // this is delegated to caller (CVocodecs) as our channel + // may be hybrids between 2 interfaces in case of odd n' of channel device) - // done - return ok; + // done + return ok; } //////////////////////////////////////////////////////////////////////////////////////// @@ -73,12 +73,12 @@ bool CUsb3003Interface::Init(uint8 uiOddCodec) uint8 CUsb3003Interface::GetChannelCodec(int iCh) const { - uint8 uiCodec = CODEC_NONE; - if ( (iCh >= 0) && (iCh <= USB3003_NB_CH) ) - { - uiCodec = m_uiChCodecs[iCh]; - } - return uiCodec; + uint8 uiCodec = CODEC_NONE; + if ( (iCh >= 0) && (iCh <= USB3003_NB_CH) ) + { + uiCodec = m_uiChCodecs[iCh]; + } + return uiCodec; } //////////////////////////////////////////////////////////////////////////////////////// @@ -86,43 +86,43 @@ uint8 CUsb3003Interface::GetChannelCodec(int iCh) const CVocodecChannel *CUsb3003Interface::GetChannelWithChannelIn(int iCh) { - CVocodecChannel *Channel = NULL; - bool done = false; - for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ ) - { - if ( iCh == 2 ) - { - if ( (m_Channels[i]->GetChannelIn() == iCh) && !(m_Channels[i]->IsInterfaceOut(this)) ) - { - Channel = m_Channels[i]; - done = true; - } - } - else - { - if ( (m_Channels[i]->GetChannelIn() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) ) - { - Channel = m_Channels[i]; - done = true; - } - } - } - return Channel; + CVocodecChannel *Channel = NULL; + bool done = false; + for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ ) + { + if ( iCh == 2 ) + { + if ( (m_Channels[i]->GetChannelIn() == iCh) && !(m_Channels[i]->IsInterfaceOut(this)) ) + { + Channel = m_Channels[i]; + done = true; + } + } + else + { + if ( (m_Channels[i]->GetChannelIn() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) ) + { + Channel = m_Channels[i]; + done = true; + } + } + } + return Channel; } CVocodecChannel *CUsb3003Interface::GetChannelWithChannelOut(int iCh) { - CVocodecChannel *Channel = NULL; - bool done = false; - for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ ) - { - if ( (m_Channels[i]->GetChannelOut() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) ) - { - Channel = m_Channels[i]; - done = true; - } - } - return Channel; + CVocodecChannel *Channel = NULL; + bool done = false; + for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ ) + { + if ( (m_Channels[i]->GetChannelOut() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) ) + { + Channel = m_Channels[i]; + done = true; + } + } + return Channel; } //////////////////////////////////////////////////////////////////////////////////////// @@ -130,39 +130,39 @@ CVocodecChannel *CUsb3003Interface::GetChannelWithChannelOut(int iCh) bool CUsb3003Interface::IsValidChannelPacket(const CBuffer &buffer, int *ch, CAmbePacket *packet) { - bool valid = false; - uint8 tag[] = { PKT_HEADER,0x00,0x0C,PKT_CHANNEL }; - - if ( (buffer.size() == 16) && (buffer.Compare(tag, sizeof(tag)) == 0)) - { - *ch = buffer.data()[4] - PKT_CHANNEL0; - if ( *ch == 0 ) - packet->SetCodec(CODEC_AMBEPLUS); - else if ( *ch == 1 ) - packet->SetCodec(CODEC_AMBE2PLUS); - else - packet->SetCodec(CODEC_NONE); - packet->SetAmbe(&(buffer.data()[7])); - valid = (*ch < GetNbChannels()); - //std::cout << "CHAN " << *ch << " " << buffer.size() << " " << (int)buffer[6] << std::endl; - } - return valid; + bool valid = false; + uint8 tag[] = { PKT_HEADER,0x00,0x0C,PKT_CHANNEL }; + + if ( (buffer.size() == 16) && (buffer.Compare(tag, sizeof(tag)) == 0)) + { + *ch = buffer.data()[4] - PKT_CHANNEL0; + if ( *ch == 0 ) + packet->SetCodec(CODEC_AMBEPLUS); + else if ( *ch == 1 ) + packet->SetCodec(CODEC_AMBE2PLUS); + else + packet->SetCodec(CODEC_NONE); + packet->SetAmbe(&(buffer.data()[7])); + valid = (*ch < GetNbChannels()); + //std::cout << "CHAN " << *ch << " " << buffer.size() << " " << (int)buffer[6] << std::endl; + } + return valid; } bool CUsb3003Interface::IsValidSpeechPacket(const CBuffer &buffer, int *ch, CVoicePacket *packet) { - bool valid = false; - - if ( (buffer.size() > 6) && - (buffer.data()[0] == PKT_HEADER) && (buffer.data()[3] == PKT_SPEECH) && - (buffer.data()[5] == PKT_SPEECHD) ) - { - *ch = buffer.data()[4] - PKT_CHANNEL0; - packet->SetVoice(&(buffer.data()[7]), buffer.data()[6] * 2); - valid = (*ch < GetNbChannels()); - //std::cout << "SPCH " << *ch << " " << buffer.size() << std::endl; - } - return valid; + bool valid = false; + + if ( (buffer.size() > 6) && + (buffer.data()[0] == PKT_HEADER) && (buffer.data()[3] == PKT_SPEECH) && + (buffer.data()[5] == PKT_SPEECHD) ) + { + *ch = buffer.data()[4] - PKT_CHANNEL0; + packet->SetVoice(&(buffer.data()[7]), buffer.data()[6] * 2); + valid = (*ch < GetNbChannels()); + //std::cout << "SPCH " << *ch << " " << buffer.size() << std::endl; + } + return valid; } //////////////////////////////////////////////////////////////////////////////////////// @@ -170,30 +170,30 @@ bool CUsb3003Interface::IsValidSpeechPacket(const CBuffer &buffer, int *ch, CVoi void CUsb3003Interface::EncodeChannelPacket(CBuffer *buffer, int ch, CAmbePacket *packet) { - uint size = (uint16)packet->GetAmbeSize() + 3; - buffer->clear(); - buffer->Append((uint8)PKT_HEADER); - buffer->Append((uint8)HIBYTE(size)); - buffer->Append((uint8)LOBYTE(size)); - buffer->Append((uint8)PKT_CHANNEL); - buffer->Append((uint8)(PKT_CHANNEL0+ch)); - buffer->Append((uint8)(PKT_CHAND)); - buffer->Append((uint8)(packet->GetAmbeSize()*8)); - buffer->Append(packet->GetAmbe(), packet->GetAmbeSize()); + uint size = (uint16)packet->GetAmbeSize() + 3; + buffer->clear(); + buffer->Append((uint8)PKT_HEADER); + buffer->Append((uint8)HIBYTE(size)); + buffer->Append((uint8)LOBYTE(size)); + buffer->Append((uint8)PKT_CHANNEL); + buffer->Append((uint8)(PKT_CHANNEL0+ch)); + buffer->Append((uint8)(PKT_CHAND)); + buffer->Append((uint8)(packet->GetAmbeSize()*8)); + buffer->Append(packet->GetAmbe(), packet->GetAmbeSize()); } void CUsb3003Interface::EncodeSpeechPacket(CBuffer *buffer, int ch, CVoicePacket *packet) { - uint16 size = (uint16)packet->GetVoiceSize() + 3; - buffer->clear(); - buffer->Append((uint8)PKT_HEADER); - buffer->Append((uint8)HIBYTE(size)); - buffer->Append((uint8)LOBYTE(size)); - buffer->Append((uint8)PKT_SPEECH); - buffer->Append((uint8)(PKT_CHANNEL0+ch)); - buffer->Append((uint8)PKT_SPEECHD); - buffer->Append((uint8)(packet->GetVoiceSize()/2)); - buffer->Append(packet->GetVoice(), packet->GetVoiceSize()); + uint16 size = (uint16)packet->GetVoiceSize() + 3; + buffer->clear(); + buffer->Append((uint8)PKT_HEADER); + buffer->Append((uint8)HIBYTE(size)); + buffer->Append((uint8)LOBYTE(size)); + buffer->Append((uint8)PKT_SPEECH); + buffer->Append((uint8)(PKT_CHANNEL0+ch)); + buffer->Append((uint8)PKT_SPEECHD); + buffer->Append((uint8)(packet->GetVoiceSize()/2)); + buffer->Append(packet->GetVoice(), packet->GetVoiceSize()); } @@ -202,122 +202,122 @@ void CUsb3003Interface::EncodeSpeechPacket(CBuffer *buffer, int ch, CVoicePacket bool CUsb3003Interface::OpenDevice(void) { - FT_STATUS ftStatus; - int baudrate = 921600; + FT_STATUS ftStatus; + int baudrate = 921600; - //sets serial VID/PID for a Standard Device NOTE: This is for legacy purposes only. This can be ommitted. - ftStatus = FT_SetVIDPID(m_uiVid, m_uiPid); - if (ftStatus != FT_OK) {FTDI_Error((char *)"FT_SetVIDPID", ftStatus ); return false; } + //sets serial VID/PID for a Standard Device NOTE: This is for legacy purposes only. This can be ommitted. + ftStatus = FT_SetVIDPID(m_uiVid, m_uiPid); + if (ftStatus != FT_OK) {FTDI_Error((char *)"FT_SetVIDPID", ftStatus ); return false; } - ftStatus = FT_OpenEx((PVOID)m_szDeviceSerial, FT_OPEN_BY_SERIAL_NUMBER, &m_FtdiHandle); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_OpenEx", ftStatus ); return false; } + ftStatus = FT_OpenEx((PVOID)m_szDeviceSerial, FT_OPEN_BY_SERIAL_NUMBER, &m_FtdiHandle); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_OpenEx", ftStatus ); return false; } - CTimePoint::TaskSleepFor(50); - FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX ); - CTimePoint::TaskSleepFor(50); + CTimePoint::TaskSleepFor(50); + FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX ); + CTimePoint::TaskSleepFor(50); - ftStatus = FT_SetDataCharacteristics(m_FtdiHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE); - if ( ftStatus != FT_OK ) { FTDI_Error((char *)"FT_SetDataCharacteristics", ftStatus ); return false; } + ftStatus = FT_SetDataCharacteristics(m_FtdiHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE); + if ( ftStatus != FT_OK ) { FTDI_Error((char *)"FT_SetDataCharacteristics", ftStatus ); return false; } - ftStatus = FT_SetFlowControl(m_FtdiHandle, FT_FLOW_RTS_CTS, 0x11, 0x13); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetFlowControl", ftStatus ); return false; } + ftStatus = FT_SetFlowControl(m_FtdiHandle, FT_FLOW_RTS_CTS, 0x11, 0x13); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetFlowControl", ftStatus ); return false; } - ftStatus = FT_SetRts (m_FtdiHandle); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetRts", ftStatus ); return false; } + ftStatus = FT_SetRts (m_FtdiHandle); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetRts", ftStatus ); return false; } - //for usb-3012 pull DTR high to take AMBE3003 out of reset. - //for other devices noting is connected to DTR so it is a dont care - ftStatus = FT_ClrDtr(m_FtdiHandle); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_ClrDtr", ftStatus); return false; } + //for usb-3012 pull DTR high to take AMBE3003 out of reset. + //for other devices noting is connected to DTR so it is a dont care + ftStatus = FT_ClrDtr(m_FtdiHandle); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_ClrDtr", ftStatus); return false; } - ftStatus = FT_SetBaudRate(m_FtdiHandle, baudrate ); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetBaudRate", ftStatus ); return false; } + ftStatus = FT_SetBaudRate(m_FtdiHandle, baudrate ); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetBaudRate", ftStatus ); return false; } - ftStatus = FT_SetLatencyTimer(m_FtdiHandle, 4); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetLatencyTimer", ftStatus ); return false; } + ftStatus = FT_SetLatencyTimer(m_FtdiHandle, 4); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetLatencyTimer", ftStatus ); return false; } - ftStatus = FT_SetUSBParameters(m_FtdiHandle, USB3XXX_MAXPACKETSIZE, 0); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetUSBParameters", ftStatus ); return false; } + ftStatus = FT_SetUSBParameters(m_FtdiHandle, USB3XXX_MAXPACKETSIZE, 0); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetUSBParameters", ftStatus ); return false; } - ftStatus = FT_SetTimeouts(m_FtdiHandle, 200, 200 ); - if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetTimeouts", ftStatus ); return false; } + ftStatus = FT_SetTimeouts(m_FtdiHandle, 200, 200 ); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetTimeouts", ftStatus ); return false; } - // done - return true; + // done + return true; } bool CUsb3003Interface::ResetDevice(void) { - bool ok = false; - int len; - char rxpacket[100]; - char zeropacket[10] = - { - 0,0,0,0,0,0,0,0,0,0 - }; - char txpacket[7] = - { - PKT_HEADER, - 0, - 3, - 0, - PKT_RESET, - PKT_PARITYBYTE, - 3 ^ PKT_RESET ^ PKT_PARITYBYTE - }; - - - //the chip might be in a state where it is waiting to receive bytes from a prior incomplete packet. - //first send 350 zeros in case, the chip's receive state is still waiting for characters - //if we send more than needed, the exta characters will just get discarded since they do not match the header byte - //after that we send PKT_RESET to reset the device - //As long as the AMBE3000 is able to receive via uart, this method will succeed in resetting it. - - for ( int i = 0; i < 35 ; i++ ) - { - FTDI_write_packet(m_FtdiHandle, zeropacket, sizeof(zeropacket)); - } - - - // write soft-reset packet - if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) - { - // read reply - len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ); - ok = ((len == 7) && (rxpacket[4] == PKT_READY)); - if ( !ok ) - { - std::cout << "USB-3003 soft reset failed" << std::endl; - } - } - - // done - return ok; + bool ok = false; + int len; + char rxpacket[100]; + char zeropacket[10] = + { + 0,0,0,0,0,0,0,0,0,0 + }; + char txpacket[7] = + { + PKT_HEADER, + 0, + 3, + 0, + PKT_RESET, + PKT_PARITYBYTE, + 3 ^ PKT_RESET ^ PKT_PARITYBYTE + }; + + + //the chip might be in a state where it is waiting to receive bytes from a prior incomplete packet. + //first send 350 zeros in case, the chip's receive state is still waiting for characters + //if we send more than needed, the exta characters will just get discarded since they do not match the header byte + //after that we send PKT_RESET to reset the device + //As long as the AMBE3000 is able to receive via uart, this method will succeed in resetting it. + + for ( int i = 0; i < 35 ; i++ ) + { + FTDI_write_packet(m_FtdiHandle, zeropacket, sizeof(zeropacket)); + } + + + // write soft-reset packet + if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) + { + // read reply + len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ); + ok = ((len == 7) && (rxpacket[4] == PKT_READY)); + if ( !ok ) + { + std::cout << "USB-3003 soft reset failed" << std::endl; + } + } + + // done + return ok; } bool CUsb3003Interface::ConfigureDevice(void) { - bool ok = true; - uint8 pkt_ratep_ambeplus[] = { 0x01,0x30,0x07,0x63,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x48 }; - uint8 pkt_ratep_ambe2plus[] = { 0x04,0x31,0x07,0x54,0x24,0x00,0x00,0x00,0x00,0x00,0x6F,0x48 }; - - // configure each channels for desired codec - for ( int i = 0; i < USB3003_NB_CH; i++ ) - { - switch ( m_uiChCodecs[i] ) - { - case CODEC_AMBEPLUS: - ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambeplus, 0, 0); - break; - case CODEC_AMBE2PLUS: - ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambe2plus, 0, 0); - break; - case CODEC_NONE: - default: - break; - } - } - - // done - return ok; + bool ok = true; + uint8 pkt_ratep_ambeplus[] = { 0x01,0x30,0x07,0x63,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x48 }; + uint8 pkt_ratep_ambe2plus[] = { 0x04,0x31,0x07,0x54,0x24,0x00,0x00,0x00,0x00,0x00,0x6F,0x48 }; + + // configure each channels for desired codec + for ( int i = 0; i < USB3003_NB_CH; i++ ) + { + switch ( m_uiChCodecs[i] ) + { + case CODEC_AMBEPLUS: + ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambeplus, 0, 0); + break; + case CODEC_AMBE2PLUS: + ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambe2plus, 0, 0); + break; + case CODEC_NONE: + default: + break; + } + } + + // done + return ok; } diff --git a/ambed/cusb3003interface.h b/ambed/cusb3003interface.h index 984130e..91bd4ce 100644 --- a/ambed/cusb3003interface.h +++ b/ambed/cusb3003interface.h @@ -40,40 +40,40 @@ class CUsb3003Interface : public CUsb3xxxInterface { public: - // constructors - CUsb3003Interface(uint32, uint32, const char *, const char *); - - // destructor - virtual ~CUsb3003Interface() {} - - // initialization - bool Init(uint8); - - // manage channels - int GetNbChannels(void) const { return USB3003_NB_CH; } - uint8 GetChannelCodec(int) const; - - // manage vocodec channels - CVocodecChannel *GetChannelWithChannelIn(int); - CVocodecChannel *GetChannelWithChannelOut(int); + // constructors + CUsb3003Interface(uint32, uint32, const char *, const char *); + + // destructor + virtual ~CUsb3003Interface() {} + + // initialization + bool Init(uint8); + + // manage channels + int GetNbChannels(void) const { return USB3003_NB_CH; } + uint8 GetChannelCodec(int) const; + + // manage vocodec channels + CVocodecChannel *GetChannelWithChannelIn(int); + CVocodecChannel *GetChannelWithChannelOut(int); protected: - // decoder helper - bool IsValidChannelPacket(const CBuffer &, int *, CAmbePacket *); - bool IsValidSpeechPacket(const CBuffer &, int *, CVoicePacket *); - - // encoder helpers - void EncodeChannelPacket(CBuffer *, int, CAmbePacket *); - void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *); - - // low level - bool OpenDevice(void); - bool ResetDevice(void); - bool ConfigureDevice(void); - int GetDeviceFifoSize(void) const { return 2; } - - // data - uint8 m_uiChCodecs[USB3003_NB_CH]; + // decoder helper + bool IsValidChannelPacket(const CBuffer &, int *, CAmbePacket *); + bool IsValidSpeechPacket(const CBuffer &, int *, CVoicePacket *); + + // encoder helpers + void EncodeChannelPacket(CBuffer *, int, CAmbePacket *); + void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *); + + // low level + bool OpenDevice(void); + bool ResetDevice(void); + bool ConfigureDevice(void); + int GetDeviceFifoSize(void) const { return 2; } + + // data + uint8 m_uiChCodecs[USB3003_NB_CH]; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/ambed/cusb3xxxinterface.cpp b/ambed/cusb3xxxinterface.cpp index 53be523..05c7227 100644 --- a/ambed/cusb3xxxinterface.cpp +++ b/ambed/cusb3xxxinterface.cpp @@ -38,13 +38,13 @@ CUsb3xxxInterface::CUsb3xxxInterface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial) { - m_FtdiHandle = NULL; - m_uiVid = uiVid; - m_uiPid = uiPid; - ::strcpy(m_szDeviceName, szDeviceName); - ::strcpy(m_szDeviceSerial, szDeviceSerial); - m_iSpeechFifolLevel = 0; - m_iChannelFifolLevel = 0; + m_FtdiHandle = NULL; + m_uiVid = uiVid; + m_uiPid = uiPid; + ::strcpy(m_szDeviceName, szDeviceName); + ::strcpy(m_szDeviceSerial, szDeviceSerial); + m_iSpeechFifolLevel = 0; + m_iChannelFifolLevel = 0; } //////////////////////////////////////////////////////////////////////////////////////// @@ -52,19 +52,19 @@ CUsb3xxxInterface::CUsb3xxxInterface(uint32 uiVid, uint32 uiPid, const char *szD CUsb3xxxInterface::~CUsb3xxxInterface() { - // delete m_SpeechQueues - for ( unsigned i = 0; i < m_SpeechQueues.size(); i++ ) - { - delete m_SpeechQueues[i]; - } - m_SpeechQueues.clear(); - - // delete m_ChannelQueues - for ( unsigned i = 0; i < m_ChannelQueues.size(); i++ ) - { - delete m_ChannelQueues[i]; - } - m_ChannelQueues.clear(); + // delete m_SpeechQueues + for ( unsigned i = 0; i < m_SpeechQueues.size(); i++ ) + { + delete m_SpeechQueues[i]; + } + m_SpeechQueues.clear(); + + // delete m_ChannelQueues + for ( unsigned i = 0; i < m_ChannelQueues.size(); i++ ) + { + delete m_ChannelQueues[i]; + } + m_ChannelQueues.clear(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -72,44 +72,44 @@ CUsb3xxxInterface::~CUsb3xxxInterface() bool CUsb3xxxInterface::Init(void) { - bool ok = true; - - // open USB device - std::cout << "Opening " << m_szDeviceName << ":" << m_szDeviceSerial << " device" << std::endl; - if ( ok &= OpenDevice() ) - { - // reset - //std::cout << "Reseting " << m_szDeviceName << "device" << std::endl; - if ( ok &= ResetDevice() ) - { - // read version - //std::cout << "Reading " << m_szDeviceName << " device version" << std::endl; - if ( ok &= ReadDeviceVersion() ) - { - // send configuration packet(s) - //std::cout << "Configuring " << m_szDeviceName << " device" << std::endl; - ok &= DisableParity(); - ok &= ConfigureDevice(); - } - } - } - std::cout << std::endl; - - // create our queues - for ( int i = 0; i < GetNbChannels(); i++ ) - { - m_SpeechQueues.push_back(new CPacketQueue); - m_ChannelQueues.push_back(new CPacketQueue); - } - - // base class - if ( ok ) - { - ok &= CVocodecInterface::Init(); - } - - // done - return ok; + bool ok = true; + + // open USB device + std::cout << "Opening " << m_szDeviceName << ":" << m_szDeviceSerial << " device" << std::endl; + if ( ok &= OpenDevice() ) + { + // reset + //std::cout << "Reseting " << m_szDeviceName << "device" << std::endl; + if ( ok &= ResetDevice() ) + { + // read version + //std::cout << "Reading " << m_szDeviceName << " device version" << std::endl; + if ( ok &= ReadDeviceVersion() ) + { + // send configuration packet(s) + //std::cout << "Configuring " << m_szDeviceName << " device" << std::endl; + ok &= DisableParity(); + ok &= ConfigureDevice(); + } + } + } + std::cout << std::endl; + + // create our queues + for ( int i = 0; i < GetNbChannels(); i++ ) + { + m_SpeechQueues.push_back(new CPacketQueue); + m_ChannelQueues.push_back(new CPacketQueue); + } + + // base class + if ( ok ) + { + ok &= CVocodecInterface::Init(); + } + + // done + return ok; } @@ -118,212 +118,217 @@ bool CUsb3xxxInterface::Init(void) void CUsb3xxxInterface::Task(void) { - CBuffer Buffer; - int iCh; - CPacketQueue *Queue; - CVocodecChannel *Channel; - CAmbePacket AmbePacket; - CVoicePacket VoicePacket; - bool done; - - // TODO : - // preserve packets PIDs, so the transcoded CAmbePacket returned - // to CStream client is garantied to have the same PID - // than the corresponding incoming packet - - // process the device incoming packet - // get all packets from device and push them - // to the relevant clients queues - if ( ReadBuffer(&Buffer) ) - { - if ( IsValidSpeechPacket(Buffer, &iCh, &VoicePacket) ) - { - // update fifo level - // as we get a speech packet, it means that the device - // channel fifo input decreased by 1 - m_iChannelFifolLevel = MAX(0, m_iChannelFifolLevel-1); - - // push back to relevant channel voice queue - // our incoming channel packet has now been through the decoder - // find the coupled channel encoder and push to it's queue - // this is were the DVSI enc-dec channel crossover take place - Channel = GetChannelWithChannelIn(iCh); - if ( Channel != NULL ) - { - Queue = Channel->GetVoiceQueue(); - CVoicePacket *clone = new CVoicePacket(VoicePacket); - Channel->ProcessSignal(*clone); - Queue->push(clone); - Channel->ReleaseVoiceQueue(); - } - } - else if ( IsValidChannelPacket(Buffer, &iCh, &AmbePacket) ) - { - // update fifo level - // as we get a channel packet, it means that the device - // speech fifo input decreased by 1 - m_iSpeechFifolLevel = MAX(0, m_iSpeechFifolLevel-1); - - // push back to relevant channel outcoming queue - // we are done with this packet transcoding - // it's final step - Channel = GetChannelWithChannelOut(iCh); - if ( Channel != NULL ) - { - Queue = Channel->GetPacketQueueOut(); - CAmbePacket *clone = new CAmbePacket(AmbePacket); - Queue->push(clone); - Channel->ReleasePacketQueueOut(); - } - } - } - - // process the streams (channels) incoming queue - // make sure that packets from different channels - // are interlaced so to keep the device fifo busy - do - { - done = true; - for ( unsigned i = 0; i < m_Channels.size(); i++) - { - // get channel - Channel = m_Channels[i]; - - // any packet in voice queue ? - if ( Channel->IsInterfaceOut(this) ) - { - Queue = Channel->GetVoiceQueue(); - if ( !Queue->empty() ) - { - // get packet - CVoicePacket *Packet = (CVoicePacket *)Queue->front(); - Queue->pop(); - // this is second step of transcoding - // we just received from hardware a decoded speech packet - // post it to relevant channel encoder - int i = Channel->GetChannelOut(); - Packet->SetChannel(i); - m_SpeechQueues[i]->push(Packet); - // done - done = false; - } - Channel->ReleaseVoiceQueue(); - } - - // any packet in ambe queue for us ? - if ( Channel->IsInterfaceIn(this) ) - { - Queue = Channel->GetPacketQueueIn(); - if ( !Queue->empty() ) - { - // get packet - CAmbePacket *Packet = (CAmbePacket *)Queue->front(); - Queue->pop(); - // this is first step of transcoding - // a fresh new packet to be transcoded is showing up - // post it to relevant channel decoder - int i = Channel->GetChannelIn(); - Packet->SetChannel(i); - m_ChannelQueues[i]->push(Packet); - // done - done = false; - } - Channel->ReleasePacketQueueIn(); - } - } - } while (!done); - - // process device incoming queues (aka to device) - // interlace speech and channels packets - // and post to final device queue - do - { - done = true; - // loop on all channels - for ( int i = 0; i < GetNbChannels(); i++ ) - { - // speech - if ( !m_SpeechQueues[i]->empty() ) - { - // get packet - CPacket *Packet = m_SpeechQueues[i]->front(); - m_SpeechQueues[i]->pop(); - // and push to device queue - m_DeviceQueue.push(Packet); - // next - done = false; - } - // ambe - if ( !m_ChannelQueues[i]->empty() ) - { - // get packet - CPacket *Packet = m_ChannelQueues[i]->front(); - m_ChannelQueues[i]->pop(); - // and push to device queue - m_DeviceQueue.push(Packet); - // done = false; - } - } - - } while (!done); - - // process device queue to feed hardware - // make sure that device fifo is fed all the time - int fifoSize = GetDeviceFifoSize(); - do - { - done = true; - // if device fifo level is zero (device idle) - // wait that at least 3 packets are in incoming - // queue before restarting - if ( ((m_iSpeechFifolLevel+m_iChannelFifolLevel) > 0) || (m_DeviceQueue.size() >= unsigned(fifoSize+1)) ) - { - // any packet to send ? - if ( m_DeviceQueue.size() > 0 ) - { - // yes, get it - CPacket *Packet = m_DeviceQueue.front(); - if ( Packet->IsVoice() && (m_iSpeechFifolLevel < fifoSize) ) - { - // encode & post - EncodeSpeechPacket(&Buffer, Packet->GetChannel(), (CVoicePacket *)Packet); - WriteBuffer(Buffer); - // remove from queue - m_DeviceQueue.pop(); - // and delete it - delete Packet; - // update fifo level - m_iSpeechFifolLevel++; - // next - done = false; + CBuffer Buffer; + int iCh; + CPacketQueue *Queue; + CVocodecChannel *Channel; + CAmbePacket AmbePacket; + CVoicePacket VoicePacket; + bool done; + + // TODO : + // preserve packets PIDs, so the transcoded CAmbePacket returned + // to CStream client is garantied to have the same PID + // than the corresponding incoming packet + + // process the device incoming packet + // get all packets from device and push them + // to the relevant clients queues + if ( ReadBuffer(&Buffer) ) + { + if ( IsValidSpeechPacket(Buffer, &iCh, &VoicePacket) ) + { + // update fifo level + // as we get a speech packet, it means that the device + // channel fifo input decreased by 1 + m_iChannelFifolLevel = MAX(0, m_iChannelFifolLevel-1); + + // push back to relevant channel voice queue + // our incoming channel packet has now been through the decoder + // find the coupled channel encoder and push to it's queue + // this is were the DVSI enc-dec channel crossover take place + Channel = GetChannelWithChannelIn(iCh); + if ( Channel != NULL ) + { + Queue = Channel->GetVoiceQueue(); + CVoicePacket *clone = new CVoicePacket(VoicePacket); + Channel->ProcessSignal(*clone); + Queue->push(clone); + Channel->ReleaseVoiceQueue(); + } + } + else if ( IsValidChannelPacket(Buffer, &iCh, &AmbePacket) ) + { + // update fifo level + // as we get a channel packet, it means that the device + // speech fifo input decreased by 1 + m_iSpeechFifolLevel = MAX(0, m_iSpeechFifolLevel-1); + + // push back to relevant channel outcoming queue + // we are done with this packet transcoding + // it's final step + Channel = GetChannelWithChannelOut(iCh); + if ( Channel != NULL ) + { + Queue = Channel->GetPacketQueueOut(); + CAmbePacket *clone = new CAmbePacket(AmbePacket); + Queue->push(clone); + Channel->ReleasePacketQueueOut(); + } + } + } + + // process the streams (channels) incoming queue + // make sure that packets from different channels + // are interlaced so to keep the device fifo busy + do + { + done = true; + for ( unsigned i = 0; i < m_Channels.size(); i++) + { + // get channel + Channel = m_Channels[i]; + + // any packet in voice queue ? + if ( Channel->IsInterfaceOut(this) ) + { + Queue = Channel->GetVoiceQueue(); + if ( !Queue->empty() ) + { + // get packet + CVoicePacket *Packet = (CVoicePacket *)Queue->front(); + Queue->pop(); + // this is second step of transcoding + // we just received from hardware a decoded speech packet + // post it to relevant channel encoder + int i = Channel->GetChannelOut(); + Packet->SetChannel(i); + m_SpeechQueues[i]->push(Packet); + // done + done = false; + } + Channel->ReleaseVoiceQueue(); + } + + // any packet in ambe queue for us ? + if ( Channel->IsInterfaceIn(this) ) + { + Queue = Channel->GetPacketQueueIn(); + if ( !Queue->empty() ) + { + // get packet + CAmbePacket *Packet = (CAmbePacket *)Queue->front(); + Queue->pop(); + // this is first step of transcoding + // a fresh new packet to be transcoded is showing up + // post it to relevant channel decoder + int i = Channel->GetChannelIn(); + Packet->SetChannel(i); + m_ChannelQueues[i]->push(Packet); + // done + done = false; + } + Channel->ReleasePacketQueueIn(); + } + } + } + while (!done); + + // process device incoming queues (aka to device) + // interlace speech and channels packets + // and post to final device queue + do + { + done = true; + // loop on all channels + for ( int i = 0; i < GetNbChannels(); i++ ) + { + // speech + if ( !m_SpeechQueues[i]->empty() ) + { + // get packet + CPacket *Packet = m_SpeechQueues[i]->front(); + m_SpeechQueues[i]->pop(); + // and push to device queue + m_DeviceQueue.push(Packet); + // next + done = false; + } + // ambe + if ( !m_ChannelQueues[i]->empty() ) + { + // get packet + CPacket *Packet = m_ChannelQueues[i]->front(); + m_ChannelQueues[i]->pop(); + // and push to device queue + m_DeviceQueue.push(Packet); + // done = false; + } + } + + } + while (!done); + + // process device queue to feed hardware + // make sure that device fifo is fed all the time + int fifoSize = GetDeviceFifoSize(); + do + { + done = true; + // if device fifo level is zero (device idle) + // wait that at least 3 packets are in incoming + // queue before restarting + if ( ((m_iSpeechFifolLevel+m_iChannelFifolLevel) > 0) || (m_DeviceQueue.size() >= unsigned(fifoSize+1)) ) + { + // any packet to send ? + if ( m_DeviceQueue.size() > 0 ) + { + // yes, get it + CPacket *Packet = m_DeviceQueue.front(); + if ( Packet->IsVoice() && (m_iSpeechFifolLevel < fifoSize) ) + { + // encode & post + EncodeSpeechPacket(&Buffer, Packet->GetChannel(), (CVoicePacket *)Packet); + WriteBuffer(Buffer); + // remove from queue + m_DeviceQueue.pop(); + // and delete it + delete Packet; + // update fifo level + m_iSpeechFifolLevel++; + // next + done = false; #ifdef DEBUG_DUMPFILE - g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Sp" << Packet->GetChannel() << "->" << std::endl; std::cout.flush(); + g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Sp" << Packet->GetChannel() << "->" << std::endl; + std::cout.flush(); #endif - } - else if ( Packet->IsAmbe() && (m_iChannelFifolLevel < fifoSize) ) - { - // encode & post - EncodeChannelPacket(&Buffer, Packet->GetChannel(), (CAmbePacket *)Packet); - WriteBuffer(Buffer); - // remove from queue - m_DeviceQueue.pop(); - // and delete it - delete Packet; - // update fifo level - m_iChannelFifolLevel++; - // next - done = false; + } + else if ( Packet->IsAmbe() && (m_iChannelFifolLevel < fifoSize) ) + { + // encode & post + EncodeChannelPacket(&Buffer, Packet->GetChannel(), (CAmbePacket *)Packet); + WriteBuffer(Buffer); + // remove from queue + m_DeviceQueue.pop(); + // and delete it + delete Packet; + // update fifo level + m_iChannelFifolLevel++; + // next + done = false; #ifdef DEBUG_DUMPFILE - g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Ch" << Packet->GetChannel() << "->" << std::endl; std::cout.flush(); + g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Ch" << Packet->GetChannel() << "->" << std::endl; + std::cout.flush(); #endif - } + } - } - } - } while (!done); + } + } + } + while (!done); - // and wait a bit - CTimePoint::TaskSleepFor(2); + // and wait a bit + CTimePoint::TaskSleepFor(2); } @@ -332,100 +337,100 @@ void CUsb3xxxInterface::Task(void) bool CUsb3xxxInterface::ReadDeviceVersion(void) { - bool ok = false; - int i, len; - char rxpacket[128]; - char txpacket[8] = - { - PKT_HEADER, - 0, - 4, - PKT_CONTROL, - PKT_PRODID, - PKT_VERSTRING, - PKT_PARITYBYTE, - 4 ^ PKT_CONTROL ^ PKT_PRODID ^ PKT_VERSTRING ^ PKT_PARITYBYTE - }; - - // write packet - if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) - { - // read reply - len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4; - ok = (len != 0); - //we succeed in reading a packet, print it out - std::cout << "ReadDeviceVersion : "; - for ( i = 4; i < len+4 ; i++ ) - { - std::cout << (char)(rxpacket[i] & 0x00ff); - } - std::cout << std::endl; - } - return ok; + bool ok = false; + int i, len; + char rxpacket[128]; + char txpacket[8] = + { + PKT_HEADER, + 0, + 4, + PKT_CONTROL, + PKT_PRODID, + PKT_VERSTRING, + PKT_PARITYBYTE, + 4 ^ PKT_CONTROL ^ PKT_PRODID ^ PKT_VERSTRING ^ PKT_PARITYBYTE + }; + + // write packet + if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) + { + // read reply + len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4; + ok = (len != 0); + //we succeed in reading a packet, print it out + std::cout << "ReadDeviceVersion : "; + for ( i = 4; i < len+4 ; i++ ) + { + std::cout << (char)(rxpacket[i] & 0x00ff); + } + std::cout << std::endl; + } + return ok; } bool CUsb3xxxInterface::DisableParity(void) { - bool ok = false; - int len; - char rxpacket[16]; - char txpacket[8] = - { - PKT_HEADER, - 0, - 4, - PKT_CONTROL, - PKT_PARITYMODE,0x00, - PKT_PARITYBYTE, - 4 ^ PKT_CONTROL ^ PKT_PARITYMODE ^ 0x00 ^ PKT_PARITYBYTE - }; - - // write packet - if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) - { - // read reply - len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4; - ok = ((len == 2) && (rxpacket[4] == PKT_PARITYMODE) &&(rxpacket[5] == 0x00) ); - } - return ok; + bool ok = false; + int len; + char rxpacket[16]; + char txpacket[8] = + { + PKT_HEADER, + 0, + 4, + PKT_CONTROL, + PKT_PARITYMODE,0x00, + PKT_PARITYBYTE, + 4 ^ PKT_CONTROL ^ PKT_PARITYMODE ^ 0x00 ^ PKT_PARITYBYTE + }; + + // write packet + if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) + { + // read reply + len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4; + ok = ((len == 2) && (rxpacket[4] == PKT_PARITYMODE) &&(rxpacket[5] == 0x00) ); + } + return ok; } bool CUsb3xxxInterface::ConfigureChannel(uint8 pkt_ch, const uint8 *pkt_ratep, int in_gain, int out_gain) { - bool ok = false; - int len; - char rxpacket[64]; - char txpacket[] = - { - PKT_HEADER, - 0, - 33, - PKT_CONTROL, - 0x00, - PKT_ECMODE, 0x00,0x00, - PKT_DCMODE, 0x00,0x00, - PKT_COMPAND,0x00, - PKT_RATEP, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - PKT_CHANFMT,0x00,0x00, - PKT_SPCHFMT,0x00,0x00, - PKT_GAIN, 0x00,0x00, - PKT_INIT, 0x03 - }; - - // update packet content - txpacket[4] = pkt_ch; - :: memcpy(&(txpacket[14]), pkt_ratep, 12); - txpacket[33] = (uint8)(signed char)in_gain; - txpacket[34] = (uint8)(signed char)out_gain; - - // write packet - if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) - { - // read reply - len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4; - ok = ((len == 18) && (rxpacket[20] == PKT_INIT) &&(rxpacket[21] == 0x00) ); - } - return ok; + bool ok = false; + int len; + char rxpacket[64]; + char txpacket[] = + { + PKT_HEADER, + 0, + 33, + PKT_CONTROL, + 0x00, + PKT_ECMODE, 0x00,0x00, + PKT_DCMODE, 0x00,0x00, + PKT_COMPAND,0x00, + PKT_RATEP, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + PKT_CHANFMT,0x00,0x00, + PKT_SPCHFMT,0x00,0x00, + PKT_GAIN, 0x00,0x00, + PKT_INIT, 0x03 + }; + + // update packet content + txpacket[4] = pkt_ch; + :: memcpy(&(txpacket[14]), pkt_ratep, 12); + txpacket[33] = (uint8)(signed char)in_gain; + txpacket[34] = (uint8)(signed char)out_gain; + + // write packet + if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) + { + // read reply + len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4; + ok = ((len == 18) && (rxpacket[20] == PKT_INIT) &&(rxpacket[21] == 0x00) ); + } + return ok; } @@ -435,89 +440,89 @@ bool CUsb3xxxInterface::ConfigureChannel(uint8 pkt_ch, const uint8 *pkt_ratep, i bool CUsb3xxxInterface::ReadBuffer(CBuffer *buffer) { - bool ok = false; - int n; - - // any byte in tx queue ? - if ( FT_GetQueueStatus(m_FtdiHandle, (LPDWORD)&n) == FT_OK ) - { - //if ( (FT_GetQueueStatus(m_FtdiHandle, (LPDWORD)&n) == FT_OK) && (n != 0) ) - if ( n != 0 ) - { - buffer->clear(); - buffer->resize(USB3XXX_MAXPACKETSIZE); - n = FTDI_read_packet(m_FtdiHandle, (char *)buffer->data(), USB3XXX_MAXPACKETSIZE); - buffer->resize(n); - ok = (n != 0); - } - } - return ok; + bool ok = false; + int n; + + // any byte in tx queue ? + if ( FT_GetQueueStatus(m_FtdiHandle, (LPDWORD)&n) == FT_OK ) + { + //if ( (FT_GetQueueStatus(m_FtdiHandle, (LPDWORD)&n) == FT_OK) && (n != 0) ) + if ( n != 0 ) + { + buffer->clear(); + buffer->resize(USB3XXX_MAXPACKETSIZE); + n = FTDI_read_packet(m_FtdiHandle, (char *)buffer->data(), USB3XXX_MAXPACKETSIZE); + buffer->resize(n); + ok = (n != 0); + } + } + return ok; } bool CUsb3xxxInterface::WriteBuffer(const CBuffer &buffer) { - return FTDI_write_packet(m_FtdiHandle, (const char *)buffer.data(), (int)buffer.size()); + return FTDI_write_packet(m_FtdiHandle, (const char *)buffer.data(), (int)buffer.size()); } int CUsb3xxxInterface::FTDI_read_packet(FT_HANDLE ftHandle, char *pkt, int maxlen) { - int plen; - - // first read 4 bytes header - if ( FTDI_read_bytes(ftHandle, pkt, 4) ) - { - // get payload length - plen = (pkt[1] & 0x00ff); - plen <<= 8; - plen += (pkt[2] & 0x00ff); - // check buffer length - if (plen+4 > maxlen) - { - std::cout << "FTDI_read_packet supplied buffer is not large enough for packet" << std::endl; - FT_Purge(ftHandle, FT_PURGE_RX); - return 0; - } - // and get payload - if ( FTDI_read_bytes(ftHandle, &pkt[4], plen) ) - { - return plen+4; - } - } - return 0; + int plen; + + // first read 4 bytes header + if ( FTDI_read_bytes(ftHandle, pkt, 4) ) + { + // get payload length + plen = (pkt[1] & 0x00ff); + plen <<= 8; + plen += (pkt[2] & 0x00ff); + // check buffer length + if (plen+4 > maxlen) + { + std::cout << "FTDI_read_packet supplied buffer is not large enough for packet" << std::endl; + FT_Purge(ftHandle, FT_PURGE_RX); + return 0; + } + // and get payload + if ( FTDI_read_bytes(ftHandle, &pkt[4], plen) ) + { + return plen+4; + } + } + return 0; } bool CUsb3xxxInterface::FTDI_read_bytes(FT_HANDLE ftHandle, char *buffer, int len) { - // this relies on FT_SetTimouts() mechanism - int n; - bool ok = false; - - ok = (FT_Read(ftHandle, (LPVOID)buffer, len, (LPDWORD)&n) == FT_OK) && (n == len); - if ( !ok ) - { - //FT_Purge(ftHandle, FT_PURGE_RX); - std::cout << "FTDI_read_bytes(" << len << ") failed : " << n << std::endl; - } - - return ok; + // this relies on FT_SetTimouts() mechanism + int n; + bool ok = false; + + ok = (FT_Read(ftHandle, (LPVOID)buffer, len, (LPDWORD)&n) == FT_OK) && (n == len); + if ( !ok ) + { + //FT_Purge(ftHandle, FT_PURGE_RX); + std::cout << "FTDI_read_bytes(" << len << ") failed : " << n << std::endl; + } + + return ok; } bool CUsb3xxxInterface::FTDI_write_packet(FT_HANDLE ft_handle, const char *pkt, int len) { - FT_STATUS ftStatus; - bool ok = true; - int nwritten; - - if ( len > 0 ) - { - ftStatus = FT_Write(m_FtdiHandle, (LPVOID *)pkt, (DWORD)len, (LPDWORD)&nwritten); - ok = (ftStatus == FT_OK) && (len == nwritten); - if ( !ok ) - { - FTDI_Error((char *)"FT_Write", ftStatus); - } - } - return ok; + FT_STATUS ftStatus; + bool ok = true; + int nwritten; + + if ( len > 0 ) + { + ftStatus = FT_Write(m_FtdiHandle, (LPVOID *)pkt, (DWORD)len, (LPDWORD)&nwritten); + ok = (ftStatus == FT_OK) && (len == nwritten); + if ( !ok ) + { + FTDI_Error((char *)"FT_Write", ftStatus); + } + } + return ok; } //////////////////////////////////////////////////////////////////////////////////////// @@ -525,5 +530,5 @@ bool CUsb3xxxInterface::FTDI_write_packet(FT_HANDLE ft_handle, const char *pkt, void CUsb3xxxInterface::FTDI_Error(char *func_string, FT_STATUS ftStatus) { - std::cout << "FTDI function " << func_string << " error " << (int)ftStatus << std::endl; + std::cout << "FTDI function " << func_string << " error " << (int)ftStatus << std::endl; } diff --git a/ambed/cusb3xxxinterface.h b/ambed/cusb3xxxinterface.h index d7dd3cf..d116ca6 100644 --- a/ambed/cusb3xxxinterface.h +++ b/ambed/cusb3xxxinterface.h @@ -72,64 +72,64 @@ class CUsb3xxxInterface : public CVocodecInterface { public: - // constructors - CUsb3xxxInterface(uint32, uint32, const char *, const char *); - - // destructor - virtual ~CUsb3xxxInterface(); - - // initialization - bool Init(void); - - // get - const char *GetName(void) const { return m_szDeviceName; } - const char *GetSerial(void) const { return m_szDeviceSerial; } - - // task - void Task(void); + // constructors + CUsb3xxxInterface(uint32, uint32, const char *, const char *); + + // destructor + virtual ~CUsb3xxxInterface(); + + // initialization + bool Init(void); + + // get + const char *GetName(void) const { return m_szDeviceName; } + const char *GetSerial(void) const { return m_szDeviceSerial; } + + // task + void Task(void); protected: - // decoder helper - virtual bool IsValidChannelPacket(const CBuffer &, int *, CAmbePacket *) { return false; } - virtual bool IsValidSpeechPacket(const CBuffer &, int *, CVoicePacket *) { return false; } - - // encoder helpers - virtual void EncodeChannelPacket(CBuffer *, int, CAmbePacket *) {} - virtual void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *) {} - - // low level - virtual bool OpenDevice(void) { return false; } - virtual bool ResetDevice(void) { return false; } - bool ReadDeviceVersion(void); - bool DisableParity(void); - virtual bool ConfigureDevice(void) { return false; } - bool ConfigureChannel(uint8, const uint8 *, int, int); - virtual int GetDeviceFifoSize(void) const { return 1; } - - // io level - bool ReadBuffer(CBuffer *); - bool WriteBuffer(const CBuffer &); - int FTDI_read_packet(FT_HANDLE, char *, int); - bool FTDI_read_bytes(FT_HANDLE, char *, int); - bool FTDI_write_packet(FT_HANDLE, const char *, int); - - // error reporting - void FTDI_Error(char *, FT_STATUS); - + // decoder helper + virtual bool IsValidChannelPacket(const CBuffer &, int *, CAmbePacket *) { return false; } + virtual bool IsValidSpeechPacket(const CBuffer &, int *, CVoicePacket *) { return false; } + + // encoder helpers + virtual void EncodeChannelPacket(CBuffer *, int, CAmbePacket *) {} + virtual void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *) {} + + // low level + virtual bool OpenDevice(void) { return false; } + virtual bool ResetDevice(void) { return false; } + bool ReadDeviceVersion(void); + bool DisableParity(void); + virtual bool ConfigureDevice(void) { return false; } + bool ConfigureChannel(uint8, const uint8 *, int, int); + virtual int GetDeviceFifoSize(void) const { return 1; } + + // io level + bool ReadBuffer(CBuffer *); + bool WriteBuffer(const CBuffer &); + int FTDI_read_packet(FT_HANDLE, char *, int); + bool FTDI_read_bytes(FT_HANDLE, char *, int); + bool FTDI_write_packet(FT_HANDLE, const char *, int); + + // error reporting + void FTDI_Error(char *, FT_STATUS); + protected: - // data - uint32 m_uiVid; - uint32 m_uiPid; - char m_szDeviceName[FTDI_MAX_STRINGLENGTH]; - char m_szDeviceSerial[FTDI_MAX_STRINGLENGTH]; - FT_HANDLE m_FtdiHandle; - - // queue - std::vector m_SpeechQueues; - std::vector m_ChannelQueues; - CPacketQueue m_DeviceQueue; - int m_iSpeechFifolLevel; - int m_iChannelFifolLevel; + // data + uint32 m_uiVid; + uint32 m_uiPid; + char m_szDeviceName[FTDI_MAX_STRINGLENGTH]; + char m_szDeviceSerial[FTDI_MAX_STRINGLENGTH]; + FT_HANDLE m_FtdiHandle; + + // queue + std::vector m_SpeechQueues; + std::vector m_ChannelQueues; + CPacketQueue m_DeviceQueue; + int m_iSpeechFifolLevel; + int m_iChannelFifolLevel; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/ambed/cvocodecchannel.cpp b/ambed/cvocodecchannel.cpp index 7a10d41..204243d 100644 --- a/ambed/cvocodecchannel.cpp +++ b/ambed/cvocodecchannel.cpp @@ -32,13 +32,13 @@ CVocodecChannel::CVocodecChannel(CVocodecInterface *InterfaceIn, int iChIn, CVocodecInterface *InterfaceOut, int iChOut, int iSpeechGain) { - m_bOpen = false; - m_InterfaceIn = InterfaceIn; - m_iChannelIn = iChIn; - m_InterfaceOut = InterfaceOut; - m_iChannelOut = iChOut; - m_iSpeechGain = iSpeechGain; - m_signalProcessor = new CSignalProcessor((float)m_iSpeechGain); + m_bOpen = false; + m_InterfaceIn = InterfaceIn; + m_iChannelIn = iChIn; + m_InterfaceOut = InterfaceOut; + m_iChannelOut = iChOut; + m_iSpeechGain = iSpeechGain; + m_signalProcessor = new CSignalProcessor((float)m_iSpeechGain); } //////////////////////////////////////////////////////////////////////////////////////// @@ -46,8 +46,8 @@ CVocodecChannel::CVocodecChannel(CVocodecInterface *InterfaceIn, int iChIn, CVoc CVocodecChannel::~CVocodecChannel() { - PurgeAllQueues(); - delete m_signalProcessor; + PurgeAllQueues(); + delete m_signalProcessor; } //////////////////////////////////////////////////////////////////////////////////////// @@ -55,29 +55,29 @@ CVocodecChannel::~CVocodecChannel() bool CVocodecChannel::Open(void) { - bool ok = false; - if ( !m_bOpen ) - { - m_bOpen = true; - ok = true; - PurgeAllQueues(); - std::cout << "Vocodec channel " << - m_InterfaceIn->GetName() << ":" << (int)m_iChannelIn << " -> " << - m_InterfaceOut->GetName() << ":" << (int)m_iChannelOut << " open" << std::endl; - } - return ok; + bool ok = false; + if ( !m_bOpen ) + { + m_bOpen = true; + ok = true; + PurgeAllQueues(); + std::cout << "Vocodec channel " << + m_InterfaceIn->GetName() << ":" << (int)m_iChannelIn << " -> " << + m_InterfaceOut->GetName() << ":" << (int)m_iChannelOut << " open" << std::endl; + } + return ok; } void CVocodecChannel::Close(void) { - if ( m_bOpen ) - { - m_bOpen = false; - PurgeAllQueues(); - std::cout << "Vocodec channel " << - m_InterfaceIn->GetName() << ":" << (int)m_iChannelIn << " -> " << - m_InterfaceOut->GetName() << ":" << (int)m_iChannelOut << " closed" << std::endl; - } + if ( m_bOpen ) + { + m_bOpen = false; + PurgeAllQueues(); + std::cout << "Vocodec channel " << + m_InterfaceIn->GetName() << ":" << (int)m_iChannelIn << " -> " << + m_InterfaceOut->GetName() << ":" << (int)m_iChannelOut << " closed" << std::endl; + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -85,12 +85,12 @@ void CVocodecChannel::Close(void) uint8 CVocodecChannel::GetCodecIn(void) const { - return m_InterfaceIn->GetChannelCodec(m_iChannelIn); + return m_InterfaceIn->GetChannelCodec(m_iChannelIn); } uint8 CVocodecChannel::GetCodecOut(void) const { - return m_InterfaceOut->GetChannelCodec(m_iChannelOut); + return m_InterfaceOut->GetChannelCodec(m_iChannelOut); } //////////////////////////////////////////////////////////////////////////////////////// @@ -98,7 +98,7 @@ uint8 CVocodecChannel::GetCodecOut(void) const void CVocodecChannel::ProcessSignal(CVoicePacket& voicePacket) { - m_signalProcessor->Process(voicePacket.GetVoice(), voicePacket.GetVoiceSize()); + m_signalProcessor->Process(voicePacket.GetVoice(), voicePacket.GetVoiceSize()); } @@ -107,12 +107,12 @@ void CVocodecChannel::ProcessSignal(CVoicePacket& voicePacket) void CVocodecChannel::PurgeAllQueues(void) { - GetPacketQueueIn()->Purge(); - ReleasePacketQueueIn(); - GetPacketQueueOut()->Purge(); - ReleasePacketQueueOut(); - GetVoiceQueue()->Purge(); - ReleaseVoiceQueue(); + GetPacketQueueIn()->Purge(); + ReleasePacketQueueIn(); + GetPacketQueueOut()->Purge(); + ReleasePacketQueueOut(); + GetVoiceQueue()->Purge(); + ReleaseVoiceQueue(); } diff --git a/ambed/cvocodecchannel.h b/ambed/cvocodecchannel.h index 9726b9d..23e6254 100644 --- a/ambed/cvocodecchannel.h +++ b/ambed/cvocodecchannel.h @@ -38,67 +38,67 @@ class CVocodecInterface; class CVocodecChannel { public: - // constructors - CVocodecChannel(CVocodecInterface *, int, CVocodecInterface *, int, int); - - // destructor - virtual ~CVocodecChannel(); - - // open & close - bool Open(void); - bool IsOpen(void) const { return m_bOpen; } - void Close(void); - - // get - uint8 GetCodecIn(void) const; - uint8 GetCodecOut(void) const; - int GetChannelIn(void) const { return m_iChannelIn; } - int GetChannelOut(void) const { return m_iChannelOut; } - int GetSpeechGain(void) const { return m_iSpeechGain; } - - //Processing - void ProcessSignal(CVoicePacket& voicePacket); - - // interfaces - bool IsInterfaceIn(const CVocodecInterface *interface) { return (interface == m_InterfaceIn); } - bool IsInterfaceOut(const CVocodecInterface *interface) { return (interface == m_InterfaceOut); } - - // queues - CPacketQueue *GetPacketQueueIn(void) { m_QueuePacketIn.Lock(); return &m_QueuePacketIn; } - void ReleasePacketQueueIn(void) { m_QueuePacketIn.Unlock(); } - CPacketQueue *GetPacketQueueOut(void) { m_QueuePacketOut.Lock(); return &m_QueuePacketOut; } - void ReleasePacketQueueOut(void) { m_QueuePacketOut.Unlock(); } - CPacketQueue *GetVoiceQueue(void) { m_QueueVoice.Lock(); return &m_QueueVoice; } - void ReleaseVoiceQueue(void) { m_QueueVoice.Unlock(); } - - // operators - //virtual bool operator ==(const CVocodecChannel &) const { return false; } - + // constructors + CVocodecChannel(CVocodecInterface *, int, CVocodecInterface *, int, int); + + // destructor + virtual ~CVocodecChannel(); + + // open & close + bool Open(void); + bool IsOpen(void) const { return m_bOpen; } + void Close(void); + + // get + uint8 GetCodecIn(void) const; + uint8 GetCodecOut(void) const; + int GetChannelIn(void) const { return m_iChannelIn; } + int GetChannelOut(void) const { return m_iChannelOut; } + int GetSpeechGain(void) const { return m_iSpeechGain; } + + //Processing + void ProcessSignal(CVoicePacket& voicePacket); + + // interfaces + bool IsInterfaceIn(const CVocodecInterface *interface) { return (interface == m_InterfaceIn); } + bool IsInterfaceOut(const CVocodecInterface *interface) { return (interface == m_InterfaceOut); } + + // queues + CPacketQueue *GetPacketQueueIn(void) { m_QueuePacketIn.Lock(); return &m_QueuePacketIn; } + void ReleasePacketQueueIn(void) { m_QueuePacketIn.Unlock(); } + CPacketQueue *GetPacketQueueOut(void) { m_QueuePacketOut.Lock(); return &m_QueuePacketOut; } + void ReleasePacketQueueOut(void) { m_QueuePacketOut.Unlock(); } + CPacketQueue *GetVoiceQueue(void) { m_QueueVoice.Lock(); return &m_QueueVoice; } + void ReleaseVoiceQueue(void) { m_QueueVoice.Unlock(); } + + // operators + //virtual bool operator ==(const CVocodecChannel &) const { return false; } + protected: - // queues helpers - void PurgeAllQueues(void); - + // queues helpers + void PurgeAllQueues(void); + protected: - // status - bool m_bOpen; - - // connected interfaces - CVocodecInterface *m_InterfaceIn; - int m_iChannelIn; - CVocodecInterface *m_InterfaceOut; - int m_iChannelOut; - - // ambe queues - CPacketQueue m_QueuePacketIn; - CPacketQueue m_QueuePacketOut; - // voice queue - CPacketQueue m_QueueVoice; - - // settings - int m_iSpeechGain; - + // status + bool m_bOpen; + + // connected interfaces + CVocodecInterface *m_InterfaceIn; + int m_iChannelIn; + CVocodecInterface *m_InterfaceOut; + int m_iChannelOut; + + // ambe queues + CPacketQueue m_QueuePacketIn; + CPacketQueue m_QueuePacketOut; + // voice queue + CPacketQueue m_QueueVoice; + + // settings + int m_iSpeechGain; + private: - CSignalProcessor* m_signalProcessor; + CSignalProcessor* m_signalProcessor; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/ambed/cvocodecinterface.cpp b/ambed/cvocodecinterface.cpp index e730e09..6d1a60d 100644 --- a/ambed/cvocodecinterface.cpp +++ b/ambed/cvocodecinterface.cpp @@ -33,9 +33,9 @@ CVocodecInterface::CVocodecInterface() { - m_Channels.reserve(5); - m_bStopThread = false; - m_pThread = NULL; + m_Channels.reserve(5); + m_bStopThread = false; + m_pThread = NULL; } //////////////////////////////////////////////////////////////////////////////////////// @@ -43,17 +43,17 @@ CVocodecInterface::CVocodecInterface() CVocodecInterface::~CVocodecInterface() { - // empty channel array - // chennels are deleted by their owner (CVocodecs) - m_Channels.clear(); - - // stop thread - m_bStopThread = true; - if ( m_pThread != NULL ) - { - m_pThread->join(); - delete m_pThread; - } + // empty channel array + // chennels are deleted by their owner (CVocodecs) + m_Channels.clear(); + + // stop thread + m_bStopThread = true; + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -61,14 +61,14 @@ CVocodecInterface::~CVocodecInterface() bool CVocodecInterface::Init(void) { - // reset stop flag - m_bStopThread = false; - - // start thread; - m_pThread = new std::thread(CVocodecInterface::Thread, this); - - // done - return true; + // reset stop flag + m_bStopThread = false; + + // start thread; + m_pThread = new std::thread(CVocodecInterface::Thread, this); + + // done + return true; } @@ -77,10 +77,10 @@ bool CVocodecInterface::Init(void) void CVocodecInterface::Thread(CVocodecInterface *This) { - while ( !This->m_bStopThread ) - { - This->Task(); - } + while ( !This->m_bStopThread ) + { + This->Task(); + } } @@ -89,7 +89,7 @@ void CVocodecInterface::Thread(CVocodecInterface *This) void CVocodecInterface::AddChannel(CVocodecChannel *Channel) { - m_Channels.push_back(Channel); + m_Channels.push_back(Channel); } diff --git a/ambed/cvocodecinterface.h b/ambed/cvocodecinterface.h index 66f8fbb..d73a5c3 100644 --- a/ambed/cvocodecinterface.h +++ b/ambed/cvocodecinterface.h @@ -35,40 +35,40 @@ class CVocodecs; class CVocodecInterface { public: - // constructors - CVocodecInterface(); - - // destructor - virtual ~CVocodecInterface(); - - // initialization - virtual bool Init(void); - - // get - virtual const char *GetName(void) const { return ""; } - - // manage channels - virtual int GetNbChannels(void) const { return 0; } - virtual uint8 GetChannelCodec(int) const { return CODEC_NONE; } - void AddChannel(CVocodecChannel *); - virtual CVocodecChannel *GetChannelWithChannelIn(int) { return NULL; } - virtual CVocodecChannel *GetChannelWithChannelOut(int) { return NULL; } - - // task - static void Thread(CVocodecInterface *); - virtual void Task(void) {}; + // constructors + CVocodecInterface(); + + // destructor + virtual ~CVocodecInterface(); + + // initialization + virtual bool Init(void); + + // get + virtual const char *GetName(void) const { return ""; } + + // manage channels + virtual int GetNbChannels(void) const { return 0; } + virtual uint8 GetChannelCodec(int) const { return CODEC_NONE; } + void AddChannel(CVocodecChannel *); + virtual CVocodecChannel *GetChannelWithChannelIn(int) { return NULL; } + virtual CVocodecChannel *GetChannelWithChannelOut(int) { return NULL; } + + // task + static void Thread(CVocodecInterface *); + virtual void Task(void) {}; + + // operators + virtual bool operator ==(const CVocodecInterface &) const { return false; } - // operators - virtual bool operator ==(const CVocodecInterface &) const { return false; } - protected: - // array of channels - std::vector m_Channels; - - // thread - bool m_bStopThread; - std::thread *m_pThread; - + // array of channels + std::vector m_Channels; + + // thread + bool m_bStopThread; + std::thread *m_pThread; + }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/ambed/cvocodecs.cpp b/ambed/cvocodecs.cpp index 7030f32..ad6d6a4 100644 --- a/ambed/cvocodecs.cpp +++ b/ambed/cvocodecs.cpp @@ -36,9 +36,9 @@ CVocodecs g_Vocodecs; CVocodecs::CVocodecs() { - m_Interfaces.reserve(5); - m_Channels.reserve(20); - m_FtdiDeviceDescrs.reserve(10); + m_Interfaces.reserve(5); + m_Channels.reserve(20); + m_FtdiDeviceDescrs.reserve(10); } //////////////////////////////////////////////////////////////////////////////////////// @@ -46,33 +46,33 @@ CVocodecs::CVocodecs() CVocodecs::~CVocodecs() { - // delete channels - m_MutexChannels.lock(); - { - for ( unsigned i = 0; i < m_Channels.size(); i++ ) - { - delete m_Channels[i]; - } - m_Channels.clear(); - } - m_MutexChannels.unlock(); + // delete channels + m_MutexChannels.lock(); + { + for ( unsigned i = 0; i < m_Channels.size(); i++ ) + { + delete m_Channels[i]; + } + m_Channels.clear(); + } + m_MutexChannels.unlock(); - // delete interfaces - m_MutexInterfaces.lock(); - { - for ( unsigned i = 0; i < m_Interfaces.size(); i++ ) - { - delete m_Interfaces[i]; - } - m_Interfaces.clear(); - } - m_MutexInterfaces.unlock(); + // delete interfaces + m_MutexInterfaces.lock(); + { + for ( unsigned i = 0; i < m_Interfaces.size(); i++ ) + { + delete m_Interfaces[i]; + } + m_Interfaces.clear(); + } + m_MutexInterfaces.unlock(); - // delete ftdi device descriptors - for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) - { - delete m_FtdiDeviceDescrs[i]; - } + // delete ftdi device descriptors + for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) + { + delete m_FtdiDeviceDescrs[i]; + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -80,176 +80,176 @@ CVocodecs::~CVocodecs() bool CVocodecs::Init(void) { - bool ok = true; - int iNbCh = 0; + bool ok = true; + int iNbCh = 0; - // discover and add vocodecs interfaces - DiscoverFtdiDevices(); + // discover and add vocodecs interfaces + DiscoverFtdiDevices(); - // and create interfaces for the discovered devices - // first handle all even number of channels devices - std::vector Multi3003DevicesChs; - for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) - { - CFtdiDeviceDescr *descr = m_FtdiDeviceDescrs[i]; - if ( !descr->IsUsed() && IsEven(descr->GetNbChannels()) ) - { - // create the object - iNbCh += CFtdiDeviceDescr::CreateInterface(descr, &Multi3003DevicesChs); - // and flag as used - descr->SetUsed(true); - } - } - // next handle all single channel devices. - // they must be handeled in pair, or in pair with another - // even number of channels device. - std::vector PairsOf3000DevicesChs; - for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) - { - CFtdiDeviceDescr *descr1 = m_FtdiDeviceDescrs[i]; - CFtdiDeviceDescr *descr2 = NULL; - if ( !descr1->IsUsed() && (descr1->GetNbChannels() == 1) ) - { - // any other single channel device to pair with ? - bool found = false; - unsigned j = i+1; - while ( !found && (j < m_FtdiDeviceDescrs.size()) ) - { - descr2 = m_FtdiDeviceDescrs[j]; - found = (!descr2->IsUsed() && (descr2->GetNbChannels() == 1)); - j++; - } - // found one ? - if ( found ) - { - // yes, create and pair both interfaces - iNbCh += CFtdiDeviceDescr::CreateInterfacePair(descr1, descr2, &PairsOf3000DevicesChs); - // and flag as used - descr1->SetUsed(true); - descr2->SetUsed(true); - } - } - } - // now we should have only remaining the 3 channels device(s) - // and possibly an unique single channel device - std::vector Single3003DeviceChannels; - for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) - { - CFtdiDeviceDescr *descr1 = m_FtdiDeviceDescrs[i]; - CFtdiDeviceDescr *descr2 = NULL; - if ( !descr1->IsUsed() && (descr1->GetNbChannels() == 3) ) - { - // any other 3 channel device to pair with ? - bool found = false; - unsigned j = i+1; - while ( !found && (j < m_FtdiDeviceDescrs.size()) ) - { - descr2 = m_FtdiDeviceDescrs[j]; - found = (!descr2->IsUsed() && (descr2->GetNbChannels() == 3)); - j++; - } - // found one ? - if ( found ) - { - // yes, create and pair both interfaces - iNbCh += CFtdiDeviceDescr::CreateInterfacePair(descr1, descr2, &Multi3003DevicesChs); - // and flag as used - descr1->SetUsed(true); - descr2->SetUsed(true); - } - } - } - // at this point we should have only remaining an unique 3 channels - // and or a unique single channel - std::vector Combined3003And3000DeviceChannels; - for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) - { - CFtdiDeviceDescr *descr1 = m_FtdiDeviceDescrs[i]; - CFtdiDeviceDescr *descr2 = NULL; - // Any 3003 ? - if ( !descr1->IsUsed() && (descr1->GetNbChannels() == 3) ) - { - // any single channel device to pair with ? - bool found = false; - unsigned j = 0; - while ( !found && (j < m_FtdiDeviceDescrs.size()) ) - { - descr2 = m_FtdiDeviceDescrs[j]; - found = ((descr1 != descr2) && !descr2->IsUsed() && (descr2->GetNbChannels() == 1)); - j++; - } - // found one ? - if ( found ) - { - // yes, create and pair both interfaces - iNbCh += CFtdiDeviceDescr::CreateInterfacePair(descr1, descr2, &Combined3003And3000DeviceChannels); - // and flag as used - descr1->SetUsed(true); - descr2->SetUsed(true); - } - else - { - // no, just create a standalone 3003 interface - iNbCh += CFtdiDeviceDescr::CreateInterface(descr1, &Single3003DeviceChannels); - // and flag as used - descr1->SetUsed(true); - } - } - } - // at this point we should possible only have unique 3003 remaining + // and create interfaces for the discovered devices + // first handle all even number of channels devices + std::vector Multi3003DevicesChs; + for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) + { + CFtdiDeviceDescr *descr = m_FtdiDeviceDescrs[i]; + if ( !descr->IsUsed() && IsEven(descr->GetNbChannels()) ) + { + // create the object + iNbCh += CFtdiDeviceDescr::CreateInterface(descr, &Multi3003DevicesChs); + // and flag as used + descr->SetUsed(true); + } + } + // next handle all single channel devices. + // they must be handeled in pair, or in pair with another + // even number of channels device. + std::vector PairsOf3000DevicesChs; + for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) + { + CFtdiDeviceDescr *descr1 = m_FtdiDeviceDescrs[i]; + CFtdiDeviceDescr *descr2 = NULL; + if ( !descr1->IsUsed() && (descr1->GetNbChannels() == 1) ) + { + // any other single channel device to pair with ? + bool found = false; + unsigned j = i+1; + while ( !found && (j < m_FtdiDeviceDescrs.size()) ) + { + descr2 = m_FtdiDeviceDescrs[j]; + found = (!descr2->IsUsed() && (descr2->GetNbChannels() == 1)); + j++; + } + // found one ? + if ( found ) + { + // yes, create and pair both interfaces + iNbCh += CFtdiDeviceDescr::CreateInterfacePair(descr1, descr2, &PairsOf3000DevicesChs); + // and flag as used + descr1->SetUsed(true); + descr2->SetUsed(true); + } + } + } + // now we should have only remaining the 3 channels device(s) + // and possibly an unique single channel device + std::vector Single3003DeviceChannels; + for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) + { + CFtdiDeviceDescr *descr1 = m_FtdiDeviceDescrs[i]; + CFtdiDeviceDescr *descr2 = NULL; + if ( !descr1->IsUsed() && (descr1->GetNbChannels() == 3) ) + { + // any other 3 channel device to pair with ? + bool found = false; + unsigned j = i+1; + while ( !found && (j < m_FtdiDeviceDescrs.size()) ) + { + descr2 = m_FtdiDeviceDescrs[j]; + found = (!descr2->IsUsed() && (descr2->GetNbChannels() == 3)); + j++; + } + // found one ? + if ( found ) + { + // yes, create and pair both interfaces + iNbCh += CFtdiDeviceDescr::CreateInterfacePair(descr1, descr2, &Multi3003DevicesChs); + // and flag as used + descr1->SetUsed(true); + descr2->SetUsed(true); + } + } + } + // at this point we should have only remaining an unique 3 channels + // and or a unique single channel + std::vector Combined3003And3000DeviceChannels; + for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) + { + CFtdiDeviceDescr *descr1 = m_FtdiDeviceDescrs[i]; + CFtdiDeviceDescr *descr2 = NULL; + // Any 3003 ? + if ( !descr1->IsUsed() && (descr1->GetNbChannels() == 3) ) + { + // any single channel device to pair with ? + bool found = false; + unsigned j = 0; + while ( !found && (j < m_FtdiDeviceDescrs.size()) ) + { + descr2 = m_FtdiDeviceDescrs[j]; + found = ((descr1 != descr2) && !descr2->IsUsed() && (descr2->GetNbChannels() == 1)); + j++; + } + // found one ? + if ( found ) + { + // yes, create and pair both interfaces + iNbCh += CFtdiDeviceDescr::CreateInterfacePair(descr1, descr2, &Combined3003And3000DeviceChannels); + // and flag as used + descr1->SetUsed(true); + descr2->SetUsed(true); + } + else + { + // no, just create a standalone 3003 interface + iNbCh += CFtdiDeviceDescr::CreateInterface(descr1, &Single3003DeviceChannels); + // and flag as used + descr1->SetUsed(true); + } + } + } + // at this point we should possible only have unique 3003 remaining - // now agregate channels by order of priority - // for proper load sharing - // pairs of 3000 devices first - { - for ( unsigned i = 0; i < PairsOf3000DevicesChs.size(); i++ ) - { - m_Channels.push_back(PairsOf3000DevicesChs.at(i)); - } - PairsOf3000DevicesChs.clear(); - } - // next the left-over single 3003 device - { - for ( unsigned i = 0; i < Single3003DeviceChannels.size(); i++ ) - { - m_Channels.push_back(Single3003DeviceChannels.at(i)); - } - Single3003DeviceChannels.clear(); - } - // finally interlace multi-3003 and pairs of 3003 devices which always - // results to 6 channels per pair of 3003 - { - unsigned n = (int)Multi3003DevicesChs.size() / 6; - for ( unsigned i = 0; (i < 6) && (n != 0); i++ ) - { - for ( unsigned j = 0; j < n; j++ ) - { - m_Channels.push_back(Multi3003DevicesChs.at((j*6) + i)); - } - } - Multi3003DevicesChs.clear(); - } - // and finaly the hybrid combination of 3003 / 3000 - { - for ( unsigned i = 0; i < Combined3003And3000DeviceChannels.size(); i++ ) - { - m_Channels.push_back(Combined3003And3000DeviceChannels.at(i)); - } - Combined3003And3000DeviceChannels.clear(); - } + // now agregate channels by order of priority + // for proper load sharing + // pairs of 3000 devices first + { + for ( unsigned i = 0; i < PairsOf3000DevicesChs.size(); i++ ) + { + m_Channels.push_back(PairsOf3000DevicesChs.at(i)); + } + PairsOf3000DevicesChs.clear(); + } + // next the left-over single 3003 device + { + for ( unsigned i = 0; i < Single3003DeviceChannels.size(); i++ ) + { + m_Channels.push_back(Single3003DeviceChannels.at(i)); + } + Single3003DeviceChannels.clear(); + } + // finally interlace multi-3003 and pairs of 3003 devices which always + // results to 6 channels per pair of 3003 + { + unsigned n = (int)Multi3003DevicesChs.size() / 6; + for ( unsigned i = 0; (i < 6) && (n != 0); i++ ) + { + for ( unsigned j = 0; j < n; j++ ) + { + m_Channels.push_back(Multi3003DevicesChs.at((j*6) + i)); + } + } + Multi3003DevicesChs.clear(); + } + // and finaly the hybrid combination of 3003 / 3000 + { + for ( unsigned i = 0; i < Combined3003And3000DeviceChannels.size(); i++ ) + { + m_Channels.push_back(Combined3003And3000DeviceChannels.at(i)); + } + Combined3003And3000DeviceChannels.clear(); + } - // done - if ( ok ) - { - std::cout << "Codec interfaces initialized successfully : " << iNbCh << " channels available" << std::endl; - } - else - { - std::cout << "At least one codec interfaces failed to initialize : " << iNbCh << " channels availables" << std::endl; - } - // done - return ok; + // done + if ( ok ) + { + std::cout << "Codec interfaces initialized successfully : " << iNbCh << " channels available" << std::endl; + } + else + { + std::cout << "At least one codec interfaces failed to initialize : " << iNbCh << " channels availables" << std::endl; + } + // done + return ok; } //////////////////////////////////////////////////////////////////////////////////////// @@ -257,51 +257,51 @@ bool CVocodecs::Init(void) bool CVocodecs::DiscoverFtdiDevices(void) { - bool ok = false; - int iNbDevices = 0; - FT_DEVICE_LIST_INFO_NODE *list; + bool ok = false; + int iNbDevices = 0; + FT_DEVICE_LIST_INFO_NODE *list; - // clear vector - for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) - { - delete m_FtdiDeviceDescrs[i]; - } + // clear vector + for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) + { + delete m_FtdiDeviceDescrs[i]; + } - // and discover - if ( FT_CreateDeviceInfoList((LPDWORD)&iNbDevices) == FT_OK ) - { - std::cout << "Detected " << iNbDevices << " USB-FTDI devices" << std::endl << std::endl; - ok = true; - if ( iNbDevices > 0 ) - { - // allocate the list - list = new FT_DEVICE_LIST_INFO_NODE[iNbDevices]; + // and discover + if ( FT_CreateDeviceInfoList((LPDWORD)&iNbDevices) == FT_OK ) + { + std::cout << "Detected " << iNbDevices << " USB-FTDI devices" << std::endl << std::endl; + ok = true; + if ( iNbDevices > 0 ) + { + // allocate the list + list = new FT_DEVICE_LIST_INFO_NODE[iNbDevices]; - // fill - if ( FT_GetDeviceInfoList(list, (LPDWORD)&iNbDevices) == FT_OK ) - { - // process - for ( int i = 0; i < iNbDevices; i++ ) - { - std::cout << "Description : " << list[i].Description << "\t Serial : " << list[i].SerialNumber << std::endl; - CFtdiDeviceDescr *descr = new CFtdiDeviceDescr( - LOWORD(list[i].ID), HIWORD(list[i].ID), - list[i].Description, list[i].SerialNumber); - m_FtdiDeviceDescrs.push_back(descr); - } - } - else - { - ok = false; - } + // fill + if ( FT_GetDeviceInfoList(list, (LPDWORD)&iNbDevices) == FT_OK ) + { + // process + for ( int i = 0; i < iNbDevices; i++ ) + { + std::cout << "Description : " << list[i].Description << "\t Serial : " << list[i].SerialNumber << std::endl; + CFtdiDeviceDescr *descr = new CFtdiDeviceDescr( + LOWORD(list[i].ID), HIWORD(list[i].ID), + list[i].Description, list[i].SerialNumber); + m_FtdiDeviceDescrs.push_back(descr); + } + } + else + { + ok = false; + } - // and delete - delete list; - } - } + // and delete + delete list; + } + } - // done - return ok; + // done + return ok; } //////////////////////////////////////////////////////////////////////////////////////// @@ -309,31 +309,31 @@ bool CVocodecs::DiscoverFtdiDevices(void) CVocodecChannel *CVocodecs::OpenChannel(uint8 uiCodecIn, uint8 uiCodecOut) { - CVocodecChannel *Channel = NULL; - bool done = false; + CVocodecChannel *Channel = NULL; + bool done = false; - // loop on all interface until suitable & available channel found - m_MutexChannels.lock(); - for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ ) - { - if ( !m_Channels[i]->IsOpen() && - (m_Channels[i]->GetCodecIn() == uiCodecIn) && - (m_Channels[i]->GetCodecOut() == uiCodecOut) ) - { - if ( m_Channels[i]->Open() ) - { - Channel = m_Channels[i]; - done = true; - } - } - } - m_MutexChannels.unlock(); + // loop on all interface until suitable & available channel found + m_MutexChannels.lock(); + for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ ) + { + if ( !m_Channels[i]->IsOpen() && + (m_Channels[i]->GetCodecIn() == uiCodecIn) && + (m_Channels[i]->GetCodecOut() == uiCodecOut) ) + { + if ( m_Channels[i]->Open() ) + { + Channel = m_Channels[i]; + done = true; + } + } + } + m_MutexChannels.unlock(); - // done - return Channel; + // done + return Channel; } void CVocodecs::CloseChannel(CVocodecChannel *Channel) { - Channel->Close(); + Channel->Close(); } diff --git a/ambed/cvocodecs.h b/ambed/cvocodecs.h index 62da1f6..8d0e647 100644 --- a/ambed/cvocodecs.h +++ b/ambed/cvocodecs.h @@ -35,43 +35,43 @@ class CVocodecs { public: - // constructors - CVocodecs(); - - // destructor - virtual ~CVocodecs(); - - // initialization - bool Init(void); - - // manage interfaces - int GetNbInterfaces(void) const { return (int)m_Interfaces.size(); } - CVocodecInterface *GetInterface(int); - - // manage channels - CVocodecChannel *OpenChannel(uint8, uint8); - void AddChannel(CVocodecChannel *ch) { m_Channels.push_back(ch); } - void CloseChannel(CVocodecChannel *); + // constructors + CVocodecs(); + + // destructor + virtual ~CVocodecs(); + + // initialization + bool Init(void); + + // manage interfaces + int GetNbInterfaces(void) const { return (int)m_Interfaces.size(); } + CVocodecInterface *GetInterface(int); + + // manage channels + CVocodecChannel *OpenChannel(uint8, uint8); + void AddChannel(CVocodecChannel *ch) { m_Channels.push_back(ch); } + void CloseChannel(CVocodecChannel *); protected: - // initialisation helpers - bool DiscoverFtdiDevices(void); - - // helpers - bool IsEven(int i) const { return ((i % 2) == 0); } - bool IsOdd(int i) const { return !IsEven(i); } - + // initialisation helpers + bool DiscoverFtdiDevices(void); + + // helpers + bool IsEven(int i) const { return ((i % 2) == 0); } + bool IsOdd(int i) const { return !IsEven(i); } + protected: - // array of interfaces - std::mutex m_MutexInterfaces; - std::vector m_Interfaces; - - // array of channels - std::mutex m_MutexChannels; - std::vector m_Channels; - - // array of FTDI desciptors - std::vector m_FtdiDeviceDescrs; + // array of interfaces + std::mutex m_MutexInterfaces; + std::vector m_Interfaces; + + // array of channels + std::mutex m_MutexChannels; + std::vector m_Channels; + + // array of FTDI desciptors + std::vector m_FtdiDeviceDescrs; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/ambed/cvoicepacket.cpp b/ambed/cvoicepacket.cpp index 3cfb66e..d62faed 100644 --- a/ambed/cvoicepacket.cpp +++ b/ambed/cvoicepacket.cpp @@ -33,22 +33,22 @@ CVoicePacket::CVoicePacket() { - m_iSize = 0; - ::memset(m_uiVoice, 0, sizeof(m_uiVoice)); + m_iSize = 0; + ::memset(m_uiVoice, 0, sizeof(m_uiVoice)); } CVoicePacket::CVoicePacket(const uint8 *voice, int size) { - m_iSize = MIN(size, sizeof(m_uiVoice)); - ::memset(m_uiVoice, 0, sizeof(m_uiVoice)); - ::memcpy(m_uiVoice, voice, m_iSize); + m_iSize = MIN(size, sizeof(m_uiVoice)); + ::memset(m_uiVoice, 0, sizeof(m_uiVoice)); + ::memcpy(m_uiVoice, voice, m_iSize); } CVoicePacket::CVoicePacket(const CVoicePacket &packet) - : CPacket(packet) + : CPacket(packet) { - m_iSize = packet.m_iSize; - ::memcpy(m_uiVoice, packet.m_uiVoice, sizeof(m_uiVoice)); + m_iSize = packet.m_iSize; + ::memcpy(m_uiVoice, packet.m_uiVoice, sizeof(m_uiVoice)); } @@ -64,8 +64,8 @@ CVoicePacket::~CVoicePacket() void CVoicePacket::SetVoice(const uint8 *voice, int size) { - m_iSize = MIN(size, sizeof(m_uiVoice)); - ::memset(m_uiVoice, 0, sizeof(m_uiVoice)); - ::memcpy(m_uiVoice, voice, m_iSize); + m_iSize = MIN(size, sizeof(m_uiVoice)); + ::memset(m_uiVoice, 0, sizeof(m_uiVoice)); + ::memcpy(m_uiVoice, voice, m_iSize); } diff --git a/ambed/cvoicepacket.h b/ambed/cvoicepacket.h index bb8e6ce..305da8f 100644 --- a/ambed/cvoicepacket.h +++ b/ambed/cvoicepacket.h @@ -40,28 +40,28 @@ class CVoicePacket : public CPacket { public: - // constructors - CVoicePacket(); - CVoicePacket(const uint8 *, int); - CVoicePacket(const CVoicePacket &); - - // destructor - virtual ~CVoicePacket(); + // constructors + CVoicePacket(); + CVoicePacket(const uint8 *, int); + CVoicePacket(const CVoicePacket &); - // identity - bool IsVoice(void) const { return true; } + // destructor + virtual ~CVoicePacket(); + + // identity + bool IsVoice(void) const { return true; } + + // get + uint8 *GetVoice(void) { return m_uiVoice; } + int GetVoiceSize(void) const { return m_iSize; } + + // set + void SetVoice(const uint8 *, int); - // get - uint8 *GetVoice(void) { return m_uiVoice; } - int GetVoiceSize(void) const { return m_iSize; } - - // set - void SetVoice(const uint8 *, int); - protected: - // data - int m_iSize; - uint8 m_uiVoice[VOICE_SIZEMAX]; + // data + int m_iSize; + uint8 m_uiVoice[VOICE_SIZEMAX]; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/ambed/ftd2xx.h b/ambed/ftd2xx.h old mode 100755 new mode 100644 index e5bbb46..4a3783a --- a/ambed/ftd2xx.h +++ b/ambed/ftd2xx.h @@ -80,7 +80,8 @@ typedef ULONG FT_STATUS; // // Device status // -enum { +enum +{ FT_OK, FT_INVALID_HANDLE, FT_DEVICE_NOT_FOUND, @@ -210,7 +211,8 @@ typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); typedef ULONG FT_DEVICE; -enum { +enum +{ FT_DEVICE_BM, FT_DEVICE_AM, FT_DEVICE_100AX, @@ -224,7 +226,7 @@ enum { FT_DEVICE_4222H_0, FT_DEVICE_4222H_1_2, FT_DEVICE_4222H_3, - FT_DEVICE_4222_PROG, + FT_DEVICE_4222_PROG, }; // @@ -316,1123 +318,1137 @@ extern "C" { #ifdef FTD2XX_STATIC - FTD2XX_API - FT_STATUS WINAPI FT_Initialise( - void - ); - - FTD2XX_API - void WINAPI FT_Finalise( - void - ); +FTD2XX_API +FT_STATUS WINAPI FT_Initialise( + void +); + +FTD2XX_API +void WINAPI FT_Finalise( + void +); #endif // FTD2XX_STATIC - FTD2XX_API - FT_STATUS WINAPI FT_Open( - int deviceNumber, - FT_HANDLE *pHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_OpenEx( - PVOID pArg1, - DWORD Flags, - FT_HANDLE *pHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ListDevices( - PVOID pArg1, - PVOID pArg2, - DWORD Flags - ); - - FTD2XX_API - FT_STATUS WINAPI FT_Close( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_Read( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD dwBytesToRead, - LPDWORD lpBytesReturned - ); - - FTD2XX_API - FT_STATUS WINAPI FT_Write( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD dwBytesToWrite, - LPDWORD lpBytesWritten - ); - - FTD2XX_API - FT_STATUS WINAPI FT_IoCtl( - FT_HANDLE ftHandle, - DWORD dwIoControlCode, - LPVOID lpInBuf, - DWORD nInBufSize, - LPVOID lpOutBuf, - DWORD nOutBufSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetBaudRate( - FT_HANDLE ftHandle, - ULONG BaudRate - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetDivisor( - FT_HANDLE ftHandle, - USHORT Divisor - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetDataCharacteristics( - FT_HANDLE ftHandle, - UCHAR WordLength, - UCHAR StopBits, - UCHAR Parity - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetFlowControl( - FT_HANDLE ftHandle, - USHORT FlowControl, - UCHAR XonChar, - UCHAR XoffChar - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ResetDevice( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetDtr( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ClrDtr( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetRts( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ClrRts( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetModemStatus( - FT_HANDLE ftHandle, - ULONG *pModemStatus - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetChars( - FT_HANDLE ftHandle, - UCHAR EventChar, - UCHAR EventCharEnabled, - UCHAR ErrorChar, - UCHAR ErrorCharEnabled - ); - - FTD2XX_API - FT_STATUS WINAPI FT_Purge( - FT_HANDLE ftHandle, - ULONG Mask - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetTimeouts( - FT_HANDLE ftHandle, - ULONG ReadTimeout, - ULONG WriteTimeout - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetQueueStatus( - FT_HANDLE ftHandle, - DWORD *dwRxBytes - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetEventNotification( - FT_HANDLE ftHandle, - DWORD Mask, - PVOID Param - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetStatus( - FT_HANDLE ftHandle, - DWORD *dwRxBytes, - DWORD *dwTxBytes, - DWORD *dwEventDWord - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetBreakOn( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetBreakOff( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetWaitMask( - FT_HANDLE ftHandle, - DWORD Mask - ); - - FTD2XX_API - FT_STATUS WINAPI FT_WaitOnMask( - FT_HANDLE ftHandle, - DWORD *Mask - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetEventStatus( - FT_HANDLE ftHandle, - DWORD *dwEventDWord - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ReadEE( - FT_HANDLE ftHandle, - DWORD dwWordOffset, - LPWORD lpwValue - ); - - FTD2XX_API - FT_STATUS WINAPI FT_WriteEE( - FT_HANDLE ftHandle, - DWORD dwWordOffset, - WORD wValue - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EraseEE( - FT_HANDLE ftHandle - ); +FTD2XX_API +FT_STATUS WINAPI FT_Open( + int deviceNumber, + FT_HANDLE *pHandle +); + +FTD2XX_API +FT_STATUS WINAPI FT_OpenEx( + PVOID pArg1, + DWORD Flags, + FT_HANDLE *pHandle +); + +FTD2XX_API +FT_STATUS WINAPI FT_ListDevices( + PVOID pArg1, + PVOID pArg2, + DWORD Flags +); + +FTD2XX_API +FT_STATUS WINAPI FT_Close( + FT_HANDLE ftHandle +); + +FTD2XX_API +FT_STATUS WINAPI FT_Read( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD dwBytesToRead, + LPDWORD lpBytesReturned +); + +FTD2XX_API +FT_STATUS WINAPI FT_Write( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD dwBytesToWrite, + LPDWORD lpBytesWritten +); + +FTD2XX_API +FT_STATUS WINAPI FT_IoCtl( + FT_HANDLE ftHandle, + DWORD dwIoControlCode, + LPVOID lpInBuf, + DWORD nInBufSize, + LPVOID lpOutBuf, + DWORD nOutBufSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped +); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBaudRate( + FT_HANDLE ftHandle, + ULONG BaudRate +); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDivisor( + FT_HANDLE ftHandle, + USHORT Divisor +); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDataCharacteristics( + FT_HANDLE ftHandle, + UCHAR WordLength, + UCHAR StopBits, + UCHAR Parity +); + +FTD2XX_API +FT_STATUS WINAPI FT_SetFlowControl( + FT_HANDLE ftHandle, + USHORT FlowControl, + UCHAR XonChar, + UCHAR XoffChar +); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetDevice( + FT_HANDLE ftHandle +); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDtr( + FT_HANDLE ftHandle +); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrDtr( + FT_HANDLE ftHandle +); + +FTD2XX_API +FT_STATUS WINAPI FT_SetRts( + FT_HANDLE ftHandle +); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrRts( + FT_HANDLE ftHandle +); + +FTD2XX_API +FT_STATUS WINAPI FT_GetModemStatus( + FT_HANDLE ftHandle, + ULONG *pModemStatus +); + +FTD2XX_API +FT_STATUS WINAPI FT_SetChars( + FT_HANDLE ftHandle, + UCHAR EventChar, + UCHAR EventCharEnabled, + UCHAR ErrorChar, + UCHAR ErrorCharEnabled +); + +FTD2XX_API +FT_STATUS WINAPI FT_Purge( + FT_HANDLE ftHandle, + ULONG Mask +); + +FTD2XX_API +FT_STATUS WINAPI FT_SetTimeouts( + FT_HANDLE ftHandle, + ULONG ReadTimeout, + ULONG WriteTimeout +); + +FTD2XX_API +FT_STATUS WINAPI FT_GetQueueStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes +); + +FTD2XX_API +FT_STATUS WINAPI FT_SetEventNotification( + FT_HANDLE ftHandle, + DWORD Mask, + PVOID Param +); + +FTD2XX_API +FT_STATUS WINAPI FT_GetStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes, + DWORD *dwTxBytes, + DWORD *dwEventDWord +); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOn( + FT_HANDLE ftHandle +); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOff( + FT_HANDLE ftHandle +); + +FTD2XX_API +FT_STATUS WINAPI FT_SetWaitMask( + FT_HANDLE ftHandle, + DWORD Mask +); + +FTD2XX_API +FT_STATUS WINAPI FT_WaitOnMask( + FT_HANDLE ftHandle, + DWORD *Mask +); + +FTD2XX_API +FT_STATUS WINAPI FT_GetEventStatus( + FT_HANDLE ftHandle, + DWORD *dwEventDWord +); + +FTD2XX_API +FT_STATUS WINAPI FT_ReadEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + LPWORD lpwValue +); + +FTD2XX_API +FT_STATUS WINAPI FT_WriteEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + WORD wValue +); + +FTD2XX_API +FT_STATUS WINAPI FT_EraseEE( + FT_HANDLE ftHandle +); +// +// structure to hold program data for FT_EE_Program, FT_EE_ProgramEx, FT_EE_Read +// and FT_EE_ReadEx functions +// +typedef struct ft_program_data +{ + + DWORD Signature1; // Header - must be 0x00000000 + DWORD Signature2; // Header - must be 0xffffffff + DWORD Version; // Header - FT_PROGRAM_DATA version + // 0 = original + // 1 = FT2232 extensions + // 2 = FT232R extensions + // 3 = FT2232H extensions + // 4 = FT4232H extensions + // 5 = FT232H extensions + + WORD VendorId; // 0x0403 + WORD ProductId; // 0x6001 + char *Manufacturer; // "FTDI" + char *ManufacturerId; // "FT" + char *Description; // "USB HS Serial Converter" + char *SerialNumber; // "FT000001" if fixed, or NULL + WORD MaxPower; // 0 < MaxPower <= 500 + WORD PnP; // 0 = disabled, 1 = enabled + WORD SelfPowered; // 0 = bus powered, 1 = self powered + WORD RemoteWakeup; // 0 = not capable, 1 = capable + // + // Rev4 (FT232B) extensions + // + UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise + UCHAR IsoIn; // non-zero if in endpoint is isochronous + UCHAR IsoOut; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable; // non-zero if pull down enabled + UCHAR SerNumEnable; // non-zero if serial number to be used + UCHAR USBVersionEnable; // non-zero if chip uses USBVersion + WORD USBVersion; // BCD (0x0200 => USB2) + // + // Rev 5 (FT2232) extensions + // + UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise + UCHAR IsoInA; // non-zero if in endpoint is isochronous + UCHAR IsoInB; // non-zero if in endpoint is isochronous + UCHAR IsoOutA; // non-zero if out endpoint is isochronous + UCHAR IsoOutB; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable5; // non-zero if pull down enabled + UCHAR SerNumEnable5; // non-zero if serial number to be used + UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion + WORD USBVersion5; // BCD (0x0200 => USB2) + UCHAR AIsHighCurrent; // non-zero if interface is high current + UCHAR BIsHighCurrent; // non-zero if interface is high current + UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer; // non-zero if interface is Fast serial + UCHAR AIsVCP; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsVCP; // non-zero if interface is to use VCP drivers + // + // Rev 6 (FT232R) extensions + // + UCHAR UseExtOsc; // Use External Oscillator + UCHAR HighDriveIOs; // High Drive I/Os + UCHAR EndpointSize; // Endpoint size + UCHAR PullDownEnableR; // non-zero if pull down enabled + UCHAR SerNumEnableR; // non-zero if serial number to be used + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + UCHAR RIsD2XX; // non-zero if using D2XX driver + // + // Rev 7 (FT2232H) Extensions + // + UCHAR PullDownEnable7; // non-zero if pull down enabled + UCHAR SerNumEnable7; // non-zero if serial number to be used + UCHAR ALSlowSlew; // non-zero if AL pins have slow slew + UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input + UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR AHSlowSlew; // non-zero if AH pins have slow slew + UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input + UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BLSlowSlew; // non-zero if BL pins have slow slew + UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input + UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BHSlowSlew; // non-zero if BH pins have slow slew + UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input + UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR IFAIsFifo7; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar7; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer7; // non-zero if interface is Fast serial + UCHAR AIsVCP7; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo7; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar7; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer7; // non-zero if interface is Fast serial + UCHAR BIsVCP7; // non-zero if interface is to use VCP drivers + UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs // - // structure to hold program data for FT_EE_Program, FT_EE_ProgramEx, FT_EE_Read - // and FT_EE_ReadEx functions + // Rev 8 (FT4232H) Extensions // - typedef struct ft_program_data { - - DWORD Signature1; // Header - must be 0x00000000 - DWORD Signature2; // Header - must be 0xffffffff - DWORD Version; // Header - FT_PROGRAM_DATA version - // 0 = original - // 1 = FT2232 extensions - // 2 = FT232R extensions - // 3 = FT2232H extensions - // 4 = FT4232H extensions - // 5 = FT232H extensions - - WORD VendorId; // 0x0403 - WORD ProductId; // 0x6001 - char *Manufacturer; // "FTDI" - char *ManufacturerId; // "FT" - char *Description; // "USB HS Serial Converter" - char *SerialNumber; // "FT000001" if fixed, or NULL - WORD MaxPower; // 0 < MaxPower <= 500 - WORD PnP; // 0 = disabled, 1 = enabled - WORD SelfPowered; // 0 = bus powered, 1 = self powered - WORD RemoteWakeup; // 0 = not capable, 1 = capable - // - // Rev4 (FT232B) extensions - // - UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise - UCHAR IsoIn; // non-zero if in endpoint is isochronous - UCHAR IsoOut; // non-zero if out endpoint is isochronous - UCHAR PullDownEnable; // non-zero if pull down enabled - UCHAR SerNumEnable; // non-zero if serial number to be used - UCHAR USBVersionEnable; // non-zero if chip uses USBVersion - WORD USBVersion; // BCD (0x0200 => USB2) - // - // Rev 5 (FT2232) extensions - // - UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise - UCHAR IsoInA; // non-zero if in endpoint is isochronous - UCHAR IsoInB; // non-zero if in endpoint is isochronous - UCHAR IsoOutA; // non-zero if out endpoint is isochronous - UCHAR IsoOutB; // non-zero if out endpoint is isochronous - UCHAR PullDownEnable5; // non-zero if pull down enabled - UCHAR SerNumEnable5; // non-zero if serial number to be used - UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion - WORD USBVersion5; // BCD (0x0200 => USB2) - UCHAR AIsHighCurrent; // non-zero if interface is high current - UCHAR BIsHighCurrent; // non-zero if interface is high current - UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO - UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IFAIsFastSer; // non-zero if interface is Fast serial - UCHAR AIsVCP; // non-zero if interface is to use VCP drivers - UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO - UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IFBIsFastSer; // non-zero if interface is Fast serial - UCHAR BIsVCP; // non-zero if interface is to use VCP drivers - // - // Rev 6 (FT232R) extensions - // - UCHAR UseExtOsc; // Use External Oscillator - UCHAR HighDriveIOs; // High Drive I/Os - UCHAR EndpointSize; // Endpoint size - UCHAR PullDownEnableR; // non-zero if pull down enabled - UCHAR SerNumEnableR; // non-zero if serial number to be used - UCHAR InvertTXD; // non-zero if invert TXD - UCHAR InvertRXD; // non-zero if invert RXD - UCHAR InvertRTS; // non-zero if invert RTS - UCHAR InvertCTS; // non-zero if invert CTS - UCHAR InvertDTR; // non-zero if invert DTR - UCHAR InvertDSR; // non-zero if invert DSR - UCHAR InvertDCD; // non-zero if invert DCD - UCHAR InvertRI; // non-zero if invert RI - UCHAR Cbus0; // Cbus Mux control - UCHAR Cbus1; // Cbus Mux control - UCHAR Cbus2; // Cbus Mux control - UCHAR Cbus3; // Cbus Mux control - UCHAR Cbus4; // Cbus Mux control - UCHAR RIsD2XX; // non-zero if using D2XX driver - // - // Rev 7 (FT2232H) Extensions - // - UCHAR PullDownEnable7; // non-zero if pull down enabled - UCHAR SerNumEnable7; // non-zero if serial number to be used - UCHAR ALSlowSlew; // non-zero if AL pins have slow slew - UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input - UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR AHSlowSlew; // non-zero if AH pins have slow slew - UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input - UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BLSlowSlew; // non-zero if BL pins have slow slew - UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input - UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BHSlowSlew; // non-zero if BH pins have slow slew - UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input - UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR IFAIsFifo7; // non-zero if interface is 245 FIFO - UCHAR IFAIsFifoTar7; // non-zero if interface is 245 FIFO CPU target - UCHAR IFAIsFastSer7; // non-zero if interface is Fast serial - UCHAR AIsVCP7; // non-zero if interface is to use VCP drivers - UCHAR IFBIsFifo7; // non-zero if interface is 245 FIFO - UCHAR IFBIsFifoTar7; // non-zero if interface is 245 FIFO CPU target - UCHAR IFBIsFastSer7; // non-zero if interface is Fast serial - UCHAR BIsVCP7; // non-zero if interface is to use VCP drivers - UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs - // - // Rev 8 (FT4232H) Extensions - // - UCHAR PullDownEnable8; // non-zero if pull down enabled - UCHAR SerNumEnable8; // non-zero if serial number to be used - UCHAR ASlowSlew; // non-zero if A pins have slow slew - UCHAR ASchmittInput; // non-zero if A pins are Schmitt input - UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BSlowSlew; // non-zero if B pins have slow slew - UCHAR BSchmittInput; // non-zero if B pins are Schmitt input - UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR CSlowSlew; // non-zero if C pins have slow slew - UCHAR CSchmittInput; // non-zero if C pins are Schmitt input - UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR DSlowSlew; // non-zero if D pins have slow slew - UCHAR DSchmittInput; // non-zero if D pins are Schmitt input - UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN - UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN - UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN - UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN - UCHAR AIsVCP8; // non-zero if interface is to use VCP drivers - UCHAR BIsVCP8; // non-zero if interface is to use VCP drivers - UCHAR CIsVCP8; // non-zero if interface is to use VCP drivers - UCHAR DIsVCP8; // non-zero if interface is to use VCP drivers - // - // Rev 9 (FT232H) Extensions - // - UCHAR PullDownEnableH; // non-zero if pull down enabled - UCHAR SerNumEnableH; // non-zero if serial number to be used - UCHAR ACSlowSlewH; // non-zero if AC pins have slow slew - UCHAR ACSchmittInputH; // non-zero if AC pins are Schmitt input - UCHAR ACDriveCurrentH; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR ADSlowSlewH; // non-zero if AD pins have slow slew - UCHAR ADSchmittInputH; // non-zero if AD pins are Schmitt input - UCHAR ADDriveCurrentH; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR Cbus0H; // Cbus Mux control - UCHAR Cbus1H; // Cbus Mux control - UCHAR Cbus2H; // Cbus Mux control - UCHAR Cbus3H; // Cbus Mux control - UCHAR Cbus4H; // Cbus Mux control - UCHAR Cbus5H; // Cbus Mux control - UCHAR Cbus6H; // Cbus Mux control - UCHAR Cbus7H; // Cbus Mux control - UCHAR Cbus8H; // Cbus Mux control - UCHAR Cbus9H; // Cbus Mux control - UCHAR IsFifoH; // non-zero if interface is 245 FIFO - UCHAR IsFifoTarH; // non-zero if interface is 245 FIFO CPU target - UCHAR IsFastSerH; // non-zero if interface is Fast serial - UCHAR IsFT1248H; // non-zero if interface is FT1248 - UCHAR FT1248CpolH; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) - UCHAR FT1248LsbH; // FT1248 data is LSB (1) or MSB (0) - UCHAR FT1248FlowControlH; // FT1248 flow control enable - UCHAR IsVCPH; // non-zero if interface is to use VCP drivers - UCHAR PowerSaveEnableH; // non-zero if using ACBUS7 to save power for self-powered designs - - } FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; - - FTD2XX_API - FT_STATUS WINAPI FT_EE_Program( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_ProgramEx( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_Read( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_ReadEx( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_UASize( - FT_HANDLE ftHandle, - LPDWORD lpdwSize - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_UAWrite( - FT_HANDLE ftHandle, - PUCHAR pucData, - DWORD dwDataLen - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_UARead( - FT_HANDLE ftHandle, - PUCHAR pucData, - DWORD dwDataLen, - LPDWORD lpdwBytesRead - ); - - - typedef struct ft_eeprom_header { - FT_DEVICE deviceType; // FTxxxx device type to be programmed - // Device descriptor options - WORD VendorId; // 0x0403 - WORD ProductId; // 0x6001 - UCHAR SerNumEnable; // non-zero if serial number to be used - // Config descriptor options - WORD MaxPower; // 0 < MaxPower <= 500 - UCHAR SelfPowered; // 0 = bus powered, 1 = self powered - UCHAR RemoteWakeup; // 0 = not capable, 1 = capable - // Hardware options - UCHAR PullDownEnable; // non-zero if pull down in suspend enabled - } FT_EEPROM_HEADER, *PFT_EEPROM_HEADER; - - - // FT232B EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_232b { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - } FT_EEPROM_232B, *PFT_EEPROM_232B; - - - // FT2232 EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_2232 { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR AIsHighCurrent; // non-zero if interface is high current - UCHAR BIsHighCurrent; // non-zero if interface is high current - // Hardware options - UCHAR AIsFifo; // non-zero if interface is 245 FIFO - UCHAR AIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR AIsFastSer; // non-zero if interface is Fast serial - UCHAR BIsFifo; // non-zero if interface is 245 FIFO - UCHAR BIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR BIsFastSer; // non-zero if interface is Fast serial - // Driver option - UCHAR ADriverType; // - UCHAR BDriverType; // - } FT_EEPROM_2232, *PFT_EEPROM_2232; - - - // FT232R EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_232r { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR IsHighCurrent; // non-zero if interface is high current - // Hardware options - UCHAR UseExtOsc; // Use External Oscillator - UCHAR InvertTXD; // non-zero if invert TXD - UCHAR InvertRXD; // non-zero if invert RXD - UCHAR InvertRTS; // non-zero if invert RTS - UCHAR InvertCTS; // non-zero if invert CTS - UCHAR InvertDTR; // non-zero if invert DTR - UCHAR InvertDSR; // non-zero if invert DSR - UCHAR InvertDCD; // non-zero if invert DCD - UCHAR InvertRI; // non-zero if invert RI - UCHAR Cbus0; // Cbus Mux control - UCHAR Cbus1; // Cbus Mux control - UCHAR Cbus2; // Cbus Mux control - UCHAR Cbus3; // Cbus Mux control - UCHAR Cbus4; // Cbus Mux control - // Driver option - UCHAR DriverType; // - } FT_EEPROM_232R, *PFT_EEPROM_232R; - - - // FT2232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_2232h { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR ALSlowSlew; // non-zero if AL pins have slow slew - UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input - UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR AHSlowSlew; // non-zero if AH pins have slow slew - UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input - UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BLSlowSlew; // non-zero if BL pins have slow slew - UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input - UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BHSlowSlew; // non-zero if BH pins have slow slew - UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input - UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - // Hardware options - UCHAR AIsFifo; // non-zero if interface is 245 FIFO - UCHAR AIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR AIsFastSer; // non-zero if interface is Fast serial - UCHAR BIsFifo; // non-zero if interface is 245 FIFO - UCHAR BIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR BIsFastSer; // non-zero if interface is Fast serial - UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs - // Driver option - UCHAR ADriverType; // - UCHAR BDriverType; // - } FT_EEPROM_2232H, *PFT_EEPROM_2232H; - - - // FT4232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_4232h { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR ASlowSlew; // non-zero if A pins have slow slew - UCHAR ASchmittInput; // non-zero if A pins are Schmitt input - UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BSlowSlew; // non-zero if B pins have slow slew - UCHAR BSchmittInput; // non-zero if B pins are Schmitt input - UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR CSlowSlew; // non-zero if C pins have slow slew - UCHAR CSchmittInput; // non-zero if C pins are Schmitt input - UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR DSlowSlew; // non-zero if D pins have slow slew - UCHAR DSchmittInput; // non-zero if D pins are Schmitt input - UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - // Hardware options - UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN - UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN - UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN - UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN - // Driver option - UCHAR ADriverType; // - UCHAR BDriverType; // - UCHAR CDriverType; // - UCHAR DDriverType; // - } FT_EEPROM_4232H, *PFT_EEPROM_4232H; - - - // FT232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_232h { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR ACSlowSlew; // non-zero if AC bus pins have slow slew - UCHAR ACSchmittInput; // non-zero if AC bus pins are Schmitt input - UCHAR ACDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR ADSlowSlew; // non-zero if AD bus pins have slow slew - UCHAR ADSchmittInput; // non-zero if AD bus pins are Schmitt input - UCHAR ADDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - // CBUS options - UCHAR Cbus0; // Cbus Mux control - UCHAR Cbus1; // Cbus Mux control - UCHAR Cbus2; // Cbus Mux control - UCHAR Cbus3; // Cbus Mux control - UCHAR Cbus4; // Cbus Mux control - UCHAR Cbus5; // Cbus Mux control - UCHAR Cbus6; // Cbus Mux control - UCHAR Cbus7; // Cbus Mux control - UCHAR Cbus8; // Cbus Mux control - UCHAR Cbus9; // Cbus Mux control - // FT1248 options - UCHAR FT1248Cpol; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) - UCHAR FT1248Lsb; // FT1248 data is LSB (1) or MSB (0) - UCHAR FT1248FlowControl; // FT1248 flow control enable - // Hardware options - UCHAR IsFifo; // non-zero if interface is 245 FIFO - UCHAR IsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IsFastSer; // non-zero if interface is Fast serial - UCHAR IsFT1248 ; // non-zero if interface is FT1248 - UCHAR PowerSaveEnable; // - // Driver option - UCHAR DriverType; // - } FT_EEPROM_232H, *PFT_EEPROM_232H; - - - // FT X Series EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program - typedef struct ft_eeprom_x_series { - // Common header - FT_EEPROM_HEADER common; // common elements for all device EEPROMs - // Drive options - UCHAR ACSlowSlew; // non-zero if AC bus pins have slow slew - UCHAR ACSchmittInput; // non-zero if AC bus pins are Schmitt input - UCHAR ACDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR ADSlowSlew; // non-zero if AD bus pins have slow slew - UCHAR ADSchmittInput; // non-zero if AD bus pins are Schmitt input - UCHAR ADDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - // CBUS options - UCHAR Cbus0; // Cbus Mux control - UCHAR Cbus1; // Cbus Mux control - UCHAR Cbus2; // Cbus Mux control - UCHAR Cbus3; // Cbus Mux control - UCHAR Cbus4; // Cbus Mux control - UCHAR Cbus5; // Cbus Mux control - UCHAR Cbus6; // Cbus Mux control - // UART signal options - UCHAR InvertTXD; // non-zero if invert TXD - UCHAR InvertRXD; // non-zero if invert RXD - UCHAR InvertRTS; // non-zero if invert RTS - UCHAR InvertCTS; // non-zero if invert CTS - UCHAR InvertDTR; // non-zero if invert DTR - UCHAR InvertDSR; // non-zero if invert DSR - UCHAR InvertDCD; // non-zero if invert DCD - UCHAR InvertRI; // non-zero if invert RI - // Battery Charge Detect options - UCHAR BCDEnable; // Enable Battery Charger Detection - UCHAR BCDForceCbusPWREN; // asserts the power enable signal on CBUS when charging port detected - UCHAR BCDDisableSleep; // forces the device never to go into sleep mode - // I2C options - WORD I2CSlaveAddress; // I2C slave device address - DWORD I2CDeviceId; // I2C device ID - UCHAR I2CDisableSchmitt; // Disable I2C Schmitt trigger - // FT1248 options - UCHAR FT1248Cpol; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) - UCHAR FT1248Lsb; // FT1248 data is LSB (1) or MSB (0) - UCHAR FT1248FlowControl; // FT1248 flow control enable - // Hardware options - UCHAR RS485EchoSuppress; // - UCHAR PowerSaveEnable; // - // Driver option - UCHAR DriverType; // - } FT_EEPROM_X_SERIES, *PFT_EEPROM_X_SERIES; - - - FTD2XX_API - FT_STATUS WINAPI FT_EEPROM_Read( - FT_HANDLE ftHandle, - void *eepromData, - DWORD eepromDataSize, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - - - FTD2XX_API - FT_STATUS WINAPI FT_EEPROM_Program( - FT_HANDLE ftHandle, - void *eepromData, - DWORD eepromDataSize, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - - - FTD2XX_API - FT_STATUS WINAPI FT_SetLatencyTimer( - FT_HANDLE ftHandle, - UCHAR ucLatency - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetLatencyTimer( - FT_HANDLE ftHandle, - PUCHAR pucLatency - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetBitMode( - FT_HANDLE ftHandle, - UCHAR ucMask, - UCHAR ucEnable - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetBitMode( - FT_HANDLE ftHandle, - PUCHAR pucMode - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetUSBParameters( - FT_HANDLE ftHandle, - ULONG ulInTransferSize, - ULONG ulOutTransferSize - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetDeadmanTimeout( - FT_HANDLE ftHandle, - ULONG ulDeadmanTimeout - ); + UCHAR PullDownEnable8; // non-zero if pull down enabled + UCHAR SerNumEnable8; // non-zero if serial number to be used + UCHAR ASlowSlew; // non-zero if A pins have slow slew + UCHAR ASchmittInput; // non-zero if A pins are Schmitt input + UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BSlowSlew; // non-zero if B pins have slow slew + UCHAR BSchmittInput; // non-zero if B pins are Schmitt input + UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR CSlowSlew; // non-zero if C pins have slow slew + UCHAR CSchmittInput; // non-zero if C pins are Schmitt input + UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR DSlowSlew; // non-zero if D pins have slow slew + UCHAR DSchmittInput; // non-zero if D pins are Schmitt input + UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN + UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN + UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN + UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN + UCHAR AIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR BIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR CIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR DIsVCP8; // non-zero if interface is to use VCP drivers + // + // Rev 9 (FT232H) Extensions + // + UCHAR PullDownEnableH; // non-zero if pull down enabled + UCHAR SerNumEnableH; // non-zero if serial number to be used + UCHAR ACSlowSlewH; // non-zero if AC pins have slow slew + UCHAR ACSchmittInputH; // non-zero if AC pins are Schmitt input + UCHAR ACDriveCurrentH; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR ADSlowSlewH; // non-zero if AD pins have slow slew + UCHAR ADSchmittInputH; // non-zero if AD pins are Schmitt input + UCHAR ADDriveCurrentH; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR Cbus0H; // Cbus Mux control + UCHAR Cbus1H; // Cbus Mux control + UCHAR Cbus2H; // Cbus Mux control + UCHAR Cbus3H; // Cbus Mux control + UCHAR Cbus4H; // Cbus Mux control + UCHAR Cbus5H; // Cbus Mux control + UCHAR Cbus6H; // Cbus Mux control + UCHAR Cbus7H; // Cbus Mux control + UCHAR Cbus8H; // Cbus Mux control + UCHAR Cbus9H; // Cbus Mux control + UCHAR IsFifoH; // non-zero if interface is 245 FIFO + UCHAR IsFifoTarH; // non-zero if interface is 245 FIFO CPU target + UCHAR IsFastSerH; // non-zero if interface is Fast serial + UCHAR IsFT1248H; // non-zero if interface is FT1248 + UCHAR FT1248CpolH; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) + UCHAR FT1248LsbH; // FT1248 data is LSB (1) or MSB (0) + UCHAR FT1248FlowControlH; // FT1248 flow control enable + UCHAR IsVCPH; // non-zero if interface is to use VCP drivers + UCHAR PowerSaveEnableH; // non-zero if using ACBUS7 to save power for self-powered designs + +} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Program( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData +); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ProgramEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber +); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Read( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData +); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ReadEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber +); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UASize( + FT_HANDLE ftHandle, + LPDWORD lpdwSize +); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UAWrite( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen +); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UARead( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen, + LPDWORD lpdwBytesRead +); + + +typedef struct ft_eeprom_header +{ + FT_DEVICE deviceType; // FTxxxx device type to be programmed + // Device descriptor options + WORD VendorId; // 0x0403 + WORD ProductId; // 0x6001 + UCHAR SerNumEnable; // non-zero if serial number to be used + // Config descriptor options + WORD MaxPower; // 0 < MaxPower <= 500 + UCHAR SelfPowered; // 0 = bus powered, 1 = self powered + UCHAR RemoteWakeup; // 0 = not capable, 1 = capable + // Hardware options + UCHAR PullDownEnable; // non-zero if pull down in suspend enabled +} FT_EEPROM_HEADER, *PFT_EEPROM_HEADER; + + +// FT232B EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program +typedef struct ft_eeprom_232b +{ + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs +} FT_EEPROM_232B, *PFT_EEPROM_232B; + + +// FT2232 EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program +typedef struct ft_eeprom_2232 +{ + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR AIsHighCurrent; // non-zero if interface is high current + UCHAR BIsHighCurrent; // non-zero if interface is high current + // Hardware options + UCHAR AIsFifo; // non-zero if interface is 245 FIFO + UCHAR AIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR AIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsFifo; // non-zero if interface is 245 FIFO + UCHAR BIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR BIsFastSer; // non-zero if interface is Fast serial + // Driver option + UCHAR ADriverType; // + UCHAR BDriverType; // +} FT_EEPROM_2232, *PFT_EEPROM_2232; + + +// FT232R EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program +typedef struct ft_eeprom_232r +{ + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR IsHighCurrent; // non-zero if interface is high current + // Hardware options + UCHAR UseExtOsc; // Use External Oscillator + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + // Driver option + UCHAR DriverType; // +} FT_EEPROM_232R, *PFT_EEPROM_232R; + + +// FT2232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program +typedef struct ft_eeprom_2232h +{ + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR ALSlowSlew; // non-zero if AL pins have slow slew + UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input + UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR AHSlowSlew; // non-zero if AH pins have slow slew + UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input + UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BLSlowSlew; // non-zero if BL pins have slow slew + UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input + UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BHSlowSlew; // non-zero if BH pins have slow slew + UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input + UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + // Hardware options + UCHAR AIsFifo; // non-zero if interface is 245 FIFO + UCHAR AIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR AIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsFifo; // non-zero if interface is 245 FIFO + UCHAR BIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR BIsFastSer; // non-zero if interface is Fast serial + UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs + // Driver option + UCHAR ADriverType; // + UCHAR BDriverType; // +} FT_EEPROM_2232H, *PFT_EEPROM_2232H; + + +// FT4232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program +typedef struct ft_eeprom_4232h +{ + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR ASlowSlew; // non-zero if A pins have slow slew + UCHAR ASchmittInput; // non-zero if A pins are Schmitt input + UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BSlowSlew; // non-zero if B pins have slow slew + UCHAR BSchmittInput; // non-zero if B pins are Schmitt input + UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR CSlowSlew; // non-zero if C pins have slow slew + UCHAR CSchmittInput; // non-zero if C pins are Schmitt input + UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR DSlowSlew; // non-zero if D pins have slow slew + UCHAR DSchmittInput; // non-zero if D pins are Schmitt input + UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + // Hardware options + UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN + UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN + UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN + UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN + // Driver option + UCHAR ADriverType; // + UCHAR BDriverType; // + UCHAR CDriverType; // + UCHAR DDriverType; // +} FT_EEPROM_4232H, *PFT_EEPROM_4232H; + + +// FT232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program +typedef struct ft_eeprom_232h +{ + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR ACSlowSlew; // non-zero if AC bus pins have slow slew + UCHAR ACSchmittInput; // non-zero if AC bus pins are Schmitt input + UCHAR ACDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR ADSlowSlew; // non-zero if AD bus pins have slow slew + UCHAR ADSchmittInput; // non-zero if AD bus pins are Schmitt input + UCHAR ADDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + // CBUS options + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + UCHAR Cbus5; // Cbus Mux control + UCHAR Cbus6; // Cbus Mux control + UCHAR Cbus7; // Cbus Mux control + UCHAR Cbus8; // Cbus Mux control + UCHAR Cbus9; // Cbus Mux control + // FT1248 options + UCHAR FT1248Cpol; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) + UCHAR FT1248Lsb; // FT1248 data is LSB (1) or MSB (0) + UCHAR FT1248FlowControl; // FT1248 flow control enable + // Hardware options + UCHAR IsFifo; // non-zero if interface is 245 FIFO + UCHAR IsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IsFastSer; // non-zero if interface is Fast serial + UCHAR IsFT1248 ; // non-zero if interface is FT1248 + UCHAR PowerSaveEnable; // + // Driver option + UCHAR DriverType; // +} FT_EEPROM_232H, *PFT_EEPROM_232H; + + +// FT X Series EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program +typedef struct ft_eeprom_x_series +{ + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR ACSlowSlew; // non-zero if AC bus pins have slow slew + UCHAR ACSchmittInput; // non-zero if AC bus pins are Schmitt input + UCHAR ACDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR ADSlowSlew; // non-zero if AD bus pins have slow slew + UCHAR ADSchmittInput; // non-zero if AD bus pins are Schmitt input + UCHAR ADDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + // CBUS options + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + UCHAR Cbus5; // Cbus Mux control + UCHAR Cbus6; // Cbus Mux control + // UART signal options + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + // Battery Charge Detect options + UCHAR BCDEnable; // Enable Battery Charger Detection + UCHAR BCDForceCbusPWREN; // asserts the power enable signal on CBUS when charging port detected + UCHAR BCDDisableSleep; // forces the device never to go into sleep mode + // I2C options + WORD I2CSlaveAddress; // I2C slave device address + DWORD I2CDeviceId; // I2C device ID + UCHAR I2CDisableSchmitt; // Disable I2C Schmitt trigger + // FT1248 options + UCHAR FT1248Cpol; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) + UCHAR FT1248Lsb; // FT1248 data is LSB (1) or MSB (0) + UCHAR FT1248FlowControl; // FT1248 flow control enable + // Hardware options + UCHAR RS485EchoSuppress; // + UCHAR PowerSaveEnable; // + // Driver option + UCHAR DriverType; // +} FT_EEPROM_X_SERIES, *PFT_EEPROM_X_SERIES; + + +FTD2XX_API +FT_STATUS WINAPI FT_EEPROM_Read( + FT_HANDLE ftHandle, + void *eepromData, + DWORD eepromDataSize, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber +); + + +FTD2XX_API +FT_STATUS WINAPI FT_EEPROM_Program( + FT_HANDLE ftHandle, + void *eepromData, + DWORD eepromDataSize, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber +); + + +FTD2XX_API +FT_STATUS WINAPI FT_SetLatencyTimer( + FT_HANDLE ftHandle, + UCHAR ucLatency +); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLatencyTimer( + FT_HANDLE ftHandle, + PUCHAR pucLatency +); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBitMode( + FT_HANDLE ftHandle, + UCHAR ucMask, + UCHAR ucEnable +); + +FTD2XX_API +FT_STATUS WINAPI FT_GetBitMode( + FT_HANDLE ftHandle, + PUCHAR pucMode +); + +FTD2XX_API +FT_STATUS WINAPI FT_SetUSBParameters( + FT_HANDLE ftHandle, + ULONG ulInTransferSize, + ULONG ulOutTransferSize +); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDeadmanTimeout( + FT_HANDLE ftHandle, + ULONG ulDeadmanTimeout +); #ifndef _WIN32 - // Extra functions for non-Windows platforms to compensate - // for lack of .INF file to specify Vendor and Product IDs. - - FTD2XX_API - FT_STATUS FT_SetVIDPID( - DWORD dwVID, - DWORD dwPID - ); - - FTD2XX_API - FT_STATUS FT_GetVIDPID( - DWORD * pdwVID, - DWORD * pdwPID - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetDeviceLocId( - FT_HANDLE ftHandle, - LPDWORD lpdwLocId - ); +// Extra functions for non-Windows platforms to compensate +// for lack of .INF file to specify Vendor and Product IDs. + +FTD2XX_API +FT_STATUS FT_SetVIDPID( + DWORD dwVID, + DWORD dwPID +); + +FTD2XX_API +FT_STATUS FT_GetVIDPID( + DWORD * pdwVID, + DWORD * pdwPID +); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceLocId( + FT_HANDLE ftHandle, + LPDWORD lpdwLocId +); #endif // _WIN32 - FTD2XX_API - FT_STATUS WINAPI FT_GetDeviceInfo( - FT_HANDLE ftHandle, - FT_DEVICE *lpftDevice, - LPDWORD lpdwID, - PCHAR SerialNumber, - PCHAR Description, - LPVOID Dummy - ); - - FTD2XX_API - FT_STATUS WINAPI FT_StopInTask( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_RestartInTask( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_SetResetPipeRetryCount( - FT_HANDLE ftHandle, - DWORD dwCount - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ResetPort( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_CyclePort( - FT_HANDLE ftHandle - ); +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfo( + FT_HANDLE ftHandle, + FT_DEVICE *lpftDevice, + LPDWORD lpdwID, + PCHAR SerialNumber, + PCHAR Description, + LPVOID Dummy +); + +FTD2XX_API +FT_STATUS WINAPI FT_StopInTask( + FT_HANDLE ftHandle +); + +FTD2XX_API +FT_STATUS WINAPI FT_RestartInTask( + FT_HANDLE ftHandle +); + +FTD2XX_API +FT_STATUS WINAPI FT_SetResetPipeRetryCount( + FT_HANDLE ftHandle, + DWORD dwCount +); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetPort( + FT_HANDLE ftHandle +); + +FTD2XX_API +FT_STATUS WINAPI FT_CyclePort( + FT_HANDLE ftHandle +); - // - // Win32-type functions - // +// +// Win32-type functions +// - FTD2XX_API - FT_HANDLE WINAPI FT_W32_CreateFile( - LPCTSTR lpszName, - DWORD dwAccess, - DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, - DWORD dwCreate, - DWORD dwAttrsAndFlags, - HANDLE hTemplate - ); - - FTD2XX_API - BOOL WINAPI FT_W32_CloseHandle( - FT_HANDLE ftHandle - ); - - FTD2XX_API - BOOL WINAPI FT_W32_ReadFile( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped - ); - - FTD2XX_API - BOOL WINAPI FT_W32_WriteFile( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesWritten, - LPOVERLAPPED lpOverlapped - ); - - FTD2XX_API - DWORD WINAPI FT_W32_GetLastError( - FT_HANDLE ftHandle - ); - - FTD2XX_API - BOOL WINAPI FT_W32_GetOverlappedResult( - FT_HANDLE ftHandle, - LPOVERLAPPED lpOverlapped, - LPDWORD lpdwBytesTransferred, - BOOL bWait - ); - - FTD2XX_API - BOOL WINAPI FT_W32_CancelIo( - FT_HANDLE ftHandle - ); +FTD2XX_API +FT_HANDLE WINAPI FT_W32_CreateFile( + LPCTSTR lpszName, + DWORD dwAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreate, + DWORD dwAttrsAndFlags, + HANDLE hTemplate +); + +FTD2XX_API +BOOL WINAPI FT_W32_CloseHandle( + FT_HANDLE ftHandle +); + +FTD2XX_API +BOOL WINAPI FT_W32_ReadFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped +); + +FTD2XX_API +BOOL WINAPI FT_W32_WriteFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten, + LPOVERLAPPED lpOverlapped +); + +FTD2XX_API +DWORD WINAPI FT_W32_GetLastError( + FT_HANDLE ftHandle +); + +FTD2XX_API +BOOL WINAPI FT_W32_GetOverlappedResult( + FT_HANDLE ftHandle, + LPOVERLAPPED lpOverlapped, + LPDWORD lpdwBytesTransferred, + BOOL bWait +); + +FTD2XX_API +BOOL WINAPI FT_W32_CancelIo( + FT_HANDLE ftHandle +); - // - // Win32 COMM API type functions - // - typedef struct _FTCOMSTAT { - DWORD fCtsHold : 1; - DWORD fDsrHold : 1; - DWORD fRlsdHold : 1; - DWORD fXoffHold : 1; - DWORD fXoffSent : 1; - DWORD fEof : 1; - DWORD fTxim : 1; - DWORD fReserved : 25; - DWORD cbInQue; - DWORD cbOutQue; - } FTCOMSTAT, *LPFTCOMSTAT; - - typedef struct _FTDCB { - DWORD DCBlength; /* sizeof(FTDCB) */ - DWORD BaudRate; /* Baudrate at which running */ - DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ - DWORD fParity: 1; /* Enable parity checking */ - DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ - DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ - DWORD fDtrControl:2; /* DTR Flow control */ - DWORD fDsrSensitivity:1; /* DSR Sensitivity */ - DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ - DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ - DWORD fInX: 1; /* Enable input X-ON/X-OFF */ - DWORD fErrorChar: 1; /* Enable Err Replacement */ - DWORD fNull: 1; /* Enable Null stripping */ - DWORD fRtsControl:2; /* Rts Flow control */ - DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ - DWORD fDummy2:17; /* Reserved */ - WORD wReserved; /* Not currently used */ - WORD XonLim; /* Transmit X-ON threshold */ - WORD XoffLim; /* Transmit X-OFF threshold */ - BYTE ByteSize; /* Number of bits/byte, 4-8 */ - BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ - BYTE StopBits; /* FT_STOP_BITS_1 or FT_STOP_BITS_2 */ - char XonChar; /* Tx and Rx X-ON character */ - char XoffChar; /* Tx and Rx X-OFF character */ - char ErrorChar; /* Error replacement char */ - char EofChar; /* End of Input character */ - char EvtChar; /* Received Event character */ - WORD wReserved1; /* Fill for now. */ - } FTDCB, *LPFTDCB; - - typedef struct _FTTIMEOUTS { - DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ - DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ - DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ - DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ - DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ - } FTTIMEOUTS,*LPFTTIMEOUTS; - - - FTD2XX_API - BOOL WINAPI FT_W32_ClearCommBreak( - FT_HANDLE ftHandle - ); - - FTD2XX_API - BOOL WINAPI FT_W32_ClearCommError( - FT_HANDLE ftHandle, - LPDWORD lpdwErrors, - LPFTCOMSTAT lpftComstat - ); - - FTD2XX_API - BOOL WINAPI FT_W32_EscapeCommFunction( - FT_HANDLE ftHandle, - DWORD dwFunc - ); - - FTD2XX_API - BOOL WINAPI FT_W32_GetCommModemStatus( - FT_HANDLE ftHandle, - LPDWORD lpdwModemStatus - ); - - FTD2XX_API - BOOL WINAPI FT_W32_GetCommState( - FT_HANDLE ftHandle, - LPFTDCB lpftDcb - ); - - FTD2XX_API - BOOL WINAPI FT_W32_GetCommTimeouts( - FT_HANDLE ftHandle, - FTTIMEOUTS *pTimeouts - ); - - FTD2XX_API - BOOL WINAPI FT_W32_PurgeComm( - FT_HANDLE ftHandle, - DWORD dwMask - ); - - FTD2XX_API - BOOL WINAPI FT_W32_SetCommBreak( - FT_HANDLE ftHandle - ); - - FTD2XX_API - BOOL WINAPI FT_W32_SetCommMask( - FT_HANDLE ftHandle, - ULONG ulEventMask - ); - - FTD2XX_API - BOOL WINAPI FT_W32_GetCommMask( - FT_HANDLE ftHandle, - LPDWORD lpdwEventMask - ); - - FTD2XX_API - BOOL WINAPI FT_W32_SetCommState( - FT_HANDLE ftHandle, - LPFTDCB lpftDcb - ); - - FTD2XX_API - BOOL WINAPI FT_W32_SetCommTimeouts( - FT_HANDLE ftHandle, - FTTIMEOUTS *pTimeouts - ); - - FTD2XX_API - BOOL WINAPI FT_W32_SetupComm( - FT_HANDLE ftHandle, - DWORD dwReadBufferSize, - DWORD dwWriteBufferSize - ); - - FTD2XX_API - BOOL WINAPI FT_W32_WaitCommEvent( - FT_HANDLE ftHandle, - PULONG pulEvent, - LPOVERLAPPED lpOverlapped - ); +// +// Win32 COMM API type functions +// +typedef struct _FTCOMSTAT +{ + DWORD fCtsHold : 1; + DWORD fDsrHold : 1; + DWORD fRlsdHold : 1; + DWORD fXoffHold : 1; + DWORD fXoffSent : 1; + DWORD fEof : 1; + DWORD fTxim : 1; + DWORD fReserved : 25; + DWORD cbInQue; + DWORD cbOutQue; +} FTCOMSTAT, *LPFTCOMSTAT; + +typedef struct _FTDCB +{ + DWORD DCBlength; /* sizeof(FTDCB) */ + DWORD BaudRate; /* Baudrate at which running */ + DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ + DWORD fParity: 1; /* Enable parity checking */ + DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ + DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ + DWORD fDtrControl:2; /* DTR Flow control */ + DWORD fDsrSensitivity:1; /* DSR Sensitivity */ + DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ + DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ + DWORD fInX: 1; /* Enable input X-ON/X-OFF */ + DWORD fErrorChar: 1; /* Enable Err Replacement */ + DWORD fNull: 1; /* Enable Null stripping */ + DWORD fRtsControl:2; /* Rts Flow control */ + DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ + DWORD fDummy2:17; /* Reserved */ + WORD wReserved; /* Not currently used */ + WORD XonLim; /* Transmit X-ON threshold */ + WORD XoffLim; /* Transmit X-OFF threshold */ + BYTE ByteSize; /* Number of bits/byte, 4-8 */ + BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ + BYTE StopBits; /* FT_STOP_BITS_1 or FT_STOP_BITS_2 */ + char XonChar; /* Tx and Rx X-ON character */ + char XoffChar; /* Tx and Rx X-OFF character */ + char ErrorChar; /* Error replacement char */ + char EofChar; /* End of Input character */ + char EvtChar; /* Received Event character */ + WORD wReserved1; /* Fill for now. */ +} FTDCB, *LPFTDCB; + +typedef struct _FTTIMEOUTS +{ + DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ + DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ + DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ +} FTTIMEOUTS,*LPFTTIMEOUTS; + + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommBreak( + FT_HANDLE ftHandle +); + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommError( + FT_HANDLE ftHandle, + LPDWORD lpdwErrors, + LPFTCOMSTAT lpftComstat +); + +FTD2XX_API +BOOL WINAPI FT_W32_EscapeCommFunction( + FT_HANDLE ftHandle, + DWORD dwFunc +); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommModemStatus( + FT_HANDLE ftHandle, + LPDWORD lpdwModemStatus +); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb +); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts +); + +FTD2XX_API +BOOL WINAPI FT_W32_PurgeComm( + FT_HANDLE ftHandle, + DWORD dwMask +); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommBreak( + FT_HANDLE ftHandle +); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommMask( + FT_HANDLE ftHandle, + ULONG ulEventMask +); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommMask( + FT_HANDLE ftHandle, + LPDWORD lpdwEventMask +); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb +); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts +); + +FTD2XX_API +BOOL WINAPI FT_W32_SetupComm( + FT_HANDLE ftHandle, + DWORD dwReadBufferSize, + DWORD dwWriteBufferSize +); + +FTD2XX_API +BOOL WINAPI FT_W32_WaitCommEvent( + FT_HANDLE ftHandle, + PULONG pulEvent, + LPOVERLAPPED lpOverlapped +); - // - // Device information - // +// +// Device information +// - typedef struct _ft_device_list_info_node { - ULONG Flags; - ULONG Type; - ULONG ID; - DWORD LocId; - char SerialNumber[16]; - char Description[64]; - FT_HANDLE ftHandle; - } FT_DEVICE_LIST_INFO_NODE; - - // Device information flags - enum { - FT_FLAGS_OPENED = 1, - FT_FLAGS_HISPEED = 2 - }; - - - FTD2XX_API - FT_STATUS WINAPI FT_CreateDeviceInfoList( - LPDWORD lpdwNumDevs - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetDeviceInfoList( - FT_DEVICE_LIST_INFO_NODE *pDest, - LPDWORD lpdwNumDevs - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetDeviceInfoDetail( - DWORD dwIndex, - LPDWORD lpdwFlags, - LPDWORD lpdwType, - LPDWORD lpdwID, - LPDWORD lpdwLocId, - LPVOID lpSerialNumber, - LPVOID lpDescription, - FT_HANDLE *pftHandle - ); +typedef struct _ft_device_list_info_node +{ + ULONG Flags; + ULONG Type; + ULONG ID; + DWORD LocId; + char SerialNumber[16]; + char Description[64]; + FT_HANDLE ftHandle; +} FT_DEVICE_LIST_INFO_NODE; + +// Device information flags +enum +{ + FT_FLAGS_OPENED = 1, + FT_FLAGS_HISPEED = 2 +}; - // - // Version information - // +FTD2XX_API +FT_STATUS WINAPI FT_CreateDeviceInfoList( + LPDWORD lpdwNumDevs +); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoList( + FT_DEVICE_LIST_INFO_NODE *pDest, + LPDWORD lpdwNumDevs +); - FTD2XX_API - FT_STATUS WINAPI FT_GetDriverVersion( - FT_HANDLE ftHandle, - LPDWORD lpdwVersion - ); +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoDetail( + DWORD dwIndex, + LPDWORD lpdwFlags, + LPDWORD lpdwType, + LPDWORD lpdwID, + LPDWORD lpdwLocId, + LPVOID lpSerialNumber, + LPVOID lpDescription, + FT_HANDLE *pftHandle +); - FTD2XX_API - FT_STATUS WINAPI FT_GetLibraryVersion( - LPDWORD lpdwVersion - ); +// +// Version information +// - FTD2XX_API - FT_STATUS WINAPI FT_Rescan( - void - ); +FTD2XX_API +FT_STATUS WINAPI FT_GetDriverVersion( + FT_HANDLE ftHandle, + LPDWORD lpdwVersion +); - FTD2XX_API - FT_STATUS WINAPI FT_Reload( - WORD wVid, - WORD wPid - ); +FTD2XX_API +FT_STATUS WINAPI FT_GetLibraryVersion( + LPDWORD lpdwVersion +); - FTD2XX_API - FT_STATUS WINAPI FT_GetComPortNumber( - FT_HANDLE ftHandle, - LPLONG lpdwComPortNumber - ); +FTD2XX_API +FT_STATUS WINAPI FT_Rescan( + void +); - // - // FT232H additional EEPROM functions - // +FTD2XX_API +FT_STATUS WINAPI FT_Reload( + WORD wVid, + WORD wPid +); + +FTD2XX_API +FT_STATUS WINAPI FT_GetComPortNumber( + FT_HANDLE ftHandle, + LPLONG lpdwComPortNumber +); + + +// +// FT232H additional EEPROM functions +// - FTD2XX_API - FT_STATUS WINAPI FT_EE_ReadConfig( - FT_HANDLE ftHandle, - UCHAR ucAddress, - PUCHAR pucValue - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_WriteConfig( - FT_HANDLE ftHandle, - UCHAR ucAddress, - UCHAR ucValue - ); - - FTD2XX_API - FT_STATUS WINAPI FT_EE_ReadECC( - FT_HANDLE ftHandle, - UCHAR ucOption, - LPWORD lpwValue - ); - - FTD2XX_API - FT_STATUS WINAPI FT_GetQueueStatusEx( - FT_HANDLE ftHandle, - DWORD *dwRxBytes - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ComPortIdle( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_ComPortCancelIdle( - FT_HANDLE ftHandle - ); - - FTD2XX_API - FT_STATUS WINAPI FT_VendorCmdGet( - FT_HANDLE ftHandle, - UCHAR Request, - UCHAR *Buf, - USHORT Len - ); - - FTD2XX_API - FT_STATUS WINAPI FT_VendorCmdSet( - FT_HANDLE ftHandle, - UCHAR Request, - UCHAR *Buf, - USHORT Len - ); - - FTD2XX_API - FT_STATUS WINAPI FT_VendorCmdGetEx( - FT_HANDLE ftHandle, - USHORT wValue, - UCHAR *Buf, - USHORT Len - ); - - FTD2XX_API - FT_STATUS WINAPI FT_VendorCmdSetEx( - FT_HANDLE ftHandle, - USHORT wValue, - UCHAR *Buf, - USHORT Len - ); +FTD2XX_API +FT_STATUS WINAPI FT_EE_ReadConfig( + FT_HANDLE ftHandle, + UCHAR ucAddress, + PUCHAR pucValue +); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_WriteConfig( + FT_HANDLE ftHandle, + UCHAR ucAddress, + UCHAR ucValue +); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ReadECC( + FT_HANDLE ftHandle, + UCHAR ucOption, + LPWORD lpwValue +); + +FTD2XX_API +FT_STATUS WINAPI FT_GetQueueStatusEx( + FT_HANDLE ftHandle, + DWORD *dwRxBytes +); + +FTD2XX_API +FT_STATUS WINAPI FT_ComPortIdle( + FT_HANDLE ftHandle +); + +FTD2XX_API +FT_STATUS WINAPI FT_ComPortCancelIdle( + FT_HANDLE ftHandle +); + +FTD2XX_API +FT_STATUS WINAPI FT_VendorCmdGet( + FT_HANDLE ftHandle, + UCHAR Request, + UCHAR *Buf, + USHORT Len +); + +FTD2XX_API +FT_STATUS WINAPI FT_VendorCmdSet( + FT_HANDLE ftHandle, + UCHAR Request, + UCHAR *Buf, + USHORT Len +); + +FTD2XX_API +FT_STATUS WINAPI FT_VendorCmdGetEx( + FT_HANDLE ftHandle, + USHORT wValue, + UCHAR *Buf, + USHORT Len +); + +FTD2XX_API +FT_STATUS WINAPI FT_VendorCmdSetEx( + FT_HANDLE ftHandle, + USHORT wValue, + UCHAR *Buf, + USHORT Len +); #ifdef __cplusplus } diff --git a/ambed/main.cpp b/ambed/main.cpp index 23e3666..392142a 100644 --- a/ambed/main.cpp +++ b/ambed/main.cpp @@ -35,24 +35,24 @@ int main() { - // initialize ambeserver - g_AmbeServer.SetListenIp(TRANSCODER_IP); - - // and let it run - std::cout << "Starting AMBEd " << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_REVISION << std::endl << std::endl; - if ( ! g_AmbeServer.Start() ) - { - std::cout << "Error starting AMBEd" << std::endl; - return EXIT_FAILURE; - } - std::cout << "AMBEd started and listening on " << g_AmbeServer.GetListenIp() << std::endl; + // initialize ambeserver + g_AmbeServer.SetListenIp(TRANSCODER_IP); + + // and let it run + std::cout << "Starting AMBEd " << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_REVISION << std::endl << std::endl; + if ( ! g_AmbeServer.Start() ) + { + std::cout << "Error starting AMBEd" << std::endl; + return EXIT_FAILURE; + } + std::cout << "AMBEd started and listening on " << g_AmbeServer.GetListenIp() << std::endl; pause(); // wait for any signal - // and wait for end - g_AmbeServer.Stop(); - std::cout << "AMBEd stopped" << std::endl; + // and wait for end + g_AmbeServer.Stop(); + std::cout << "AMBEd stopped" << std::endl; - // done - return EXIT_SUCCESS; + // done + return EXIT_SUCCESS; } diff --git a/ambed/main.h b/ambed/main.h index 0359749..ec0b541 100644 --- a/ambed/main.h +++ b/ambed/main.h @@ -127,10 +127,12 @@ grid #if USE_BANDPASSFILTER == 1 -const float FILTER_TAPS[] { --0.05063341f, -0.00060337f, -0.08892498f, -0.02026701f, -0.05940750f, -0.10977641f, 0.03244024f, -0.22304499f, -0.11452865f, 0.72500000f, 0.11452865f, -0.22304499f, 0.03244024f, -0.10977641f, -0.05940750f, -0.02026701f, --0.08892498f, -0.00060337f, -0.05063341f }; +const float FILTER_TAPS[] +{ + -0.05063341f, -0.00060337f, -0.08892498f, -0.02026701f, -0.05940750f, -0.10977641f, 0.03244024f, -0.22304499f, + 0.11452865f, 0.72500000f, 0.11452865f, -0.22304499f, 0.03244024f, -0.10977641f, -0.05940750f, -0.02026701f, + -0.08892498f, -0.00060337f, -0.05063341f + }; #define FILTER_TAPS_LENGTH 19 #endif diff --git a/src/cbmclient.cpp b/src/cbmclient.cpp index 8dc4b0c..271374c 100644 --- a/src/cbmclient.cpp +++ b/src/cbmclient.cpp @@ -35,12 +35,12 @@ CBmClient::CBmClient() } CBmClient::CBmClient(const CCallsign &callsign, const CIp &ip, char reflectorModule) - : CClient(callsign, ip, reflectorModule) + : CClient(callsign, ip, reflectorModule) { } CBmClient::CBmClient(const CBmClient &client) - : CClient(client) + : CClient(client) { } @@ -49,6 +49,6 @@ CBmClient::CBmClient(const CBmClient &client) bool CBmClient::IsAlive(void) const { - return (m_LastKeepaliveTime.DurationSinceNow() < XLX_KEEPALIVE_TIMEOUT); + return (m_LastKeepaliveTime.DurationSinceNow() < XLX_KEEPALIVE_TIMEOUT); } diff --git a/src/cbmclient.h b/src/cbmclient.h index fc47778..4e302c9 100644 --- a/src/cbmclient.h +++ b/src/cbmclient.h @@ -39,26 +39,26 @@ class CBmClient : public CClient { public: - // constructors - CBmClient(); - CBmClient(const CCallsign &, const CIp &, char = ' '); - CBmClient(const CBmClient &); - - // destructor - virtual ~CBmClient() {}; - - // identity - int GetProtocol(void) const { return PROTOCOL_XLX; } - int GetProtocolRevision(void) const { return XLX_PROTOCOL_REVISION_2; } - const char *GetProtocolName(void) const { return "XLX"; } - int GetCodec(void) const { return CODEC_AMBE2PLUS; } - bool IsPeer(void) const { return true; } - - // status - bool IsAlive(void) const; - - // reporting - void WriteXml(std::ofstream &) {} + // constructors + CBmClient(); + CBmClient(const CCallsign &, const CIp &, char = ' '); + CBmClient(const CBmClient &); + + // destructor + virtual ~CBmClient() {}; + + // identity + int GetProtocol(void) const { return PROTOCOL_XLX; } + int GetProtocolRevision(void) const { return XLX_PROTOCOL_REVISION_2; } + const char *GetProtocolName(void) const { return "XLX"; } + int GetCodec(void) const { return CODEC_AMBE2PLUS; } + bool IsPeer(void) const { return true; } + + // status + bool IsAlive(void) const; + + // reporting + void WriteXml(std::ofstream &) {} }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cbmpeer.cpp b/src/cbmpeer.cpp index 36a3e4d..84e6c91 100644 --- a/src/cbmpeer.cpp +++ b/src/cbmpeer.cpp @@ -38,16 +38,16 @@ CBmPeer::CBmPeer() } CBmPeer::CBmPeer(const CCallsign &callsign, const CIp &ip, const char *modules, const CVersion &version) -: CPeer(callsign, ip, modules, version) + : CPeer(callsign, ip, modules, version) { - std::cout << "Adding BM peer" << std::endl; + std::cout << "Adding BM peer" << std::endl; - // and construct all xlx clients - for ( unsigned i = 0; i < ::strlen(modules); i++ ) - { - // create and append to vector - m_Clients.push_back(std::make_shared(callsign, ip, modules[i])); - } + // and construct all xlx clients + for ( unsigned i = 0; i < ::strlen(modules); i++ ) + { + // create and append to vector + m_Clients.push_back(std::make_shared(callsign, ip, modules[i])); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -55,7 +55,7 @@ CBmPeer::CBmPeer(const CCallsign &callsign, const CIp &ip, const char *modules, bool CBmPeer::IsAlive(void) const { - return (m_LastKeepaliveTime.DurationSinceNow() < XLX_KEEPALIVE_TIMEOUT); + return (m_LastKeepaliveTime.DurationSinceNow() < XLX_KEEPALIVE_TIMEOUT); } //////////////////////////////////////////////////////////////////////////////////////// @@ -63,5 +63,5 @@ bool CBmPeer::IsAlive(void) const int CBmPeer::GetProtocolRevision(const CVersion &version) { - return XLX_PROTOCOL_REVISION_2; + return XLX_PROTOCOL_REVISION_2; } diff --git a/src/cbmpeer.h b/src/cbmpeer.h index 2e78e07..acda26b 100644 --- a/src/cbmpeer.h +++ b/src/cbmpeer.h @@ -39,20 +39,20 @@ class CBmPeer : public CPeer { public: - // constructors - CBmPeer(); - CBmPeer(const CCallsign &, const CIp &, const char *, const CVersion &); - CBmPeer(const CBmPeer &) = delete; + // constructors + CBmPeer(); + CBmPeer(const CCallsign &, const CIp &, const char *, const CVersion &); + CBmPeer(const CBmPeer &) = delete; - // status - bool IsAlive(void) const; + // status + bool IsAlive(void) const; - // identity - int GetProtocol(void) const { return PROTOCOL_XLX; } - const char *GetProtocolName(void) const { return "XLX"; } + // identity + int GetProtocol(void) const { return PROTOCOL_XLX; } + const char *GetProtocolName(void) const { return "XLX"; } - // revision helper - static int GetProtocolRevision(const CVersion &); + // revision helper + static int GetProtocolRevision(const CVersion &); }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cbptc19696.cpp b/src/cbptc19696.cpp index 226fbb0..a5f6e7f 100644 --- a/src/cbptc19696.cpp +++ b/src/cbptc19696.cpp @@ -37,305 +37,318 @@ CBPTC19696::~CBPTC19696() // The main decode function void CBPTC19696::decode(const unsigned char* in, unsigned char* out) { - assert(in != nullptr); - assert(out != nullptr); + assert(in != nullptr); + assert(out != nullptr); - // Get the raw binary - decodeExtractBinary(in); + // Get the raw binary + decodeExtractBinary(in); - // Deinterleave - decodeDeInterleave(); + // Deinterleave + decodeDeInterleave(); - // Error check - decodeErrorCheck(); + // Error check + decodeErrorCheck(); - // Extract Data - decodeExtractData(out); + // Extract Data + decodeExtractData(out); } // The main encode function void CBPTC19696::encode(const unsigned char* in, unsigned char* out) { - assert(in != nullptr); - assert(out != nullptr); + assert(in != nullptr); + assert(out != nullptr); - // Extract Data - encodeExtractData(in); + // Extract Data + encodeExtractData(in); - // Error check - encodeErrorCheck(); + // Error check + encodeErrorCheck(); - // Deinterleave - encodeInterleave(); + // Deinterleave + encodeInterleave(); - // Get the raw binary - encodeExtractBinary(out); + // Get the raw binary + encodeExtractBinary(out); } void CBPTC19696::decodeExtractBinary(const unsigned char* in) { - // First block - CUtils::byteToBitsBE(in[0U], m_rawData + 0U); - CUtils::byteToBitsBE(in[1U], m_rawData + 8U); - CUtils::byteToBitsBE(in[2U], m_rawData + 16U); - CUtils::byteToBitsBE(in[3U], m_rawData + 24U); - CUtils::byteToBitsBE(in[4U], m_rawData + 32U); - CUtils::byteToBitsBE(in[5U], m_rawData + 40U); - CUtils::byteToBitsBE(in[6U], m_rawData + 48U); - CUtils::byteToBitsBE(in[7U], m_rawData + 56U); - CUtils::byteToBitsBE(in[8U], m_rawData + 64U); - CUtils::byteToBitsBE(in[9U], m_rawData + 72U); - CUtils::byteToBitsBE(in[10U], m_rawData + 80U); - CUtils::byteToBitsBE(in[11U], m_rawData + 88U); - CUtils::byteToBitsBE(in[12U], m_rawData + 96U); - - // Handle the two bits - bool bits[8U]; - CUtils::byteToBitsBE(in[20U], bits); - m_rawData[98U] = bits[6U]; - m_rawData[99U] = bits[7U]; - - // Second block - CUtils::byteToBitsBE(in[21U], m_rawData + 100U); - CUtils::byteToBitsBE(in[22U], m_rawData + 108U); - CUtils::byteToBitsBE(in[23U], m_rawData + 116U); - CUtils::byteToBitsBE(in[24U], m_rawData + 124U); - CUtils::byteToBitsBE(in[25U], m_rawData + 132U); - CUtils::byteToBitsBE(in[26U], m_rawData + 140U); - CUtils::byteToBitsBE(in[27U], m_rawData + 148U); - CUtils::byteToBitsBE(in[28U], m_rawData + 156U); - CUtils::byteToBitsBE(in[29U], m_rawData + 164U); - CUtils::byteToBitsBE(in[30U], m_rawData + 172U); - CUtils::byteToBitsBE(in[31U], m_rawData + 180U); - CUtils::byteToBitsBE(in[32U], m_rawData + 188U); + // First block + CUtils::byteToBitsBE(in[0U], m_rawData + 0U); + CUtils::byteToBitsBE(in[1U], m_rawData + 8U); + CUtils::byteToBitsBE(in[2U], m_rawData + 16U); + CUtils::byteToBitsBE(in[3U], m_rawData + 24U); + CUtils::byteToBitsBE(in[4U], m_rawData + 32U); + CUtils::byteToBitsBE(in[5U], m_rawData + 40U); + CUtils::byteToBitsBE(in[6U], m_rawData + 48U); + CUtils::byteToBitsBE(in[7U], m_rawData + 56U); + CUtils::byteToBitsBE(in[8U], m_rawData + 64U); + CUtils::byteToBitsBE(in[9U], m_rawData + 72U); + CUtils::byteToBitsBE(in[10U], m_rawData + 80U); + CUtils::byteToBitsBE(in[11U], m_rawData + 88U); + CUtils::byteToBitsBE(in[12U], m_rawData + 96U); + + // Handle the two bits + bool bits[8U]; + CUtils::byteToBitsBE(in[20U], bits); + m_rawData[98U] = bits[6U]; + m_rawData[99U] = bits[7U]; + + // Second block + CUtils::byteToBitsBE(in[21U], m_rawData + 100U); + CUtils::byteToBitsBE(in[22U], m_rawData + 108U); + CUtils::byteToBitsBE(in[23U], m_rawData + 116U); + CUtils::byteToBitsBE(in[24U], m_rawData + 124U); + CUtils::byteToBitsBE(in[25U], m_rawData + 132U); + CUtils::byteToBitsBE(in[26U], m_rawData + 140U); + CUtils::byteToBitsBE(in[27U], m_rawData + 148U); + CUtils::byteToBitsBE(in[28U], m_rawData + 156U); + CUtils::byteToBitsBE(in[29U], m_rawData + 164U); + CUtils::byteToBitsBE(in[30U], m_rawData + 172U); + CUtils::byteToBitsBE(in[31U], m_rawData + 180U); + CUtils::byteToBitsBE(in[32U], m_rawData + 188U); } // Deinterleave the raw data void CBPTC19696::decodeDeInterleave() { - for (unsigned int i = 0U; i < 196U; i++) - m_deInterData[i] = false; - - // The first bit is R(3) which is not used so can be ignored - for (unsigned int a = 0U; a < 196U; a++) { - // Calculate the interleave sequence - unsigned int interleaveSequence = (a * 181U) % 196U; - // Shuffle the data - m_deInterData[a] = m_rawData[interleaveSequence]; - } + for (unsigned int i = 0U; i < 196U; i++) + m_deInterData[i] = false; + + // The first bit is R(3) which is not used so can be ignored + for (unsigned int a = 0U; a < 196U; a++) + { + // Calculate the interleave sequence + unsigned int interleaveSequence = (a * 181U) % 196U; + // Shuffle the data + m_deInterData[a] = m_rawData[interleaveSequence]; + } } // Check each row with a Hamming (15,11,3) code and each column with a Hamming (13,9,3) code void CBPTC19696::decodeErrorCheck() { - bool fixing; - unsigned int count = 0U; - do { - fixing = false; - - // Run through each of the 15 columns - bool col[13U]; - for (unsigned int c = 0U; c < 15U; c++) { - unsigned int pos = c + 1U; - for (unsigned int a = 0U; a < 13U; a++) { - col[a] = m_deInterData[pos]; - pos = pos + 15U; - } - - if (CHamming::decode1393(col)) { - unsigned int pos = c + 1U; - for (unsigned int a = 0U; a < 13U; a++) { - m_deInterData[pos] = col[a]; - pos = pos + 15U; - } - - fixing = true; - } - } - - // Run through each of the 9 rows containing data - for (unsigned int r = 0U; r < 9U; r++) { - unsigned int pos = (r * 15U) + 1U; - if (CHamming::decode15113_2(m_deInterData + pos)) - fixing = true; - } - - count++; - } while (fixing && count < 5U); + bool fixing; + unsigned int count = 0U; + do + { + fixing = false; + + // Run through each of the 15 columns + bool col[13U]; + for (unsigned int c = 0U; c < 15U; c++) + { + unsigned int pos = c + 1U; + for (unsigned int a = 0U; a < 13U; a++) + { + col[a] = m_deInterData[pos]; + pos = pos + 15U; + } + + if (CHamming::decode1393(col)) + { + unsigned int pos = c + 1U; + for (unsigned int a = 0U; a < 13U; a++) + { + m_deInterData[pos] = col[a]; + pos = pos + 15U; + } + + fixing = true; + } + } + + // Run through each of the 9 rows containing data + for (unsigned int r = 0U; r < 9U; r++) + { + unsigned int pos = (r * 15U) + 1U; + if (CHamming::decode15113_2(m_deInterData + pos)) + fixing = true; + } + + count++; + } + while (fixing && count < 5U); } // Extract the 96 bits of payload void CBPTC19696::decodeExtractData(unsigned char* data) const { - bool bData[96U]; - unsigned int pos = 0U; - for (unsigned int a = 4U; a <= 11U; a++, pos++) - bData[pos] = m_deInterData[a]; - - for (unsigned int a = 16U; a <= 26U; a++, pos++) - bData[pos] = m_deInterData[a]; - - for (unsigned int a = 31U; a <= 41U; a++, pos++) - bData[pos] = m_deInterData[a]; - - for (unsigned int a = 46U; a <= 56U; a++, pos++) - bData[pos] = m_deInterData[a]; - - for (unsigned int a = 61U; a <= 71U; a++, pos++) - bData[pos] = m_deInterData[a]; - - for (unsigned int a = 76U; a <= 86U; a++, pos++) - bData[pos] = m_deInterData[a]; - - for (unsigned int a = 91U; a <= 101U; a++, pos++) - bData[pos] = m_deInterData[a]; - - for (unsigned int a = 106U; a <= 116U; a++, pos++) - bData[pos] = m_deInterData[a]; - - for (unsigned int a = 121U; a <= 131U; a++, pos++) - bData[pos] = m_deInterData[a]; - - CUtils::bitsToByteBE(bData + 0U, data[0U]); - CUtils::bitsToByteBE(bData + 8U, data[1U]); - CUtils::bitsToByteBE(bData + 16U, data[2U]); - CUtils::bitsToByteBE(bData + 24U, data[3U]); - CUtils::bitsToByteBE(bData + 32U, data[4U]); - CUtils::bitsToByteBE(bData + 40U, data[5U]); - CUtils::bitsToByteBE(bData + 48U, data[6U]); - CUtils::bitsToByteBE(bData + 56U, data[7U]); - CUtils::bitsToByteBE(bData + 64U, data[8U]); - CUtils::bitsToByteBE(bData + 72U, data[9U]); - CUtils::bitsToByteBE(bData + 80U, data[10U]); - CUtils::bitsToByteBE(bData + 88U, data[11U]); + bool bData[96U]; + unsigned int pos = 0U; + for (unsigned int a = 4U; a <= 11U; a++, pos++) + bData[pos] = m_deInterData[a]; + + for (unsigned int a = 16U; a <= 26U; a++, pos++) + bData[pos] = m_deInterData[a]; + + for (unsigned int a = 31U; a <= 41U; a++, pos++) + bData[pos] = m_deInterData[a]; + + for (unsigned int a = 46U; a <= 56U; a++, pos++) + bData[pos] = m_deInterData[a]; + + for (unsigned int a = 61U; a <= 71U; a++, pos++) + bData[pos] = m_deInterData[a]; + + for (unsigned int a = 76U; a <= 86U; a++, pos++) + bData[pos] = m_deInterData[a]; + + for (unsigned int a = 91U; a <= 101U; a++, pos++) + bData[pos] = m_deInterData[a]; + + for (unsigned int a = 106U; a <= 116U; a++, pos++) + bData[pos] = m_deInterData[a]; + + for (unsigned int a = 121U; a <= 131U; a++, pos++) + bData[pos] = m_deInterData[a]; + + CUtils::bitsToByteBE(bData + 0U, data[0U]); + CUtils::bitsToByteBE(bData + 8U, data[1U]); + CUtils::bitsToByteBE(bData + 16U, data[2U]); + CUtils::bitsToByteBE(bData + 24U, data[3U]); + CUtils::bitsToByteBE(bData + 32U, data[4U]); + CUtils::bitsToByteBE(bData + 40U, data[5U]); + CUtils::bitsToByteBE(bData + 48U, data[6U]); + CUtils::bitsToByteBE(bData + 56U, data[7U]); + CUtils::bitsToByteBE(bData + 64U, data[8U]); + CUtils::bitsToByteBE(bData + 72U, data[9U]); + CUtils::bitsToByteBE(bData + 80U, data[10U]); + CUtils::bitsToByteBE(bData + 88U, data[11U]); } // Extract the 96 bits of payload void CBPTC19696::encodeExtractData(const unsigned char* in) { - bool bData[96U]; - CUtils::byteToBitsBE(in[0U], bData + 0U); - CUtils::byteToBitsBE(in[1U], bData + 8U); - CUtils::byteToBitsBE(in[2U], bData + 16U); - CUtils::byteToBitsBE(in[3U], bData + 24U); - CUtils::byteToBitsBE(in[4U], bData + 32U); - CUtils::byteToBitsBE(in[5U], bData + 40U); - CUtils::byteToBitsBE(in[6U], bData + 48U); - CUtils::byteToBitsBE(in[7U], bData + 56U); - CUtils::byteToBitsBE(in[8U], bData + 64U); - CUtils::byteToBitsBE(in[9U], bData + 72U); - CUtils::byteToBitsBE(in[10U], bData + 80U); - CUtils::byteToBitsBE(in[11U], bData + 88U); - - for (unsigned int i = 0U; i < 196U; i++) - m_deInterData[i] = false; - - unsigned int pos = 0U; - for (unsigned int a = 4U; a <= 11U; a++, pos++) - m_deInterData[a] = bData[pos]; - - for (unsigned int a = 16U; a <= 26U; a++, pos++) - m_deInterData[a] = bData[pos]; - - for (unsigned int a = 31U; a <= 41U; a++, pos++) - m_deInterData[a] = bData[pos]; - - for (unsigned int a = 46U; a <= 56U; a++, pos++) - m_deInterData[a] = bData[pos]; - - for (unsigned int a = 61U; a <= 71U; a++, pos++) - m_deInterData[a] = bData[pos]; - - for (unsigned int a = 76U; a <= 86U; a++, pos++) - m_deInterData[a] = bData[pos]; - - for (unsigned int a = 91U; a <= 101U; a++, pos++) - m_deInterData[a] = bData[pos]; - - for (unsigned int a = 106U; a <= 116U; a++, pos++) - m_deInterData[a] = bData[pos]; - - for (unsigned int a = 121U; a <= 131U; a++, pos++) - m_deInterData[a] = bData[pos]; + bool bData[96U]; + CUtils::byteToBitsBE(in[0U], bData + 0U); + CUtils::byteToBitsBE(in[1U], bData + 8U); + CUtils::byteToBitsBE(in[2U], bData + 16U); + CUtils::byteToBitsBE(in[3U], bData + 24U); + CUtils::byteToBitsBE(in[4U], bData + 32U); + CUtils::byteToBitsBE(in[5U], bData + 40U); + CUtils::byteToBitsBE(in[6U], bData + 48U); + CUtils::byteToBitsBE(in[7U], bData + 56U); + CUtils::byteToBitsBE(in[8U], bData + 64U); + CUtils::byteToBitsBE(in[9U], bData + 72U); + CUtils::byteToBitsBE(in[10U], bData + 80U); + CUtils::byteToBitsBE(in[11U], bData + 88U); + + for (unsigned int i = 0U; i < 196U; i++) + m_deInterData[i] = false; + + unsigned int pos = 0U; + for (unsigned int a = 4U; a <= 11U; a++, pos++) + m_deInterData[a] = bData[pos]; + + for (unsigned int a = 16U; a <= 26U; a++, pos++) + m_deInterData[a] = bData[pos]; + + for (unsigned int a = 31U; a <= 41U; a++, pos++) + m_deInterData[a] = bData[pos]; + + for (unsigned int a = 46U; a <= 56U; a++, pos++) + m_deInterData[a] = bData[pos]; + + for (unsigned int a = 61U; a <= 71U; a++, pos++) + m_deInterData[a] = bData[pos]; + + for (unsigned int a = 76U; a <= 86U; a++, pos++) + m_deInterData[a] = bData[pos]; + + for (unsigned int a = 91U; a <= 101U; a++, pos++) + m_deInterData[a] = bData[pos]; + + for (unsigned int a = 106U; a <= 116U; a++, pos++) + m_deInterData[a] = bData[pos]; + + for (unsigned int a = 121U; a <= 131U; a++, pos++) + m_deInterData[a] = bData[pos]; } // Check each row with a Hamming (15,11,3) code and each column with a Hamming (13,9,3) code void CBPTC19696::encodeErrorCheck() { - // Run through each of the 9 rows containing data - for (unsigned int r = 0U; r < 9U; r++) { - unsigned int pos = (r * 15U) + 1U; - CHamming::encode15113_2(m_deInterData + pos); - } - - // Run through each of the 15 columns - bool col[13U]; - for (unsigned int c = 0U; c < 15U; c++) { - unsigned int pos = c + 1U; - for (unsigned int a = 0U; a < 13U; a++) { - col[a] = m_deInterData[pos]; - pos = pos + 15U; - } - - CHamming::encode1393(col); - - pos = c + 1U; - for (unsigned int a = 0U; a < 13U; a++) { - m_deInterData[pos] = col[a]; - pos = pos + 15U; - } - } + // Run through each of the 9 rows containing data + for (unsigned int r = 0U; r < 9U; r++) + { + unsigned int pos = (r * 15U) + 1U; + CHamming::encode15113_2(m_deInterData + pos); + } + + // Run through each of the 15 columns + bool col[13U]; + for (unsigned int c = 0U; c < 15U; c++) + { + unsigned int pos = c + 1U; + for (unsigned int a = 0U; a < 13U; a++) + { + col[a] = m_deInterData[pos]; + pos = pos + 15U; + } + + CHamming::encode1393(col); + + pos = c + 1U; + for (unsigned int a = 0U; a < 13U; a++) + { + m_deInterData[pos] = col[a]; + pos = pos + 15U; + } + } } // Interleave the raw data void CBPTC19696::encodeInterleave() { - for (unsigned int i = 0U; i < 196U; i++) - m_rawData[i] = false; - - // The first bit is R(3) which is not used so can be ignored - for (unsigned int a = 0U; a < 196U; a++) { - // Calculate the interleave sequence - unsigned int interleaveSequence = (a * 181U) % 196U; - // Unshuffle the data - m_rawData[interleaveSequence] = m_deInterData[a]; - } + for (unsigned int i = 0U; i < 196U; i++) + m_rawData[i] = false; + + // The first bit is R(3) which is not used so can be ignored + for (unsigned int a = 0U; a < 196U; a++) + { + // Calculate the interleave sequence + unsigned int interleaveSequence = (a * 181U) % 196U; + // Unshuffle the data + m_rawData[interleaveSequence] = m_deInterData[a]; + } } void CBPTC19696::encodeExtractBinary(unsigned char* data) { - // First block - CUtils::bitsToByteBE(m_rawData + 0U, data[0U]); - CUtils::bitsToByteBE(m_rawData + 8U, data[1U]); - CUtils::bitsToByteBE(m_rawData + 16U, data[2U]); - CUtils::bitsToByteBE(m_rawData + 24U, data[3U]); - CUtils::bitsToByteBE(m_rawData + 32U, data[4U]); - CUtils::bitsToByteBE(m_rawData + 40U, data[5U]); - CUtils::bitsToByteBE(m_rawData + 48U, data[6U]); - CUtils::bitsToByteBE(m_rawData + 56U, data[7U]); - CUtils::bitsToByteBE(m_rawData + 64U, data[8U]); - CUtils::bitsToByteBE(m_rawData + 72U, data[9U]); - CUtils::bitsToByteBE(m_rawData + 80U, data[10U]); - CUtils::bitsToByteBE(m_rawData + 88U, data[11U]); - - // Handle the two bits - unsigned char byte; - CUtils::bitsToByteBE(m_rawData + 96U, byte); - data[12U] = (data[12U] & 0x3FU) | ((byte >> 0) & 0xC0U); - data[20U] = (data[20U] & 0xFCU) | ((byte >> 4) & 0x03U); - - // Second block - CUtils::bitsToByteBE(m_rawData + 100U, data[21U]); - CUtils::bitsToByteBE(m_rawData + 108U, data[22U]); - CUtils::bitsToByteBE(m_rawData + 116U, data[23U]); - CUtils::bitsToByteBE(m_rawData + 124U, data[24U]); - CUtils::bitsToByteBE(m_rawData + 132U, data[25U]); - CUtils::bitsToByteBE(m_rawData + 140U, data[26U]); - CUtils::bitsToByteBE(m_rawData + 148U, data[27U]); - CUtils::bitsToByteBE(m_rawData + 156U, data[28U]); - CUtils::bitsToByteBE(m_rawData + 164U, data[29U]); - CUtils::bitsToByteBE(m_rawData + 172U, data[30U]); - CUtils::bitsToByteBE(m_rawData + 180U, data[31U]); - CUtils::bitsToByteBE(m_rawData + 188U, data[32U]); + // First block + CUtils::bitsToByteBE(m_rawData + 0U, data[0U]); + CUtils::bitsToByteBE(m_rawData + 8U, data[1U]); + CUtils::bitsToByteBE(m_rawData + 16U, data[2U]); + CUtils::bitsToByteBE(m_rawData + 24U, data[3U]); + CUtils::bitsToByteBE(m_rawData + 32U, data[4U]); + CUtils::bitsToByteBE(m_rawData + 40U, data[5U]); + CUtils::bitsToByteBE(m_rawData + 48U, data[6U]); + CUtils::bitsToByteBE(m_rawData + 56U, data[7U]); + CUtils::bitsToByteBE(m_rawData + 64U, data[8U]); + CUtils::bitsToByteBE(m_rawData + 72U, data[9U]); + CUtils::bitsToByteBE(m_rawData + 80U, data[10U]); + CUtils::bitsToByteBE(m_rawData + 88U, data[11U]); + + // Handle the two bits + unsigned char byte; + CUtils::bitsToByteBE(m_rawData + 96U, byte); + data[12U] = (data[12U] & 0x3FU) | ((byte >> 0) & 0xC0U); + data[20U] = (data[20U] & 0xFCU) | ((byte >> 4) & 0x03U); + + // Second block + CUtils::bitsToByteBE(m_rawData + 100U, data[21U]); + CUtils::bitsToByteBE(m_rawData + 108U, data[22U]); + CUtils::bitsToByteBE(m_rawData + 116U, data[23U]); + CUtils::bitsToByteBE(m_rawData + 124U, data[24U]); + CUtils::bitsToByteBE(m_rawData + 132U, data[25U]); + CUtils::bitsToByteBE(m_rawData + 140U, data[26U]); + CUtils::bitsToByteBE(m_rawData + 148U, data[27U]); + CUtils::bitsToByteBE(m_rawData + 156U, data[28U]); + CUtils::bitsToByteBE(m_rawData + 164U, data[29U]); + CUtils::bitsToByteBE(m_rawData + 172U, data[30U]); + CUtils::bitsToByteBE(m_rawData + 180U, data[31U]); + CUtils::bitsToByteBE(m_rawData + 188U, data[32U]); } diff --git a/src/cbptc19696.h b/src/cbptc19696.h index f1b690c..cbf584c 100644 --- a/src/cbptc19696.h +++ b/src/cbptc19696.h @@ -22,26 +22,26 @@ class CBPTC19696 { public: - CBPTC19696(); - ~CBPTC19696(); - - void decode(const unsigned char* in, unsigned char* out); - - void encode(const unsigned char* in, unsigned char* out); - + CBPTC19696(); + ~CBPTC19696(); + + void decode(const unsigned char* in, unsigned char* out); + + void encode(const unsigned char* in, unsigned char* out); + private: - bool m_rawData[196]; - bool m_deInterData[196]; - - void decodeExtractBinary(const unsigned char* in); - void decodeErrorCheck(); - void decodeDeInterleave(); - void decodeExtractData(unsigned char* data) const; - - void encodeExtractData(const unsigned char* in); - void encodeInterleave(); - void encodeErrorCheck(); - void encodeExtractBinary(unsigned char* data); + bool m_rawData[196]; + bool m_deInterData[196]; + + void decodeExtractBinary(const unsigned char* in); + void decodeErrorCheck(); + void decodeDeInterleave(); + void decodeExtractData(unsigned char* data) const; + + void encodeExtractData(const unsigned char* in); + void encodeInterleave(); + void encodeErrorCheck(); + void encodeExtractBinary(unsigned char* data); }; #endif diff --git a/src/cbuffer.cpp b/src/cbuffer.cpp index 6603e5f..6c2097a 100644 --- a/src/cbuffer.cpp +++ b/src/cbuffer.cpp @@ -92,7 +92,8 @@ void CBuffer::Append(const char *sz) void CBuffer::ReplaceAt(int i, uint8_t ui) { - if ( m_data.size() < (i+sizeof(uint8_t)) ) { + if ( m_data.size() < (i+sizeof(uint8_t)) ) + { m_data.resize(i+sizeof(uint8_t)); } *(uint8_t *)(&(m_data.data()[i])) = ui; @@ -100,7 +101,8 @@ void CBuffer::ReplaceAt(int i, uint8_t ui) void CBuffer::ReplaceAt(int i, uint16_t ui) { - if ( m_data.size() < (i+sizeof(uint16_t)) ) { + if ( m_data.size() < (i+sizeof(uint16_t)) ) + { m_data.resize(i+sizeof(uint16_t)); } *(uint16_t *)(&(m_data.data()[i])) = ui; @@ -108,7 +110,8 @@ void CBuffer::ReplaceAt(int i, uint16_t ui) void CBuffer::ReplaceAt(int i, uint32_t ui) { - if ( m_data.size() < (i+sizeof(uint32_t)) ) { + if ( m_data.size() < (i+sizeof(uint32_t)) ) + { m_data.resize(i+sizeof(uint32_t)); } *(uint32_t *)(&(m_data.data()[i])) = ui; @@ -116,7 +119,8 @@ void CBuffer::ReplaceAt(int i, uint32_t ui) void CBuffer::ReplaceAt(int i, const uint8_t *ptr, int len) { - if ( m_data.size() < unsigned(i+len) ) { + if ( m_data.size() < unsigned(i+len) ) + { m_data.resize(i+len); } ::memcpy(&(m_data.data()[i]), ptr, len); @@ -128,7 +132,8 @@ void CBuffer::ReplaceAt(int i, const uint8_t *ptr, int len) int CBuffer::Compare(uint8_t *buffer, int len) const { int result = -1; - if ( m_data.size() >= unsigned(len) ) { + if ( m_data.size() >= unsigned(len) ) + { result = ::memcmp(m_data.data(), buffer, len); } return result; @@ -137,7 +142,8 @@ int CBuffer::Compare(uint8_t *buffer, int len) const int CBuffer::Compare(uint8_t *buffer, int off, int len) const { int result = -1; - if ( m_data.size() >= unsigned(off+len) ) { + if ( m_data.size() >= unsigned(off+len) ) + { result = ::memcmp(&(m_data.data()[off]), buffer, len); } return result; @@ -149,7 +155,8 @@ int CBuffer::Compare(uint8_t *buffer, int off, int len) const bool CBuffer::operator ==(const CBuffer &Buffer) const { - if ( m_data.size() == Buffer.m_data.size() ) { + if ( m_data.size() == Buffer.m_data.size() ) + { return (::memcmp((const char *)m_data.data(), (const char *)Buffer.m_data.data(), m_data.size()) == 0); } return false; @@ -157,7 +164,8 @@ bool CBuffer::operator ==(const CBuffer &Buffer) const bool CBuffer::operator ==(const char *sz) const { - if ( m_data.size() == ::strlen(sz) ) { + if ( m_data.size() == ::strlen(sz) ) + { return (::memcmp((const char *)m_data.data(), sz, m_data.size()) == 0); } return false; @@ -174,14 +182,18 @@ CBuffer::operator const char *() const void CBuffer::DebugDump(std::ofstream &debugout) const { // dump an hex line - for ( unsigned int i = 0; i < m_data.size(); i++ ) { + for ( unsigned int i = 0; i < m_data.size(); i++ ) + { char sz[16]; //sprintf(sz, "%02X", m_data.data()[i]); sprintf(sz, "0x%02X", m_data.data()[i]); debugout << sz; - if ( i == m_data.size()-1 ) { + if ( i == m_data.size()-1 ) + { debugout << std::endl; - } else { + } + else + { debugout << ','; } } @@ -190,14 +202,19 @@ void CBuffer::DebugDump(std::ofstream &debugout) const void CBuffer::DebugDumpAscii(std::ofstream &debugout) const { // dump an ascii line - for ( unsigned int i = 0; i < m_data.size(); i++ ) { + for ( unsigned int i = 0; i < m_data.size(); i++ ) + { char c = m_data.data()[i]; - if ( isascii(c) ) { + if ( isascii(c) ) + { debugout << c; - } else { + } + else + { debugout << '.'; } - if ( i == m_data.size()-1 ) { + if ( i == m_data.size()-1 ) + { debugout << std::endl; } } diff --git a/src/ccallsign.cpp b/src/ccallsign.cpp index 52dd9bd..0dcb7b5 100644 --- a/src/ccallsign.cpp +++ b/src/ccallsign.cpp @@ -34,49 +34,49 @@ CCallsign::CCallsign() { - // blank all - ::memset(m_Callsign, ' ', sizeof(m_Callsign)); - ::memset(m_Suffix, ' ', sizeof(m_Suffix)); - m_Module = ' '; + // blank all + ::memset(m_Callsign, ' ', sizeof(m_Callsign)); + ::memset(m_Suffix, ' ', sizeof(m_Suffix)); + m_Module = ' '; #ifndef NO_XLX - m_uiDmrid = 0; + m_uiDmrid = 0; #endif } CCallsign::CCallsign(const char *sz, uint32 dmrid) { - // blank all - ::memset(m_Callsign, ' ', sizeof(m_Callsign)); - ::memset(m_Suffix, ' ', sizeof(m_Suffix)); - m_Module = ' '; + // blank all + ::memset(m_Callsign, ' ', sizeof(m_Callsign)); + ::memset(m_Suffix, ' ', sizeof(m_Suffix)); + m_Module = ' '; #ifndef NO_XLX - m_uiDmrid = dmrid; + m_uiDmrid = dmrid; #endif - // and populate - if ( ::strlen(sz) > 0 ) - { - // callsign valid - ::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign)-1)); - if ( strlen(sz) >= sizeof(m_Callsign) ) - { - m_Module = sz[sizeof(m_Callsign)-1]; - } + // and populate + if ( ::strlen(sz) > 0 ) + { + // callsign valid + ::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign)-1)); + if ( strlen(sz) >= sizeof(m_Callsign) ) + { + m_Module = sz[sizeof(m_Callsign)-1]; + } #ifndef NO_XLX - // dmrid ok ? - if ( m_uiDmrid == 0 ) - { + // dmrid ok ? + if ( m_uiDmrid == 0 ) + { g_DmridDir.Lock(); { - m_uiDmrid = g_DmridDir.FindDmrid(*this); - } - g_DmridDir.Unlock(); - } - } - else if ( m_uiDmrid != 0 ) - { - g_DmridDir.Lock(); - { + m_uiDmrid = g_DmridDir.FindDmrid(*this); + } + g_DmridDir.Unlock(); + } + } + else if ( m_uiDmrid != 0 ) + { + g_DmridDir.Lock(); + { const CCallsign *callsign = g_DmridDir.FindCallsign(m_uiDmrid); if ( callsign != nullptr ) { @@ -85,7 +85,7 @@ CCallsign::CCallsign(const char *sz, uint32 dmrid) } g_DmridDir.Unlock(); #endif - } + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -93,53 +93,53 @@ CCallsign::CCallsign(const char *sz, uint32 dmrid) bool CCallsign::IsValid(void) const { - bool valid = true; - int i; - - // callsign - // first 3 chars are letter or number but cannot be all number - int iNum = 0; - for ( i = 0; i < 3; i++ ) - { - valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]); - if ( IsNumber(m_Callsign[i]) ) - { - iNum++; - } - } - valid &= (iNum < 3); - // all remaining char are letter, number or space - for ( ; i < CALLSIGN_LEN; i++) - { - valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]) || IsSpace(m_Callsign[i]); - } - - // prefix - // all chars are number, uppercase or space - for ( i = 0; i < CALLSUFFIX_LEN; i++ ) - { - valid &= IsLetter(m_Suffix[i]) || IsNumber(m_Suffix[i]) || IsSpace(m_Suffix[i]); - } - - // module - // is an letter or space - valid &= IsLetter(m_Module) || IsSpace(m_Module); - - // dmrid is not tested, as it can be nullptr - // if station does is not dmr registered - - // done - return valid; + bool valid = true; + int i; + + // callsign + // first 3 chars are letter or number but cannot be all number + int iNum = 0; + for ( i = 0; i < 3; i++ ) + { + valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]); + if ( IsNumber(m_Callsign[i]) ) + { + iNum++; + } + } + valid &= (iNum < 3); + // all remaining char are letter, number or space + for ( ; i < CALLSIGN_LEN; i++) + { + valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]) || IsSpace(m_Callsign[i]); + } + + // prefix + // all chars are number, uppercase or space + for ( i = 0; i < CALLSUFFIX_LEN; i++ ) + { + valid &= IsLetter(m_Suffix[i]) || IsNumber(m_Suffix[i]) || IsSpace(m_Suffix[i]); + } + + // module + // is an letter or space + valid &= IsLetter(m_Module) || IsSpace(m_Module); + + // dmrid is not tested, as it can be nullptr + // if station does is not dmr registered + + // done + return valid; } bool CCallsign::HasSuffix(void) const { - bool has = false; - for ( int i = 0; i < CALLSUFFIX_LEN; i++ ) - { - has |= (m_Suffix[i] != ' '); - } - return has; + bool has = false; + for ( int i = 0; i < CALLSUFFIX_LEN; i++ ) + { + has |= (m_Suffix[i] != ' '); + } + return has; } //////////////////////////////////////////////////////////////////////////////////////// @@ -147,64 +147,64 @@ bool CCallsign::HasSuffix(void) const void CCallsign::SetCallsign(const char *sz, bool UpdateDmrid) { - // set callsign - ::memset(m_Callsign, ' ', sizeof(m_Callsign)); - m_Module = ' '; - ::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign)-1)); - if ( strlen(sz) >= sizeof(m_Callsign) ) - { - m_Module = sz[sizeof(m_Callsign)-1]; - } + // set callsign + ::memset(m_Callsign, ' ', sizeof(m_Callsign)); + m_Module = ' '; + ::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign)-1)); + if ( strlen(sz) >= sizeof(m_Callsign) ) + { + m_Module = sz[sizeof(m_Callsign)-1]; + } #ifndef NO_XLX - // and update dmrid - if ( UpdateDmrid ) - { - g_DmridDir.Lock(); - { - m_uiDmrid = g_DmridDir.FindDmrid(*this); - } - g_DmridDir.Unlock(); - } + // and update dmrid + if ( UpdateDmrid ) + { + g_DmridDir.Lock(); + { + m_uiDmrid = g_DmridDir.FindDmrid(*this); + } + g_DmridDir.Unlock(); + } #endif } void CCallsign::SetCallsign(const uint8 *buffer, int len, bool UpdateDmrid) { - // set callsign - ::memset(m_Callsign, ' ', sizeof(m_Callsign)); - m_Module = ' '; - ::memcpy(m_Callsign, buffer, MIN(len, sizeof(m_Callsign)-1)); - for ( unsigned i = 0; i < sizeof(m_Callsign); i++ ) - { - if ( m_Callsign[i] == 0 ) - { - m_Callsign[i] = ' '; - } - } - if ( (len >= (int)sizeof(m_Callsign)) && ((char)buffer[sizeof(m_Callsign)-1] != 0) ) - { - m_Module = (char)buffer[sizeof(m_Callsign)-1]; - } + // set callsign + ::memset(m_Callsign, ' ', sizeof(m_Callsign)); + m_Module = ' '; + ::memcpy(m_Callsign, buffer, MIN(len, sizeof(m_Callsign)-1)); + for ( unsigned i = 0; i < sizeof(m_Callsign); i++ ) + { + if ( m_Callsign[i] == 0 ) + { + m_Callsign[i] = ' '; + } + } + if ( (len >= (int)sizeof(m_Callsign)) && ((char)buffer[sizeof(m_Callsign)-1] != 0) ) + { + m_Module = (char)buffer[sizeof(m_Callsign)-1]; + } #ifndef NO_XLX - if ( UpdateDmrid ) - { - g_DmridDir.Lock(); - { - m_uiDmrid = g_DmridDir.FindDmrid(*this); - } - g_DmridDir.Unlock(); - } + if ( UpdateDmrid ) + { + g_DmridDir.Lock(); + { + m_uiDmrid = g_DmridDir.FindDmrid(*this); + } + g_DmridDir.Unlock(); + } #endif } #ifndef NO_XLX void CCallsign::SetDmrid(uint32 dmrid, bool UpdateCallsign) { - m_uiDmrid = dmrid; - if ( UpdateCallsign ) - { - g_DmridDir.Lock(); - { + m_uiDmrid = dmrid; + if ( UpdateCallsign ) + { + g_DmridDir.Lock(); + { const CCallsign *callsign = g_DmridDir.FindCallsign(dmrid); if ( callsign != nullptr ) { @@ -212,35 +212,35 @@ void CCallsign::SetDmrid(uint32 dmrid, bool UpdateCallsign) } } g_DmridDir.Unlock(); - } + } } void CCallsign::SetDmrid(const uint8 *buffer, bool UpdateCallsign) { - char sz[9]; - ::memcpy(sz, buffer, 8); - sz[8] = 0; - SetDmrid((uint32)::strtol(sz, nullptr, 16), UpdateCallsign); + char sz[9]; + ::memcpy(sz, buffer, 8); + sz[8] = 0; + SetDmrid((uint32)::strtol(sz, nullptr, 16), UpdateCallsign); } #endif void CCallsign::SetModule(char c) { - m_Module = c; + m_Module = c; } void CCallsign::SetSuffix(const char *sz) { - ::memset(m_Suffix, ' ', sizeof(m_Suffix)); - ::memcpy(m_Suffix, sz, MIN(strlen(sz), sizeof(m_Suffix))); + ::memset(m_Suffix, ' ', sizeof(m_Suffix)); + ::memcpy(m_Suffix, sz, MIN(strlen(sz), sizeof(m_Suffix))); } void CCallsign::SetSuffix(const uint8 *buffer, int len) { - len = MIN(len, sizeof(m_Suffix)); - ::memset(m_Suffix, ' ', sizeof(m_Suffix)); - ::memcpy(m_Suffix, buffer, len); + len = MIN(len, sizeof(m_Suffix)); + ::memset(m_Suffix, ' ', sizeof(m_Suffix)); + ::memcpy(m_Suffix, buffer, len); } //////////////////////////////////////////////////////////////////////////////////////// @@ -248,10 +248,10 @@ void CCallsign::SetSuffix(const uint8 *buffer, int len) void CCallsign::PatchCallsign(int off, const uint8 *patch, int len) { - if ( off < CALLSIGN_LEN ) - { - ::memcpy(m_Callsign, patch, MIN(len, sizeof(m_Callsign) - off)); - } + if ( off < CALLSIGN_LEN ) + { + ::memcpy(m_Callsign, patch, MIN(len, sizeof(m_Callsign) - off)); + } } @@ -260,26 +260,26 @@ void CCallsign::PatchCallsign(int off, const uint8 *patch, int len) void CCallsign::GetCallsign(uint8 *buffer) const { - ::memcpy(buffer, m_Callsign, sizeof(m_Callsign)); - if ( HasModule() ) - { - buffer[sizeof(m_Callsign)-1] = m_Module; - } + ::memcpy(buffer, m_Callsign, sizeof(m_Callsign)); + if ( HasModule() ) + { + buffer[sizeof(m_Callsign)-1] = m_Module; + } } void CCallsign::GetCallsignString(char *sz) const { - unsigned i; - for ( i = 0; (i < sizeof(m_Callsign)) && (m_Callsign[i] != ' '); i++ ) - { - sz[i] = m_Callsign[i]; - } - sz[i] = 0; + unsigned i; + for ( i = 0; (i < sizeof(m_Callsign)) && (m_Callsign[i] != ' '); i++ ) + { + sz[i] = m_Callsign[i]; + } + sz[i] = 0; } void CCallsign::GetSuffix(uint8 *buffer) const { - ::memcpy(buffer, m_Suffix, sizeof(m_Suffix)); + ::memcpy(buffer, m_Suffix, sizeof(m_Suffix)); } //////////////////////////////////////////////////////////////////////////////////////// @@ -287,32 +287,32 @@ void CCallsign::GetSuffix(uint8 *buffer) const bool CCallsign::HasSameCallsign(const CCallsign &Callsign) const { - return (::memcmp(m_Callsign, Callsign.m_Callsign, sizeof(m_Callsign)) == 0); + return (::memcmp(m_Callsign, Callsign.m_Callsign, sizeof(m_Callsign)) == 0); } bool CCallsign::HasSameCallsignWithWildcard(const CCallsign &callsign) const { - bool same = true; - bool done = false; - - for ( unsigned i = 0; (i < sizeof(m_Callsign)) && same && !done; i++ ) - { - if ( !(done = ((m_Callsign[i] == '*') || (callsign[i] == '*'))) ) - { - same &= (m_Callsign[i] == callsign[i]); - } - } - return same; + bool same = true; + bool done = false; + + for ( unsigned i = 0; (i < sizeof(m_Callsign)) && same && !done; i++ ) + { + if ( !(done = ((m_Callsign[i] == '*') || (callsign[i] == '*'))) ) + { + same &= (m_Callsign[i] == callsign[i]); + } + } + return same; } bool CCallsign::HasLowerCallsign(const CCallsign &Callsign) const { - return (::memcmp(m_Callsign, Callsign.m_Callsign, sizeof(m_Callsign)) < 0); + return (::memcmp(m_Callsign, Callsign.m_Callsign, sizeof(m_Callsign)) < 0); } bool CCallsign::HasSameModule(const CCallsign &Callsign) const { - return (m_Module == Callsign.m_Module); + return (m_Module == Callsign.m_Module); } @@ -321,12 +321,12 @@ bool CCallsign::HasSameModule(const CCallsign &Callsign) const bool CCallsign::operator ==(const CCallsign &callsign) const { - return ((::memcmp(callsign.m_Callsign, m_Callsign, sizeof(m_Callsign)) == 0) && (m_Module == callsign.m_Module) - && (::memcmp(callsign.m_Suffix, m_Suffix, sizeof(m_Suffix)) == 0) + return ((::memcmp(callsign.m_Callsign, m_Callsign, sizeof(m_Callsign)) == 0) && (m_Module == callsign.m_Module) + && (::memcmp(callsign.m_Suffix, m_Suffix, sizeof(m_Suffix)) == 0) #ifndef NO_XLX - && (m_uiDmrid == callsign.m_uiDmrid) + && (m_uiDmrid == callsign.m_uiDmrid) #endif - ); + ); } CCallsign::operator const char *() const @@ -335,23 +335,23 @@ CCallsign::operator const char *() const // empty ::memset(sz, 0, sizeof(m_sz)); - // callsign - sz[CALLSIGN_LEN] = 0; - ::memcpy(sz, m_Callsign, sizeof(m_Callsign)); - // module - if ( HasModule() ) - { - sz[sizeof(m_Callsign)] = m_Module; - } - // suffix - if ( HasSuffix() ) - { - ::strcat(sz, " / "); - ::strncat(sz, m_Suffix, sizeof(m_Suffix)); - } - - // done - return m_sz; + // callsign + sz[CALLSIGN_LEN] = 0; + ::memcpy(sz, m_Callsign, sizeof(m_Callsign)); + // module + if ( HasModule() ) + { + sz[sizeof(m_Callsign)] = m_Module; + } + // suffix + if ( HasSuffix() ) + { + ::strcat(sz, " / "); + ::strncat(sz, m_Suffix, sizeof(m_Suffix)); + } + + // done + return m_sz; } //////////////////////////////////////////////////////////////////////////////////////// @@ -359,15 +359,15 @@ CCallsign::operator const char *() const bool CCallsign::IsNumber(char c) const { - return ((c >= '0') && (c <= '9')); + return ((c >= '0') && (c <= '9')); } bool CCallsign::IsLetter(char c) const { - return ((c >= 'A') && (c <= 'Z')); + return ((c >= 'A') && (c <= 'Z')); } bool CCallsign::IsSpace(char c) const { - return (c == ' '); + return (c == ' '); } diff --git a/src/ccallsign.h b/src/ccallsign.h index d56c22c..0ee48c7 100644 --- a/src/ccallsign.h +++ b/src/ccallsign.h @@ -38,62 +38,62 @@ class CCallsign { public: - // contructors - CCallsign(); - CCallsign(const char *, uint32 = 0); + // contructors + CCallsign(); + CCallsign(const char *, uint32 = 0); - // status - bool IsValid(void) const; - bool HasSuffix(void) const; - bool HasModule(void) const { return m_Module != ' '; } + // status + bool IsValid(void) const; + bool HasSuffix(void) const; + bool HasModule(void) const { return m_Module != ' '; } - // set - void SetCallsign(const char *, bool = true); - void SetCallsign(const uint8 *, int, bool = true); + // set + void SetCallsign(const char *, bool = true); + void SetCallsign(const uint8 *, int, bool = true); #ifndef NO_XLX - void SetDmrid(uint32, bool = true); - void SetDmrid(const uint8 *, bool = true); + void SetDmrid(uint32, bool = true); + void SetDmrid(const uint8 *, bool = true); #endif - void SetModule(char); - void SetSuffix(const char *); - void SetSuffix(const uint8 *, int); + void SetModule(char); + void SetSuffix(const char *); + void SetSuffix(const uint8 *, int); - // modify - void PatchCallsign(int, const uint8 *, int); + // modify + void PatchCallsign(int, const uint8 *, int); - // get - void GetCallsign(uint8 *) const; - void GetCallsignString(char *) const; + // get + void GetCallsign(uint8 *) const; + void GetCallsignString(char *) const; #ifndef NO_XLX - uint32 GetDmrid(void) const { return m_uiDmrid; } + uint32 GetDmrid(void) const { return m_uiDmrid; } #endif - void GetSuffix(uint8 *) const; - char GetModule(void) const { return m_Module; } + void GetSuffix(uint8 *) const; + char GetModule(void) const { return m_Module; } - // compare - bool HasSameCallsign(const CCallsign &) const; - bool HasSameCallsignWithWildcard(const CCallsign &) const; - bool HasLowerCallsign(const CCallsign &) const; - bool HasSameModule(const CCallsign &) const; + // compare + bool HasSameCallsign(const CCallsign &) const; + bool HasSameCallsignWithWildcard(const CCallsign &) const; + bool HasLowerCallsign(const CCallsign &) const; + bool HasSameModule(const CCallsign &) const; - // operators - bool operator ==(const CCallsign &) const; - operator const char *() const; + // operators + bool operator ==(const CCallsign &) const; + operator const char *() const; protected: - // helper - bool IsNumber(char) const; - bool IsLetter(char) const; - bool IsSpace(char) const; + // helper + bool IsNumber(char) const; + bool IsLetter(char) const; + bool IsSpace(char) const; protected: - // data - char m_Callsign[CALLSIGN_LEN]; - char m_Suffix[CALLSUFFIX_LEN]; - char m_Module; - char m_sz[CALLSIGN_LEN+CALLSUFFIX_LEN+5]; + // data + char m_Callsign[CALLSIGN_LEN]; + char m_Suffix[CALLSUFFIX_LEN]; + char m_Module; + char m_sz[CALLSIGN_LEN+CALLSUFFIX_LEN+5]; #ifndef NO_XLX - uint32 m_uiDmrid; + uint32 m_uiDmrid; #endif }; diff --git a/src/ccallsignlist.cpp b/src/ccallsignlist.cpp index 0169084..875bcae 100644 --- a/src/ccallsignlist.cpp +++ b/src/ccallsignlist.cpp @@ -34,8 +34,8 @@ CCallsignList::CCallsignList() { - m_Filename = nullptr; - ::memset(&m_LastModTime, 0, sizeof(time_t)); + m_Filename = nullptr; + ::memset(&m_LastModTime, 0, sizeof(time_t)); } //////////////////////////////////////////////////////////////////////////////////////// @@ -43,86 +43,86 @@ CCallsignList::CCallsignList() bool CCallsignList::LoadFromFile(const char *filename) { - bool ok = false; - char sz[256]; - char szStar[2] = "*"; - - // and load - std::ifstream file (filename); - if ( file.is_open() ) - { - Lock(); - - // empty list - m_Callsigns.clear(); - // fill with file content - while ( file.getline(sz, sizeof(sz)).good() ) - { - // remove leading & trailing spaces - char *szt = TrimWhiteSpaces(sz); - - // crack it - if ( (::strlen(szt) > 0) && (szt[0] != '#') ) - { - // 1st token is callsign - if ( (szt = ::strtok(szt, " ,\t")) != nullptr ) - { - CCallsign callsign(szt); - // 2nd token is modules list - szt = ::strtok(nullptr, " ,\t"); - // if token absent, use wildcard - if ( szt == nullptr ) - { - szt = szStar; - } - // and add to list - m_Callsigns.push_back(CCallsignListItem(callsign, CIp(), szt)); - } - } - } - // close file - file.close(); - - // keep file path - m_Filename = filename; - - // update time - GetLastModTime(&m_LastModTime); - - // and done - Unlock(); - ok = true; - std::cout << "Gatekeeper loaded " << m_Callsigns.size() << " lines from " << filename << std::endl; - } - else - { - std::cout << "Gatekeeper cannot find " << filename << std::endl; - } - - return ok; + bool ok = false; + char sz[256]; + char szStar[2] = "*"; + + // and load + std::ifstream file (filename); + if ( file.is_open() ) + { + Lock(); + + // empty list + m_Callsigns.clear(); + // fill with file content + while ( file.getline(sz, sizeof(sz)).good() ) + { + // remove leading & trailing spaces + char *szt = TrimWhiteSpaces(sz); + + // crack it + if ( (::strlen(szt) > 0) && (szt[0] != '#') ) + { + // 1st token is callsign + if ( (szt = ::strtok(szt, " ,\t")) != nullptr ) + { + CCallsign callsign(szt); + // 2nd token is modules list + szt = ::strtok(nullptr, " ,\t"); + // if token absent, use wildcard + if ( szt == nullptr ) + { + szt = szStar; + } + // and add to list + m_Callsigns.push_back(CCallsignListItem(callsign, CIp(), szt)); + } + } + } + // close file + file.close(); + + // keep file path + m_Filename = filename; + + // update time + GetLastModTime(&m_LastModTime); + + // and done + Unlock(); + ok = true; + std::cout << "Gatekeeper loaded " << m_Callsigns.size() << " lines from " << filename << std::endl; + } + else + { + std::cout << "Gatekeeper cannot find " << filename << std::endl; + } + + return ok; } bool CCallsignList::ReloadFromFile(void) { - bool ok = false; + bool ok = false; - if ( m_Filename != nullptr ) - { - ok = LoadFromFile(m_Filename); - } - return ok; + if ( m_Filename != nullptr ) + { + ok = LoadFromFile(m_Filename); + } + return ok; } bool CCallsignList::NeedReload(void) { - bool needReload = false; - - time_t time; - if ( GetLastModTime(&time) ) - { - needReload = time != m_LastModTime; - } - return needReload; + bool needReload = false; + + time_t time; + if ( GetLastModTime(&time) ) + { + needReload = time != m_LastModTime; + } + return needReload; } //////////////////////////////////////////////////////////////////////////////////////// @@ -130,46 +130,46 @@ bool CCallsignList::NeedReload(void) bool CCallsignList::IsCallsignListedWithWildcard(const CCallsign &callsign) const { - for ( const auto &item : m_Callsigns ) - { - if (item.HasSameCallsignWithWildcard(callsign)) + for ( const auto &item : m_Callsigns ) + { + if (item.HasSameCallsignWithWildcard(callsign)) return true; - } + } - return false; + return false; } bool CCallsignList::IsCallsignListedWithWildcard(const CCallsign &callsign, char module) const { - for ( const auto &item : m_Callsigns ) - { - if (item.HasSameCallsignWithWildcard(callsign) && ((module == ' ') || item.HasModuleListed(module)) ) + for ( const auto &item : m_Callsigns ) + { + if (item.HasSameCallsignWithWildcard(callsign) && ((module == ' ') || item.HasModuleListed(module)) ) return true; - } + } - return false; + return false; } bool CCallsignList::IsCallsignListed(const CCallsign &callsign, char module) const { - for ( const auto &item : m_Callsigns ) - { - if (item.HasSameCallsign(callsign) && item.HasModuleListed(module)) + for ( const auto &item : m_Callsigns ) + { + if (item.HasSameCallsign(callsign) && item.HasModuleListed(module)) return true; - } + } - return false; + return false; } bool CCallsignList::IsCallsignListed(const CCallsign &callsign, char *modules) const { - for ( const auto &item : m_Callsigns ) - { - if (item.HasSameCallsign(callsign) && item.CheckListedModules(modules)) + for ( const auto &item : m_Callsigns ) + { + if (item.HasSameCallsign(callsign) && item.CheckListedModules(modules)) return true; - } + } - return false; + return false; } //////////////////////////////////////////////////////////////////////////////////////// @@ -177,15 +177,15 @@ bool CCallsignList::IsCallsignListed(const CCallsign &callsign, char *modules) c CCallsignListItem *CCallsignList::FindListItem(const CCallsign &Callsign) { - for ( auto &item : m_Callsigns ) - { - if ( item.GetCallsign().HasSameCallsign(Callsign) ) - { - return &item; - } - } + for ( auto &item : m_Callsigns ) + { + if ( item.GetCallsign().HasSameCallsign(Callsign) ) + { + return &item; + } + } - return nullptr; + return nullptr; } @@ -194,37 +194,37 @@ CCallsignListItem *CCallsignList::FindListItem(const CCallsign &Callsign) char *CCallsignList::TrimWhiteSpaces(char *str) { - char *end; + char *end; - // Trim leading space & tabs - while((*str == ' ') || (*str == '\t')) str++; + // Trim leading space & tabs + while((*str == ' ') || (*str == '\t')) str++; - // All spaces? - if(*str == 0) - return str; + // All spaces? + if(*str == 0) + return str; - // Trim trailing space, tab or lf - end = str + ::strlen(str) - 1; - while((end > str) && ((*end == ' ') || (*end == '\t') || (*end == '\r'))) end--; + // Trim trailing space, tab or lf + end = str + ::strlen(str) - 1; + while((end > str) && ((*end == ' ') || (*end == '\t') || (*end == '\r'))) end--; - // Write new null terminator - *(end+1) = 0; + // Write new null terminator + *(end+1) = 0; - return str; + return str; } bool CCallsignList::GetLastModTime(time_t *time) { - bool ok = false; - - if ( m_Filename != nullptr ) - { - struct stat fileStat; - if( ::stat(m_Filename, &fileStat) != -1 ) - { - *time = fileStat.st_mtime; - ok = true; - } - } - return ok; + bool ok = false; + + if ( m_Filename != nullptr ) + { + struct stat fileStat; + if( ::stat(m_Filename, &fileStat) != -1 ) + { + *time = fileStat.st_mtime; + ok = true; + } + } + return ok; } diff --git a/src/ccallsignlist.h b/src/ccallsignlist.h index 4425461..34834a9 100644 --- a/src/ccallsignlist.h +++ b/src/ccallsignlist.h @@ -36,43 +36,43 @@ class CCallsignList { public: - // constructor - CCallsignList(); + // constructor + CCallsignList(); - // destructor - virtual ~CCallsignList() {} + // destructor + virtual ~CCallsignList() {} - // locks - void Lock(void) { m_Mutex.lock(); } - void Unlock(void) { m_Mutex.unlock(); } + // locks + void Lock(void) { m_Mutex.lock(); } + void Unlock(void) { m_Mutex.unlock(); } - // file io - virtual bool LoadFromFile(const char *); - bool ReloadFromFile(void); - bool NeedReload(void); + // file io + virtual bool LoadFromFile(const char *); + bool ReloadFromFile(void); + bool NeedReload(void); - // compare - bool IsCallsignListedWithWildcard(const CCallsign &) const; - bool IsCallsignListedWithWildcard(const CCallsign &, char) const; - bool IsCallsignListed(const CCallsign &, char) const; - bool IsCallsignListed(const CCallsign &, char*) const; + // compare + bool IsCallsignListedWithWildcard(const CCallsign &) const; + bool IsCallsignListedWithWildcard(const CCallsign &, char) const; + bool IsCallsignListed(const CCallsign &, char) const; + bool IsCallsignListed(const CCallsign &, char*) const; // pass-thru bool empty() const { return m_Callsigns.empty(); } std::list::iterator begin() { return m_Callsigns.begin(); } std::list::iterator end() { return m_Callsigns.end(); } - // find - CCallsignListItem *FindListItem(const CCallsign &); + // find + CCallsignListItem *FindListItem(const CCallsign &); protected: - bool GetLastModTime(time_t *); - char *TrimWhiteSpaces(char *); + bool GetLastModTime(time_t *); + char *TrimWhiteSpaces(char *); - // data - std::mutex m_Mutex; - const char * m_Filename; - time_t m_LastModTime; + // data + std::mutex m_Mutex; + const char * m_Filename; + time_t m_LastModTime; std::list m_Callsigns; }; diff --git a/src/ccallsignlistitem.cpp b/src/ccallsignlistitem.cpp index bd8aa96..85a8b62 100644 --- a/src/ccallsignlistitem.cpp +++ b/src/ccallsignlistitem.cpp @@ -31,76 +31,76 @@ CCallsignListItem::CCallsignListItem() { - ::memset(m_Modules, 0, sizeof(m_Modules)); - ::memset(m_szUrl, 0, sizeof(m_szUrl)); + ::memset(m_Modules, 0, sizeof(m_Modules)); + ::memset(m_szUrl, 0, sizeof(m_szUrl)); } CCallsignListItem::CCallsignListItem(const CCallsign &callsign, const CIp &ip, const char *modules) { - m_Callsign = callsign; - ::memset(m_szUrl, 0, sizeof(m_szUrl)); - m_Ip = ip; - if ( modules != nullptr ) - { - ::memset(m_Modules, 0, sizeof(m_Modules)); - if ( modules[0] == '*' ) - { - for ( char i = 0; i < NB_OF_MODULES; i++ ) - { - m_Modules[i] = 'A' + i; - } - } - else - { - int n = MIN((int)::strlen(modules), sizeof(m_Modules)-1); - int j = 0; - for ( int i = 0; i < n; i++ ) - { - if ( (modules[i] - 'A') < NB_OF_MODULES ) - { - m_Modules[j++] = modules[i]; - } - } - } - } + m_Callsign = callsign; + ::memset(m_szUrl, 0, sizeof(m_szUrl)); + m_Ip = ip; + if ( modules != nullptr ) + { + ::memset(m_Modules, 0, sizeof(m_Modules)); + if ( modules[0] == '*' ) + { + for ( char i = 0; i < NB_OF_MODULES; i++ ) + { + m_Modules[i] = 'A' + i; + } + } + else + { + int n = MIN((int)::strlen(modules), sizeof(m_Modules)-1); + int j = 0; + for ( int i = 0; i < n; i++ ) + { + if ( (modules[i] - 'A') < NB_OF_MODULES ) + { + m_Modules[j++] = modules[i]; + } + } + } + } } CCallsignListItem::CCallsignListItem(const CCallsign &callsign, const char *url, const char *modules) { - m_Callsign = callsign; - ::strncpy(m_szUrl, url, URL_MAXLEN); - m_Ip = CIp(m_szUrl); - if ( modules != nullptr ) - { - ::memset(m_Modules, 0, sizeof(m_Modules)); - if ( modules[0] == '*' ) - { - for ( char i = 0; i < NB_OF_MODULES; i++ ) - { - m_Modules[i] = 'A' + i; - } - } - else - { - int n = MIN((int)::strlen(modules), sizeof(m_Modules)-1); - int j = 0; - for ( int i = 0; i < n; i++ ) - { - if ( (modules[i] - 'A') < NB_OF_MODULES ) - { - m_Modules[j++] = modules[i]; - } - } - } - } + m_Callsign = callsign; + ::strncpy(m_szUrl, url, URL_MAXLEN); + m_Ip = CIp(m_szUrl); + if ( modules != nullptr ) + { + ::memset(m_Modules, 0, sizeof(m_Modules)); + if ( modules[0] == '*' ) + { + for ( char i = 0; i < NB_OF_MODULES; i++ ) + { + m_Modules[i] = 'A' + i; + } + } + else + { + int n = MIN((int)::strlen(modules), sizeof(m_Modules)-1); + int j = 0; + for ( int i = 0; i < n; i++ ) + { + if ( (modules[i] - 'A') < NB_OF_MODULES ) + { + m_Modules[j++] = modules[i]; + } + } + } + } } CCallsignListItem::CCallsignListItem(const CCallsignListItem &item) { - m_Callsign = item.m_Callsign; - ::memcpy(m_szUrl, item.m_szUrl, sizeof(m_szUrl)); - m_Ip = item.m_Ip; - ::memcpy(m_Modules, item.m_Modules, sizeof(m_Modules)); + m_Callsign = item.m_Callsign; + ::memcpy(m_szUrl, item.m_szUrl, sizeof(m_szUrl)); + m_Ip = item.m_Ip; + ::memcpy(m_Modules, item.m_Modules, sizeof(m_Modules)); } @@ -109,38 +109,38 @@ CCallsignListItem::CCallsignListItem(const CCallsignListItem &item) bool CCallsignListItem::HasSameCallsign(const CCallsign &callsign) const { - return m_Callsign.HasSameCallsign(callsign); + return m_Callsign.HasSameCallsign(callsign); } bool CCallsignListItem::HasSameCallsignWithWildcard(const CCallsign &callsign) const { - return m_Callsign.HasSameCallsignWithWildcard(callsign); + return m_Callsign.HasSameCallsignWithWildcard(callsign); } bool CCallsignListItem::HasModuleListed(char module) const { - return (::strchr(m_Modules, (int)module) != nullptr); + return (::strchr(m_Modules, (int)module) != nullptr); } bool CCallsignListItem::CheckListedModules(char *Modules) const { - bool listed = false; + bool listed = false; - if ( Modules != nullptr ) - { - // build a list of common modules - char list[27]; - list[0] = 0; - // - for ( unsigned i = 0; i < ::strlen(Modules); i++ ) - { - if ( HasModuleListed(Modules[i]) ) - { - ::strncat(list, &(Modules[i]), 1); - listed = true; - } - } - ::strcpy(Modules, list); - } - return listed; + if ( Modules != nullptr ) + { + // build a list of common modules + char list[27]; + list[0] = 0; + // + for ( unsigned i = 0; i < ::strlen(Modules); i++ ) + { + if ( HasModuleListed(Modules[i]) ) + { + ::strncat(list, &(Modules[i]), 1); + listed = true; + } + } + ::strcpy(Modules, list); + } + return listed; } diff --git a/src/ccallsignlistitem.h b/src/ccallsignlistitem.h index 33467a4..e41d529 100644 --- a/src/ccallsignlistitem.h +++ b/src/ccallsignlistitem.h @@ -40,35 +40,35 @@ class CCallsignListItem { public: - // constructor - CCallsignListItem(); - CCallsignListItem(const CCallsign &, const CIp &, const char *); - CCallsignListItem(const CCallsign &, const char *, const char *); - CCallsignListItem(const CCallsignListItem &); + // constructor + CCallsignListItem(); + CCallsignListItem(const CCallsign &, const CIp &, const char *); + CCallsignListItem(const CCallsign &, const char *, const char *); + CCallsignListItem(const CCallsignListItem &); - // destructor - virtual ~CCallsignListItem() {} + // destructor + virtual ~CCallsignListItem() {} - // compare - bool HasSameCallsign(const CCallsign &) const; - bool HasSameCallsignWithWildcard(const CCallsign &) const; - bool HasModuleListed(char) const; - bool CheckListedModules(char*) const; + // compare + bool HasSameCallsign(const CCallsign &) const; + bool HasSameCallsignWithWildcard(const CCallsign &) const; + bool HasModuleListed(char) const; + bool CheckListedModules(char*) const; - // get - const CCallsign &GetCallsign(void) const { return m_Callsign; } - const CIp &GetIp(void) const { return m_Ip; } - const char *GetModules(void) { return m_Modules; } + // get + const CCallsign &GetCallsign(void) const { return m_Callsign; } + const CIp &GetIp(void) const { return m_Ip; } + const char *GetModules(void) { return m_Modules; } - // update - void ResolveIp(void) { m_Ip = CIp(m_szUrl); } + // update + void ResolveIp(void) { m_Ip = CIp(m_szUrl); } protected: - // data - CCallsign m_Callsign; - char m_szUrl[URL_MAXLEN+1]; - CIp m_Ip; - char m_Modules[27]; + // data + CCallsign m_Callsign; + char m_szUrl[URL_MAXLEN+1]; + CIp m_Ip; + char m_Modules[27]; }; diff --git a/src/cclient.cpp b/src/cclient.cpp index c2d2d3e..eb60948 100644 --- a/src/cclient.cpp +++ b/src/cclient.cpp @@ -32,33 +32,33 @@ CClient::CClient() { - m_ReflectorModule = ' '; - m_ModuleMastered = ' '; - m_LastKeepaliveTime.Now(); - m_ConnectTime = std::time(nullptr); - m_LastHeardTime = std::time(nullptr); + m_ReflectorModule = ' '; + m_ModuleMastered = ' '; + m_LastKeepaliveTime.Now(); + m_ConnectTime = std::time(nullptr); + m_LastHeardTime = std::time(nullptr); } CClient::CClient(const CCallsign &callsign, const CIp &ip, char reflectorModule) { - m_ReflectorModule = reflectorModule; - m_Callsign = callsign; - m_Ip = ip; - m_ModuleMastered = ' '; - m_LastKeepaliveTime.Now(); - m_ConnectTime = std::time(nullptr); - m_LastHeardTime = std::time(nullptr); + m_ReflectorModule = reflectorModule; + m_Callsign = callsign; + m_Ip = ip; + m_ModuleMastered = ' '; + m_LastKeepaliveTime.Now(); + m_ConnectTime = std::time(nullptr); + m_LastHeardTime = std::time(nullptr); } CClient::CClient(const CClient &client) { - m_Callsign = client.m_Callsign; - m_Ip = client.m_Ip; - m_ReflectorModule = client.m_ReflectorModule; - m_ModuleMastered = client.m_ModuleMastered; - m_LastKeepaliveTime = client.m_LastKeepaliveTime; - m_ConnectTime = client.m_ConnectTime; - m_LastHeardTime = client.m_LastHeardTime; + m_Callsign = client.m_Callsign; + m_Ip = client.m_Ip; + m_ReflectorModule = client.m_ReflectorModule; + m_ModuleMastered = client.m_ModuleMastered; + m_LastKeepaliveTime = client.m_LastKeepaliveTime; + m_ConnectTime = client.m_ConnectTime; + m_LastHeardTime = client.m_LastHeardTime; } //////////////////////////////////////////////////////////////////////////////////////// @@ -66,7 +66,7 @@ CClient::CClient(const CClient &client) void CClient::Alive(void) { - m_LastKeepaliveTime.Now();; + m_LastKeepaliveTime.Now(); } @@ -75,9 +75,9 @@ void CClient::Alive(void) bool CClient::operator ==(const CClient &client) const { - return ((client.m_Callsign == m_Callsign) && - (client.m_Ip == m_Ip) && - (client.m_ReflectorModule == m_ReflectorModule)); + return ((client.m_Callsign == m_Callsign) && + (client.m_Ip == m_Ip) && + (client.m_ReflectorModule == m_ReflectorModule)); } //////////////////////////////////////////////////////////////////////////////////////// @@ -85,38 +85,38 @@ bool CClient::operator ==(const CClient &client) const void CClient::WriteXml(std::ofstream &xmlFile) { - xmlFile << "" << std::endl; - xmlFile << "\t" << m_Callsign << "" << std::endl; - xmlFile << "\t" << m_Ip.GetAddress() << "" << std::endl; - xmlFile << "\t" << m_ReflectorModule << "" << std::endl; - xmlFile << "\t" << GetProtocolName() << "" << std::endl; - char mbstr[100]; - if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_ConnectTime))) - { - xmlFile << "\t" << mbstr << "" << std::endl; - } - if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime))) - { - xmlFile << "\t" << mbstr << "" << std::endl; - } - xmlFile << "" << std::endl; + xmlFile << "" << std::endl; + xmlFile << "\t" << m_Callsign << "" << std::endl; + xmlFile << "\t" << m_Ip.GetAddress() << "" << std::endl; + xmlFile << "\t" << m_ReflectorModule << "" << std::endl; + xmlFile << "\t" << GetProtocolName() << "" << std::endl; + char mbstr[100]; + if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_ConnectTime))) + { + xmlFile << "\t" << mbstr << "" << std::endl; + } + if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime))) + { + xmlFile << "\t" << mbstr << "" << std::endl; + } + xmlFile << "" << std::endl; } void CClient::GetJsonObject(char *Buffer) { - char sz[512]; - char mbstr[100]; - char cs[16]; - - if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime))) - { - m_Callsign.GetCallsignString(cs); - - ::sprintf(sz, "{\"callsign\":\"%s\",\"module\":\"%c\",\"linkedto\":\"%c\",\"time\":\"%s\"}", - cs, - m_Callsign.GetModule(), - m_ReflectorModule, - mbstr); - ::strcat(Buffer, sz); - } + char sz[512]; + char mbstr[100]; + char cs[16]; + + if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime))) + { + m_Callsign.GetCallsignString(cs); + + ::sprintf(sz, "{\"callsign\":\"%s\",\"module\":\"%c\",\"linkedto\":\"%c\",\"time\":\"%s\"}", + cs, + m_Callsign.GetModule(), + m_ReflectorModule, + mbstr); + ::strcat(Buffer, sz); + } } diff --git a/src/cclient.h b/src/cclient.h index 4fcb2cc..12c0475 100644 --- a/src/cclient.h +++ b/src/cclient.h @@ -39,64 +39,64 @@ class CClient { public: - // constructors - CClient(); - CClient(const CCallsign &, const CIp &, char = ' '); - CClient(const CClient &); - - // destructor - virtual ~CClient() {}; - - // operators - bool operator ==(const CClient &) const; - - // get - const CCallsign &GetCallsign(void) const { return m_Callsign; } - const CIp &GetIp(void) const { return m_Ip; } - bool HasModule(void) const { return m_Callsign.HasModule(); } - char GetModule(void) const { return m_Callsign.GetModule(); } - bool HasReflectorModule(void) const { return m_ReflectorModule != ' '; } - char GetReflectorModule(void) const { return m_ReflectorModule; } - - // set - void SetModule(char c) { m_Callsign.SetModule(c); } - void SetReflectorModule(char c) { m_ReflectorModule = c; } - - // identity - virtual int GetProtocol(void) const { return PROTOCOL_NONE; } - virtual int GetProtocolRevision(void) const { return 0; } - virtual int GetCodec(void) const { return CODEC_NONE; } - virtual const char *GetProtocolName(void) const { return "none"; } - virtual bool IsNode(void) const { return false; } - virtual bool IsPeer(void) const { return false; } - virtual bool IsDextraDongle(void) const { return false; } - virtual void SetDextraDongle(void) { } - - // status - virtual void Alive(void); - virtual bool IsAlive(void) const { return false; } - virtual bool IsAMaster(void) const { return (m_ModuleMastered != ' '); } - virtual void SetMasterOfModule(char c) { m_ModuleMastered = c; } - virtual void NotAMaster(void) { m_ModuleMastered = ' '; } - virtual void Heard(void) { m_LastHeardTime = std::time(nullptr); } - - // reporting - virtual void WriteXml(std::ofstream &); - virtual void GetJsonObject(char *); + // constructors + CClient(); + CClient(const CCallsign &, const CIp &, char = ' '); + CClient(const CClient &); + + // destructor + virtual ~CClient() {}; + + // operators + bool operator ==(const CClient &) const; + + // get + const CCallsign &GetCallsign(void) const { return m_Callsign; } + const CIp &GetIp(void) const { return m_Ip; } + bool HasModule(void) const { return m_Callsign.HasModule(); } + char GetModule(void) const { return m_Callsign.GetModule(); } + bool HasReflectorModule(void) const { return m_ReflectorModule != ' '; } + char GetReflectorModule(void) const { return m_ReflectorModule; } + + // set + void SetModule(char c) { m_Callsign.SetModule(c); } + void SetReflectorModule(char c) { m_ReflectorModule = c; } + + // identity + virtual int GetProtocol(void) const { return PROTOCOL_NONE; } + virtual int GetProtocolRevision(void) const { return 0; } + virtual int GetCodec(void) const { return CODEC_NONE; } + virtual const char *GetProtocolName(void) const { return "none"; } + virtual bool IsNode(void) const { return false; } + virtual bool IsPeer(void) const { return false; } + virtual bool IsDextraDongle(void) const { return false; } + virtual void SetDextraDongle(void) { } + + // status + virtual void Alive(void); + virtual bool IsAlive(void) const { return false; } + virtual bool IsAMaster(void) const { return (m_ModuleMastered != ' '); } + virtual void SetMasterOfModule(char c) { m_ModuleMastered = c; } + virtual void NotAMaster(void) { m_ModuleMastered = ' '; } + virtual void Heard(void) { m_LastHeardTime = std::time(nullptr); } + + // reporting + virtual void WriteXml(std::ofstream &); + virtual void GetJsonObject(char *); protected: - // data - CCallsign m_Callsign; - CIp m_Ip; - - // linked to - char m_ReflectorModule; - - // status - char m_ModuleMastered; - CTimePoint m_LastKeepaliveTime; - std::time_t m_ConnectTime; - std::time_t m_LastHeardTime; + // data + CCallsign m_Callsign; + CIp m_Ip; + + // linked to + char m_ReflectorModule; + + // status + char m_ModuleMastered; + CTimePoint m_LastKeepaliveTime; + std::time_t m_ConnectTime; + std::time_t m_LastHeardTime; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cclients.cpp b/src/cclients.cpp index b14b4f1..f41f25d 100644 --- a/src/cclients.cpp +++ b/src/cclients.cpp @@ -41,9 +41,9 @@ CClients::CClients() CClients::~CClients() { - m_Mutex.lock(); + m_Mutex.lock(); m_Clients.clear(); - m_Mutex.unlock(); + m_Mutex.unlock(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -51,23 +51,22 @@ CClients::~CClients() void CClients::AddClient(std::shared_ptr client) { - // first check if client already exists - for ( auto it=begin(); it!=end(); it++ ) - { - if (*client == *(*it)) - // if found, just do nothing - // so *client keep pointing on a valid object - // on function return - { - // delete new one + // first check if client already exists + for ( auto it=begin(); it!=end(); it++ ) + { + if (*client == *(*it)) + // if found, just do nothing + // so *client keep pointing on a valid object + // on function return + { + // delete new one return; - } - } + } + } // and append m_Clients.push_back(client); - std::cout << "New client " << client->GetCallsign() << " at " << client->GetIp() - << " added with protocol " << client->GetProtocolName(); + std::cout << "New client " << client->GetCallsign() << " at " << client->GetIp() << " added with protocol " << client->GetProtocolName(); if ( client->GetReflectorModule() != ' ' ) { std::cout << " on module " << client->GetReflectorModule(); @@ -79,40 +78,40 @@ void CClients::AddClient(std::shared_ptr client) void CClients::RemoveClient(std::shared_ptr client) { - // look for the client - bool found = false; - for ( auto it=begin(); it!=end(); it++ ) - { - // compare objetc pointers - if ( *it == client ) - { - // found it ! - if ( !(*it)->IsAMaster() ) - { - // remove it - std::cout << "Client " << (*it)->GetCallsign() << " at " << (*it)->GetIp() << " removed with protocol " << (*it)->GetProtocolName(); - if ( (*it)->GetReflectorModule() != ' ' ) - { - std::cout << " on module " << (*it)->GetReflectorModule(); - } - std::cout << std::endl; - m_Clients.erase(it); - // notify - g_Reflector.OnClientsChanged(); + // look for the client + bool found = false; + for ( auto it=begin(); it!=end(); it++ ) + { + // compare objetc pointers + if ( *it == client ) + { + // found it ! + if ( !(*it)->IsAMaster() ) + { + // remove it + std::cout << "Client " << (*it)->GetCallsign() << " at " << (*it)->GetIp() << " removed with protocol " << (*it)->GetProtocolName(); + if ( (*it)->GetReflectorModule() != ' ' ) + { + std::cout << " on module " << (*it)->GetReflectorModule(); + } + std::cout << std::endl; + m_Clients.erase(it); + // notify + g_Reflector.OnClientsChanged(); break; - } - } - } + } + } + } } bool CClients::IsClient(std::shared_ptr client) const { - for ( auto it=cbegin(); it!=cend(); it++ ) - { - if (*it == client) + for ( auto it=cbegin(); it!=cend(); it++ ) + { + if (*it == client) return true; - } - return false; + } + return false; } //////////////////////////////////////////////////////////////////////////////////////// @@ -120,97 +119,89 @@ bool CClients::IsClient(std::shared_ptr client) const std::shared_ptr CClients::FindClient(const CIp &Ip) { - // find client - for ( auto it=begin(); it!=end(); it++ ) - { - if ( (*it)->GetIp() == Ip ) - { - return *it; - } - } + // find client + for ( auto it=begin(); it!=end(); it++ ) + { + if ( (*it)->GetIp() == Ip ) + { + return *it; + } + } - // done - return nullptr; + // done + return nullptr; } std::shared_ptr CClients::FindClient(const CIp &Ip, int Protocol) { - // find client - for ( auto it=begin(); it!=end(); it++ ) - { - if ( ((*it)->GetIp() == Ip) && ((*it)->GetProtocol() == Protocol)) - { - return *it; - } - } + // find client + for ( auto it=begin(); it!=end(); it++ ) + { + if ( ((*it)->GetIp() == Ip) && ((*it)->GetProtocol() == Protocol)) + { + return *it; + } + } - // done - return nullptr; + // done + return nullptr; } std::shared_ptr CClients::FindClient(const CIp &Ip, int Protocol, char ReflectorModule) { - // find client - for ( auto it=begin(); it!=end(); it++ ) - { - if ( ((*it)->GetIp() == Ip) && - ((*it)->GetReflectorModule() == ReflectorModule) && - ((*it)->GetProtocol() == Protocol) ) - { - return *it; - } - } + // find client + for ( auto it=begin(); it!=end(); it++ ) + { + if ( ((*it)->GetIp() == Ip) && ((*it)->GetReflectorModule() == ReflectorModule) && ((*it)->GetProtocol() == Protocol) ) + { + return *it; + } + } - // done - return nullptr; + // done + return nullptr; } std::shared_ptr CClients::FindClient(const CCallsign &Callsign, const CIp &Ip, int Protocol) { - // find client - for ( auto it=begin(); it!=end(); it++ ) - { - if ( (*it)->GetCallsign().HasSameCallsign(Callsign) && - ((*it)->GetIp() == Ip) && - ((*it)->GetProtocol() == Protocol) ) - { - return *it; - } - } + // find client + for ( auto it=begin(); it!=end(); it++ ) + { + if ( (*it)->GetCallsign().HasSameCallsign(Callsign) && ((*it)->GetIp() == Ip) && ((*it)->GetProtocol() == Protocol) ) + { + return *it; + } + } - return nullptr; + return nullptr; } std::shared_ptr CClients::FindClient(const CCallsign &Callsign, char module, const CIp &Ip, int Protocol) { - // find client - for ( auto it=begin(); it!=end(); it++ ) - { - if ( (*it)->GetCallsign().HasSameCallsign(Callsign) && - ((*it)->GetModule() == module) && - ((*it)->GetIp() == Ip) && - ((*it)->GetProtocol() == Protocol) ) - { - return *it; - } - } + // find client + for ( auto it=begin(); it!=end(); it++ ) + { + if ( (*it)->GetCallsign().HasSameCallsign(Callsign) && ((*it)->GetModule() == module) && ((*it)->GetIp() == Ip) && ((*it)->GetProtocol() == Protocol) ) + { + return *it; + } + } - return nullptr; + return nullptr; } std::shared_ptr CClients::FindClient(const CCallsign &Callsign, int Protocol) { - // find client - for ( auto it=begin(); it!=end(); it++ ) - { - if ( ((*it)->GetProtocol() == Protocol) && - (*it)->GetCallsign().HasSameCallsign(Callsign) ) - { - return *it; - } - } + // find client + for ( auto it=begin(); it!=end(); it++ ) + { + if ( ((*it)->GetProtocol() == Protocol) && (*it)->GetCallsign().HasSameCallsign(Callsign) ) + { + return *it; + } + } - return nullptr; + return nullptr; } //////////////////////////////////////////////////////////////////////////////////////// @@ -218,42 +209,39 @@ std::shared_ptr CClients::FindClient(const CCallsign &Callsign, int Pro std::shared_ptr CClients::FindNextClient(int Protocol, std::list>::iterator &it) { - while ( it != end() ) - { - if ( (*it)->GetProtocol() == Protocol ) - { - return *it++; - } + while ( it != end() ) + { + if ( (*it)->GetProtocol() == Protocol ) + { + return *it++; + } it++; - } - return nullptr; + } + return nullptr; } std::shared_ptr CClients::FindNextClient(const CIp &Ip, int Protocol, std::list>::iterator &it) { - while ( it != end() ) - { - if ( ((*it)->GetProtocol() == Protocol) && - ((*it)->GetIp() == Ip) ) - { - return *it++; - } + while ( it != end() ) + { + if ( ((*it)->GetProtocol() == Protocol) && ((*it)->GetIp() == Ip) ) + { + return *it++; + } it++; - } - return nullptr; + } + return nullptr; } std::shared_ptr CClients::FindNextClient(const CCallsign &Callsign, const CIp &Ip, int Protocol, std::list>::iterator &it) { - while ( it != end() ) - { - if ( ((*it)->GetProtocol() == Protocol) && - ((*it)->GetIp() == Ip) && - (*it)->GetCallsign().HasSameCallsign(Callsign) ) - { - return *it++; - } + while ( it != end() ) + { + if ( ((*it)->GetProtocol() == Protocol) && ((*it)->GetIp() == Ip) && (*it)->GetCallsign().HasSameCallsign(Callsign) ) + { + return *it++; + } it++; - } - return nullptr; + } + return nullptr; } diff --git a/src/cclients.h b/src/cclients.h index 37bcf5f..1f54e8a 100644 --- a/src/cclients.h +++ b/src/cclients.h @@ -39,21 +39,21 @@ class CClients { public: - // constructors - CClients(); + // constructors + CClients(); - // destructors - virtual ~CClients(); + // destructors + virtual ~CClients(); - // locks - void Lock(void) { m_Mutex.lock(); } - void Unlock(void) { m_Mutex.unlock(); } + // locks + void Lock(void) { m_Mutex.lock(); } + void Unlock(void) { m_Mutex.unlock(); } - // manage Clients - int GetSize(void) const { return (int)m_Clients.size(); } - void AddClient(std::shared_ptr); - void RemoveClient(std::shared_ptr); - bool IsClient(std::shared_ptr) const; + // manage Clients + int GetSize(void) const { return (int)m_Clients.size(); } + void AddClient(std::shared_ptr); + void RemoveClient(std::shared_ptr); + bool IsClient(std::shared_ptr) const; // pass-thru std::list>::iterator begin() { return m_Clients.begin(); } @@ -61,23 +61,23 @@ public: std::list>::const_iterator cbegin() const { return m_Clients.cbegin(); } std::list>::const_iterator cend() const { return m_Clients.cend(); } - // find clients - std::shared_ptr FindClient(const CIp &); - std::shared_ptr FindClient(const CIp &, int); - std::shared_ptr FindClient(const CIp &, int, char); - std::shared_ptr FindClient(const CCallsign &, const CIp &, int); - std::shared_ptr FindClient(const CCallsign &, char, const CIp &, int); - std::shared_ptr FindClient(const CCallsign &, int); + // find clients + std::shared_ptr FindClient(const CIp &); + std::shared_ptr FindClient(const CIp &, int); + std::shared_ptr FindClient(const CIp &, int, char); + std::shared_ptr FindClient(const CCallsign &, const CIp &, int); + std::shared_ptr FindClient(const CCallsign &, char, const CIp &, int); + std::shared_ptr FindClient(const CCallsign &, int); - // iterate on clients - std::shared_ptr FindNextClient(int, std::list>::iterator &); - std::shared_ptr FindNextClient(const CIp &, int, std::list>::iterator &); - std::shared_ptr FindNextClient(const CCallsign &, const CIp &, int, std::list>::iterator &); + // iterate on clients + std::shared_ptr FindNextClient(int, std::list>::iterator &); + std::shared_ptr FindNextClient(const CIp &, int, std::list>::iterator &); + std::shared_ptr FindNextClient(const CCallsign &, const CIp &, int, std::list>::iterator &); protected: - // data - std::mutex m_Mutex; - std::list> m_Clients; + // data + std::mutex m_Mutex; + std::list> m_Clients; }; diff --git a/src/ccodecstream.cpp b/src/ccodecstream.cpp index 1803cdd..bf58f3a 100644 --- a/src/ccodecstream.cpp +++ b/src/ccodecstream.cpp @@ -38,20 +38,20 @@ CCodecStream::CCodecStream(CPacketStream *PacketStream, uint16 uiId, uint8 uiCodecIn, uint8 uiCodecOut) { - keep_running = true; - m_pThread = nullptr; - m_uiStreamId = uiId; - m_uiPid = 0; - m_uiCodecIn = uiCodecIn; - m_uiCodecOut = uiCodecOut; - m_bConnected = false; - m_fPingMin = -1; - m_fPingMax = -1; - m_fPingSum = 0; - m_fPingCount = 0; - m_uiTotalPackets = 0; - m_uiTimeoutPackets = 0; - m_PacketStream = PacketStream; + keep_running = true; + m_pThread = nullptr; + m_uiStreamId = uiId; + m_uiPid = 0; + m_uiCodecIn = uiCodecIn; + m_uiCodecOut = uiCodecOut; + m_bConnected = false; + m_fPingMin = -1; + m_fPingMax = -1; + m_fPingSum = 0; + m_fPingCount = 0; + m_uiTotalPackets = 0; + m_uiTimeoutPackets = 0; + m_PacketStream = PacketStream; } //////////////////////////////////////////////////////////////////////////////////////// @@ -59,30 +59,30 @@ CCodecStream::CCodecStream(CPacketStream *PacketStream, uint16 uiId, uint8 uiCod CCodecStream::~CCodecStream() { - // close socket - m_Socket.Close(); - - // kill threads - keep_running = false; - if ( m_pThread != nullptr ) - { - m_pThread->join(); - delete m_pThread; + // close socket + m_Socket.Close(); + + // kill threads + keep_running = false; + if ( m_pThread != nullptr ) + { + m_pThread->join(); + delete m_pThread; m_pThread = nullptr; - } - - // empty local queue - while ( !m_LocalQueue.empty() ) - { - delete m_LocalQueue.front(); - m_LocalQueue.pop(); - } - // empty ourselves - while ( !empty() ) - { - delete front(); - pop(); - } + } + + // empty local queue + while ( !m_LocalQueue.empty() ) + { + delete m_LocalQueue.front(); + m_LocalQueue.pop(); + } + // empty ourselves + while ( !empty() ) + { + delete front(); + pop(); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -92,8 +92,8 @@ bool CCodecStream::Init(uint16 uiPort) { m_bConnected = keep_running = false; // prepare for the worst - // create the send to address - m_uiPort = uiPort; + // create the send to address + m_uiPort = uiPort; auto s = g_Reflector.GetTranscoderIp(); m_Ip.Initialize(strchr(s, ':') ? AF_INET6 : AF_INET, m_uiPort, s); @@ -114,10 +114,11 @@ bool CCodecStream::Init(uint16 uiPort) #endif CIp ip(m_Ip.GetFamily(), m_uiPort, s); - // create our socket - if (ip.IsSet()) + // create our socket + if (ip.IsSet()) { - if (! m_Socket.Open(ip)) { + if (! m_Socket.Open(ip)) + { std::cerr << "Error opening socket on IP address " << m_Ip << std::endl; return false; } @@ -131,22 +132,22 @@ bool CCodecStream::Init(uint16 uiPort) keep_running = m_bConnected = true; m_pThread = new std::thread(CCodecStream::Thread, this); - return true; + return true; } void CCodecStream::Close(void) { - // close socket - keep_running = m_bConnected = false; - m_Socket.Close(); - - // kill threads - if ( m_pThread != nullptr ) - { - m_pThread->join(); - delete m_pThread; - m_pThread = nullptr; - } + // close socket + keep_running = m_bConnected = false; + m_Socket.Close(); + + // kill threads + if ( m_pThread != nullptr ) + { + m_pThread->join(); + delete m_pThread; + m_pThread = nullptr; + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -154,7 +155,7 @@ void CCodecStream::Close(void) bool CCodecStream::IsEmpty(void) const { - return (m_LocalQueue.empty() && m_PacketStream->empty()); + return (m_LocalQueue.empty() && m_PacketStream->empty()); } //////////////////////////////////////////////////////////////////////////////////////// @@ -162,96 +163,96 @@ bool CCodecStream::IsEmpty(void) const void CCodecStream::Thread(CCodecStream *This) { - while (This->keep_running) - { - This->Task(); - } + while (This->keep_running) + { + This->Task(); + } } void CCodecStream::Task(void) { - CBuffer Buffer; - CIp Ip; - uint8 Ambe[AMBE_SIZE]; - uint8 DStarSync[] = { 0x55,0x2D,0x16 }; - - // any packet from transcoder - if ( m_Socket.Receive(Buffer, Ip, 5) ) - { - // crack - if ( IsValidAmbePacket(Buffer, Ambe) ) - { - // tickle - m_TimeoutTimer.Now(); - - // update statistics - double ping = m_StatsTimer.DurationSinceNow(); - if ( m_fPingMin == -1 ) - { - m_fPingMin = ping; - m_fPingMax = ping; - - } - else - { - m_fPingMin = MIN(m_fPingMin, ping); - m_fPingMax = MAX(m_fPingMax, ping); - - } - m_fPingSum += ping; - m_fPingCount += 1; - - // pop the original packet - if ( !m_LocalQueue.empty() ) - { - CDvFramePacket *Packet = (CDvFramePacket *)m_LocalQueue.front(); - m_LocalQueue.pop(); - // todo: check the PID - // update content with transcoded ambe - Packet->SetAmbe(m_uiCodecOut, Ambe); - // tag syncs in DvData - if ( (m_uiCodecOut == CODEC_AMBEPLUS) && (Packet->GetPacketId() % 21) == 0 ) - { - Packet->SetDvData(DStarSync); - } - // and push it back to client - m_PacketStream->Lock(); - m_PacketStream->push(Packet); - m_PacketStream->Unlock(); - } - else - { - std::cout << "Unexpected transcoded packet received from ambed" << std::endl; - } - } - } - - // anything in our queue - while ( !empty() ) - { - // yes, pop it from queue - CPacket *Packet = front(); - pop(); - - // yes, send to ambed - // this assume that thread pushing the Packet - // have verified that the CodecStream is connected - // and that the packet needs transcoding - m_StatsTimer.Now(); - m_uiTotalPackets++; - EncodeAmbePacket(&Buffer, ((CDvFramePacket *)Packet)->GetAmbe(m_uiCodecIn)); - m_Socket.Send(Buffer, m_Ip, m_uiPort); - - // and push to our local queue - m_LocalQueue.push(Packet); - } - - // handle timeout - if ( !m_LocalQueue.empty() && (m_TimeoutTimer.DurationSinceNow() >= (TRANSCODER_AMBEPACKET_TIMEOUT/1000.0f)) ) - { - //std::cout << "ambed packet timeout" << std::endl; - m_uiTimeoutPackets++; - } + CBuffer Buffer; + CIp Ip; + uint8 Ambe[AMBE_SIZE]; + uint8 DStarSync[] = { 0x55,0x2D,0x16 }; + + // any packet from transcoder + if ( m_Socket.Receive(Buffer, Ip, 5) ) + { + // crack + if ( IsValidAmbePacket(Buffer, Ambe) ) + { + // tickle + m_TimeoutTimer.Now(); + + // update statistics + double ping = m_StatsTimer.DurationSinceNow(); + if ( m_fPingMin == -1 ) + { + m_fPingMin = ping; + m_fPingMax = ping; + + } + else + { + m_fPingMin = MIN(m_fPingMin, ping); + m_fPingMax = MAX(m_fPingMax, ping); + + } + m_fPingSum += ping; + m_fPingCount += 1; + + // pop the original packet + if ( !m_LocalQueue.empty() ) + { + CDvFramePacket *Packet = (CDvFramePacket *)m_LocalQueue.front(); + m_LocalQueue.pop(); + // todo: check the PID + // update content with transcoded ambe + Packet->SetAmbe(m_uiCodecOut, Ambe); + // tag syncs in DvData + if ( (m_uiCodecOut == CODEC_AMBEPLUS) && (Packet->GetPacketId() % 21) == 0 ) + { + Packet->SetDvData(DStarSync); + } + // and push it back to client + m_PacketStream->Lock(); + m_PacketStream->push(Packet); + m_PacketStream->Unlock(); + } + else + { + std::cout << "Unexpected transcoded packet received from ambed" << std::endl; + } + } + } + + // anything in our queue + while ( !empty() ) + { + // yes, pop it from queue + CPacket *Packet = front(); + pop(); + + // yes, send to ambed + // this assume that thread pushing the Packet + // have verified that the CodecStream is connected + // and that the packet needs transcoding + m_StatsTimer.Now(); + m_uiTotalPackets++; + EncodeAmbePacket(&Buffer, ((CDvFramePacket *)Packet)->GetAmbe(m_uiCodecIn)); + m_Socket.Send(Buffer, m_Ip, m_uiPort); + + // and push to our local queue + m_LocalQueue.push(Packet); + } + + // handle timeout + if ( !m_LocalQueue.empty() && (m_TimeoutTimer.DurationSinceNow() >= (TRANSCODER_AMBEPACKET_TIMEOUT/1000.0f)) ) + { + //std::cout << "ambed packet timeout" << std::endl; + m_uiTimeoutPackets++; + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -259,14 +260,14 @@ void CCodecStream::Task(void) bool CCodecStream::IsValidAmbePacket(const CBuffer &Buffer, uint8 *Ambe) { - bool valid = false; - - if ( (Buffer.size() == 11) && (Buffer.data()[0] == m_uiCodecOut) ) - { - ::memcpy(Ambe, &(Buffer.data()[2]), 9); - valid = true; - } - return valid; + bool valid = false; + + if ( (Buffer.size() == 11) && (Buffer.data()[0] == m_uiCodecOut) ) + { + ::memcpy(Ambe, &(Buffer.data()[2]), 9); + valid = true; + } + return valid; } //////////////////////////////////////////////////////////////////////////////////////// @@ -274,8 +275,8 @@ bool CCodecStream::IsValidAmbePacket(const CBuffer &Buffer, uint8 *Ambe) void CCodecStream::EncodeAmbePacket(CBuffer *Buffer, const uint8 *Ambe) { - Buffer->clear(); - Buffer->Append(m_uiCodecIn); - Buffer->Append(m_uiPid); - Buffer->Append((uint8 *)Ambe, 9); + Buffer->clear(); + Buffer->Append(m_uiCodecIn); + Buffer->Append(m_uiPid); + Buffer->Append((uint8 *)Ambe, 9); } diff --git a/src/ccodecstream.h b/src/ccodecstream.h index 1b9e6e0..36aad17 100644 --- a/src/ccodecstream.h +++ b/src/ccodecstream.h @@ -46,69 +46,69 @@ class CPacketStream; class CCodecStream : public CPacketQueue { public: - // constructor - CCodecStream(CPacketStream *, uint16, uint8, uint8); + // constructor + CCodecStream(CPacketStream *, uint16, uint8, uint8); - // destructor - virtual ~CCodecStream(); + // destructor + virtual ~CCodecStream(); - // initialization - bool Init(uint16); - void Close(void); + // initialization + bool Init(uint16); + void Close(void); - // get - bool IsConnected(void) const { return m_bConnected; } - uint16 GetStreamId(void) const { return m_uiStreamId; } - double GetPingMin(void) const { return m_fPingMin; } - double GetPingMax(void) const { return m_fPingMax; } - double GetPingAve(void) const { return (m_fPingCount != 0) ? m_fPingSum/m_fPingCount : 0; } - uint32 GetTotalPackets(void) const { return m_uiTotalPackets; } - uint32 GetTimeoutPackets(void) const { return m_uiTimeoutPackets; } - bool IsEmpty(void) const; + // get + bool IsConnected(void) const { return m_bConnected; } + uint16 GetStreamId(void) const { return m_uiStreamId; } + double GetPingMin(void) const { return m_fPingMin; } + double GetPingMax(void) const { return m_fPingMax; } + double GetPingAve(void) const { return (m_fPingCount != 0) ? m_fPingSum/m_fPingCount : 0; } + uint32 GetTotalPackets(void) const { return m_uiTotalPackets; } + uint32 GetTimeoutPackets(void) const { return m_uiTimeoutPackets; } + bool IsEmpty(void) const; - // task - static void Thread(CCodecStream *); - void Task(void); + // task + static void Thread(CCodecStream *); + void Task(void); protected: - // packet decoding helpers - bool IsValidAmbePacket(const CBuffer &, uint8 *); + // packet decoding helpers + bool IsValidAmbePacket(const CBuffer &, uint8 *); - // packet encoding helpers - void EncodeAmbePacket(CBuffer *, const uint8 *); + // packet encoding helpers + void EncodeAmbePacket(CBuffer *, const uint8 *); protected: - // data - uint16 m_uiStreamId; - uint16 m_uiPort; - uint8 m_uiPid; - uint8 m_uiCodecIn; - uint8 m_uiCodecOut; - - // socket - CIp m_Ip; - CUdpSocket m_Socket; - bool m_bConnected; - - // associated packet stream - CPacketStream *m_PacketStream; - CPacketQueue m_LocalQueue; - - // thread - std::atomic keep_running; - std::thread *m_pThread; - CTimePoint m_TimeoutTimer; - CTimePoint m_StatsTimer; - - // statistics - double m_fPingMin; - double m_fPingMax; - double m_fPingSum; - double m_fPingCount; - uint32 m_uiTotalPackets; - uint32 m_uiTimeoutPackets; + // data + uint16 m_uiStreamId; + uint16 m_uiPort; + uint8 m_uiPid; + uint8 m_uiCodecIn; + uint8 m_uiCodecOut; + + // socket + CIp m_Ip; + CUdpSocket m_Socket; + bool m_bConnected; + + // associated packet stream + CPacketStream *m_PacketStream; + CPacketQueue m_LocalQueue; + + // thread + std::atomic keep_running; + std::thread *m_pThread; + CTimePoint m_TimeoutTimer; + CTimePoint m_StatsTimer; + + // statistics + double m_fPingMin; + double m_fPingMax; + double m_fPingSum; + double m_fPingCount; + uint32 m_uiTotalPackets; + uint32 m_uiTimeoutPackets; }; diff --git a/src/ccrc.cpp b/src/ccrc.cpp index 934b7cd..95b0eee 100644 --- a/src/ccrc.cpp +++ b/src/ccrc.cpp @@ -25,227 +25,238 @@ #include #include -const uint8_t CRC8_TABLE[] = { - 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, - 0x24, 0x23, 0x2A, 0x2D, 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, - 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, 0xE0, 0xE7, 0xEE, 0xE9, - 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, - 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1, - 0xB4, 0xB3, 0xBA, 0xBD, 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, - 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, 0xB7, 0xB0, 0xB9, 0xBE, - 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, - 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, - 0x03, 0x04, 0x0D, 0x0A, 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, - 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, 0x89, 0x8E, 0x87, 0x80, - 0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, - 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, - 0xDD, 0xDA, 0xD3, 0xD4, 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, - 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, 0x19, 0x1E, 0x17, 0x10, - 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, - 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, - 0x6A, 0x6D, 0x64, 0x63, 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, - 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, 0xAE, 0xA9, 0xA0, 0xA7, - 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, - 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, - 0xFA, 0xFD, 0xF4, 0xF3, 0x01 }; - -const uint16_t CCITT16_TABLE1[] = { - 0x0000U, 0x1189U, 0x2312U, 0x329bU, 0x4624U, 0x57adU, 0x6536U, 0x74bfU, - 0x8c48U, 0x9dc1U, 0xaf5aU, 0xbed3U, 0xca6cU, 0xdbe5U, 0xe97eU, 0xf8f7U, - 0x1081U, 0x0108U, 0x3393U, 0x221aU, 0x56a5U, 0x472cU, 0x75b7U, 0x643eU, - 0x9cc9U, 0x8d40U, 0xbfdbU, 0xae52U, 0xdaedU, 0xcb64U, 0xf9ffU, 0xe876U, - 0x2102U, 0x308bU, 0x0210U, 0x1399U, 0x6726U, 0x76afU, 0x4434U, 0x55bdU, - 0xad4aU, 0xbcc3U, 0x8e58U, 0x9fd1U, 0xeb6eU, 0xfae7U, 0xc87cU, 0xd9f5U, - 0x3183U, 0x200aU, 0x1291U, 0x0318U, 0x77a7U, 0x662eU, 0x54b5U, 0x453cU, - 0xbdcbU, 0xac42U, 0x9ed9U, 0x8f50U, 0xfbefU, 0xea66U, 0xd8fdU, 0xc974U, - 0x4204U, 0x538dU, 0x6116U, 0x709fU, 0x0420U, 0x15a9U, 0x2732U, 0x36bbU, - 0xce4cU, 0xdfc5U, 0xed5eU, 0xfcd7U, 0x8868U, 0x99e1U, 0xab7aU, 0xbaf3U, - 0x5285U, 0x430cU, 0x7197U, 0x601eU, 0x14a1U, 0x0528U, 0x37b3U, 0x263aU, - 0xdecdU, 0xcf44U, 0xfddfU, 0xec56U, 0x98e9U, 0x8960U, 0xbbfbU, 0xaa72U, - 0x6306U, 0x728fU, 0x4014U, 0x519dU, 0x2522U, 0x34abU, 0x0630U, 0x17b9U, - 0xef4eU, 0xfec7U, 0xcc5cU, 0xddd5U, 0xa96aU, 0xb8e3U, 0x8a78U, 0x9bf1U, - 0x7387U, 0x620eU, 0x5095U, 0x411cU, 0x35a3U, 0x242aU, 0x16b1U, 0x0738U, - 0xffcfU, 0xee46U, 0xdcddU, 0xcd54U, 0xb9ebU, 0xa862U, 0x9af9U, 0x8b70U, - 0x8408U, 0x9581U, 0xa71aU, 0xb693U, 0xc22cU, 0xd3a5U, 0xe13eU, 0xf0b7U, - 0x0840U, 0x19c9U, 0x2b52U, 0x3adbU, 0x4e64U, 0x5fedU, 0x6d76U, 0x7cffU, - 0x9489U, 0x8500U, 0xb79bU, 0xa612U, 0xd2adU, 0xc324U, 0xf1bfU, 0xe036U, - 0x18c1U, 0x0948U, 0x3bd3U, 0x2a5aU, 0x5ee5U, 0x4f6cU, 0x7df7U, 0x6c7eU, - 0xa50aU, 0xb483U, 0x8618U, 0x9791U, 0xe32eU, 0xf2a7U, 0xc03cU, 0xd1b5U, - 0x2942U, 0x38cbU, 0x0a50U, 0x1bd9U, 0x6f66U, 0x7eefU, 0x4c74U, 0x5dfdU, - 0xb58bU, 0xa402U, 0x9699U, 0x8710U, 0xf3afU, 0xe226U, 0xd0bdU, 0xc134U, - 0x39c3U, 0x284aU, 0x1ad1U, 0x0b58U, 0x7fe7U, 0x6e6eU, 0x5cf5U, 0x4d7cU, - 0xc60cU, 0xd785U, 0xe51eU, 0xf497U, 0x8028U, 0x91a1U, 0xa33aU, 0xb2b3U, - 0x4a44U, 0x5bcdU, 0x6956U, 0x78dfU, 0x0c60U, 0x1de9U, 0x2f72U, 0x3efbU, - 0xd68dU, 0xc704U, 0xf59fU, 0xe416U, 0x90a9U, 0x8120U, 0xb3bbU, 0xa232U, - 0x5ac5U, 0x4b4cU, 0x79d7U, 0x685eU, 0x1ce1U, 0x0d68U, 0x3ff3U, 0x2e7aU, - 0xe70eU, 0xf687U, 0xc41cU, 0xd595U, 0xa12aU, 0xb0a3U, 0x8238U, 0x93b1U, - 0x6b46U, 0x7acfU, 0x4854U, 0x59ddU, 0x2d62U, 0x3cebU, 0x0e70U, 0x1ff9U, - 0xf78fU, 0xe606U, 0xd49dU, 0xc514U, 0xb1abU, 0xa022U, 0x92b9U, 0x8330U, - 0x7bc7U, 0x6a4eU, 0x58d5U, 0x495cU, 0x3de3U, 0x2c6aU, 0x1ef1U, 0x0f78U }; - -const uint16_t CCITT16_TABLE2[] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, - 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, - 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, - 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, - 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, - 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, - 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, - 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, - 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, - 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, - 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, - 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, - 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, - 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, - 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, - 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, - 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, - 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, - 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, - 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, - 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, - 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, - 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 }; +const uint8_t CRC8_TABLE[] = +{ + 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, + 0x24, 0x23, 0x2A, 0x2D, 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, + 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, 0xE0, 0xE7, 0xEE, 0xE9, + 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, + 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1, + 0xB4, 0xB3, 0xBA, 0xBD, 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, + 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, 0xB7, 0xB0, 0xB9, 0xBE, + 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, + 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, + 0x03, 0x04, 0x0D, 0x0A, 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, + 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, 0x89, 0x8E, 0x87, 0x80, + 0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, + 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, + 0xDD, 0xDA, 0xD3, 0xD4, 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, + 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, 0x19, 0x1E, 0x17, 0x10, + 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, + 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, + 0x6A, 0x6D, 0x64, 0x63, 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, + 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, 0xAE, 0xA9, 0xA0, 0xA7, + 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, + 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, + 0xFA, 0xFD, 0xF4, 0xF3, 0x01 +}; + +const uint16_t CCITT16_TABLE1[] = +{ + 0x0000U, 0x1189U, 0x2312U, 0x329bU, 0x4624U, 0x57adU, 0x6536U, 0x74bfU, + 0x8c48U, 0x9dc1U, 0xaf5aU, 0xbed3U, 0xca6cU, 0xdbe5U, 0xe97eU, 0xf8f7U, + 0x1081U, 0x0108U, 0x3393U, 0x221aU, 0x56a5U, 0x472cU, 0x75b7U, 0x643eU, + 0x9cc9U, 0x8d40U, 0xbfdbU, 0xae52U, 0xdaedU, 0xcb64U, 0xf9ffU, 0xe876U, + 0x2102U, 0x308bU, 0x0210U, 0x1399U, 0x6726U, 0x76afU, 0x4434U, 0x55bdU, + 0xad4aU, 0xbcc3U, 0x8e58U, 0x9fd1U, 0xeb6eU, 0xfae7U, 0xc87cU, 0xd9f5U, + 0x3183U, 0x200aU, 0x1291U, 0x0318U, 0x77a7U, 0x662eU, 0x54b5U, 0x453cU, + 0xbdcbU, 0xac42U, 0x9ed9U, 0x8f50U, 0xfbefU, 0xea66U, 0xd8fdU, 0xc974U, + 0x4204U, 0x538dU, 0x6116U, 0x709fU, 0x0420U, 0x15a9U, 0x2732U, 0x36bbU, + 0xce4cU, 0xdfc5U, 0xed5eU, 0xfcd7U, 0x8868U, 0x99e1U, 0xab7aU, 0xbaf3U, + 0x5285U, 0x430cU, 0x7197U, 0x601eU, 0x14a1U, 0x0528U, 0x37b3U, 0x263aU, + 0xdecdU, 0xcf44U, 0xfddfU, 0xec56U, 0x98e9U, 0x8960U, 0xbbfbU, 0xaa72U, + 0x6306U, 0x728fU, 0x4014U, 0x519dU, 0x2522U, 0x34abU, 0x0630U, 0x17b9U, + 0xef4eU, 0xfec7U, 0xcc5cU, 0xddd5U, 0xa96aU, 0xb8e3U, 0x8a78U, 0x9bf1U, + 0x7387U, 0x620eU, 0x5095U, 0x411cU, 0x35a3U, 0x242aU, 0x16b1U, 0x0738U, + 0xffcfU, 0xee46U, 0xdcddU, 0xcd54U, 0xb9ebU, 0xa862U, 0x9af9U, 0x8b70U, + 0x8408U, 0x9581U, 0xa71aU, 0xb693U, 0xc22cU, 0xd3a5U, 0xe13eU, 0xf0b7U, + 0x0840U, 0x19c9U, 0x2b52U, 0x3adbU, 0x4e64U, 0x5fedU, 0x6d76U, 0x7cffU, + 0x9489U, 0x8500U, 0xb79bU, 0xa612U, 0xd2adU, 0xc324U, 0xf1bfU, 0xe036U, + 0x18c1U, 0x0948U, 0x3bd3U, 0x2a5aU, 0x5ee5U, 0x4f6cU, 0x7df7U, 0x6c7eU, + 0xa50aU, 0xb483U, 0x8618U, 0x9791U, 0xe32eU, 0xf2a7U, 0xc03cU, 0xd1b5U, + 0x2942U, 0x38cbU, 0x0a50U, 0x1bd9U, 0x6f66U, 0x7eefU, 0x4c74U, 0x5dfdU, + 0xb58bU, 0xa402U, 0x9699U, 0x8710U, 0xf3afU, 0xe226U, 0xd0bdU, 0xc134U, + 0x39c3U, 0x284aU, 0x1ad1U, 0x0b58U, 0x7fe7U, 0x6e6eU, 0x5cf5U, 0x4d7cU, + 0xc60cU, 0xd785U, 0xe51eU, 0xf497U, 0x8028U, 0x91a1U, 0xa33aU, 0xb2b3U, + 0x4a44U, 0x5bcdU, 0x6956U, 0x78dfU, 0x0c60U, 0x1de9U, 0x2f72U, 0x3efbU, + 0xd68dU, 0xc704U, 0xf59fU, 0xe416U, 0x90a9U, 0x8120U, 0xb3bbU, 0xa232U, + 0x5ac5U, 0x4b4cU, 0x79d7U, 0x685eU, 0x1ce1U, 0x0d68U, 0x3ff3U, 0x2e7aU, + 0xe70eU, 0xf687U, 0xc41cU, 0xd595U, 0xa12aU, 0xb0a3U, 0x8238U, 0x93b1U, + 0x6b46U, 0x7acfU, 0x4854U, 0x59ddU, 0x2d62U, 0x3cebU, 0x0e70U, 0x1ff9U, + 0xf78fU, 0xe606U, 0xd49dU, 0xc514U, 0xb1abU, 0xa022U, 0x92b9U, 0x8330U, + 0x7bc7U, 0x6a4eU, 0x58d5U, 0x495cU, 0x3de3U, 0x2c6aU, 0x1ef1U, 0x0f78U +}; + +const uint16_t CCITT16_TABLE2[] = +{ + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 +}; bool CCRC::checkFiveBit(bool* in, unsigned int tcrc) { - assert(in != nullptr); + assert(in != nullptr); - unsigned int crc; - encodeFiveBit(in, crc); + unsigned int crc; + encodeFiveBit(in, crc); - return crc == tcrc; + return crc == tcrc; } void CCRC::encodeFiveBit(const bool* in, unsigned int& tcrc) { - assert(in != nullptr); + assert(in != nullptr); - unsigned short total = 0U; - for (unsigned int i = 0U; i < 72U; i += 8U) { - unsigned char c; - CUtils::bitsToByteBE(in + i, c); - total += c; - } + unsigned short total = 0U; + for (unsigned int i = 0U; i < 72U; i += 8U) + { + unsigned char c; + CUtils::bitsToByteBE(in + i, c); + total += c; + } - total %= 31U; + total %= 31U; - tcrc = total; + tcrc = total; } void CCRC::addCCITT162(unsigned char *in, unsigned int length) { - assert(in != nullptr); - assert(length > 2U); + assert(in != nullptr); + assert(length > 2U); - union { - uint16_t crc16; - uint8_t crc8[2U]; - }; + union + { + uint16_t crc16; + uint8_t crc8[2U]; + }; - crc16 = 0U; + crc16 = 0U; - for (unsigned i = 0U; i < (length - 2U); i++) - crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ in[i]]; + for (unsigned i = 0U; i < (length - 2U); i++) + crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ in[i]]; - crc16 = ~crc16; + crc16 = ~crc16; - in[length - 1U] = crc8[0U]; - in[length - 2U] = crc8[1U]; + in[length - 1U] = crc8[0U]; + in[length - 2U] = crc8[1U]; } bool CCRC::checkCCITT162(const unsigned char *in, unsigned int length) { - assert(in != nullptr); - assert(length > 2U); + assert(in != nullptr); + assert(length > 2U); - union { - uint16_t crc16; - uint8_t crc8[2U]; - }; + union + { + uint16_t crc16; + uint8_t crc8[2U]; + }; - crc16 = 0U; + crc16 = 0U; - for (unsigned i = 0U; i < (length - 2U); i++) - crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ in[i]]; + for (unsigned i = 0U; i < (length - 2U); i++) + crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ in[i]]; - crc16 = ~crc16; + crc16 = ~crc16; - return crc8[0U] == in[length - 1U] && crc8[1U] == in[length - 2U]; + return crc8[0U] == in[length - 1U] && crc8[1U] == in[length - 2U]; } void CCRC::addCCITT161(unsigned char *in, unsigned int length) { - assert(in != nullptr); - assert(length > 2U); + assert(in != nullptr); + assert(length > 2U); - union { - uint16_t crc16; - uint8_t crc8[2U]; - }; + union + { + uint16_t crc16; + uint8_t crc8[2U]; + }; - crc16 = 0xFFFFU; + crc16 = 0xFFFFU; - for (unsigned int i = 0U; i < (length - 2U); i++) - crc16 = uint16_t(crc8[1U]) ^ CCITT16_TABLE1[crc8[0U] ^ in[i]]; + for (unsigned int i = 0U; i < (length - 2U); i++) + crc16 = uint16_t(crc8[1U]) ^ CCITT16_TABLE1[crc8[0U] ^ in[i]]; - crc16 = ~crc16; + crc16 = ~crc16; - in[length - 2U] = crc8[0U]; - in[length - 1U] = crc8[1U]; + in[length - 2U] = crc8[0U]; + in[length - 1U] = crc8[1U]; } bool CCRC::checkCCITT161(const unsigned char *in, unsigned int length) { - assert(in != nullptr); - assert(length > 2U); + assert(in != nullptr); + assert(length > 2U); - union { - uint16_t crc16; - uint8_t crc8[2U]; - }; + union + { + uint16_t crc16; + uint8_t crc8[2U]; + }; - crc16 = 0xFFFFU; + crc16 = 0xFFFFU; - for (unsigned int i = 0U; i < (length - 2U); i++) - crc16 = uint16_t(crc8[1U]) ^ CCITT16_TABLE1[crc8[0U] ^ in[i]]; + for (unsigned int i = 0U; i < (length - 2U); i++) + crc16 = uint16_t(crc8[1U]) ^ CCITT16_TABLE1[crc8[0U] ^ in[i]]; - crc16 = ~crc16; + crc16 = ~crc16; - return crc8[0U] == in[length - 2U] && crc8[1U] == in[length - 1U]; + return crc8[0U] == in[length - 2U] && crc8[1U] == in[length - 1U]; } unsigned char CCRC::crc8(const unsigned char *in, unsigned int length) { - assert(in != nullptr); + assert(in != nullptr); - uint8_t crc = 0U; + uint8_t crc = 0U; - for (unsigned int i = 0U; i < length; i++) - crc = CRC8_TABLE[crc ^ in[i]]; + for (unsigned int i = 0U; i < length; i++) + crc = CRC8_TABLE[crc ^ in[i]]; - return crc; + return crc; } unsigned char CCRC::addCRC(const unsigned char* in, unsigned int length) { - assert(in != nullptr); + assert(in != nullptr); - unsigned char crc = 0U; + unsigned char crc = 0U; - for (unsigned int i = 0U; i < length; i++) - crc += in[i]; + for (unsigned int i = 0U; i < length; i++) + crc += in[i]; - return crc; + return crc; } diff --git a/src/ccrc.h b/src/ccrc.h index 82730d4..90bca98 100644 --- a/src/ccrc.h +++ b/src/ccrc.h @@ -22,18 +22,18 @@ class CCRC { public: - static bool checkFiveBit(bool* in, unsigned int tcrc); - static void encodeFiveBit(const bool* in, unsigned int& tcrc); - - static void addCCITT161(unsigned char* in, unsigned int length); - static void addCCITT162(unsigned char* in, unsigned int length); - - static bool checkCCITT161(const unsigned char* in, unsigned int length); - static bool checkCCITT162(const unsigned char* in, unsigned int length); - - static unsigned char crc8(const unsigned char* in, unsigned int length); - - static unsigned char addCRC(const unsigned char* in, unsigned int length); + static bool checkFiveBit(bool* in, unsigned int tcrc); + static void encodeFiveBit(const bool* in, unsigned int& tcrc); + + static void addCCITT161(unsigned char* in, unsigned int length); + static void addCCITT162(unsigned char* in, unsigned int length); + + static bool checkCCITT161(const unsigned char* in, unsigned int length); + static bool checkCCITT162(const unsigned char* in, unsigned int length); + + static unsigned char crc8(const unsigned char* in, unsigned int length); + + static unsigned char addCRC(const unsigned char* in, unsigned int length); }; #endif diff --git a/src/cdcsclient.cpp b/src/cdcsclient.cpp index eec1d19..f14a249 100644 --- a/src/cdcsclient.cpp +++ b/src/cdcsclient.cpp @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- #include "main.h" @@ -34,12 +34,12 @@ CDcsClient::CDcsClient() } CDcsClient::CDcsClient(const CCallsign &callsign, const CIp &ip, char reflectorModule) -: CClient(callsign, ip, reflectorModule) + : CClient(callsign, ip, reflectorModule) { } CDcsClient::CDcsClient(const CDcsClient &client) -: CClient(client) + : CClient(client) { } @@ -48,5 +48,5 @@ CDcsClient::CDcsClient(const CDcsClient &client) bool CDcsClient::IsAlive(void) const { - return (m_LastKeepaliveTime.DurationSinceNow() < DCS_KEEPALIVE_TIMEOUT); + return (m_LastKeepaliveTime.DurationSinceNow() < DCS_KEEPALIVE_TIMEOUT); } diff --git a/src/cdcsclient.h b/src/cdcsclient.h index 2e579f4..62ae4ef 100644 --- a/src/cdcsclient.h +++ b/src/cdcsclient.h @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- #ifndef cdcsclient_h @@ -37,22 +37,22 @@ class CDcsClient : public CClient { public: - // constructors - CDcsClient(); - CDcsClient(const CCallsign &, const CIp &, char = ' '); - CDcsClient(const CDcsClient &); - - // destructor - virtual ~CDcsClient() {}; - - // identity - int GetProtocol(void) const { return PROTOCOL_DCS; } - const char *GetProtocolName(void) const { return "DCS"; } - int GetCodec(void) const { return CODEC_AMBEPLUS; } - bool IsNode(void) const { return true; } - - // status - bool IsAlive(void) const; + // constructors + CDcsClient(); + CDcsClient(const CCallsign &, const CIp &, char = ' '); + CDcsClient(const CDcsClient &); + + // destructor + virtual ~CDcsClient() {}; + + // identity + int GetProtocol(void) const { return PROTOCOL_DCS; } + const char *GetProtocolName(void) const { return "DCS"; } + int GetCodec(void) const { return CODEC_AMBEPLUS; } + bool IsNode(void) const { return true; } + + // status + bool IsAlive(void) const; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cdcsprotocol.cpp b/src/cdcsprotocol.cpp index 56e2afe..4bb5b09 100644 --- a/src/cdcsprotocol.cpp +++ b/src/cdcsprotocol.cpp @@ -35,15 +35,15 @@ bool CDcsProtocol::Init(void) { - // base class - if (! CProtocol::Initialize("DCS", DCS_PORT, DSTAR_IPV4, DSTAR_IPV6)) + // base class + if (! CProtocol::Initialize("DCS", DCS_PORT, DSTAR_IPV4, DSTAR_IPV6)) return false; - // update time - m_LastKeepaliveTime.Now(); + // update time + m_LastKeepaliveTime.Now(); - // done - return true; + // done + return true; } @@ -53,14 +53,14 @@ bool CDcsProtocol::Init(void) void CDcsProtocol::Task(void) { - CBuffer Buffer; - CIp Ip; - CCallsign Callsign; - char ToLinkModule; - CDvHeaderPacket *Header; - CDvFramePacket *Frame; - - // handle incoming packets + CBuffer Buffer; + CIp Ip; + CCallsign Callsign; + char ToLinkModule; + CDvHeaderPacket *Header; + CDvFramePacket *Frame; + + // handle incoming packets #if DSTAR_IPV6==true #if DSTAR_IPV4==true if ( ReceiveDS(Buffer, Ip, 20) ) @@ -70,128 +70,128 @@ void CDcsProtocol::Task(void) #else if ( Receive4(Buffer, Ip, 20) ) #endif - { - // crack the packet - if ( IsValidDvPacket(Buffer, &Header, &Frame) ) - { - //std::cout << "DCS DV packet" << std::endl; - - // callsign muted? - if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_DCS, Header->GetRpt2Module()) ) - { - // handle it - OnDvHeaderPacketIn(Header, Ip); - - if ( !Frame->IsLastPacket() ) - { - //std::cout << "DCS DV frame" << std::endl; - OnDvFramePacketIn(Frame, &Ip); - } - else - { - //std::cout << "DCS DV last frame" << std::endl; - OnDvLastFramePacketIn((CDvLastFramePacket *)Frame, &Ip); - } - } - else - { - delete Header; - delete Frame; - } - } - else if ( IsValidConnectPacket(Buffer, &Callsign, &ToLinkModule) ) - { - std::cout << "DCS connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl; - - // callsign authorized? - if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_DCS) && g_Reflector.IsValidModule(ToLinkModule) ) - { - // valid module ? - if ( g_Reflector.IsValidModule(ToLinkModule) ) - { - // acknowledge the request - EncodeConnectAckPacket(Callsign, ToLinkModule, &Buffer); - Send(Buffer, Ip); - - // create the client and append - g_Reflector.GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule)); - g_Reflector.ReleaseClients(); - } - else - { - std::cout << "DCS node " << Callsign << " connect attempt on non-existing module" << std::endl; - - // deny the request - EncodeConnectNackPacket(Callsign, ToLinkModule, &Buffer); - Send(Buffer, Ip); - } - } - else - { - // deny the request - EncodeConnectNackPacket(Callsign, ToLinkModule, &Buffer); - Send(Buffer, Ip); - } - - } - else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) - { - std::cout << "DCS disconnect packet from " << Callsign << " at " << Ip << std::endl; - - // find client - CClients *clients = g_Reflector.GetClients(); - std::shared_ptrclient = clients->FindClient(Ip, PROTOCOL_DCS); - if ( client != nullptr ) - { - // remove it - clients->RemoveClient(client); - // and acknowledge the disconnect - EncodeConnectNackPacket(Callsign, ' ', &Buffer); - Send(Buffer, Ip); - } - g_Reflector.ReleaseClients(); - } - else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) - { - //std::cout << "DCS keepalive packet from " << Callsign << " at " << Ip << std::endl; - - // find all clients with that callsign & ip and keep them alive - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(Callsign, Ip, PROTOCOL_DCS, it)) != nullptr ) - { - client->Alive(); - } - g_Reflector.ReleaseClients(); - } - else if ( IsIgnorePacket(Buffer) ) - { - // valid but ignore packet - //std::cout << "DCS ignored packet from " << Ip << std::endl; - } - else - { - // invalid packet - std::cout << "DCS packet (" << Buffer.size() << ") from " << Ip << std::endl; - } - } - - // handle end of streaming timeout - CheckStreamsTimeout(); - - // handle queue from reflector - HandleQueue(); - - // keep client alive - if ( m_LastKeepaliveTime.DurationSinceNow() > DCS_KEEPALIVE_PERIOD ) - { - // - HandleKeepalives(); - - // update time - m_LastKeepaliveTime.Now(); - } + { + // crack the packet + if ( IsValidDvPacket(Buffer, &Header, &Frame) ) + { + //std::cout << "DCS DV packet" << std::endl; + + // callsign muted? + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_DCS, Header->GetRpt2Module()) ) + { + // handle it + OnDvHeaderPacketIn(Header, Ip); + + if ( !Frame->IsLastPacket() ) + { + //std::cout << "DCS DV frame" << std::endl; + OnDvFramePacketIn(Frame, &Ip); + } + else + { + //std::cout << "DCS DV last frame" << std::endl; + OnDvLastFramePacketIn((CDvLastFramePacket *)Frame, &Ip); + } + } + else + { + delete Header; + delete Frame; + } + } + else if ( IsValidConnectPacket(Buffer, &Callsign, &ToLinkModule) ) + { + std::cout << "DCS connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl; + + // callsign authorized? + if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_DCS) && g_Reflector.IsValidModule(ToLinkModule) ) + { + // valid module ? + if ( g_Reflector.IsValidModule(ToLinkModule) ) + { + // acknowledge the request + EncodeConnectAckPacket(Callsign, ToLinkModule, &Buffer); + Send(Buffer, Ip); + + // create the client and append + g_Reflector.GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule)); + g_Reflector.ReleaseClients(); + } + else + { + std::cout << "DCS node " << Callsign << " connect attempt on non-existing module" << std::endl; + + // deny the request + EncodeConnectNackPacket(Callsign, ToLinkModule, &Buffer); + Send(Buffer, Ip); + } + } + else + { + // deny the request + EncodeConnectNackPacket(Callsign, ToLinkModule, &Buffer); + Send(Buffer, Ip); + } + + } + else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) + { + std::cout << "DCS disconnect packet from " << Callsign << " at " << Ip << std::endl; + + // find client + CClients *clients = g_Reflector.GetClients(); + std::shared_ptrclient = clients->FindClient(Ip, PROTOCOL_DCS); + if ( client != nullptr ) + { + // remove it + clients->RemoveClient(client); + // and acknowledge the disconnect + EncodeConnectNackPacket(Callsign, ' ', &Buffer); + Send(Buffer, Ip); + } + g_Reflector.ReleaseClients(); + } + else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) + { + //std::cout << "DCS keepalive packet from " << Callsign << " at " << Ip << std::endl; + + // find all clients with that callsign & ip and keep them alive + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(Callsign, Ip, PROTOCOL_DCS, it)) != nullptr ) + { + client->Alive(); + } + g_Reflector.ReleaseClients(); + } + else if ( IsIgnorePacket(Buffer) ) + { + // valid but ignore packet + //std::cout << "DCS ignored packet from " << Ip << std::endl; + } + else + { + // invalid packet + std::cout << "DCS packet (" << Buffer.size() << ") from " << Ip << std::endl; + } + } + + // handle end of streaming timeout + CheckStreamsTimeout(); + + // handle queue from reflector + HandleQueue(); + + // keep client alive + if ( m_LastKeepaliveTime.DurationSinceNow() > DCS_KEEPALIVE_PERIOD ) + { + // + HandleKeepalives(); + + // update time + m_LastKeepaliveTime.Now(); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -199,53 +199,53 @@ void CDcsProtocol::Task(void) bool CDcsProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip) { - bool newstream = false; - - // find the stream - CPacketStream *stream = GetStream(Header->GetStreamId()); - if ( stream == nullptr ) - { - // no stream open yet, open a new one - CCallsign via(Header->GetRpt1Callsign()); - - // find this client - std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_DCS); - if ( client != nullptr ) - { - // get client callsign - via = client->GetCallsign(); - // and try to open the stream - if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) - { - // keep the handle - m_Streams.push_back(stream); - newstream = true; - } - } - // release - g_Reflector.ReleaseClients(); - - // update last heard - g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), via, Header->GetRpt2Callsign()); - g_Reflector.ReleaseUsers(); - - // delete header if needed - if ( !newstream ) - { - delete Header; - } - } - else - { - // stream already open - // skip packet, but tickle the stream - stream->Tickle(); - // and delete packet - delete Header; - } - - // done - return newstream; + bool newstream = false; + + // find the stream + CPacketStream *stream = GetStream(Header->GetStreamId()); + if ( stream == nullptr ) + { + // no stream open yet, open a new one + CCallsign via(Header->GetRpt1Callsign()); + + // find this client + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_DCS); + if ( client != nullptr ) + { + // get client callsign + via = client->GetCallsign(); + // and try to open the stream + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) + { + // keep the handle + m_Streams.push_back(stream); + newstream = true; + } + } + // release + g_Reflector.ReleaseClients(); + + // update last heard + g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), via, Header->GetRpt2Callsign()); + g_Reflector.ReleaseUsers(); + + // delete header if needed + if ( !newstream ) + { + delete Header; + } + } + else + { + // stream already open + // skip packet, but tickle the stream + stream->Tickle(); + // and delete packet + delete Header; + } + + // done + return newstream; } //////////////////////////////////////////////////////////////////////////////////////// @@ -253,69 +253,69 @@ bool CDcsProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip) void CDcsProtocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) - { - // get the packet - CPacket *packet = m_Queue.front(); - m_Queue.pop(); - - // get our sender's id - int iModId = g_Reflector.GetModuleIndex(packet->GetModuleId()); - - // check if it's header and update cache - if ( packet->IsDvHeader() ) - { - // this relies on queue feeder setting valid module id - m_StreamsCache[iModId].m_dvHeader = CDvHeaderPacket((const CDvHeaderPacket &)*packet); - m_StreamsCache[iModId].m_iSeqCounter = 0; - } - else - { - // encode it - CBuffer buffer; - if ( packet->IsLastPacket() ) - { - EncodeDvLastPacket( - m_StreamsCache[iModId].m_dvHeader, - (const CDvFramePacket &)*packet, - m_StreamsCache[iModId].m_iSeqCounter++, - &buffer); - } - else if ( packet->IsDvFrame() ) - { - EncodeDvPacket( - m_StreamsCache[iModId].m_dvHeader, - (const CDvFramePacket &)*packet, - m_StreamsCache[iModId].m_iSeqCounter++, - &buffer); - } - - // send it - if ( buffer.size() > 0 ) - { - // and push it to all our clients linked to the module and who are not streaming in - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_DCS, it)) != nullptr ) - { - // is this client busy ? - if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) ) - { - // no, send the packet - Send(buffer, client->GetIp()); - - } - } - g_Reflector.ReleaseClients(); - } - } - - // done - delete packet; - } - m_Queue.Unlock(); + m_Queue.Lock(); + while ( !m_Queue.empty() ) + { + // get the packet + CPacket *packet = m_Queue.front(); + m_Queue.pop(); + + // get our sender's id + int iModId = g_Reflector.GetModuleIndex(packet->GetModuleId()); + + // check if it's header and update cache + if ( packet->IsDvHeader() ) + { + // this relies on queue feeder setting valid module id + m_StreamsCache[iModId].m_dvHeader = CDvHeaderPacket((const CDvHeaderPacket &)*packet); + m_StreamsCache[iModId].m_iSeqCounter = 0; + } + else + { + // encode it + CBuffer buffer; + if ( packet->IsLastPacket() ) + { + EncodeDvLastPacket( + m_StreamsCache[iModId].m_dvHeader, + (const CDvFramePacket &)*packet, + m_StreamsCache[iModId].m_iSeqCounter++, + &buffer); + } + else if ( packet->IsDvFrame() ) + { + EncodeDvPacket( + m_StreamsCache[iModId].m_dvHeader, + (const CDvFramePacket &)*packet, + m_StreamsCache[iModId].m_iSeqCounter++, + &buffer); + } + + // send it + if ( buffer.size() > 0 ) + { + // and push it to all our clients linked to the module and who are not streaming in + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_DCS, it)) != nullptr ) + { + // is this client busy ? + if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) ) + { + // no, send the packet + Send(buffer, client->GetIp()); + + } + } + g_Reflector.ReleaseClients(); + } + } + + // done + delete packet; + } + m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -323,47 +323,47 @@ void CDcsProtocol::HandleQueue(void) void CDcsProtocol::HandleKeepalives(void) { - // DCS protocol sends and monitors keepalives packets - // event if the client is currently streaming - // so, send keepalives to all - CBuffer keepalive1; - EncodeKeepAlivePacket(&keepalive1); - - // iterate on clients - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_DCS, it)) != nullptr ) - { - // encode client's specific keepalive packet - CBuffer keepalive2; - EncodeKeepAlivePacket(&keepalive2, client); - - // send keepalive - Send(keepalive1, client->GetIp()); - Send(keepalive2, client->GetIp()); - - // is this client busy ? - if ( client->IsAMaster() ) - { - // yes, just tickle it - client->Alive(); - } - // check it's still with us - else if ( !client->IsAlive() ) - { - // no, disconnect - CBuffer disconnect; - EncodeDisconnectPacket(&disconnect, client); - Send(disconnect, client->GetIp()); - - // remove it - std::cout << "DCS client " << client->GetCallsign() << " keepalive timeout" << std::endl; - clients->RemoveClient(client); - } - - } - g_Reflector.ReleaseClients(); + // DCS protocol sends and monitors keepalives packets + // event if the client is currently streaming + // so, send keepalives to all + CBuffer keepalive1; + EncodeKeepAlivePacket(&keepalive1); + + // iterate on clients + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_DCS, it)) != nullptr ) + { + // encode client's specific keepalive packet + CBuffer keepalive2; + EncodeKeepAlivePacket(&keepalive2, client); + + // send keepalive + Send(keepalive1, client->GetIp()); + Send(keepalive2, client->GetIp()); + + // is this client busy ? + if ( client->IsAMaster() ) + { + // yes, just tickle it + client->Alive(); + } + // check it's still with us + else if ( !client->IsAlive() ) + { + // no, disconnect + CBuffer disconnect; + EncodeDisconnectPacket(&disconnect, client); + Send(disconnect, client->GetIp()); + + // remove it + std::cout << "DCS client " << client->GetCallsign() << " keepalive timeout" << std::endl; + clients->RemoveClient(client); + } + + } + g_Reflector.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -371,98 +371,98 @@ void CDcsProtocol::HandleKeepalives(void) bool CDcsProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsign, char *reflectormodule) { - bool valid = false; - if ( Buffer.size() == 519 ) - { - callsign->SetCallsign(Buffer.data(), 8); - callsign->SetModule(Buffer.data()[8]); - *reflectormodule = Buffer.data()[9]; - valid = (callsign->IsValid() && IsLetter(*reflectormodule)); - } - return valid; + bool valid = false; + if ( Buffer.size() == 519 ) + { + callsign->SetCallsign(Buffer.data(), 8); + callsign->SetModule(Buffer.data()[8]); + *reflectormodule = Buffer.data()[9]; + valid = (callsign->IsValid() && IsLetter(*reflectormodule)); + } + return valid; } bool CDcsProtocol::IsValidDisconnectPacket(const CBuffer &Buffer, CCallsign *callsign) { - bool valid = false; - if ((Buffer.size() == 11) && (Buffer.data()[9] == ' ')) - { - callsign->SetCallsign(Buffer.data(), 8); - callsign->SetModule(Buffer.data()[8]); - valid = callsign->IsValid(); - } - else if ((Buffer.size() == 19) && (Buffer.data()[9] == ' ') && (Buffer.data()[10] == 0x00)) - { - callsign->SetCallsign(Buffer.data(), 8); - callsign->SetModule(Buffer.data()[8]); - valid = callsign->IsValid(); - } - return valid; + bool valid = false; + if ((Buffer.size() == 11) && (Buffer.data()[9] == ' ')) + { + callsign->SetCallsign(Buffer.data(), 8); + callsign->SetModule(Buffer.data()[8]); + valid = callsign->IsValid(); + } + else if ((Buffer.size() == 19) && (Buffer.data()[9] == ' ') && (Buffer.data()[10] == 0x00)) + { + callsign->SetCallsign(Buffer.data(), 8); + callsign->SetModule(Buffer.data()[8]); + valid = callsign->IsValid(); + } + return valid; } bool CDcsProtocol::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *callsign) { - bool valid = false; - if ( (Buffer.size() == 17) || (Buffer.size() == 15) || (Buffer.size() == 22) ) - { - callsign->SetCallsign(Buffer.data(), 8); - valid = callsign->IsValid(); - } - return valid; + bool valid = false; + if ( (Buffer.size() == 17) || (Buffer.size() == 15) || (Buffer.size() == 22) ) + { + callsign->SetCallsign(Buffer.data(), 8); + valid = callsign->IsValid(); + } + return valid; } bool CDcsProtocol::IsValidDvPacket(const CBuffer &Buffer, CDvHeaderPacket **header, CDvFramePacket **frame) { - uint8 tag[] = { '0','0','0','1' }; - - bool valid = false; - *header = nullptr; - *frame = nullptr; - - if ( (Buffer.size() >= 100) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - // get the header - *header = new CDvHeaderPacket((struct dstar_header *)&(Buffer.data()[4]), *((uint16 *)&(Buffer.data()[43])), 0x80); - - // get the frame - if ( ((Buffer.data()[45]) & 0x40) != 0 ) - { - // it's the last frame - *frame = new CDvLastFramePacket((struct dstar_dvframe *)&(Buffer.data()[46]), *((uint16 *)&(Buffer.data()[43])), Buffer.data()[45]); - } - else - { - // it's a regular DV frame - *frame = new CDvFramePacket((struct dstar_dvframe *)&(Buffer.data()[46]), *((uint16 *)&(Buffer.data()[43])), Buffer.data()[45]); - } - - // check validity of packets - if ( !((*header)->IsValid() && (*frame)->IsValid()) ) - { - delete *header; - delete *frame; - *header = nullptr; - *frame = nullptr; - } - else - { - valid = true; - } - } - // done - return valid; + uint8 tag[] = { '0','0','0','1' }; + + bool valid = false; + *header = nullptr; + *frame = nullptr; + + if ( (Buffer.size() >= 100) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + // get the header + *header = new CDvHeaderPacket((struct dstar_header *)&(Buffer.data()[4]), *((uint16 *)&(Buffer.data()[43])), 0x80); + + // get the frame + if ( ((Buffer.data()[45]) & 0x40) != 0 ) + { + // it's the last frame + *frame = new CDvLastFramePacket((struct dstar_dvframe *)&(Buffer.data()[46]), *((uint16 *)&(Buffer.data()[43])), Buffer.data()[45]); + } + else + { + // it's a regular DV frame + *frame = new CDvFramePacket((struct dstar_dvframe *)&(Buffer.data()[46]), *((uint16 *)&(Buffer.data()[43])), Buffer.data()[45]); + } + + // check validity of packets + if ( !((*header)->IsValid() && (*frame)->IsValid()) ) + { + delete *header; + delete *frame; + *header = nullptr; + *frame = nullptr; + } + else + { + valid = true; + } + } + // done + return valid; } bool CDcsProtocol::IsIgnorePacket(const CBuffer &Buffer) { - bool valid = false; - uint8 tag[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; - - if ( Buffer.size() == 15 ) - { - valid = (Buffer.Compare(tag, sizeof(tag)) == 0); - } - return valid; + bool valid = false; + uint8 tag[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; + + if ( Buffer.size() == 15 ) + { + valid = (Buffer.Compare(tag, sizeof(tag)) == 0); + } + return valid; } @@ -471,81 +471,81 @@ bool CDcsProtocol::IsIgnorePacket(const CBuffer &Buffer) void CDcsProtocol::EncodeKeepAlivePacket(CBuffer *Buffer) { - Buffer->Set(GetReflectorCallsign()); + Buffer->Set(GetReflectorCallsign()); } void CDcsProtocol::EncodeKeepAlivePacket(CBuffer *Buffer, std::shared_ptrClient) { - uint8 tag[] = { 0x0A,0x00,0x20,0x20 }; - - Buffer->Set((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN-1); - Buffer->Append((uint8)Client->GetReflectorModule()); - Buffer->Append((uint8)' '); - Buffer->Append((uint8 *)(const char *)Client->GetCallsign(), CALLSIGN_LEN-1); - Buffer->Append((uint8)Client->GetModule()); - Buffer->Append((uint8)Client->GetModule()); - Buffer->Append(tag, sizeof(tag)); + uint8 tag[] = { 0x0A,0x00,0x20,0x20 }; + + Buffer->Set((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN-1); + Buffer->Append((uint8)Client->GetReflectorModule()); + Buffer->Append((uint8)' '); + Buffer->Append((uint8 *)(const char *)Client->GetCallsign(), CALLSIGN_LEN-1); + Buffer->Append((uint8)Client->GetModule()); + Buffer->Append((uint8)Client->GetModule()); + Buffer->Append(tag, sizeof(tag)); } void CDcsProtocol::EncodeConnectAckPacket(const CCallsign &Callsign, char ReflectorModule, CBuffer *Buffer) { - uint8 tag[] = { 'A','C','K',0x00 }; - uint8 cs[CALLSIGN_LEN]; - - Callsign.GetCallsign(cs); - Buffer->Set(cs, CALLSIGN_LEN-1); - Buffer->Append((uint8)' '); - Buffer->Append((uint8)Callsign.GetModule()); - Buffer->Append((uint8)ReflectorModule); - Buffer->Append(tag, sizeof(tag)); + uint8 tag[] = { 'A','C','K',0x00 }; + uint8 cs[CALLSIGN_LEN]; + + Callsign.GetCallsign(cs); + Buffer->Set(cs, CALLSIGN_LEN-1); + Buffer->Append((uint8)' '); + Buffer->Append((uint8)Callsign.GetModule()); + Buffer->Append((uint8)ReflectorModule); + Buffer->Append(tag, sizeof(tag)); } void CDcsProtocol::EncodeConnectNackPacket(const CCallsign &Callsign, char ReflectorModule, CBuffer *Buffer) { - uint8 tag[] = { 'N','A','K',0x00 }; - uint8 cs[CALLSIGN_LEN]; - - Callsign.GetCallsign(cs); - Buffer->Set(cs, CALLSIGN_LEN-1); - Buffer->Append((uint8)' '); - Buffer->Append((uint8)Callsign.GetModule()); - Buffer->Append((uint8)ReflectorModule); - Buffer->Append(tag, sizeof(tag)); + uint8 tag[] = { 'N','A','K',0x00 }; + uint8 cs[CALLSIGN_LEN]; + + Callsign.GetCallsign(cs); + Buffer->Set(cs, CALLSIGN_LEN-1); + Buffer->Append((uint8)' '); + Buffer->Append((uint8)Callsign.GetModule()); + Buffer->Append((uint8)ReflectorModule); + Buffer->Append(tag, sizeof(tag)); } void CDcsProtocol::EncodeDisconnectPacket(CBuffer *Buffer, std::shared_ptrClient) { - Buffer->Set((uint8 *)(const char *)Client->GetCallsign(), CALLSIGN_LEN-1); - Buffer->Append((uint8)' '); - Buffer->Append((uint8)Client->GetModule()); - Buffer->Append((uint8)0x00); - Buffer->Append((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN-1); - Buffer->Append((uint8)' '); - Buffer->Append((uint8)0x00); + Buffer->Set((uint8 *)(const char *)Client->GetCallsign(), CALLSIGN_LEN-1); + Buffer->Append((uint8)' '); + Buffer->Append((uint8)Client->GetModule()); + Buffer->Append((uint8)0x00); + Buffer->Append((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN-1); + Buffer->Append((uint8)' '); + Buffer->Append((uint8)0x00); } void CDcsProtocol::EncodeDvPacket(const CDvHeaderPacket &Header, const CDvFramePacket &DvFrame, uint32 iSeq, CBuffer *Buffer) const { - uint8 tag[] = { '0','0','0','1' }; - struct dstar_header DstarHeader; - - Header.ConvertToDstarStruct(&DstarHeader); - - Buffer->Set(tag, sizeof(tag)); - Buffer->Append((uint8 *)&DstarHeader, sizeof(struct dstar_header) - sizeof(uint16)); - Buffer->Append(DvFrame.GetStreamId()); - Buffer->Append((uint8)(DvFrame.GetPacketId() % 21)); - Buffer->Append((uint8 *)DvFrame.GetAmbe(), AMBE_SIZE); - Buffer->Append((uint8 *)DvFrame.GetDvData(), DVDATA_SIZE); - Buffer->Append((uint8)((iSeq >> 0) & 0xFF)); - Buffer->Append((uint8)((iSeq >> 8) & 0xFF)); - Buffer->Append((uint8)((iSeq >> 16) & 0xFF)); - Buffer->Append((uint8)0x01); - Buffer->Append((uint8)0x00, 38); + uint8 tag[] = { '0','0','0','1' }; + struct dstar_header DstarHeader; + + Header.ConvertToDstarStruct(&DstarHeader); + + Buffer->Set(tag, sizeof(tag)); + Buffer->Append((uint8 *)&DstarHeader, sizeof(struct dstar_header) - sizeof(uint16)); + Buffer->Append(DvFrame.GetStreamId()); + Buffer->Append((uint8)(DvFrame.GetPacketId() % 21)); + Buffer->Append((uint8 *)DvFrame.GetAmbe(), AMBE_SIZE); + Buffer->Append((uint8 *)DvFrame.GetDvData(), DVDATA_SIZE); + Buffer->Append((uint8)((iSeq >> 0) & 0xFF)); + Buffer->Append((uint8)((iSeq >> 8) & 0xFF)); + Buffer->Append((uint8)((iSeq >> 16) & 0xFF)); + Buffer->Append((uint8)0x01); + Buffer->Append((uint8)0x00, 38); } void CDcsProtocol::EncodeDvLastPacket(const CDvHeaderPacket &Header, const CDvFramePacket &DvFrame, uint32 iSeq, CBuffer *Buffer) const { - EncodeDvPacket(Header, DvFrame, iSeq, Buffer); - (Buffer->data())[45] |= 0x40; + EncodeDvPacket(Header, DvFrame, iSeq, Buffer); + (Buffer->data())[45] |= 0x40; } diff --git a/src/cdcsprotocol.h b/src/cdcsprotocol.h index 3791fcd..0bddece 100644 --- a/src/cdcsprotocol.h +++ b/src/cdcsprotocol.h @@ -40,54 +40,54 @@ class CDcsStreamCacheItem { public: - CDcsStreamCacheItem() { m_iSeqCounter = 0; } - ~CDcsStreamCacheItem() {} + CDcsStreamCacheItem() { m_iSeqCounter = 0; } + ~CDcsStreamCacheItem() {} - CDvHeaderPacket m_dvHeader; - uint32 m_iSeqCounter; + CDvHeaderPacket m_dvHeader; + uint32 m_iSeqCounter; }; class CDcsProtocol : public CProtocol { public: - // initialization - bool Init(void); + // initialization + bool Init(void); - // task - void Task(void); + // task + void Task(void); protected: - // queue helper - void HandleQueue(void); - - // keepalive helpers - void HandleKeepalives(void); - - // stream helpers - bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); - - // packet decoding helpers - bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *); - bool IsValidDisconnectPacket(const CBuffer &, CCallsign *); - bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); - bool IsValidDvPacket(const CBuffer &, CDvHeaderPacket **, CDvFramePacket **); - bool IsIgnorePacket(const CBuffer &); - - // packet encoding helpers - void EncodeKeepAlivePacket(CBuffer *); - void EncodeKeepAlivePacket(CBuffer *, std::shared_ptr); - void EncodeConnectAckPacket(const CCallsign &, char, CBuffer *); - void EncodeConnectNackPacket(const CCallsign &, char, CBuffer *); - void EncodeDisconnectPacket(CBuffer *, std::shared_ptr); - void EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket &, uint32, CBuffer *) const; - void EncodeDvLastPacket(const CDvHeaderPacket &, const CDvFramePacket &, uint32, CBuffer *) const; + // queue helper + void HandleQueue(void); + + // keepalive helpers + void HandleKeepalives(void); + + // stream helpers + bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); + + // packet decoding helpers + bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *); + bool IsValidDisconnectPacket(const CBuffer &, CCallsign *); + bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); + bool IsValidDvPacket(const CBuffer &, CDvHeaderPacket **, CDvFramePacket **); + bool IsIgnorePacket(const CBuffer &); + + // packet encoding helpers + void EncodeKeepAlivePacket(CBuffer *); + void EncodeKeepAlivePacket(CBuffer *, std::shared_ptr); + void EncodeConnectAckPacket(const CCallsign &, char, CBuffer *); + void EncodeConnectNackPacket(const CCallsign &, char, CBuffer *); + void EncodeDisconnectPacket(CBuffer *, std::shared_ptr); + void EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket &, uint32, CBuffer *) const; + void EncodeDvLastPacket(const CDvHeaderPacket &, const CDvFramePacket &, uint32, CBuffer *) const; protected: - // for keep alive - CTimePoint m_LastKeepaliveTime; + // for keep alive + CTimePoint m_LastKeepaliveTime; - // for queue header caches - std::array m_StreamsCache; + // for queue header caches + std::array m_StreamsCache; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cdextraclient.cpp b/src/cdextraclient.cpp index 6d8a67a..b64ce29 100644 --- a/src/cdextraclient.cpp +++ b/src/cdextraclient.cpp @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- #include "main.h" @@ -31,19 +31,19 @@ CDextraClient::CDextraClient() { - m_ProtRev = 0; + m_ProtRev = 0; } CDextraClient::CDextraClient(const CCallsign &callsign, const CIp &ip, char reflectorModule, int protRev) - : CClient(callsign, ip, reflectorModule) + : CClient(callsign, ip, reflectorModule) { - m_ProtRev = protRev; + m_ProtRev = protRev; } CDextraClient::CDextraClient(const CDextraClient &client) - : CClient(client) + : CClient(client) { - m_ProtRev = client.m_ProtRev; + m_ProtRev = client.m_ProtRev; } //////////////////////////////////////////////////////////////////////////////////////// @@ -51,6 +51,6 @@ CDextraClient::CDextraClient(const CDextraClient &client) bool CDextraClient::IsAlive(void) const { - return (m_LastKeepaliveTime.DurationSinceNow() < DEXTRA_KEEPALIVE_TIMEOUT); + return (m_LastKeepaliveTime.DurationSinceNow() < DEXTRA_KEEPALIVE_TIMEOUT); } diff --git a/src/cdextraclient.h b/src/cdextraclient.h index 453c5f4..27bf0e9 100644 --- a/src/cdextraclient.h +++ b/src/cdextraclient.h @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- #ifndef cdextraclient_h @@ -37,27 +37,27 @@ class CDextraClient : public CClient { public: - // constructors - CDextraClient(); - CDextraClient(const CCallsign &, const CIp &, char = ' ', int = 0); - CDextraClient(const CDextraClient &); - - // destructor - virtual ~CDextraClient() {}; - - // identity - int GetProtocol(void) const { return PROTOCOL_DEXTRA; } - int GetProtocolRevision(void) const { return m_ProtRev; } - const char *GetProtocolName(void) const { return "DExtra"; } - int GetCodec(void) const { return CODEC_AMBEPLUS; } - bool IsNode(void) const { return true; } - - // status - bool IsAlive(void) const; + // constructors + CDextraClient(); + CDextraClient(const CCallsign &, const CIp &, char = ' ', int = 0); + CDextraClient(const CDextraClient &); + + // destructor + virtual ~CDextraClient() {}; + + // identity + int GetProtocol(void) const { return PROTOCOL_DEXTRA; } + int GetProtocolRevision(void) const { return m_ProtRev; } + const char *GetProtocolName(void) const { return "DExtra"; } + int GetCodec(void) const { return CODEC_AMBEPLUS; } + bool IsNode(void) const { return true; } + + // status + bool IsAlive(void) const; protected: - // data - int m_ProtRev; + // data + int m_ProtRev; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cdextrapeer.cpp b/src/cdextrapeer.cpp index 4631357..00612f3 100644 --- a/src/cdextrapeer.cpp +++ b/src/cdextrapeer.cpp @@ -39,16 +39,16 @@ CDextraPeer::CDextraPeer() } CDextraPeer::CDextraPeer(const CCallsign &callsign, const CIp &ip, const char *modules, const CVersion &version) -: CPeer(callsign, ip, modules, version) + : CPeer(callsign, ip, modules, version) { - std::cout << "Adding DExtra peer" << std::endl; + std::cout << "Adding DExtra peer" << std::endl; - // and construct the DExtra clients - for ( unsigned i = 0; i < ::strlen(modules); i++ ) - { - // create and append to vector - m_Clients.push_back(std::make_shared(callsign, ip, modules[i], version.GetMajor())); - } + // and construct the DExtra clients + for ( unsigned i = 0; i < ::strlen(modules); i++ ) + { + // create and append to vector + m_Clients.push_back(std::make_shared(callsign, ip, modules[i], version.GetMajor())); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -56,12 +56,12 @@ CDextraPeer::CDextraPeer(const CCallsign &callsign, const CIp &ip, const char *m bool CDextraPeer::IsAlive(void) const { - for ( auto it=cbegin(); it!=cend(); it++ ) - { - if (! (*it)->IsAlive()) + for ( auto it=cbegin(); it!=cend(); it++ ) + { + if (! (*it)->IsAlive()) return false; - } - return true; + } + return true; } //////////////////////////////////////////////////////////////////////////////////////// @@ -69,5 +69,5 @@ bool CDextraPeer::IsAlive(void) const int CDextraPeer::GetProtocolRevision(const CVersion &version) { - return version.GetMajor(); + return version.GetMajor(); } diff --git a/src/cdextrapeer.h b/src/cdextrapeer.h index ecf0ce4..f94a451 100644 --- a/src/cdextrapeer.h +++ b/src/cdextrapeer.h @@ -38,20 +38,20 @@ class CDextraPeer : public CPeer { public: - // constructors - CDextraPeer(); - CDextraPeer(const CCallsign &, const CIp &, const char *, const CVersion &); - CDextraPeer(const CDextraPeer &) = delete; + // constructors + CDextraPeer(); + CDextraPeer(const CCallsign &, const CIp &, const char *, const CVersion &); + CDextraPeer(const CDextraPeer &) = delete; - // status - bool IsAlive(void) const; + // status + bool IsAlive(void) const; - // identity - int GetProtocol(void) const { return PROTOCOL_DEXTRA; } - const char *GetProtocolName(void) const { return "DExtra"; } + // identity + int GetProtocol(void) const { return PROTOCOL_DEXTRA; } + const char *GetProtocolName(void) const { return "DExtra"; } - // revision helper - static int GetProtocolRevision(const CVersion &); + // revision helper + static int GetProtocolRevision(const CVersion &); }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cdextraprotocol.cpp b/src/cdextraprotocol.cpp index 93e6507..36ebdc2 100644 --- a/src/cdextraprotocol.cpp +++ b/src/cdextraprotocol.cpp @@ -37,16 +37,16 @@ bool CDextraProtocol::Initialize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6) { - // base class - if (! CProtocol::Initialize(type, port, has_ipv4, has_ipv6)) + // base class + if (! CProtocol::Initialize(type, port, has_ipv4, has_ipv6)) return false; - // update time - m_LastKeepaliveTime.Now(); - m_LastPeersLinkTime.Now(); + // update time + m_LastKeepaliveTime.Now(); + m_LastPeersLinkTime.Now(); - // done - return true; + // done + return true; } //////////////////////////////////////////////////////////////////////////////////////// @@ -54,16 +54,16 @@ bool CDextraProtocol::Initialize(const char *type, const uint16 port, const bool void CDextraProtocol::Task(void) { - CBuffer Buffer; - CIp Ip; - CCallsign Callsign; - char ToLinkModule; - int ProtRev; - CDvHeaderPacket *Header; - CDvFramePacket *Frame; - CDvLastFramePacket *LastFrame; - - // any incoming packet ? + CBuffer Buffer; + CIp Ip; + CCallsign Callsign; + char ToLinkModule; + int ProtRev; + CDvHeaderPacket *Header; + CDvFramePacket *Frame; + CDvLastFramePacket *LastFrame; + + // any incoming packet ? #if DSTAR_IPV6==true #if DSTAR_IPV4==true if ( ReceiveDS(Buffer, Ip, 20) ) @@ -73,165 +73,165 @@ void CDextraProtocol::Task(void) #else if ( Receive4(Buffer, Ip, 20) ) #endif - { - // crack the packet - if ( (Frame = IsValidDvFramePacket(Buffer)) != nullptr ) - { - //std::cout << "DExtra DV frame" << std::endl; - - // handle it - OnDvFramePacketIn(Frame, &Ip); - } - else if ( (Header = IsValidDvHeaderPacket(Buffer)) != nullptr ) - { - //std::cout << "DExtra DV header:" << std::endl << *Header << std::endl; - //std::cout << "DExtra DV header:" << std::endl; - - // callsign muted? - if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_DEXTRA, Header->GetRpt2Module()) ) - { - // handle it - OnDvHeaderPacketIn(Header, Ip); - } - else - { - delete Header; - } - } - else if ( (LastFrame = IsValidDvLastFramePacket(Buffer)) != nullptr ) - { - //std::cout << "DExtra DV last frame" << std::endl; - - // handle it - OnDvLastFramePacketIn(LastFrame, &Ip); - } - else if ( IsValidConnectPacket(Buffer, &Callsign, &ToLinkModule, &ProtRev) ) - { - std::cout << "DExtra connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << " rev " << ProtRev << std::endl; - - // callsign authorized? - if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_DEXTRA) ) - { - // valid module ? - if ( g_Reflector.IsValidModule(ToLinkModule) ) - { - // is this an ack for a link request? - CPeerCallsignList *list = g_GateKeeper.GetPeerList(); - CCallsignListItem *item = list->FindListItem(Callsign); - if ( item != nullptr && Callsign.GetModule() == item->GetModules()[1] && ToLinkModule == item->GetModules()[0] ) - { - std::cout << "DExtra ack packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl; - - // already connected ? - CPeers *peers = g_Reflector.GetPeers(); - if ( peers->FindPeer(Callsign, Ip, PROTOCOL_DEXTRA) == nullptr ) - { - // create the new peer - // this also create one client per module - // append the peer to reflector peer list - // this also add all new clients to reflector client list - peers->AddPeer(std::make_shared(Callsign, Ip, std::string(1, ToLinkModule).c_str(), CVersion(2, 0, 0))); - } - g_Reflector.ReleasePeers(); - } - else - { - // acknowledge the request - EncodeConnectAckPacket(&Buffer, ProtRev); - Send(Buffer, Ip); - - // create the client and append - g_Reflector.GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule, ProtRev)); - g_Reflector.ReleaseClients(); - } - g_GateKeeper.ReleasePeerList(); - } - else - { - std::cout << "DExtra node " << Callsign << " connect attempt on non-existing module" << std::endl; - - // deny the request - EncodeConnectNackPacket(&Buffer); - Send(Buffer, Ip); - } - } - else - { - // deny the request - EncodeConnectNackPacket(&Buffer); - Send(Buffer, Ip); - } - } - else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) - { - std::cout << "DExtra disconnect packet from " << Callsign << " at " << Ip << std::endl; - - // find client & remove it - CClients *clients = g_Reflector.GetClients(); - std::shared_ptrclient = clients->FindClient(Ip, PROTOCOL_DEXTRA); - if ( client != nullptr ) - { - // ack disconnect packet - if ( client->GetProtocolRevision() == 1 ) - { - EncodeDisconnectedPacket(&Buffer); - Send(Buffer, Ip); - } - else if ( client->GetProtocolRevision() == 2 ) - { - Send(Buffer, Ip); - } - // and remove it - clients->RemoveClient(client); - } - g_Reflector.ReleaseClients(); - } - else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) - { - //std::cout << "DExtra keepalive packet from " << Callsign << " at " << Ip << std::endl; - - // find all clients with that callsign & ip and keep them alive - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(Callsign, Ip, PROTOCOL_DEXTRA, it)) != nullptr ) - { - client->Alive(); - } - g_Reflector.ReleaseClients(); - } - else - { - std::cout << "DExtra packet (" << Buffer.size() << ")" << std::endl; - //std::cout << Buffer.data() << std::endl; - } - } - - // handle end of streaming timeout - CheckStreamsTimeout(); - - // handle queue from reflector - HandleQueue(); - - // keep alive - if ( m_LastKeepaliveTime.DurationSinceNow() > DEXTRA_KEEPALIVE_PERIOD ) - { - // handle keep alives - HandleKeepalives(); - - // update time - m_LastKeepaliveTime.Now(); - } - - // peer connections - if ( m_LastPeersLinkTime.DurationSinceNow() > DEXTRA_RECONNECT_PERIOD ) - { - // handle remote peers connections - HandlePeerLinks(); - - // update time - m_LastPeersLinkTime.Now(); - } + { + // crack the packet + if ( (Frame = IsValidDvFramePacket(Buffer)) != nullptr ) + { + //std::cout << "DExtra DV frame" << std::endl; + + // handle it + OnDvFramePacketIn(Frame, &Ip); + } + else if ( (Header = IsValidDvHeaderPacket(Buffer)) != nullptr ) + { + //std::cout << "DExtra DV header:" << std::endl << *Header << std::endl; + //std::cout << "DExtra DV header:" << std::endl; + + // callsign muted? + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_DEXTRA, Header->GetRpt2Module()) ) + { + // handle it + OnDvHeaderPacketIn(Header, Ip); + } + else + { + delete Header; + } + } + else if ( (LastFrame = IsValidDvLastFramePacket(Buffer)) != nullptr ) + { + //std::cout << "DExtra DV last frame" << std::endl; + + // handle it + OnDvLastFramePacketIn(LastFrame, &Ip); + } + else if ( IsValidConnectPacket(Buffer, &Callsign, &ToLinkModule, &ProtRev) ) + { + std::cout << "DExtra connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << " rev " << ProtRev << std::endl; + + // callsign authorized? + if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_DEXTRA) ) + { + // valid module ? + if ( g_Reflector.IsValidModule(ToLinkModule) ) + { + // is this an ack for a link request? + CPeerCallsignList *list = g_GateKeeper.GetPeerList(); + CCallsignListItem *item = list->FindListItem(Callsign); + if ( item != nullptr && Callsign.GetModule() == item->GetModules()[1] && ToLinkModule == item->GetModules()[0] ) + { + std::cout << "DExtra ack packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl; + + // already connected ? + CPeers *peers = g_Reflector.GetPeers(); + if ( peers->FindPeer(Callsign, Ip, PROTOCOL_DEXTRA) == nullptr ) + { + // create the new peer + // this also create one client per module + // append the peer to reflector peer list + // this also add all new clients to reflector client list + peers->AddPeer(std::make_shared(Callsign, Ip, std::string(1, ToLinkModule).c_str(), CVersion(2, 0, 0))); + } + g_Reflector.ReleasePeers(); + } + else + { + // acknowledge the request + EncodeConnectAckPacket(&Buffer, ProtRev); + Send(Buffer, Ip); + + // create the client and append + g_Reflector.GetClients()->AddClient(std::make_shared(Callsign, Ip, ToLinkModule, ProtRev)); + g_Reflector.ReleaseClients(); + } + g_GateKeeper.ReleasePeerList(); + } + else + { + std::cout << "DExtra node " << Callsign << " connect attempt on non-existing module" << std::endl; + + // deny the request + EncodeConnectNackPacket(&Buffer); + Send(Buffer, Ip); + } + } + else + { + // deny the request + EncodeConnectNackPacket(&Buffer); + Send(Buffer, Ip); + } + } + else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) + { + std::cout << "DExtra disconnect packet from " << Callsign << " at " << Ip << std::endl; + + // find client & remove it + CClients *clients = g_Reflector.GetClients(); + std::shared_ptrclient = clients->FindClient(Ip, PROTOCOL_DEXTRA); + if ( client != nullptr ) + { + // ack disconnect packet + if ( client->GetProtocolRevision() == 1 ) + { + EncodeDisconnectedPacket(&Buffer); + Send(Buffer, Ip); + } + else if ( client->GetProtocolRevision() == 2 ) + { + Send(Buffer, Ip); + } + // and remove it + clients->RemoveClient(client); + } + g_Reflector.ReleaseClients(); + } + else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) + { + //std::cout << "DExtra keepalive packet from " << Callsign << " at " << Ip << std::endl; + + // find all clients with that callsign & ip and keep them alive + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(Callsign, Ip, PROTOCOL_DEXTRA, it)) != nullptr ) + { + client->Alive(); + } + g_Reflector.ReleaseClients(); + } + else + { + std::cout << "DExtra packet (" << Buffer.size() << ")" << std::endl; + //std::cout << Buffer.data() << std::endl; + } + } + + // handle end of streaming timeout + CheckStreamsTimeout(); + + // handle queue from reflector + HandleQueue(); + + // keep alive + if ( m_LastKeepaliveTime.DurationSinceNow() > DEXTRA_KEEPALIVE_PERIOD ) + { + // handle keep alives + HandleKeepalives(); + + // update time + m_LastKeepaliveTime.Now(); + } + + // peer connections + if ( m_LastPeersLinkTime.DurationSinceNow() > DEXTRA_RECONNECT_PERIOD ) + { + // handle remote peers connections + HandlePeerLinks(); + + // update time + m_LastPeersLinkTime.Now(); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -239,42 +239,42 @@ void CDextraProtocol::Task(void) void CDextraProtocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) - { - // get the packet - CPacket *packet = m_Queue.front(); - m_Queue.pop(); - - // encode it - CBuffer buffer; - if ( EncodeDvPacket(*packet, &buffer) ) - { - // and push it to all our clients linked to the module and who are not streaming in - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_DEXTRA, it)) != nullptr ) - { - // is this client busy ? - if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) ) - { - // no, send the packet - int n = packet->IsDvHeader() ? 5 : 1; - for ( int i = 0; i < n; i++ ) - { - Send(buffer, client->GetIp()); - } - } - } - g_Reflector.ReleaseClients(); - } - - - // done - delete packet; - } - m_Queue.Unlock(); + m_Queue.Lock(); + while ( !m_Queue.empty() ) + { + // get the packet + CPacket *packet = m_Queue.front(); + m_Queue.pop(); + + // encode it + CBuffer buffer; + if ( EncodeDvPacket(*packet, &buffer) ) + { + // and push it to all our clients linked to the module and who are not streaming in + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_DEXTRA, it)) != nullptr ) + { + // is this client busy ? + if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) ) + { + // no, send the packet + int n = packet->IsDvHeader() ? 5 : 1; + for ( int i = 0; i < n; i++ ) + { + Send(buffer, client->GetIp()); + } + } + } + g_Reflector.ReleaseClients(); + } + + + // done + delete packet; + } + m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -282,80 +282,80 @@ void CDextraProtocol::HandleQueue(void) void CDextraProtocol::HandleKeepalives(void) { - // DExtra protocol sends and monitors keepalives packets - // event if the client is currently streaming - // so, send keepalives to all - CBuffer keepalive; - EncodeKeepAlivePacket(&keepalive); - - // iterate on clients - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_DEXTRA, it)) != nullptr ) - { - // send keepalive - Send(keepalive, client->GetIp()); - - // client busy ? - if ( client->IsAMaster() ) - { - // yes, just tickle it - client->Alive(); - } - // otherwise check if still with us - else if ( !client->IsAlive() ) - { - CPeers *peers = g_Reflector.GetPeers(); - std::shared_ptrpeer = peers->FindPeer(client->GetCallsign(), client->GetIp(), PROTOCOL_DEXTRA); - if ( peer != nullptr && peer->GetReflectorModules()[0] == client->GetReflectorModule() ) - { - // no, but this is a peer client, so it will be handled below - } - else - { - // no, disconnect - CBuffer disconnect; - EncodeDisconnectPacket(&disconnect, client->GetReflectorModule()); - Send(disconnect, client->GetIp()); - - // remove it - std::cout << "DExtra client " << client->GetCallsign() << " keepalive timeout" << std::endl; - clients->RemoveClient(client); - } - g_Reflector.ReleasePeers(); - } - - } - g_Reflector.ReleaseClients(); - - // iterate on peers - CPeers *peers = g_Reflector.GetPeers(); - auto pit = peers->begin(); - std::shared_ptrpeer = nullptr; - while ( (peer = peers->FindNextPeer(PROTOCOL_DEXTRA, pit)) != nullptr ) - { - // keepalives are sent between clients - - // some client busy or still with us ? - if ( !peer->IsAMaster() && !peer->IsAlive() ) - { - // no, disconnect all clients - CBuffer disconnect; - EncodeDisconnectPacket(&disconnect, peer->GetReflectorModules()[0]); - CClients *clients = g_Reflector.GetClients(); - for ( auto cit=peer->cbegin(); cit!=peer->cend(); cit++ ) - { - Send(disconnect, (*cit)->GetIp()); - } - g_Reflector.ReleaseClients(); - - // remove it - std::cout << "DExtra peer " << peer->GetCallsign() << " keepalive timeout" << std::endl; - peers->RemovePeer(peer); - } - } - g_Reflector.ReleasePeers(); + // DExtra protocol sends and monitors keepalives packets + // event if the client is currently streaming + // so, send keepalives to all + CBuffer keepalive; + EncodeKeepAlivePacket(&keepalive); + + // iterate on clients + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_DEXTRA, it)) != nullptr ) + { + // send keepalive + Send(keepalive, client->GetIp()); + + // client busy ? + if ( client->IsAMaster() ) + { + // yes, just tickle it + client->Alive(); + } + // otherwise check if still with us + else if ( !client->IsAlive() ) + { + CPeers *peers = g_Reflector.GetPeers(); + std::shared_ptrpeer = peers->FindPeer(client->GetCallsign(), client->GetIp(), PROTOCOL_DEXTRA); + if ( peer != nullptr && peer->GetReflectorModules()[0] == client->GetReflectorModule() ) + { + // no, but this is a peer client, so it will be handled below + } + else + { + // no, disconnect + CBuffer disconnect; + EncodeDisconnectPacket(&disconnect, client->GetReflectorModule()); + Send(disconnect, client->GetIp()); + + // remove it + std::cout << "DExtra client " << client->GetCallsign() << " keepalive timeout" << std::endl; + clients->RemoveClient(client); + } + g_Reflector.ReleasePeers(); + } + + } + g_Reflector.ReleaseClients(); + + // iterate on peers + CPeers *peers = g_Reflector.GetPeers(); + auto pit = peers->begin(); + std::shared_ptrpeer = nullptr; + while ( (peer = peers->FindNextPeer(PROTOCOL_DEXTRA, pit)) != nullptr ) + { + // keepalives are sent between clients + + // some client busy or still with us ? + if ( !peer->IsAMaster() && !peer->IsAlive() ) + { + // no, disconnect all clients + CBuffer disconnect; + EncodeDisconnectPacket(&disconnect, peer->GetReflectorModules()[0]); + CClients *clients = g_Reflector.GetClients(); + for ( auto cit=peer->cbegin(); cit!=peer->cend(); cit++ ) + { + Send(disconnect, (*cit)->GetIp()); + } + g_Reflector.ReleaseClients(); + + // remove it + std::cout << "DExtra peer " << peer->GetCallsign() << " keepalive timeout" << std::endl; + peers->RemovePeer(peer); + } + } + g_Reflector.ReleasePeers(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -363,51 +363,51 @@ void CDextraProtocol::HandleKeepalives(void) void CDextraProtocol::HandlePeerLinks(void) { - CBuffer buffer; - - // get the list of peers - CPeerCallsignList *list = g_GateKeeper.GetPeerList(); - CPeers *peers = g_Reflector.GetPeers(); - - // check if all our connected peers are still listed by gatekeeper - // if not, disconnect - auto pit = peers->begin(); - std::shared_ptrpeer = nullptr; - while ( (peer = peers->FindNextPeer(PROTOCOL_DEXTRA, pit)) != nullptr ) - { - if ( list->FindListItem(peer->GetCallsign()) == nullptr ) - { - // send disconnect packet - EncodeDisconnectPacket(&buffer, peer->GetReflectorModules()[0]); - Send(buffer, peer->GetIp()); - std::cout << "Sending disconnect packet to XRF peer " << peer->GetCallsign() << " at " << peer->GetIp() << std::endl; - // remove client - peers->RemovePeer(peer); - } - } - - // check if all ours peers listed by gatekeeper are connected - // if not, connect or reconnect - for ( auto it=list->begin(); it!=list->end(); it++ ) - { - if ( !(*it).GetCallsign().HasSameCallsignWithWildcard(CCallsign("XRF*")) ) - continue; - if ( strlen((*it).GetModules()) != 2 ) - continue; - if ( peers->FindPeer((*it).GetCallsign(), PROTOCOL_DEXTRA) == nullptr ) - { - // resolve again peer's IP in case it's a dynamic IP - (*it).ResolveIp(); - // send connect packet to re-initiate peer link - EncodeConnectPacket(&buffer, (*it).GetModules()); - Send(buffer, (*it).GetIp(), DEXTRA_PORT); - std::cout << "Sending connect packet to XRF peer " << (*it).GetCallsign() << " @ " << (*it).GetIp() << " for module " << (*it).GetModules()[1] << " (module " << (*it).GetModules()[0] << ")" << std::endl; - } - } - - // done - g_Reflector.ReleasePeers(); - g_GateKeeper.ReleasePeerList(); + CBuffer buffer; + + // get the list of peers + CPeerCallsignList *list = g_GateKeeper.GetPeerList(); + CPeers *peers = g_Reflector.GetPeers(); + + // check if all our connected peers are still listed by gatekeeper + // if not, disconnect + auto pit = peers->begin(); + std::shared_ptrpeer = nullptr; + while ( (peer = peers->FindNextPeer(PROTOCOL_DEXTRA, pit)) != nullptr ) + { + if ( list->FindListItem(peer->GetCallsign()) == nullptr ) + { + // send disconnect packet + EncodeDisconnectPacket(&buffer, peer->GetReflectorModules()[0]); + Send(buffer, peer->GetIp()); + std::cout << "Sending disconnect packet to XRF peer " << peer->GetCallsign() << " at " << peer->GetIp() << std::endl; + // remove client + peers->RemovePeer(peer); + } + } + + // check if all ours peers listed by gatekeeper are connected + // if not, connect or reconnect + for ( auto it=list->begin(); it!=list->end(); it++ ) + { + if ( !(*it).GetCallsign().HasSameCallsignWithWildcard(CCallsign("XRF*")) ) + continue; + if ( strlen((*it).GetModules()) != 2 ) + continue; + if ( peers->FindPeer((*it).GetCallsign(), PROTOCOL_DEXTRA) == nullptr ) + { + // resolve again peer's IP in case it's a dynamic IP + (*it).ResolveIp(); + // send connect packet to re-initiate peer link + EncodeConnectPacket(&buffer, (*it).GetModules()); + Send(buffer, (*it).GetIp(), DEXTRA_PORT); + std::cout << "Sending connect packet to XRF peer " << (*it).GetCallsign() << " @ " << (*it).GetIp() << " for module " << (*it).GetModules()[1] << " (module " << (*it).GetModules()[0] << ")" << std::endl; + } + } + + // done + g_Reflector.ReleasePeers(); + g_GateKeeper.ReleasePeerList(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -415,60 +415,60 @@ void CDextraProtocol::HandlePeerLinks(void) bool CDextraProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip) { - bool newstream = false; - - // find the stream - CPacketStream *stream = GetStream(Header->GetStreamId()); - if ( stream == nullptr ) - { - // no stream open yet, open a new one - CCallsign via(Header->GetRpt1Callsign()); - - // find this client - std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_DEXTRA); - if ( client != nullptr ) - { - // get client callsign - via = client->GetCallsign(); - // apply protocol revision details - if ( client->GetProtocolRevision() == 2 ) - { - // update Header RPT2 module letter with - // the module the client is linked to - Header->SetRpt2Module(client->GetReflectorModule()); - } - // and try to open the stream - if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) - { - // keep the handle - m_Streams.push_back(stream); - newstream = true; - } - } - // release - g_Reflector.ReleaseClients(); - - // update last heard - g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), via, Header->GetRpt2Callsign()); - g_Reflector.ReleaseUsers(); - - // delete header if needed - if ( !newstream ) - { - delete Header; - } - } - else - { - // stream already open - // skip packet, but tickle the stream - stream->Tickle(); - // and delete packet - delete Header; - } - - // done - return newstream; + bool newstream = false; + + // find the stream + CPacketStream *stream = GetStream(Header->GetStreamId()); + if ( stream == nullptr ) + { + // no stream open yet, open a new one + CCallsign via(Header->GetRpt1Callsign()); + + // find this client + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_DEXTRA); + if ( client != nullptr ) + { + // get client callsign + via = client->GetCallsign(); + // apply protocol revision details + if ( client->GetProtocolRevision() == 2 ) + { + // update Header RPT2 module letter with + // the module the client is linked to + Header->SetRpt2Module(client->GetReflectorModule()); + } + // and try to open the stream + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) + { + // keep the handle + m_Streams.push_back(stream); + newstream = true; + } + } + // release + g_Reflector.ReleaseClients(); + + // update last heard + g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), via, Header->GetRpt2Callsign()); + g_Reflector.ReleaseUsers(); + + // delete header if needed + if ( !newstream ) + { + delete Header; + } + } + else + { + // stream already open + // skip packet, but tickle the stream + stream->Tickle(); + // and delete packet + delete Header; + } + + // done + return newstream; } //////////////////////////////////////////////////////////////////////////////////////// @@ -476,114 +476,114 @@ bool CDextraProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip) bool CDextraProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsign, char *reflectormodule, int *revision) { - bool valid = false; - if ((Buffer.size() == 11) && (Buffer.data()[9] != ' ')) - { - callsign->SetCallsign(Buffer.data(), 8); - callsign->SetModule(Buffer.data()[8]); - *reflectormodule = Buffer.data()[9]; - *revision = (Buffer.data()[10] == 11) ? 1 : 0; - valid = (callsign->IsValid() && IsLetter(*reflectormodule)); - // detect revision - if ( (Buffer.data()[10] == 11) ) - { - *revision = 1; - } - else if ( callsign->HasSameCallsignWithWildcard(CCallsign("XRF*")) ) - { - *revision = 2; - } - else - { - *revision = 0; - } - } - return valid; + bool valid = false; + if ((Buffer.size() == 11) && (Buffer.data()[9] != ' ')) + { + callsign->SetCallsign(Buffer.data(), 8); + callsign->SetModule(Buffer.data()[8]); + *reflectormodule = Buffer.data()[9]; + *revision = (Buffer.data()[10] == 11) ? 1 : 0; + valid = (callsign->IsValid() && IsLetter(*reflectormodule)); + // detect revision + if ( (Buffer.data()[10] == 11) ) + { + *revision = 1; + } + else if ( callsign->HasSameCallsignWithWildcard(CCallsign("XRF*")) ) + { + *revision = 2; + } + else + { + *revision = 0; + } + } + return valid; } bool CDextraProtocol::IsValidDisconnectPacket(const CBuffer &Buffer, CCallsign *callsign) { - bool valid = false; - if ((Buffer.size() == 11) && (Buffer.data()[9] == ' ')) - { - callsign->SetCallsign(Buffer.data(), 8); - callsign->SetModule(Buffer.data()[8]); - valid = callsign->IsValid(); - } - return valid; + bool valid = false; + if ((Buffer.size() == 11) && (Buffer.data()[9] == ' ')) + { + callsign->SetCallsign(Buffer.data(), 8); + callsign->SetModule(Buffer.data()[8]); + valid = callsign->IsValid(); + } + return valid; } bool CDextraProtocol::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *callsign) { - bool valid = false; - if (Buffer.size() == 9) - { - callsign->SetCallsign(Buffer.data(), 8); - valid = callsign->IsValid(); - } - return valid; + bool valid = false; + if (Buffer.size() == 9) + { + callsign->SetCallsign(Buffer.data(), 8); + valid = callsign->IsValid(); + } + return valid; } CDvHeaderPacket *CDextraProtocol::IsValidDvHeaderPacket(const CBuffer &Buffer) { - CDvHeaderPacket *header = nullptr; - - if ( (Buffer.size() == 56) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) && - (Buffer.data()[4] == 0x10) && (Buffer.data()[8] == 0x20) ) - { - // create packet - header = new CDvHeaderPacket((struct dstar_header *)&(Buffer.data()[15]), - *((uint16 *)&(Buffer.data()[12])), 0x80); - // check validity of packet - if ( !header->IsValid() ) - { - delete header; - header = nullptr; - } - } - return header; + CDvHeaderPacket *header = nullptr; + + if ( (Buffer.size() == 56) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) && + (Buffer.data()[4] == 0x10) && (Buffer.data()[8] == 0x20) ) + { + // create packet + header = new CDvHeaderPacket((struct dstar_header *)&(Buffer.data()[15]), + *((uint16 *)&(Buffer.data()[12])), 0x80); + // check validity of packet + if ( !header->IsValid() ) + { + delete header; + header = nullptr; + } + } + return header; } CDvFramePacket *CDextraProtocol::IsValidDvFramePacket(const CBuffer &Buffer) { - CDvFramePacket *dvframe = nullptr; - - if ( (Buffer.size() == 27) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) && - (Buffer.data()[4] == 0x20) && (Buffer.data()[8] == 0x20) && - ((Buffer.data()[14] & 0x40) == 0) ) - { - // create packet - dvframe = new CDvFramePacket((struct dstar_dvframe *)&(Buffer.data()[15]), - *((uint16 *)&(Buffer.data()[12])), Buffer.data()[14]); - // check validity of packet - if ( !dvframe->IsValid() ) - { - delete dvframe; - dvframe = nullptr; - } - } - return dvframe; + CDvFramePacket *dvframe = nullptr; + + if ( (Buffer.size() == 27) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) && + (Buffer.data()[4] == 0x20) && (Buffer.data()[8] == 0x20) && + ((Buffer.data()[14] & 0x40) == 0) ) + { + // create packet + dvframe = new CDvFramePacket((struct dstar_dvframe *)&(Buffer.data()[15]), + *((uint16 *)&(Buffer.data()[12])), Buffer.data()[14]); + // check validity of packet + if ( !dvframe->IsValid() ) + { + delete dvframe; + dvframe = nullptr; + } + } + return dvframe; } CDvLastFramePacket *CDextraProtocol::IsValidDvLastFramePacket(const CBuffer &Buffer) { - CDvLastFramePacket *dvframe = nullptr; - - if ( (Buffer.size() == 27) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) && - (Buffer.data()[4] == 0x20) && (Buffer.data()[8] == 0x20) && - ((Buffer.data()[14] & 0x40) != 0) ) - { - // create packet - dvframe = new CDvLastFramePacket((struct dstar_dvframe *)&(Buffer.data()[15]), - *((uint16 *)&(Buffer.data()[12])), Buffer.data()[14]); - // check validity of packet - if ( !dvframe->IsValid() ) - { - delete dvframe; - dvframe = nullptr; - } - } - return dvframe; + CDvLastFramePacket *dvframe = nullptr; + + if ( (Buffer.size() == 27) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) && + (Buffer.data()[4] == 0x20) && (Buffer.data()[8] == 0x20) && + ((Buffer.data()[14] & 0x40) != 0) ) + { + // create packet + dvframe = new CDvLastFramePacket((struct dstar_dvframe *)&(Buffer.data()[15]), + *((uint16 *)&(Buffer.data()[12])), Buffer.data()[14]); + // check validity of packet + if ( !dvframe->IsValid() ) + { + delete dvframe; + dvframe = nullptr; + } + } + return dvframe; } //////////////////////////////////////////////////////////////////////////////////////// @@ -591,101 +591,101 @@ CDvLastFramePacket *CDextraProtocol::IsValidDvLastFramePacket(const CBuffer &Buf void CDextraProtocol::EncodeKeepAlivePacket(CBuffer *Buffer) { - Buffer->Set(GetReflectorCallsign()); + Buffer->Set(GetReflectorCallsign()); } void CDextraProtocol::EncodeConnectPacket(CBuffer *Buffer, const char *Modules) { - uint8 lm = (uint8)Modules[0]; - uint8 rm = (uint8)Modules[1]; - Buffer->Set((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN); - Buffer->Append(lm); - Buffer->Append(rm); - Buffer->Append((uint8)0); + uint8 lm = (uint8)Modules[0]; + uint8 rm = (uint8)Modules[1]; + Buffer->Set((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN); + Buffer->Append(lm); + Buffer->Append(rm); + Buffer->Append((uint8)0); } void CDextraProtocol::EncodeConnectAckPacket(CBuffer *Buffer, int ProtRev) { - // is it for a XRF or repeater - if ( ProtRev == 2 ) - { - // XRFxxx - uint8 rm = (Buffer->data())[8]; - uint8 lm = (Buffer->data())[9]; - Buffer->clear(); - Buffer->Set((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN); - Buffer->Append(lm); - Buffer->Append(rm); - Buffer->Append((uint8)0); - } - else - { - // regular repeater - uint8 tag[] = { 'A','C','K',0 }; - Buffer->resize(Buffer->size()-1); - Buffer->Append(tag, sizeof(tag)); - } + // is it for a XRF or repeater + if ( ProtRev == 2 ) + { + // XRFxxx + uint8 rm = (Buffer->data())[8]; + uint8 lm = (Buffer->data())[9]; + Buffer->clear(); + Buffer->Set((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN); + Buffer->Append(lm); + Buffer->Append(rm); + Buffer->Append((uint8)0); + } + else + { + // regular repeater + uint8 tag[] = { 'A','C','K',0 }; + Buffer->resize(Buffer->size()-1); + Buffer->Append(tag, sizeof(tag)); + } } void CDextraProtocol::EncodeConnectNackPacket(CBuffer *Buffer) { - uint8 tag[] = { 'N','A','K',0 }; - Buffer->resize(Buffer->size()-1); - Buffer->Append(tag, sizeof(tag)); + uint8 tag[] = { 'N','A','K',0 }; + Buffer->resize(Buffer->size()-1); + Buffer->Append(tag, sizeof(tag)); } void CDextraProtocol::EncodeDisconnectPacket(CBuffer *Buffer, char Module) { - uint8 tag[] = { ' ',0 }; - Buffer->Set((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN); - Buffer->Append((uint8)Module); - Buffer->Append(tag, sizeof(tag)); + uint8 tag[] = { ' ',0 }; + Buffer->Set((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN); + Buffer->Append((uint8)Module); + Buffer->Append(tag, sizeof(tag)); } void CDextraProtocol::EncodeDisconnectedPacket(CBuffer *Buffer) { - uint8 tag[] = { 'D','I','S','C','O','N','N','E','C','T','E','D' }; - Buffer->Set(tag, sizeof(tag)); + uint8 tag[] = { 'D','I','S','C','O','N','N','E','C','T','E','D' }; + Buffer->Set(tag, sizeof(tag)); } bool CDextraProtocol::EncodeDvHeaderPacket(const CDvHeaderPacket &Packet, CBuffer *Buffer) const { - uint8 tag[] = { 'D','S','V','T',0x10,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; - struct dstar_header DstarHeader; + uint8 tag[] = { 'D','S','V','T',0x10,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; + struct dstar_header DstarHeader; - Packet.ConvertToDstarStruct(&DstarHeader); + Packet.ConvertToDstarStruct(&DstarHeader); - Buffer->Set(tag, sizeof(tag)); - Buffer->Append(Packet.GetStreamId()); - Buffer->Append((uint8)0x80); - Buffer->Append((uint8 *)&DstarHeader, sizeof(struct dstar_header)); + Buffer->Set(tag, sizeof(tag)); + Buffer->Append(Packet.GetStreamId()); + Buffer->Append((uint8)0x80); + Buffer->Append((uint8 *)&DstarHeader, sizeof(struct dstar_header)); - return true; + return true; } bool CDextraProtocol::EncodeDvFramePacket(const CDvFramePacket &Packet, CBuffer *Buffer) const { - uint8 tag[] = { 'D','S','V','T',0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; + uint8 tag[] = { 'D','S','V','T',0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; - Buffer->Set(tag, sizeof(tag)); - Buffer->Append(Packet.GetStreamId()); - Buffer->Append((uint8)(Packet.GetPacketId() % 21)); - Buffer->Append((uint8 *)Packet.GetAmbe(), AMBE_SIZE); - Buffer->Append((uint8 *)Packet.GetDvData(), DVDATA_SIZE); + Buffer->Set(tag, sizeof(tag)); + Buffer->Append(Packet.GetStreamId()); + Buffer->Append((uint8)(Packet.GetPacketId() % 21)); + Buffer->Append((uint8 *)Packet.GetAmbe(), AMBE_SIZE); + Buffer->Append((uint8 *)Packet.GetDvData(), DVDATA_SIZE); - return true; + return true; } bool CDextraProtocol::EncodeDvLastFramePacket(const CDvLastFramePacket &Packet, CBuffer *Buffer) const { - uint8 tag1[] = { 'D','S','V','T',0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; - uint8 tag2[] = { 0x55,0xC8,0x7A,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x1A,0xC6 }; + uint8 tag1[] = { 'D','S','V','T',0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; + uint8 tag2[] = { 0x55,0xC8,0x7A,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x1A,0xC6 }; - Buffer->Set(tag1, sizeof(tag1)); - Buffer->Append(Packet.GetStreamId()); - Buffer->Append((uint8)((Packet.GetPacketId() % 21) | 0x40)); - Buffer->Append(tag2, sizeof(tag2)); + Buffer->Set(tag1, sizeof(tag1)); + Buffer->Append(Packet.GetStreamId()); + Buffer->Append((uint8)((Packet.GetPacketId() % 21) | 0x40)); + Buffer->Append(tag2, sizeof(tag2)); - return true; + return true; } diff --git a/src/cdextraprotocol.h b/src/cdextraprotocol.h index 46e9a45..4393f88 100644 --- a/src/cdextraprotocol.h +++ b/src/cdextraprotocol.h @@ -58,46 +58,46 @@ class CDextraProtocol : public CProtocol { public: - // initialization - bool Initialize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); + // initialization + bool Initialize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); - // task - void Task(void); + // task + void Task(void); protected: - // queue helper - void HandleQueue(void); + // queue helper + void HandleQueue(void); - // keepalive helpers - void HandlePeerLinks(void); - void HandleKeepalives(void); + // keepalive helpers + void HandlePeerLinks(void); + void HandleKeepalives(void); - // stream helpers - bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); + // stream helpers + bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); - // packet decoding helpers - bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, int *); - bool IsValidDisconnectPacket(const CBuffer &, CCallsign *); - bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); - CDvHeaderPacket *IsValidDvHeaderPacket(const CBuffer &); - CDvFramePacket *IsValidDvFramePacket(const CBuffer &); - CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &); + // packet decoding helpers + bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, int *); + bool IsValidDisconnectPacket(const CBuffer &, CCallsign *); + bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); + CDvHeaderPacket *IsValidDvHeaderPacket(const CBuffer &); + CDvFramePacket *IsValidDvFramePacket(const CBuffer &); + CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &); - // packet encoding helpers - void EncodeKeepAlivePacket(CBuffer *); - void EncodeConnectPacket(CBuffer *, const char *); - void EncodeConnectAckPacket(CBuffer *, int); - void EncodeConnectNackPacket(CBuffer *); - void EncodeDisconnectPacket(CBuffer *, char); - void EncodeDisconnectedPacket(CBuffer *); - bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; - bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; - bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; + // packet encoding helpers + void EncodeKeepAlivePacket(CBuffer *); + void EncodeConnectPacket(CBuffer *, const char *); + void EncodeConnectAckPacket(CBuffer *, int); + void EncodeConnectNackPacket(CBuffer *); + void EncodeDisconnectPacket(CBuffer *, char); + void EncodeDisconnectedPacket(CBuffer *); + bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; + bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; + bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; protected: - // time - CTimePoint m_LastKeepaliveTime; - CTimePoint m_LastPeersLinkTime; + // time + CTimePoint m_LastKeepaliveTime; + CTimePoint m_LastPeersLinkTime; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cdmriddir.cpp b/src/cdmriddir.cpp index 4ced138..a23b5b9 100644 --- a/src/cdmriddir.cpp +++ b/src/cdmriddir.cpp @@ -34,20 +34,20 @@ CDmridDir::CDmridDir() { - keep_running = true; - m_pThread = nullptr; + keep_running = true; + m_pThread = nullptr; } CDmridDir::~CDmridDir() { - // kill threads - keep_running = false; - if ( m_pThread != nullptr ) - { - m_pThread->join(); - delete m_pThread; + // kill threads + keep_running = false; + if ( m_pThread != nullptr ) + { + m_pThread->join(); + delete m_pThread; m_pThread = nullptr; - } + } } @@ -59,24 +59,24 @@ bool CDmridDir::Init(void) // load content Reload(); - // reset run flag - keep_running = true; + // reset run flag + keep_running = true; - // start thread; - m_pThread = new std::thread(CDmridDir::Thread, this); + // start thread; + m_pThread = new std::thread(CDmridDir::Thread, this); - return true; + return true; } void CDmridDir::Close(void) { - keep_running = false; - if ( m_pThread != nullptr ) - { - m_pThread->join(); - delete m_pThread; - m_pThread = nullptr; - } + keep_running = false; + if ( m_pThread != nullptr ) + { + m_pThread->join(); + delete m_pThread; + m_pThread = nullptr; + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -84,18 +84,18 @@ void CDmridDir::Close(void) void CDmridDir::Thread(CDmridDir *This) { - while (This->keep_running) - { - // Wait DMRIDDB_REFRESH_RATE minutes + while (This->keep_running) + { + // Wait DMRIDDB_REFRESH_RATE minutes for (int i=0; i<30*DMRIDDB_REFRESH_RATE && This->keep_running; i++) - CTimePoint::TaskSleepFor(2000); - - // have lists files changed ? - if ( This->NeedReload() ) - { - This->Reload(); - } - } + CTimePoint::TaskSleepFor(2000); + + // have lists files changed ? + if ( This->NeedReload() ) + { + This->Reload(); + } + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -103,18 +103,18 @@ void CDmridDir::Thread(CDmridDir *This) bool CDmridDir::Reload(void) { - CBuffer buffer; - bool ok = false; - - if ( LoadContent(&buffer) ) - { - Lock(); - { - ok = RefreshContent(buffer); - } - Unlock(); - } - return ok; + CBuffer buffer; + bool ok = false; + + if ( LoadContent(&buffer) ) + { + Lock(); + { + ok = RefreshContent(buffer); + } + Unlock(); + } + return ok; } @@ -123,22 +123,22 @@ bool CDmridDir::Reload(void) const CCallsign *CDmridDir::FindCallsign(uint32 dmrid) { - auto found = m_CallsignMap.find(dmrid); - if ( found != m_CallsignMap.end() ) - { - return &(found->second); - } - return nullptr; + auto found = m_CallsignMap.find(dmrid); + if ( found != m_CallsignMap.end() ) + { + return &(found->second); + } + return nullptr; } uint32 CDmridDir::FindDmrid(const CCallsign &callsign) { - auto found = m_DmridMap.find(callsign); - if ( found != m_DmridMap.end() ) - { - return (found->second); - } - return 0; + auto found = m_DmridMap.find(callsign); + if ( found != m_DmridMap.end() ) + { + return (found->second); + } + return 0; } @@ -147,15 +147,15 @@ uint32 CDmridDir::FindDmrid(const CCallsign &callsign) bool CDmridDir::IsValidDmrid(const char *sz) { - bool ok = false; - size_t n = ::strlen(sz); - if ( (n > 0) && (n <= 8) ) - { - ok = true; - for ( size_t i = 0; (i < n) && ok; i++ ) - { - ok &= ::isdigit(sz[i]); - } - } - return ok; + bool ok = false; + size_t n = ::strlen(sz); + if ( (n > 0) && (n <= 8) ) + { + ok = true; + for ( size_t i = 0; (i < n) && ok; i++ ) + { + ok &= ::isdigit(sz[i]); + } + } + return ok; } diff --git a/src/cdmriddir.h b/src/cdmriddir.h index 8794b5d..0fdaad1 100644 --- a/src/cdmriddir.h +++ b/src/cdmriddir.h @@ -36,8 +36,8 @@ struct CDmridDirCallsignCompare { - bool operator() (const CCallsign &cs1, const CCallsign &cs2) const - { return cs1.HasLowerCallsign(cs2);} + bool operator() (const CCallsign &cs1, const CCallsign &cs2) const + { return cs1.HasLowerCallsign(cs2);} }; @@ -46,48 +46,48 @@ struct CDmridDirCallsignCompare class CDmridDir { public: - // constructor - CDmridDir(); + // constructor + CDmridDir(); - // destructor - ~CDmridDir(); + // destructor + ~CDmridDir(); - // init & close - virtual bool Init(void); - virtual void Close(void); + // init & close + virtual bool Init(void); + virtual void Close(void); - // locks - void Lock(void) { m_Mutex.lock(); } - void Unlock(void) { m_Mutex.unlock(); } + // locks + void Lock(void) { m_Mutex.lock(); } + void Unlock(void) { m_Mutex.unlock(); } - // refresh - virtual bool LoadContent(CBuffer *) { return false; } - virtual bool RefreshContent(const CBuffer &) { return false; } + // refresh + virtual bool LoadContent(CBuffer *) { return false; } + virtual bool RefreshContent(const CBuffer &) { return false; } - // find - const CCallsign *FindCallsign(uint32); - uint32 FindDmrid(const CCallsign &); + // find + const CCallsign *FindCallsign(uint32); + uint32 FindDmrid(const CCallsign &); protected: - // thread - static void Thread(CDmridDir *); + // thread + static void Thread(CDmridDir *); - // reload helpers - bool Reload(void); - virtual bool NeedReload(void) { return false; } - bool IsValidDmrid(const char *); + // reload helpers + bool Reload(void); + virtual bool NeedReload(void) { return false; } + bool IsValidDmrid(const char *); protected: // data - std::map m_CallsignMap; - std::map m_DmridMap; + std::map m_CallsignMap; + std::map m_DmridMap; - // Lock() - std::mutex m_Mutex; + // Lock() + std::mutex m_Mutex; - // thread - std::atomic keep_running; - std::thread *m_pThread; + // thread + std::atomic keep_running; + std::thread *m_pThread; }; diff --git a/src/cdmriddirfile.cpp b/src/cdmriddirfile.cpp index 61dcb5f..b1a9e7a 100644 --- a/src/cdmriddirfile.cpp +++ b/src/cdmriddirfile.cpp @@ -38,7 +38,7 @@ CDmridDirFile g_DmridDir; CDmridDirFile::CDmridDirFile() { - ::memset(&m_LastModTime, 0, sizeof(time_t)); + ::memset(&m_LastModTime, 0, sizeof(time_t)); } @@ -47,7 +47,7 @@ CDmridDirFile::CDmridDirFile() bool CDmridDirFile::Init(void) { - return CDmridDir::Init(); + return CDmridDir::Init(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -55,111 +55,111 @@ bool CDmridDirFile::Init(void) bool CDmridDirFile::NeedReload(void) { - bool needReload = false; - - time_t time; - if ( GetLastModTime(&time) ) - { - needReload = time != m_LastModTime; - } - return needReload; + bool needReload = false; + + time_t time; + if ( GetLastModTime(&time) ) + { + needReload = time != m_LastModTime; + } + return needReload; } bool CDmridDirFile::LoadContent(CBuffer *buffer) { - bool ok = false; - std::ifstream file; - std::streampos size; - - // open file - file.open(DMRIDDB_PATH, std::ios::in | std::ios::binary | std::ios::ate); - if ( file.is_open() ) - { - // read file - size = file.tellg(); - if ( size > 0 ) - { - // read file into buffer - buffer->resize((int)size+1); - file.seekg (0, std::ios::beg); - file.read((char *)buffer->data(), (int)size); - - // close file - file.close(); - - // update time - GetLastModTime(&m_LastModTime); - - // done - ok = true; - } - } - - // done - return ok; + bool ok = false; + std::ifstream file; + std::streampos size; + + // open file + file.open(DMRIDDB_PATH, std::ios::in | std::ios::binary | std::ios::ate); + if ( file.is_open() ) + { + // read file + size = file.tellg(); + if ( size > 0 ) + { + // read file into buffer + buffer->resize((int)size+1); + file.seekg (0, std::ios::beg); + file.read((char *)buffer->data(), (int)size); + + // close file + file.close(); + + // update time + GetLastModTime(&m_LastModTime); + + // done + ok = true; + } + } + + // done + return ok; } bool CDmridDirFile::RefreshContent(const CBuffer &buffer) { - bool ok = false; - - // clear directory - m_CallsignMap.clear(); - m_DmridMap.clear(); - - // scan buffer - if ( buffer.size() > 0 ) - { - // crack it - char *ptr1 = (char *)buffer.data(); - char *ptr2; - - // get next line - while ( (ptr2 = ::strchr(ptr1, '\n')) != nullptr ) - { - *ptr2 = 0; - // get items - char *dmrid; - char *callsign; - if ( ((dmrid = ::strtok(ptr1, ";")) != nullptr) && IsValidDmrid(dmrid) ) - { - if ( ((callsign = ::strtok(nullptr, ";")) != nullptr) ) - { - // new entry - uint32 ui = atoi(dmrid); - CCallsign cs(callsign, ui); - if ( cs.IsValid() ) - { - m_CallsignMap.insert(std::pair(ui, cs)); - m_DmridMap.insert(std::pair(cs,ui)); - } - } - } - // next line - ptr1 = ptr2+1; - } - - // done - ok = true; - } - - // report - std::cout << "Read " << m_DmridMap.size() << " DMR ids from file " << DMRIDDB_PATH << std::endl; - - // done - return ok; + bool ok = false; + + // clear directory + m_CallsignMap.clear(); + m_DmridMap.clear(); + + // scan buffer + if ( buffer.size() > 0 ) + { + // crack it + char *ptr1 = (char *)buffer.data(); + char *ptr2; + + // get next line + while ( (ptr2 = ::strchr(ptr1, '\n')) != nullptr ) + { + *ptr2 = 0; + // get items + char *dmrid; + char *callsign; + if ( ((dmrid = ::strtok(ptr1, ";")) != nullptr) && IsValidDmrid(dmrid) ) + { + if ( ((callsign = ::strtok(nullptr, ";")) != nullptr) ) + { + // new entry + uint32 ui = atoi(dmrid); + CCallsign cs(callsign, ui); + if ( cs.IsValid() ) + { + m_CallsignMap.insert(std::pair(ui, cs)); + m_DmridMap.insert(std::pair(cs,ui)); + } + } + } + // next line + ptr1 = ptr2+1; + } + + // done + ok = true; + } + + // report + std::cout << "Read " << m_DmridMap.size() << " DMR ids from file " << DMRIDDB_PATH << std::endl; + + // done + return ok; } bool CDmridDirFile::GetLastModTime(time_t *time) { - bool ok = false; - - struct stat fileStat; - if( ::stat(DMRIDDB_PATH, &fileStat) != -1 ) - { - *time = fileStat.st_mtime; - ok = true; - } - return ok; + bool ok = false; + + struct stat fileStat; + if( ::stat(DMRIDDB_PATH, &fileStat) != -1 ) + { + *time = fileStat.st_mtime; + ok = true; + } + return ok; } diff --git a/src/cdmriddirfile.h b/src/cdmriddirfile.h index 8466068..8a5f14e 100644 --- a/src/cdmriddirfile.h +++ b/src/cdmriddirfile.h @@ -32,28 +32,28 @@ class CDmridDirFile : public CDmridDir { public: - // constructor - CDmridDirFile(); - - // destructor - ~CDmridDirFile() {} - - // init & close - bool Init(void); - - // refresh - bool LoadContent(CBuffer *); - bool RefreshContent(const CBuffer &); - + // constructor + CDmridDirFile(); + + // destructor + ~CDmridDirFile() {} + + // init & close + bool Init(void); + + // refresh + bool LoadContent(CBuffer *); + bool RefreshContent(const CBuffer &); + protected: - // reload helpers - bool NeedReload(void); - bool GetLastModTime(time_t *); - + // reload helpers + bool NeedReload(void); + bool GetLastModTime(time_t *); + protected: - // data - time_t m_LastModTime; - }; + // data + time_t m_LastModTime; +}; //////////////////////////////////////////////////////////////////////////////////////// #endif /* cdmrididirfile_h */ diff --git a/src/cdmriddirhttp.cpp b/src/cdmriddirhttp.cpp index 6a4fbb2..369513e 100644 --- a/src/cdmriddirhttp.cpp +++ b/src/cdmriddirhttp.cpp @@ -39,56 +39,56 @@ CDmridDirHttp g_DmridDir; bool CDmridDirHttp::LoadContent(CBuffer *buffer) { - // get file from xlxapi server - return HttpGet("xlxapi.rlx.lu", "api/exportdmr.php", 80, buffer); + // get file from xlxapi server + return HttpGet("xlxapi.rlx.lu", "api/exportdmr.php", 80, buffer); } bool CDmridDirHttp::RefreshContent(const CBuffer &buffer) { - bool ok = false; - - // clear directory - m_CallsignMap.clear(); - m_DmridMap.clear(); - - // scan file - if ( buffer.size() > 0 ) - { - char *ptr1 = (char *)buffer.data(); - char *ptr2; - // get next line - while ( (ptr2 = ::strchr(ptr1, '\n')) != nullptr ) - { - *ptr2 = 0; - // get items - char *dmrid; - char *callsign; - if ( ((dmrid = ::strtok(ptr1, ";")) != nullptr) && IsValidDmrid(dmrid) ) - { - if ( ((callsign = ::strtok(nullptr, ";")) != nullptr) ) - { - // new entry - uint32 ui = atoi(dmrid); - CCallsign cs(callsign, ui); - if ( cs.IsValid() ) - { - m_CallsignMap.insert(std::pair(ui, cs)); - m_DmridMap.insert(std::pair(cs,ui)); - } - } - } - // next line - ptr1 = ptr2+1; - } - // done - ok = true; - } - - // report - std::cout << "Read " << m_DmridMap.size() << " DMR ids from xlxapi.rlx.lu database " << std::endl; - - // done - return ok; + bool ok = false; + + // clear directory + m_CallsignMap.clear(); + m_DmridMap.clear(); + + // scan file + if ( buffer.size() > 0 ) + { + char *ptr1 = (char *)buffer.data(); + char *ptr2; + // get next line + while ( (ptr2 = ::strchr(ptr1, '\n')) != nullptr ) + { + *ptr2 = 0; + // get items + char *dmrid; + char *callsign; + if ( ((dmrid = ::strtok(ptr1, ";")) != nullptr) && IsValidDmrid(dmrid) ) + { + if ( ((callsign = ::strtok(nullptr, ";")) != nullptr) ) + { + // new entry + uint32 ui = atoi(dmrid); + CCallsign cs(callsign, ui); + if ( cs.IsValid() ) + { + m_CallsignMap.insert(std::pair(ui, cs)); + m_DmridMap.insert(std::pair(cs,ui)); + } + } + } + // next line + ptr1 = ptr2+1; + } + // done + ok = true; + } + + // report + std::cout << "Read " << m_DmridMap.size() << " DMR ids from xlxapi.rlx.lu database " << std::endl; + + // done + return ok; } @@ -99,83 +99,84 @@ bool CDmridDirHttp::RefreshContent(const CBuffer &buffer) bool CDmridDirHttp::HttpGet(const char *hostname, const char *filename, int port, CBuffer *buffer) { - bool ok = false; - int sock_id; - - // open socket - if ( (sock_id = ::socket(AF_INET, SOCK_STREAM, 0)) >= 0 ) - { - // get hostname address - struct sockaddr_in servaddr; - struct hostent *hp; - ::memset(&servaddr,0,sizeof(servaddr)); - if( (hp = gethostbyname(hostname)) != nullptr ) - { - // dns resolved - ::memcpy((char *)&servaddr.sin_addr.s_addr, (char *)hp->h_addr, hp->h_length); - servaddr.sin_port = htons(port); - servaddr.sin_family = AF_INET; - - // connect - if ( ::connect(sock_id, (struct sockaddr *)&servaddr, sizeof(servaddr)) == 0) - { - // send the GET request - char request[DMRID_HTTPGET_SIZEMAX]; - ::sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: xlxd\r\n\r\n", - filename, (const char *)g_Reflector.GetCallsign()); - ::write(sock_id, request, strlen(request)); - - // config receive timeouts - fd_set read_set; - struct timeval timeout; - timeout.tv_sec = 5; - timeout.tv_usec = 0; - FD_ZERO(&read_set); - FD_SET(sock_id, &read_set); - - // get the reply back - buffer->clear(); - bool done = false; - do - { - char buf[1440]; - ssize_t len = 0; - select(sock_id+1, &read_set, nullptr, nullptr, &timeout); - //if ( (ret > 0) || ((ret < 0) && (errno == EINPROGRESS)) ) - //if ( ret >= 0 ) - //{ - usleep(5000); - len = read(sock_id, buf, 1440); - if ( len > 0 ) - { - buffer->Append((uint8 *)buf, (int)len); - ok = true; - } - //} - done = (len <= 0); - - } while (!done); - buffer->Append((uint8)0); - - // and disconnect - close(sock_id); - } - else - { - std::cout << "Cannot establish connection with host " << hostname << std::endl; - } - } - else - { - std::cout << "Host " << hostname << " not found" << std::endl; - } - - } - else - { - std::cout << "Failed to open wget socket" << std::endl; - } - - // done - return ok; + bool ok = false; + int sock_id; + + // open socket + if ( (sock_id = ::socket(AF_INET, SOCK_STREAM, 0)) >= 0 ) + { + // get hostname address + struct sockaddr_in servaddr; + struct hostent *hp; + ::memset(&servaddr,0,sizeof(servaddr)); + if( (hp = gethostbyname(hostname)) != nullptr ) + { + // dns resolved + ::memcpy((char *)&servaddr.sin_addr.s_addr, (char *)hp->h_addr, hp->h_length); + servaddr.sin_port = htons(port); + servaddr.sin_family = AF_INET; + + // connect + if ( ::connect(sock_id, (struct sockaddr *)&servaddr, sizeof(servaddr)) == 0) + { + // send the GET request + char request[DMRID_HTTPGET_SIZEMAX]; + ::sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: xlxd\r\n\r\n", + filename, (const char *)g_Reflector.GetCallsign()); + ::write(sock_id, request, strlen(request)); + + // config receive timeouts + fd_set read_set; + struct timeval timeout; + timeout.tv_sec = 5; + timeout.tv_usec = 0; + FD_ZERO(&read_set); + FD_SET(sock_id, &read_set); + + // get the reply back + buffer->clear(); + bool done = false; + do + { + char buf[1440]; + ssize_t len = 0; + select(sock_id+1, &read_set, nullptr, nullptr, &timeout); + //if ( (ret > 0) || ((ret < 0) && (errno == EINPROGRESS)) ) + //if ( ret >= 0 ) + //{ + usleep(5000); + len = read(sock_id, buf, 1440); + if ( len > 0 ) + { + buffer->Append((uint8 *)buf, (int)len); + ok = true; + } + //} + done = (len <= 0); + + } + while (!done); + buffer->Append((uint8)0); + + // and disconnect + close(sock_id); + } + else + { + std::cout << "Cannot establish connection with host " << hostname << std::endl; + } + } + else + { + std::cout << "Host " << hostname << " not found" << std::endl; + } + + } + else + { + std::cout << "Failed to open wget socket" << std::endl; + } + + // done + return ok; } diff --git a/src/cdmriddirhttp.h b/src/cdmriddirhttp.h index 1d90ec1..6ab5306 100644 --- a/src/cdmriddirhttp.h +++ b/src/cdmriddirhttp.h @@ -32,20 +32,20 @@ class CDmridDirHttp : public CDmridDir { public: - // constructor - CDmridDirHttp() {} - - // destructor - ~CDmridDirHttp() {} - - // refresh - bool LoadContent(CBuffer *); - bool RefreshContent(const CBuffer &); - + // constructor + CDmridDirHttp() {} + + // destructor + ~CDmridDirHttp() {} + + // refresh + bool LoadContent(CBuffer *); + bool RefreshContent(const CBuffer &); + protected: - // reload helpers - bool NeedReload(void) { return true; } - bool HttpGet(const char *, const char *, int, CBuffer *); + // reload helpers + bool NeedReload(void) { return true; } + bool HttpGet(const char *, const char *, int, CBuffer *); }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cdmrmmdvmclient.cpp b/src/cdmrmmdvmclient.cpp index 09c9e1c..edb52e7 100644 --- a/src/cdmrmmdvmclient.cpp +++ b/src/cdmrmmdvmclient.cpp @@ -34,12 +34,12 @@ CDmrmmdvmClient::CDmrmmdvmClient() } CDmrmmdvmClient::CDmrmmdvmClient(const CCallsign &callsign, const CIp &ip, char reflectorModule) -: CClient(callsign, ip, reflectorModule) + : CClient(callsign, ip, reflectorModule) { } CDmrmmdvmClient::CDmrmmdvmClient(const CDmrmmdvmClient &client) -: CClient(client) + : CClient(client) { } @@ -48,5 +48,5 @@ CDmrmmdvmClient::CDmrmmdvmClient(const CDmrmmdvmClient &client) bool CDmrmmdvmClient::IsAlive(void) const { - return (m_LastKeepaliveTime.DurationSinceNow() < DMRMMDVM_KEEPALIVE_TIMEOUT); + return (m_LastKeepaliveTime.DurationSinceNow() < DMRMMDVM_KEEPALIVE_TIMEOUT); } diff --git a/src/cdmrmmdvmclient.h b/src/cdmrmmdvmclient.h index b5880ab..01f82d5 100644 --- a/src/cdmrmmdvmclient.h +++ b/src/cdmrmmdvmclient.h @@ -37,22 +37,22 @@ class CDmrmmdvmClient : public CClient { public: - // constructors - CDmrmmdvmClient(); - CDmrmmdvmClient(const CCallsign &, const CIp &, char = ' '); - CDmrmmdvmClient(const CDmrmmdvmClient &); - - // destructor - virtual ~CDmrmmdvmClient() {}; - - // identity - int GetProtocol(void) const { return PROTOCOL_DMRMMDVM; } - const char *GetProtocolName(void) const { return "DMRMmdvm"; } - int GetCodec(void) const { return CODEC_AMBE2PLUS; } - bool IsNode(void) const { return true; } - - // status - bool IsAlive(void) const; + // constructors + CDmrmmdvmClient(); + CDmrmmdvmClient(const CCallsign &, const CIp &, char = ' '); + CDmrmmdvmClient(const CDmrmmdvmClient &); + + // destructor + virtual ~CDmrmmdvmClient() {}; + + // identity + int GetProtocol(void) const { return PROTOCOL_DMRMMDVM; } + const char *GetProtocolName(void) const { return "DMRMmdvm"; } + int GetCodec(void) const { return CODEC_AMBE2PLUS; } + bool IsNode(void) const { return true; } + + // status + bool IsAlive(void) const; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cdmrmmdvmprotocol.cpp b/src/cdmrmmdvmprotocol.cpp index 5325745..6bd67d9 100644 --- a/src/cdmrmmdvmprotocol.cpp +++ b/src/cdmrmmdvmprotocol.cpp @@ -56,20 +56,20 @@ static uint8 g_DmrSyncMSData[] = { 0x0D,0x5D,0x7F,0x77,0xFD,0x75,0x70 }; bool CDmrmmdvmProtocol::Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6) { - // base class - if (! CProtocol::Initialize(type, port, has_ipv4, has_ipv6)) + // base class + if (! CProtocol::Initialize(type, port, has_ipv4, has_ipv6)) return false; - // update time - m_LastKeepaliveTime.Now(); + // update time + m_LastKeepaliveTime.Now(); - // random number generator - time_t t; - ::srand((unsigned) time(&t)); - m_uiAuthSeed = (uint32)rand(); + // random number generator + time_t t; + ::srand((unsigned) time(&t)); + m_uiAuthSeed = (uint32)rand(); - // done - return true; + // done + return true; } @@ -79,17 +79,17 @@ bool CDmrmmdvmProtocol::Initalize(const char *type, const uint16 port, const boo void CDmrmmdvmProtocol::Task(void) { - CBuffer Buffer; - CIp Ip; - CCallsign Callsign; - int iRssi; - uint8 Cmd; - uint8 CallType; - CDvHeaderPacket *Header; - CDvFramePacket *Frames[3]; - CDvLastFramePacket *LastFrame; - - // handle incoming packets + CBuffer Buffer; + CIp Ip; + CCallsign Callsign; + int iRssi; + uint8 Cmd; + uint8 CallType; + CDvHeaderPacket *Header; + CDvFramePacket *Frames[3]; + CDvLastFramePacket *LastFrame; + + // handle incoming packets #if DMR_IPV6==true #if DMR_IPV4==true if ( ReceiveDS(Buffer, Ip, 20) ) @@ -99,173 +99,173 @@ void CDmrmmdvmProtocol::Task(void) #else if ( Receive4(Buffer, Ip, 20) ) #endif - { - //Buffer.DebugDump(g_Reflector.m_DebugFile); - // crack the packet - if ( IsValidDvFramePacket(Buffer, Frames) ) - { - //std::cout << "DMRmmdvm DV frame" << std::endl; - - for ( int i = 0; i < 3; i++ ) - { - OnDvFramePacketIn(Frames[i], &Ip); - } - } - else if ( IsValidDvHeaderPacket(Buffer, &Header, &Cmd, &CallType) ) - { - //std::cout << "DMRmmdvm DV header:" << std::endl << *Header << std::endl; - //std::cout << "DMRmmdvm DV header" << std::endl; - - // callsign muted? - if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_DMRMMDVM) ) - { - // handle it - OnDvHeaderPacketIn(Header, Ip, Cmd, CallType); - } - else - { - delete Header; - } - } - else if ( IsValidDvLastFramePacket(Buffer, &LastFrame) ) - { - //std::cout << "DMRmmdvm DV last frame" << std::endl; - - OnDvLastFramePacketIn(LastFrame, &Ip); - } - else if ( IsValidConnectPacket(Buffer, &Callsign, Ip) ) - { - std::cout << "DMRmmdvm connect packet from " << Callsign << " at " << Ip << std::endl; - - // callsign authorized? - if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_DMRMMDVM) ) - { - // acknowledge the request - EncodeConnectAckPacket(&Buffer, Callsign, m_uiAuthSeed); - Send(Buffer, Ip); - } - else - { - // deny the request - EncodeNackPacket(&Buffer, Callsign); - Send(Buffer, Ip); - } - - } - else if ( IsValidAuthenticationPacket(Buffer, &Callsign, Ip) ) - { - std::cout << "DMRmmdvm authentication packet from " << Callsign << " at " << Ip << std::endl; - - // callsign authorized? - if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_DMRMMDVM) ) - { - // acknowledge the request - EncodeAckPacket(&Buffer, Callsign); - Send(Buffer, Ip); - - // add client if needed - CClients *clients = g_Reflector.GetClients(); - std::shared_ptrclient = clients->FindClient(Callsign, Ip, PROTOCOL_DMRMMDVM); - // client already connected ? - if ( client == nullptr ) - { - std::cout << "DMRmmdvm login from " << Callsign << " at " << Ip << std::endl; - - // create the client and append - clients->AddClient(std::make_shared(Callsign, Ip)); - } - else - { - client->Alive(); - } - // and done - g_Reflector.ReleaseClients(); - } - else - { - // deny the request - EncodeNackPacket(&Buffer, Callsign); - Send(Buffer, Ip); - } - - } - else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) - { - std::cout << "DMRmmdvm disconnect packet from " << Callsign << " at " << Ip << std::endl; - - // find client & remove it - CClients *clients = g_Reflector.GetClients(); - std::shared_ptrclient = clients->FindClient(Ip, PROTOCOL_DMRMMDVM); - if ( client != nullptr ) - { - clients->RemoveClient(client); - } - g_Reflector.ReleaseClients(); - } - else if ( IsValidConfigPacket(Buffer, &Callsign, Ip) ) - { - std::cout << "DMRmmdvm configuration packet from " << Callsign << " at " << Ip << std::endl; - - // acknowledge the request - EncodeAckPacket(&Buffer, Callsign); - Send(Buffer, Ip); - } - else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) - { - //std::cout << "DMRmmdvm keepalive packet from " << Callsign << " at " << Ip << std::endl; - - // find all clients with that callsign & ip and keep them alive - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(Callsign, Ip, PROTOCOL_DMRMMDVM, it)) != nullptr ) - { - // acknowledge - EncodeKeepAlivePacket(&Buffer, client); - Send(Buffer, Ip); - - // and mark as alive - client->Alive(); - } - g_Reflector.ReleaseClients(); - } - else if ( IsValidRssiPacket(Buffer, &Callsign, &iRssi) ) - { - // std::cout << "DMRmmdvm RSSI packet from " << Callsign << " at " << Ip << std::endl - - // ignore... - } - else if ( IsValidOptionPacket(Buffer, &Callsign) ) - { - std::cout << "DMRmmdvm options packet from " << Callsign << " at " << Ip << std::endl; - - // acknowledge the request - EncodeAckPacket(&Buffer, Callsign); - Send(Buffer, Ip); - } - else if ( Buffer.size() != 55 ) - { - std::cout << "DMRmmdvm packet (" << Buffer.size() << ")" << std::endl; - //std::cout << Buffer << std::endl; - } - } - - // handle end of streaming timeout - CheckStreamsTimeout(); - - // handle queue from reflector - HandleQueue(); - - - // keep client alive - if ( m_LastKeepaliveTime.DurationSinceNow() > DMRMMDVM_KEEPALIVE_PERIOD ) - { - // - HandleKeepalives(); - - // update time - m_LastKeepaliveTime.Now(); - } + { + //Buffer.DebugDump(g_Reflector.m_DebugFile); + // crack the packet + if ( IsValidDvFramePacket(Buffer, Frames) ) + { + //std::cout << "DMRmmdvm DV frame" << std::endl; + + for ( int i = 0; i < 3; i++ ) + { + OnDvFramePacketIn(Frames[i], &Ip); + } + } + else if ( IsValidDvHeaderPacket(Buffer, &Header, &Cmd, &CallType) ) + { + //std::cout << "DMRmmdvm DV header:" << std::endl << *Header << std::endl; + //std::cout << "DMRmmdvm DV header" << std::endl; + + // callsign muted? + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_DMRMMDVM) ) + { + // handle it + OnDvHeaderPacketIn(Header, Ip, Cmd, CallType); + } + else + { + delete Header; + } + } + else if ( IsValidDvLastFramePacket(Buffer, &LastFrame) ) + { + //std::cout << "DMRmmdvm DV last frame" << std::endl; + + OnDvLastFramePacketIn(LastFrame, &Ip); + } + else if ( IsValidConnectPacket(Buffer, &Callsign, Ip) ) + { + std::cout << "DMRmmdvm connect packet from " << Callsign << " at " << Ip << std::endl; + + // callsign authorized? + if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_DMRMMDVM) ) + { + // acknowledge the request + EncodeConnectAckPacket(&Buffer, Callsign, m_uiAuthSeed); + Send(Buffer, Ip); + } + else + { + // deny the request + EncodeNackPacket(&Buffer, Callsign); + Send(Buffer, Ip); + } + + } + else if ( IsValidAuthenticationPacket(Buffer, &Callsign, Ip) ) + { + std::cout << "DMRmmdvm authentication packet from " << Callsign << " at " << Ip << std::endl; + + // callsign authorized? + if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_DMRMMDVM) ) + { + // acknowledge the request + EncodeAckPacket(&Buffer, Callsign); + Send(Buffer, Ip); + + // add client if needed + CClients *clients = g_Reflector.GetClients(); + std::shared_ptrclient = clients->FindClient(Callsign, Ip, PROTOCOL_DMRMMDVM); + // client already connected ? + if ( client == nullptr ) + { + std::cout << "DMRmmdvm login from " << Callsign << " at " << Ip << std::endl; + + // create the client and append + clients->AddClient(std::make_shared(Callsign, Ip)); + } + else + { + client->Alive(); + } + // and done + g_Reflector.ReleaseClients(); + } + else + { + // deny the request + EncodeNackPacket(&Buffer, Callsign); + Send(Buffer, Ip); + } + + } + else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) + { + std::cout << "DMRmmdvm disconnect packet from " << Callsign << " at " << Ip << std::endl; + + // find client & remove it + CClients *clients = g_Reflector.GetClients(); + std::shared_ptrclient = clients->FindClient(Ip, PROTOCOL_DMRMMDVM); + if ( client != nullptr ) + { + clients->RemoveClient(client); + } + g_Reflector.ReleaseClients(); + } + else if ( IsValidConfigPacket(Buffer, &Callsign, Ip) ) + { + std::cout << "DMRmmdvm configuration packet from " << Callsign << " at " << Ip << std::endl; + + // acknowledge the request + EncodeAckPacket(&Buffer, Callsign); + Send(Buffer, Ip); + } + else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) + { + //std::cout << "DMRmmdvm keepalive packet from " << Callsign << " at " << Ip << std::endl; + + // find all clients with that callsign & ip and keep them alive + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(Callsign, Ip, PROTOCOL_DMRMMDVM, it)) != nullptr ) + { + // acknowledge + EncodeKeepAlivePacket(&Buffer, client); + Send(Buffer, Ip); + + // and mark as alive + client->Alive(); + } + g_Reflector.ReleaseClients(); + } + else if ( IsValidRssiPacket(Buffer, &Callsign, &iRssi) ) + { + // std::cout << "DMRmmdvm RSSI packet from " << Callsign << " at " << Ip << std::endl + + // ignore... + } + else if ( IsValidOptionPacket(Buffer, &Callsign) ) + { + std::cout << "DMRmmdvm options packet from " << Callsign << " at " << Ip << std::endl; + + // acknowledge the request + EncodeAckPacket(&Buffer, Callsign); + Send(Buffer, Ip); + } + else if ( Buffer.size() != 55 ) + { + std::cout << "DMRmmdvm packet (" << Buffer.size() << ")" << std::endl; + //std::cout << Buffer << std::endl; + } + } + + // handle end of streaming timeout + CheckStreamsTimeout(); + + // handle queue from reflector + HandleQueue(); + + + // keep client alive + if ( m_LastKeepaliveTime.DurationSinceNow() > DMRMMDVM_KEEPALIVE_PERIOD ) + { + // + HandleKeepalives(); + + // update time + m_LastKeepaliveTime.Now(); + } } @@ -274,100 +274,100 @@ void CDmrmmdvmProtocol::Task(void) bool CDmrmmdvmProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip, uint8 cmd, uint8 CallType) { - bool newstream = false; - bool lastheard = false; - - // - CCallsign via(Header->GetRpt1Callsign()); - - // find the stream - CPacketStream *stream = GetStream(Header->GetStreamId()); - if ( stream == nullptr ) - { - // no stream open yet, open a new one - // firstfind this client - std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_DMRMMDVM); - if ( client != nullptr ) - { - // process cmd if any - if ( !client->HasReflectorModule() ) - { - // not linked yet - if ( cmd == CMD_LINK ) - { - if ( g_Reflector.IsValidModule(Header->GetRpt2Module()) ) - { - std::cout << "DMRmmdvm client " << client->GetCallsign() << " linking on module " << Header->GetRpt2Module() << std::endl; - // link - client->SetReflectorModule(Header->GetRpt2Module()); - } - else - { - std::cout << "DMRMMDVM node " << via << " link attempt on non-existing module" << std::endl; - } - } - } - else - { - // already linked - if ( cmd == CMD_UNLINK ) - { - std::cout << "DMRmmdvm client " << client->GetCallsign() << " unlinking" << std::endl; - // unlink - client->SetReflectorModule(' '); - } - else - { - // replace rpt2 module with currently linked module - Header->SetRpt2Module(client->GetReflectorModule()); - } - } - - // and now, re-check module is valid && that it's not a private call - if ( g_Reflector.IsValidModule(Header->GetRpt2Module()) && (CallType == DMR_GROUP_CALL) ) - { - // yes, try to open the stream - if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) - { - // keep the handle - m_Streams.push_back(stream); - newstream = true; - lastheard = true; - } - } - } - else - { - lastheard = true; - } - - // release - g_Reflector.ReleaseClients(); - - // update last heard - if ( lastheard ) - { - g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), via, Header->GetRpt2Callsign()); - g_Reflector.ReleaseUsers(); - } - - // delete header if needed - if ( !newstream ) - { - delete Header; - } - } - else - { - // stream already open - // skip packet, but tickle the stream - stream->Tickle(); - // and delete packet - delete Header; - } - - // done - return newstream; + bool newstream = false; + bool lastheard = false; + + // + CCallsign via(Header->GetRpt1Callsign()); + + // find the stream + CPacketStream *stream = GetStream(Header->GetStreamId()); + if ( stream == nullptr ) + { + // no stream open yet, open a new one + // firstfind this client + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_DMRMMDVM); + if ( client != nullptr ) + { + // process cmd if any + if ( !client->HasReflectorModule() ) + { + // not linked yet + if ( cmd == CMD_LINK ) + { + if ( g_Reflector.IsValidModule(Header->GetRpt2Module()) ) + { + std::cout << "DMRmmdvm client " << client->GetCallsign() << " linking on module " << Header->GetRpt2Module() << std::endl; + // link + client->SetReflectorModule(Header->GetRpt2Module()); + } + else + { + std::cout << "DMRMMDVM node " << via << " link attempt on non-existing module" << std::endl; + } + } + } + else + { + // already linked + if ( cmd == CMD_UNLINK ) + { + std::cout << "DMRmmdvm client " << client->GetCallsign() << " unlinking" << std::endl; + // unlink + client->SetReflectorModule(' '); + } + else + { + // replace rpt2 module with currently linked module + Header->SetRpt2Module(client->GetReflectorModule()); + } + } + + // and now, re-check module is valid && that it's not a private call + if ( g_Reflector.IsValidModule(Header->GetRpt2Module()) && (CallType == DMR_GROUP_CALL) ) + { + // yes, try to open the stream + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) + { + // keep the handle + m_Streams.push_back(stream); + newstream = true; + lastheard = true; + } + } + } + else + { + lastheard = true; + } + + // release + g_Reflector.ReleaseClients(); + + // update last heard + if ( lastheard ) + { + g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), via, Header->GetRpt2Callsign()); + g_Reflector.ReleaseUsers(); + } + + // delete header if needed + if ( !newstream ) + { + delete Header; + } + } + else + { + // stream already open + // skip packet, but tickle the stream + stream->Tickle(); + // and delete packet + delete Header; + } + + // done + return newstream; } //////////////////////////////////////////////////////////////////////////////////////// @@ -376,89 +376,89 @@ bool CDmrmmdvmProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &I void CDmrmmdvmProtocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) - { - // get the packet - CPacket *packet = m_Queue.front(); - m_Queue.pop(); - - // get our sender's id - int iModId = g_Reflector.GetModuleIndex(packet->GetModuleId()); - - // encode - CBuffer buffer; - - // check if it's header - if ( packet->IsDvHeader() ) - { - // update local stream cache - // this relies on queue feeder setting valid module id - m_StreamsCache[iModId].m_dvHeader = CDvHeaderPacket((const CDvHeaderPacket &)*packet); - m_StreamsCache[iModId].m_uiSeqId = 0; - - // encode it - EncodeDvHeaderPacket((const CDvHeaderPacket &)*packet, m_StreamsCache[iModId].m_uiSeqId, &buffer); - m_StreamsCache[iModId].m_uiSeqId = 1; - } - // check if it's a last frame - else if ( packet->IsLastPacket() ) - { - // encode it - EncodeDvLastPacket(m_StreamsCache[iModId].m_dvHeader, m_StreamsCache[iModId].m_uiSeqId, &buffer); - m_StreamsCache[iModId].m_uiSeqId = (m_StreamsCache[iModId].m_uiSeqId + 1) & 0xFF; - } - // otherwise, just a regular DV frame - else - { - // update local stream cache or send triplet when needed - switch ( packet->GetDmrPacketSubid() ) - { - case 1: - m_StreamsCache[iModId].m_dvFrame0 = CDvFramePacket((const CDvFramePacket &)*packet); - break; - case 2: - m_StreamsCache[iModId].m_dvFrame1 = CDvFramePacket((const CDvFramePacket &)*packet); - break; - case 3: - EncodeDvPacket( - m_StreamsCache[iModId].m_dvHeader, - m_StreamsCache[iModId].m_dvFrame0, - m_StreamsCache[iModId].m_dvFrame1, - (const CDvFramePacket &)*packet, - m_StreamsCache[iModId].m_uiSeqId, - &buffer); - m_StreamsCache[iModId].m_uiSeqId = (m_StreamsCache[iModId].m_uiSeqId + 1) & 0xFF; - break; - default: - break; - } - } - - // send it - if ( buffer.size() > 0 ) - { - // and push it to all our clients linked to the module and who are not streaming in - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_DMRMMDVM, it)) != nullptr ) - { - // is this client busy ? - if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) ) - { - // no, send the packet - Send(buffer, client->GetIp()); - - } - } - g_Reflector.ReleaseClients(); - } - - // done - delete packet; - } - m_Queue.Unlock(); + m_Queue.Lock(); + while ( !m_Queue.empty() ) + { + // get the packet + CPacket *packet = m_Queue.front(); + m_Queue.pop(); + + // get our sender's id + int iModId = g_Reflector.GetModuleIndex(packet->GetModuleId()); + + // encode + CBuffer buffer; + + // check if it's header + if ( packet->IsDvHeader() ) + { + // update local stream cache + // this relies on queue feeder setting valid module id + m_StreamsCache[iModId].m_dvHeader = CDvHeaderPacket((const CDvHeaderPacket &)*packet); + m_StreamsCache[iModId].m_uiSeqId = 0; + + // encode it + EncodeDvHeaderPacket((const CDvHeaderPacket &)*packet, m_StreamsCache[iModId].m_uiSeqId, &buffer); + m_StreamsCache[iModId].m_uiSeqId = 1; + } + // check if it's a last frame + else if ( packet->IsLastPacket() ) + { + // encode it + EncodeDvLastPacket(m_StreamsCache[iModId].m_dvHeader, m_StreamsCache[iModId].m_uiSeqId, &buffer); + m_StreamsCache[iModId].m_uiSeqId = (m_StreamsCache[iModId].m_uiSeqId + 1) & 0xFF; + } + // otherwise, just a regular DV frame + else + { + // update local stream cache or send triplet when needed + switch ( packet->GetDmrPacketSubid() ) + { + case 1: + m_StreamsCache[iModId].m_dvFrame0 = CDvFramePacket((const CDvFramePacket &)*packet); + break; + case 2: + m_StreamsCache[iModId].m_dvFrame1 = CDvFramePacket((const CDvFramePacket &)*packet); + break; + case 3: + EncodeDvPacket( + m_StreamsCache[iModId].m_dvHeader, + m_StreamsCache[iModId].m_dvFrame0, + m_StreamsCache[iModId].m_dvFrame1, + (const CDvFramePacket &)*packet, + m_StreamsCache[iModId].m_uiSeqId, + &buffer); + m_StreamsCache[iModId].m_uiSeqId = (m_StreamsCache[iModId].m_uiSeqId + 1) & 0xFF; + break; + default: + break; + } + } + + // send it + if ( buffer.size() > 0 ) + { + // and push it to all our clients linked to the module and who are not streaming in + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_DMRMMDVM, it)) != nullptr ) + { + // is this client busy ? + if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) ) + { + // no, send the packet + Send(buffer, client->GetIp()); + + } + } + g_Reflector.ReleaseClients(); + } + + // done + delete packet; + } + m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -466,36 +466,36 @@ void CDmrmmdvmProtocol::HandleQueue(void) void CDmrmmdvmProtocol::HandleKeepalives(void) { - // DMRhomebrew protocol keepalive request is client tasks - // here, just check that all clients are still alive - // and disconnect them if not - - // iterate on clients - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_DMRMMDVM, it)) != nullptr ) - { - // is this client busy ? - if ( client->IsAMaster() ) - { - // yes, just tickle it - client->Alive(); - } - // check it's still with us - else if ( !client->IsAlive() ) - { - // no, disconnect - CBuffer disconnect; - Send(disconnect, client->GetIp()); - - // remove it - std::cout << "DMRmmdvm client " << client->GetCallsign() << " keepalive timeout" << std::endl; - clients->RemoveClient(client); - } - - } - g_Reflector.ReleaseClients(); + // DMRhomebrew protocol keepalive request is client tasks + // here, just check that all clients are still alive + // and disconnect them if not + + // iterate on clients + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_DMRMMDVM, it)) != nullptr ) + { + // is this client busy ? + if ( client->IsAMaster() ) + { + // yes, just tickle it + client->Alive(); + } + // check it's still with us + else if ( !client->IsAlive() ) + { + // no, disconnect + CBuffer disconnect; + Send(disconnect, client->GetIp()); + + // remove it + std::cout << "DMRmmdvm client " << client->GetCallsign() << " keepalive timeout" << std::endl; + clients->RemoveClient(client); + } + + } + g_Reflector.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -503,329 +503,329 @@ void CDmrmmdvmProtocol::HandleKeepalives(void) bool CDmrmmdvmProtocol::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *callsign) { - uint8 tag[] = { 'R','P','T','P','I','N','G' }; - - bool valid = false; - if ( (Buffer.size() == 11) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[10],Buffer.data()[9]),MAKEWORD(Buffer.data()[8],Buffer.data()[7])); - callsign->SetDmrid(uiRptrId, true); - callsign->SetModule(MMDVM_MODULE_ID); - valid = callsign->IsValid(); - } - return valid; + uint8 tag[] = { 'R','P','T','P','I','N','G' }; + + bool valid = false; + if ( (Buffer.size() == 11) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[10],Buffer.data()[9]),MAKEWORD(Buffer.data()[8],Buffer.data()[7])); + callsign->SetDmrid(uiRptrId, true); + callsign->SetModule(MMDVM_MODULE_ID); + valid = callsign->IsValid(); + } + return valid; } bool CDmrmmdvmProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsign, const CIp &Ip) { - uint8 tag[] = { 'R','P','T','L' }; - - bool valid = false; - if ( (Buffer.size() == 8) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[7],Buffer.data()[6]),MAKEWORD(Buffer.data()[5],Buffer.data()[4])); - callsign->SetDmrid(uiRptrId, true); - callsign->SetModule(MMDVM_MODULE_ID); - valid = callsign->IsValid(); - if ( !valid) - { - std::cout << "DMRmmdvm connect packet from IP address " << Ip << " / unrecognized id " << (int)callsign->GetDmrid() << std::endl; - } - } - return valid; + uint8 tag[] = { 'R','P','T','L' }; + + bool valid = false; + if ( (Buffer.size() == 8) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[7],Buffer.data()[6]),MAKEWORD(Buffer.data()[5],Buffer.data()[4])); + callsign->SetDmrid(uiRptrId, true); + callsign->SetModule(MMDVM_MODULE_ID); + valid = callsign->IsValid(); + if ( !valid) + { + std::cout << "DMRmmdvm connect packet from IP address " << Ip << " / unrecognized id " << (int)callsign->GetDmrid() << std::endl; + } + } + return valid; } bool CDmrmmdvmProtocol::IsValidAuthenticationPacket(const CBuffer &Buffer, CCallsign *callsign, const CIp &Ip) { - uint8 tag[] = { 'R','P','T','K' }; - - bool valid = false; - if ( (Buffer.size() == 40) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[7],Buffer.data()[6]),MAKEWORD(Buffer.data()[5],Buffer.data()[4])); - callsign->SetDmrid(uiRptrId, true); - callsign->SetModule(MMDVM_MODULE_ID); - valid = callsign->IsValid(); - if ( !valid) - { - std::cout << "DMRmmdvm authnetication packet from IP address " << Ip << " / unrecognized id " << (int)callsign->GetDmrid() << std::endl; - } - - } - return valid; + uint8 tag[] = { 'R','P','T','K' }; + + bool valid = false; + if ( (Buffer.size() == 40) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[7],Buffer.data()[6]),MAKEWORD(Buffer.data()[5],Buffer.data()[4])); + callsign->SetDmrid(uiRptrId, true); + callsign->SetModule(MMDVM_MODULE_ID); + valid = callsign->IsValid(); + if ( !valid) + { + std::cout << "DMRmmdvm authnetication packet from IP address " << Ip << " / unrecognized id " << (int)callsign->GetDmrid() << std::endl; + } + + } + return valid; } bool CDmrmmdvmProtocol::IsValidDisconnectPacket(const CBuffer &Buffer, CCallsign *callsign) { - uint8 tag[] = { 'R','P','T','C','L' }; - - bool valid = false; - if ( (Buffer.size() == 13) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[7],Buffer.data()[6]),MAKEWORD(Buffer.data()[5],Buffer.data()[4])); - callsign->SetDmrid(uiRptrId, true); - callsign->SetModule(MMDVM_MODULE_ID); - valid = callsign->IsValid(); - } - return valid; + uint8 tag[] = { 'R','P','T','C','L' }; + + bool valid = false; + if ( (Buffer.size() == 13) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[7],Buffer.data()[6]),MAKEWORD(Buffer.data()[5],Buffer.data()[4])); + callsign->SetDmrid(uiRptrId, true); + callsign->SetModule(MMDVM_MODULE_ID); + valid = callsign->IsValid(); + } + return valid; } bool CDmrmmdvmProtocol::IsValidConfigPacket(const CBuffer &Buffer, CCallsign *callsign, const CIp &Ip) { - uint8 tag[] = { 'R','P','T','C' }; - - bool valid = false; - if ( (Buffer.size() == 302) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[7],Buffer.data()[6]),MAKEWORD(Buffer.data()[5],Buffer.data()[4])); - callsign->SetDmrid(uiRptrId, true); - callsign->SetModule(MMDVM_MODULE_ID); - valid = callsign->IsValid(); - if ( !valid) - { - std::cout << "DMRmmdvm config packet from IP address " << Ip << " / unrecognized id " << (int)callsign->GetDmrid() << std::endl; - } - - } - return valid; + uint8 tag[] = { 'R','P','T','C' }; + + bool valid = false; + if ( (Buffer.size() == 302) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[7],Buffer.data()[6]),MAKEWORD(Buffer.data()[5],Buffer.data()[4])); + callsign->SetDmrid(uiRptrId, true); + callsign->SetModule(MMDVM_MODULE_ID); + valid = callsign->IsValid(); + if ( !valid) + { + std::cout << "DMRmmdvm config packet from IP address " << Ip << " / unrecognized id " << (int)callsign->GetDmrid() << std::endl; + } + + } + return valid; } bool CDmrmmdvmProtocol::IsValidOptionPacket(const CBuffer &Buffer, CCallsign *callsign) { - uint8 tag[] = { 'R','P','T','O' }; - - bool valid = false; - if ( (Buffer.size() >= 8) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[7],Buffer.data()[6]),MAKEWORD(Buffer.data()[5],Buffer.data()[4])); - callsign->SetDmrid(uiRptrId, true); - callsign->SetModule(MMDVM_MODULE_ID); - valid = callsign->IsValid(); - } - return valid; + uint8 tag[] = { 'R','P','T','O' }; + + bool valid = false; + if ( (Buffer.size() >= 8) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[7],Buffer.data()[6]),MAKEWORD(Buffer.data()[5],Buffer.data()[4])); + callsign->SetDmrid(uiRptrId, true); + callsign->SetModule(MMDVM_MODULE_ID); + valid = callsign->IsValid(); + } + return valid; } bool CDmrmmdvmProtocol::IsValidRssiPacket(const CBuffer &Buffer, CCallsign *callsign, int *rssi) { - uint8 tag[] = { 'R','P','T','I','N','T','R' }; - - bool valid = false; - if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - // ignore rest of it, as not used - // dmrid is asci hex on 8 bytes - // rssi is ascii :x-xx - valid = true; - } - return valid; + uint8 tag[] = { 'R','P','T','I','N','T','R' }; + + bool valid = false; + if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + // ignore rest of it, as not used + // dmrid is asci hex on 8 bytes + // rssi is ascii :x-xx + valid = true; + } + return valid; } bool CDmrmmdvmProtocol::IsValidDvHeaderPacket(const CBuffer &Buffer, CDvHeaderPacket **header, uint8 *cmd, uint8 *CallType) { - uint8 tag[] = { 'D','M','R','D' }; - - bool valid = false; - *header = nullptr; - *cmd = CMD_NONE; - - if ( (Buffer.size() == 55) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - // frame details - uint8 uiFrameType = (Buffer.data()[15] & 0x30) >> 4; - uint8 uiSlot = (Buffer.data()[15] & 0x80) ? DMR_SLOT2 : DMR_SLOT1; - uint8 uiCallType = (Buffer.data()[15] & 0x40) ? DMR_PRIVATE_CALL : DMR_GROUP_CALL; - uint8 uiSlotType = Buffer.data()[15] & 0x0F; - //std::cout << (int)uiSlot << std::endl; - if ( (uiFrameType == DMRMMDVM_FRAMETYPE_DATASYNC) && - (uiSlot == DMRMMDVM_REFLECTOR_SLOT) && - (uiSlotType == MMDVM_SLOTTYPE_HEADER) ) - { - // extract sync - uint8 dmrsync[7]; - dmrsync[0] = Buffer.data()[33] & 0x0F; - ::memcpy(&dmrsync[1], &Buffer.data()[34], 5); - dmrsync[6] = Buffer.data()[39] & 0xF0; - // and check - if ( (::memcmp(dmrsync, g_DmrSyncMSData, sizeof(dmrsync)) == 0) || - (::memcmp(dmrsync, g_DmrSyncBSData, sizeof(dmrsync)) == 0)) - { - // get payload - //CBPTC19696 bptc; - //uint8 lcdata[12]; - //bptc.decode(&(Buffer.data()[20]), lcdata); - - // crack DMR header - //uint8 uiSeqId = Buffer.data()[4]; - uint32 uiSrcId = MAKEDWORD(MAKEWORD(Buffer.data()[7],Buffer.data()[6]),MAKEWORD(Buffer.data()[5],0)); - uint32 uiDstId = MAKEDWORD(MAKEWORD(Buffer.data()[10],Buffer.data()[9]),MAKEWORD(Buffer.data()[8],0)); - uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[14],Buffer.data()[13]),MAKEWORD(Buffer.data()[12],Buffer.data()[11])); - //uint8 uiVoiceSeq = (Buffer.data()[15] & 0x0F); - uint32 uiStreamId = *(uint32 *)(&Buffer.data()[16]); - - // call type - *CallType = uiCallType; - - // link/unlink command ? - if ( uiDstId == 4000 ) - { - *cmd = CMD_UNLINK; - } - else if ( DmrDstIdToModule(uiDstId) != ' ' ) - { - *cmd = CMD_LINK; - } - else - { - *cmd = CMD_NONE; - } - - // build DVHeader - CCallsign csMY = CCallsign("", uiSrcId); - CCallsign rpt1 = CCallsign("", uiRptrId); - rpt1.SetModule(MMDVM_MODULE_ID); - CCallsign rpt2 = m_ReflectorCallsign; - rpt2.SetModule(DmrDstIdToModule(uiDstId)); - - // and packet - *header = new CDvHeaderPacket(uiSrcId, CCallsign("CQCQCQ"), rpt1, rpt2, uiStreamId, 0, 0); - valid = (*header)->IsValid(); - if ( !valid ) - { - delete *header; - *header = nullptr; - } - } - } - } - // done - return valid; + uint8 tag[] = { 'D','M','R','D' }; + + bool valid = false; + *header = nullptr; + *cmd = CMD_NONE; + + if ( (Buffer.size() == 55) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + // frame details + uint8 uiFrameType = (Buffer.data()[15] & 0x30) >> 4; + uint8 uiSlot = (Buffer.data()[15] & 0x80) ? DMR_SLOT2 : DMR_SLOT1; + uint8 uiCallType = (Buffer.data()[15] & 0x40) ? DMR_PRIVATE_CALL : DMR_GROUP_CALL; + uint8 uiSlotType = Buffer.data()[15] & 0x0F; + //std::cout << (int)uiSlot << std::endl; + if ( (uiFrameType == DMRMMDVM_FRAMETYPE_DATASYNC) && + (uiSlot == DMRMMDVM_REFLECTOR_SLOT) && + (uiSlotType == MMDVM_SLOTTYPE_HEADER) ) + { + // extract sync + uint8 dmrsync[7]; + dmrsync[0] = Buffer.data()[33] & 0x0F; + ::memcpy(&dmrsync[1], &Buffer.data()[34], 5); + dmrsync[6] = Buffer.data()[39] & 0xF0; + // and check + if ( (::memcmp(dmrsync, g_DmrSyncMSData, sizeof(dmrsync)) == 0) || + (::memcmp(dmrsync, g_DmrSyncBSData, sizeof(dmrsync)) == 0)) + { + // get payload + //CBPTC19696 bptc; + //uint8 lcdata[12]; + //bptc.decode(&(Buffer.data()[20]), lcdata); + + // crack DMR header + //uint8 uiSeqId = Buffer.data()[4]; + uint32 uiSrcId = MAKEDWORD(MAKEWORD(Buffer.data()[7],Buffer.data()[6]),MAKEWORD(Buffer.data()[5],0)); + uint32 uiDstId = MAKEDWORD(MAKEWORD(Buffer.data()[10],Buffer.data()[9]),MAKEWORD(Buffer.data()[8],0)); + uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[14],Buffer.data()[13]),MAKEWORD(Buffer.data()[12],Buffer.data()[11])); + //uint8 uiVoiceSeq = (Buffer.data()[15] & 0x0F); + uint32 uiStreamId = *(uint32 *)(&Buffer.data()[16]); + + // call type + *CallType = uiCallType; + + // link/unlink command ? + if ( uiDstId == 4000 ) + { + *cmd = CMD_UNLINK; + } + else if ( DmrDstIdToModule(uiDstId) != ' ' ) + { + *cmd = CMD_LINK; + } + else + { + *cmd = CMD_NONE; + } + + // build DVHeader + CCallsign csMY = CCallsign("", uiSrcId); + CCallsign rpt1 = CCallsign("", uiRptrId); + rpt1.SetModule(MMDVM_MODULE_ID); + CCallsign rpt2 = m_ReflectorCallsign; + rpt2.SetModule(DmrDstIdToModule(uiDstId)); + + // and packet + *header = new CDvHeaderPacket(uiSrcId, CCallsign("CQCQCQ"), rpt1, rpt2, uiStreamId, 0, 0); + valid = (*header)->IsValid(); + if ( !valid ) + { + delete *header; + *header = nullptr; + } + } + } + } + // done + return valid; } bool CDmrmmdvmProtocol::IsValidDvFramePacket(const CBuffer &Buffer, CDvFramePacket **frames) { - uint8 tag[] = { 'D','M','R','D' }; - - bool valid = false; - frames[0] = nullptr; - frames[1] = nullptr; - frames[2] = nullptr; - - if ( (Buffer.size() == 55) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - // frame details - uint8 uiFrameType = (Buffer.data()[15] & 0x30) >> 4; - uint8 uiSlot = (Buffer.data()[15] & 0x80) ? DMR_SLOT2 : DMR_SLOT1; - uint8 uiCallType = (Buffer.data()[15] & 0x40) ? DMR_PRIVATE_CALL : DMR_GROUP_CALL; - if ( ((uiFrameType == DMRMMDVM_FRAMETYPE_VOICE) || (uiFrameType == DMRMMDVM_FRAMETYPE_VOICESYNC)) && - (uiSlot == DMRMMDVM_REFLECTOR_SLOT) && (uiCallType == DMR_GROUP_CALL) ) - { - // crack DMR header - //uint8 uiSeqId = Buffer.data()[4]; - //uint32 uiSrcId = MAKEDWORD(MAKEWORD(Buffer.data()[7],Buffer.data()[6]),MAKEWORD(Buffer.data()[5],0)); - //uint32 uiDstId = MAKEDWORD(MAKEWORD(Buffer.data()[10],Buffer.data()[9]),MAKEWORD(Buffer.data()[8],0)); - //uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[14],Buffer.data()[13]),MAKEWORD(Buffer.data()[12],Buffer.data()[11])); - uint8 uiVoiceSeq = (Buffer.data()[15] & 0x0F); - uint32 uiStreamId = *(uint32 *)(&Buffer.data()[16]); - - // crack payload - uint8 dmrframe[33]; - uint8 dmr3ambe[27]; - uint8 dmrambe[9]; - uint8 dmrsync[7]; - // get the 33 bytes ambe - memcpy(dmrframe, &(Buffer.data()[20]), 33); - // extract the 3 ambe frames - memcpy(dmr3ambe, dmrframe, 14); - dmr3ambe[13] &= 0xF0; - dmr3ambe[13] |= (dmrframe[19] & 0x0F); - memcpy(&dmr3ambe[14], &dmrframe[20], 14); - // extract sync - dmrsync[0] = dmrframe[13] & 0x0F; - ::memcpy(&dmrsync[1], &dmrframe[14], 5); - dmrsync[6] = dmrframe[19] & 0xF0; - - // debug - //CBuffer dump; - //dump.Set(dmrsync, 6); - //dump.DebugDump(g_Reflector.m_DebugFile); - - // and create 3 dv frames - // frame1 - memcpy(dmrambe, &dmr3ambe[0], 9); - frames[0] = new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 1); - - // frame2 - memcpy(dmrambe, &dmr3ambe[9], 9); - frames[1] = new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 2); - - // frame3 - memcpy(dmrambe, &dmr3ambe[18], 9); - frames[2] = new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 3); - - // check - valid = true; - } - } - // done - return valid; + uint8 tag[] = { 'D','M','R','D' }; + + bool valid = false; + frames[0] = nullptr; + frames[1] = nullptr; + frames[2] = nullptr; + + if ( (Buffer.size() == 55) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + // frame details + uint8 uiFrameType = (Buffer.data()[15] & 0x30) >> 4; + uint8 uiSlot = (Buffer.data()[15] & 0x80) ? DMR_SLOT2 : DMR_SLOT1; + uint8 uiCallType = (Buffer.data()[15] & 0x40) ? DMR_PRIVATE_CALL : DMR_GROUP_CALL; + if ( ((uiFrameType == DMRMMDVM_FRAMETYPE_VOICE) || (uiFrameType == DMRMMDVM_FRAMETYPE_VOICESYNC)) && + (uiSlot == DMRMMDVM_REFLECTOR_SLOT) && (uiCallType == DMR_GROUP_CALL) ) + { + // crack DMR header + //uint8 uiSeqId = Buffer.data()[4]; + //uint32 uiSrcId = MAKEDWORD(MAKEWORD(Buffer.data()[7],Buffer.data()[6]),MAKEWORD(Buffer.data()[5],0)); + //uint32 uiDstId = MAKEDWORD(MAKEWORD(Buffer.data()[10],Buffer.data()[9]),MAKEWORD(Buffer.data()[8],0)); + //uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[14],Buffer.data()[13]),MAKEWORD(Buffer.data()[12],Buffer.data()[11])); + uint8 uiVoiceSeq = (Buffer.data()[15] & 0x0F); + uint32 uiStreamId = *(uint32 *)(&Buffer.data()[16]); + + // crack payload + uint8 dmrframe[33]; + uint8 dmr3ambe[27]; + uint8 dmrambe[9]; + uint8 dmrsync[7]; + // get the 33 bytes ambe + memcpy(dmrframe, &(Buffer.data()[20]), 33); + // extract the 3 ambe frames + memcpy(dmr3ambe, dmrframe, 14); + dmr3ambe[13] &= 0xF0; + dmr3ambe[13] |= (dmrframe[19] & 0x0F); + memcpy(&dmr3ambe[14], &dmrframe[20], 14); + // extract sync + dmrsync[0] = dmrframe[13] & 0x0F; + ::memcpy(&dmrsync[1], &dmrframe[14], 5); + dmrsync[6] = dmrframe[19] & 0xF0; + + // debug + //CBuffer dump; + //dump.Set(dmrsync, 6); + //dump.DebugDump(g_Reflector.m_DebugFile); + + // and create 3 dv frames + // frame1 + memcpy(dmrambe, &dmr3ambe[0], 9); + frames[0] = new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 1); + + // frame2 + memcpy(dmrambe, &dmr3ambe[9], 9); + frames[1] = new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 2); + + // frame3 + memcpy(dmrambe, &dmr3ambe[18], 9); + frames[2] = new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 3); + + // check + valid = true; + } + } + // done + return valid; } bool CDmrmmdvmProtocol::IsValidDvLastFramePacket(const CBuffer &Buffer, CDvLastFramePacket **frame) { - uint8 tag[] = { 'D','M','R','D' }; - - bool valid = false; - *frame = nullptr; - - if ( (Buffer.size() == 55) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - // frame details - uint8 uiFrameType = (Buffer.data()[15] & 0x30) >> 4; - uint8 uiSlot = (Buffer.data()[15] & 0x80) ? DMR_SLOT2 : DMR_SLOT1; - //uint8 uiCallType = (Buffer.data()[15] & 0x40) ? DMR_PRIVATE_CALL : DMR_GROUP_CALL; - uint8 uiSlotType = Buffer.data()[15] & 0x0F; - //std::cout << (int)uiSlot << std::endl; - if ( (uiFrameType == DMRMMDVM_FRAMETYPE_DATASYNC) && - (uiSlot == DMRMMDVM_REFLECTOR_SLOT) && - (uiSlotType == MMDVM_SLOTTYPE_TERMINATOR) ) - { - // extract sync - uint8 dmrsync[7]; - dmrsync[0] = Buffer.data()[33] & 0x0F; - ::memcpy(&dmrsync[1], &Buffer.data()[34], 5); - dmrsync[6] = Buffer.data()[39] & 0xF0; - // and check - if ( (::memcmp(dmrsync, g_DmrSyncMSData, sizeof(dmrsync)) == 0) || - (::memcmp(dmrsync, g_DmrSyncBSData, sizeof(dmrsync)) == 0)) - { - // get payload - //CBPTC19696 bptc; - //uint8 lcdata[12]; - //bptc.decode(&(Buffer.data()[20]), lcdata); - - // crack DMR header - //uint8 uiSeqId = Buffer.data()[4]; - //uint32 uiSrcId = MAKEDWORD(MAKEWORD(Buffer.data()[7],Buffer.data()[6]),MAKEWORD(Buffer.data()[5],0)); - //uint32 uiDstId = MAKEDWORD(MAKEWORD(Buffer.data()[10],Buffer.data()[9]),MAKEWORD(Buffer.data()[8],0)); - //uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[14],Buffer.data()[13]),MAKEWORD(Buffer.data()[12],Buffer.data()[11])); - //uint8 uiVoiceSeq = (Buffer.data()[15] & 0x0F); - uint32 uiStreamId = *(uint32 *)(&Buffer.data()[16]); - - // dummy ambe - uint8 ambe[9]; - ::memset(ambe, 0, sizeof(ambe)); - - - // and packet - *frame = new CDvLastFramePacket(ambe, dmrsync, uiStreamId, 0, 0); - - // check - valid = true; - } - } - } - // done - return valid; + uint8 tag[] = { 'D','M','R','D' }; + + bool valid = false; + *frame = nullptr; + + if ( (Buffer.size() == 55) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + // frame details + uint8 uiFrameType = (Buffer.data()[15] & 0x30) >> 4; + uint8 uiSlot = (Buffer.data()[15] & 0x80) ? DMR_SLOT2 : DMR_SLOT1; + //uint8 uiCallType = (Buffer.data()[15] & 0x40) ? DMR_PRIVATE_CALL : DMR_GROUP_CALL; + uint8 uiSlotType = Buffer.data()[15] & 0x0F; + //std::cout << (int)uiSlot << std::endl; + if ( (uiFrameType == DMRMMDVM_FRAMETYPE_DATASYNC) && + (uiSlot == DMRMMDVM_REFLECTOR_SLOT) && + (uiSlotType == MMDVM_SLOTTYPE_TERMINATOR) ) + { + // extract sync + uint8 dmrsync[7]; + dmrsync[0] = Buffer.data()[33] & 0x0F; + ::memcpy(&dmrsync[1], &Buffer.data()[34], 5); + dmrsync[6] = Buffer.data()[39] & 0xF0; + // and check + if ( (::memcmp(dmrsync, g_DmrSyncMSData, sizeof(dmrsync)) == 0) || + (::memcmp(dmrsync, g_DmrSyncBSData, sizeof(dmrsync)) == 0)) + { + // get payload + //CBPTC19696 bptc; + //uint8 lcdata[12]; + //bptc.decode(&(Buffer.data()[20]), lcdata); + + // crack DMR header + //uint8 uiSeqId = Buffer.data()[4]; + //uint32 uiSrcId = MAKEDWORD(MAKEWORD(Buffer.data()[7],Buffer.data()[6]),MAKEWORD(Buffer.data()[5],0)); + //uint32 uiDstId = MAKEDWORD(MAKEWORD(Buffer.data()[10],Buffer.data()[9]),MAKEWORD(Buffer.data()[8],0)); + //uint32 uiRptrId = MAKEDWORD(MAKEWORD(Buffer.data()[14],Buffer.data()[13]),MAKEWORD(Buffer.data()[12],Buffer.data()[11])); + //uint8 uiVoiceSeq = (Buffer.data()[15] & 0x0F); + uint32 uiStreamId = *(uint32 *)(&Buffer.data()[16]); + + // dummy ambe + uint8 ambe[9]; + ::memset(ambe, 0, sizeof(ambe)); + + + // and packet + *frame = new CDvLastFramePacket(ambe, dmrsync, uiStreamId, 0, 0); + + // check + valid = true; + } + } + } + // done + return valid; } //////////////////////////////////////////////////////////////////////////////////////// @@ -833,186 +833,186 @@ bool CDmrmmdvmProtocol::IsValidDvLastFramePacket(const CBuffer &Buffer, CDvLastF void CDmrmmdvmProtocol::EncodeKeepAlivePacket(CBuffer *Buffer, std::shared_ptrClient) { - uint8 tag[] = { 'M','S','T','P','O','N','G' }; + uint8 tag[] = { 'M','S','T','P','O','N','G' }; - Buffer->Set(tag, sizeof(tag)); - uint32 uiDmrId = Client->GetCallsign().GetDmrid(); - Buffer->Append((uint8 *)&uiDmrId, 4); + Buffer->Set(tag, sizeof(tag)); + uint32 uiDmrId = Client->GetCallsign().GetDmrid(); + Buffer->Append((uint8 *)&uiDmrId, 4); } void CDmrmmdvmProtocol::EncodeAckPacket(CBuffer *Buffer, const CCallsign &Callsign) { - uint8 tag[] = { 'R','P','T','A','C','K' }; + uint8 tag[] = { 'R','P','T','A','C','K' }; - Buffer->Set(tag, sizeof(tag)); + Buffer->Set(tag, sizeof(tag)); } void CDmrmmdvmProtocol::EncodeConnectAckPacket(CBuffer *Buffer, const CCallsign &Callsign, uint32 AuthSeed) { - uint8 tag[] = { 'R','P','T','A','C','K' }; + uint8 tag[] = { 'R','P','T','A','C','K' }; - Buffer->Set(tag, sizeof(tag)); - Buffer->Append(AuthSeed); + Buffer->Set(tag, sizeof(tag)); + Buffer->Append(AuthSeed); } void CDmrmmdvmProtocol::EncodeNackPacket(CBuffer *Buffer, const CCallsign &Callsign) { - uint8 tag[] = { 'M','S','T','N','A','K' }; + uint8 tag[] = { 'M','S','T','N','A','K' }; - Buffer->Set(tag, sizeof(tag)); + Buffer->Set(tag, sizeof(tag)); } void CDmrmmdvmProtocol::EncodeClosePacket(CBuffer *Buffer, std::shared_ptrClient) { - uint8 tag[] = { 'M','S','T','C','L' }; + uint8 tag[] = { 'M','S','T','C','L' }; - Buffer->Set(tag, sizeof(tag)); + Buffer->Set(tag, sizeof(tag)); } bool CDmrmmdvmProtocol::EncodeDvHeaderPacket(const CDvHeaderPacket &Packet, uint8 seqid, CBuffer *Buffer) const { - uint8 tag[] = { 'D','M','R','D' }; - - Buffer->Set(tag, sizeof(tag)); - - // DMR header - // uiSeqId - Buffer->Append((uint8)seqid); - // uiSrcId - uint32 uiSrcId = Packet.GetMyCallsign().GetDmrid(); - AppendDmrIdToBuffer(Buffer, uiSrcId); - // uiDstId = TG9 - uint32 uiDstId = 9; // ModuleToDmrDestId(Packet.GetRpt2Module()); - AppendDmrIdToBuffer(Buffer, uiDstId); - // uiRptrId - uint32 uiRptrId = Packet.GetRpt1Callsign().GetDmrid(); - AppendDmrRptrIdToBuffer(Buffer, uiRptrId); - // uiBitField - uint8 uiBitField = - (DMRMMDVM_FRAMETYPE_DATASYNC << 4) | - ((DMRMMDVM_REFLECTOR_SLOT == DMR_SLOT2) ? 0x80 : 0x00) | - MMDVM_SLOTTYPE_HEADER; - Buffer->Append((uint8)uiBitField); - // uiStreamId - uint32 uiStreamId = Packet.GetStreamId(); - Buffer->Append((uint32)uiStreamId); - - // Payload - AppendVoiceLCToBuffer(Buffer, uiSrcId); - - // BER - Buffer->Append((uint8)0); - - // RSSI - Buffer->Append((uint8)0); - - // done - return true; + uint8 tag[] = { 'D','M','R','D' }; + + Buffer->Set(tag, sizeof(tag)); + + // DMR header + // uiSeqId + Buffer->Append((uint8)seqid); + // uiSrcId + uint32 uiSrcId = Packet.GetMyCallsign().GetDmrid(); + AppendDmrIdToBuffer(Buffer, uiSrcId); + // uiDstId = TG9 + uint32 uiDstId = 9; // ModuleToDmrDestId(Packet.GetRpt2Module()); + AppendDmrIdToBuffer(Buffer, uiDstId); + // uiRptrId + uint32 uiRptrId = Packet.GetRpt1Callsign().GetDmrid(); + AppendDmrRptrIdToBuffer(Buffer, uiRptrId); + // uiBitField + uint8 uiBitField = + (DMRMMDVM_FRAMETYPE_DATASYNC << 4) | + ((DMRMMDVM_REFLECTOR_SLOT == DMR_SLOT2) ? 0x80 : 0x00) | + MMDVM_SLOTTYPE_HEADER; + Buffer->Append((uint8)uiBitField); + // uiStreamId + uint32 uiStreamId = Packet.GetStreamId(); + Buffer->Append((uint32)uiStreamId); + + // Payload + AppendVoiceLCToBuffer(Buffer, uiSrcId); + + // BER + Buffer->Append((uint8)0); + + // RSSI + Buffer->Append((uint8)0); + + // done + return true; } void CDmrmmdvmProtocol::EncodeDvPacket( - const CDvHeaderPacket &Header, - const CDvFramePacket &DvFrame0, const CDvFramePacket &DvFrame1, const CDvFramePacket &DvFrame2, - uint8 seqid, CBuffer *Buffer) const + const CDvHeaderPacket &Header, + const CDvFramePacket &DvFrame0, const CDvFramePacket &DvFrame1, const CDvFramePacket &DvFrame2, + uint8 seqid, CBuffer *Buffer) const { - uint8 tag[] = { 'D','M','R','D' }; - Buffer->Set(tag, sizeof(tag)); - - // DMR header - // uiSeqId - Buffer->Append((uint8)seqid); - // uiSrcId - uint32 uiSrcId = Header.GetMyCallsign().GetDmrid(); - AppendDmrIdToBuffer(Buffer, uiSrcId); - // uiDstId = TG9 - uint32 uiDstId = 9; // ModuleToDmrDestId(Header.GetRpt2Module()); - AppendDmrIdToBuffer(Buffer, uiDstId); - // uiRptrId - uint32 uiRptrId = Header.GetRpt1Callsign().GetDmrid(); - AppendDmrRptrIdToBuffer(Buffer, uiRptrId); - // uiBitField - uint8 uiBitField = - ((DMRMMDVM_REFLECTOR_SLOT == DMR_SLOT2) ? 0x80 : 0x00); - if ( DvFrame0.GetDmrPacketId() == 0 ) - { - uiBitField |= (DMRMMDVM_FRAMETYPE_VOICESYNC << 4); - } - else - { - uiBitField |= (DMRMMDVM_FRAMETYPE_VOICE << 4); - } - uiBitField |= (DvFrame0.GetDmrPacketId() & 0x0F); - Buffer->Append((uint8)uiBitField); - - // uiStreamId - uint32 uiStreamId = Header.GetStreamId(); - Buffer->Append((uint32)uiStreamId); - - // Payload - // frame0 - Buffer->ReplaceAt(20, DvFrame0.GetAmbePlus(), 9); - // 1/2 frame1 - Buffer->ReplaceAt(29, DvFrame1.GetAmbePlus(), 5); - Buffer->ReplaceAt(33, (uint8)(Buffer->at(33) & 0xF0)); - // 1/2 frame1 - Buffer->ReplaceAt(39, DvFrame1.GetAmbePlus()+4, 5); - Buffer->ReplaceAt(39, (uint8)(Buffer->at(39) & 0x0F)); - // frame2 - Buffer->ReplaceAt(44, DvFrame2.GetAmbePlus(), 9); - - // sync or embedded signaling - ReplaceEMBInBuffer(Buffer, DvFrame0.GetDmrPacketId()); - - // debug - //CBuffer dump; - //dump.Set(&(Buffer->data()[33]), 7); - //dump.DebugDump(g_Reflector.m_DebugFile); - - // BER - Buffer->Append((uint8)0); - - // RSSI - Buffer->Append((uint8)0); + uint8 tag[] = { 'D','M','R','D' }; + Buffer->Set(tag, sizeof(tag)); + + // DMR header + // uiSeqId + Buffer->Append((uint8)seqid); + // uiSrcId + uint32 uiSrcId = Header.GetMyCallsign().GetDmrid(); + AppendDmrIdToBuffer(Buffer, uiSrcId); + // uiDstId = TG9 + uint32 uiDstId = 9; // ModuleToDmrDestId(Header.GetRpt2Module()); + AppendDmrIdToBuffer(Buffer, uiDstId); + // uiRptrId + uint32 uiRptrId = Header.GetRpt1Callsign().GetDmrid(); + AppendDmrRptrIdToBuffer(Buffer, uiRptrId); + // uiBitField + uint8 uiBitField = + ((DMRMMDVM_REFLECTOR_SLOT == DMR_SLOT2) ? 0x80 : 0x00); + if ( DvFrame0.GetDmrPacketId() == 0 ) + { + uiBitField |= (DMRMMDVM_FRAMETYPE_VOICESYNC << 4); + } + else + { + uiBitField |= (DMRMMDVM_FRAMETYPE_VOICE << 4); + } + uiBitField |= (DvFrame0.GetDmrPacketId() & 0x0F); + Buffer->Append((uint8)uiBitField); + + // uiStreamId + uint32 uiStreamId = Header.GetStreamId(); + Buffer->Append((uint32)uiStreamId); + + // Payload + // frame0 + Buffer->ReplaceAt(20, DvFrame0.GetAmbePlus(), 9); + // 1/2 frame1 + Buffer->ReplaceAt(29, DvFrame1.GetAmbePlus(), 5); + Buffer->ReplaceAt(33, (uint8)(Buffer->at(33) & 0xF0)); + // 1/2 frame1 + Buffer->ReplaceAt(39, DvFrame1.GetAmbePlus()+4, 5); + Buffer->ReplaceAt(39, (uint8)(Buffer->at(39) & 0x0F)); + // frame2 + Buffer->ReplaceAt(44, DvFrame2.GetAmbePlus(), 9); + + // sync or embedded signaling + ReplaceEMBInBuffer(Buffer, DvFrame0.GetDmrPacketId()); + + // debug + //CBuffer dump; + //dump.Set(&(Buffer->data()[33]), 7); + //dump.DebugDump(g_Reflector.m_DebugFile); + + // BER + Buffer->Append((uint8)0); + + // RSSI + Buffer->Append((uint8)0); } void CDmrmmdvmProtocol::EncodeDvLastPacket(const CDvHeaderPacket &Packet, uint8 seqid, CBuffer *Buffer) const { - uint8 tag[] = { 'D','M','R','D' }; - - Buffer->Set(tag, sizeof(tag)); - - // DMR header - // uiSeqId - Buffer->Append((uint8)seqid); - // uiSrcId - uint32 uiSrcId = Packet.GetMyCallsign().GetDmrid(); - AppendDmrIdToBuffer(Buffer, uiSrcId); - // uiDstId - uint32 uiDstId = 9; //ModuleToDmrDestId(Packet.GetRpt2Module()); - AppendDmrIdToBuffer(Buffer, uiDstId); - // uiRptrId - uint32 uiRptrId = Packet.GetRpt1Callsign().GetDmrid(); - AppendDmrRptrIdToBuffer(Buffer, uiRptrId); - // uiBitField - uint8 uiBitField = - (DMRMMDVM_FRAMETYPE_DATASYNC << 4) | - ((DMRMMDVM_REFLECTOR_SLOT == DMR_SLOT2) ? 0x80 : 0x00) | - MMDVM_SLOTTYPE_TERMINATOR; - Buffer->Append((uint8)uiBitField); - // uiStreamId - uint32 uiStreamId = Packet.GetStreamId(); - Buffer->Append((uint32)uiStreamId); - - // Payload - AppendTerminatorLCToBuffer(Buffer, uiSrcId); - - // BER - Buffer->Append((uint8)0); - - // RSSI - Buffer->Append((uint8)0); + uint8 tag[] = { 'D','M','R','D' }; + + Buffer->Set(tag, sizeof(tag)); + + // DMR header + // uiSeqId + Buffer->Append((uint8)seqid); + // uiSrcId + uint32 uiSrcId = Packet.GetMyCallsign().GetDmrid(); + AppendDmrIdToBuffer(Buffer, uiSrcId); + // uiDstId + uint32 uiDstId = 9; //ModuleToDmrDestId(Packet.GetRpt2Module()); + AppendDmrIdToBuffer(Buffer, uiDstId); + // uiRptrId + uint32 uiRptrId = Packet.GetRpt1Callsign().GetDmrid(); + AppendDmrRptrIdToBuffer(Buffer, uiRptrId); + // uiBitField + uint8 uiBitField = + (DMRMMDVM_FRAMETYPE_DATASYNC << 4) | + ((DMRMMDVM_REFLECTOR_SLOT == DMR_SLOT2) ? 0x80 : 0x00) | + MMDVM_SLOTTYPE_TERMINATOR; + Buffer->Append((uint8)uiBitField); + // uiStreamId + uint32 uiStreamId = Packet.GetStreamId(); + Buffer->Append((uint32)uiStreamId); + + // Payload + AppendTerminatorLCToBuffer(Buffer, uiSrcId); + + // BER + Buffer->Append((uint8)0); + + // RSSI + Buffer->Append((uint8)0); } @@ -1021,17 +1021,17 @@ void CDmrmmdvmProtocol::EncodeDvLastPacket(const CDvHeaderPacket &Packet, uint8 char CDmrmmdvmProtocol::DmrDstIdToModule(uint32 tg) const { - // is it a 4xxx ? - if ( (tg >= 4001) && (tg <= (4000 + NB_OF_MODULES)) ) - { - return ((char)(tg - 4001) + 'A'); - } - return ' '; + // is it a 4xxx ? + if ( (tg >= 4001) && (tg <= (4000 + NB_OF_MODULES)) ) + { + return ((char)(tg - 4001) + 'A'); + } + return ' '; } uint32 CDmrmmdvmProtocol::ModuleToDmrDestId(char m) const { - return (uint32)(m - 'A')+4001; + return (uint32)(m - 'A')+4001; } //////////////////////////////////////////////////////////////////////////////////////// @@ -1039,164 +1039,164 @@ uint32 CDmrmmdvmProtocol::ModuleToDmrDestId(char m) const void CDmrmmdvmProtocol::AppendVoiceLCToBuffer(CBuffer *buffer, uint32 uiSrcId) const { - uint8 payload[33]; - - // fill payload - CBPTC19696 bptc; - ::memset(payload, 0, sizeof(payload)); - // LC data - uint8 lc[12]; - { - ::memset(lc, 0, sizeof(lc)); - // uiDstId = TG9 - lc[5] = 9; - // uiSrcId - lc[6] = (uint8)LOBYTE(HIWORD(uiSrcId)); - lc[7] = (uint8)HIBYTE(LOWORD(uiSrcId)); - lc[8] = (uint8)LOBYTE(LOWORD(uiSrcId)); - // parity - uint8 parity[4]; - CRS129::encode(lc, 9, parity); - lc[9] = parity[2] ^ DMR_VOICE_LC_HEADER_CRC_MASK; - lc[10] = parity[1] ^ DMR_VOICE_LC_HEADER_CRC_MASK; - lc[11] = parity[0] ^ DMR_VOICE_LC_HEADER_CRC_MASK; - } - // sync - ::memcpy(payload+13, g_DmrSyncBSData, sizeof(g_DmrSyncBSData)); - // slot type - { - // slot type - uint8 slottype[3]; - ::memset(slottype, 0, sizeof(slottype)); - slottype[0] = (DMRMMDVM_REFLECTOR_COLOUR << 4) & 0xF0; - slottype[0] |= (DMR_DT_VOICE_LC_HEADER << 0) & 0x0FU; - CGolay2087::encode(slottype); - payload[12U] = (payload[12U] & 0xC0U) | ((slottype[0U] >> 2) & 0x3FU); - payload[13U] = (payload[13U] & 0x0FU) | ((slottype[0U] << 6) & 0xC0U) | ((slottype[1U] >> 2) & 0x30U); - payload[19U] = (payload[19U] & 0xF0U) | ((slottype[1U] >> 2) & 0x0FU); - payload[20U] = (payload[20U] & 0x03U) | ((slottype[1U] << 6) & 0xC0U) | ((slottype[2U] >> 2) & 0x3CU); - - } - // and encode - bptc.encode(lc, payload); - - // and append - buffer->Append(payload, sizeof(payload)); + uint8 payload[33]; + + // fill payload + CBPTC19696 bptc; + ::memset(payload, 0, sizeof(payload)); + // LC data + uint8 lc[12]; + { + ::memset(lc, 0, sizeof(lc)); + // uiDstId = TG9 + lc[5] = 9; + // uiSrcId + lc[6] = (uint8)LOBYTE(HIWORD(uiSrcId)); + lc[7] = (uint8)HIBYTE(LOWORD(uiSrcId)); + lc[8] = (uint8)LOBYTE(LOWORD(uiSrcId)); + // parity + uint8 parity[4]; + CRS129::encode(lc, 9, parity); + lc[9] = parity[2] ^ DMR_VOICE_LC_HEADER_CRC_MASK; + lc[10] = parity[1] ^ DMR_VOICE_LC_HEADER_CRC_MASK; + lc[11] = parity[0] ^ DMR_VOICE_LC_HEADER_CRC_MASK; + } + // sync + ::memcpy(payload+13, g_DmrSyncBSData, sizeof(g_DmrSyncBSData)); + // slot type + { + // slot type + uint8 slottype[3]; + ::memset(slottype, 0, sizeof(slottype)); + slottype[0] = (DMRMMDVM_REFLECTOR_COLOUR << 4) & 0xF0; + slottype[0] |= (DMR_DT_VOICE_LC_HEADER << 0) & 0x0FU; + CGolay2087::encode(slottype); + payload[12U] = (payload[12U] & 0xC0U) | ((slottype[0U] >> 2) & 0x3FU); + payload[13U] = (payload[13U] & 0x0FU) | ((slottype[0U] << 6) & 0xC0U) | ((slottype[1U] >> 2) & 0x30U); + payload[19U] = (payload[19U] & 0xF0U) | ((slottype[1U] >> 2) & 0x0FU); + payload[20U] = (payload[20U] & 0x03U) | ((slottype[1U] << 6) & 0xC0U) | ((slottype[2U] >> 2) & 0x3CU); + + } + // and encode + bptc.encode(lc, payload); + + // and append + buffer->Append(payload, sizeof(payload)); } void CDmrmmdvmProtocol::AppendTerminatorLCToBuffer(CBuffer *buffer, uint32 uiSrcId) const { - uint8 payload[33]; - - // fill payload - CBPTC19696 bptc; - ::memset(payload, 0, sizeof(payload)); - // LC data - uint8 lc[12]; - { - ::memset(lc, 0, sizeof(lc)); - // uiDstId = TG9 - lc[5] = 9; - // uiSrcId - lc[6] = (uint8)LOBYTE(HIWORD(uiSrcId)); - lc[7] = (uint8)HIBYTE(LOWORD(uiSrcId)); - lc[8] = (uint8)LOBYTE(LOWORD(uiSrcId)); - // parity - uint8 parity[4]; - CRS129::encode(lc, 9, parity); - lc[9] = parity[2] ^ DMR_TERMINATOR_WITH_LC_CRC_MASK; - lc[10] = parity[1] ^ DMR_TERMINATOR_WITH_LC_CRC_MASK; - lc[11] = parity[0] ^ DMR_TERMINATOR_WITH_LC_CRC_MASK; - } - // sync - ::memcpy(payload+13, g_DmrSyncBSData, sizeof(g_DmrSyncBSData)); - // slot type - { - // slot type - uint8 slottype[3]; - ::memset(slottype, 0, sizeof(slottype)); - slottype[0] = (DMRMMDVM_REFLECTOR_COLOUR << 4) & 0xF0; - slottype[0] |= (DMR_DT_TERMINATOR_WITH_LC << 0) & 0x0FU; - CGolay2087::encode(slottype); - payload[12U] = (payload[12U] & 0xC0U) | ((slottype[0U] >> 2) & 0x3FU); - payload[13U] = (payload[13U] & 0x0FU) | ((slottype[0U] << 6) & 0xC0U) | ((slottype[1U] >> 2) & 0x30U); - payload[19U] = (payload[19U] & 0xF0U) | ((slottype[1U] >> 2) & 0x0FU); - payload[20U] = (payload[20U] & 0x03U) | ((slottype[1U] << 6) & 0xC0U) | ((slottype[2U] >> 2) & 0x3CU); - } - // and encode - bptc.encode(lc, payload); - - // and append - buffer->Append(payload, sizeof(payload)); + uint8 payload[33]; + + // fill payload + CBPTC19696 bptc; + ::memset(payload, 0, sizeof(payload)); + // LC data + uint8 lc[12]; + { + ::memset(lc, 0, sizeof(lc)); + // uiDstId = TG9 + lc[5] = 9; + // uiSrcId + lc[6] = (uint8)LOBYTE(HIWORD(uiSrcId)); + lc[7] = (uint8)HIBYTE(LOWORD(uiSrcId)); + lc[8] = (uint8)LOBYTE(LOWORD(uiSrcId)); + // parity + uint8 parity[4]; + CRS129::encode(lc, 9, parity); + lc[9] = parity[2] ^ DMR_TERMINATOR_WITH_LC_CRC_MASK; + lc[10] = parity[1] ^ DMR_TERMINATOR_WITH_LC_CRC_MASK; + lc[11] = parity[0] ^ DMR_TERMINATOR_WITH_LC_CRC_MASK; + } + // sync + ::memcpy(payload+13, g_DmrSyncBSData, sizeof(g_DmrSyncBSData)); + // slot type + { + // slot type + uint8 slottype[3]; + ::memset(slottype, 0, sizeof(slottype)); + slottype[0] = (DMRMMDVM_REFLECTOR_COLOUR << 4) & 0xF0; + slottype[0] |= (DMR_DT_TERMINATOR_WITH_LC << 0) & 0x0FU; + CGolay2087::encode(slottype); + payload[12U] = (payload[12U] & 0xC0U) | ((slottype[0U] >> 2) & 0x3FU); + payload[13U] = (payload[13U] & 0x0FU) | ((slottype[0U] << 6) & 0xC0U) | ((slottype[1U] >> 2) & 0x30U); + payload[19U] = (payload[19U] & 0xF0U) | ((slottype[1U] >> 2) & 0x0FU); + payload[20U] = (payload[20U] & 0x03U) | ((slottype[1U] << 6) & 0xC0U) | ((slottype[2U] >> 2) & 0x3CU); + } + // and encode + bptc.encode(lc, payload); + + // and append + buffer->Append(payload, sizeof(payload)); } void CDmrmmdvmProtocol::ReplaceEMBInBuffer(CBuffer *buffer, uint8 uiDmrPacketId) const { - // voice packet A ? - if ( uiDmrPacketId == 0 ) - { - // sync - buffer->ReplaceAt(33, (uint8)(buffer->at(33) | (g_DmrSyncBSVoice[0] & 0x0F))); - buffer->ReplaceAt(34, g_DmrSyncBSVoice+1, 5); - buffer->ReplaceAt(39, (uint8)(buffer->at(39) | (g_DmrSyncBSVoice[6] & 0xF0))); - } - // voice packet B,C,D,E ? - else if ( (uiDmrPacketId >= 1) && (uiDmrPacketId <= 4 ) ) - { - // EMB LC - uint8 emb[2]; - emb[0] = (DMRMMDVM_REFLECTOR_COLOUR << 4) & 0xF0; - //emb[0] |= PI ? 0x08U : 0x00; - //emb[0] |= (LCSS << 1) & 0x06; - emb[1] = 0x00; - // encode - CQR1676::encode(emb); - // and append - buffer->ReplaceAt(33, (uint8)((buffer->at(33) & 0xF0) | ((emb[0U] >> 4) & 0x0F))); - buffer->ReplaceAt(34, (uint8)((buffer->at(34) & 0x0F) | ((emb[0U] << 4) & 0xF0))); - buffer->ReplaceAt(34, (uint8)(buffer->at(34) & 0xF0)); - buffer->ReplaceAt(35, (uint8)0); - buffer->ReplaceAt(36, (uint8)0); - buffer->ReplaceAt(37, (uint8)0); - buffer->ReplaceAt(38, (uint8)(buffer->at(38) & 0x0F)); - buffer->ReplaceAt(38, (uint8)((buffer->at(38) & 0xF0) | ((emb[1U] >> 4) & 0x0F))); - buffer->ReplaceAt(39, (uint8)((buffer->at(39) & 0x0F) | ((emb[1U] << 4) & 0xF0))); - } - // voice packet F - else - { - // nullptr - uint8 emb[2]; - emb[0] = (DMRMMDVM_REFLECTOR_COLOUR << 4) & 0xF0; - //emb[0] |= PI ? 0x08U : 0x00; - //emb[0] |= (LCSS << 1) & 0x06; - emb[1] = 0x00; - // encode - CQR1676::encode(emb); - // and append - buffer->ReplaceAt(33, (uint8)((buffer->at(33) & 0xF0) | ((emb[0U] >> 4) & 0x0F))); - buffer->ReplaceAt(34, (uint8)((buffer->at(34) & 0x0F) | ((emb[0U] << 4) & 0xF0))); - buffer->ReplaceAt(34, (uint8)(buffer->at(34) & 0xF0)); - buffer->ReplaceAt(35, (uint8)0); - buffer->ReplaceAt(36, (uint8)0); - buffer->ReplaceAt(37, (uint8)0); - buffer->ReplaceAt(38, (uint8)(buffer->at(38) & 0x0F)); - buffer->ReplaceAt(38, (uint8)((buffer->at(38) & 0xF0) | ((emb[1U] >> 4) & 0x0F))); - buffer->ReplaceAt(39, (uint8)((buffer->at(39) & 0x0F) | ((emb[1U] << 4) & 0xF0))); - } + // voice packet A ? + if ( uiDmrPacketId == 0 ) + { + // sync + buffer->ReplaceAt(33, (uint8)(buffer->at(33) | (g_DmrSyncBSVoice[0] & 0x0F))); + buffer->ReplaceAt(34, g_DmrSyncBSVoice+1, 5); + buffer->ReplaceAt(39, (uint8)(buffer->at(39) | (g_DmrSyncBSVoice[6] & 0xF0))); + } + // voice packet B,C,D,E ? + else if ( (uiDmrPacketId >= 1) && (uiDmrPacketId <= 4 ) ) + { + // EMB LC + uint8 emb[2]; + emb[0] = (DMRMMDVM_REFLECTOR_COLOUR << 4) & 0xF0; + //emb[0] |= PI ? 0x08U : 0x00; + //emb[0] |= (LCSS << 1) & 0x06; + emb[1] = 0x00; + // encode + CQR1676::encode(emb); + // and append + buffer->ReplaceAt(33, (uint8)((buffer->at(33) & 0xF0) | ((emb[0U] >> 4) & 0x0F))); + buffer->ReplaceAt(34, (uint8)((buffer->at(34) & 0x0F) | ((emb[0U] << 4) & 0xF0))); + buffer->ReplaceAt(34, (uint8)(buffer->at(34) & 0xF0)); + buffer->ReplaceAt(35, (uint8)0); + buffer->ReplaceAt(36, (uint8)0); + buffer->ReplaceAt(37, (uint8)0); + buffer->ReplaceAt(38, (uint8)(buffer->at(38) & 0x0F)); + buffer->ReplaceAt(38, (uint8)((buffer->at(38) & 0xF0) | ((emb[1U] >> 4) & 0x0F))); + buffer->ReplaceAt(39, (uint8)((buffer->at(39) & 0x0F) | ((emb[1U] << 4) & 0xF0))); + } + // voice packet F + else + { + // nullptr + uint8 emb[2]; + emb[0] = (DMRMMDVM_REFLECTOR_COLOUR << 4) & 0xF0; + //emb[0] |= PI ? 0x08U : 0x00; + //emb[0] |= (LCSS << 1) & 0x06; + emb[1] = 0x00; + // encode + CQR1676::encode(emb); + // and append + buffer->ReplaceAt(33, (uint8)((buffer->at(33) & 0xF0) | ((emb[0U] >> 4) & 0x0F))); + buffer->ReplaceAt(34, (uint8)((buffer->at(34) & 0x0F) | ((emb[0U] << 4) & 0xF0))); + buffer->ReplaceAt(34, (uint8)(buffer->at(34) & 0xF0)); + buffer->ReplaceAt(35, (uint8)0); + buffer->ReplaceAt(36, (uint8)0); + buffer->ReplaceAt(37, (uint8)0); + buffer->ReplaceAt(38, (uint8)(buffer->at(38) & 0x0F)); + buffer->ReplaceAt(38, (uint8)((buffer->at(38) & 0xF0) | ((emb[1U] >> 4) & 0x0F))); + buffer->ReplaceAt(39, (uint8)((buffer->at(39) & 0x0F) | ((emb[1U] << 4) & 0xF0))); + } } void CDmrmmdvmProtocol::AppendDmrIdToBuffer(CBuffer *buffer, uint32 id) const { - buffer->Append((uint8)LOBYTE(HIWORD(id))); - buffer->Append((uint8)HIBYTE(LOWORD(id))); - buffer->Append((uint8)LOBYTE(LOWORD(id))); + buffer->Append((uint8)LOBYTE(HIWORD(id))); + buffer->Append((uint8)HIBYTE(LOWORD(id))); + buffer->Append((uint8)LOBYTE(LOWORD(id))); } void CDmrmmdvmProtocol::AppendDmrRptrIdToBuffer(CBuffer *buffer, uint32 id) const { - buffer->Append((uint8)HIBYTE(HIWORD(id))); - buffer->Append((uint8)LOBYTE(HIWORD(id))); - buffer->Append((uint8)HIBYTE(LOWORD(id))); - buffer->Append((uint8)LOBYTE(LOWORD(id))); + buffer->Append((uint8)HIBYTE(HIWORD(id))); + buffer->Append((uint8)LOBYTE(HIWORD(id))); + buffer->Append((uint8)HIBYTE(LOWORD(id))); + buffer->Append((uint8)LOBYTE(LOWORD(id))); } diff --git a/src/cdmrmmdvmprotocol.h b/src/cdmrmmdvmprotocol.h index a20bbe0..8b63a28 100644 --- a/src/cdmrmmdvmprotocol.h +++ b/src/cdmrmmdvmprotocol.h @@ -52,82 +52,82 @@ class CDmrmmdvmStreamCacheItem { public: - CDmrmmdvmStreamCacheItem() {} - ~CDmrmmdvmStreamCacheItem() {} + CDmrmmdvmStreamCacheItem() {} + ~CDmrmmdvmStreamCacheItem() {} - CDvHeaderPacket m_dvHeader; - CDvFramePacket m_dvFrame0; - CDvFramePacket m_dvFrame1; + CDvHeaderPacket m_dvHeader; + CDvFramePacket m_dvFrame0; + CDvFramePacket m_dvFrame1; - uint8 m_uiSeqId; + uint8 m_uiSeqId; }; class CDmrmmdvmProtocol : public CProtocol { public: - // initialization - bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); + // initialization + bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); - // task - void Task(void); + // task + void Task(void); protected: - // queue helper - void HandleQueue(void); - - // keepalive helpers - void HandleKeepalives(void); - - // stream helpers - bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &, uint8, uint8); - - // packet decoding helpers - bool IsValidConnectPacket(const CBuffer &, CCallsign *, const CIp &); - bool IsValidAuthenticationPacket(const CBuffer &, CCallsign *, const CIp &); - bool IsValidDisconnectPacket(const CBuffer &, CCallsign *); - bool IsValidConfigPacket(const CBuffer &, CCallsign *, const CIp &); - bool IsValidOptionPacket(const CBuffer &, CCallsign *); - bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); - bool IsValidRssiPacket(const CBuffer &, CCallsign *, int *); - bool IsValidDvHeaderPacket(const CBuffer &, CDvHeaderPacket **, uint8 *, uint8 *); - bool IsValidDvFramePacket(const CBuffer &, CDvFramePacket **); - bool IsValidDvLastFramePacket(const CBuffer &, CDvLastFramePacket **); - - // packet encoding helpers - void EncodeKeepAlivePacket(CBuffer *, std::shared_ptr); - void EncodeAckPacket(CBuffer *, const CCallsign &); - void EncodeConnectAckPacket(CBuffer *, const CCallsign &, uint32); - void EncodeNackPacket(CBuffer *, const CCallsign &); - void EncodeClosePacket(CBuffer *, std::shared_ptr); - bool EncodeDvHeaderPacket(const CDvHeaderPacket &, uint8, CBuffer *) const; - void EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket &, const CDvFramePacket &, const CDvFramePacket &, uint8, CBuffer *) const; - void EncodeDvLastPacket(const CDvHeaderPacket &, uint8, CBuffer *) const; - - // dmr DstId to Module helper - char DmrDstIdToModule(uint32) const; - uint32 ModuleToDmrDestId(char) const; - - // Buffer & LC helpers - void AppendVoiceLCToBuffer(CBuffer *, uint32) const; - void AppendTerminatorLCToBuffer(CBuffer *, uint32) const; - void ReplaceEMBInBuffer(CBuffer *, uint8) const; - void AppendDmrIdToBuffer(CBuffer *, uint32) const; - void AppendDmrRptrIdToBuffer(CBuffer *, uint32) const; + // queue helper + void HandleQueue(void); + + // keepalive helpers + void HandleKeepalives(void); + + // stream helpers + bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &, uint8, uint8); + + // packet decoding helpers + bool IsValidConnectPacket(const CBuffer &, CCallsign *, const CIp &); + bool IsValidAuthenticationPacket(const CBuffer &, CCallsign *, const CIp &); + bool IsValidDisconnectPacket(const CBuffer &, CCallsign *); + bool IsValidConfigPacket(const CBuffer &, CCallsign *, const CIp &); + bool IsValidOptionPacket(const CBuffer &, CCallsign *); + bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); + bool IsValidRssiPacket(const CBuffer &, CCallsign *, int *); + bool IsValidDvHeaderPacket(const CBuffer &, CDvHeaderPacket **, uint8 *, uint8 *); + bool IsValidDvFramePacket(const CBuffer &, CDvFramePacket **); + bool IsValidDvLastFramePacket(const CBuffer &, CDvLastFramePacket **); + + // packet encoding helpers + void EncodeKeepAlivePacket(CBuffer *, std::shared_ptr); + void EncodeAckPacket(CBuffer *, const CCallsign &); + void EncodeConnectAckPacket(CBuffer *, const CCallsign &, uint32); + void EncodeNackPacket(CBuffer *, const CCallsign &); + void EncodeClosePacket(CBuffer *, std::shared_ptr); + bool EncodeDvHeaderPacket(const CDvHeaderPacket &, uint8, CBuffer *) const; + void EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket &, const CDvFramePacket &, const CDvFramePacket &, uint8, CBuffer *) const; + void EncodeDvLastPacket(const CDvHeaderPacket &, uint8, CBuffer *) const; + + // dmr DstId to Module helper + char DmrDstIdToModule(uint32) const; + uint32 ModuleToDmrDestId(char) const; + + // Buffer & LC helpers + void AppendVoiceLCToBuffer(CBuffer *, uint32) const; + void AppendTerminatorLCToBuffer(CBuffer *, uint32) const; + void ReplaceEMBInBuffer(CBuffer *, uint8) const; + void AppendDmrIdToBuffer(CBuffer *, uint32) const; + void AppendDmrRptrIdToBuffer(CBuffer *, uint32) const; protected: - // for keep alive - CTimePoint m_LastKeepaliveTime; + // for keep alive + CTimePoint m_LastKeepaliveTime; - // for stream id - uint16 m_uiStreamId; + // for stream id + uint16 m_uiStreamId; - // for queue header caches - std::array m_StreamsCache; + // for queue header caches + std::array m_StreamsCache; - // for authentication - uint32 m_uiAuthSeed; + // for authentication + uint32 m_uiAuthSeed; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cdmrplusclient.cpp b/src/cdmrplusclient.cpp index 7f457d1..efeda32 100644 --- a/src/cdmrplusclient.cpp +++ b/src/cdmrplusclient.cpp @@ -34,12 +34,12 @@ CDmrplusClient::CDmrplusClient() } CDmrplusClient::CDmrplusClient(const CCallsign &callsign, const CIp &ip, char reflectorModule) -: CClient(callsign, ip, reflectorModule) + : CClient(callsign, ip, reflectorModule) { } CDmrplusClient::CDmrplusClient(const CDmrplusClient &client) -: CClient(client) + : CClient(client) { } @@ -48,5 +48,5 @@ CDmrplusClient::CDmrplusClient(const CDmrplusClient &client) bool CDmrplusClient::IsAlive(void) const { - return (m_LastKeepaliveTime.DurationSinceNow() < DMRPLUS_KEEPALIVE_TIMEOUT); + return (m_LastKeepaliveTime.DurationSinceNow() < DMRPLUS_KEEPALIVE_TIMEOUT); } diff --git a/src/cdmrplusclient.h b/src/cdmrplusclient.h index 628b2a4..5b40742 100644 --- a/src/cdmrplusclient.h +++ b/src/cdmrplusclient.h @@ -37,22 +37,22 @@ class CDmrplusClient : public CClient { public: - // constructors - CDmrplusClient(); - CDmrplusClient(const CCallsign &, const CIp &, char = ' '); - CDmrplusClient(const CDmrplusClient &); - - // destructor - virtual ~CDmrplusClient() {}; - - // identity - int GetProtocol(void) const { return PROTOCOL_DMRPLUS; } - const char *GetProtocolName(void) const { return "DMRplus"; } - int GetCodec(void) const { return CODEC_AMBE2PLUS; } - bool IsNode(void) const { return true; } - - // status - bool IsAlive(void) const; + // constructors + CDmrplusClient(); + CDmrplusClient(const CCallsign &, const CIp &, char = ' '); + CDmrplusClient(const CDmrplusClient &); + + // destructor + virtual ~CDmrplusClient() {}; + + // identity + int GetProtocol(void) const { return PROTOCOL_DMRPLUS; } + const char *GetProtocolName(void) const { return "DMRplus"; } + int GetCodec(void) const { return CODEC_AMBE2PLUS; } + bool IsNode(void) const { return true; } + + // status + bool IsAlive(void) const; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cdmrplusprotocol.cpp b/src/cdmrplusprotocol.cpp index 2c3c809..1113c89 100644 --- a/src/cdmrplusprotocol.cpp +++ b/src/cdmrplusprotocol.cpp @@ -49,19 +49,19 @@ static uint8 g_DmrSyncMSData[] = { 0x0D,0x5D,0x7F,0x77,0xFD,0x75,0x70 }; bool CDmrplusProtocol::Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6) { - // base class - if (! CProtocol::Initialize(type, port, has_ipv4, has_ipv6)) + // base class + if (! CProtocol::Initialize(type, port, has_ipv4, has_ipv6)) return false; - // update time - m_LastKeepaliveTime.Now(); + // update time + m_LastKeepaliveTime.Now(); - // random number generator - time_t t; - ::srand((unsigned) time(&t)); + // random number generator + time_t t; + ::srand((unsigned) time(&t)); - // done - return true; + // done + return true; } @@ -71,14 +71,14 @@ bool CDmrplusProtocol::Initalize(const char *type, const uint16 port, const bool void CDmrplusProtocol::Task(void) { - CBuffer Buffer; - CIp Ip; - CCallsign Callsign; - char ToLinkModule; - CDvHeaderPacket *Header; - CDvFramePacket *Frames[3]; - - // handle incoming packets + CBuffer Buffer; + CIp Ip; + CCallsign Callsign; + char ToLinkModule; + CDvHeaderPacket *Header; + CDvFramePacket *Frames[3]; + + // handle incoming packets #if DMR_IPV6==true #if DMR_IPV4==true if ( ReceiveDS(Buffer, Ip, 20) ) @@ -88,117 +88,117 @@ void CDmrplusProtocol::Task(void) #else if ( Receive4(Buffer, Ip, 20) ) #endif - { - // crack the packet - if ( IsValidDvFramePacket(Ip, Buffer, Frames) ) - { - //std::cout << "DMRplus DV frame" << std::endl; - //Buffer.DebugDump(g_Reflector.m_DebugFile); - - for ( int i = 0; i < 3; i++ ) - { - OnDvFramePacketIn(Frames[i], &Ip); - /*if ( !Frames[i]->IsLastPacket() ) - { - //std::cout << "DMRplus DV frame" << std::endl; - OnDvFramePacketIn(Frames[i], &Ip); - } - else - { - //std::cout << "DMRplus DV last frame" << std::endl; - OnDvLastFramePacketIn((CDvLastFramePacket *)Frames[i], &Ip); - }*/ - } - } - else if ( IsValidDvHeaderPacket(Ip, Buffer, &Header) ) - { - //std::cout << "DMRplus DV header:" << std::endl; - //std::cout << "DMRplus DV header:" << std::endl << *Header << std::endl; - //Buffer.DebugDump(g_Reflector.m_DebugFile); - - // callsign muted? - if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_DMRPLUS) ) - { - // handle it - OnDvHeaderPacketIn(Header, Ip); - } - else - { - delete Header; - } - } - else if ( IsValidConnectPacket(Buffer, &Callsign, &ToLinkModule, Ip) ) - { - //std::cout << "DMRplus keepalive/connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl; - - // callsign authorized? - if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_DMRPLUS) ) - { - // acknowledge the request - EncodeConnectAckPacket(&Buffer); - Send(Buffer, Ip); - - // add client if needed - CClients *clients = g_Reflector.GetClients(); - std::shared_ptrclient = clients->FindClient(Callsign, Ip, PROTOCOL_DMRPLUS); - // client already connected ? - if ( client == nullptr ) - { - std::cout << "DMRplus connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl; - - // create the client and append - clients->AddClient(std::make_shared(Callsign, Ip, ToLinkModule)); - } - else - { - client->Alive(); - } - // and done - g_Reflector.ReleaseClients(); - } - else - { - // deny the request - EncodeConnectNackPacket(&Buffer); - Send(Buffer, Ip); - } - - } - else if ( IsValidDisconnectPacket(Buffer, &Callsign, &ToLinkModule) ) - { - std::cout << "DMRplus disconnect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl; - - // find client & remove it - CClients *clients = g_Reflector.GetClients(); - std::shared_ptrclient = clients->FindClient(Ip, PROTOCOL_DMRPLUS); - if ( client != nullptr ) - { - clients->RemoveClient(client); - } - g_Reflector.ReleaseClients(); - } - else - { - //std::cout << "DMRPlus packet (" << Buffer.size() << ")" << " at " << Ip << std::endl; - } - } - - // handle end of streaming timeout - CheckStreamsTimeout(); - - // handle queue from reflector - HandleQueue(); - - - // keep client alive - if ( m_LastKeepaliveTime.DurationSinceNow() > DMRPLUS_KEEPALIVE_PERIOD ) - { - // - HandleKeepalives(); - - // update time - m_LastKeepaliveTime.Now(); - } + { + // crack the packet + if ( IsValidDvFramePacket(Ip, Buffer, Frames) ) + { + //std::cout << "DMRplus DV frame" << std::endl; + //Buffer.DebugDump(g_Reflector.m_DebugFile); + + for ( int i = 0; i < 3; i++ ) + { + OnDvFramePacketIn(Frames[i], &Ip); + /*if ( !Frames[i]->IsLastPacket() ) + { + //std::cout << "DMRplus DV frame" << std::endl; + OnDvFramePacketIn(Frames[i], &Ip); + } + else + { + //std::cout << "DMRplus DV last frame" << std::endl; + OnDvLastFramePacketIn((CDvLastFramePacket *)Frames[i], &Ip); + }*/ + } + } + else if ( IsValidDvHeaderPacket(Ip, Buffer, &Header) ) + { + //std::cout << "DMRplus DV header:" << std::endl; + //std::cout << "DMRplus DV header:" << std::endl << *Header << std::endl; + //Buffer.DebugDump(g_Reflector.m_DebugFile); + + // callsign muted? + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_DMRPLUS) ) + { + // handle it + OnDvHeaderPacketIn(Header, Ip); + } + else + { + delete Header; + } + } + else if ( IsValidConnectPacket(Buffer, &Callsign, &ToLinkModule, Ip) ) + { + //std::cout << "DMRplus keepalive/connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl; + + // callsign authorized? + if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_DMRPLUS) ) + { + // acknowledge the request + EncodeConnectAckPacket(&Buffer); + Send(Buffer, Ip); + + // add client if needed + CClients *clients = g_Reflector.GetClients(); + std::shared_ptrclient = clients->FindClient(Callsign, Ip, PROTOCOL_DMRPLUS); + // client already connected ? + if ( client == nullptr ) + { + std::cout << "DMRplus connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl; + + // create the client and append + clients->AddClient(std::make_shared(Callsign, Ip, ToLinkModule)); + } + else + { + client->Alive(); + } + // and done + g_Reflector.ReleaseClients(); + } + else + { + // deny the request + EncodeConnectNackPacket(&Buffer); + Send(Buffer, Ip); + } + + } + else if ( IsValidDisconnectPacket(Buffer, &Callsign, &ToLinkModule) ) + { + std::cout << "DMRplus disconnect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl; + + // find client & remove it + CClients *clients = g_Reflector.GetClients(); + std::shared_ptrclient = clients->FindClient(Ip, PROTOCOL_DMRPLUS); + if ( client != nullptr ) + { + clients->RemoveClient(client); + } + g_Reflector.ReleaseClients(); + } + else + { + //std::cout << "DMRPlus packet (" << Buffer.size() << ")" << " at " << Ip << std::endl; + } + } + + // handle end of streaming timeout + CheckStreamsTimeout(); + + // handle queue from reflector + HandleQueue(); + + + // keep client alive + if ( m_LastKeepaliveTime.DurationSinceNow() > DMRPLUS_KEEPALIVE_PERIOD ) + { + // + HandleKeepalives(); + + // update time + m_LastKeepaliveTime.Now(); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -206,50 +206,50 @@ void CDmrplusProtocol::Task(void) bool CDmrplusProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip) { - bool newstream = false; - - // find the stream - CPacketStream *stream = GetStream(Header->GetStreamId()); - if ( stream == nullptr ) - { - // no stream open yet, open a new one - // find this client - std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_DMRPLUS); - if ( client != nullptr ) - { - // and try to open the stream - if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) - { - // keep the handle - m_Streams.push_back(stream); - newstream = true; - } - } - // release - g_Reflector.ReleaseClients(); - } - else - { - // stream already open - // skip packet, but tickle the stream - stream->Tickle(); - // and delete packet - delete Header; - } - - // update last heard - g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), Header->GetRpt1Callsign(), Header->GetRpt2Callsign()); - g_Reflector.ReleaseUsers(); - - // delete header if needed - if ( !newstream ) - { - delete Header; - } - - - // done - return newstream; + bool newstream = false; + + // find the stream + CPacketStream *stream = GetStream(Header->GetStreamId()); + if ( stream == nullptr ) + { + // no stream open yet, open a new one + // find this client + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_DMRPLUS); + if ( client != nullptr ) + { + // and try to open the stream + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) + { + // keep the handle + m_Streams.push_back(stream); + newstream = true; + } + } + // release + g_Reflector.ReleaseClients(); + } + else + { + // stream already open + // skip packet, but tickle the stream + stream->Tickle(); + // and delete packet + delete Header; + } + + // update last heard + g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), Header->GetRpt1Callsign(), Header->GetRpt2Callsign()); + g_Reflector.ReleaseUsers(); + + // delete header if needed + if ( !newstream ) + { + delete Header; + } + + + // done + return newstream; } //////////////////////////////////////////////////////////////////////////////////////// @@ -258,107 +258,107 @@ bool CDmrplusProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip void CDmrplusProtocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) - { - // get the packet - CPacket *packet = m_Queue.front(); - m_Queue.pop(); - - // get our sender's id - int iModId = g_Reflector.GetModuleIndex(packet->GetModuleId()); - - // encode - CBuffer buffer; - - // check if it's header - if ( packet->IsDvHeader() ) - { - // update local stream cache - // this relies on queue feeder setting valid module id - m_StreamsCache[iModId].m_dvHeader = CDvHeaderPacket((const CDvHeaderPacket &)*packet); - m_StreamsCache[iModId].m_uiSeqId = 4; - - // encode it - EncodeDvHeaderPacket((const CDvHeaderPacket &)*packet, &buffer); - } - else - { - // update local stream cache or send triplet when needed - switch ( packet->GetDmrPacketSubid() ) - { - case 1: - m_StreamsCache[iModId].m_dvFrame0 = CDvFramePacket((const CDvFramePacket &)*packet); - break; - case 2: - m_StreamsCache[iModId].m_dvFrame1 = CDvFramePacket((const CDvFramePacket &)*packet); - break; - case 3: - EncodeDvPacket( - m_StreamsCache[iModId].m_dvHeader, - m_StreamsCache[iModId].m_dvFrame0, - m_StreamsCache[iModId].m_dvFrame1, - (const CDvFramePacket &)*packet, - m_StreamsCache[iModId].m_uiSeqId, - &buffer); - m_StreamsCache[iModId].m_uiSeqId = GetNextSeqId(m_StreamsCache[iModId].m_uiSeqId); - break; - default: - break; - } - - } - - // send it - if ( buffer.size() > 0 ) - { - // and push it to all our clients linked to the module and who are not streaming in - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_DMRPLUS, it)) != nullptr ) - { - // is this client busy ? - if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) ) - { - // no, send the packet - Send(buffer, client->GetIp()); - } - } - g_Reflector.ReleaseClients(); - - // debug - //buffer.DebugDump(g_Reflector.m_DebugFile); - } - - // done - delete packet; - } - m_Queue.Unlock(); + m_Queue.Lock(); + while ( !m_Queue.empty() ) + { + // get the packet + CPacket *packet = m_Queue.front(); + m_Queue.pop(); + + // get our sender's id + int iModId = g_Reflector.GetModuleIndex(packet->GetModuleId()); + + // encode + CBuffer buffer; + + // check if it's header + if ( packet->IsDvHeader() ) + { + // update local stream cache + // this relies on queue feeder setting valid module id + m_StreamsCache[iModId].m_dvHeader = CDvHeaderPacket((const CDvHeaderPacket &)*packet); + m_StreamsCache[iModId].m_uiSeqId = 4; + + // encode it + EncodeDvHeaderPacket((const CDvHeaderPacket &)*packet, &buffer); + } + else + { + // update local stream cache or send triplet when needed + switch ( packet->GetDmrPacketSubid() ) + { + case 1: + m_StreamsCache[iModId].m_dvFrame0 = CDvFramePacket((const CDvFramePacket &)*packet); + break; + case 2: + m_StreamsCache[iModId].m_dvFrame1 = CDvFramePacket((const CDvFramePacket &)*packet); + break; + case 3: + EncodeDvPacket( + m_StreamsCache[iModId].m_dvHeader, + m_StreamsCache[iModId].m_dvFrame0, + m_StreamsCache[iModId].m_dvFrame1, + (const CDvFramePacket &)*packet, + m_StreamsCache[iModId].m_uiSeqId, + &buffer); + m_StreamsCache[iModId].m_uiSeqId = GetNextSeqId(m_StreamsCache[iModId].m_uiSeqId); + break; + default: + break; + } + + } + + // send it + if ( buffer.size() > 0 ) + { + // and push it to all our clients linked to the module and who are not streaming in + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_DMRPLUS, it)) != nullptr ) + { + // is this client busy ? + if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) ) + { + // no, send the packet + Send(buffer, client->GetIp()); + } + } + g_Reflector.ReleaseClients(); + + // debug + //buffer.DebugDump(g_Reflector.m_DebugFile); + } + + // done + delete packet; + } + m_Queue.Unlock(); } void CDmrplusProtocol::SendBufferToClients(const CBuffer &buffer, uint8 module) { - if ( buffer.size() > 0 ) - { - // and push it to all our clients linked to the module and who are not streaming in - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_DMRPLUS, it)) != nullptr ) - { - // is this client busy ? - if ( !client->IsAMaster() && (client->GetReflectorModule() == module) ) - { - // no, send the packet - Send(buffer, client->GetIp()); - } - } - g_Reflector.ReleaseClients(); - - // debug - //buffer.DebugDump(g_Reflector.m_DebugFile); - } + if ( buffer.size() > 0 ) + { + // and push it to all our clients linked to the module and who are not streaming in + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_DMRPLUS, it)) != nullptr ) + { + // is this client busy ? + if ( !client->IsAMaster() && (client->GetReflectorModule() == module) ) + { + // no, send the packet + Send(buffer, client->GetIp()); + } + } + g_Reflector.ReleaseClients(); + + // debug + //buffer.DebugDump(g_Reflector.m_DebugFile); + } } @@ -367,37 +367,37 @@ void CDmrplusProtocol::SendBufferToClients(const CBuffer &buffer, uint8 module) void CDmrplusProtocol::HandleKeepalives(void) { - // DMRplus protocol keepalive request is client tasks - // here, just check that all clients are still alive - // and disconnect them if not - - // iterate on clients - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_DMRPLUS, it)) != nullptr ) - { - // is this client busy ? - if ( client->IsAMaster() ) - { - // yes, just tickle it - client->Alive(); - } - // check it's still with us - else if ( !client->IsAlive() ) - { - // no, disconnect - //CBuffer disconnect; - //EncodeDisconnectPacket(&disconnect, client); - //Send(disconnect, client->GetIp()); - - // remove it - std::cout << "DMRplus client " << client->GetCallsign() << " keepalive timeout" << std::endl; - clients->RemoveClient(client); - } - - } - g_Reflector.ReleaseClients(); + // DMRplus protocol keepalive request is client tasks + // here, just check that all clients are still alive + // and disconnect them if not + + // iterate on clients + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_DMRPLUS, it)) != nullptr ) + { + // is this client busy ? + if ( client->IsAMaster() ) + { + // yes, just tickle it + client->Alive(); + } + // check it's still with us + else if ( !client->IsAlive() ) + { + // no, disconnect + //CBuffer disconnect; + //EncodeDisconnectPacket(&disconnect, client); + //Send(disconnect, client->GetIp()); + + // remove it + std::cout << "DMRplus client " << client->GetCallsign() << " keepalive timeout" << std::endl; + clients->RemoveClient(client); + } + + } + g_Reflector.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -405,155 +405,155 @@ void CDmrplusProtocol::HandleKeepalives(void) bool CDmrplusProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsign, char *reflectormodule, const CIp &Ip) { - bool valid = false; - if ( Buffer.size() == 31 ) - { - char sz[9]; - ::memcpy(sz, Buffer.data(), 8); - sz[8] = 0; - uint32 dmrid = atoi(sz); - callsign->SetDmrid(dmrid, true); - callsign->SetModule(DMRPLUS_MODULE_ID); - ::memcpy(sz, &Buffer.data()[8], 4); - sz[4] = 0; - *reflectormodule = DmrDstIdToModule(atoi(sz)); - valid = (callsign->IsValid() && (std::isupper(*reflectormodule) || (*reflectormodule == ' ')) ); - if ( !valid) - { - std::cout << "DMRplus connect packet from IP address " << Ip << " / unrecognized id " << (int)callsign->GetDmrid() << std::endl; - } - } - return valid; + bool valid = false; + if ( Buffer.size() == 31 ) + { + char sz[9]; + ::memcpy(sz, Buffer.data(), 8); + sz[8] = 0; + uint32 dmrid = atoi(sz); + callsign->SetDmrid(dmrid, true); + callsign->SetModule(DMRPLUS_MODULE_ID); + ::memcpy(sz, &Buffer.data()[8], 4); + sz[4] = 0; + *reflectormodule = DmrDstIdToModule(atoi(sz)); + valid = (callsign->IsValid() && (std::isupper(*reflectormodule) || (*reflectormodule == ' ')) ); + if ( !valid) + { + std::cout << "DMRplus connect packet from IP address " << Ip << " / unrecognized id " << (int)callsign->GetDmrid() << std::endl; + } + } + return valid; } bool CDmrplusProtocol::IsValidDisconnectPacket(const CBuffer &Buffer, CCallsign *callsign, char *reflectormodule) { - bool valid = false; - if ( Buffer.size() == 32 ) - { - char sz[9]; - ::memcpy(sz, Buffer.data(), 8); - sz[8] = 0; - uint32 dmrid = atoi(sz); - callsign->SetDmrid(dmrid, true); - callsign->SetModule(DMRPLUS_MODULE_ID); - *reflectormodule = Buffer.data()[11] - '0' + 'A'; - valid = (callsign->IsValid() && std::isupper(*reflectormodule)); - } - return valid; + bool valid = false; + if ( Buffer.size() == 32 ) + { + char sz[9]; + ::memcpy(sz, Buffer.data(), 8); + sz[8] = 0; + uint32 dmrid = atoi(sz); + callsign->SetDmrid(dmrid, true); + callsign->SetModule(DMRPLUS_MODULE_ID); + *reflectormodule = Buffer.data()[11] - '0' + 'A'; + valid = (callsign->IsValid() && std::isupper(*reflectormodule)); + } + return valid; } bool CDmrplusProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CBuffer &Buffer, CDvHeaderPacket **Header) { - bool valid = false; - *Header = nullptr; - - uint8 uiPacketType = Buffer.data()[8]; - if ( (Buffer.size() == 72) && ( uiPacketType == 2 ) ) - { - // frame details - uint8 uiSlot = (Buffer.data()[16] == 0x22) ? DMR_SLOT2 : DMR_SLOT1; - uint8 uiCallType = (Buffer.data()[62] == 1) ? DMR_GROUP_CALL : DMR_PRIVATE_CALL; - uint8 uiColourCode = Buffer.data()[20] & 0x0F; - if ( (uiSlot == DMRPLUS_REFLECTOR_SLOT) && (uiCallType == DMR_GROUP_CALL) && (uiColourCode == DMRPLUS_REFLECTOR_COLOUR) ) - { - // more frames details - //uint8 uiSeqId = Buffer.data()[4]; - //uint8 uiVoiceSeq = (Buffer.data()[18] & 0x0F) - 7; // aka slot type - uint32 uiDstId = *(uint32 *)(&Buffer.data()[64]) & 0x00FFFFFF; - uint32 uiSrcId = *(uint32 *)(&Buffer.data()[68]) & 0x00FFFFFF; - - // build DVHeader - CCallsign csMY = CCallsign("", uiSrcId); - CCallsign rpt1 = CCallsign("", uiSrcId); - rpt1.SetModule(DMRPLUS_MODULE_ID); - CCallsign rpt2 = m_ReflectorCallsign; - rpt2.SetModule(DmrDstIdToModule(uiDstId)); - uint32 uiStreamId = IpToStreamId(Ip); - - // and packet - *Header = new CDvHeaderPacket(uiSrcId, CCallsign("CQCQCQ"), rpt1, rpt2, uiStreamId, 0, 0); - valid = (*Header)->IsValid(); - if ( !valid ) - { - delete *Header; - *Header = nullptr; - } - } - } - // done - return valid; + bool valid = false; + *Header = nullptr; + + uint8 uiPacketType = Buffer.data()[8]; + if ( (Buffer.size() == 72) && ( uiPacketType == 2 ) ) + { + // frame details + uint8 uiSlot = (Buffer.data()[16] == 0x22) ? DMR_SLOT2 : DMR_SLOT1; + uint8 uiCallType = (Buffer.data()[62] == 1) ? DMR_GROUP_CALL : DMR_PRIVATE_CALL; + uint8 uiColourCode = Buffer.data()[20] & 0x0F; + if ( (uiSlot == DMRPLUS_REFLECTOR_SLOT) && (uiCallType == DMR_GROUP_CALL) && (uiColourCode == DMRPLUS_REFLECTOR_COLOUR) ) + { + // more frames details + //uint8 uiSeqId = Buffer.data()[4]; + //uint8 uiVoiceSeq = (Buffer.data()[18] & 0x0F) - 7; // aka slot type + uint32 uiDstId = *(uint32 *)(&Buffer.data()[64]) & 0x00FFFFFF; + uint32 uiSrcId = *(uint32 *)(&Buffer.data()[68]) & 0x00FFFFFF; + + // build DVHeader + CCallsign csMY = CCallsign("", uiSrcId); + CCallsign rpt1 = CCallsign("", uiSrcId); + rpt1.SetModule(DMRPLUS_MODULE_ID); + CCallsign rpt2 = m_ReflectorCallsign; + rpt2.SetModule(DmrDstIdToModule(uiDstId)); + uint32 uiStreamId = IpToStreamId(Ip); + + // and packet + *Header = new CDvHeaderPacket(uiSrcId, CCallsign("CQCQCQ"), rpt1, rpt2, uiStreamId, 0, 0); + valid = (*Header)->IsValid(); + if ( !valid ) + { + delete *Header; + *Header = nullptr; + } + } + } + // done + return valid; } bool CDmrplusProtocol::IsValidDvFramePacket(const CIp &Ip, const CBuffer &Buffer, CDvFramePacket **frames) { - bool valid = false; - frames[0] = nullptr; - frames[1] = nullptr; - frames[2] = nullptr; - - uint8 uiPacketType = Buffer.data()[8]; - if ( (Buffer.size() == 72) && ((uiPacketType == 1) || (uiPacketType == 3)) ) - { - // frame details - uint8 uiSlot = (Buffer.data()[16] == 0x22) ? DMR_SLOT2 : DMR_SLOT1; - uint8 uiCallType = (Buffer.data()[62] == 1) ? DMR_GROUP_CALL : DMR_PRIVATE_CALL; - uint8 uiColourCode = Buffer.data()[20] & 0x0F; - if ( (uiSlot == DMRPLUS_REFLECTOR_SLOT) && (uiCallType == DMR_GROUP_CALL) && (uiColourCode == DMRPLUS_REFLECTOR_COLOUR) ) - { - // more frames details - //uint8 uiSeqId = Buffer.data()[4]; - uint8 uiVoiceSeq = (Buffer.data()[18] & 0x0F) - 7; // aka slot type - //uint32 uiDstId = *(uint32 *)(&Buffer.data()[64]) & 0x00FFFFFF; - //uint32 uiSrcId = *(uint32 *)(&Buffer.data()[68]) & 0x00FFFFFF; - - // crack payload - uint8 dmrframe[33]; - uint8 dmr3ambe[27]; - uint8 dmrambe[9]; - uint8 dmrsync[7]; - // get the 33 bytes ambe - memcpy(dmrframe, &(Buffer.data()[26]), 33); - // handle endianess - SwapEndianess(dmrframe, sizeof(dmrframe)); - // extract the 3 ambe frames - memcpy(dmr3ambe, dmrframe, 14); - dmr3ambe[13] &= 0xF0; - dmr3ambe[13] |= (dmrframe[19] & 0x0F); - memcpy(&dmr3ambe[14], &dmrframe[20], 14); - // extract sync - dmrsync[0] = dmrframe[13] & 0x0F; - ::memcpy(&dmrsync[1], &dmrframe[14], 5); - dmrsync[6] = dmrframe[19] & 0xF0; - - // and create 3 dv frames - uint32 uiStreamId = IpToStreamId(Ip); - // frame1 - memcpy(dmrambe, &dmr3ambe[0], 9); - frames[0] = new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 1); - - // frame2 - memcpy(dmrambe, &dmr3ambe[9], 9); - frames[1] = new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 2); - - // frame3 - memcpy(dmrambe, &dmr3ambe[18], 9); - if ( uiPacketType == 3 ) - { - frames[2] = new CDvLastFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 3); - } - else - { - frames[2] = new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 3); - } - - // check - valid = true; - } - } - - // done - return valid; + bool valid = false; + frames[0] = nullptr; + frames[1] = nullptr; + frames[2] = nullptr; + + uint8 uiPacketType = Buffer.data()[8]; + if ( (Buffer.size() == 72) && ((uiPacketType == 1) || (uiPacketType == 3)) ) + { + // frame details + uint8 uiSlot = (Buffer.data()[16] == 0x22) ? DMR_SLOT2 : DMR_SLOT1; + uint8 uiCallType = (Buffer.data()[62] == 1) ? DMR_GROUP_CALL : DMR_PRIVATE_CALL; + uint8 uiColourCode = Buffer.data()[20] & 0x0F; + if ( (uiSlot == DMRPLUS_REFLECTOR_SLOT) && (uiCallType == DMR_GROUP_CALL) && (uiColourCode == DMRPLUS_REFLECTOR_COLOUR) ) + { + // more frames details + //uint8 uiSeqId = Buffer.data()[4]; + uint8 uiVoiceSeq = (Buffer.data()[18] & 0x0F) - 7; // aka slot type + //uint32 uiDstId = *(uint32 *)(&Buffer.data()[64]) & 0x00FFFFFF; + //uint32 uiSrcId = *(uint32 *)(&Buffer.data()[68]) & 0x00FFFFFF; + + // crack payload + uint8 dmrframe[33]; + uint8 dmr3ambe[27]; + uint8 dmrambe[9]; + uint8 dmrsync[7]; + // get the 33 bytes ambe + memcpy(dmrframe, &(Buffer.data()[26]), 33); + // handle endianess + SwapEndianess(dmrframe, sizeof(dmrframe)); + // extract the 3 ambe frames + memcpy(dmr3ambe, dmrframe, 14); + dmr3ambe[13] &= 0xF0; + dmr3ambe[13] |= (dmrframe[19] & 0x0F); + memcpy(&dmr3ambe[14], &dmrframe[20], 14); + // extract sync + dmrsync[0] = dmrframe[13] & 0x0F; + ::memcpy(&dmrsync[1], &dmrframe[14], 5); + dmrsync[6] = dmrframe[19] & 0xF0; + + // and create 3 dv frames + uint32 uiStreamId = IpToStreamId(Ip); + // frame1 + memcpy(dmrambe, &dmr3ambe[0], 9); + frames[0] = new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 1); + + // frame2 + memcpy(dmrambe, &dmr3ambe[9], 9); + frames[1] = new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 2); + + // frame3 + memcpy(dmrambe, &dmr3ambe[18], 9); + if ( uiPacketType == 3 ) + { + frames[2] = new CDvLastFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 3); + } + else + { + frames[2] = new CDvFramePacket(dmrambe, dmrsync, uiStreamId, uiVoiceSeq, 3); + } + + // check + valid = true; + } + } + + // done + return valid; } @@ -562,143 +562,145 @@ bool CDmrplusProtocol::IsValidDvFramePacket(const CIp &Ip, const CBuffer &Buffer void CDmrplusProtocol::EncodeConnectAckPacket(CBuffer *Buffer) { - uint8 tag[] = { 'A','C','K',' ','O','K',0x0A,0x00 }; - Buffer->Set(tag, sizeof(tag)); + uint8 tag[] = { 'A','C','K',' ','O','K',0x0A,0x00 }; + Buffer->Set(tag, sizeof(tag)); } void CDmrplusProtocol::EncodeConnectNackPacket(CBuffer *Buffer) { - uint8 tag[] = { 'N','A','K',' ','O','K',0x0A,0x00 }; - Buffer->Set(tag, sizeof(tag)); + uint8 tag[] = { 'N','A','K',' ','O','K',0x0A,0x00 }; + Buffer->Set(tag, sizeof(tag)); } bool CDmrplusProtocol::EncodeDvHeaderPacket(const CDvHeaderPacket &Packet, CBuffer *Buffer) const { - uint8 tag[] = { 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02, - 0x00,0x05,0x01,0x02,0x00,0x00,0x00 } ; - Buffer->Set(tag, sizeof(tag)); - - // uiSeqId - //Buffer->ReplaceAt(4, 2); - // uiPktType - //Buffer->ReplaceAt(8, 2); - // uiSlot - Buffer->Append((uint16)((DMRPLUS_REFLECTOR_SLOT == DMR_SLOT1) ? 0x1111 : 0x2222)); - // uiSlotType - Buffer->Append((uint16)0xEEEE); - // uiColourCode - uint8 uiColourCode = DMRPLUS_REFLECTOR_COLOUR | (DMRPLUS_REFLECTOR_COLOUR << 4); - Buffer->Append((uint8)uiColourCode); - Buffer->Append((uint8)uiColourCode); - // uiFrameType - Buffer->Append((uint16)0x1111); - // reserved - Buffer->Append((uint16)0x0000); - // payload - uint32 uiSrcId = Packet.GetMyCallsign().GetDmrid() & 0x00FFFFFF; - uint32 uiDstId = ModuleToDmrDestId(Packet.GetRpt2Module()) & 0x00FFFFFF; - Buffer->Append((uint8)0x00, 34); - Buffer->ReplaceAt(36, HIBYTE(HIWORD(uiSrcId))); - Buffer->ReplaceAt(38, LOBYTE(HIWORD(uiSrcId))); - Buffer->ReplaceAt(40, HIBYTE(LOWORD(uiSrcId))); - Buffer->ReplaceAt(42, LOBYTE(LOWORD(uiSrcId))); - - // reserved - Buffer->Append((uint16)0x0000); - // uiCallType - Buffer->Append((uint8)0x01); - // reserved - Buffer->Append((uint8)0x00); - // uiDstId - Buffer->Append(uiDstId); - // uiSrcId - Buffer->Append(uiSrcId); - - // done - return true; + uint8 tag[] = { 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02, + 0x00,0x05,0x01,0x02,0x00,0x00,0x00 + } ; + Buffer->Set(tag, sizeof(tag)); + + // uiSeqId + //Buffer->ReplaceAt(4, 2); + // uiPktType + //Buffer->ReplaceAt(8, 2); + // uiSlot + Buffer->Append((uint16)((DMRPLUS_REFLECTOR_SLOT == DMR_SLOT1) ? 0x1111 : 0x2222)); + // uiSlotType + Buffer->Append((uint16)0xEEEE); + // uiColourCode + uint8 uiColourCode = DMRPLUS_REFLECTOR_COLOUR | (DMRPLUS_REFLECTOR_COLOUR << 4); + Buffer->Append((uint8)uiColourCode); + Buffer->Append((uint8)uiColourCode); + // uiFrameType + Buffer->Append((uint16)0x1111); + // reserved + Buffer->Append((uint16)0x0000); + // payload + uint32 uiSrcId = Packet.GetMyCallsign().GetDmrid() & 0x00FFFFFF; + uint32 uiDstId = ModuleToDmrDestId(Packet.GetRpt2Module()) & 0x00FFFFFF; + Buffer->Append((uint8)0x00, 34); + Buffer->ReplaceAt(36, HIBYTE(HIWORD(uiSrcId))); + Buffer->ReplaceAt(38, LOBYTE(HIWORD(uiSrcId))); + Buffer->ReplaceAt(40, HIBYTE(LOWORD(uiSrcId))); + Buffer->ReplaceAt(42, LOBYTE(LOWORD(uiSrcId))); + + // reserved + Buffer->Append((uint16)0x0000); + // uiCallType + Buffer->Append((uint8)0x01); + // reserved + Buffer->Append((uint8)0x00); + // uiDstId + Buffer->Append(uiDstId); + // uiSrcId + Buffer->Append(uiSrcId); + + // done + return true; } void CDmrplusProtocol::EncodeDvPacket - (const CDvHeaderPacket &Header, - const CDvFramePacket &DvFrame0, const CDvFramePacket &DvFrame1, const CDvFramePacket &DvFrame2, - uint8 seqid, CBuffer *Buffer) const - { - - uint8 tag[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, - 0x00,0x05,0x01,0x02,0x00,0x00,0x00 } ; - Buffer->Set(tag, sizeof(tag)); - - // uiSeqId - Buffer->ReplaceAt(4, seqid); - // uiPktType - //Buffer->ReplaceAt(8, 1); - // uiSlot - Buffer->Append((uint16)((DMRPLUS_REFLECTOR_SLOT == DMR_SLOT1) ? 0x1111 : 0x2222)); - // uiVoiceSeq - uint8 uiVoiceSeq = (DvFrame0.GetDmrPacketId() + 7) | ((DvFrame0.GetDmrPacketId() + 7) << 4); - Buffer->Append((uint8)uiVoiceSeq); - Buffer->Append((uint8)uiVoiceSeq); - // uiColourCode - uint8 uiColourCode = DMRPLUS_REFLECTOR_COLOUR | (DMRPLUS_REFLECTOR_COLOUR << 4); - Buffer->Append((uint8)uiColourCode); - Buffer->Append((uint8)uiColourCode); - // uiFrameType - Buffer->Append((uint16)0x1111); - // reserved - Buffer->Append((uint16)0x0000); - - // payload - uint32 uiSrcId = Header.GetMyCallsign().GetDmrid() & 0x00FFFFFF; - uint32 uiDstId = ModuleToDmrDestId(Header.GetRpt2Module()) & 0x00FFFFFF; - // frame0 - Buffer->ReplaceAt(26, DvFrame0.GetAmbePlus(), 9); - // 1/2 frame1 - Buffer->ReplaceAt(35, DvFrame1.GetAmbePlus(), 5); - Buffer->ReplaceAt(39, (uint8)(Buffer->at(39) & 0xF0)); - // 1/2 frame1 - Buffer->ReplaceAt(45, DvFrame1.GetAmbePlus()+4, 5); - Buffer->ReplaceAt(45, (uint8)(Buffer->at(45) & 0x0F)); - // frame2 - Buffer->ReplaceAt(50, DvFrame2.GetAmbePlus(), 9); - - // sync or embedded signaling - ReplaceEMBInBuffer(Buffer, DvFrame0.GetDmrPacketId()); - - // reserved - Buffer->Append((uint16)0x0000); - Buffer->Append((uint8)0x00); - // uiCallType - Buffer->Append((uint8)0x01); - // reserved - Buffer->Append((uint8)0x00); - // uiDstId - Buffer->Append(uiDstId); - // uiSrcId - Buffer->Append(uiSrcId); - - // handle indianess - SwapEndianess(&(Buffer->data()[26]), 34); +(const CDvHeaderPacket &Header, + const CDvFramePacket &DvFrame0, const CDvFramePacket &DvFrame1, const CDvFramePacket &DvFrame2, + uint8 seqid, CBuffer *Buffer) const +{ + + uint8 tag[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x00,0x05,0x01,0x02,0x00,0x00,0x00 + } ; + Buffer->Set(tag, sizeof(tag)); + + // uiSeqId + Buffer->ReplaceAt(4, seqid); + // uiPktType + //Buffer->ReplaceAt(8, 1); + // uiSlot + Buffer->Append((uint16)((DMRPLUS_REFLECTOR_SLOT == DMR_SLOT1) ? 0x1111 : 0x2222)); + // uiVoiceSeq + uint8 uiVoiceSeq = (DvFrame0.GetDmrPacketId() + 7) | ((DvFrame0.GetDmrPacketId() + 7) << 4); + Buffer->Append((uint8)uiVoiceSeq); + Buffer->Append((uint8)uiVoiceSeq); + // uiColourCode + uint8 uiColourCode = DMRPLUS_REFLECTOR_COLOUR | (DMRPLUS_REFLECTOR_COLOUR << 4); + Buffer->Append((uint8)uiColourCode); + Buffer->Append((uint8)uiColourCode); + // uiFrameType + Buffer->Append((uint16)0x1111); + // reserved + Buffer->Append((uint16)0x0000); + + // payload + uint32 uiSrcId = Header.GetMyCallsign().GetDmrid() & 0x00FFFFFF; + uint32 uiDstId = ModuleToDmrDestId(Header.GetRpt2Module()) & 0x00FFFFFF; + // frame0 + Buffer->ReplaceAt(26, DvFrame0.GetAmbePlus(), 9); + // 1/2 frame1 + Buffer->ReplaceAt(35, DvFrame1.GetAmbePlus(), 5); + Buffer->ReplaceAt(39, (uint8)(Buffer->at(39) & 0xF0)); + // 1/2 frame1 + Buffer->ReplaceAt(45, DvFrame1.GetAmbePlus()+4, 5); + Buffer->ReplaceAt(45, (uint8)(Buffer->at(45) & 0x0F)); + // frame2 + Buffer->ReplaceAt(50, DvFrame2.GetAmbePlus(), 9); + + // sync or embedded signaling + ReplaceEMBInBuffer(Buffer, DvFrame0.GetDmrPacketId()); + + // reserved + Buffer->Append((uint16)0x0000); + Buffer->Append((uint8)0x00); + // uiCallType + Buffer->Append((uint8)0x01); + // reserved + Buffer->Append((uint8)0x00); + // uiDstId + Buffer->Append(uiDstId); + // uiSrcId + Buffer->Append(uiSrcId); + + // handle indianess + SwapEndianess(&(Buffer->data()[26]), 34); } void CDmrplusProtocol::EncodeDvLastPacket - (const CDvHeaderPacket &Header, - const CDvFramePacket &DvFrame0, const CDvFramePacket &DvFrame1, const CDvFramePacket &DvFrame2, - uint8 seqid, CBuffer *Buffer) const - { - EncodeDvPacket(Header, DvFrame0, DvFrame1, DvFrame2, seqid, Buffer); - Buffer->ReplaceAt(8, (uint8)3); - Buffer->ReplaceAt(18, (uint16)0x2222); - } +(const CDvHeaderPacket &Header, + const CDvFramePacket &DvFrame0, const CDvFramePacket &DvFrame1, const CDvFramePacket &DvFrame2, + uint8 seqid, CBuffer *Buffer) const +{ + EncodeDvPacket(Header, DvFrame0, DvFrame1, DvFrame2, seqid, Buffer); + Buffer->ReplaceAt(8, (uint8)3); + Buffer->ReplaceAt(18, (uint16)0x2222); +} void CDmrplusProtocol::SwapEndianess(uint8 *buffer, int len) const { - for ( int i = 0; i < len; i += 2 ) - { - uint8 t = buffer[i]; - buffer[i] = buffer[i+1]; - buffer[i+1] = t; - } + for ( int i = 0; i < len; i += 2 ) + { + uint8 t = buffer[i]; + buffer[i] = buffer[i+1]; + buffer[i+1] = t; + } } @@ -707,7 +709,7 @@ void CDmrplusProtocol::SwapEndianess(uint8 *buffer, int len) const uint8 CDmrplusProtocol::GetNextSeqId(uint8 uiSeqId) const { - return (uiSeqId + 1) & 0xFF; + return (uiSeqId + 1) & 0xFF; } //////////////////////////////////////////////////////////////////////////////////////// @@ -715,17 +717,17 @@ uint8 CDmrplusProtocol::GetNextSeqId(uint8 uiSeqId) const char CDmrplusProtocol::DmrDstIdToModule(uint32 tg) const { - // is it a 4xxx ? - if ( (tg >= 4001) && (tg <= (4000 + NB_OF_MODULES)) ) - { - return ((char)(tg - 4001) + 'A'); - } - return ' '; + // is it a 4xxx ? + if ( (tg >= 4001) && (tg <= (4000 + NB_OF_MODULES)) ) + { + return ((char)(tg - 4001) + 'A'); + } + return ' '; } uint32 CDmrplusProtocol::ModuleToDmrDestId(char m) const { - return (uint32)(m - 'A')+4001; + return (uint32)(m - 'A')+4001; } //////////////////////////////////////////////////////////////////////////////////////// @@ -733,105 +735,105 @@ uint32 CDmrplusProtocol::ModuleToDmrDestId(char m) const void CDmrplusProtocol::AppendVoiceLCToBuffer(CBuffer *buffer, uint32 uiSrcId) const { - uint8 payload[34]; - - // fill payload - CBPTC19696 bptc; - ::memset(payload, 0, sizeof(payload)); - // LC data - uint8 lc[12]; - { - ::memset(lc, 0, sizeof(lc)); - // uiDstId = TG9 - lc[5] = 9; - // uiSrcId - lc[6] = (uint8)LOBYTE(HIWORD(uiSrcId)); - lc[7] = (uint8)HIBYTE(LOWORD(uiSrcId)); - lc[8] = (uint8)LOBYTE(LOWORD(uiSrcId)); - // parity - uint8 parity[4]; - CRS129::encode(lc, 9, parity); - lc[9] = parity[2] ^ DMR_VOICE_LC_HEADER_CRC_MASK; - lc[10] = parity[1] ^ DMR_VOICE_LC_HEADER_CRC_MASK; - lc[11] = parity[0] ^ DMR_VOICE_LC_HEADER_CRC_MASK; - } - // sync - ::memcpy(payload+13, g_DmrSyncBSData, sizeof(g_DmrSyncBSData)); - // slot type - { - // slot type - uint8 slottype[3]; - ::memset(slottype, 0, sizeof(slottype)); - slottype[0] = (DMRPLUS_REFLECTOR_COLOUR << 4) & 0xF0; - slottype[0] |= (DMR_DT_VOICE_LC_HEADER << 0) & 0x0FU; - CGolay2087::encode(slottype); - payload[12U] = (payload[12U] & 0xC0U) | ((slottype[0U] >> 2) & 0x3FU); - payload[13U] = (payload[13U] & 0x0FU) | ((slottype[0U] << 6) & 0xC0U) | ((slottype[1U] >> 2) & 0x30U); - payload[19U] = (payload[19U] & 0xF0U) | ((slottype[1U] >> 2) & 0x0FU); - payload[20U] = (payload[20U] & 0x03U) | ((slottype[1U] << 6) & 0xC0U) | ((slottype[2U] >> 2) & 0x3CU); - - } - // and encode - bptc.encode(lc, payload); - - // and append - buffer->Append(payload, sizeof(payload)); + uint8 payload[34]; + + // fill payload + CBPTC19696 bptc; + ::memset(payload, 0, sizeof(payload)); + // LC data + uint8 lc[12]; + { + ::memset(lc, 0, sizeof(lc)); + // uiDstId = TG9 + lc[5] = 9; + // uiSrcId + lc[6] = (uint8)LOBYTE(HIWORD(uiSrcId)); + lc[7] = (uint8)HIBYTE(LOWORD(uiSrcId)); + lc[8] = (uint8)LOBYTE(LOWORD(uiSrcId)); + // parity + uint8 parity[4]; + CRS129::encode(lc, 9, parity); + lc[9] = parity[2] ^ DMR_VOICE_LC_HEADER_CRC_MASK; + lc[10] = parity[1] ^ DMR_VOICE_LC_HEADER_CRC_MASK; + lc[11] = parity[0] ^ DMR_VOICE_LC_HEADER_CRC_MASK; + } + // sync + ::memcpy(payload+13, g_DmrSyncBSData, sizeof(g_DmrSyncBSData)); + // slot type + { + // slot type + uint8 slottype[3]; + ::memset(slottype, 0, sizeof(slottype)); + slottype[0] = (DMRPLUS_REFLECTOR_COLOUR << 4) & 0xF0; + slottype[0] |= (DMR_DT_VOICE_LC_HEADER << 0) & 0x0FU; + CGolay2087::encode(slottype); + payload[12U] = (payload[12U] & 0xC0U) | ((slottype[0U] >> 2) & 0x3FU); + payload[13U] = (payload[13U] & 0x0FU) | ((slottype[0U] << 6) & 0xC0U) | ((slottype[1U] >> 2) & 0x30U); + payload[19U] = (payload[19U] & 0xF0U) | ((slottype[1U] >> 2) & 0x0FU); + payload[20U] = (payload[20U] & 0x03U) | ((slottype[1U] << 6) & 0xC0U) | ((slottype[2U] >> 2) & 0x3CU); + + } + // and encode + bptc.encode(lc, payload); + + // and append + buffer->Append(payload, sizeof(payload)); } void CDmrplusProtocol::ReplaceEMBInBuffer(CBuffer *buffer, uint8 uiDmrPacketId) const { - // voice packet A ? - if ( uiDmrPacketId == 0 ) - { - // sync - buffer->ReplaceAt(39, (uint8)(buffer->at(39) | (g_DmrSyncBSVoice[0] & 0x0F))); - buffer->ReplaceAt(40, g_DmrSyncBSVoice+1, 5); - buffer->ReplaceAt(45, (uint8)(buffer->at(45) | (g_DmrSyncBSVoice[6] & 0xF0))); - } - // voice packet B,C,D,E ? - else if ( (uiDmrPacketId >= 1) && (uiDmrPacketId <= 4 ) ) - { - // EMB LC - uint8 emb[2]; - emb[0] = (DMRMMDVM_REFLECTOR_COLOUR << 4) & 0xF0; - //emb[0] |= PI ? 0x08U : 0x00; - //emb[0] |= (LCSS << 1) & 0x06; - emb[1] = 0x00; - // encode - CQR1676::encode(emb); - // and append - buffer->ReplaceAt(39, (uint8)((buffer->at(39) & 0xF0) | ((emb[0U] >> 4) & 0x0F))); - buffer->ReplaceAt(40, (uint8)((buffer->at(40) & 0x0F) | ((emb[0U] << 4) & 0xF0))); - buffer->ReplaceAt(40, (uint8)(buffer->at(40) & 0xF0)); - buffer->ReplaceAt(41, (uint8)0); - buffer->ReplaceAt(42, (uint8)0); - buffer->ReplaceAt(43, (uint8)0); - buffer->ReplaceAt(44, (uint8)(buffer->at(44) & 0x0F)); - buffer->ReplaceAt(44, (uint8)((buffer->at(44) & 0xF0) | ((emb[1U] >> 4) & 0x0F))); - buffer->ReplaceAt(45, (uint8)((buffer->at(45) & 0x0F) | ((emb[1U] << 4) & 0xF0))); - } - // voice packet F - else - { - // nullptr - uint8 emb[2]; - emb[0] = (DMRMMDVM_REFLECTOR_COLOUR << 4) & 0xF0; - //emb[0] |= PI ? 0x08U : 0x00; - //emb[0] |= (LCSS << 1) & 0x06; - emb[1] = 0x00; - // encode - CQR1676::encode(emb); - // and append - buffer->ReplaceAt(39, (uint8)((buffer->at(39) & 0xF0) | ((emb[0U] >> 4) & 0x0F))); - buffer->ReplaceAt(40, (uint8)((buffer->at(40) & 0x0F) | ((emb[0U] << 4) & 0xF0))); - buffer->ReplaceAt(40, (uint8)(buffer->at(40) & 0xF0)); - buffer->ReplaceAt(41, (uint8)0); - buffer->ReplaceAt(42, (uint8)0); - buffer->ReplaceAt(43, (uint8)0); - buffer->ReplaceAt(44, (uint8)(buffer->at(44) & 0x0F)); - buffer->ReplaceAt(44, (uint8)((buffer->at(44) & 0xF0) | ((emb[1U] >> 4) & 0x0F))); - buffer->ReplaceAt(45, (uint8)((buffer->at(45) & 0x0F) | ((emb[1U] << 4) & 0xF0))); - } + // voice packet A ? + if ( uiDmrPacketId == 0 ) + { + // sync + buffer->ReplaceAt(39, (uint8)(buffer->at(39) | (g_DmrSyncBSVoice[0] & 0x0F))); + buffer->ReplaceAt(40, g_DmrSyncBSVoice+1, 5); + buffer->ReplaceAt(45, (uint8)(buffer->at(45) | (g_DmrSyncBSVoice[6] & 0xF0))); + } + // voice packet B,C,D,E ? + else if ( (uiDmrPacketId >= 1) && (uiDmrPacketId <= 4 ) ) + { + // EMB LC + uint8 emb[2]; + emb[0] = (DMRMMDVM_REFLECTOR_COLOUR << 4) & 0xF0; + //emb[0] |= PI ? 0x08U : 0x00; + //emb[0] |= (LCSS << 1) & 0x06; + emb[1] = 0x00; + // encode + CQR1676::encode(emb); + // and append + buffer->ReplaceAt(39, (uint8)((buffer->at(39) & 0xF0) | ((emb[0U] >> 4) & 0x0F))); + buffer->ReplaceAt(40, (uint8)((buffer->at(40) & 0x0F) | ((emb[0U] << 4) & 0xF0))); + buffer->ReplaceAt(40, (uint8)(buffer->at(40) & 0xF0)); + buffer->ReplaceAt(41, (uint8)0); + buffer->ReplaceAt(42, (uint8)0); + buffer->ReplaceAt(43, (uint8)0); + buffer->ReplaceAt(44, (uint8)(buffer->at(44) & 0x0F)); + buffer->ReplaceAt(44, (uint8)((buffer->at(44) & 0xF0) | ((emb[1U] >> 4) & 0x0F))); + buffer->ReplaceAt(45, (uint8)((buffer->at(45) & 0x0F) | ((emb[1U] << 4) & 0xF0))); + } + // voice packet F + else + { + // nullptr + uint8 emb[2]; + emb[0] = (DMRMMDVM_REFLECTOR_COLOUR << 4) & 0xF0; + //emb[0] |= PI ? 0x08U : 0x00; + //emb[0] |= (LCSS << 1) & 0x06; + emb[1] = 0x00; + // encode + CQR1676::encode(emb); + // and append + buffer->ReplaceAt(39, (uint8)((buffer->at(39) & 0xF0) | ((emb[0U] >> 4) & 0x0F))); + buffer->ReplaceAt(40, (uint8)((buffer->at(40) & 0x0F) | ((emb[0U] << 4) & 0xF0))); + buffer->ReplaceAt(40, (uint8)(buffer->at(40) & 0xF0)); + buffer->ReplaceAt(41, (uint8)0); + buffer->ReplaceAt(42, (uint8)0); + buffer->ReplaceAt(43, (uint8)0); + buffer->ReplaceAt(44, (uint8)(buffer->at(44) & 0x0F)); + buffer->ReplaceAt(44, (uint8)((buffer->at(44) & 0xF0) | ((emb[1U] >> 4) & 0x0F))); + buffer->ReplaceAt(45, (uint8)((buffer->at(45) & 0x0F) | ((emb[1U] << 4) & 0xF0))); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -841,5 +843,5 @@ void CDmrplusProtocol::ReplaceEMBInBuffer(CBuffer *buffer, uint8 uiDmrPacketId) // uiStreamId helpers uint32 CDmrplusProtocol::IpToStreamId(const CIp &ip) const { - return ip.GetAddr() ^ (uint32)(MAKEDWORD(ip.GetPort(), ip.GetPort())); + return ip.GetAddr() ^ (uint32)(MAKEDWORD(ip.GetPort(), ip.GetPort())); } diff --git a/src/cdmrplusprotocol.h b/src/cdmrplusprotocol.h index 4823fd2..51eea96 100644 --- a/src/cdmrplusprotocol.h +++ b/src/cdmrplusprotocol.h @@ -43,72 +43,72 @@ class CDmrplusStreamCacheItem { public: - CDmrplusStreamCacheItem() { m_uiSeqId = 0x77; } + CDmrplusStreamCacheItem() { m_uiSeqId = 0x77; } - CDvHeaderPacket m_dvHeader; - CDvFramePacket m_dvFrame0; - CDvFramePacket m_dvFrame1; + CDvHeaderPacket m_dvHeader; + CDvFramePacket m_dvFrame0; + CDvFramePacket m_dvFrame1; - uint8 m_uiSeqId; + uint8 m_uiSeqId; }; class CDmrplusProtocol : public CProtocol { public: - // initialization - bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); + // initialization + bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); - // task - void Task(void); + // task + void Task(void); protected: - // queue helper - void HandleQueue(void); - void SendBufferToClients(const CBuffer &, uint8); + // queue helper + void HandleQueue(void); + void SendBufferToClients(const CBuffer &, uint8); - // keepalive helpers - void HandleKeepalives(void); + // keepalive helpers + void HandleKeepalives(void); - // stream helpers - bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); + // stream helpers + bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); - // packet decoding helpers - bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, const CIp &); - bool IsValidDisconnectPacket(const CBuffer &, CCallsign *, char *); - bool IsValidDvHeaderPacket(const CIp &, const CBuffer &, CDvHeaderPacket **); - bool IsValidDvFramePacket(const CIp &, const CBuffer &, CDvFramePacket **); + // packet decoding helpers + bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, const CIp &); + bool IsValidDisconnectPacket(const CBuffer &, CCallsign *, char *); + bool IsValidDvHeaderPacket(const CIp &, const CBuffer &, CDvHeaderPacket **); + bool IsValidDvFramePacket(const CIp &, const CBuffer &, CDvFramePacket **); - // packet encoding helpers - void EncodeConnectAckPacket(CBuffer *); - void EncodeConnectNackPacket(CBuffer *); - bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; - void EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket &, const CDvFramePacket &, const CDvFramePacket &, uint8, CBuffer *) const; - void EncodeDvLastPacket(const CDvHeaderPacket &, const CDvFramePacket &, const CDvFramePacket &, const CDvFramePacket &, uint8, CBuffer *) const; - void SwapEndianess(uint8 *, int) const; + // packet encoding helpers + void EncodeConnectAckPacket(CBuffer *); + void EncodeConnectNackPacket(CBuffer *); + bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; + void EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket &, const CDvFramePacket &, const CDvFramePacket &, uint8, CBuffer *) const; + void EncodeDvLastPacket(const CDvHeaderPacket &, const CDvFramePacket &, const CDvFramePacket &, const CDvFramePacket &, uint8, CBuffer *) const; + void SwapEndianess(uint8 *, int) const; - // dmr SeqId helper - uint8 GetNextSeqId(uint8) const; + // dmr SeqId helper + uint8 GetNextSeqId(uint8) const; - // dmr DstId to Module helper - char DmrDstIdToModule(uint32) const; - uint32 ModuleToDmrDestId(char) const; + // dmr DstId to Module helper + char DmrDstIdToModule(uint32) const; + uint32 ModuleToDmrDestId(char) const; - // uiStreamId helpers - uint32 IpToStreamId(const CIp &) const; + // uiStreamId helpers + uint32 IpToStreamId(const CIp &) const; - // Buffer & LC helpers - void AppendVoiceLCToBuffer(CBuffer *, uint32) const; - void AppendTerminatorLCToBuffer(CBuffer *, uint32) const; - void ReplaceEMBInBuffer(CBuffer *, uint8) const; + // Buffer & LC helpers + void AppendVoiceLCToBuffer(CBuffer *, uint32) const; + void AppendTerminatorLCToBuffer(CBuffer *, uint32) const; + void ReplaceEMBInBuffer(CBuffer *, uint8) const; protected: - // for keep alive - CTimePoint m_LastKeepaliveTime; + // for keep alive + CTimePoint m_LastKeepaliveTime; - // for queue header caches - std::array m_StreamsCache; + // for queue header caches + std::array m_StreamsCache; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cdplusclient.cpp b/src/cdplusclient.cpp index 19f59c3..defa43f 100644 --- a/src/cdplusclient.cpp +++ b/src/cdplusclient.cpp @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- #include "main.h" @@ -31,19 +31,19 @@ CDplusClient::CDplusClient() { - m_bDextraDongle = false; + m_bDextraDongle = false; } CDplusClient::CDplusClient(const CCallsign &callsign, const CIp &ip, char reflectorModule) - : CClient(callsign, ip, reflectorModule) + : CClient(callsign, ip, reflectorModule) { - m_bDextraDongle = false; + m_bDextraDongle = false; } CDplusClient::CDplusClient(const CDplusClient &client) - : CClient(client) + : CClient(client) { - m_bDextraDongle = client.m_bDextraDongle; + m_bDextraDongle = client.m_bDextraDongle; } //////////////////////////////////////////////////////////////////////////////////////// @@ -51,11 +51,11 @@ CDplusClient::CDplusClient(const CDplusClient &client) bool CDplusClient::IsAlive(void) const { - return (m_LastKeepaliveTime.DurationSinceNow() < DPLUS_KEEPALIVE_TIMEOUT); + return (m_LastKeepaliveTime.DurationSinceNow() < DPLUS_KEEPALIVE_TIMEOUT); } void CDplusClient::SetMasterOfModule(char c) { - CClient::SetMasterOfModule(c); - SetReflectorModule(c); + CClient::SetMasterOfModule(c); + SetReflectorModule(c); } diff --git a/src/cdplusclient.h b/src/cdplusclient.h index d615e12..f2312cb 100644 --- a/src/cdplusclient.h +++ b/src/cdplusclient.h @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- #ifndef cdplusclient_h @@ -37,29 +37,29 @@ class CDplusClient : public CClient { public: - // constructors - CDplusClient(); - CDplusClient(const CCallsign &, const CIp &, char = ' '); - CDplusClient(const CDplusClient &); - - // destructor - virtual ~CDplusClient() {}; - - // identity - int GetProtocol(void) const { return PROTOCOL_DPLUS; } - const char *GetProtocolName(void) const { return "DPlus"; } - int GetCodec(void) const { return CODEC_AMBEPLUS; } - bool IsNode(void) const { return true; } - bool IsDextraDongle(void) const { return m_bDextraDongle; } - void SetDextraDongle(void) { m_bDextraDongle = true; } - - // status - bool IsAlive(void) const; - void SetMasterOfModule(char); - + // constructors + CDplusClient(); + CDplusClient(const CCallsign &, const CIp &, char = ' '); + CDplusClient(const CDplusClient &); + + // destructor + virtual ~CDplusClient() {}; + + // identity + int GetProtocol(void) const { return PROTOCOL_DPLUS; } + const char *GetProtocolName(void) const { return "DPlus"; } + int GetCodec(void) const { return CODEC_AMBEPLUS; } + bool IsNode(void) const { return true; } + bool IsDextraDongle(void) const { return m_bDextraDongle; } + void SetDextraDongle(void) { m_bDextraDongle = true; } + + // status + bool IsAlive(void) const; + void SetMasterOfModule(char); + protected: - // data - bool m_bDextraDongle; + // data + bool m_bDextraDongle; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cdplusprotocol.cpp b/src/cdplusprotocol.cpp index acb72ea..b2a35a8 100644 --- a/src/cdplusprotocol.cpp +++ b/src/cdplusprotocol.cpp @@ -36,15 +36,15 @@ bool CDplusProtocol::Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6) { - // base class - if (! CProtocol::Initialize(type, port, has_ipv4, has_ipv6)) + // base class + if (! CProtocol::Initialize(type, port, has_ipv4, has_ipv6)) return false; - // update time - m_LastKeepaliveTime.Now(); + // update time + m_LastKeepaliveTime.Now(); - // done - return true; + // done + return true; } @@ -54,14 +54,14 @@ bool CDplusProtocol::Initalize(const char *type, const uint16 port, const bool h void CDplusProtocol::Task(void) { - CBuffer Buffer; - CIp Ip; - CCallsign Callsign; - CDvHeaderPacket *Header; - CDvFramePacket *Frame; - CDvLastFramePacket *LastFrame; - - // handle incoming packets + CBuffer Buffer; + CIp Ip; + CCallsign Callsign; + CDvHeaderPacket *Header; + CDvFramePacket *Frame; + CDvLastFramePacket *LastFrame; + + // handle incoming packets #if DSTAR_IPV6==true #if DSTAR_IPV4==true if ( ReceiveDS(Buffer, Ip, 20) ) @@ -71,191 +71,191 @@ void CDplusProtocol::Task(void) #else if ( Receive4(Buffer, Ip, 20) ) #endif - { - // crack the packet - if ( (Frame = IsValidDvFramePacket(Buffer)) != nullptr ) - { - //std::cout << "DPlus DV frame" << std::endl; - - // handle it - OnDvFramePacketIn(Frame, &Ip); - } - else if ( (Header = IsValidDvHeaderPacket(Buffer)) != nullptr ) - { - //std::cout << "DPlus DV header:" << std::endl << *Header << std::endl; - - // callsign muted? - if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_DPLUS, Header->GetRpt2Module()) ) - { - // handle it - OnDvHeaderPacketIn(Header, Ip); - } - else - { - delete Header; - } - } - else if ( (LastFrame = IsValidDvLastFramePacket(Buffer)) != nullptr ) - { - //std::cout << "DPlus DV last frame" << std::endl; - - // handle it - OnDvLastFramePacketIn(LastFrame, &Ip); - } - else if ( IsValidConnectPacket(Buffer) ) - { - std::cout << "DPlus connect request packet from " << Ip << std::endl; - - // acknowledge the request - Send(Buffer, Ip); - } - else if ( IsValidLoginPacket(Buffer, &Callsign) ) - { - std::cout << "DPlus login packet from " << Callsign << " at " << Ip << std::endl; - - // callsign authorized? - if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_DPLUS) ) - { - // acknowledge the request - EncodeLoginAckPacket(&Buffer); - Send(Buffer, Ip); - - // create the client and append - g_Reflector.GetClients()->AddClient(std::make_shared(Callsign, Ip)); - g_Reflector.ReleaseClients(); - } - else - { - // deny the request - EncodeLoginNackPacket(&Buffer); - Send(Buffer, Ip); - } - - } - else if ( IsValidDisconnectPacket(Buffer) ) - { - std::cout << "DPlus disconnect packet from " << Ip << std::endl; - - // find client - CClients *clients = g_Reflector.GetClients(); - std::shared_ptrclient = clients->FindClient(Ip, PROTOCOL_DPLUS); - if ( client != nullptr ) - { - // remove it - clients->RemoveClient(client); - // and acknowledge the disconnect - EncodeDisconnectPacket(&Buffer); - Send(Buffer, Ip); - } - g_Reflector.ReleaseClients(); - } - else if ( IsValidKeepAlivePacket(Buffer) ) - { - //std::cout << "DPlus keepalive packet from " << Ip << std::endl; - - // find all clients with that callsign & ip and keep them alive - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(Ip, PROTOCOL_DPLUS, it)) != nullptr ) - { - client->Alive(); - } - g_Reflector.ReleaseClients(); - } - else - { - std::cout << "DPlus packet (" << Buffer.size() << ")" << std::endl; - } - } - - // handle end of streaming timeout - CheckStreamsTimeout(); - - // handle queue from reflector - HandleQueue(); - - // keep client alive - if ( m_LastKeepaliveTime.DurationSinceNow() > DPLUS_KEEPALIVE_PERIOD ) - { - // - HandleKeepalives(); - - // update time - m_LastKeepaliveTime.Now(); - } - } + { + // crack the packet + if ( (Frame = IsValidDvFramePacket(Buffer)) != nullptr ) + { + //std::cout << "DPlus DV frame" << std::endl; + + // handle it + OnDvFramePacketIn(Frame, &Ip); + } + else if ( (Header = IsValidDvHeaderPacket(Buffer)) != nullptr ) + { + //std::cout << "DPlus DV header:" << std::endl << *Header << std::endl; + + // callsign muted? + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_DPLUS, Header->GetRpt2Module()) ) + { + // handle it + OnDvHeaderPacketIn(Header, Ip); + } + else + { + delete Header; + } + } + else if ( (LastFrame = IsValidDvLastFramePacket(Buffer)) != nullptr ) + { + //std::cout << "DPlus DV last frame" << std::endl; + + // handle it + OnDvLastFramePacketIn(LastFrame, &Ip); + } + else if ( IsValidConnectPacket(Buffer) ) + { + std::cout << "DPlus connect request packet from " << Ip << std::endl; + + // acknowledge the request + Send(Buffer, Ip); + } + else if ( IsValidLoginPacket(Buffer, &Callsign) ) + { + std::cout << "DPlus login packet from " << Callsign << " at " << Ip << std::endl; + + // callsign authorized? + if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_DPLUS) ) + { + // acknowledge the request + EncodeLoginAckPacket(&Buffer); + Send(Buffer, Ip); + + // create the client and append + g_Reflector.GetClients()->AddClient(std::make_shared(Callsign, Ip)); + g_Reflector.ReleaseClients(); + } + else + { + // deny the request + EncodeLoginNackPacket(&Buffer); + Send(Buffer, Ip); + } + + } + else if ( IsValidDisconnectPacket(Buffer) ) + { + std::cout << "DPlus disconnect packet from " << Ip << std::endl; + + // find client + CClients *clients = g_Reflector.GetClients(); + std::shared_ptrclient = clients->FindClient(Ip, PROTOCOL_DPLUS); + if ( client != nullptr ) + { + // remove it + clients->RemoveClient(client); + // and acknowledge the disconnect + EncodeDisconnectPacket(&Buffer); + Send(Buffer, Ip); + } + g_Reflector.ReleaseClients(); + } + else if ( IsValidKeepAlivePacket(Buffer) ) + { + //std::cout << "DPlus keepalive packet from " << Ip << std::endl; + + // find all clients with that callsign & ip and keep them alive + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(Ip, PROTOCOL_DPLUS, it)) != nullptr ) + { + client->Alive(); + } + g_Reflector.ReleaseClients(); + } + else + { + std::cout << "DPlus packet (" << Buffer.size() << ")" << std::endl; + } + } + + // handle end of streaming timeout + CheckStreamsTimeout(); + + // handle queue from reflector + HandleQueue(); + + // keep client alive + if ( m_LastKeepaliveTime.DurationSinceNow() > DPLUS_KEEPALIVE_PERIOD ) + { + // + HandleKeepalives(); + + // update time + m_LastKeepaliveTime.Now(); + } +} //////////////////////////////////////////////////////////////////////////////////////// // streams helpers bool CDplusProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip) { - bool newstream = false; - - // find the stream - CPacketStream *stream = GetStream(Header->GetStreamId()); - if ( stream == nullptr ) - { - // no stream open yet, open a new one - CCallsign via(Header->GetRpt1Callsign()); - - // first, check module is valid - if ( g_Reflector.IsValidModule(Header->GetRpt1Module()) ) - { - // find this client - std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_DPLUS); - if ( client != nullptr ) - { - // now we know if it's a dextra dongle or a genuine dplus node - if ( Header->GetRpt2Callsign().HasSameCallsignWithWildcard(CCallsign("XRF*")) ) - { - client->SetDextraDongle(); - } - // now we know its module, let's update it - if ( !client->HasModule() ) - { - client->SetModule(Header->GetRpt1Module()); - } - // get client callsign - via = client->GetCallsign(); - // and try to open the stream - if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) - { - // keep the handle - m_Streams.push_back(stream); - newstream = true; - } - } - // release - g_Reflector.ReleaseClients(); - - // update last heard - g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), via, Header->GetRpt2Callsign()); - g_Reflector.ReleaseUsers(); - - // delete header if needed - if ( !newstream ) - { - delete Header; - } - } - else - { - std::cout << "DPlus node " << via << " link attempt on non-existing module" << std::endl; - } - } - else - { - // stream already open - // skip packet, but tickle the stream - stream->Tickle(); - // and delete packet - delete Header; - } - - // done - return newstream; + bool newstream = false; + + // find the stream + CPacketStream *stream = GetStream(Header->GetStreamId()); + if ( stream == nullptr ) + { + // no stream open yet, open a new one + CCallsign via(Header->GetRpt1Callsign()); + + // first, check module is valid + if ( g_Reflector.IsValidModule(Header->GetRpt1Module()) ) + { + // find this client + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_DPLUS); + if ( client != nullptr ) + { + // now we know if it's a dextra dongle or a genuine dplus node + if ( Header->GetRpt2Callsign().HasSameCallsignWithWildcard(CCallsign("XRF*")) ) + { + client->SetDextraDongle(); + } + // now we know its module, let's update it + if ( !client->HasModule() ) + { + client->SetModule(Header->GetRpt1Module()); + } + // get client callsign + via = client->GetCallsign(); + // and try to open the stream + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) + { + // keep the handle + m_Streams.push_back(stream); + newstream = true; + } + } + // release + g_Reflector.ReleaseClients(); + + // update last heard + g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), via, Header->GetRpt2Callsign()); + g_Reflector.ReleaseUsers(); + + // delete header if needed + if ( !newstream ) + { + delete Header; + } + } + else + { + std::cout << "DPlus node " << via << " link attempt on non-existing module" << std::endl; + } + } + else + { + // stream already open + // skip packet, but tickle the stream + stream->Tickle(); + // and delete packet + delete Header; + } + + // done + return newstream; } //////////////////////////////////////////////////////////////////////////////////////// @@ -263,113 +263,113 @@ bool CDplusProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip) void CDplusProtocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) - { - // get the packet - CPacket *packet = m_Queue.front(); - m_Queue.pop(); - - // get our sender's id - int iModId = g_Reflector.GetModuleIndex(packet->GetModuleId()); - - // check if it's header and update cache - if ( packet->IsDvHeader() ) - { - // this relies on queue feeder setting valid module id - m_StreamsCache[iModId].m_dvHeader = CDvHeaderPacket((const CDvHeaderPacket &)*packet); - m_StreamsCache[iModId].m_iSeqCounter = 0; - } - - // encode it - CBuffer buffer; - if ( EncodeDvPacket(*packet, &buffer) ) - { - // and push it to all our clients who are not streaming in - // note that for dplus protocol, all stream of all modules are push to all clients - // it's client who decide which stream he's interrrested in - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_DPLUS, it)) != nullptr ) - { - // is this client busy ? - if ( !client->IsAMaster() ) - { - // check if client is a dextra dongle - // then replace RPT2 with XRF instead of REF - // if the client type is not yet known, send bothheaders - if ( packet->IsDvHeader() ) - { - // sending header in Dplus is client specific - SendDvHeader((CDvHeaderPacket *)packet, (CDplusClient *)client.get()); - } - else if ( packet->IsDvFrame() ) - { - // and send the DV frame - Send(buffer, client->GetIp()); - - // is it time to insert a DVheader copy ? - if ( (m_StreamsCache[iModId].m_iSeqCounter++ % 21) == 20 ) - { - // yes, clone it - CDvHeaderPacket packet2(m_StreamsCache[iModId].m_dvHeader); - // and send it - SendDvHeader(&packet2, (CDplusClient *)client.get()); - } - } - else - { - // otherwise, send the original packet - Send(buffer, client->GetIp()); - } - } - } - g_Reflector.ReleaseClients(); - } - - - // done - delete packet; - } - m_Queue.Unlock(); + m_Queue.Lock(); + while ( !m_Queue.empty() ) + { + // get the packet + CPacket *packet = m_Queue.front(); + m_Queue.pop(); + + // get our sender's id + int iModId = g_Reflector.GetModuleIndex(packet->GetModuleId()); + + // check if it's header and update cache + if ( packet->IsDvHeader() ) + { + // this relies on queue feeder setting valid module id + m_StreamsCache[iModId].m_dvHeader = CDvHeaderPacket((const CDvHeaderPacket &)*packet); + m_StreamsCache[iModId].m_iSeqCounter = 0; + } + + // encode it + CBuffer buffer; + if ( EncodeDvPacket(*packet, &buffer) ) + { + // and push it to all our clients who are not streaming in + // note that for dplus protocol, all stream of all modules are push to all clients + // it's client who decide which stream he's interrrested in + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_DPLUS, it)) != nullptr ) + { + // is this client busy ? + if ( !client->IsAMaster() ) + { + // check if client is a dextra dongle + // then replace RPT2 with XRF instead of REF + // if the client type is not yet known, send bothheaders + if ( packet->IsDvHeader() ) + { + // sending header in Dplus is client specific + SendDvHeader((CDvHeaderPacket *)packet, (CDplusClient *)client.get()); + } + else if ( packet->IsDvFrame() ) + { + // and send the DV frame + Send(buffer, client->GetIp()); + + // is it time to insert a DVheader copy ? + if ( (m_StreamsCache[iModId].m_iSeqCounter++ % 21) == 20 ) + { + // yes, clone it + CDvHeaderPacket packet2(m_StreamsCache[iModId].m_dvHeader); + // and send it + SendDvHeader(&packet2, (CDplusClient *)client.get()); + } + } + else + { + // otherwise, send the original packet + Send(buffer, client->GetIp()); + } + } + } + g_Reflector.ReleaseClients(); + } + + + // done + delete packet; + } + m_Queue.Unlock(); } void CDplusProtocol::SendDvHeader(CDvHeaderPacket *packet, CDplusClient *client) { - // encode it - CBuffer buffer; - if ( EncodeDvPacket(*packet, &buffer) ) - { - if ( (client->IsDextraDongle() || !client->HasModule()) ) - { - // clone the packet and patch it - CDvHeaderPacket packet2(*((CDvHeaderPacket *)packet)); - CCallsign rpt2 = packet2.GetRpt2Callsign(); - rpt2.PatchCallsign(0, (const uint8 *)"XRF", 3); - packet2.SetRpt2Callsign(rpt2); - - // encode it - CBuffer buffer2; - if ( EncodeDvPacket(packet2, &buffer2) ) - { - // and send it - Send(buffer2, client->GetIp()); - } - - // client type known ? - if ( !client->HasModule() ) - { - // no, send also the genuine packet - Send(buffer, client->GetIp()); - } - } - else - { - // otherwise, send the original packet - Send(buffer, client->GetIp()); - } - } + // encode it + CBuffer buffer; + if ( EncodeDvPacket(*packet, &buffer) ) + { + if ( (client->IsDextraDongle() || !client->HasModule()) ) + { + // clone the packet and patch it + CDvHeaderPacket packet2(*((CDvHeaderPacket *)packet)); + CCallsign rpt2 = packet2.GetRpt2Callsign(); + rpt2.PatchCallsign(0, (const uint8 *)"XRF", 3); + packet2.SetRpt2Callsign(rpt2); + + // encode it + CBuffer buffer2; + if ( EncodeDvPacket(packet2, &buffer2) ) + { + // and send it + Send(buffer2, client->GetIp()); + } + + // client type known ? + if ( !client->HasModule() ) + { + // no, send also the genuine packet + Send(buffer, client->GetIp()); + } + } + else + { + // otherwise, send the original packet + Send(buffer, client->GetIp()); + } + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -377,40 +377,40 @@ void CDplusProtocol::SendDvHeader(CDvHeaderPacket *packet, CDplusClient *client) void CDplusProtocol::HandleKeepalives(void) { - // send keepalives - CBuffer keepalive; - EncodeKeepAlivePacket(&keepalive); - - // iterate on clients - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_DPLUS, it)) != nullptr ) - { - // send keepalive - //std::cout << "Sending DPlus packet @ " << client->GetIp() << std::endl; - Send(keepalive, client->GetIp()); - - // is this client busy ? - if ( client->IsAMaster() ) - { - // yes, just tickle it - client->Alive(); - } - // check it's still with us - else if ( !client->IsAlive() ) - { - // no, disconnect - CBuffer disconnect; - EncodeDisconnectPacket(&disconnect); - Send(disconnect, client->GetIp()); - - // and remove it - std::cout << "DPlus client " << client->GetCallsign() << " keepalive timeout" << std::endl; - clients->RemoveClient(client); - } - } - g_Reflector.ReleaseClients(); + // send keepalives + CBuffer keepalive; + EncodeKeepAlivePacket(&keepalive); + + // iterate on clients + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_DPLUS, it)) != nullptr ) + { + // send keepalive + //std::cout << "Sending DPlus packet @ " << client->GetIp() << std::endl; + Send(keepalive, client->GetIp()); + + // is this client busy ? + if ( client->IsAMaster() ) + { + // yes, just tickle it + client->Alive(); + } + // check it's still with us + else if ( !client->IsAlive() ) + { + // no, disconnect + CBuffer disconnect; + EncodeDisconnectPacket(&disconnect); + Send(disconnect, client->GetIp()); + + // and remove it + std::cout << "DPlus client " << client->GetCallsign() << " keepalive timeout" << std::endl; + clients->RemoveClient(client); + } + } + g_Reflector.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -418,99 +418,99 @@ void CDplusProtocol::HandleKeepalives(void) bool CDplusProtocol::IsValidConnectPacket(const CBuffer &Buffer) { - uint8 tag[] = { 0x05,0x00,0x18,0x00,0x01 }; - return (Buffer == CBuffer(tag, sizeof(tag))); + uint8 tag[] = { 0x05,0x00,0x18,0x00,0x01 }; + return (Buffer == CBuffer(tag, sizeof(tag))); } bool CDplusProtocol::IsValidLoginPacket(const CBuffer &Buffer, CCallsign *Callsign) { - uint8 Tag[] = { 0x1C,0xC0,0x04,0x00 }; - bool valid = false; - - if ( (Buffer.size() == 28) &&(::memcmp(Buffer.data(), Tag, sizeof(Tag)) == 0) ) - { - Callsign->SetCallsign(&(Buffer.data()[4]), 8); - valid = Callsign->IsValid(); - } - return valid; + uint8 Tag[] = { 0x1C,0xC0,0x04,0x00 }; + bool valid = false; + + if ( (Buffer.size() == 28) &&(::memcmp(Buffer.data(), Tag, sizeof(Tag)) == 0) ) + { + Callsign->SetCallsign(&(Buffer.data()[4]), 8); + valid = Callsign->IsValid(); + } + return valid; } bool CDplusProtocol::IsValidDisconnectPacket(const CBuffer &Buffer) { - uint8 tag[] = { 0x05,0x00,0x18,0x00,0x00 }; - return (Buffer == CBuffer(tag, sizeof(tag))); + uint8 tag[] = { 0x05,0x00,0x18,0x00,0x00 }; + return (Buffer == CBuffer(tag, sizeof(tag))); } bool CDplusProtocol::IsValidKeepAlivePacket(const CBuffer &Buffer) { - uint8 tag[] = { 0x03,0x60,0x00 }; - return (Buffer == CBuffer(tag, sizeof(tag))); + uint8 tag[] = { 0x03,0x60,0x00 }; + return (Buffer == CBuffer(tag, sizeof(tag))); } CDvHeaderPacket *CDplusProtocol::IsValidDvHeaderPacket(const CBuffer &Buffer) { - CDvHeaderPacket *header = nullptr; - - if ( (Buffer.size() == 58) && - (Buffer.data()[0] == 0x3A) && (Buffer.data()[1] == 0x80) && - (Buffer.Compare((uint8 *)"DSVT", 2, 4) == 0) && - (Buffer.data()[6] == 0x10) && (Buffer.data()[10] == 0x20) ) - { - // create packet - header = new CDvHeaderPacket((struct dstar_header *)&(Buffer.data()[17]), - *((uint16 *)&(Buffer.data()[14])), 0x80); - // check validity of packet - if ( !header->IsValid() ) - { - delete header; - header = nullptr; - } - } - return header; + CDvHeaderPacket *header = nullptr; + + if ( (Buffer.size() == 58) && + (Buffer.data()[0] == 0x3A) && (Buffer.data()[1] == 0x80) && + (Buffer.Compare((uint8 *)"DSVT", 2, 4) == 0) && + (Buffer.data()[6] == 0x10) && (Buffer.data()[10] == 0x20) ) + { + // create packet + header = new CDvHeaderPacket((struct dstar_header *)&(Buffer.data()[17]), + *((uint16 *)&(Buffer.data()[14])), 0x80); + // check validity of packet + if ( !header->IsValid() ) + { + delete header; + header = nullptr; + } + } + return header; } CDvFramePacket *CDplusProtocol::IsValidDvFramePacket(const CBuffer &Buffer) { - CDvFramePacket *dvframe = nullptr; - - if ( (Buffer.size() == 29) && - (Buffer.data()[0] == 0x1D) && (Buffer.data()[1] == 0x80) && - (Buffer.Compare((uint8 *)"DSVT", 2, 4) == 0) && - (Buffer.data()[6] == 0x20) && (Buffer.data()[10] == 0x20) ) - { - // create packet - dvframe = new CDvFramePacket((struct dstar_dvframe *)&(Buffer.data()[17]), - *((uint16 *)&(Buffer.data()[14])), Buffer.data()[16]); - // check validity of packet - if ( !dvframe->IsValid() ) - { - delete dvframe; - dvframe = nullptr; - } - } - return dvframe; + CDvFramePacket *dvframe = nullptr; + + if ( (Buffer.size() == 29) && + (Buffer.data()[0] == 0x1D) && (Buffer.data()[1] == 0x80) && + (Buffer.Compare((uint8 *)"DSVT", 2, 4) == 0) && + (Buffer.data()[6] == 0x20) && (Buffer.data()[10] == 0x20) ) + { + // create packet + dvframe = new CDvFramePacket((struct dstar_dvframe *)&(Buffer.data()[17]), + *((uint16 *)&(Buffer.data()[14])), Buffer.data()[16]); + // check validity of packet + if ( !dvframe->IsValid() ) + { + delete dvframe; + dvframe = nullptr; + } + } + return dvframe; } CDvLastFramePacket *CDplusProtocol::IsValidDvLastFramePacket(const CBuffer &Buffer) { - CDvLastFramePacket *dvframe = nullptr; - - if ( (Buffer.size() == 32) && - (Buffer.Compare((uint8 *)"DSVT", 2, 4) == 0) && - (Buffer.data()[0] == 0x20) && (Buffer.data()[1] == 0x80) && - (Buffer.data()[6] == 0x20) && (Buffer.data()[10] == 0x20) ) - { - // create packet - dvframe = new CDvLastFramePacket((struct dstar_dvframe *)&(Buffer.data()[17]), - *((uint16 *)&(Buffer.data()[14])), Buffer.data()[16]); - // check validity of packet - if ( !dvframe->IsValid() ) - { - delete dvframe; - dvframe = nullptr; - } - } - return dvframe; + CDvLastFramePacket *dvframe = nullptr; + + if ( (Buffer.size() == 32) && + (Buffer.Compare((uint8 *)"DSVT", 2, 4) == 0) && + (Buffer.data()[0] == 0x20) && (Buffer.data()[1] == 0x80) && + (Buffer.data()[6] == 0x20) && (Buffer.data()[10] == 0x20) ) + { + // create packet + dvframe = new CDvLastFramePacket((struct dstar_dvframe *)&(Buffer.data()[17]), + *((uint16 *)&(Buffer.data()[14])), Buffer.data()[16]); + // check validity of packet + if ( !dvframe->IsValid() ) + { + delete dvframe; + dvframe = nullptr; + } + } + return dvframe; } @@ -519,67 +519,67 @@ CDvLastFramePacket *CDplusProtocol::IsValidDvLastFramePacket(const CBuffer &Buff void CDplusProtocol::EncodeKeepAlivePacket(CBuffer *Buffer) { - uint8 tag[] = { 0x03,0x60,0x00 }; - Buffer->Set(tag, sizeof(tag)); + uint8 tag[] = { 0x03,0x60,0x00 }; + Buffer->Set(tag, sizeof(tag)); } void CDplusProtocol::EncodeLoginAckPacket(CBuffer *Buffer) { - uint8 tag[] = { 0x08,0xC0,0x04,0x00,'O','K','R','W' }; - Buffer->Set(tag, sizeof(tag)); + uint8 tag[] = { 0x08,0xC0,0x04,0x00,'O','K','R','W' }; + Buffer->Set(tag, sizeof(tag)); } void CDplusProtocol::EncodeLoginNackPacket(CBuffer *Buffer) { - uint8 tag[] = { 0x08,0xC0,0x04,0x00,'B','U','S','Y' }; - Buffer->Set(tag, sizeof(tag)); + uint8 tag[] = { 0x08,0xC0,0x04,0x00,'B','U','S','Y' }; + Buffer->Set(tag, sizeof(tag)); } void CDplusProtocol::EncodeDisconnectPacket(CBuffer *Buffer) { - uint8 tag[] = { 0x05,0x00,0x18,0x00,0x00 }; - Buffer->Set(tag, sizeof(tag)); + uint8 tag[] = { 0x05,0x00,0x18,0x00,0x00 }; + Buffer->Set(tag, sizeof(tag)); } bool CDplusProtocol::EncodeDvHeaderPacket(const CDvHeaderPacket &Packet, CBuffer *Buffer) const { - uint8 tag[] = { 0x3A,0x80,0x44,0x53,0x56,0x54,0x10,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; - struct dstar_header DstarHeader; + uint8 tag[] = { 0x3A,0x80,0x44,0x53,0x56,0x54,0x10,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; + struct dstar_header DstarHeader; - Packet.ConvertToDstarStruct(&DstarHeader); + Packet.ConvertToDstarStruct(&DstarHeader); - Buffer->Set(tag, sizeof(tag)); - Buffer->Append(Packet.GetStreamId()); - Buffer->Append((uint8)0x80); - Buffer->Append((uint8 *)&DstarHeader, sizeof(struct dstar_header)); + Buffer->Set(tag, sizeof(tag)); + Buffer->Append(Packet.GetStreamId()); + Buffer->Append((uint8)0x80); + Buffer->Append((uint8 *)&DstarHeader, sizeof(struct dstar_header)); - return true; + return true; } bool CDplusProtocol::EncodeDvFramePacket(const CDvFramePacket &Packet, CBuffer *Buffer) const { - uint8 tag[] = { 0x1D,0x80,0x44,0x53,0x56,0x54,0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; + uint8 tag[] = { 0x1D,0x80,0x44,0x53,0x56,0x54,0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; - Buffer->Set(tag, sizeof(tag)); - Buffer->Append(Packet.GetStreamId()); - Buffer->Append((uint8)(Packet.GetPacketId() % 21)); - Buffer->Append((uint8 *)Packet.GetAmbe(), AMBE_SIZE); - Buffer->Append((uint8 *)Packet.GetDvData(), DVDATA_SIZE); + Buffer->Set(tag, sizeof(tag)); + Buffer->Append(Packet.GetStreamId()); + Buffer->Append((uint8)(Packet.GetPacketId() % 21)); + Buffer->Append((uint8 *)Packet.GetAmbe(), AMBE_SIZE); + Buffer->Append((uint8 *)Packet.GetDvData(), DVDATA_SIZE); - return true; + return true; } bool CDplusProtocol::EncodeDvLastFramePacket(const CDvLastFramePacket &Packet, CBuffer *Buffer) const { - uint8 tag1[] = { 0x20,0x80,0x44,0x53,0x56,0x54,0x20,0x00,0x81,0x00,0x20,0x00,0x01,0x02 }; - uint8 tag2[] = { 0x55,0xC8,0x7A,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x25,0x1A,0xC6 }; + uint8 tag1[] = { 0x20,0x80,0x44,0x53,0x56,0x54,0x20,0x00,0x81,0x00,0x20,0x00,0x01,0x02 }; + uint8 tag2[] = { 0x55,0xC8,0x7A,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x25,0x1A,0xC6 }; - Buffer->Set(tag1, sizeof(tag1)); - Buffer->Append(Packet.GetStreamId()); - Buffer->Append((uint8)((Packet.GetPacketId() % 21) | 0x40)); - Buffer->Append(tag2, sizeof(tag2)); + Buffer->Set(tag1, sizeof(tag1)); + Buffer->Append(Packet.GetStreamId()); + Buffer->Append((uint8)((Packet.GetPacketId() % 21) | 0x40)); + Buffer->Append(tag2, sizeof(tag2)); - return true; + return true; } diff --git a/src/cdplusprotocol.h b/src/cdplusprotocol.h index 38715f2..0515946 100644 --- a/src/cdplusprotocol.h +++ b/src/cdplusprotocol.h @@ -42,57 +42,57 @@ class CDplusClient; class CDPlusStreamCacheItem { public: - CDPlusStreamCacheItem() { m_iSeqCounter = 0; } + CDPlusStreamCacheItem() { m_iSeqCounter = 0; } - CDvHeaderPacket m_dvHeader; - uint8 m_iSeqCounter; + CDvHeaderPacket m_dvHeader; + uint8 m_iSeqCounter; }; class CDplusProtocol : public CProtocol { public: - // initialization - bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); + // initialization + bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); - // task - void Task(void); + // task + void Task(void); protected: - // queue helper - void HandleQueue(void); - void SendDvHeader(CDvHeaderPacket *, CDplusClient *); - - // keepalive helpers - void HandleKeepalives(void); - - // stream helpers - bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); - - // packet decoding helpers - bool IsValidConnectPacket(const CBuffer &); - bool IsValidLoginPacket(const CBuffer &, CCallsign *); - bool IsValidDisconnectPacket(const CBuffer &); - bool IsValidKeepAlivePacket(const CBuffer &); - CDvHeaderPacket *IsValidDvHeaderPacket(const CBuffer &); - CDvFramePacket *IsValidDvFramePacket(const CBuffer &); - CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &); - - // packet encoding helpers - void EncodeKeepAlivePacket(CBuffer *); - void EncodeLoginAckPacket(CBuffer *); - void EncodeLoginNackPacket(CBuffer *); - void EncodeDisconnectPacket(CBuffer *); - bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; - bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; - bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; + // queue helper + void HandleQueue(void); + void SendDvHeader(CDvHeaderPacket *, CDplusClient *); + + // keepalive helpers + void HandleKeepalives(void); + + // stream helpers + bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); + + // packet decoding helpers + bool IsValidConnectPacket(const CBuffer &); + bool IsValidLoginPacket(const CBuffer &, CCallsign *); + bool IsValidDisconnectPacket(const CBuffer &); + bool IsValidKeepAlivePacket(const CBuffer &); + CDvHeaderPacket *IsValidDvHeaderPacket(const CBuffer &); + CDvFramePacket *IsValidDvFramePacket(const CBuffer &); + CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &); + + // packet encoding helpers + void EncodeKeepAlivePacket(CBuffer *); + void EncodeLoginAckPacket(CBuffer *); + void EncodeLoginNackPacket(CBuffer *); + void EncodeDisconnectPacket(CBuffer *); + bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; + bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; + bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; protected: - // for keep alive - CTimePoint m_LastKeepaliveTime; + // for keep alive + CTimePoint m_LastKeepaliveTime; - // for queue header caches - std::array m_StreamsCache; + // for queue header caches + std::array m_StreamsCache; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cdvframepacket.cpp b/src/cdvframepacket.cpp index 39d9a5b..0189b1c 100644 --- a/src/cdvframepacket.cpp +++ b/src/cdvframepacket.cpp @@ -33,24 +33,24 @@ CDvFramePacket::CDvFramePacket() { - ::memset(m_uiAmbe, 0, sizeof(m_uiAmbe)); - ::memset(m_uiDvData, 0, sizeof(m_uiDvData)); + ::memset(m_uiAmbe, 0, sizeof(m_uiAmbe)); + ::memset(m_uiDvData, 0, sizeof(m_uiDvData)); #ifndef NO_XLX - ::memset(m_uiAmbePlus, 0, sizeof(m_uiAmbePlus)); - ::memset(m_uiDvSync, 0, sizeof(m_uiDvSync)); + ::memset(m_uiAmbePlus, 0, sizeof(m_uiAmbePlus)); + ::memset(m_uiDvSync, 0, sizeof(m_uiDvSync)); #endif }; // dstar constructor CDvFramePacket::CDvFramePacket(const struct dstar_dvframe *dvframe, uint16 sid, uint8 pid) - : CPacket(sid, pid) + : CPacket(sid, pid) { - ::memcpy(m_uiAmbe, dvframe->AMBE, sizeof(m_uiAmbe)); - ::memcpy(m_uiDvData, dvframe->DVDATA, sizeof(m_uiDvData)); + ::memcpy(m_uiAmbe, dvframe->AMBE, sizeof(m_uiAmbe)); + ::memcpy(m_uiDvData, dvframe->DVDATA, sizeof(m_uiDvData)); #ifndef NO_XLX - ::memset(m_uiAmbePlus, 0, sizeof(m_uiAmbePlus)); - ::memset(m_uiDvSync, 0, sizeof(m_uiDvSync)); + ::memset(m_uiAmbePlus, 0, sizeof(m_uiAmbePlus)); + ::memset(m_uiDvSync, 0, sizeof(m_uiDvSync)); #endif } @@ -58,37 +58,37 @@ CDvFramePacket::CDvFramePacket(const struct dstar_dvframe *dvframe, uint16 sid, // dmr constructor CDvFramePacket::CDvFramePacket(const uint8 *ambe, const uint8 *sync, uint16 sid, uint8 pid, uint8 spid) - : CPacket(sid, pid, spid) + : CPacket(sid, pid, spid) { - ::memcpy(m_uiAmbePlus, ambe, sizeof(m_uiAmbePlus)); - ::memcpy(m_uiDvSync, sync, sizeof(m_uiDvSync)); - ::memset(m_uiAmbe, 0, sizeof(m_uiAmbe)); - ::memset(m_uiDvData, 0, sizeof(m_uiDvData)); + ::memcpy(m_uiAmbePlus, ambe, sizeof(m_uiAmbePlus)); + ::memcpy(m_uiDvSync, sync, sizeof(m_uiDvSync)); + ::memset(m_uiAmbe, 0, sizeof(m_uiAmbe)); + ::memset(m_uiDvData, 0, sizeof(m_uiDvData)); } // ysf constructor CDvFramePacket::CDvFramePacket(const uint8 *ambe, uint16 sid, uint8 pid, uint8 spid, uint8 fid) -: CPacket(sid, pid, spid, fid) + : CPacket(sid, pid, spid, fid) { - ::memcpy(m_uiAmbePlus, ambe, sizeof(m_uiAmbePlus)); - ::memset(m_uiDvSync, 0, sizeof(m_uiDvSync)); - ::memset(m_uiAmbe, 0, sizeof(m_uiAmbe)); - ::memset(m_uiDvData, 0, sizeof(m_uiDvData)); + ::memcpy(m_uiAmbePlus, ambe, sizeof(m_uiAmbePlus)); + ::memset(m_uiDvSync, 0, sizeof(m_uiDvSync)); + ::memset(m_uiAmbe, 0, sizeof(m_uiAmbe)); + ::memset(m_uiDvData, 0, sizeof(m_uiDvData)); } // xlx constructor CDvFramePacket::CDvFramePacket - (uint16 sid, - uint8 dstarpid, const uint8 *dstarambe, const uint8 *dstardvdata, - uint8 dmrpid, uint8 dprspid, const uint8 *dmrambe, const uint8 *dmrsync) -: CPacket(sid, dstarpid, dmrpid, dprspid, 0xFF, 0xFF, 0xFF) +(uint16 sid, + uint8 dstarpid, const uint8 *dstarambe, const uint8 *dstardvdata, + uint8 dmrpid, uint8 dprspid, const uint8 *dmrambe, const uint8 *dmrsync) + : CPacket(sid, dstarpid, dmrpid, dprspid, 0xFF, 0xFF, 0xFF) { - ::memcpy(m_uiAmbe, dstarambe, sizeof(m_uiAmbe)); - ::memcpy(m_uiDvData, dstardvdata, sizeof(m_uiDvData)); - ::memcpy(m_uiAmbePlus, dmrambe, sizeof(m_uiAmbePlus)); - ::memcpy(m_uiDvSync, dmrsync, sizeof(m_uiDvSync)); + ::memcpy(m_uiAmbe, dstarambe, sizeof(m_uiAmbe)); + ::memcpy(m_uiDvData, dstardvdata, sizeof(m_uiDvData)); + ::memcpy(m_uiAmbePlus, dmrambe, sizeof(m_uiAmbePlus)); + ::memcpy(m_uiDvSync, dmrsync, sizeof(m_uiDvSync)); } #endif @@ -97,7 +97,7 @@ CDvFramePacket::CDvFramePacket CPacket *CDvFramePacket::Duplicate(void) const { - return new CDvFramePacket(*this); + return new CDvFramePacket(*this); } //////////////////////////////////////////////////////////////////////////////////////// @@ -105,14 +105,17 @@ CPacket *CDvFramePacket::Duplicate(void) const const uint8 *CDvFramePacket::GetAmbe(uint8 uiCodec) const { - switch (uiCodec) - { - case CODEC_AMBEPLUS: return m_uiAmbe; + switch (uiCodec) + { + case CODEC_AMBEPLUS: + return m_uiAmbe; #ifndef NO_XLX - case CODEC_AMBE2PLUS: return m_uiAmbePlus; + case CODEC_AMBE2PLUS: + return m_uiAmbePlus; #endif - default: return nullptr; - } + default: + return nullptr; + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -120,22 +123,22 @@ const uint8 *CDvFramePacket::GetAmbe(uint8 uiCodec) const void CDvFramePacket::SetDvData(uint8 *DvData) { - ::memcpy(m_uiDvData, DvData, sizeof(m_uiDvData)); + ::memcpy(m_uiDvData, DvData, sizeof(m_uiDvData)); } void CDvFramePacket::SetAmbe(uint8 uiCodec, uint8 *Ambe) { - switch (uiCodec) - { - case CODEC_AMBEPLUS: - ::memcpy(m_uiAmbe, Ambe, sizeof(m_uiAmbe)); - break; + switch (uiCodec) + { + case CODEC_AMBEPLUS: + ::memcpy(m_uiAmbe, Ambe, sizeof(m_uiAmbe)); + break; #ifndef NO_XLX - case CODEC_AMBE2PLUS: - ::memcpy(m_uiAmbePlus, Ambe, sizeof(m_uiAmbe)); - break; + case CODEC_AMBE2PLUS: + ::memcpy(m_uiAmbePlus, Ambe, sizeof(m_uiAmbe)); + break; #endif - } + } } @@ -144,11 +147,11 @@ void CDvFramePacket::SetAmbe(uint8 uiCodec, uint8 *Ambe) bool CDvFramePacket::operator ==(const CDvFramePacket &DvFrame) const { - return ( (::memcmp(m_uiAmbe, DvFrame.m_uiAmbe, sizeof(m_uiAmbe)) == 0) - && (::memcmp(m_uiDvData, DvFrame.m_uiDvData, sizeof(m_uiDvData)) == 0) + return ( (::memcmp(m_uiAmbe, DvFrame.m_uiAmbe, sizeof(m_uiAmbe)) == 0) + && (::memcmp(m_uiDvData, DvFrame.m_uiDvData, sizeof(m_uiDvData)) == 0) #ifndef NO_XLX - && (::memcmp(m_uiAmbePlus, DvFrame.m_uiAmbePlus, sizeof(m_uiAmbePlus)) == 0) - && (::memcmp(m_uiDvSync, DvFrame.m_uiDvSync, sizeof(m_uiDvSync)) == 0) + && (::memcmp(m_uiAmbePlus, DvFrame.m_uiAmbePlus, sizeof(m_uiAmbePlus)) == 0) + && (::memcmp(m_uiDvSync, DvFrame.m_uiDvSync, sizeof(m_uiDvSync)) == 0) #endif - ); + ); } diff --git a/src/cdvframepacket.h b/src/cdvframepacket.h index f247422..ba1d11d 100644 --- a/src/cdvframepacket.h +++ b/src/cdvframepacket.h @@ -40,8 +40,8 @@ struct __attribute__ ((__packed__))dstar_dvframe { - uint8 AMBE[AMBE_SIZE]; - uint8 DVDATA[DVDATA_SIZE]; + uint8 AMBE[AMBE_SIZE]; + uint8 DVDATA[DVDATA_SIZE]; }; //////////////////////////////////////////////////////////////////////////////////////// @@ -49,57 +49,57 @@ struct __attribute__ ((__packed__))dstar_dvframe class CDvFramePacket : public CPacket { -friend class CCodecStream; + friend class CCodecStream; public: - // constructor - CDvFramePacket(); - CDvFramePacket(const struct dstar_dvframe *, uint16, uint8); + // constructor + CDvFramePacket(); + CDvFramePacket(const struct dstar_dvframe *, uint16, uint8); #ifndef NO_XLX - CDvFramePacket(const uint8 *, const uint8 *, uint16, uint8, uint8); - CDvFramePacket(const uint8 *, uint16, uint8, uint8, uint8); - CDvFramePacket(uint16, uint8, const uint8 *, const uint8 *, uint8, uint8, const uint8 *, const uint8 *); + CDvFramePacket(const uint8 *, const uint8 *, uint16, uint8, uint8); + CDvFramePacket(const uint8 *, uint16, uint8, uint8, uint8); + CDvFramePacket(uint16, uint8, const uint8 *, const uint8 *, uint8, uint8, const uint8 *, const uint8 *); #endif - // virtual duplication - CPacket *Duplicate(void) const; + // virtual duplication + CPacket *Duplicate(void) const; - // identity - bool IsDvFrame(void) const { return true; } + // identity + bool IsDvFrame(void) const { return true; } #ifndef NO_XLX - bool HaveTranscodableAmbe(void) const { return true; } + bool HaveTranscodableAmbe(void) const { return true; } #endif - // get - const uint8 *GetAmbe(uint8) const; - const uint8 *GetAmbe(void) const { return m_uiAmbe; } + // get + const uint8 *GetAmbe(uint8) const; + const uint8 *GetAmbe(void) const { return m_uiAmbe; } #ifndef NO_XLX - const uint8 *GetAmbePlus(void) const { return m_uiAmbePlus; } - const uint8 *GetDvSync(void) const { return m_uiDvSync; } + const uint8 *GetAmbePlus(void) const { return m_uiAmbePlus; } + const uint8 *GetDvSync(void) const { return m_uiDvSync; } #endif - const uint8 *GetDvData(void) const { return m_uiDvData; } + const uint8 *GetDvData(void) const { return m_uiDvData; } - // set - void SetDvData(uint8 *); - void SetAmbe(uint8, uint8 *); + // set + void SetDvData(uint8 *); + void SetAmbe(uint8, uint8 *); - // operators - bool operator ==(const CDvFramePacket &) const; + // operators + bool operator ==(const CDvFramePacket &) const; protected: - // get - uint8 *GetAmbeData(void) { return m_uiAmbe; } + // get + uint8 *GetAmbeData(void) { return m_uiAmbe; } #ifndef NO_XLX - uint8 *GetAmbePlusData(void) { return m_uiAmbePlus; } + uint8 *GetAmbePlusData(void) { return m_uiAmbePlus; } #endif protected: - // data (dstar) - uint8 m_uiAmbe[AMBE_SIZE]; - uint8 m_uiDvData[DVDATA_SIZE]; + // data (dstar) + uint8 m_uiAmbe[AMBE_SIZE]; + uint8 m_uiDvData[DVDATA_SIZE]; #ifndef NO_XLX - // data (dmr) - uint8 m_uiAmbePlus[AMBEPLUS_SIZE]; - uint8 m_uiDvSync[DVSYNC_SIZE]; + // data (dmr) + uint8 m_uiAmbePlus[AMBEPLUS_SIZE]; + uint8 m_uiDvSync[DVSYNC_SIZE]; #endif }; diff --git a/src/cdvheaderpacket.cpp b/src/cdvheaderpacket.cpp index b6f4a2b..df15628 100644 --- a/src/cdvheaderpacket.cpp +++ b/src/cdvheaderpacket.cpp @@ -33,57 +33,57 @@ CDvHeaderPacket::CDvHeaderPacket() { - m_uiFlag1 = 0; - m_uiFlag2 = 0; - m_uiFlag3 = 0; - m_uiCrc = 0; + m_uiFlag1 = 0; + m_uiFlag2 = 0; + m_uiFlag3 = 0; + m_uiCrc = 0; } // dstar constructor CDvHeaderPacket::CDvHeaderPacket(const struct dstar_header *buffer, uint16 sid, uint8 pid) - : CPacket(sid, pid) + : CPacket(sid, pid) { - m_uiFlag1 = buffer->Flag1; - m_uiFlag2 = buffer->Flag2; - m_uiFlag3 = buffer->Flag3; - m_csUR.SetCallsign(buffer->UR, CALLSIGN_LEN); - m_csRPT1.SetCallsign(buffer->RPT1, CALLSIGN_LEN); - m_csRPT2.SetCallsign(buffer->RPT2, CALLSIGN_LEN); - m_csMY.SetCallsign(buffer->MY, CALLSIGN_LEN); - m_csMY.SetSuffix(buffer->SUFFIX, CALLSUFFIX_LEN); - m_uiCrc = buffer->Crc; + m_uiFlag1 = buffer->Flag1; + m_uiFlag2 = buffer->Flag2; + m_uiFlag3 = buffer->Flag3; + m_csUR.SetCallsign(buffer->UR, CALLSIGN_LEN); + m_csRPT1.SetCallsign(buffer->RPT1, CALLSIGN_LEN); + m_csRPT2.SetCallsign(buffer->RPT2, CALLSIGN_LEN); + m_csMY.SetCallsign(buffer->MY, CALLSIGN_LEN); + m_csMY.SetSuffix(buffer->SUFFIX, CALLSUFFIX_LEN); + m_uiCrc = buffer->Crc; } #ifndef NO_XLX // dmr constructor CDvHeaderPacket::CDvHeaderPacket(uint32 my, const CCallsign &ur, const CCallsign &rpt1, const CCallsign &rpt2, uint16 sid, uint8 pid, uint8 spid) - : CPacket(sid, pid, spid) + : CPacket(sid, pid, spid) { - m_uiFlag1 = 0; - m_uiFlag2 = 0; - m_uiFlag3 = 0; - m_uiCrc = 0; - m_csUR = ur; - m_csRPT1 = rpt1; - m_csRPT2 = rpt2; - m_csMY = CCallsign("", my); + m_uiFlag1 = 0; + m_uiFlag2 = 0; + m_uiFlag3 = 0; + m_uiCrc = 0; + m_csUR = ur; + m_csRPT1 = rpt1; + m_csRPT2 = rpt2; + m_csMY = CCallsign("", my); } // YSF constructor CDvHeaderPacket::CDvHeaderPacket(const CCallsign &my, const CCallsign &ur, const CCallsign &rpt1, const CCallsign &rpt2, uint16 sid, uint8 pid) -: CPacket(sid, pid, 0, 0) + : CPacket(sid, pid, 0, 0) { - m_uiFlag1 = 0; - m_uiFlag2 = 0; - m_uiFlag3 = 0; - m_uiCrc = 0; - m_csUR = ur; - m_csRPT1 = rpt1; - m_csRPT2 = rpt2; - m_csMY = my; + m_uiFlag1 = 0; + m_uiFlag2 = 0; + m_uiFlag3 = 0; + m_uiCrc = 0; + m_csUR = ur; + m_csRPT1 = rpt1; + m_csRPT2 = rpt2; + m_csMY = my; } #endif @@ -92,7 +92,7 @@ CDvHeaderPacket::CDvHeaderPacket(const CCallsign &my, const CCallsign &ur, const CPacket *CDvHeaderPacket::Duplicate(void) const { - return new CDvHeaderPacket(*this); + return new CDvHeaderPacket(*this); } //////////////////////////////////////////////////////////////////////////////////////// @@ -100,16 +100,16 @@ CPacket *CDvHeaderPacket::Duplicate(void) const void CDvHeaderPacket::ConvertToDstarStruct(struct dstar_header *buffer) const { - ::memset(buffer, 0, sizeof(struct dstar_header)); - buffer->Flag1 = m_uiFlag1; - buffer->Flag2 = m_uiFlag2; - buffer->Flag3 = m_uiFlag3; - m_csUR.GetCallsign(buffer->UR); - m_csRPT1.GetCallsign(buffer->RPT1); - m_csRPT2.GetCallsign(buffer->RPT2); - m_csMY.GetCallsign(buffer->MY); - m_csMY.GetSuffix(buffer->SUFFIX); - buffer->Crc = m_uiCrc; + ::memset(buffer, 0, sizeof(struct dstar_header)); + buffer->Flag1 = m_uiFlag1; + buffer->Flag2 = m_uiFlag2; + buffer->Flag3 = m_uiFlag3; + m_csUR.GetCallsign(buffer->UR); + m_csRPT1.GetCallsign(buffer->RPT1); + m_csRPT2.GetCallsign(buffer->RPT2); + m_csMY.GetCallsign(buffer->MY); + m_csMY.GetSuffix(buffer->SUFFIX); + buffer->Crc = m_uiCrc; } @@ -118,13 +118,13 @@ void CDvHeaderPacket::ConvertToDstarStruct(struct dstar_header *buffer) const bool CDvHeaderPacket::IsValid(void) const { - bool valid = CPacket::IsValid(); + bool valid = CPacket::IsValid(); - valid &= m_csRPT1.IsValid(); - valid &= m_csRPT2.IsValid(); - valid &= m_csMY.IsValid(); + valid &= m_csRPT1.IsValid(); + valid &= m_csRPT2.IsValid(); + valid &= m_csMY.IsValid(); - return valid; + return valid; } @@ -133,13 +133,13 @@ bool CDvHeaderPacket::IsValid(void) const bool CDvHeaderPacket::operator ==(const CDvHeaderPacket &Header) const { - return ( (m_uiFlag1 == Header.m_uiFlag1) && - (m_uiFlag2 == Header.m_uiFlag2) && - (m_uiFlag3 == Header.m_uiFlag3) && - (m_csUR == Header.m_csUR) && - (m_csRPT1 == Header.m_csRPT1) && - (m_csRPT2 == Header.m_csRPT2) && - (m_csMY == Header.m_csMY) ); + return ( (m_uiFlag1 == Header.m_uiFlag1) && + (m_uiFlag2 == Header.m_uiFlag2) && + (m_uiFlag3 == Header.m_uiFlag3) && + (m_csUR == Header.m_csUR) && + (m_csRPT1 == Header.m_csRPT1) && + (m_csRPT2 == Header.m_csRPT2) && + (m_csMY == Header.m_csMY) ); } #ifdef IMPLEMENT_CDVHEADERPACKET_CONST_CHAR_OPERATOR @@ -147,13 +147,13 @@ CDvHeaderPacket::operator const char *() const { char *sz = (char *)(const char *)m_sz; - std::sprintf(sz, "%02X %02X %02X\n%s\n%s\n%s\n%s", - m_uiFlag1, m_uiFlag2, m_uiFlag3, - (const char *)m_csUR, - (const char *)m_csRPT1, - (const char *)m_csRPT2, - (const char *)m_csMY); + std::sprintf(sz, "%02X %02X %02X\n%s\n%s\n%s\n%s", + m_uiFlag1, m_uiFlag2, m_uiFlag3, + (const char *)m_csUR, + (const char *)m_csRPT1, + (const char *)m_csRPT2, + (const char *)m_csMY); - return m_sz; + return m_sz; } #endif diff --git a/src/cdvheaderpacket.h b/src/cdvheaderpacket.h index 1535e78..dff33b1 100644 --- a/src/cdvheaderpacket.h +++ b/src/cdvheaderpacket.h @@ -38,18 +38,18 @@ struct __attribute__ ((__packed__))dstar_header { - // flags - uint8 Flag1; - uint8 Flag2; - uint8 Flag3; - // callsigns - uint8 RPT2[CALLSIGN_LEN]; - uint8 RPT1[CALLSIGN_LEN]; - uint8 UR[CALLSIGN_LEN]; - uint8 MY[CALLSIGN_LEN]; - uint8 SUFFIX[CALLSUFFIX_LEN]; - // crc - uint16 Crc; + // flags + uint8 Flag1; + uint8 Flag2; + uint8 Flag3; + // callsigns + uint8 RPT2[CALLSIGN_LEN]; + uint8 RPT1[CALLSIGN_LEN]; + uint8 UR[CALLSIGN_LEN]; + uint8 MY[CALLSIGN_LEN]; + uint8 SUFFIX[CALLSUFFIX_LEN]; + // crc + uint16 Crc; }; @@ -59,61 +59,61 @@ struct __attribute__ ((__packed__))dstar_header class CDvHeaderPacket : public CPacket { public: - // constructor - CDvHeaderPacket(); - CDvHeaderPacket(const struct dstar_header *, uint16, uint8); + // constructor + CDvHeaderPacket(); + CDvHeaderPacket(const struct dstar_header *, uint16, uint8); #ifndef NO_XLX - CDvHeaderPacket(uint32, const CCallsign &, const CCallsign &, const CCallsign &, uint16, uint8, uint8); - CDvHeaderPacket(const CCallsign &, const CCallsign &, const CCallsign &, const CCallsign &, uint16, uint8); + CDvHeaderPacket(uint32, const CCallsign &, const CCallsign &, const CCallsign &, uint16, uint8, uint8); + CDvHeaderPacket(const CCallsign &, const CCallsign &, const CCallsign &, const CCallsign &, uint16, uint8); #endif - // virtual duplication - CPacket *Duplicate(void) const; + // virtual duplication + CPacket *Duplicate(void) const; - // identity - bool IsDvHeader(void) const { return true; } + // identity + bool IsDvHeader(void) const { return true; } - // conversion - void ConvertToDstarStruct(struct dstar_header *) const; + // conversion + void ConvertToDstarStruct(struct dstar_header *) const; - // get valid - bool IsValid(void) const; + // get valid + bool IsValid(void) const; - // get callsigns - const CCallsign &GetUrCallsign(void) const { return m_csUR; } - const CCallsign &GetRpt1Callsign(void) const { return m_csRPT1; } - const CCallsign &GetRpt2Callsign(void) const { return m_csRPT2; } - const CCallsign &GetMyCallsign(void) const { return m_csMY; } + // get callsigns + const CCallsign &GetUrCallsign(void) const { return m_csUR; } + const CCallsign &GetRpt1Callsign(void) const { return m_csRPT1; } + const CCallsign &GetRpt2Callsign(void) const { return m_csRPT2; } + const CCallsign &GetMyCallsign(void) const { return m_csMY; } - // get modules - char GetUrModule(void) const { return m_csUR.GetModule(); } - char GetRpt1Module(void) const { return m_csRPT1.GetModule(); } - char GetRpt2Module(void) const { return m_csRPT2.GetModule(); } - char GetMyModule(void) const { return m_csMY.GetModule(); } + // get modules + char GetUrModule(void) const { return m_csUR.GetModule(); } + char GetRpt1Module(void) const { return m_csRPT1.GetModule(); } + char GetRpt2Module(void) const { return m_csRPT2.GetModule(); } + char GetMyModule(void) const { return m_csMY.GetModule(); } - // set callsigns - void SetRpt2Callsign(const CCallsign &cs) { m_csRPT2 = cs; } - void SetRpt2Module(char c) { m_csRPT2.SetModule(c); } + // set callsigns + void SetRpt2Callsign(const CCallsign &cs) { m_csRPT2 = cs; } + void SetRpt2Module(char c) { m_csRPT2.SetModule(c); } - // operators - bool operator ==(const CDvHeaderPacket &) const; + // operators + bool operator ==(const CDvHeaderPacket &) const; #ifdef IMPLEMENT_CDVHEADERPACKET_CONST_CHAR_OPERATOR - operator const char *() const; + operator const char *() const; #endif protected: - // data - uint8 m_uiFlag1; - uint8 m_uiFlag2; - uint8 m_uiFlag3; - CCallsign m_csUR; - CCallsign m_csRPT1; - CCallsign m_csRPT2; - CCallsign m_csMY; - uint16 m_uiCrc; + // data + uint8 m_uiFlag1; + uint8 m_uiFlag2; + uint8 m_uiFlag3; + CCallsign m_csUR; + CCallsign m_csRPT1; + CCallsign m_csRPT2; + CCallsign m_csMY; + uint16 m_uiCrc; #ifdef IMPLEMENT_CDVHEADERPACKET_CONST_CHAR_OPERATOR - // buffer - char m_sz[256]; + // buffer + char m_sz[256]; #endif }; diff --git a/src/cdvlastframepacket.cpp b/src/cdvlastframepacket.cpp index b00c764..06731cd 100644 --- a/src/cdvlastframepacket.cpp +++ b/src/cdvlastframepacket.cpp @@ -36,7 +36,7 @@ CDvLastFramePacket::CDvLastFramePacket() // dstar constructor CDvLastFramePacket::CDvLastFramePacket(const struct dstar_dvframe *DvFrame, uint16 sid, uint8 pid) - : CDvFramePacket(DvFrame, sid, pid) + : CDvFramePacket(DvFrame, sid, pid) { } @@ -44,24 +44,24 @@ CDvLastFramePacket::CDvLastFramePacket(const struct dstar_dvframe *DvFrame, uint // dmr constructor CDvLastFramePacket::CDvLastFramePacket(const uint8 *ambe, const uint8 *sync, uint16 sid, uint8 pid, uint8 spid) - : CDvFramePacket(ambe, sync, sid, pid, spid) + : CDvFramePacket(ambe, sync, sid, pid, spid) { } // dstar + dmr constructor CDvLastFramePacket::CDvLastFramePacket - (uint16 sid, - uint8 dstarpid, const uint8 *dstarambe, const uint8 *dstardvdata, - uint8 dmrpid, uint8 dprspid, const uint8 *dmrambe, const uint8 *dmrsync) - : CDvFramePacket(sid, dstarpid, dstarambe, dstardvdata, dmrpid, dprspid, dmrambe, dmrsync) +(uint16 sid, + uint8 dstarpid, const uint8 *dstarambe, const uint8 *dstardvdata, + uint8 dmrpid, uint8 dprspid, const uint8 *dmrambe, const uint8 *dmrsync) + : CDvFramePacket(sid, dstarpid, dstarambe, dstardvdata, dmrpid, dprspid, dmrambe, dmrsync) { } // ysf constructor CDvLastFramePacket::CDvLastFramePacket(const uint8 *ambe, uint16 sid, uint8 pid, uint8 spid, uint8 fid) - : CDvFramePacket(ambe, sid, pid, spid, fid) + : CDvFramePacket(ambe, sid, pid, spid, fid) { } #endif @@ -70,7 +70,7 @@ CDvLastFramePacket::CDvLastFramePacket(const uint8 *ambe, uint16 sid, uint8 pid, // copy constructor CDvLastFramePacket::CDvLastFramePacket(const CDvLastFramePacket &DvFrame) - : CDvFramePacket(DvFrame) + : CDvFramePacket(DvFrame) { } @@ -79,5 +79,5 @@ CDvLastFramePacket::CDvLastFramePacket(const CDvLastFramePacket &DvFrame) CPacket *CDvLastFramePacket::Duplicate(void) const { - return new CDvLastFramePacket(*this); + return new CDvLastFramePacket(*this); } diff --git a/src/cdvlastframepacket.h b/src/cdvlastframepacket.h index 6ca0fc6..1663d5e 100644 --- a/src/cdvlastframepacket.h +++ b/src/cdvlastframepacket.h @@ -38,22 +38,22 @@ class CDvLastFramePacket : public CDvFramePacket { public: - // constructor - CDvLastFramePacket(); - CDvLastFramePacket(const struct dstar_dvframe *, uint16, uint8); + // constructor + CDvLastFramePacket(); + CDvLastFramePacket(const struct dstar_dvframe *, uint16, uint8); #ifndef NO_XLX - CDvLastFramePacket(const uint8 *, const uint8 *, uint16, uint8, uint8); - CDvLastFramePacket(const uint8 *, uint16, uint8, uint8, uint8); - CDvLastFramePacket(uint16, uint8, const uint8 *, const uint8 *, uint8, uint8, const uint8 *, const uint8 *); + CDvLastFramePacket(const uint8 *, const uint8 *, uint16, uint8, uint8); + CDvLastFramePacket(const uint8 *, uint16, uint8, uint8, uint8); + CDvLastFramePacket(uint16, uint8, const uint8 *, const uint8 *, uint8, uint8, const uint8 *, const uint8 *); #endif - CDvLastFramePacket(const CDvLastFramePacket &); + CDvLastFramePacket(const CDvLastFramePacket &); - // virtual duplication - CPacket *Duplicate(void) const; + // virtual duplication + CPacket *Duplicate(void) const; - // identity - bool IsLastPacket(void) const { return true; } - bool HaveTranscodableAmbe(void) const { return false; } + // identity + bool IsLastPacket(void) const { return true; } + bool HaveTranscodableAmbe(void) const { return false; } }; diff --git a/src/cg3client.cpp b/src/cg3client.cpp index 02ec339..6c06e67 100644 --- a/src/cg3client.cpp +++ b/src/cg3client.cpp @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- #include "main.h" @@ -34,13 +34,13 @@ CG3Client::CG3Client() } CG3Client::CG3Client(const CCallsign &callsign, const CIp &ip, char reflectorModule) - : CClient(callsign, ip, reflectorModule) + : CClient(callsign, ip, reflectorModule) { } CG3Client::CG3Client(const CG3Client &client) - : CClient(client) + : CClient(client) { } @@ -49,6 +49,6 @@ CG3Client::CG3Client(const CG3Client &client) bool CG3Client::IsAlive(void) const { - return (m_LastKeepaliveTime.DurationSinceNow() < G3_KEEPALIVE_TIMEOUT); + return (m_LastKeepaliveTime.DurationSinceNow() < G3_KEEPALIVE_TIMEOUT); } diff --git a/src/cg3client.h b/src/cg3client.h index 5e6b486..36a6b0b 100644 --- a/src/cg3client.h +++ b/src/cg3client.h @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- #ifndef cg3client_h @@ -37,25 +37,25 @@ class CG3Client : public CClient { public: - // constructors - CG3Client(); - CG3Client(const CCallsign &, const CIp &, char = ' '); - CG3Client(const CG3Client &); - - // destructor - virtual ~CG3Client() {}; - - // identity - int GetProtocol(void) const { return PROTOCOL_G3; } - const char *GetProtocolName(void) const { return "Terminal/AP"; } - int GetCodec(void) const { return CODEC_AMBEPLUS; } - bool IsNode(void) const { return true; } - - // status - bool IsAlive(void) const; + // constructors + CG3Client(); + CG3Client(const CCallsign &, const CIp &, char = ' '); + CG3Client(const CG3Client &); + + // destructor + virtual ~CG3Client() {}; + + // identity + int GetProtocol(void) const { return PROTOCOL_G3; } + const char *GetProtocolName(void) const { return "Terminal/AP"; } + int GetCodec(void) const { return CODEC_AMBEPLUS; } + bool IsNode(void) const { return true; } + + // status + bool IsAlive(void) const; protected: - // data + // data }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cg3protocol.cpp b/src/cg3protocol.cpp index bec6c16..00cbf07 100644 --- a/src/cg3protocol.cpp +++ b/src/cg3protocol.cpp @@ -40,18 +40,18 @@ bool CG3Protocol::Initalize(const char */*type*/, const uint16 /*port*/, const bool /*has_ipv4*/, const bool /*has_ipv6*/) { - ReadOptions(); + ReadOptions(); - // init reflector apparent callsign - m_ReflectorCallsign = g_Reflector.GetCallsign(); + // init reflector apparent callsign + m_ReflectorCallsign = g_Reflector.GetCallsign(); - // reset stop flag - keep_running = true; + // reset stop flag + keep_running = true; - // update the reflector callsign + // update the reflector callsign m_ReflectorCallsign.PatchCallsign(0, (const uint8 *)"XLX", 3); - // create our sockets + // create our sockets CIp ip(AF_INET, G3_DV_PORT, g_Reflector.GetListenIPv4()); if ( ip.IsSet() ) { @@ -61,61 +61,62 @@ bool CG3Protocol::Initalize(const char */*type*/, const uint16 /*port*/, const b else return false; - //create helper socket + //create helper socket ip.SetPort(G3_PRESENCE_PORT); - if (! m_PresenceSocket.Open(ip)) { - std::cout << "Error opening socket on port UDP" << G3_PRESENCE_PORT << " on ip " << ip << std::endl; - return false; - } + if (! m_PresenceSocket.Open(ip)) + { + std::cout << "Error opening socket on port UDP" << G3_PRESENCE_PORT << " on ip " << ip << std::endl; + return false; + } ip.SetPort(G3_CONFIG_PORT); - if (! m_ConfigSocket.Open(ip)) + if (! m_ConfigSocket.Open(ip)) { - std::cout << "Error opening G3 config socket on port UDP" << G3_CONFIG_PORT << " on ip " << ip << std::endl; + std::cout << "Error opening G3 config socket on port UDP" << G3_CONFIG_PORT << " on ip " << ip << std::endl; return false; } - if (! m_IcmpRawSocket.Open(IPPROTO_ICMP)) - { - std::cout << "Error opening raw socket for ICMP" << std::endl; + if (! m_IcmpRawSocket.Open(IPPROTO_ICMP)) + { + std::cout << "Error opening raw socket for ICMP" << std::endl; return false; - } + } - // start helper threads + // start helper threads m_pThread = new std::thread(CProtocol::Thread, this); m_pPresenceThread = new std::thread(PresenceThread, this); m_pPresenceThread = new std::thread(ConfigThread, this); m_pPresenceThread = new std::thread(IcmpThread, this); - // update time - m_LastKeepaliveTime.Now(); + // update time + m_LastKeepaliveTime.Now(); - // done - return true; + // done + return true; } void CG3Protocol::Close(void) { - if (m_pPresenceThread != nullptr) - { - m_pPresenceThread->join(); - delete m_pPresenceThread; - m_pPresenceThread = nullptr; - } - - if (m_pConfigThread != nullptr) - { - m_pConfigThread->join(); - delete m_pConfigThread; - m_pConfigThread = nullptr; - } - - if (m_pIcmpThread != nullptr) - { - m_pIcmpThread->join(); - delete m_pIcmpThread; - m_pIcmpThread = nullptr; - } + if (m_pPresenceThread != nullptr) + { + m_pPresenceThread->join(); + delete m_pPresenceThread; + m_pPresenceThread = nullptr; + } + + if (m_pConfigThread != nullptr) + { + m_pConfigThread->join(); + delete m_pConfigThread; + m_pConfigThread = nullptr; + } + + if (m_pIcmpThread != nullptr) + { + m_pIcmpThread->join(); + delete m_pIcmpThread; + m_pIcmpThread = nullptr; + } } @@ -124,26 +125,26 @@ void CG3Protocol::Close(void) void CG3Protocol::PresenceThread(CG3Protocol *This) { - while (This->keep_running) - { - This->PresenceTask(); - } + while (This->keep_running) + { + This->PresenceTask(); + } } void CG3Protocol::ConfigThread(CG3Protocol *This) { - while (This->keep_running) - { - This->ConfigTask(); - } + while (This->keep_running) + { + This->ConfigTask(); + } } void CG3Protocol::IcmpThread(CG3Protocol *This) { - while (This->keep_running) - { - This->IcmpTask(); - } + while (This->keep_running) + { + This->IcmpTask(); + } } @@ -152,95 +153,95 @@ void CG3Protocol::IcmpThread(CG3Protocol *This) void CG3Protocol::PresenceTask(void) { - CBuffer Buffer; - CIp ReqIp; - CCallsign Callsign; - CCallsign Owner; - CCallsign Terminal; - - - if ( m_PresenceSocket.Receive(Buffer, ReqIp, 20) ) - { - - CIp Ip(ReqIp); - Ip.SetPort(G3_DV_PORT); - - if (Buffer.size() == 32) - { - Callsign.SetCallsign(&Buffer.data()[8], 8); - Owner.SetCallsign(&Buffer.data()[16], 8); - Terminal.SetCallsign(&Buffer.data()[24], 8); - - std::cout << "Presence from " << Ip << " as " << Callsign << " on terminal " << Terminal << std::endl; - - // accept - Buffer.data()[2] = 0x80; // response - Buffer.data()[3] = 0x00; // ok - - if (m_GwAddress == 0) - { - Buffer.Append(*(uint32 *)m_ConfigSocket.GetLocalAddr()); - } - else - { - Buffer.Append(m_GwAddress); - } - - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrextant = nullptr; - while ( (extant = clients->FindNextClient(PROTOCOL_G3, it)) != nullptr ) - { - CIp ClIp = extant->GetIp(); - if (ClIp.GetAddr() == Ip.GetAddr()) - { - break; - } - } - - if (extant == nullptr) - { - it = clients->begin(); - - // do we already have a client with the same call (IP changed)? - while ( (extant = clients->FindNextClient(PROTOCOL_G3, it)) != nullptr ) - { - { - if (extant->GetCallsign().HasSameCallsign(Terminal)) - { - //delete old client - clients->RemoveClient(extant); - break; - } - } - } - - // create new client - CG3Client *client = new CG3Client(Terminal, Ip); - - // and append - clients->AddClient(client); - } - else - { - // client changed callsign - if (!extant->GetCallsign().HasSameCallsign(Terminal)) - { - //delete old client - clients->RemoveClient(extant); - - // create new client - CG3Client *client = new CG3Client(Terminal, Ip); - - // and append - clients->AddClient(client); - } - } - g_Reflector.ReleaseClients(); - - m_PresenceSocket.Send(Buffer, ReqIp); - } - } + CBuffer Buffer; + CIp ReqIp; + CCallsign Callsign; + CCallsign Owner; + CCallsign Terminal; + + + if ( m_PresenceSocket.Receive(Buffer, ReqIp, 20) ) + { + + CIp Ip(ReqIp); + Ip.SetPort(G3_DV_PORT); + + if (Buffer.size() == 32) + { + Callsign.SetCallsign(&Buffer.data()[8], 8); + Owner.SetCallsign(&Buffer.data()[16], 8); + Terminal.SetCallsign(&Buffer.data()[24], 8); + + std::cout << "Presence from " << Ip << " as " << Callsign << " on terminal " << Terminal << std::endl; + + // accept + Buffer.data()[2] = 0x80; // response + Buffer.data()[3] = 0x00; // ok + + if (m_GwAddress == 0) + { + Buffer.Append(*(uint32 *)m_ConfigSocket.GetLocalAddr()); + } + else + { + Buffer.Append(m_GwAddress); + } + + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrextant = nullptr; + while ( (extant = clients->FindNextClient(PROTOCOL_G3, it)) != nullptr ) + { + CIp ClIp = extant->GetIp(); + if (ClIp.GetAddr() == Ip.GetAddr()) + { + break; + } + } + + if (extant == nullptr) + { + it = clients->begin(); + + // do we already have a client with the same call (IP changed)? + while ( (extant = clients->FindNextClient(PROTOCOL_G3, it)) != nullptr ) + { + { + if (extant->GetCallsign().HasSameCallsign(Terminal)) + { + //delete old client + clients->RemoveClient(extant); + break; + } + } + } + + // create new client + CG3Client *client = new CG3Client(Terminal, Ip); + + // and append + clients->AddClient(client); + } + else + { + // client changed callsign + if (!extant->GetCallsign().HasSameCallsign(Terminal)) + { + //delete old client + clients->RemoveClient(extant); + + // create new client + CG3Client *client = new CG3Client(Terminal, Ip); + + // and append + clients->AddClient(client); + } + } + g_Reflector.ReleaseClients(); + + m_PresenceSocket.Send(Buffer, ReqIp); + } + } } @@ -249,103 +250,103 @@ void CG3Protocol::PresenceTask(void) void CG3Protocol::ConfigTask(void) { - CBuffer Buffer; - CIp Ip; - CCallsign Call; - bool isRepeaterCall; - - if ( m_ConfigSocket.Receive(&Buffer, &Ip, 20) != -1 ) - { - - if (Buffer.size() == 16) - { - if (memcmp(&Buffer.data()[8], " ", 8) == 0) - { - Call.SetCallsign(GetReflectorCallsign(), 8); - } - else - { - Call.SetCallsign(&Buffer.data()[8], 8); - } - - isRepeaterCall = ((Buffer.data()[2] & 0x10) == 0x10); - - std::cout << "Config request from " << Ip << " for " << Call << " (" << ((char *)(isRepeaterCall)?"repeater":"routed") << ")" << std::endl; - - //std::cout << "Local address: " << inet_ntoa(*m_ConfigSocket.GetLocalAddr()) << std::endl; - - Buffer.data()[2] |= 0x80; // response - - if (isRepeaterCall) - { - if ((Call.HasSameCallsign(GetReflectorCallsign())) && (g_Reflector.IsValidModule(Call.GetModule()))) - { - Buffer.data()[3] = 0x00; // ok - } - else - { - std::cout << "Module " << Call << " invalid" << std::endl; - Buffer.data()[3] = 0x01; // reject - } - } - else - { - // reject routed calls for now - Buffer.data()[3] = 0x01; // reject - } - - char module = Call.GetModule(); - - if (!strchr(m_Modules.c_str(), module) && !strchr(m_Modules.c_str(), '*')) - { - // restricted - std::cout << "Module " << Call << " restricted by configuration" << std::endl; - Buffer.data()[3] = 0x01; // reject - } - - // UR - Buffer.resize(8); - Buffer.Append((uint8 *)(const char *)Call, CALLSIGN_LEN - 1); - Buffer.Append((uint8)module); - - // RPT1 - Buffer.Append((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN - 1); - Buffer.Append((uint8)'G'); - - // RPT2 - Buffer.Append((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN - 1); - - if (isRepeaterCall) - { - Buffer.Append((uint8)Call.GetModule()); - } - else - { - // routed - no module for now - Buffer.Append((uint8)' '); - } - - if (Buffer.data()[3] == 0x00) - { - std::cout << "External G3 gateway address " << inet_ntoa(*(in_addr *)&m_GwAddress) << std::endl; - - if (m_GwAddress == 0) - { - Buffer.Append(*(uint32 *)m_ConfigSocket.GetLocalAddr()); - } - else - { - Buffer.Append(m_GwAddress); - } - } - else - { - Buffer.Append(0u); - } - - m_ConfigSocket.Send(Buffer, Ip); - } - } + CBuffer Buffer; + CIp Ip; + CCallsign Call; + bool isRepeaterCall; + + if ( m_ConfigSocket.Receive(&Buffer, &Ip, 20) != -1 ) + { + + if (Buffer.size() == 16) + { + if (memcmp(&Buffer.data()[8], " ", 8) == 0) + { + Call.SetCallsign(GetReflectorCallsign(), 8); + } + else + { + Call.SetCallsign(&Buffer.data()[8], 8); + } + + isRepeaterCall = ((Buffer.data()[2] & 0x10) == 0x10); + + std::cout << "Config request from " << Ip << " for " << Call << " (" << ((char *)(isRepeaterCall)?"repeater":"routed") << ")" << std::endl; + + //std::cout << "Local address: " << inet_ntoa(*m_ConfigSocket.GetLocalAddr()) << std::endl; + + Buffer.data()[2] |= 0x80; // response + + if (isRepeaterCall) + { + if ((Call.HasSameCallsign(GetReflectorCallsign())) && (g_Reflector.IsValidModule(Call.GetModule()))) + { + Buffer.data()[3] = 0x00; // ok + } + else + { + std::cout << "Module " << Call << " invalid" << std::endl; + Buffer.data()[3] = 0x01; // reject + } + } + else + { + // reject routed calls for now + Buffer.data()[3] = 0x01; // reject + } + + char module = Call.GetModule(); + + if (!strchr(m_Modules.c_str(), module) && !strchr(m_Modules.c_str(), '*')) + { + // restricted + std::cout << "Module " << Call << " restricted by configuration" << std::endl; + Buffer.data()[3] = 0x01; // reject + } + + // UR + Buffer.resize(8); + Buffer.Append((uint8 *)(const char *)Call, CALLSIGN_LEN - 1); + Buffer.Append((uint8)module); + + // RPT1 + Buffer.Append((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN - 1); + Buffer.Append((uint8)'G'); + + // RPT2 + Buffer.Append((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN - 1); + + if (isRepeaterCall) + { + Buffer.Append((uint8)Call.GetModule()); + } + else + { + // routed - no module for now + Buffer.Append((uint8)' '); + } + + if (Buffer.data()[3] == 0x00) + { + std::cout << "External G3 gateway address " << inet_ntoa(*(in_addr *)&m_GwAddress) << std::endl; + + if (m_GwAddress == 0) + { + Buffer.Append(*(uint32 *)m_ConfigSocket.GetLocalAddr()); + } + else + { + Buffer.Append(m_GwAddress); + } + } + else + { + Buffer.Append(0u); + } + + m_ConfigSocket.Send(Buffer, Ip); + } + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -353,28 +354,28 @@ void CG3Protocol::ConfigTask(void) void CG3Protocol::IcmpTask(void) { - CBuffer Buffer; - CIp Ip; - int iIcmpType; - - if ((iIcmpType = m_IcmpRawSocket.IcmpReceive(&Buffer, &Ip, 20)) != -1) - { - if (iIcmpType == ICMP_DEST_UNREACH) - { - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_G3, it)) != nullptr ) - { - CIp ClientIp = client->GetIp(); - if (ClientIp.GetAddr() == Ip.GetAddr()) - { - clients->RemoveClient(client); - } - } - g_Reflector.ReleaseClients(); - } - } + CBuffer Buffer; + CIp Ip; + int iIcmpType; + + if ((iIcmpType = m_IcmpRawSocket.IcmpReceive(&Buffer, &Ip, 20)) != -1) + { + if (iIcmpType == ICMP_DEST_UNREACH) + { + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_G3, it)) != nullptr ) + { + CIp ClientIp = client->GetIp(); + if (ClientIp.GetAddr() == Ip.GetAddr()) + { + clients->RemoveClient(client); + } + } + g_Reflector.ReleaseClients(); + } + } } @@ -383,100 +384,100 @@ void CG3Protocol::IcmpTask(void) void CG3Protocol::Task(void) { - CBuffer Buffer; - CIp Ip; - CCallsign Callsign; - char ToLinkModule; - int ProtRev; - CDvHeaderPacket *Header; - CDvFramePacket *Frame; - CDvLastFramePacket *LastFrame; - - // any incoming packet ? - if ( m_Socket4.Receive(Buffer, Ip, 20) ) - { - CIp ClIp; - CIp *BaseIp = nullptr; - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_G3, it)) != nullptr ) - { - ClIp = client->GetIp(); - if (ClIp.GetAddr() == Ip.GetAddr()) - { - BaseIp = &ClIp; - client->Alive(); - // supress host checks - no ping needed to trigger potential ICMPs - // the regular data flow will do it - m_LastKeepaliveTime.Now(); - break; - } - } - g_Reflector.ReleaseClients(); - - if (BaseIp != nullptr) - { - // crack the packet - if ( (Frame = IsValidDvFramePacket(Buffer)) != nullptr ) - { - //std::cout << "Terminal DV frame" << std::endl; - - // handle it - OnDvFramePacketIn(Frame, BaseIp); - } - else if ( (Header = IsValidDvHeaderPacket(Buffer)) != nullptr ) - { - //std::cout << "Terminal DV header" << std::endl; - - // callsign muted? - if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_G3, Header->GetRpt2Module()) ) - { - // handle it - OnDvHeaderPacketIn(Header, *BaseIp); - } - else - { - delete Header; - } - } - else if ( (LastFrame = IsValidDvLastFramePacket(Buffer)) != nullptr ) - { - //std::cout << "Terminal DV last frame" << std::endl; - - // handle it - OnDvLastFramePacketIn(LastFrame, BaseIp); - } - else - { - //std::cout << "Invalid terminal packet (" << Buffer.size() << ")" << std::endl; - //std::cout << Buffer.data() << std::endl; - } - } - else - { - //std::cout << "Invalid client " << Ip << std::endl; - } - } - - // handle end of streaming timeout - CheckStreamsTimeout(); - - // handle queue from reflector - HandleQueue(); - - // keep alive during idle if needed - if ( m_LastKeepaliveTime.DurationSinceNow() > G3_KEEPALIVE_PERIOD ) - { - // handle keep alives - HandleKeepalives(); - - // update time - m_LastKeepaliveTime.Now(); - - // reload option if needed - called once every G3_KEEPALIVE_PERIOD - NeedReload(); - } + CBuffer Buffer; + CIp Ip; + CCallsign Callsign; + char ToLinkModule; + int ProtRev; + CDvHeaderPacket *Header; + CDvFramePacket *Frame; + CDvLastFramePacket *LastFrame; + + // any incoming packet ? + if ( m_Socket4.Receive(Buffer, Ip, 20) ) + { + CIp ClIp; + CIp *BaseIp = nullptr; + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_G3, it)) != nullptr ) + { + ClIp = client->GetIp(); + if (ClIp.GetAddr() == Ip.GetAddr()) + { + BaseIp = &ClIp; + client->Alive(); + // supress host checks - no ping needed to trigger potential ICMPs + // the regular data flow will do it + m_LastKeepaliveTime.Now(); + break; + } + } + g_Reflector.ReleaseClients(); + + if (BaseIp != nullptr) + { + // crack the packet + if ( (Frame = IsValidDvFramePacket(Buffer)) != nullptr ) + { + //std::cout << "Terminal DV frame" << std::endl; + + // handle it + OnDvFramePacketIn(Frame, BaseIp); + } + else if ( (Header = IsValidDvHeaderPacket(Buffer)) != nullptr ) + { + //std::cout << "Terminal DV header" << std::endl; + + // callsign muted? + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_G3, Header->GetRpt2Module()) ) + { + // handle it + OnDvHeaderPacketIn(Header, *BaseIp); + } + else + { + delete Header; + } + } + else if ( (LastFrame = IsValidDvLastFramePacket(Buffer)) != nullptr ) + { + //std::cout << "Terminal DV last frame" << std::endl; + + // handle it + OnDvLastFramePacketIn(LastFrame, BaseIp); + } + else + { + //std::cout << "Invalid terminal packet (" << Buffer.size() << ")" << std::endl; + //std::cout << Buffer.data() << std::endl; + } + } + else + { + //std::cout << "Invalid client " << Ip << std::endl; + } + } + + // handle end of streaming timeout + CheckStreamsTimeout(); + + // handle queue from reflector + HandleQueue(); + + // keep alive during idle if needed + if ( m_LastKeepaliveTime.DurationSinceNow() > G3_KEEPALIVE_PERIOD ) + { + // handle keep alives + HandleKeepalives(); + + // update time + m_LastKeepaliveTime.Now(); + + // reload option if needed - called once every G3_KEEPALIVE_PERIOD + NeedReload(); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -484,44 +485,44 @@ void CG3Protocol::Task(void) void CG3Protocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) - { - // supress host checks - m_LastKeepaliveTime.Now(); - - // get the packet - CPacket *packet = m_Queue.front(); - m_Queue.pop(); - - // encode it - CBuffer buffer; - if ( EncodeDvPacket(*packet, &buffer) ) - { - // and push it to all our clients linked to the module and who are not streaming in - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_G3, it)) != nullptr ) - { - // is this client busy ? - if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) ) - { - // not busy, send the packet - int n = packet->IsDvHeader() ? 5 : 1; - for ( int i = 0; i < n; i++ ) - { - Send(buffer, client->GetIp()); - } - } - } - g_Reflector.ReleaseClients(); - } - - // done - delete packet; - } - m_Queue.Unlock(); + m_Queue.Lock(); + while ( !m_Queue.empty() ) + { + // supress host checks + m_LastKeepaliveTime.Now(); + + // get the packet + CPacket *packet = m_Queue.front(); + m_Queue.pop(); + + // encode it + CBuffer buffer; + if ( EncodeDvPacket(*packet, &buffer) ) + { + // and push it to all our clients linked to the module and who are not streaming in + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_G3, it)) != nullptr ) + { + // is this client busy ? + if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) ) + { + // not busy, send the packet + int n = packet->IsDvHeader() ? 5 : 1; + for ( int i = 0; i < n; i++ ) + { + Send(buffer, client->GetIp()); + } + } + } + g_Reflector.ReleaseClients(); + } + + // done + delete packet; + } + m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -529,28 +530,28 @@ void CG3Protocol::HandleQueue(void) void CG3Protocol::HandleKeepalives(void) { - // G3 Terminal mode does not support keepalive - // We will send some short packed and expect - // A ICMP unreachable on failure - CBuffer keepalive((uint8 *)"PING", 4); - - // iterate on clients - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_G3, it)) != nullptr ) - { - if (!client->IsAlive()) - { - clients->RemoveClient(client); - } - else - { - // send keepalive packet - Send(keepalive, client->GetIp()); - } - } - g_Reflector.ReleaseClients(); + // G3 Terminal mode does not support keepalive + // We will send some short packed and expect + // A ICMP unreachable on failure + CBuffer keepalive((uint8 *)"PING", 4); + + // iterate on clients + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_G3, it)) != nullptr ) + { + if (!client->IsAlive()) + { + clients->RemoveClient(client); + } + else + { + // send keepalive packet + Send(keepalive, client->GetIp()); + } + } + g_Reflector.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -558,93 +559,93 @@ void CG3Protocol::HandleKeepalives(void) bool CG3Protocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip) { - bool newstream = false; - - // find the stream - CPacketStream *stream = GetStream(Header->GetStreamId(), &Ip); - - if ( stream == nullptr ) - { - // no stream open yet, open a new one - CCallsign via(Header->GetRpt1Callsign()); - - // find this client - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_G3, it)) != nullptr ) - { - CIp ClIp = client->GetIp(); - if (ClIp.GetAddr() == Ip.GetAddr()) - { - break; - } - } - - if ( client != nullptr ) - { - - // move it to the proper module - if (m_ReflectorCallsign.HasSameCallsign(Header->GetRpt2Callsign())) - { - if (client->GetReflectorModule() != Header->GetRpt2Callsign().GetModule()) - { - char new_module = Header->GetRpt2Callsign().GetModule(); - if (strchr(m_Modules.c_str(), '*') || strchr(m_Modules.c_str(), new_module)) - { - client->SetReflectorModule(new_module); - } - else - { - // drop if invalid module - delete Header; - g_Reflector.ReleaseClients(); - return nullptr; - } - } - - // get client callsign - via = client->GetCallsign(); - - // and try to open the stream - if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) - { - // keep the handle - m_Streams.push_back(stream); - newstream = true; - } - - // update last heard - g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), via, Header->GetRpt2Callsign()); - g_Reflector.ReleaseUsers(); - - // delete header if needed - if ( !newstream ) - { - delete Header; - } - - } - else - { - // drop - delete Header; - } - } - // release - g_Reflector.ReleaseClients(); - } - else - { - // stream already open - // skip packet, but tickle the stream - stream->Tickle(); - // and delete packet - delete Header; - } - - // done - return newstream; + bool newstream = false; + + // find the stream + CPacketStream *stream = GetStream(Header->GetStreamId(), &Ip); + + if ( stream == nullptr ) + { + // no stream open yet, open a new one + CCallsign via(Header->GetRpt1Callsign()); + + // find this client + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_G3, it)) != nullptr ) + { + CIp ClIp = client->GetIp(); + if (ClIp.GetAddr() == Ip.GetAddr()) + { + break; + } + } + + if ( client != nullptr ) + { + + // move it to the proper module + if (m_ReflectorCallsign.HasSameCallsign(Header->GetRpt2Callsign())) + { + if (client->GetReflectorModule() != Header->GetRpt2Callsign().GetModule()) + { + char new_module = Header->GetRpt2Callsign().GetModule(); + if (strchr(m_Modules.c_str(), '*') || strchr(m_Modules.c_str(), new_module)) + { + client->SetReflectorModule(new_module); + } + else + { + // drop if invalid module + delete Header; + g_Reflector.ReleaseClients(); + return nullptr; + } + } + + // get client callsign + via = client->GetCallsign(); + + // and try to open the stream + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) + { + // keep the handle + m_Streams.push_back(stream); + newstream = true; + } + + // update last heard + g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), via, Header->GetRpt2Callsign()); + g_Reflector.ReleaseUsers(); + + // delete header if needed + if ( !newstream ) + { + delete Header; + } + + } + else + { + // drop + delete Header; + } + } + // release + g_Reflector.ReleaseClients(); + } + else + { + // stream already open + // skip packet, but tickle the stream + stream->Tickle(); + // and delete packet + delete Header; + } + + // done + return newstream; } @@ -653,64 +654,64 @@ bool CG3Protocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip) CDvHeaderPacket *CG3Protocol::IsValidDvHeaderPacket(const CBuffer &Buffer) { - CDvHeaderPacket *header = nullptr; - - if ( (Buffer.size() == 56) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) && - (Buffer.data()[4] == 0x10) && (Buffer.data()[8] == 0x20) ) - { - // create packet - header = new CDvHeaderPacket((struct dstar_header *)&(Buffer.data()[15]), - *((uint16 *)&(Buffer.data()[12])), 0x80); - // check validity of packet - if ( !header->IsValid() ) - { - delete header; - header = nullptr; - } - } - return header; + CDvHeaderPacket *header = nullptr; + + if ( (Buffer.size() == 56) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) && + (Buffer.data()[4] == 0x10) && (Buffer.data()[8] == 0x20) ) + { + // create packet + header = new CDvHeaderPacket((struct dstar_header *)&(Buffer.data()[15]), + *((uint16 *)&(Buffer.data()[12])), 0x80); + // check validity of packet + if ( !header->IsValid() ) + { + delete header; + header = nullptr; + } + } + return header; } CDvFramePacket *CG3Protocol::IsValidDvFramePacket(const CBuffer &Buffer) { - CDvFramePacket *dvframe = nullptr; - - if ( (Buffer.size() == 27) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) && - (Buffer.data()[4] == 0x20) && (Buffer.data()[8] == 0x20) && - ((Buffer.data()[14] & 0x40) == 0) ) - { - // create packet - dvframe = new CDvFramePacket((struct dstar_dvframe *)&(Buffer.data()[15]), - *((uint16 *)&(Buffer.data()[12])), Buffer.data()[14]); - // check validity of packet - if ( !dvframe->IsValid() ) - { - delete dvframe; - dvframe = nullptr; - } - } - return dvframe; + CDvFramePacket *dvframe = nullptr; + + if ( (Buffer.size() == 27) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) && + (Buffer.data()[4] == 0x20) && (Buffer.data()[8] == 0x20) && + ((Buffer.data()[14] & 0x40) == 0) ) + { + // create packet + dvframe = new CDvFramePacket((struct dstar_dvframe *)&(Buffer.data()[15]), + *((uint16 *)&(Buffer.data()[12])), Buffer.data()[14]); + // check validity of packet + if ( !dvframe->IsValid() ) + { + delete dvframe; + dvframe = nullptr; + } + } + return dvframe; } CDvLastFramePacket *CG3Protocol::IsValidDvLastFramePacket(const CBuffer &Buffer) { - CDvLastFramePacket *dvframe = nullptr; - - if ( (Buffer.size() == 27) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) && - (Buffer.data()[4] == 0x20) && (Buffer.data()[8] == 0x20) && - ((Buffer.data()[14] & 0x40) != 0) ) - { - // create packet - dvframe = new CDvLastFramePacket((struct dstar_dvframe *)&(Buffer.data()[15]), - *((uint16 *)&(Buffer.data()[12])), Buffer.data()[14]); - // check validity of packet - if ( !dvframe->IsValid() ) - { - delete dvframe; - dvframe = nullptr; - } - } - return dvframe; + CDvLastFramePacket *dvframe = nullptr; + + if ( (Buffer.size() == 27) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) && + (Buffer.data()[4] == 0x20) && (Buffer.data()[8] == 0x20) && + ((Buffer.data()[14] & 0x40) != 0) ) + { + // create packet + dvframe = new CDvLastFramePacket((struct dstar_dvframe *)&(Buffer.data()[15]), + *((uint16 *)&(Buffer.data()[12])), Buffer.data()[14]); + // check validity of packet + if ( !dvframe->IsValid() ) + { + delete dvframe; + dvframe = nullptr; + } + } + return dvframe; } //////////////////////////////////////////////////////////////////////////////////////// @@ -718,44 +719,44 @@ CDvLastFramePacket *CG3Protocol::IsValidDvLastFramePacket(const CBuffer &Buffer) bool CG3Protocol::EncodeDvHeaderPacket(const CDvHeaderPacket &Packet, CBuffer *Buffer) const { - uint8 tag[] = { 'D','S','V','T',0x10,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; - struct dstar_header DstarHeader; + uint8 tag[] = { 'D','S','V','T',0x10,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; + struct dstar_header DstarHeader; - Packet.ConvertToDstarStruct(&DstarHeader); + Packet.ConvertToDstarStruct(&DstarHeader); - Buffer->Set(tag, sizeof(tag)); - Buffer->Append(Packet.GetStreamId()); - Buffer->Append((uint8)0x80); - Buffer->Append((uint8 *)&DstarHeader, sizeof(struct dstar_header)); + Buffer->Set(tag, sizeof(tag)); + Buffer->Append(Packet.GetStreamId()); + Buffer->Append((uint8)0x80); + Buffer->Append((uint8 *)&DstarHeader, sizeof(struct dstar_header)); - return true; + return true; } bool CG3Protocol::EncodeDvFramePacket(const CDvFramePacket &Packet, CBuffer *Buffer) const { - uint8 tag[] = { 'D','S','V','T',0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; + uint8 tag[] = { 'D','S','V','T',0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; - Buffer->Set(tag, sizeof(tag)); - Buffer->Append(Packet.GetStreamId()); - Buffer->Append((uint8)(Packet.GetPacketId() % 21)); - Buffer->Append((uint8 *)Packet.GetAmbe(), AMBE_SIZE); - Buffer->Append((uint8 *)Packet.GetDvData(), DVDATA_SIZE); + Buffer->Set(tag, sizeof(tag)); + Buffer->Append(Packet.GetStreamId()); + Buffer->Append((uint8)(Packet.GetPacketId() % 21)); + Buffer->Append((uint8 *)Packet.GetAmbe(), AMBE_SIZE); + Buffer->Append((uint8 *)Packet.GetDvData(), DVDATA_SIZE); - return true; + return true; } bool CG3Protocol::EncodeDvLastFramePacket(const CDvLastFramePacket &Packet, CBuffer *Buffer) const { - uint8 tag1[] = { 'D','S','V','T',0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; - uint8 tag2[] = { 0x55,0xC8,0x7A,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x1A,0xC6 }; + uint8 tag1[] = { 'D','S','V','T',0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; + uint8 tag2[] = { 0x55,0xC8,0x7A,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x1A,0xC6 }; - Buffer->Set(tag1, sizeof(tag1)); - Buffer->Append(Packet.GetStreamId()); - Buffer->Append((uint8)((Packet.GetPacketId() % 21) | 0x40)); - Buffer->Append(tag2, sizeof(tag2)); + Buffer->Set(tag1, sizeof(tag1)); + Buffer->Append(Packet.GetStreamId()); + Buffer->Append((uint8)((Packet.GetPacketId() % 21) | 0x40)); + Buffer->Append(tag2, sizeof(tag2)); - return true; + return true; } //////////////////////////////////////////////////////////////////////////////////////// @@ -763,99 +764,99 @@ bool CG3Protocol::EncodeDvLastFramePacket(const CDvLastFramePacket &Packet, CBuf char *CG3Protocol::TrimWhiteSpaces(char *str) { - char *end; - while ((*str == ' ') || (*str == '\t')) str++; - if (*str == 0) - return str; - end = str + strlen(str) - 1; - while ((end > str) && ((*end == ' ') || (*end == '\t') || (*end == '\r'))) end --; - *(end + 1) = 0; - return str; + char *end; + while ((*str == ' ') || (*str == '\t')) str++; + if (*str == 0) + return str; + end = str + strlen(str) - 1; + while ((end > str) && ((*end == ' ') || (*end == '\t') || (*end == '\r'))) end --; + *(end + 1) = 0; + return str; } void CG3Protocol::NeedReload(void) { - struct stat fileStat; - - if (::stat(TERMINALOPTIONS_PATH, &fileStat) != -1) - { - if (m_LastModTime != fileStat.st_mtime) - { - ReadOptions(); - - // we have new options - iterate on clients for potential removal - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_G3, it)) != nullptr ) - { - char module = client->GetReflectorModule(); - if (!strchr(m_Modules.c_str(), module) && !strchr(m_Modules.c_str(), '*')) - { - clients->RemoveClient(client); - } - } - g_Reflector.ReleaseClients(); - } - } + struct stat fileStat; + + if (::stat(TERMINALOPTIONS_PATH, &fileStat) != -1) + { + if (m_LastModTime != fileStat.st_mtime) + { + ReadOptions(); + + // we have new options - iterate on clients for potential removal + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_G3, it)) != nullptr ) + { + char module = client->GetReflectorModule(); + if (!strchr(m_Modules.c_str(), module) && !strchr(m_Modules.c_str(), '*')) + { + clients->RemoveClient(client); + } + } + g_Reflector.ReleaseClients(); + } + } } void CG3Protocol::ReadOptions(void) { - char sz[256]; - int opts = 0; - - - std::ifstream file(TERMINALOPTIONS_PATH); - if (file.is_open()) - { - m_GwAddress = 0u; - m_Modules = "*"; - - while (file.getline(sz, sizeof(sz)).good()) - { - char *szt = TrimWhiteSpaces(sz); - char *szval; - - if ((::strlen(szt) > 0) && szt[0] != '#') - { - if ((szt = ::strtok(szt, " ,\t")) != nullptr) - { - if ((szval = ::strtok(nullptr, " ,\t")) != nullptr) - { - if (::strncmp(szt, "address", 7) == 0) - { - in_addr addr = { .s_addr = inet_addr(szval) }; - if (addr.s_addr) - { - std::cout << "G3 handler address set to " << inet_ntoa(addr) << std::endl; - m_GwAddress = addr.s_addr; - opts++; - } - } - else if (strncmp(szt, "modules", 7) == 0) - { - std::cout << "G3 handler module list set to " << szval << std::endl; - m_Modules = szval; - opts++; - } - else - { - // unknown option - ignore - } - } - } - } - } - std::cout << "G3 handler loaded " << opts << " options from file " << TERMINALOPTIONS_PATH << std::endl; - file.close(); - - struct stat fileStat; - - if (::stat(TERMINALOPTIONS_PATH, &fileStat) != -1) - { - m_LastModTime = fileStat.st_mtime; - } - } + char sz[256]; + int opts = 0; + + + std::ifstream file(TERMINALOPTIONS_PATH); + if (file.is_open()) + { + m_GwAddress = 0u; + m_Modules = "*"; + + while (file.getline(sz, sizeof(sz)).good()) + { + char *szt = TrimWhiteSpaces(sz); + char *szval; + + if ((::strlen(szt) > 0) && szt[0] != '#') + { + if ((szt = ::strtok(szt, " ,\t")) != nullptr) + { + if ((szval = ::strtok(nullptr, " ,\t")) != nullptr) + { + if (::strncmp(szt, "address", 7) == 0) + { + in_addr addr = { .s_addr = inet_addr(szval) }; + if (addr.s_addr) + { + std::cout << "G3 handler address set to " << inet_ntoa(addr) << std::endl; + m_GwAddress = addr.s_addr; + opts++; + } + } + else if (strncmp(szt, "modules", 7) == 0) + { + std::cout << "G3 handler module list set to " << szval << std::endl; + m_Modules = szval; + opts++; + } + else + { + // unknown option - ignore + } + } + } + } + } + std::cout << "G3 handler loaded " << opts << " options from file " << TERMINALOPTIONS_PATH << std::endl; + file.close(); + + struct stat fileStat; + + if (::stat(TERMINALOPTIONS_PATH, &fileStat) != -1) + { + m_LastModTime = fileStat.st_mtime; + } + } } diff --git a/src/cg3protocol.h b/src/cg3protocol.h index 2192f08..d311f77 100644 --- a/src/cg3protocol.h +++ b/src/cg3protocol.h @@ -63,73 +63,73 @@ class CG3Protocol : public CProtocol { public: - // constructor - CG3Protocol() : m_GwAddress(0u), m_Modules("*"), m_LastModTime(0) {} + // constructor + CG3Protocol() : m_GwAddress(0u), m_Modules("*"), m_LastModTime(0) {} - // initialization - bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); + // initialization + bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); - // close - void Close(void); + // close + void Close(void); - // task - void Task(void); + // task + void Task(void); protected: - // threads - static void PresenceThread(CG3Protocol *); - static void ConfigThread(CG3Protocol *); - static void IcmpThread(CG3Protocol *); + // threads + static void PresenceThread(CG3Protocol *); + static void ConfigThread(CG3Protocol *); + static void IcmpThread(CG3Protocol *); - // helper tasks - void PresenceTask(void); - void ConfigTask(void); - void IcmpTask(void); + // helper tasks + void PresenceTask(void); + void ConfigTask(void); + void IcmpTask(void); - // config - void ReadOptions(void); + // config + void ReadOptions(void); - // helper - char *TrimWhiteSpaces(char *); - void NeedReload(void); + // helper + char *TrimWhiteSpaces(char *); + void NeedReload(void); - // queue helper - void HandleQueue(void); + // queue helper + void HandleQueue(void); - // keepalive helpers - void HandleKeepalives(void); + // keepalive helpers + void HandleKeepalives(void); - // stream helpers - bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); + // stream helpers + bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); - // packet decoding helpers - CDvHeaderPacket *IsValidDvHeaderPacket(const CBuffer &); - CDvFramePacket *IsValidDvFramePacket(const CBuffer &); - CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &); + // packet decoding helpers + CDvHeaderPacket *IsValidDvHeaderPacket(const CBuffer &); + CDvFramePacket *IsValidDvFramePacket(const CBuffer &); + CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &); - // packet encoding helpers - bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; - bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; - bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; + // packet encoding helpers + bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; + bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; + bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; protected: - std::thread *m_pPresenceThread; - std::thread *m_pConfigThread; - std::thread *m_pIcmpThread; - - // time - CTimePoint m_LastKeepaliveTime; - - // sockets - CUdpSocket m_DvOutSocket; - CUdpSocket m_PresenceSocket; - CUdpMsgSocket m_ConfigSocket; - CRawSocket m_IcmpRawSocket; - - // optional params - uint32 m_GwAddress; - std::string m_Modules; - time_t m_LastModTime; + std::thread *m_pPresenceThread; + std::thread *m_pConfigThread; + std::thread *m_pIcmpThread; + + // time + CTimePoint m_LastKeepaliveTime; + + // sockets + CUdpSocket m_DvOutSocket; + CUdpSocket m_PresenceSocket; + CUdpMsgSocket m_ConfigSocket; + CRawSocket m_IcmpRawSocket; + + // optional params + uint32 m_GwAddress; + std::string m_Modules; + time_t m_LastModTime; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cgatekeeper.cpp b/src/cgatekeeper.cpp index 056ba78..8fbc18b 100644 --- a/src/cgatekeeper.cpp +++ b/src/cgatekeeper.cpp @@ -36,8 +36,8 @@ CGateKeeper g_GateKeeper; CGateKeeper::CGateKeeper() { - keep_running = true; - m_pThread = nullptr; + keep_running = true; + m_pThread = nullptr; } //////////////////////////////////////////////////////////////////////////////////////// @@ -45,14 +45,14 @@ CGateKeeper::CGateKeeper() CGateKeeper::~CGateKeeper() { - // kill threads - keep_running = false; - if ( m_pThread != nullptr ) - { - m_pThread->join(); - delete m_pThread; + // kill threads + keep_running = false; + if ( m_pThread != nullptr ) + { + m_pThread->join(); + delete m_pThread; m_pThread = nullptr; - } + } } @@ -62,29 +62,29 @@ CGateKeeper::~CGateKeeper() bool CGateKeeper::Init(void) { - // load lists from files - m_NodeWhiteList.LoadFromFile(WHITELIST_PATH); - m_NodeBlackList.LoadFromFile(BLACKLIST_PATH); - m_PeerList.LoadFromFile(INTERLINKLIST_PATH); + // load lists from files + m_NodeWhiteList.LoadFromFile(WHITELIST_PATH); + m_NodeBlackList.LoadFromFile(BLACKLIST_PATH); + m_PeerList.LoadFromFile(INTERLINKLIST_PATH); - // reset run flag - keep_running = true; + // reset run flag + keep_running = true; - // start thread; - m_pThread = new std::thread(CGateKeeper::Thread, this); + // start thread; + m_pThread = new std::thread(CGateKeeper::Thread, this); - return true; + return true; } void CGateKeeper::Close(void) { - keep_running = false; - if ( m_pThread != nullptr ) - { - m_pThread->join(); - delete m_pThread; - m_pThread = nullptr; - } + keep_running = false; + if ( m_pThread != nullptr ) + { + m_pThread->join(); + delete m_pThread; + m_pThread = nullptr; + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -92,97 +92,97 @@ void CGateKeeper::Close(void) bool CGateKeeper::MayLink(const CCallsign &callsign, const CIp &ip, int protocol, char *modules) const { - bool ok = true; - - switch (protocol) - { - // repeaters - case PROTOCOL_DEXTRA: - case PROTOCOL_DPLUS: - case PROTOCOL_DCS: - #ifndef NO_XLX - case PROTOCOL_DMRPLUS: - case PROTOCOL_DMRMMDVM: - case PROTOCOL_YSF: - #endif - #ifndef NO_G3 - case PROTOCOL_G3: - #endif - // first check is IP & callsigned listed OK - ok &= IsNodeListedOk(callsign, ip); - // todo: then apply any protocol specific authorisation for the operation - break; + bool ok = true; + + switch (protocol) + { + // repeaters + case PROTOCOL_DEXTRA: + case PROTOCOL_DPLUS: + case PROTOCOL_DCS: +#ifndef NO_XLX + case PROTOCOL_DMRPLUS: + case PROTOCOL_DMRMMDVM: + case PROTOCOL_YSF: +#endif +#ifndef NO_G3 + case PROTOCOL_G3: +#endif + // first check is IP & callsigned listed OK + ok &= IsNodeListedOk(callsign, ip); + // todo: then apply any protocol specific authorisation for the operation + break; #ifndef NO_XLX - // XLX interlinks - case PROTOCOL_XLX: - ok &= IsPeerListedOk(callsign, ip, modules); - break; + // XLX interlinks + case PROTOCOL_XLX: + ok &= IsPeerListedOk(callsign, ip, modules); + break; #endif - // unsupported - case PROTOCOL_NONE: - default: - ok = false; - break; - } - - // report - if ( !ok ) - { - std::cout << "Gatekeeper blocking linking of " << callsign << " @ " << ip << " using protocol " << protocol << std::endl; - } - - // done - return ok; + // unsupported + case PROTOCOL_NONE: + default: + ok = false; + break; + } + + // report + if ( !ok ) + { + std::cout << "Gatekeeper blocking linking of " << callsign << " @ " << ip << " using protocol " << protocol << std::endl; + } + + // done + return ok; } bool CGateKeeper::MayTransmit(const CCallsign &callsign, const CIp &ip, int protocol, char module) const { - bool ok = true; - - switch (protocol) - { - // repeaters, protocol specific - case PROTOCOL_ANY: - case PROTOCOL_DEXTRA: - case PROTOCOL_DPLUS: - case PROTOCOL_DCS: + bool ok = true; + + switch (protocol) + { + // repeaters, protocol specific + case PROTOCOL_ANY: + case PROTOCOL_DEXTRA: + case PROTOCOL_DPLUS: + case PROTOCOL_DCS: #ifndef NO_XLX - case PROTOCOL_DMRPLUS: - case PROTOCOL_DMRMMDVM: - case PROTOCOL_YSF: + case PROTOCOL_DMRPLUS: + case PROTOCOL_DMRMMDVM: + case PROTOCOL_YSF: #endif #ifndef NO_G3 - case PROTOCOL_G3: + case PROTOCOL_G3: #endif - // first check is IP & callsigned listed OK - ok &= IsNodeListedOk(callsign, ip, module); - // todo: then apply any protocol specific authorisation for the operation - break; + // first check is IP & callsigned listed OK + ok &= IsNodeListedOk(callsign, ip, module); + // todo: then apply any protocol specific authorisation for the operation + break; #ifndef NO_XLX - // XLX interlinks - case PROTOCOL_XLX: - ok &= IsPeerListedOk(callsign, ip, module); - break; + // XLX interlinks + case PROTOCOL_XLX: + ok &= IsPeerListedOk(callsign, ip, module); + break; #endif - // unsupported - case PROTOCOL_NONE: - default: - ok = false; - break; - } - - // report - if ( !ok ) - { - std::cout << "Gatekeeper blocking transmitting of " << callsign << " @ " << ip << " using protocol " << protocol << std::endl; - } - - // done - return ok; + // unsupported + case PROTOCOL_NONE: + default: + ok = false; + break; + } + + // report + if ( !ok ) + { + std::cout << "Gatekeeper blocking transmitting of " << callsign << " @ " << ip << " using protocol " << protocol << std::endl; + } + + // done + return ok; } //////////////////////////////////////////////////////////////////////////////////////// @@ -190,26 +190,26 @@ bool CGateKeeper::MayTransmit(const CCallsign &callsign, const CIp &ip, int prot void CGateKeeper::Thread(CGateKeeper *This) { - while (This->keep_running) - { - // Wait 30 seconds + while (This->keep_running) + { + // Wait 30 seconds for (int i=0; i<15 && This->keep_running; i++) - CTimePoint::TaskSleepFor(2000); - - // have lists files changed ? - if ( This->m_NodeWhiteList.NeedReload() ) - { - This->m_NodeWhiteList.ReloadFromFile(); - } - if ( This->m_NodeBlackList.NeedReload() ) - { - This->m_NodeBlackList.ReloadFromFile(); - } - if ( This->m_PeerList.NeedReload() ) - { - This->m_PeerList.ReloadFromFile(); - } - } + CTimePoint::TaskSleepFor(2000); + + // have lists files changed ? + if ( This->m_NodeWhiteList.NeedReload() ) + { + This->m_NodeWhiteList.ReloadFromFile(); + } + if ( This->m_NodeBlackList.NeedReload() ) + { + This->m_NodeBlackList.ReloadFromFile(); + } + if ( This->m_PeerList.NeedReload() ) + { + This->m_PeerList.ReloadFromFile(); + } + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -217,73 +217,73 @@ void CGateKeeper::Thread(CGateKeeper *This) bool CGateKeeper::IsNodeListedOk(const CCallsign &callsign, const CIp &ip, char module) const { - bool ok = true; - - // first check IP - - // next, check callsign - if ( ok ) - { - // first check if callsign is in white list - // note if white list is empty, everybody is authorized - const_cast(m_NodeWhiteList).Lock(); - if ( !m_NodeWhiteList.empty() ) - { - ok = m_NodeWhiteList.IsCallsignListedWithWildcard(callsign, module); - } - const_cast(m_NodeWhiteList).Unlock(); - - // then check if not blacklisted - const_cast(m_NodeBlackList).Lock(); - ok &= !m_NodeBlackList.IsCallsignListedWithWildcard(callsign); - const_cast(m_NodeBlackList).Unlock(); - } - - // done - return ok; + bool ok = true; + + // first check IP + + // next, check callsign + if ( ok ) + { + // first check if callsign is in white list + // note if white list is empty, everybody is authorized + const_cast(m_NodeWhiteList).Lock(); + if ( !m_NodeWhiteList.empty() ) + { + ok = m_NodeWhiteList.IsCallsignListedWithWildcard(callsign, module); + } + const_cast(m_NodeWhiteList).Unlock(); + + // then check if not blacklisted + const_cast(m_NodeBlackList).Lock(); + ok &= !m_NodeBlackList.IsCallsignListedWithWildcard(callsign); + const_cast(m_NodeBlackList).Unlock(); + } + + // done + return ok; } bool CGateKeeper::IsPeerListedOk(const CCallsign &callsign, const CIp &ip, char module) const { - bool ok = true; - - // first check IP - - // next, check callsign - if ( ok ) - { - // look for an exact match in the list - const_cast(m_PeerList).Lock(); - if ( !m_PeerList.empty() ) - { - ok = m_PeerList.IsCallsignListed(callsign, module); - } - const_cast(m_PeerList).Unlock(); - } - - // done - return ok; + bool ok = true; + + // first check IP + + // next, check callsign + if ( ok ) + { + // look for an exact match in the list + const_cast(m_PeerList).Lock(); + if ( !m_PeerList.empty() ) + { + ok = m_PeerList.IsCallsignListed(callsign, module); + } + const_cast(m_PeerList).Unlock(); + } + + // done + return ok; } bool CGateKeeper::IsPeerListedOk(const CCallsign &callsign, const CIp &ip, char *modules) const { - bool ok = true; - - // first check IP - - // next, check callsign - if ( ok ) - { - // look for an exact match in the list - const_cast(m_PeerList).Lock(); - if ( !m_PeerList.empty() ) - { - ok = m_PeerList.IsCallsignListed(callsign, modules); - } - const_cast(m_PeerList).Unlock(); - } - - // done - return ok; + bool ok = true; + + // first check IP + + // next, check callsign + if ( ok ) + { + // look for an exact match in the list + const_cast(m_PeerList).Lock(); + if ( !m_PeerList.empty() ) + { + ok = m_PeerList.IsCallsignListed(callsign, modules); + } + const_cast(m_PeerList).Unlock(); + } + + // done + return ok; } diff --git a/src/cgatekeeper.h b/src/cgatekeeper.h index 10561ba..96236ff 100644 --- a/src/cgatekeeper.h +++ b/src/cgatekeeper.h @@ -37,42 +37,42 @@ class CGateKeeper { public: - // constructor - CGateKeeper(); + // constructor + CGateKeeper(); - // destructor - virtual ~CGateKeeper(); + // destructor + virtual ~CGateKeeper(); - // init & clode - bool Init(void); - void Close(void); + // init & clode + bool Init(void); + void Close(void); - // authorizations - bool MayLink(const CCallsign &, const CIp &, int, char * = nullptr) const; - bool MayTransmit(const CCallsign &, const CIp &, int = PROTOCOL_ANY, char = ' ') const; + // authorizations + bool MayLink(const CCallsign &, const CIp &, int, char * = nullptr) const; + bool MayTransmit(const CCallsign &, const CIp &, int = PROTOCOL_ANY, char = ' ') const; - // peer list handeling - CPeerCallsignList *GetPeerList(void) { m_PeerList.Lock(); return &m_PeerList; } - void ReleasePeerList(void) { m_PeerList.Unlock(); } + // peer list handeling + CPeerCallsignList *GetPeerList(void) { m_PeerList.Lock(); return &m_PeerList; } + void ReleasePeerList(void) { m_PeerList.Unlock(); } protected: - // thread - static void Thread(CGateKeeper *); + // thread + static void Thread(CGateKeeper *); - // operation helpers - bool IsNodeListedOk(const CCallsign &, const CIp &, char = ' ') const; - bool IsPeerListedOk(const CCallsign &, const CIp &, char) const; - bool IsPeerListedOk(const CCallsign &, const CIp &, char *) const; + // operation helpers + bool IsNodeListedOk(const CCallsign &, const CIp &, char = ' ') const; + bool IsPeerListedOk(const CCallsign &, const CIp &, char) const; + bool IsPeerListedOk(const CCallsign &, const CIp &, char *) const; protected: - // data - CCallsignList m_NodeWhiteList; - CCallsignList m_NodeBlackList; - CPeerCallsignList m_PeerList; + // data + CCallsignList m_NodeWhiteList; + CCallsignList m_NodeBlackList; + CPeerCallsignList m_PeerList; - // thread - std::atomic keep_running; - std::thread *m_pThread; + // thread + std::atomic keep_running; + std::thread *m_pThread; }; diff --git a/src/cgolay2087.cpp b/src/cgolay2087.cpp index 7bdebd3..95fb159 100644 --- a/src/cgolay2087.cpp +++ b/src/cgolay2087.cpp @@ -22,188 +22,192 @@ #include const unsigned int ENCODING_TABLE_2087[] = -{0x0000U, 0xB08EU, 0xE093U, 0x501DU, 0x70A9U, 0xC027U, 0x903AU, 0x20B4U, 0x60DCU, 0xD052U, 0x804FU, 0x30C1U, - 0x1075U, 0xA0FBU, 0xF0E6U, 0x4068U, 0x7036U, 0xC0B8U, 0x90A5U, 0x202BU, 0x009FU, 0xB011U, 0xE00CU, 0x5082U, - 0x10EAU, 0xA064U, 0xF079U, 0x40F7U, 0x6043U, 0xD0CDU, 0x80D0U, 0x305EU, 0xD06CU, 0x60E2U, 0x30FFU, 0x8071U, - 0xA0C5U, 0x104BU, 0x4056U, 0xF0D8U, 0xB0B0U, 0x003EU, 0x5023U, 0xE0ADU, 0xC019U, 0x7097U, 0x208AU, 0x9004U, - 0xA05AU, 0x10D4U, 0x40C9U, 0xF047U, 0xD0F3U, 0x607DU, 0x3060U, 0x80EEU, 0xC086U, 0x7008U, 0x2015U, 0x909BU, - 0xB02FU, 0x00A1U, 0x50BCU, 0xE032U, 0x90D9U, 0x2057U, 0x704AU, 0xC0C4U, 0xE070U, 0x50FEU, 0x00E3U, 0xB06DU, - 0xF005U, 0x408BU, 0x1096U, 0xA018U, 0x80ACU, 0x3022U, 0x603FU, 0xD0B1U, 0xE0EFU, 0x5061U, 0x007CU, 0xB0F2U, - 0x9046U, 0x20C8U, 0x70D5U, 0xC05BU, 0x8033U, 0x30BDU, 0x60A0U, 0xD02EU, 0xF09AU, 0x4014U, 0x1009U, 0xA087U, - 0x40B5U, 0xF03BU, 0xA026U, 0x10A8U, 0x301CU, 0x8092U, 0xD08FU, 0x6001U, 0x2069U, 0x90E7U, 0xC0FAU, 0x7074U, - 0x50C0U, 0xE04EU, 0xB053U, 0x00DDU, 0x3083U, 0x800DU, 0xD010U, 0x609EU, 0x402AU, 0xF0A4U, 0xA0B9U, 0x1037U, - 0x505FU, 0xE0D1U, 0xB0CCU, 0x0042U, 0x20F6U, 0x9078U, 0xC065U, 0x70EBU, 0xA03DU, 0x10B3U, 0x40AEU, 0xF020U, - 0xD094U, 0x601AU, 0x3007U, 0x8089U, 0xC0E1U, 0x706FU, 0x2072U, 0x90FCU, 0xB048U, 0x00C6U, 0x50DBU, 0xE055U, - 0xD00BU, 0x6085U, 0x3098U, 0x8016U, 0xA0A2U, 0x102CU, 0x4031U, 0xF0BFU, 0xB0D7U, 0x0059U, 0x5044U, 0xE0CAU, - 0xC07EU, 0x70F0U, 0x20EDU, 0x9063U, 0x7051U, 0xC0DFU, 0x90C2U, 0x204CU, 0x00F8U, 0xB076U, 0xE06BU, 0x50E5U, - 0x108DU, 0xA003U, 0xF01EU, 0x4090U, 0x6024U, 0xD0AAU, 0x80B7U, 0x3039U, 0x0067U, 0xB0E9U, 0xE0F4U, 0x507AU, - 0x70CEU, 0xC040U, 0x905DU, 0x20D3U, 0x60BBU, 0xD035U, 0x8028U, 0x30A6U, 0x1012U, 0xA09CU, 0xF081U, 0x400FU, - 0x30E4U, 0x806AU, 0xD077U, 0x60F9U, 0x404DU, 0xF0C3U, 0xA0DEU, 0x1050U, 0x5038U, 0xE0B6U, 0xB0ABU, 0x0025U, - 0x2091U, 0x901FU, 0xC002U, 0x708CU, 0x40D2U, 0xF05CU, 0xA041U, 0x10CFU, 0x307BU, 0x80F5U, 0xD0E8U, 0x6066U, - 0x200EU, 0x9080U, 0xC09DU, 0x7013U, 0x50A7U, 0xE029U, 0xB034U, 0x00BAU, 0xE088U, 0x5006U, 0x001BU, 0xB095U, - 0x9021U, 0x20AFU, 0x70B2U, 0xC03CU, 0x8054U, 0x30DAU, 0x60C7U, 0xD049U, 0xF0FDU, 0x4073U, 0x106EU, 0xA0E0U, - 0x90BEU, 0x2030U, 0x702DU, 0xC0A3U, 0xE017U, 0x5099U, 0x0084U, 0xB00AU, 0xF062U, 0x40ECU, 0x10F1U, 0xA07FU, - 0x80CBU, 0x3045U, 0x6058U, 0xD0D6U}; +{ + 0x0000U, 0xB08EU, 0xE093U, 0x501DU, 0x70A9U, 0xC027U, 0x903AU, 0x20B4U, 0x60DCU, 0xD052U, 0x804FU, 0x30C1U, + 0x1075U, 0xA0FBU, 0xF0E6U, 0x4068U, 0x7036U, 0xC0B8U, 0x90A5U, 0x202BU, 0x009FU, 0xB011U, 0xE00CU, 0x5082U, + 0x10EAU, 0xA064U, 0xF079U, 0x40F7U, 0x6043U, 0xD0CDU, 0x80D0U, 0x305EU, 0xD06CU, 0x60E2U, 0x30FFU, 0x8071U, + 0xA0C5U, 0x104BU, 0x4056U, 0xF0D8U, 0xB0B0U, 0x003EU, 0x5023U, 0xE0ADU, 0xC019U, 0x7097U, 0x208AU, 0x9004U, + 0xA05AU, 0x10D4U, 0x40C9U, 0xF047U, 0xD0F3U, 0x607DU, 0x3060U, 0x80EEU, 0xC086U, 0x7008U, 0x2015U, 0x909BU, + 0xB02FU, 0x00A1U, 0x50BCU, 0xE032U, 0x90D9U, 0x2057U, 0x704AU, 0xC0C4U, 0xE070U, 0x50FEU, 0x00E3U, 0xB06DU, + 0xF005U, 0x408BU, 0x1096U, 0xA018U, 0x80ACU, 0x3022U, 0x603FU, 0xD0B1U, 0xE0EFU, 0x5061U, 0x007CU, 0xB0F2U, + 0x9046U, 0x20C8U, 0x70D5U, 0xC05BU, 0x8033U, 0x30BDU, 0x60A0U, 0xD02EU, 0xF09AU, 0x4014U, 0x1009U, 0xA087U, + 0x40B5U, 0xF03BU, 0xA026U, 0x10A8U, 0x301CU, 0x8092U, 0xD08FU, 0x6001U, 0x2069U, 0x90E7U, 0xC0FAU, 0x7074U, + 0x50C0U, 0xE04EU, 0xB053U, 0x00DDU, 0x3083U, 0x800DU, 0xD010U, 0x609EU, 0x402AU, 0xF0A4U, 0xA0B9U, 0x1037U, + 0x505FU, 0xE0D1U, 0xB0CCU, 0x0042U, 0x20F6U, 0x9078U, 0xC065U, 0x70EBU, 0xA03DU, 0x10B3U, 0x40AEU, 0xF020U, + 0xD094U, 0x601AU, 0x3007U, 0x8089U, 0xC0E1U, 0x706FU, 0x2072U, 0x90FCU, 0xB048U, 0x00C6U, 0x50DBU, 0xE055U, + 0xD00BU, 0x6085U, 0x3098U, 0x8016U, 0xA0A2U, 0x102CU, 0x4031U, 0xF0BFU, 0xB0D7U, 0x0059U, 0x5044U, 0xE0CAU, + 0xC07EU, 0x70F0U, 0x20EDU, 0x9063U, 0x7051U, 0xC0DFU, 0x90C2U, 0x204CU, 0x00F8U, 0xB076U, 0xE06BU, 0x50E5U, + 0x108DU, 0xA003U, 0xF01EU, 0x4090U, 0x6024U, 0xD0AAU, 0x80B7U, 0x3039U, 0x0067U, 0xB0E9U, 0xE0F4U, 0x507AU, + 0x70CEU, 0xC040U, 0x905DU, 0x20D3U, 0x60BBU, 0xD035U, 0x8028U, 0x30A6U, 0x1012U, 0xA09CU, 0xF081U, 0x400FU, + 0x30E4U, 0x806AU, 0xD077U, 0x60F9U, 0x404DU, 0xF0C3U, 0xA0DEU, 0x1050U, 0x5038U, 0xE0B6U, 0xB0ABU, 0x0025U, + 0x2091U, 0x901FU, 0xC002U, 0x708CU, 0x40D2U, 0xF05CU, 0xA041U, 0x10CFU, 0x307BU, 0x80F5U, 0xD0E8U, 0x6066U, + 0x200EU, 0x9080U, 0xC09DU, 0x7013U, 0x50A7U, 0xE029U, 0xB034U, 0x00BAU, 0xE088U, 0x5006U, 0x001BU, 0xB095U, + 0x9021U, 0x20AFU, 0x70B2U, 0xC03CU, 0x8054U, 0x30DAU, 0x60C7U, 0xD049U, 0xF0FDU, 0x4073U, 0x106EU, 0xA0E0U, + 0x90BEU, 0x2030U, 0x702DU, 0xC0A3U, 0xE017U, 0x5099U, 0x0084U, 0xB00AU, 0xF062U, 0x40ECU, 0x10F1U, 0xA07FU, + 0x80CBU, 0x3045U, 0x6058U, 0xD0D6U +}; const unsigned int DECODING_TABLE_1987[] = -{0x00000U, 0x00001U, 0x00002U, 0x00003U, 0x00004U, 0x00005U, 0x00006U, 0x00007U, 0x00008U, 0x00009U, 0x0000AU, 0x0000BU, 0x0000CU, - 0x0000DU, 0x0000EU, 0x24020U, 0x00010U, 0x00011U, 0x00012U, 0x00013U, 0x00014U, 0x00015U, 0x00016U, 0x00017U, 0x00018U, 0x00019U, - 0x0001AU, 0x0001BU, 0x0001CU, 0x0001DU, 0x48040U, 0x01480U, 0x00020U, 0x00021U, 0x00022U, 0x00023U, 0x00024U, 0x00025U, 0x00026U, - 0x24008U, 0x00028U, 0x00029U, 0x0002AU, 0x24004U, 0x0002CU, 0x24002U, 0x24001U, 0x24000U, 0x00030U, 0x00031U, 0x00032U, 0x08180U, - 0x00034U, 0x00C40U, 0x00036U, 0x00C42U, 0x00038U, 0x43000U, 0x0003AU, 0x43002U, 0x02902U, 0x24012U, 0x02900U, 0x24010U, 0x00040U, - 0x00041U, 0x00042U, 0x00043U, 0x00044U, 0x00045U, 0x00046U, 0x00047U, 0x00048U, 0x00049U, 0x0004AU, 0x02500U, 0x0004CU, 0x0004DU, - 0x48010U, 0x48011U, 0x00050U, 0x00051U, 0x00052U, 0x21200U, 0x00054U, 0x00C20U, 0x48008U, 0x48009U, 0x00058U, 0x00059U, 0x48004U, - 0x48005U, 0x48002U, 0x48003U, 0x48000U, 0x48001U, 0x00060U, 0x00061U, 0x00062U, 0x00063U, 0x00064U, 0x00C10U, 0x10300U, 0x0B000U, - 0x00068U, 0x00069U, 0x01880U, 0x01881U, 0x40181U, 0x40180U, 0x24041U, 0x24040U, 0x00070U, 0x00C04U, 0x00072U, 0x00C06U, 0x00C01U, - 0x00C00U, 0x00C03U, 0x00C02U, 0x05204U, 0x00C0CU, 0x48024U, 0x48025U, 0x05200U, 0x00C08U, 0x48020U, 0x48021U, 0x00080U, 0x00081U, - 0x00082U, 0x00083U, 0x00084U, 0x00085U, 0x00086U, 0x00087U, 0x00088U, 0x00089U, 0x0008AU, 0x50200U, 0x0008CU, 0x0A800U, 0x01411U, - 0x01410U, 0x00090U, 0x00091U, 0x00092U, 0x08120U, 0x00094U, 0x00095U, 0x04A00U, 0x01408U, 0x00098U, 0x00099U, 0x01405U, 0x01404U, - 0x01403U, 0x01402U, 0x01401U, 0x01400U, 0x000A0U, 0x000A1U, 0x000A2U, 0x08110U, 0x000A4U, 0x000A5U, 0x42400U, 0x42401U, 0x000A8U, - 0x000A9U, 0x01840U, 0x01841U, 0x40141U, 0x40140U, 0x24081U, 0x24080U, 0x000B0U, 0x08102U, 0x08101U, 0x08100U, 0x000B4U, 0x08106U, - 0x08105U, 0x08104U, 0x20A01U, 0x20A00U, 0x08109U, 0x08108U, 0x01423U, 0x01422U, 0x01421U, 0x01420U, 0x000C0U, 0x000C1U, 0x000C2U, - 0x000C3U, 0x000C4U, 0x000C5U, 0x000C6U, 0x000C7U, 0x000C8U, 0x000C9U, 0x01820U, 0x01821U, 0x20600U, 0x40120U, 0x16000U, 0x16001U, - 0x000D0U, 0x000D1U, 0x42801U, 0x42800U, 0x03100U, 0x18200U, 0x03102U, 0x18202U, 0x000D8U, 0x000D9U, 0x48084U, 0x01444U, 0x48082U, - 0x01442U, 0x48080U, 0x01440U, 0x000E0U, 0x32000U, 0x01808U, 0x04600U, 0x40109U, 0x40108U, 0x0180CU, 0x4010AU, 0x01802U, 0x40104U, - 0x01800U, 0x01801U, 0x40101U, 0x40100U, 0x01804U, 0x40102U, 0x0A408U, 0x08142U, 0x08141U, 0x08140U, 0x00C81U, 0x00C80U, 0x00C83U, - 0x00C82U, 0x0A400U, 0x0A401U, 0x01810U, 0x01811U, 0x40111U, 0x40110U, 0x01814U, 0x40112U, 0x00100U, 0x00101U, 0x00102U, 0x00103U, - 0x00104U, 0x00105U, 0x00106U, 0x41800U, 0x00108U, 0x00109U, 0x0010AU, 0x02440U, 0x0010CU, 0x0010DU, 0x0010EU, 0x02444U, 0x00110U, - 0x00111U, 0x00112U, 0x080A0U, 0x00114U, 0x00115U, 0x00116U, 0x080A4U, 0x00118U, 0x00119U, 0x15000U, 0x15001U, 0x02822U, 0x02823U, - 0x02820U, 0x02821U, 0x00120U, 0x00121U, 0x00122U, 0x08090U, 0x00124U, 0x00125U, 0x10240U, 0x10241U, 0x00128U, 0x00129U, 0x0012AU, - 0x24104U, 0x09400U, 0x400C0U, 0x02810U, 0x24100U, 0x00130U, 0x08082U, 0x08081U, 0x08080U, 0x31001U, 0x31000U, 0x02808U, 0x08084U, - 0x02806U, 0x0808AU, 0x02804U, 0x08088U, 0x02802U, 0x02803U, 0x02800U, 0x02801U, 0x00140U, 0x00141U, 0x00142U, 0x02408U, 0x00144U, - 0x00145U, 0x10220U, 0x10221U, 0x00148U, 0x02402U, 0x02401U, 0x02400U, 0x400A1U, 0x400A0U, 0x02405U, 0x02404U, 0x00150U, 0x00151U, - 0x00152U, 0x02418U, 0x03080U, 0x03081U, 0x03082U, 0x03083U, 0x09801U, 0x09800U, 0x02411U, 0x02410U, 0x48102U, 0x09804U, 0x48100U, - 0x48101U, 0x00160U, 0x00161U, 0x10204U, 0x10205U, 0x10202U, 0x40088U, 0x10200U, 0x10201U, 0x40085U, 0x40084U, 0x02421U, 0x02420U, - 0x40081U, 0x40080U, 0x10208U, 0x40082U, 0x41402U, 0x080C2U, 0x41400U, 0x080C0U, 0x00D01U, 0x00D00U, 0x10210U, 0x10211U, 0x40095U, - 0x40094U, 0x02844U, 0x080C8U, 0x40091U, 0x40090U, 0x02840U, 0x02841U, 0x00180U, 0x00181U, 0x00182U, 0x08030U, 0x00184U, 0x14400U, - 0x22201U, 0x22200U, 0x00188U, 0x00189U, 0x0018AU, 0x08038U, 0x40061U, 0x40060U, 0x40063U, 0x40062U, 0x00190U, 0x08022U, 0x08021U, - 0x08020U, 0x03040U, 0x03041U, 0x08025U, 0x08024U, 0x40C00U, 0x40C01U, 0x08029U, 0x08028U, 0x2C000U, 0x2C001U, 0x01501U, 0x01500U, - 0x001A0U, 0x08012U, 0x08011U, 0x08010U, 0x40049U, 0x40048U, 0x08015U, 0x08014U, 0x06200U, 0x40044U, 0x30400U, 0x08018U, 0x40041U, - 0x40040U, 0x40043U, 0x40042U, 0x08003U, 0x08002U, 0x08001U, 0x08000U, 0x08007U, 0x08006U, 0x08005U, 0x08004U, 0x0800BU, 0x0800AU, - 0x08009U, 0x08008U, 0x40051U, 0x40050U, 0x02880U, 0x0800CU, 0x001C0U, 0x001C1U, 0x64000U, 0x64001U, 0x03010U, 0x40028U, 0x08C00U, - 0x08C01U, 0x40025U, 0x40024U, 0x02481U, 0x02480U, 0x40021U, 0x40020U, 0x40023U, 0x40022U, 0x03004U, 0x03005U, 0x08061U, 0x08060U, - 0x03000U, 0x03001U, 0x03002U, 0x03003U, 0x0300CU, 0x40034U, 0x30805U, 0x30804U, 0x03008U, 0x40030U, 0x30801U, 0x30800U, 0x4000DU, - 0x4000CU, 0x08051U, 0x08050U, 0x40009U, 0x40008U, 0x10280U, 0x4000AU, 0x40005U, 0x40004U, 0x01900U, 0x40006U, 0x40001U, 0x40000U, - 0x40003U, 0x40002U, 0x14800U, 0x08042U, 0x08041U, 0x08040U, 0x03020U, 0x40018U, 0x08045U, 0x08044U, 0x40015U, 0x40014U, 0x08049U, - 0x08048U, 0x40011U, 0x40010U, 0x40013U, 0x40012U, 0x00200U, 0x00201U, 0x00202U, 0x00203U, 0x00204U, 0x00205U, 0x00206U, 0x00207U, - 0x00208U, 0x00209U, 0x0020AU, 0x50080U, 0x0020CU, 0x0020DU, 0x0020EU, 0x50084U, 0x00210U, 0x00211U, 0x00212U, 0x21040U, 0x00214U, - 0x00215U, 0x04880U, 0x04881U, 0x00218U, 0x00219U, 0x0E001U, 0x0E000U, 0x0021CU, 0x0021DU, 0x04888U, 0x0E004U, 0x00220U, 0x00221U, - 0x00222U, 0x00223U, 0x00224U, 0x00225U, 0x10140U, 0x10141U, 0x00228U, 0x00229U, 0x0022AU, 0x24204U, 0x12401U, 0x12400U, 0x24201U, - 0x24200U, 0x00230U, 0x00231U, 0x00232U, 0x21060U, 0x2A000U, 0x2A001U, 0x2A002U, 0x2A003U, 0x20881U, 0x20880U, 0x20883U, 0x20882U, - 0x05040U, 0x05041U, 0x05042U, 0x24210U, 0x00240U, 0x00241U, 0x00242U, 0x21010U, 0x00244U, 0x46000U, 0x10120U, 0x10121U, 0x00248U, - 0x00249U, 0x0024AU, 0x21018U, 0x20480U, 0x20481U, 0x20482U, 0x20483U, 0x00250U, 0x21002U, 0x21001U, 0x21000U, 0x18081U, 0x18080U, - 0x21005U, 0x21004U, 0x12800U, 0x12801U, 0x21009U, 0x21008U, 0x05020U, 0x05021U, 0x48200U, 0x48201U, 0x00260U, 0x00261U, 0x10104U, - 0x04480U, 0x10102U, 0x10103U, 0x10100U, 0x10101U, 0x62002U, 0x62003U, 0x62000U, 0x62001U, 0x05010U, 0x05011U, 0x10108U, 0x10109U, - 0x0500CU, 0x21022U, 0x21021U, 0x21020U, 0x05008U, 0x00E00U, 0x10110U, 0x10111U, 0x05004U, 0x05005U, 0x05006U, 0x21028U, 0x05000U, - 0x05001U, 0x05002U, 0x05003U, 0x00280U, 0x00281U, 0x00282U, 0x50008U, 0x00284U, 0x00285U, 0x04810U, 0x22100U, 0x00288U, 0x50002U, - 0x50001U, 0x50000U, 0x20440U, 0x20441U, 0x50005U, 0x50004U, 0x00290U, 0x00291U, 0x04804U, 0x04805U, 0x04802U, 0x18040U, 0x04800U, - 0x04801U, 0x20821U, 0x20820U, 0x50011U, 0x50010U, 0x0480AU, 0x01602U, 0x04808U, 0x01600U, 0x002A0U, 0x002A1U, 0x04441U, 0x04440U, - 0x002A4U, 0x002A5U, 0x04830U, 0x04444U, 0x06100U, 0x20810U, 0x50021U, 0x50020U, 0x06104U, 0x20814U, 0x50025U, 0x50024U, 0x20809U, - 0x20808U, 0x13000U, 0x08300U, 0x04822U, 0x2080CU, 0x04820U, 0x04821U, 0x20801U, 0x20800U, 0x20803U, 0x20802U, 0x20805U, 0x20804U, - 0x04828U, 0x20806U, 0x002C0U, 0x002C1U, 0x04421U, 0x04420U, 0x20408U, 0x18010U, 0x2040AU, 0x18012U, 0x20404U, 0x20405U, 0x50041U, - 0x50040U, 0x20400U, 0x20401U, 0x20402U, 0x20403U, 0x18005U, 0x18004U, 0x21081U, 0x21080U, 0x18001U, 0x18000U, 0x04840U, 0x18002U, - 0x20414U, 0x1800CU, 0x21089U, 0x21088U, 0x20410U, 0x18008U, 0x20412U, 0x1800AU, 0x04403U, 0x04402U, 0x04401U, 0x04400U, 0x10182U, - 0x04406U, 0x10180U, 0x04404U, 0x01A02U, 0x0440AU, 0x01A00U, 0x04408U, 0x20420U, 0x40300U, 0x20422U, 0x40302U, 0x04413U, 0x04412U, - 0x04411U, 0x04410U, 0x18021U, 0x18020U, 0x10190U, 0x18022U, 0x20841U, 0x20840U, 0x01A10U, 0x20842U, 0x05080U, 0x05081U, 0x05082U, - 0x05083U, 0x00300U, 0x00301U, 0x00302U, 0x00303U, 0x00304U, 0x00305U, 0x10060U, 0x22080U, 0x00308U, 0x00309U, 0x28800U, 0x28801U, - 0x44402U, 0x44403U, 0x44400U, 0x44401U, 0x00310U, 0x00311U, 0x10C01U, 0x10C00U, 0x00314U, 0x00315U, 0x10070U, 0x10C04U, 0x00318U, - 0x00319U, 0x28810U, 0x10C08U, 0x44412U, 0x00000U, 0x44410U, 0x44411U, 0x00320U, 0x60400U, 0x10044U, 0x10045U, 0x10042U, 0x0C800U, - 0x10040U, 0x10041U, 0x06080U, 0x06081U, 0x06082U, 0x06083U, 0x1004AU, 0x0C808U, 0x10048U, 0x10049U, 0x58008U, 0x08282U, 0x08281U, - 0x08280U, 0x10052U, 0x0C810U, 0x10050U, 0x10051U, 0x58000U, 0x58001U, 0x58002U, 0x08288U, 0x02A02U, 0x02A03U, 0x02A00U, 0x02A01U, - 0x00340U, 0x00341U, 0x10024U, 0x10025U, 0x10022U, 0x10023U, 0x10020U, 0x10021U, 0x34001U, 0x34000U, 0x02601U, 0x02600U, 0x1002AU, - 0x34004U, 0x10028U, 0x10029U, 0x0C400U, 0x0C401U, 0x21101U, 0x21100U, 0x60800U, 0x60801U, 0x10030U, 0x10031U, 0x0C408U, 0x34010U, - 0x21109U, 0x21108U, 0x60808U, 0x60809U, 0x10038U, 0x28420U, 0x10006U, 0x10007U, 0x10004U, 0x10005U, 0x10002U, 0x10003U, 0x10000U, - 0x10001U, 0x1000EU, 0x40284U, 0x1000CU, 0x1000DU, 0x1000AU, 0x40280U, 0x10008U, 0x10009U, 0x10016U, 0x10017U, 0x10014U, 0x10015U, - 0x10012U, 0x10013U, 0x10010U, 0x10011U, 0x05104U, 0x44802U, 0x44801U, 0x44800U, 0x05100U, 0x05101U, 0x10018U, 0x28400U, 0x00380U, - 0x00381U, 0x22005U, 0x22004U, 0x22003U, 0x22002U, 0x22001U, 0x22000U, 0x06020U, 0x06021U, 0x50101U, 0x50100U, 0x11800U, 0x11801U, - 0x22009U, 0x22008U, 0x45001U, 0x45000U, 0x08221U, 0x08220U, 0x04902U, 0x22012U, 0x04900U, 0x22010U, 0x06030U, 0x45008U, 0x08229U, - 0x08228U, 0x11810U, 0x11811U, 0x04908U, 0x22018U, 0x06008U, 0x06009U, 0x08211U, 0x08210U, 0x100C2U, 0x22022U, 0x100C0U, 0x22020U, - 0x06000U, 0x06001U, 0x06002U, 0x06003U, 0x06004U, 0x40240U, 0x06006U, 0x40242U, 0x08203U, 0x08202U, 0x08201U, 0x08200U, 0x08207U, - 0x08206U, 0x08205U, 0x08204U, 0x06010U, 0x20900U, 0x08209U, 0x08208U, 0x61002U, 0x20904U, 0x61000U, 0x61001U, 0x29020U, 0x29021U, - 0x100A4U, 0x22044U, 0x100A2U, 0x22042U, 0x100A0U, 0x22040U, 0x20504U, 0x40224U, 0x0D005U, 0x0D004U, 0x20500U, 0x40220U, 0x0D001U, - 0x0D000U, 0x03204U, 0x18104U, 0x08261U, 0x08260U, 0x03200U, 0x18100U, 0x03202U, 0x18102U, 0x11421U, 0x11420U, 0x00000U, 0x11422U, - 0x03208U, 0x18108U, 0x0D011U, 0x0D010U, 0x29000U, 0x29001U, 0x10084U, 0x04500U, 0x10082U, 0x40208U, 0x10080U, 0x10081U, 0x06040U, - 0x40204U, 0x06042U, 0x40206U, 0x40201U, 0x40200U, 0x10088U, 0x40202U, 0x29010U, 0x08242U, 0x08241U, 0x08240U, 0x10092U, 0x40218U, - 0x10090U, 0x10091U, 0x11401U, 0x11400U, 0x11403U, 0x11402U, 0x40211U, 0x40210U, 0x10098U, 0x40212U, 0x00400U, 0x00401U, 0x00402U, - 0x00403U, 0x00404U, 0x00405U, 0x00406U, 0x00407U, 0x00408U, 0x00409U, 0x0040AU, 0x02140U, 0x0040CU, 0x0040DU, 0x01091U, 0x01090U, - 0x00410U, 0x00411U, 0x00412U, 0x00413U, 0x00414U, 0x00860U, 0x01089U, 0x01088U, 0x00418U, 0x38000U, 0x01085U, 0x01084U, 0x01083U, - 0x01082U, 0x01081U, 0x01080U, 0x00420U, 0x00421U, 0x00422U, 0x00423U, 0x00424U, 0x00850U, 0x42080U, 0x42081U, 0x00428U, 0x00429U, - 0x48801U, 0x48800U, 0x09100U, 0x12200U, 0x24401U, 0x24400U, 0x00430U, 0x00844U, 0x00432U, 0x00846U, 0x00841U, 0x00840U, 0x1C000U, - 0x00842U, 0x00438U, 0x0084CU, 0x010A5U, 0x010A4U, 0x00849U, 0x00848U, 0x010A1U, 0x010A0U, 0x00440U, 0x00441U, 0x00442U, 0x02108U, - 0x00444U, 0x00830U, 0x70001U, 0x70000U, 0x00448U, 0x02102U, 0x02101U, 0x02100U, 0x20280U, 0x20281U, 0x02105U, 0x02104U, 0x00450U, - 0x00824U, 0x00452U, 0x00826U, 0x00821U, 0x00820U, 0x00823U, 0x00822U, 0x24802U, 0x02112U, 0x24800U, 0x02110U, 0x00829U, 0x00828U, - 0x48400U, 0x010C0U, 0x00460U, 0x00814U, 0x04281U, 0x04280U, 0x00811U, 0x00810U, 0x00813U, 0x00812U, 0x54000U, 0x54001U, 0x02121U, - 0x02120U, 0x00819U, 0x00818U, 0x0081BU, 0x0081AU, 0x00805U, 0x00804U, 0x41100U, 0x00806U, 0x00801U, 0x00800U, 0x00803U, 0x00802U, - 0x0A080U, 0x0080CU, 0x0A082U, 0x0080EU, 0x00809U, 0x00808U, 0x0080BU, 0x0080AU, 0x00480U, 0x00481U, 0x00482U, 0x00483U, 0x00484U, - 0x14100U, 0x42020U, 0x01018U, 0x00488U, 0x00489U, 0x01015U, 0x01014U, 0x20240U, 0x01012U, 0x01011U, 0x01010U, 0x00490U, 0x00491U, - 0x0100DU, 0x0100CU, 0x0100BU, 0x0100AU, 0x01009U, 0x01008U, 0x40900U, 0x01006U, 0x01005U, 0x01004U, 0x01003U, 0x01002U, 0x01001U, - 0x01000U, 0x004A0U, 0x004A1U, 0x42004U, 0x04240U, 0x42002U, 0x42003U, 0x42000U, 0x42001U, 0x30102U, 0x30103U, 0x30100U, 0x30101U, - 0x4200AU, 0x01032U, 0x42008U, 0x01030U, 0x25000U, 0x25001U, 0x08501U, 0x08500U, 0x008C1U, 0x008C0U, 0x42010U, 0x01028U, 0x0A040U, - 0x0A041U, 0x01025U, 0x01024U, 0x01023U, 0x01022U, 0x01021U, 0x01020U, 0x004C0U, 0x49000U, 0x04221U, 0x04220U, 0x20208U, 0x20209U, - 0x08900U, 0x08901U, 0x20204U, 0x20205U, 0x02181U, 0x02180U, 0x20200U, 0x20201U, 0x20202U, 0x01050U, 0x0A028U, 0x008A4U, 0x0104DU, - 0x0104CU, 0x008A1U, 0x008A0U, 0x01049U, 0x01048U, 0x0A020U, 0x0A021U, 0x01045U, 0x01044U, 0x20210U, 0x01042U, 0x01041U, 0x01040U, - 0x04203U, 0x04202U, 0x04201U, 0x04200U, 0x00891U, 0x00890U, 0x42040U, 0x04204U, 0x0A010U, 0x0A011U, 0x01C00U, 0x04208U, 0x20220U, - 0x40500U, 0x20222U, 0x40502U, 0x0A008U, 0x00884U, 0x04211U, 0x04210U, 0x00881U, 0x00880U, 0x00883U, 0x00882U, 0x0A000U, 0x0A001U, - 0x0A002U, 0x0A003U, 0x0A004U, 0x00888U, 0x01061U, 0x01060U, 0x00500U, 0x00501U, 0x00502U, 0x02048U, 0x00504U, 0x14080U, 0x00506U, - 0x14082U, 0x00508U, 0x02042U, 0x02041U, 0x02040U, 0x09020U, 0x09021U, 0x44200U, 0x02044U, 0x00510U, 0x00511U, 0x10A01U, 0x10A00U, - 0x4A001U, 0x4A000U, 0x4A003U, 0x4A002U, 0x40880U, 0x40881U, 0x02051U, 0x02050U, 0x40884U, 0x01182U, 0x01181U, 0x01180U, 0x00520U, - 0x60200U, 0x00522U, 0x60202U, 0x09008U, 0x09009U, 0x0900AU, 0x0900BU, 0x09004U, 0x09005U, 0x30080U, 0x02060U, 0x09000U, 0x09001U, - 0x09002U, 0x09003U, 0x41042U, 0x08482U, 0x41040U, 0x08480U, 0x00941U, 0x00940U, 0x41044U, 0x00942U, 0x09014U, 0x09015U, 0x02C04U, - 0x08488U, 0x09010U, 0x09011U, 0x02C00U, 0x02C01U, 0x00540U, 0x0200AU, 0x02009U, 0x02008U, 0x08882U, 0x0200EU, 0x08880U, 0x0200CU, - 0x02003U, 0x02002U, 0x02001U, 0x02000U, 0x02007U, 0x02006U, 0x02005U, 0x02004U, 0x0C200U, 0x0C201U, 0x41020U, 0x02018U, 0x00921U, - 0x00920U, 0x41024U, 0x00922U, 0x02013U, 0x02012U, 0x02011U, 0x02010U, 0x02017U, 0x02016U, 0x02015U, 0x02014U, 0x41012U, 0x0202AU, - 0x41010U, 0x02028U, 0x26000U, 0x00910U, 0x10600U, 0x10601U, 0x02023U, 0x02022U, 0x02021U, 0x02020U, 0x09040U, 0x40480U, 0x02025U, - 0x02024U, 0x41002U, 0x00904U, 0x41000U, 0x41001U, 0x00901U, 0x00900U, 0x41004U, 0x00902U, 0x4100AU, 0x02032U, 0x41008U, 0x02030U, - 0x00909U, 0x00908U, 0x28201U, 0x28200U, 0x00580U, 0x14004U, 0x00582U, 0x14006U, 0x14001U, 0x14000U, 0x08840U, 0x14002U, 0x40810U, - 0x40811U, 0x30020U, 0x020C0U, 0x14009U, 0x14008U, 0x01111U, 0x01110U, 0x40808U, 0x40809U, 0x08421U, 0x08420U, 0x14011U, 0x14010U, - 0x01109U, 0x01108U, 0x40800U, 0x40801U, 0x40802U, 0x01104U, 0x40804U, 0x01102U, 0x01101U, 0x01100U, 0x03801U, 0x03800U, 0x30008U, - 0x08410U, 0x14021U, 0x14020U, 0x42100U, 0x42101U, 0x30002U, 0x30003U, 0x30000U, 0x30001U, 0x09080U, 0x40440U, 0x30004U, 0x30005U, - 0x08403U, 0x08402U, 0x08401U, 0x08400U, 0x08407U, 0x08406U, 0x08405U, 0x08404U, 0x40820U, 0x40821U, 0x30010U, 0x08408U, 0x40824U, - 0x01122U, 0x01121U, 0x01120U, 0x08806U, 0x0208AU, 0x08804U, 0x02088U, 0x08802U, 0x14040U, 0x08800U, 0x08801U, 0x02083U, 0x02082U, - 0x02081U, 0x02080U, 0x20300U, 0x40420U, 0x08808U, 0x02084U, 0x03404U, 0x03405U, 0x08814U, 0x02098U, 0x03400U, 0x03401U, 0x08810U, - 0x08811U, 0x40840U, 0x40841U, 0x02091U, 0x02090U, 0x40844U, 0x01142U, 0x01141U, 0x01140U, 0x04303U, 0x04302U, 0x04301U, 0x04300U, - 0x40409U, 0x40408U, 0x08820U, 0x08821U, 0x40405U, 0x40404U, 0x30040U, 0x020A0U, 0x40401U, 0x40400U, 0x40403U, 0x40402U, 0x41082U, - 0x08442U, 0x41080U, 0x08440U, 0x00981U, 0x00980U, 0x41084U, 0x00982U, 0x0A100U, 0x11200U, 0x0A102U, 0x11202U, 0x40411U, 0x40410U, - 0x40413U, 0x40412U, 0x00600U, 0x00601U, 0x00602U, 0x00603U, 0x00604U, 0x00605U, 0x00606U, 0x00607U, 0x00608U, 0x05800U, 0x0060AU, - 0x05802U, 0x200C0U, 0x12020U, 0x44100U, 0x44101U, 0x00610U, 0x00611U, 0x10901U, 0x10900U, 0x51000U, 0x51001U, 0x51002U, 0x10904U, - 0x00618U, 0x05810U, 0x01285U, 0x01284U, 0x51008U, 0x01282U, 0x01281U, 0x01280U, 0x00620U, 0x60100U, 0x040C1U, 0x040C0U, 0x12009U, - 0x12008U, 0x21800U, 0x21801U, 0x12005U, 0x12004U, 0x12007U, 0x12006U, 0x12001U, 0x12000U, 0x12003U, 0x12002U, 0x00630U, 0x00A44U, - 0x040D1U, 0x040D0U, 0x00A41U, 0x00A40U, 0x21810U, 0x00A42U, 0x12015U, 0x12014U, 0x00000U, 0x12016U, 0x12011U, 0x12010U, 0x12013U, - 0x12012U, 0x00640U, 0x00641U, 0x040A1U, 0x040A0U, 0x20088U, 0x20089U, 0x2008AU, 0x040A4U, 0x20084U, 0x20085U, 0x19000U, 0x02300U, - 0x20080U, 0x20081U, 0x20082U, 0x20083U, 0x0C100U, 0x0C101U, 0x21401U, 0x21400U, 0x00A21U, 0x00A20U, 0x00A23U, 0x00A22U, 0x20094U, - 0x20095U, 0x19010U, 0x21408U, 0x20090U, 0x20091U, 0x20092U, 0x28120U, 0x04083U, 0x04082U, 0x04081U, 0x04080U, 0x00A11U, 0x00A10U, - 0x10500U, 0x04084U, 0x200A4U, 0x0408AU, 0x04089U, 0x04088U, 0x200A0U, 0x12040U, 0x200A2U, 0x12042U, 0x00A05U, 0x00A04U, 0x04091U, - 0x04090U, 0x00A01U, 0x00A00U, 0x00A03U, 0x00A02U, 0x05404U, 0x00A0CU, 0x28105U, 0x28104U, 0x05400U, 0x00A08U, 0x28101U, 0x28100U, - 0x00680U, 0x00681U, 0x04061U, 0x04060U, 0x20048U, 0x20049U, 0x2004AU, 0x04064U, 0x20044U, 0x20045U, 0x50401U, 0x50400U, 0x20040U, - 0x20041U, 0x20042U, 0x01210U, 0x68002U, 0x68003U, 0x68000U, 0x68001U, 0x04C02U, 0x0120AU, 0x04C00U, 0x01208U, 0x20054U, 0x01206U, - 0x01205U, 0x01204U, 0x20050U, 0x01202U, 0x01201U, 0x01200U, 0x18800U, 0x04042U, 0x04041U, 0x04040U, 0x42202U, 0x04046U, 0x42200U, - 0x04044U, 0x20064U, 0x0404AU, 0x04049U, 0x04048U, 0x20060U, 0x12080U, 0x20062U, 0x12082U, 0x18810U, 0x04052U, 0x04051U, 0x04050U, - 0x4C009U, 0x4C008U, 0x42210U, 0x04054U, 0x20C01U, 0x20C00U, 0x20C03U, 0x20C02U, 0x4C001U, 0x4C000U, 0x01221U, 0x01220U, 0x2000CU, - 0x04022U, 0x04021U, 0x04020U, 0x20008U, 0x20009U, 0x2000AU, 0x04024U, 0x20004U, 0x20005U, 0x20006U, 0x04028U, 0x20000U, 0x20001U, - 0x20002U, 0x20003U, 0x2001CU, 0x04032U, 0x04031U, 0x04030U, 0x20018U, 0x18400U, 0x2001AU, 0x18402U, 0x20014U, 0x20015U, 0x20016U, - 0x01244U, 0x20010U, 0x20011U, 0x20012U, 0x01240U, 0x04003U, 0x04002U, 0x04001U, 0x04000U, 0x20028U, 0x04006U, 0x04005U, 0x04004U, - 0x20024U, 0x0400AU, 0x04009U, 0x04008U, 0x20020U, 0x20021U, 0x20022U, 0x0400CU, 0x04013U, 0x04012U, 0x04011U, 0x04010U, 0x00A81U, - 0x00A80U, 0x04015U, 0x04014U, 0x0A200U, 0x11100U, 0x04019U, 0x04018U, 0x20030U, 0x20031U, 0x50800U, 0x50801U, 0x00700U, 0x60020U, - 0x10811U, 0x10810U, 0x4400AU, 0x60024U, 0x44008U, 0x44009U, 0x44006U, 0x02242U, 0x44004U, 0x02240U, 0x44002U, 0x44003U, 0x44000U, - 0x44001U, 0x0C040U, 0x10802U, 0x10801U, 0x10800U, 0x0C044U, 0x10806U, 0x10805U, 0x10804U, 0x23000U, 0x23001U, 0x10809U, 0x10808U, - 0x44012U, 0x44013U, 0x44010U, 0x44011U, 0x60001U, 0x60000U, 0x60003U, 0x60002U, 0x60005U, 0x60004U, 0x10440U, 0x10441U, 0x60009U, - 0x60008U, 0x44024U, 0x6000AU, 0x09200U, 0x12100U, 0x44020U, 0x44021U, 0x60011U, 0x60010U, 0x10821U, 0x10820U, 0x07003U, 0x07002U, - 0x07001U, 0x07000U, 0x23020U, 0x60018U, 0x28045U, 0x28044U, 0x09210U, 0x28042U, 0x28041U, 0x28040U, 0x0C010U, 0x0C011U, 0x02209U, - 0x02208U, 0x10422U, 0x10423U, 0x10420U, 0x10421U, 0x02203U, 0x02202U, 0x02201U, 0x02200U, 0x20180U, 0x20181U, 0x44040U, 0x02204U, - 0x0C000U, 0x0C001U, 0x0C002U, 0x10840U, 0x0C004U, 0x0C005U, 0x0C006U, 0x10844U, 0x0C008U, 0x0C009U, 0x02211U, 0x02210U, 0x0C00CU, - 0x28022U, 0x28021U, 0x28020U, 0x60041U, 0x60040U, 0x10404U, 0x04180U, 0x10402U, 0x10403U, 0x10400U, 0x10401U, 0x02223U, 0x02222U, - 0x02221U, 0x02220U, 0x1040AU, 0x28012U, 0x10408U, 0x28010U, 0x0C020U, 0x0C021U, 0x41200U, 0x41201U, 0x00B01U, 0x00B00U, 0x10410U, - 0x28008U, 0x11081U, 0x11080U, 0x28005U, 0x28004U, 0x28003U, 0x28002U, 0x28001U, 0x28000U, 0x52040U, 0x14204U, 0x22405U, 0x22404U, - 0x14201U, 0x14200U, 0x22401U, 0x22400U, 0x20144U, 0x20145U, 0x44084U, 0x022C0U, 0x20140U, 0x20141U, 0x44080U, 0x44081U, 0x40A08U, - 0x10882U, 0x10881U, 0x10880U, 0x14211U, 0x14210U, 0x1A008U, 0x10884U, 0x40A00U, 0x40A01U, 0x40A02U, 0x01304U, 0x1A002U, 0x01302U, - 0x1A000U, 0x01300U, 0x60081U, 0x60080U, 0x04141U, 0x04140U, 0x60085U, 0x60084U, 0x104C0U, 0x04144U, 0x06400U, 0x06401U, 0x30200U, - 0x30201U, 0x06404U, 0x40640U, 0x30204U, 0x30205U, 0x08603U, 0x08602U, 0x08601U, 0x08600U, 0x00000U, 0x08606U, 0x08605U, 0x08604U, - 0x11041U, 0x11040U, 0x30210U, 0x11042U, 0x11045U, 0x11044U, 0x1A020U, 0x01320U, 0x52000U, 0x52001U, 0x04121U, 0x04120U, 0x20108U, - 0x20109U, 0x08A00U, 0x08A01U, 0x20104U, 0x20105U, 0x02281U, 0x02280U, 0x20100U, 0x20101U, 0x20102U, 0x20103U, 0x0C080U, 0x0C081U, - 0x0C082U, 0x04130U, 0x0C084U, 0x06808U, 0x08A10U, 0x08A11U, 0x11021U, 0x11020U, 0x11023U, 0x11022U, 0x20110U, 0x06800U, 0x20112U, - 0x06802U, 0x04103U, 0x04102U, 0x04101U, 0x04100U, 0x10482U, 0x04106U, 0x10480U, 0x04104U, 0x11011U, 0x11010U, 0x04109U, 0x04108U, - 0x20120U, 0x40600U, 0x20122U, 0x40602U, 0x11009U, 0x11008U, 0x22800U, 0x04110U, 0x1100DU, 0x1100CU, 0x22804U, 0x04114U, 0x11001U, - 0x11000U, 0x11003U, 0x11002U, 0x11005U, 0x11004U, 0x28081U, 0x28080U}; +{ + 0x00000U, 0x00001U, 0x00002U, 0x00003U, 0x00004U, 0x00005U, 0x00006U, 0x00007U, 0x00008U, 0x00009U, 0x0000AU, 0x0000BU, 0x0000CU, + 0x0000DU, 0x0000EU, 0x24020U, 0x00010U, 0x00011U, 0x00012U, 0x00013U, 0x00014U, 0x00015U, 0x00016U, 0x00017U, 0x00018U, 0x00019U, + 0x0001AU, 0x0001BU, 0x0001CU, 0x0001DU, 0x48040U, 0x01480U, 0x00020U, 0x00021U, 0x00022U, 0x00023U, 0x00024U, 0x00025U, 0x00026U, + 0x24008U, 0x00028U, 0x00029U, 0x0002AU, 0x24004U, 0x0002CU, 0x24002U, 0x24001U, 0x24000U, 0x00030U, 0x00031U, 0x00032U, 0x08180U, + 0x00034U, 0x00C40U, 0x00036U, 0x00C42U, 0x00038U, 0x43000U, 0x0003AU, 0x43002U, 0x02902U, 0x24012U, 0x02900U, 0x24010U, 0x00040U, + 0x00041U, 0x00042U, 0x00043U, 0x00044U, 0x00045U, 0x00046U, 0x00047U, 0x00048U, 0x00049U, 0x0004AU, 0x02500U, 0x0004CU, 0x0004DU, + 0x48010U, 0x48011U, 0x00050U, 0x00051U, 0x00052U, 0x21200U, 0x00054U, 0x00C20U, 0x48008U, 0x48009U, 0x00058U, 0x00059U, 0x48004U, + 0x48005U, 0x48002U, 0x48003U, 0x48000U, 0x48001U, 0x00060U, 0x00061U, 0x00062U, 0x00063U, 0x00064U, 0x00C10U, 0x10300U, 0x0B000U, + 0x00068U, 0x00069U, 0x01880U, 0x01881U, 0x40181U, 0x40180U, 0x24041U, 0x24040U, 0x00070U, 0x00C04U, 0x00072U, 0x00C06U, 0x00C01U, + 0x00C00U, 0x00C03U, 0x00C02U, 0x05204U, 0x00C0CU, 0x48024U, 0x48025U, 0x05200U, 0x00C08U, 0x48020U, 0x48021U, 0x00080U, 0x00081U, + 0x00082U, 0x00083U, 0x00084U, 0x00085U, 0x00086U, 0x00087U, 0x00088U, 0x00089U, 0x0008AU, 0x50200U, 0x0008CU, 0x0A800U, 0x01411U, + 0x01410U, 0x00090U, 0x00091U, 0x00092U, 0x08120U, 0x00094U, 0x00095U, 0x04A00U, 0x01408U, 0x00098U, 0x00099U, 0x01405U, 0x01404U, + 0x01403U, 0x01402U, 0x01401U, 0x01400U, 0x000A0U, 0x000A1U, 0x000A2U, 0x08110U, 0x000A4U, 0x000A5U, 0x42400U, 0x42401U, 0x000A8U, + 0x000A9U, 0x01840U, 0x01841U, 0x40141U, 0x40140U, 0x24081U, 0x24080U, 0x000B0U, 0x08102U, 0x08101U, 0x08100U, 0x000B4U, 0x08106U, + 0x08105U, 0x08104U, 0x20A01U, 0x20A00U, 0x08109U, 0x08108U, 0x01423U, 0x01422U, 0x01421U, 0x01420U, 0x000C0U, 0x000C1U, 0x000C2U, + 0x000C3U, 0x000C4U, 0x000C5U, 0x000C6U, 0x000C7U, 0x000C8U, 0x000C9U, 0x01820U, 0x01821U, 0x20600U, 0x40120U, 0x16000U, 0x16001U, + 0x000D0U, 0x000D1U, 0x42801U, 0x42800U, 0x03100U, 0x18200U, 0x03102U, 0x18202U, 0x000D8U, 0x000D9U, 0x48084U, 0x01444U, 0x48082U, + 0x01442U, 0x48080U, 0x01440U, 0x000E0U, 0x32000U, 0x01808U, 0x04600U, 0x40109U, 0x40108U, 0x0180CU, 0x4010AU, 0x01802U, 0x40104U, + 0x01800U, 0x01801U, 0x40101U, 0x40100U, 0x01804U, 0x40102U, 0x0A408U, 0x08142U, 0x08141U, 0x08140U, 0x00C81U, 0x00C80U, 0x00C83U, + 0x00C82U, 0x0A400U, 0x0A401U, 0x01810U, 0x01811U, 0x40111U, 0x40110U, 0x01814U, 0x40112U, 0x00100U, 0x00101U, 0x00102U, 0x00103U, + 0x00104U, 0x00105U, 0x00106U, 0x41800U, 0x00108U, 0x00109U, 0x0010AU, 0x02440U, 0x0010CU, 0x0010DU, 0x0010EU, 0x02444U, 0x00110U, + 0x00111U, 0x00112U, 0x080A0U, 0x00114U, 0x00115U, 0x00116U, 0x080A4U, 0x00118U, 0x00119U, 0x15000U, 0x15001U, 0x02822U, 0x02823U, + 0x02820U, 0x02821U, 0x00120U, 0x00121U, 0x00122U, 0x08090U, 0x00124U, 0x00125U, 0x10240U, 0x10241U, 0x00128U, 0x00129U, 0x0012AU, + 0x24104U, 0x09400U, 0x400C0U, 0x02810U, 0x24100U, 0x00130U, 0x08082U, 0x08081U, 0x08080U, 0x31001U, 0x31000U, 0x02808U, 0x08084U, + 0x02806U, 0x0808AU, 0x02804U, 0x08088U, 0x02802U, 0x02803U, 0x02800U, 0x02801U, 0x00140U, 0x00141U, 0x00142U, 0x02408U, 0x00144U, + 0x00145U, 0x10220U, 0x10221U, 0x00148U, 0x02402U, 0x02401U, 0x02400U, 0x400A1U, 0x400A0U, 0x02405U, 0x02404U, 0x00150U, 0x00151U, + 0x00152U, 0x02418U, 0x03080U, 0x03081U, 0x03082U, 0x03083U, 0x09801U, 0x09800U, 0x02411U, 0x02410U, 0x48102U, 0x09804U, 0x48100U, + 0x48101U, 0x00160U, 0x00161U, 0x10204U, 0x10205U, 0x10202U, 0x40088U, 0x10200U, 0x10201U, 0x40085U, 0x40084U, 0x02421U, 0x02420U, + 0x40081U, 0x40080U, 0x10208U, 0x40082U, 0x41402U, 0x080C2U, 0x41400U, 0x080C0U, 0x00D01U, 0x00D00U, 0x10210U, 0x10211U, 0x40095U, + 0x40094U, 0x02844U, 0x080C8U, 0x40091U, 0x40090U, 0x02840U, 0x02841U, 0x00180U, 0x00181U, 0x00182U, 0x08030U, 0x00184U, 0x14400U, + 0x22201U, 0x22200U, 0x00188U, 0x00189U, 0x0018AU, 0x08038U, 0x40061U, 0x40060U, 0x40063U, 0x40062U, 0x00190U, 0x08022U, 0x08021U, + 0x08020U, 0x03040U, 0x03041U, 0x08025U, 0x08024U, 0x40C00U, 0x40C01U, 0x08029U, 0x08028U, 0x2C000U, 0x2C001U, 0x01501U, 0x01500U, + 0x001A0U, 0x08012U, 0x08011U, 0x08010U, 0x40049U, 0x40048U, 0x08015U, 0x08014U, 0x06200U, 0x40044U, 0x30400U, 0x08018U, 0x40041U, + 0x40040U, 0x40043U, 0x40042U, 0x08003U, 0x08002U, 0x08001U, 0x08000U, 0x08007U, 0x08006U, 0x08005U, 0x08004U, 0x0800BU, 0x0800AU, + 0x08009U, 0x08008U, 0x40051U, 0x40050U, 0x02880U, 0x0800CU, 0x001C0U, 0x001C1U, 0x64000U, 0x64001U, 0x03010U, 0x40028U, 0x08C00U, + 0x08C01U, 0x40025U, 0x40024U, 0x02481U, 0x02480U, 0x40021U, 0x40020U, 0x40023U, 0x40022U, 0x03004U, 0x03005U, 0x08061U, 0x08060U, + 0x03000U, 0x03001U, 0x03002U, 0x03003U, 0x0300CU, 0x40034U, 0x30805U, 0x30804U, 0x03008U, 0x40030U, 0x30801U, 0x30800U, 0x4000DU, + 0x4000CU, 0x08051U, 0x08050U, 0x40009U, 0x40008U, 0x10280U, 0x4000AU, 0x40005U, 0x40004U, 0x01900U, 0x40006U, 0x40001U, 0x40000U, + 0x40003U, 0x40002U, 0x14800U, 0x08042U, 0x08041U, 0x08040U, 0x03020U, 0x40018U, 0x08045U, 0x08044U, 0x40015U, 0x40014U, 0x08049U, + 0x08048U, 0x40011U, 0x40010U, 0x40013U, 0x40012U, 0x00200U, 0x00201U, 0x00202U, 0x00203U, 0x00204U, 0x00205U, 0x00206U, 0x00207U, + 0x00208U, 0x00209U, 0x0020AU, 0x50080U, 0x0020CU, 0x0020DU, 0x0020EU, 0x50084U, 0x00210U, 0x00211U, 0x00212U, 0x21040U, 0x00214U, + 0x00215U, 0x04880U, 0x04881U, 0x00218U, 0x00219U, 0x0E001U, 0x0E000U, 0x0021CU, 0x0021DU, 0x04888U, 0x0E004U, 0x00220U, 0x00221U, + 0x00222U, 0x00223U, 0x00224U, 0x00225U, 0x10140U, 0x10141U, 0x00228U, 0x00229U, 0x0022AU, 0x24204U, 0x12401U, 0x12400U, 0x24201U, + 0x24200U, 0x00230U, 0x00231U, 0x00232U, 0x21060U, 0x2A000U, 0x2A001U, 0x2A002U, 0x2A003U, 0x20881U, 0x20880U, 0x20883U, 0x20882U, + 0x05040U, 0x05041U, 0x05042U, 0x24210U, 0x00240U, 0x00241U, 0x00242U, 0x21010U, 0x00244U, 0x46000U, 0x10120U, 0x10121U, 0x00248U, + 0x00249U, 0x0024AU, 0x21018U, 0x20480U, 0x20481U, 0x20482U, 0x20483U, 0x00250U, 0x21002U, 0x21001U, 0x21000U, 0x18081U, 0x18080U, + 0x21005U, 0x21004U, 0x12800U, 0x12801U, 0x21009U, 0x21008U, 0x05020U, 0x05021U, 0x48200U, 0x48201U, 0x00260U, 0x00261U, 0x10104U, + 0x04480U, 0x10102U, 0x10103U, 0x10100U, 0x10101U, 0x62002U, 0x62003U, 0x62000U, 0x62001U, 0x05010U, 0x05011U, 0x10108U, 0x10109U, + 0x0500CU, 0x21022U, 0x21021U, 0x21020U, 0x05008U, 0x00E00U, 0x10110U, 0x10111U, 0x05004U, 0x05005U, 0x05006U, 0x21028U, 0x05000U, + 0x05001U, 0x05002U, 0x05003U, 0x00280U, 0x00281U, 0x00282U, 0x50008U, 0x00284U, 0x00285U, 0x04810U, 0x22100U, 0x00288U, 0x50002U, + 0x50001U, 0x50000U, 0x20440U, 0x20441U, 0x50005U, 0x50004U, 0x00290U, 0x00291U, 0x04804U, 0x04805U, 0x04802U, 0x18040U, 0x04800U, + 0x04801U, 0x20821U, 0x20820U, 0x50011U, 0x50010U, 0x0480AU, 0x01602U, 0x04808U, 0x01600U, 0x002A0U, 0x002A1U, 0x04441U, 0x04440U, + 0x002A4U, 0x002A5U, 0x04830U, 0x04444U, 0x06100U, 0x20810U, 0x50021U, 0x50020U, 0x06104U, 0x20814U, 0x50025U, 0x50024U, 0x20809U, + 0x20808U, 0x13000U, 0x08300U, 0x04822U, 0x2080CU, 0x04820U, 0x04821U, 0x20801U, 0x20800U, 0x20803U, 0x20802U, 0x20805U, 0x20804U, + 0x04828U, 0x20806U, 0x002C0U, 0x002C1U, 0x04421U, 0x04420U, 0x20408U, 0x18010U, 0x2040AU, 0x18012U, 0x20404U, 0x20405U, 0x50041U, + 0x50040U, 0x20400U, 0x20401U, 0x20402U, 0x20403U, 0x18005U, 0x18004U, 0x21081U, 0x21080U, 0x18001U, 0x18000U, 0x04840U, 0x18002U, + 0x20414U, 0x1800CU, 0x21089U, 0x21088U, 0x20410U, 0x18008U, 0x20412U, 0x1800AU, 0x04403U, 0x04402U, 0x04401U, 0x04400U, 0x10182U, + 0x04406U, 0x10180U, 0x04404U, 0x01A02U, 0x0440AU, 0x01A00U, 0x04408U, 0x20420U, 0x40300U, 0x20422U, 0x40302U, 0x04413U, 0x04412U, + 0x04411U, 0x04410U, 0x18021U, 0x18020U, 0x10190U, 0x18022U, 0x20841U, 0x20840U, 0x01A10U, 0x20842U, 0x05080U, 0x05081U, 0x05082U, + 0x05083U, 0x00300U, 0x00301U, 0x00302U, 0x00303U, 0x00304U, 0x00305U, 0x10060U, 0x22080U, 0x00308U, 0x00309U, 0x28800U, 0x28801U, + 0x44402U, 0x44403U, 0x44400U, 0x44401U, 0x00310U, 0x00311U, 0x10C01U, 0x10C00U, 0x00314U, 0x00315U, 0x10070U, 0x10C04U, 0x00318U, + 0x00319U, 0x28810U, 0x10C08U, 0x44412U, 0x00000U, 0x44410U, 0x44411U, 0x00320U, 0x60400U, 0x10044U, 0x10045U, 0x10042U, 0x0C800U, + 0x10040U, 0x10041U, 0x06080U, 0x06081U, 0x06082U, 0x06083U, 0x1004AU, 0x0C808U, 0x10048U, 0x10049U, 0x58008U, 0x08282U, 0x08281U, + 0x08280U, 0x10052U, 0x0C810U, 0x10050U, 0x10051U, 0x58000U, 0x58001U, 0x58002U, 0x08288U, 0x02A02U, 0x02A03U, 0x02A00U, 0x02A01U, + 0x00340U, 0x00341U, 0x10024U, 0x10025U, 0x10022U, 0x10023U, 0x10020U, 0x10021U, 0x34001U, 0x34000U, 0x02601U, 0x02600U, 0x1002AU, + 0x34004U, 0x10028U, 0x10029U, 0x0C400U, 0x0C401U, 0x21101U, 0x21100U, 0x60800U, 0x60801U, 0x10030U, 0x10031U, 0x0C408U, 0x34010U, + 0x21109U, 0x21108U, 0x60808U, 0x60809U, 0x10038U, 0x28420U, 0x10006U, 0x10007U, 0x10004U, 0x10005U, 0x10002U, 0x10003U, 0x10000U, + 0x10001U, 0x1000EU, 0x40284U, 0x1000CU, 0x1000DU, 0x1000AU, 0x40280U, 0x10008U, 0x10009U, 0x10016U, 0x10017U, 0x10014U, 0x10015U, + 0x10012U, 0x10013U, 0x10010U, 0x10011U, 0x05104U, 0x44802U, 0x44801U, 0x44800U, 0x05100U, 0x05101U, 0x10018U, 0x28400U, 0x00380U, + 0x00381U, 0x22005U, 0x22004U, 0x22003U, 0x22002U, 0x22001U, 0x22000U, 0x06020U, 0x06021U, 0x50101U, 0x50100U, 0x11800U, 0x11801U, + 0x22009U, 0x22008U, 0x45001U, 0x45000U, 0x08221U, 0x08220U, 0x04902U, 0x22012U, 0x04900U, 0x22010U, 0x06030U, 0x45008U, 0x08229U, + 0x08228U, 0x11810U, 0x11811U, 0x04908U, 0x22018U, 0x06008U, 0x06009U, 0x08211U, 0x08210U, 0x100C2U, 0x22022U, 0x100C0U, 0x22020U, + 0x06000U, 0x06001U, 0x06002U, 0x06003U, 0x06004U, 0x40240U, 0x06006U, 0x40242U, 0x08203U, 0x08202U, 0x08201U, 0x08200U, 0x08207U, + 0x08206U, 0x08205U, 0x08204U, 0x06010U, 0x20900U, 0x08209U, 0x08208U, 0x61002U, 0x20904U, 0x61000U, 0x61001U, 0x29020U, 0x29021U, + 0x100A4U, 0x22044U, 0x100A2U, 0x22042U, 0x100A0U, 0x22040U, 0x20504U, 0x40224U, 0x0D005U, 0x0D004U, 0x20500U, 0x40220U, 0x0D001U, + 0x0D000U, 0x03204U, 0x18104U, 0x08261U, 0x08260U, 0x03200U, 0x18100U, 0x03202U, 0x18102U, 0x11421U, 0x11420U, 0x00000U, 0x11422U, + 0x03208U, 0x18108U, 0x0D011U, 0x0D010U, 0x29000U, 0x29001U, 0x10084U, 0x04500U, 0x10082U, 0x40208U, 0x10080U, 0x10081U, 0x06040U, + 0x40204U, 0x06042U, 0x40206U, 0x40201U, 0x40200U, 0x10088U, 0x40202U, 0x29010U, 0x08242U, 0x08241U, 0x08240U, 0x10092U, 0x40218U, + 0x10090U, 0x10091U, 0x11401U, 0x11400U, 0x11403U, 0x11402U, 0x40211U, 0x40210U, 0x10098U, 0x40212U, 0x00400U, 0x00401U, 0x00402U, + 0x00403U, 0x00404U, 0x00405U, 0x00406U, 0x00407U, 0x00408U, 0x00409U, 0x0040AU, 0x02140U, 0x0040CU, 0x0040DU, 0x01091U, 0x01090U, + 0x00410U, 0x00411U, 0x00412U, 0x00413U, 0x00414U, 0x00860U, 0x01089U, 0x01088U, 0x00418U, 0x38000U, 0x01085U, 0x01084U, 0x01083U, + 0x01082U, 0x01081U, 0x01080U, 0x00420U, 0x00421U, 0x00422U, 0x00423U, 0x00424U, 0x00850U, 0x42080U, 0x42081U, 0x00428U, 0x00429U, + 0x48801U, 0x48800U, 0x09100U, 0x12200U, 0x24401U, 0x24400U, 0x00430U, 0x00844U, 0x00432U, 0x00846U, 0x00841U, 0x00840U, 0x1C000U, + 0x00842U, 0x00438U, 0x0084CU, 0x010A5U, 0x010A4U, 0x00849U, 0x00848U, 0x010A1U, 0x010A0U, 0x00440U, 0x00441U, 0x00442U, 0x02108U, + 0x00444U, 0x00830U, 0x70001U, 0x70000U, 0x00448U, 0x02102U, 0x02101U, 0x02100U, 0x20280U, 0x20281U, 0x02105U, 0x02104U, 0x00450U, + 0x00824U, 0x00452U, 0x00826U, 0x00821U, 0x00820U, 0x00823U, 0x00822U, 0x24802U, 0x02112U, 0x24800U, 0x02110U, 0x00829U, 0x00828U, + 0x48400U, 0x010C0U, 0x00460U, 0x00814U, 0x04281U, 0x04280U, 0x00811U, 0x00810U, 0x00813U, 0x00812U, 0x54000U, 0x54001U, 0x02121U, + 0x02120U, 0x00819U, 0x00818U, 0x0081BU, 0x0081AU, 0x00805U, 0x00804U, 0x41100U, 0x00806U, 0x00801U, 0x00800U, 0x00803U, 0x00802U, + 0x0A080U, 0x0080CU, 0x0A082U, 0x0080EU, 0x00809U, 0x00808U, 0x0080BU, 0x0080AU, 0x00480U, 0x00481U, 0x00482U, 0x00483U, 0x00484U, + 0x14100U, 0x42020U, 0x01018U, 0x00488U, 0x00489U, 0x01015U, 0x01014U, 0x20240U, 0x01012U, 0x01011U, 0x01010U, 0x00490U, 0x00491U, + 0x0100DU, 0x0100CU, 0x0100BU, 0x0100AU, 0x01009U, 0x01008U, 0x40900U, 0x01006U, 0x01005U, 0x01004U, 0x01003U, 0x01002U, 0x01001U, + 0x01000U, 0x004A0U, 0x004A1U, 0x42004U, 0x04240U, 0x42002U, 0x42003U, 0x42000U, 0x42001U, 0x30102U, 0x30103U, 0x30100U, 0x30101U, + 0x4200AU, 0x01032U, 0x42008U, 0x01030U, 0x25000U, 0x25001U, 0x08501U, 0x08500U, 0x008C1U, 0x008C0U, 0x42010U, 0x01028U, 0x0A040U, + 0x0A041U, 0x01025U, 0x01024U, 0x01023U, 0x01022U, 0x01021U, 0x01020U, 0x004C0U, 0x49000U, 0x04221U, 0x04220U, 0x20208U, 0x20209U, + 0x08900U, 0x08901U, 0x20204U, 0x20205U, 0x02181U, 0x02180U, 0x20200U, 0x20201U, 0x20202U, 0x01050U, 0x0A028U, 0x008A4U, 0x0104DU, + 0x0104CU, 0x008A1U, 0x008A0U, 0x01049U, 0x01048U, 0x0A020U, 0x0A021U, 0x01045U, 0x01044U, 0x20210U, 0x01042U, 0x01041U, 0x01040U, + 0x04203U, 0x04202U, 0x04201U, 0x04200U, 0x00891U, 0x00890U, 0x42040U, 0x04204U, 0x0A010U, 0x0A011U, 0x01C00U, 0x04208U, 0x20220U, + 0x40500U, 0x20222U, 0x40502U, 0x0A008U, 0x00884U, 0x04211U, 0x04210U, 0x00881U, 0x00880U, 0x00883U, 0x00882U, 0x0A000U, 0x0A001U, + 0x0A002U, 0x0A003U, 0x0A004U, 0x00888U, 0x01061U, 0x01060U, 0x00500U, 0x00501U, 0x00502U, 0x02048U, 0x00504U, 0x14080U, 0x00506U, + 0x14082U, 0x00508U, 0x02042U, 0x02041U, 0x02040U, 0x09020U, 0x09021U, 0x44200U, 0x02044U, 0x00510U, 0x00511U, 0x10A01U, 0x10A00U, + 0x4A001U, 0x4A000U, 0x4A003U, 0x4A002U, 0x40880U, 0x40881U, 0x02051U, 0x02050U, 0x40884U, 0x01182U, 0x01181U, 0x01180U, 0x00520U, + 0x60200U, 0x00522U, 0x60202U, 0x09008U, 0x09009U, 0x0900AU, 0x0900BU, 0x09004U, 0x09005U, 0x30080U, 0x02060U, 0x09000U, 0x09001U, + 0x09002U, 0x09003U, 0x41042U, 0x08482U, 0x41040U, 0x08480U, 0x00941U, 0x00940U, 0x41044U, 0x00942U, 0x09014U, 0x09015U, 0x02C04U, + 0x08488U, 0x09010U, 0x09011U, 0x02C00U, 0x02C01U, 0x00540U, 0x0200AU, 0x02009U, 0x02008U, 0x08882U, 0x0200EU, 0x08880U, 0x0200CU, + 0x02003U, 0x02002U, 0x02001U, 0x02000U, 0x02007U, 0x02006U, 0x02005U, 0x02004U, 0x0C200U, 0x0C201U, 0x41020U, 0x02018U, 0x00921U, + 0x00920U, 0x41024U, 0x00922U, 0x02013U, 0x02012U, 0x02011U, 0x02010U, 0x02017U, 0x02016U, 0x02015U, 0x02014U, 0x41012U, 0x0202AU, + 0x41010U, 0x02028U, 0x26000U, 0x00910U, 0x10600U, 0x10601U, 0x02023U, 0x02022U, 0x02021U, 0x02020U, 0x09040U, 0x40480U, 0x02025U, + 0x02024U, 0x41002U, 0x00904U, 0x41000U, 0x41001U, 0x00901U, 0x00900U, 0x41004U, 0x00902U, 0x4100AU, 0x02032U, 0x41008U, 0x02030U, + 0x00909U, 0x00908U, 0x28201U, 0x28200U, 0x00580U, 0x14004U, 0x00582U, 0x14006U, 0x14001U, 0x14000U, 0x08840U, 0x14002U, 0x40810U, + 0x40811U, 0x30020U, 0x020C0U, 0x14009U, 0x14008U, 0x01111U, 0x01110U, 0x40808U, 0x40809U, 0x08421U, 0x08420U, 0x14011U, 0x14010U, + 0x01109U, 0x01108U, 0x40800U, 0x40801U, 0x40802U, 0x01104U, 0x40804U, 0x01102U, 0x01101U, 0x01100U, 0x03801U, 0x03800U, 0x30008U, + 0x08410U, 0x14021U, 0x14020U, 0x42100U, 0x42101U, 0x30002U, 0x30003U, 0x30000U, 0x30001U, 0x09080U, 0x40440U, 0x30004U, 0x30005U, + 0x08403U, 0x08402U, 0x08401U, 0x08400U, 0x08407U, 0x08406U, 0x08405U, 0x08404U, 0x40820U, 0x40821U, 0x30010U, 0x08408U, 0x40824U, + 0x01122U, 0x01121U, 0x01120U, 0x08806U, 0x0208AU, 0x08804U, 0x02088U, 0x08802U, 0x14040U, 0x08800U, 0x08801U, 0x02083U, 0x02082U, + 0x02081U, 0x02080U, 0x20300U, 0x40420U, 0x08808U, 0x02084U, 0x03404U, 0x03405U, 0x08814U, 0x02098U, 0x03400U, 0x03401U, 0x08810U, + 0x08811U, 0x40840U, 0x40841U, 0x02091U, 0x02090U, 0x40844U, 0x01142U, 0x01141U, 0x01140U, 0x04303U, 0x04302U, 0x04301U, 0x04300U, + 0x40409U, 0x40408U, 0x08820U, 0x08821U, 0x40405U, 0x40404U, 0x30040U, 0x020A0U, 0x40401U, 0x40400U, 0x40403U, 0x40402U, 0x41082U, + 0x08442U, 0x41080U, 0x08440U, 0x00981U, 0x00980U, 0x41084U, 0x00982U, 0x0A100U, 0x11200U, 0x0A102U, 0x11202U, 0x40411U, 0x40410U, + 0x40413U, 0x40412U, 0x00600U, 0x00601U, 0x00602U, 0x00603U, 0x00604U, 0x00605U, 0x00606U, 0x00607U, 0x00608U, 0x05800U, 0x0060AU, + 0x05802U, 0x200C0U, 0x12020U, 0x44100U, 0x44101U, 0x00610U, 0x00611U, 0x10901U, 0x10900U, 0x51000U, 0x51001U, 0x51002U, 0x10904U, + 0x00618U, 0x05810U, 0x01285U, 0x01284U, 0x51008U, 0x01282U, 0x01281U, 0x01280U, 0x00620U, 0x60100U, 0x040C1U, 0x040C0U, 0x12009U, + 0x12008U, 0x21800U, 0x21801U, 0x12005U, 0x12004U, 0x12007U, 0x12006U, 0x12001U, 0x12000U, 0x12003U, 0x12002U, 0x00630U, 0x00A44U, + 0x040D1U, 0x040D0U, 0x00A41U, 0x00A40U, 0x21810U, 0x00A42U, 0x12015U, 0x12014U, 0x00000U, 0x12016U, 0x12011U, 0x12010U, 0x12013U, + 0x12012U, 0x00640U, 0x00641U, 0x040A1U, 0x040A0U, 0x20088U, 0x20089U, 0x2008AU, 0x040A4U, 0x20084U, 0x20085U, 0x19000U, 0x02300U, + 0x20080U, 0x20081U, 0x20082U, 0x20083U, 0x0C100U, 0x0C101U, 0x21401U, 0x21400U, 0x00A21U, 0x00A20U, 0x00A23U, 0x00A22U, 0x20094U, + 0x20095U, 0x19010U, 0x21408U, 0x20090U, 0x20091U, 0x20092U, 0x28120U, 0x04083U, 0x04082U, 0x04081U, 0x04080U, 0x00A11U, 0x00A10U, + 0x10500U, 0x04084U, 0x200A4U, 0x0408AU, 0x04089U, 0x04088U, 0x200A0U, 0x12040U, 0x200A2U, 0x12042U, 0x00A05U, 0x00A04U, 0x04091U, + 0x04090U, 0x00A01U, 0x00A00U, 0x00A03U, 0x00A02U, 0x05404U, 0x00A0CU, 0x28105U, 0x28104U, 0x05400U, 0x00A08U, 0x28101U, 0x28100U, + 0x00680U, 0x00681U, 0x04061U, 0x04060U, 0x20048U, 0x20049U, 0x2004AU, 0x04064U, 0x20044U, 0x20045U, 0x50401U, 0x50400U, 0x20040U, + 0x20041U, 0x20042U, 0x01210U, 0x68002U, 0x68003U, 0x68000U, 0x68001U, 0x04C02U, 0x0120AU, 0x04C00U, 0x01208U, 0x20054U, 0x01206U, + 0x01205U, 0x01204U, 0x20050U, 0x01202U, 0x01201U, 0x01200U, 0x18800U, 0x04042U, 0x04041U, 0x04040U, 0x42202U, 0x04046U, 0x42200U, + 0x04044U, 0x20064U, 0x0404AU, 0x04049U, 0x04048U, 0x20060U, 0x12080U, 0x20062U, 0x12082U, 0x18810U, 0x04052U, 0x04051U, 0x04050U, + 0x4C009U, 0x4C008U, 0x42210U, 0x04054U, 0x20C01U, 0x20C00U, 0x20C03U, 0x20C02U, 0x4C001U, 0x4C000U, 0x01221U, 0x01220U, 0x2000CU, + 0x04022U, 0x04021U, 0x04020U, 0x20008U, 0x20009U, 0x2000AU, 0x04024U, 0x20004U, 0x20005U, 0x20006U, 0x04028U, 0x20000U, 0x20001U, + 0x20002U, 0x20003U, 0x2001CU, 0x04032U, 0x04031U, 0x04030U, 0x20018U, 0x18400U, 0x2001AU, 0x18402U, 0x20014U, 0x20015U, 0x20016U, + 0x01244U, 0x20010U, 0x20011U, 0x20012U, 0x01240U, 0x04003U, 0x04002U, 0x04001U, 0x04000U, 0x20028U, 0x04006U, 0x04005U, 0x04004U, + 0x20024U, 0x0400AU, 0x04009U, 0x04008U, 0x20020U, 0x20021U, 0x20022U, 0x0400CU, 0x04013U, 0x04012U, 0x04011U, 0x04010U, 0x00A81U, + 0x00A80U, 0x04015U, 0x04014U, 0x0A200U, 0x11100U, 0x04019U, 0x04018U, 0x20030U, 0x20031U, 0x50800U, 0x50801U, 0x00700U, 0x60020U, + 0x10811U, 0x10810U, 0x4400AU, 0x60024U, 0x44008U, 0x44009U, 0x44006U, 0x02242U, 0x44004U, 0x02240U, 0x44002U, 0x44003U, 0x44000U, + 0x44001U, 0x0C040U, 0x10802U, 0x10801U, 0x10800U, 0x0C044U, 0x10806U, 0x10805U, 0x10804U, 0x23000U, 0x23001U, 0x10809U, 0x10808U, + 0x44012U, 0x44013U, 0x44010U, 0x44011U, 0x60001U, 0x60000U, 0x60003U, 0x60002U, 0x60005U, 0x60004U, 0x10440U, 0x10441U, 0x60009U, + 0x60008U, 0x44024U, 0x6000AU, 0x09200U, 0x12100U, 0x44020U, 0x44021U, 0x60011U, 0x60010U, 0x10821U, 0x10820U, 0x07003U, 0x07002U, + 0x07001U, 0x07000U, 0x23020U, 0x60018U, 0x28045U, 0x28044U, 0x09210U, 0x28042U, 0x28041U, 0x28040U, 0x0C010U, 0x0C011U, 0x02209U, + 0x02208U, 0x10422U, 0x10423U, 0x10420U, 0x10421U, 0x02203U, 0x02202U, 0x02201U, 0x02200U, 0x20180U, 0x20181U, 0x44040U, 0x02204U, + 0x0C000U, 0x0C001U, 0x0C002U, 0x10840U, 0x0C004U, 0x0C005U, 0x0C006U, 0x10844U, 0x0C008U, 0x0C009U, 0x02211U, 0x02210U, 0x0C00CU, + 0x28022U, 0x28021U, 0x28020U, 0x60041U, 0x60040U, 0x10404U, 0x04180U, 0x10402U, 0x10403U, 0x10400U, 0x10401U, 0x02223U, 0x02222U, + 0x02221U, 0x02220U, 0x1040AU, 0x28012U, 0x10408U, 0x28010U, 0x0C020U, 0x0C021U, 0x41200U, 0x41201U, 0x00B01U, 0x00B00U, 0x10410U, + 0x28008U, 0x11081U, 0x11080U, 0x28005U, 0x28004U, 0x28003U, 0x28002U, 0x28001U, 0x28000U, 0x52040U, 0x14204U, 0x22405U, 0x22404U, + 0x14201U, 0x14200U, 0x22401U, 0x22400U, 0x20144U, 0x20145U, 0x44084U, 0x022C0U, 0x20140U, 0x20141U, 0x44080U, 0x44081U, 0x40A08U, + 0x10882U, 0x10881U, 0x10880U, 0x14211U, 0x14210U, 0x1A008U, 0x10884U, 0x40A00U, 0x40A01U, 0x40A02U, 0x01304U, 0x1A002U, 0x01302U, + 0x1A000U, 0x01300U, 0x60081U, 0x60080U, 0x04141U, 0x04140U, 0x60085U, 0x60084U, 0x104C0U, 0x04144U, 0x06400U, 0x06401U, 0x30200U, + 0x30201U, 0x06404U, 0x40640U, 0x30204U, 0x30205U, 0x08603U, 0x08602U, 0x08601U, 0x08600U, 0x00000U, 0x08606U, 0x08605U, 0x08604U, + 0x11041U, 0x11040U, 0x30210U, 0x11042U, 0x11045U, 0x11044U, 0x1A020U, 0x01320U, 0x52000U, 0x52001U, 0x04121U, 0x04120U, 0x20108U, + 0x20109U, 0x08A00U, 0x08A01U, 0x20104U, 0x20105U, 0x02281U, 0x02280U, 0x20100U, 0x20101U, 0x20102U, 0x20103U, 0x0C080U, 0x0C081U, + 0x0C082U, 0x04130U, 0x0C084U, 0x06808U, 0x08A10U, 0x08A11U, 0x11021U, 0x11020U, 0x11023U, 0x11022U, 0x20110U, 0x06800U, 0x20112U, + 0x06802U, 0x04103U, 0x04102U, 0x04101U, 0x04100U, 0x10482U, 0x04106U, 0x10480U, 0x04104U, 0x11011U, 0x11010U, 0x04109U, 0x04108U, + 0x20120U, 0x40600U, 0x20122U, 0x40602U, 0x11009U, 0x11008U, 0x22800U, 0x04110U, 0x1100DU, 0x1100CU, 0x22804U, 0x04114U, 0x11001U, + 0x11000U, 0x11003U, 0x11002U, 0x11005U, 0x11004U, 0x28081U, 0x28080U +}; #define X18 0x00040000 /* vector representation of X^{18} */ #define X11 0x00000800 /* vector representation of X^{11} */ @@ -221,42 +225,44 @@ unsigned int CGolay2087::getSyndrome1987(unsigned int pattern) * obtain its syndrome in decoding. */ { - unsigned int aux = X18; + unsigned int aux = X18; - if (pattern >= X11) { - while (pattern & MASK8) { - while (!(aux & pattern)) - aux = aux >> 1; + if (pattern >= X11) + { + while (pattern & MASK8) + { + while (!(aux & pattern)) + aux = aux >> 1; - pattern ^= (aux / X11) * GENPOL; - } - } + pattern ^= (aux / X11) * GENPOL; + } + } - return pattern; + return pattern; } unsigned char CGolay2087::decode(const unsigned char* data) { - assert(data != nullptr); + assert(data != nullptr); - unsigned int code = (data[0U] << 11) + (data[1U] << 3) + (data[2U] >> 5); - unsigned int syndrome = getSyndrome1987(code); - unsigned int error_pattern = DECODING_TABLE_1987[syndrome]; + unsigned int code = (data[0U] << 11) + (data[1U] << 3) + (data[2U] >> 5); + unsigned int syndrome = getSyndrome1987(code); + unsigned int error_pattern = DECODING_TABLE_1987[syndrome]; - if (error_pattern != 0x00U) - code ^= error_pattern; + if (error_pattern != 0x00U) + code ^= error_pattern; - return code >> 11; + return code >> 11; } void CGolay2087::encode(unsigned char* data) { - assert(data != nullptr); + assert(data != nullptr); - unsigned int value = data[0U]; + unsigned int value = data[0U]; - unsigned int cksum = ENCODING_TABLE_2087[value]; + unsigned int cksum = ENCODING_TABLE_2087[value]; - data[1U] = cksum & 0xFFU; - data[2U] = cksum >> 8; + data[1U] = cksum & 0xFFU; + data[2U] = cksum >> 8; } diff --git a/src/cgolay2087.h b/src/cgolay2087.h index 22c5c16..3f6a25f 100644 --- a/src/cgolay2087.h +++ b/src/cgolay2087.h @@ -19,14 +19,15 @@ #ifndef Golay2087_H #define Golay2087_H -class CGolay2087 { +class CGolay2087 +{ public: - static void encode(unsigned char* data); - - static unsigned char decode(const unsigned char* data); - + static void encode(unsigned char* data); + + static unsigned char decode(const unsigned char* data); + private: - static unsigned int getSyndrome1987(unsigned int pattern); + static unsigned int getSyndrome1987(unsigned int pattern); }; #endif diff --git a/src/cgolay24128.cpp b/src/cgolay24128.cpp index 4dfcba5..26baa75 100644 --- a/src/cgolay24128.cpp +++ b/src/cgolay24128.cpp @@ -8,1036 +8,1042 @@ #include #include -const unsigned int ENCODING_TABLE_23127[] = { - 0x000000U, 0x0018EAU, 0x00293EU, 0x0031D4U, 0x004A96U, 0x00527CU, 0x0063A8U, 0x007B42U, 0x008DC6U, 0x00952CU, - 0x00A4F8U, 0x00BC12U, 0x00C750U, 0x00DFBAU, 0x00EE6EU, 0x00F684U, 0x010366U, 0x011B8CU, 0x012A58U, 0x0132B2U, - 0x0149F0U, 0x01511AU, 0x0160CEU, 0x017824U, 0x018EA0U, 0x01964AU, 0x01A79EU, 0x01BF74U, 0x01C436U, 0x01DCDCU, - 0x01ED08U, 0x01F5E2U, 0x0206CCU, 0x021E26U, 0x022FF2U, 0x023718U, 0x024C5AU, 0x0254B0U, 0x026564U, 0x027D8EU, - 0x028B0AU, 0x0293E0U, 0x02A234U, 0x02BADEU, 0x02C19CU, 0x02D976U, 0x02E8A2U, 0x02F048U, 0x0305AAU, 0x031D40U, - 0x032C94U, 0x03347EU, 0x034F3CU, 0x0357D6U, 0x036602U, 0x037EE8U, 0x03886CU, 0x039086U, 0x03A152U, 0x03B9B8U, - 0x03C2FAU, 0x03DA10U, 0x03EBC4U, 0x03F32EU, 0x040D98U, 0x041572U, 0x0424A6U, 0x043C4CU, 0x04470EU, 0x045FE4U, - 0x046E30U, 0x0476DAU, 0x04805EU, 0x0498B4U, 0x04A960U, 0x04B18AU, 0x04CAC8U, 0x04D222U, 0x04E3F6U, 0x04FB1CU, - 0x050EFEU, 0x051614U, 0x0527C0U, 0x053F2AU, 0x054468U, 0x055C82U, 0x056D56U, 0x0575BCU, 0x058338U, 0x059BD2U, - 0x05AA06U, 0x05B2ECU, 0x05C9AEU, 0x05D144U, 0x05E090U, 0x05F87AU, 0x060B54U, 0x0613BEU, 0x06226AU, 0x063A80U, - 0x0641C2U, 0x065928U, 0x0668FCU, 0x067016U, 0x068692U, 0x069E78U, 0x06AFACU, 0x06B746U, 0x06CC04U, 0x06D4EEU, - 0x06E53AU, 0x06FDD0U, 0x070832U, 0x0710D8U, 0x07210CU, 0x0739E6U, 0x0742A4U, 0x075A4EU, 0x076B9AU, 0x077370U, - 0x0785F4U, 0x079D1EU, 0x07ACCAU, 0x07B420U, 0x07CF62U, 0x07D788U, 0x07E65CU, 0x07FEB6U, 0x0803DAU, 0x081B30U, - 0x082AE4U, 0x08320EU, 0x08494CU, 0x0851A6U, 0x086072U, 0x087898U, 0x088E1CU, 0x0896F6U, 0x08A722U, 0x08BFC8U, - 0x08C48AU, 0x08DC60U, 0x08EDB4U, 0x08F55EU, 0x0900BCU, 0x091856U, 0x092982U, 0x093168U, 0x094A2AU, 0x0952C0U, - 0x096314U, 0x097BFEU, 0x098D7AU, 0x099590U, 0x09A444U, 0x09BCAEU, 0x09C7ECU, 0x09DF06U, 0x09EED2U, 0x09F638U, - 0x0A0516U, 0x0A1DFCU, 0x0A2C28U, 0x0A34C2U, 0x0A4F80U, 0x0A576AU, 0x0A66BEU, 0x0A7E54U, 0x0A88D0U, 0x0A903AU, - 0x0AA1EEU, 0x0AB904U, 0x0AC246U, 0x0ADAACU, 0x0AEB78U, 0x0AF392U, 0x0B0670U, 0x0B1E9AU, 0x0B2F4EU, 0x0B37A4U, - 0x0B4CE6U, 0x0B540CU, 0x0B65D8U, 0x0B7D32U, 0x0B8BB6U, 0x0B935CU, 0x0BA288U, 0x0BBA62U, 0x0BC120U, 0x0BD9CAU, - 0x0BE81EU, 0x0BF0F4U, 0x0C0E42U, 0x0C16A8U, 0x0C277CU, 0x0C3F96U, 0x0C44D4U, 0x0C5C3EU, 0x0C6DEAU, 0x0C7500U, - 0x0C8384U, 0x0C9B6EU, 0x0CAABAU, 0x0CB250U, 0x0CC912U, 0x0CD1F8U, 0x0CE02CU, 0x0CF8C6U, 0x0D0D24U, 0x0D15CEU, - 0x0D241AU, 0x0D3CF0U, 0x0D47B2U, 0x0D5F58U, 0x0D6E8CU, 0x0D7666U, 0x0D80E2U, 0x0D9808U, 0x0DA9DCU, 0x0DB136U, - 0x0DCA74U, 0x0DD29EU, 0x0DE34AU, 0x0DFBA0U, 0x0E088EU, 0x0E1064U, 0x0E21B0U, 0x0E395AU, 0x0E4218U, 0x0E5AF2U, - 0x0E6B26U, 0x0E73CCU, 0x0E8548U, 0x0E9DA2U, 0x0EAC76U, 0x0EB49CU, 0x0ECFDEU, 0x0ED734U, 0x0EE6E0U, 0x0EFE0AU, - 0x0F0BE8U, 0x0F1302U, 0x0F22D6U, 0x0F3A3CU, 0x0F417EU, 0x0F5994U, 0x0F6840U, 0x0F70AAU, 0x0F862EU, 0x0F9EC4U, - 0x0FAF10U, 0x0FB7FAU, 0x0FCCB8U, 0x0FD452U, 0x0FE586U, 0x0FFD6CU, 0x1007B4U, 0x101F5EU, 0x102E8AU, 0x103660U, - 0x104D22U, 0x1055C8U, 0x10641CU, 0x107CF6U, 0x108A72U, 0x109298U, 0x10A34CU, 0x10BBA6U, 0x10C0E4U, 0x10D80EU, - 0x10E9DAU, 0x10F130U, 0x1104D2U, 0x111C38U, 0x112DECU, 0x113506U, 0x114E44U, 0x1156AEU, 0x11677AU, 0x117F90U, - 0x118914U, 0x1191FEU, 0x11A02AU, 0x11B8C0U, 0x11C382U, 0x11DB68U, 0x11EABCU, 0x11F256U, 0x120178U, 0x121992U, - 0x122846U, 0x1230ACU, 0x124BEEU, 0x125304U, 0x1262D0U, 0x127A3AU, 0x128CBEU, 0x129454U, 0x12A580U, 0x12BD6AU, - 0x12C628U, 0x12DEC2U, 0x12EF16U, 0x12F7FCU, 0x13021EU, 0x131AF4U, 0x132B20U, 0x1333CAU, 0x134888U, 0x135062U, - 0x1361B6U, 0x13795CU, 0x138FD8U, 0x139732U, 0x13A6E6U, 0x13BE0CU, 0x13C54EU, 0x13DDA4U, 0x13EC70U, 0x13F49AU, - 0x140A2CU, 0x1412C6U, 0x142312U, 0x143BF8U, 0x1440BAU, 0x145850U, 0x146984U, 0x14716EU, 0x1487EAU, 0x149F00U, - 0x14AED4U, 0x14B63EU, 0x14CD7CU, 0x14D596U, 0x14E442U, 0x14FCA8U, 0x15094AU, 0x1511A0U, 0x152074U, 0x15389EU, - 0x1543DCU, 0x155B36U, 0x156AE2U, 0x157208U, 0x15848CU, 0x159C66U, 0x15ADB2U, 0x15B558U, 0x15CE1AU, 0x15D6F0U, - 0x15E724U, 0x15FFCEU, 0x160CE0U, 0x16140AU, 0x1625DEU, 0x163D34U, 0x164676U, 0x165E9CU, 0x166F48U, 0x1677A2U, - 0x168126U, 0x1699CCU, 0x16A818U, 0x16B0F2U, 0x16CBB0U, 0x16D35AU, 0x16E28EU, 0x16FA64U, 0x170F86U, 0x17176CU, - 0x1726B8U, 0x173E52U, 0x174510U, 0x175DFAU, 0x176C2EU, 0x1774C4U, 0x178240U, 0x179AAAU, 0x17AB7EU, 0x17B394U, - 0x17C8D6U, 0x17D03CU, 0x17E1E8U, 0x17F902U, 0x18046EU, 0x181C84U, 0x182D50U, 0x1835BAU, 0x184EF8U, 0x185612U, - 0x1867C6U, 0x187F2CU, 0x1889A8U, 0x189142U, 0x18A096U, 0x18B87CU, 0x18C33EU, 0x18DBD4U, 0x18EA00U, 0x18F2EAU, - 0x190708U, 0x191FE2U, 0x192E36U, 0x1936DCU, 0x194D9EU, 0x195574U, 0x1964A0U, 0x197C4AU, 0x198ACEU, 0x199224U, - 0x19A3F0U, 0x19BB1AU, 0x19C058U, 0x19D8B2U, 0x19E966U, 0x19F18CU, 0x1A02A2U, 0x1A1A48U, 0x1A2B9CU, 0x1A3376U, - 0x1A4834U, 0x1A50DEU, 0x1A610AU, 0x1A79E0U, 0x1A8F64U, 0x1A978EU, 0x1AA65AU, 0x1ABEB0U, 0x1AC5F2U, 0x1ADD18U, - 0x1AECCCU, 0x1AF426U, 0x1B01C4U, 0x1B192EU, 0x1B28FAU, 0x1B3010U, 0x1B4B52U, 0x1B53B8U, 0x1B626CU, 0x1B7A86U, - 0x1B8C02U, 0x1B94E8U, 0x1BA53CU, 0x1BBDD6U, 0x1BC694U, 0x1BDE7EU, 0x1BEFAAU, 0x1BF740U, 0x1C09F6U, 0x1C111CU, - 0x1C20C8U, 0x1C3822U, 0x1C4360U, 0x1C5B8AU, 0x1C6A5EU, 0x1C72B4U, 0x1C8430U, 0x1C9CDAU, 0x1CAD0EU, 0x1CB5E4U, - 0x1CCEA6U, 0x1CD64CU, 0x1CE798U, 0x1CFF72U, 0x1D0A90U, 0x1D127AU, 0x1D23AEU, 0x1D3B44U, 0x1D4006U, 0x1D58ECU, - 0x1D6938U, 0x1D71D2U, 0x1D8756U, 0x1D9FBCU, 0x1DAE68U, 0x1DB682U, 0x1DCDC0U, 0x1DD52AU, 0x1DE4FEU, 0x1DFC14U, - 0x1E0F3AU, 0x1E17D0U, 0x1E2604U, 0x1E3EEEU, 0x1E45ACU, 0x1E5D46U, 0x1E6C92U, 0x1E7478U, 0x1E82FCU, 0x1E9A16U, - 0x1EABC2U, 0x1EB328U, 0x1EC86AU, 0x1ED080U, 0x1EE154U, 0x1EF9BEU, 0x1F0C5CU, 0x1F14B6U, 0x1F2562U, 0x1F3D88U, - 0x1F46CAU, 0x1F5E20U, 0x1F6FF4U, 0x1F771EU, 0x1F819AU, 0x1F9970U, 0x1FA8A4U, 0x1FB04EU, 0x1FCB0CU, 0x1FD3E6U, - 0x1FE232U, 0x1FFAD8U, 0x200F68U, 0x201782U, 0x202656U, 0x203EBCU, 0x2045FEU, 0x205D14U, 0x206CC0U, 0x20742AU, - 0x2082AEU, 0x209A44U, 0x20AB90U, 0x20B37AU, 0x20C838U, 0x20D0D2U, 0x20E106U, 0x20F9ECU, 0x210C0EU, 0x2114E4U, - 0x212530U, 0x213DDAU, 0x214698U, 0x215E72U, 0x216FA6U, 0x21774CU, 0x2181C8U, 0x219922U, 0x21A8F6U, 0x21B01CU, - 0x21CB5EU, 0x21D3B4U, 0x21E260U, 0x21FA8AU, 0x2209A4U, 0x22114EU, 0x22209AU, 0x223870U, 0x224332U, 0x225BD8U, - 0x226A0CU, 0x2272E6U, 0x228462U, 0x229C88U, 0x22AD5CU, 0x22B5B6U, 0x22CEF4U, 0x22D61EU, 0x22E7CAU, 0x22FF20U, - 0x230AC2U, 0x231228U, 0x2323FCU, 0x233B16U, 0x234054U, 0x2358BEU, 0x23696AU, 0x237180U, 0x238704U, 0x239FEEU, - 0x23AE3AU, 0x23B6D0U, 0x23CD92U, 0x23D578U, 0x23E4ACU, 0x23FC46U, 0x2402F0U, 0x241A1AU, 0x242BCEU, 0x243324U, - 0x244866U, 0x24508CU, 0x246158U, 0x2479B2U, 0x248F36U, 0x2497DCU, 0x24A608U, 0x24BEE2U, 0x24C5A0U, 0x24DD4AU, - 0x24EC9EU, 0x24F474U, 0x250196U, 0x25197CU, 0x2528A8U, 0x253042U, 0x254B00U, 0x2553EAU, 0x25623EU, 0x257AD4U, - 0x258C50U, 0x2594BAU, 0x25A56EU, 0x25BD84U, 0x25C6C6U, 0x25DE2CU, 0x25EFF8U, 0x25F712U, 0x26043CU, 0x261CD6U, - 0x262D02U, 0x2635E8U, 0x264EAAU, 0x265640U, 0x266794U, 0x267F7EU, 0x2689FAU, 0x269110U, 0x26A0C4U, 0x26B82EU, - 0x26C36CU, 0x26DB86U, 0x26EA52U, 0x26F2B8U, 0x27075AU, 0x271FB0U, 0x272E64U, 0x27368EU, 0x274DCCU, 0x275526U, - 0x2764F2U, 0x277C18U, 0x278A9CU, 0x279276U, 0x27A3A2U, 0x27BB48U, 0x27C00AU, 0x27D8E0U, 0x27E934U, 0x27F1DEU, - 0x280CB2U, 0x281458U, 0x28258CU, 0x283D66U, 0x284624U, 0x285ECEU, 0x286F1AU, 0x2877F0U, 0x288174U, 0x28999EU, - 0x28A84AU, 0x28B0A0U, 0x28CBE2U, 0x28D308U, 0x28E2DCU, 0x28FA36U, 0x290FD4U, 0x29173EU, 0x2926EAU, 0x293E00U, - 0x294542U, 0x295DA8U, 0x296C7CU, 0x297496U, 0x298212U, 0x299AF8U, 0x29AB2CU, 0x29B3C6U, 0x29C884U, 0x29D06EU, - 0x29E1BAU, 0x29F950U, 0x2A0A7EU, 0x2A1294U, 0x2A2340U, 0x2A3BAAU, 0x2A40E8U, 0x2A5802U, 0x2A69D6U, 0x2A713CU, - 0x2A87B8U, 0x2A9F52U, 0x2AAE86U, 0x2AB66CU, 0x2ACD2EU, 0x2AD5C4U, 0x2AE410U, 0x2AFCFAU, 0x2B0918U, 0x2B11F2U, - 0x2B2026U, 0x2B38CCU, 0x2B438EU, 0x2B5B64U, 0x2B6AB0U, 0x2B725AU, 0x2B84DEU, 0x2B9C34U, 0x2BADE0U, 0x2BB50AU, - 0x2BCE48U, 0x2BD6A2U, 0x2BE776U, 0x2BFF9CU, 0x2C012AU, 0x2C19C0U, 0x2C2814U, 0x2C30FEU, 0x2C4BBCU, 0x2C5356U, - 0x2C6282U, 0x2C7A68U, 0x2C8CECU, 0x2C9406U, 0x2CA5D2U, 0x2CBD38U, 0x2CC67AU, 0x2CDE90U, 0x2CEF44U, 0x2CF7AEU, - 0x2D024CU, 0x2D1AA6U, 0x2D2B72U, 0x2D3398U, 0x2D48DAU, 0x2D5030U, 0x2D61E4U, 0x2D790EU, 0x2D8F8AU, 0x2D9760U, - 0x2DA6B4U, 0x2DBE5EU, 0x2DC51CU, 0x2DDDF6U, 0x2DEC22U, 0x2DF4C8U, 0x2E07E6U, 0x2E1F0CU, 0x2E2ED8U, 0x2E3632U, - 0x2E4D70U, 0x2E559AU, 0x2E644EU, 0x2E7CA4U, 0x2E8A20U, 0x2E92CAU, 0x2EA31EU, 0x2EBBF4U, 0x2EC0B6U, 0x2ED85CU, - 0x2EE988U, 0x2EF162U, 0x2F0480U, 0x2F1C6AU, 0x2F2DBEU, 0x2F3554U, 0x2F4E16U, 0x2F56FCU, 0x2F6728U, 0x2F7FC2U, - 0x2F8946U, 0x2F91ACU, 0x2FA078U, 0x2FB892U, 0x2FC3D0U, 0x2FDB3AU, 0x2FEAEEU, 0x2FF204U, 0x3008DCU, 0x301036U, - 0x3021E2U, 0x303908U, 0x30424AU, 0x305AA0U, 0x306B74U, 0x30739EU, 0x30851AU, 0x309DF0U, 0x30AC24U, 0x30B4CEU, - 0x30CF8CU, 0x30D766U, 0x30E6B2U, 0x30FE58U, 0x310BBAU, 0x311350U, 0x312284U, 0x313A6EU, 0x31412CU, 0x3159C6U, - 0x316812U, 0x3170F8U, 0x31867CU, 0x319E96U, 0x31AF42U, 0x31B7A8U, 0x31CCEAU, 0x31D400U, 0x31E5D4U, 0x31FD3EU, - 0x320E10U, 0x3216FAU, 0x32272EU, 0x323FC4U, 0x324486U, 0x325C6CU, 0x326DB8U, 0x327552U, 0x3283D6U, 0x329B3CU, - 0x32AAE8U, 0x32B202U, 0x32C940U, 0x32D1AAU, 0x32E07EU, 0x32F894U, 0x330D76U, 0x33159CU, 0x332448U, 0x333CA2U, - 0x3347E0U, 0x335F0AU, 0x336EDEU, 0x337634U, 0x3380B0U, 0x33985AU, 0x33A98EU, 0x33B164U, 0x33CA26U, 0x33D2CCU, - 0x33E318U, 0x33FBF2U, 0x340544U, 0x341DAEU, 0x342C7AU, 0x343490U, 0x344FD2U, 0x345738U, 0x3466ECU, 0x347E06U, - 0x348882U, 0x349068U, 0x34A1BCU, 0x34B956U, 0x34C214U, 0x34DAFEU, 0x34EB2AU, 0x34F3C0U, 0x350622U, 0x351EC8U, - 0x352F1CU, 0x3537F6U, 0x354CB4U, 0x35545EU, 0x35658AU, 0x357D60U, 0x358BE4U, 0x35930EU, 0x35A2DAU, 0x35BA30U, - 0x35C172U, 0x35D998U, 0x35E84CU, 0x35F0A6U, 0x360388U, 0x361B62U, 0x362AB6U, 0x36325CU, 0x36491EU, 0x3651F4U, - 0x366020U, 0x3678CAU, 0x368E4EU, 0x3696A4U, 0x36A770U, 0x36BF9AU, 0x36C4D8U, 0x36DC32U, 0x36EDE6U, 0x36F50CU, - 0x3700EEU, 0x371804U, 0x3729D0U, 0x37313AU, 0x374A78U, 0x375292U, 0x376346U, 0x377BACU, 0x378D28U, 0x3795C2U, - 0x37A416U, 0x37BCFCU, 0x37C7BEU, 0x37DF54U, 0x37EE80U, 0x37F66AU, 0x380B06U, 0x3813ECU, 0x382238U, 0x383AD2U, - 0x384190U, 0x38597AU, 0x3868AEU, 0x387044U, 0x3886C0U, 0x389E2AU, 0x38AFFEU, 0x38B714U, 0x38CC56U, 0x38D4BCU, - 0x38E568U, 0x38FD82U, 0x390860U, 0x39108AU, 0x39215EU, 0x3939B4U, 0x3942F6U, 0x395A1CU, 0x396BC8U, 0x397322U, - 0x3985A6U, 0x399D4CU, 0x39AC98U, 0x39B472U, 0x39CF30U, 0x39D7DAU, 0x39E60EU, 0x39FEE4U, 0x3A0DCAU, 0x3A1520U, - 0x3A24F4U, 0x3A3C1EU, 0x3A475CU, 0x3A5FB6U, 0x3A6E62U, 0x3A7688U, 0x3A800CU, 0x3A98E6U, 0x3AA932U, 0x3AB1D8U, - 0x3ACA9AU, 0x3AD270U, 0x3AE3A4U, 0x3AFB4EU, 0x3B0EACU, 0x3B1646U, 0x3B2792U, 0x3B3F78U, 0x3B443AU, 0x3B5CD0U, - 0x3B6D04U, 0x3B75EEU, 0x3B836AU, 0x3B9B80U, 0x3BAA54U, 0x3BB2BEU, 0x3BC9FCU, 0x3BD116U, 0x3BE0C2U, 0x3BF828U, - 0x3C069EU, 0x3C1E74U, 0x3C2FA0U, 0x3C374AU, 0x3C4C08U, 0x3C54E2U, 0x3C6536U, 0x3C7DDCU, 0x3C8B58U, 0x3C93B2U, - 0x3CA266U, 0x3CBA8CU, 0x3CC1CEU, 0x3CD924U, 0x3CE8F0U, 0x3CF01AU, 0x3D05F8U, 0x3D1D12U, 0x3D2CC6U, 0x3D342CU, - 0x3D4F6EU, 0x3D5784U, 0x3D6650U, 0x3D7EBAU, 0x3D883EU, 0x3D90D4U, 0x3DA100U, 0x3DB9EAU, 0x3DC2A8U, 0x3DDA42U, - 0x3DEB96U, 0x3DF37CU, 0x3E0052U, 0x3E18B8U, 0x3E296CU, 0x3E3186U, 0x3E4AC4U, 0x3E522EU, 0x3E63FAU, 0x3E7B10U, - 0x3E8D94U, 0x3E957EU, 0x3EA4AAU, 0x3EBC40U, 0x3EC702U, 0x3EDFE8U, 0x3EEE3CU, 0x3EF6D6U, 0x3F0334U, 0x3F1BDEU, - 0x3F2A0AU, 0x3F32E0U, 0x3F49A2U, 0x3F5148U, 0x3F609CU, 0x3F7876U, 0x3F8EF2U, 0x3F9618U, 0x3FA7CCU, 0x3FBF26U, - 0x3FC464U, 0x3FDC8EU, 0x3FED5AU, 0x3FF5B0U, 0x40063AU, 0x401ED0U, 0x402F04U, 0x4037EEU, 0x404CACU, 0x405446U, - 0x406592U, 0x407D78U, 0x408BFCU, 0x409316U, 0x40A2C2U, 0x40BA28U, 0x40C16AU, 0x40D980U, 0x40E854U, 0x40F0BEU, - 0x41055CU, 0x411DB6U, 0x412C62U, 0x413488U, 0x414FCAU, 0x415720U, 0x4166F4U, 0x417E1EU, 0x41889AU, 0x419070U, - 0x41A1A4U, 0x41B94EU, 0x41C20CU, 0x41DAE6U, 0x41EB32U, 0x41F3D8U, 0x4200F6U, 0x42181CU, 0x4229C8U, 0x423122U, - 0x424A60U, 0x42528AU, 0x42635EU, 0x427BB4U, 0x428D30U, 0x4295DAU, 0x42A40EU, 0x42BCE4U, 0x42C7A6U, 0x42DF4CU, - 0x42EE98U, 0x42F672U, 0x430390U, 0x431B7AU, 0x432AAEU, 0x433244U, 0x434906U, 0x4351ECU, 0x436038U, 0x4378D2U, - 0x438E56U, 0x4396BCU, 0x43A768U, 0x43BF82U, 0x43C4C0U, 0x43DC2AU, 0x43EDFEU, 0x43F514U, 0x440BA2U, 0x441348U, - 0x44229CU, 0x443A76U, 0x444134U, 0x4459DEU, 0x44680AU, 0x4470E0U, 0x448664U, 0x449E8EU, 0x44AF5AU, 0x44B7B0U, - 0x44CCF2U, 0x44D418U, 0x44E5CCU, 0x44FD26U, 0x4508C4U, 0x45102EU, 0x4521FAU, 0x453910U, 0x454252U, 0x455AB8U, - 0x456B6CU, 0x457386U, 0x458502U, 0x459DE8U, 0x45AC3CU, 0x45B4D6U, 0x45CF94U, 0x45D77EU, 0x45E6AAU, 0x45FE40U, - 0x460D6EU, 0x461584U, 0x462450U, 0x463CBAU, 0x4647F8U, 0x465F12U, 0x466EC6U, 0x46762CU, 0x4680A8U, 0x469842U, - 0x46A996U, 0x46B17CU, 0x46CA3EU, 0x46D2D4U, 0x46E300U, 0x46FBEAU, 0x470E08U, 0x4716E2U, 0x472736U, 0x473FDCU, - 0x47449EU, 0x475C74U, 0x476DA0U, 0x47754AU, 0x4783CEU, 0x479B24U, 0x47AAF0U, 0x47B21AU, 0x47C958U, 0x47D1B2U, - 0x47E066U, 0x47F88CU, 0x4805E0U, 0x481D0AU, 0x482CDEU, 0x483434U, 0x484F76U, 0x48579CU, 0x486648U, 0x487EA2U, - 0x488826U, 0x4890CCU, 0x48A118U, 0x48B9F2U, 0x48C2B0U, 0x48DA5AU, 0x48EB8EU, 0x48F364U, 0x490686U, 0x491E6CU, - 0x492FB8U, 0x493752U, 0x494C10U, 0x4954FAU, 0x49652EU, 0x497DC4U, 0x498B40U, 0x4993AAU, 0x49A27EU, 0x49BA94U, - 0x49C1D6U, 0x49D93CU, 0x49E8E8U, 0x49F002U, 0x4A032CU, 0x4A1BC6U, 0x4A2A12U, 0x4A32F8U, 0x4A49BAU, 0x4A5150U, - 0x4A6084U, 0x4A786EU, 0x4A8EEAU, 0x4A9600U, 0x4AA7D4U, 0x4ABF3EU, 0x4AC47CU, 0x4ADC96U, 0x4AED42U, 0x4AF5A8U, - 0x4B004AU, 0x4B18A0U, 0x4B2974U, 0x4B319EU, 0x4B4ADCU, 0x4B5236U, 0x4B63E2U, 0x4B7B08U, 0x4B8D8CU, 0x4B9566U, - 0x4BA4B2U, 0x4BBC58U, 0x4BC71AU, 0x4BDFF0U, 0x4BEE24U, 0x4BF6CEU, 0x4C0878U, 0x4C1092U, 0x4C2146U, 0x4C39ACU, - 0x4C42EEU, 0x4C5A04U, 0x4C6BD0U, 0x4C733AU, 0x4C85BEU, 0x4C9D54U, 0x4CAC80U, 0x4CB46AU, 0x4CCF28U, 0x4CD7C2U, - 0x4CE616U, 0x4CFEFCU, 0x4D0B1EU, 0x4D13F4U, 0x4D2220U, 0x4D3ACAU, 0x4D4188U, 0x4D5962U, 0x4D68B6U, 0x4D705CU, - 0x4D86D8U, 0x4D9E32U, 0x4DAFE6U, 0x4DB70CU, 0x4DCC4EU, 0x4DD4A4U, 0x4DE570U, 0x4DFD9AU, 0x4E0EB4U, 0x4E165EU, - 0x4E278AU, 0x4E3F60U, 0x4E4422U, 0x4E5CC8U, 0x4E6D1CU, 0x4E75F6U, 0x4E8372U, 0x4E9B98U, 0x4EAA4CU, 0x4EB2A6U, - 0x4EC9E4U, 0x4ED10EU, 0x4EE0DAU, 0x4EF830U, 0x4F0DD2U, 0x4F1538U, 0x4F24ECU, 0x4F3C06U, 0x4F4744U, 0x4F5FAEU, - 0x4F6E7AU, 0x4F7690U, 0x4F8014U, 0x4F98FEU, 0x4FA92AU, 0x4FB1C0U, 0x4FCA82U, 0x4FD268U, 0x4FE3BCU, 0x4FFB56U, - 0x50018EU, 0x501964U, 0x5028B0U, 0x50305AU, 0x504B18U, 0x5053F2U, 0x506226U, 0x507ACCU, 0x508C48U, 0x5094A2U, - 0x50A576U, 0x50BD9CU, 0x50C6DEU, 0x50DE34U, 0x50EFE0U, 0x50F70AU, 0x5102E8U, 0x511A02U, 0x512BD6U, 0x51333CU, - 0x51487EU, 0x515094U, 0x516140U, 0x5179AAU, 0x518F2EU, 0x5197C4U, 0x51A610U, 0x51BEFAU, 0x51C5B8U, 0x51DD52U, - 0x51EC86U, 0x51F46CU, 0x520742U, 0x521FA8U, 0x522E7CU, 0x523696U, 0x524DD4U, 0x52553EU, 0x5264EAU, 0x527C00U, - 0x528A84U, 0x52926EU, 0x52A3BAU, 0x52BB50U, 0x52C012U, 0x52D8F8U, 0x52E92CU, 0x52F1C6U, 0x530424U, 0x531CCEU, - 0x532D1AU, 0x5335F0U, 0x534EB2U, 0x535658U, 0x53678CU, 0x537F66U, 0x5389E2U, 0x539108U, 0x53A0DCU, 0x53B836U, - 0x53C374U, 0x53DB9EU, 0x53EA4AU, 0x53F2A0U, 0x540C16U, 0x5414FCU, 0x542528U, 0x543DC2U, 0x544680U, 0x545E6AU, - 0x546FBEU, 0x547754U, 0x5481D0U, 0x54993AU, 0x54A8EEU, 0x54B004U, 0x54CB46U, 0x54D3ACU, 0x54E278U, 0x54FA92U, - 0x550F70U, 0x55179AU, 0x55264EU, 0x553EA4U, 0x5545E6U, 0x555D0CU, 0x556CD8U, 0x557432U, 0x5582B6U, 0x559A5CU, - 0x55AB88U, 0x55B362U, 0x55C820U, 0x55D0CAU, 0x55E11EU, 0x55F9F4U, 0x560ADAU, 0x561230U, 0x5623E4U, 0x563B0EU, - 0x56404CU, 0x5658A6U, 0x566972U, 0x567198U, 0x56871CU, 0x569FF6U, 0x56AE22U, 0x56B6C8U, 0x56CD8AU, 0x56D560U, - 0x56E4B4U, 0x56FC5EU, 0x5709BCU, 0x571156U, 0x572082U, 0x573868U, 0x57432AU, 0x575BC0U, 0x576A14U, 0x5772FEU, - 0x57847AU, 0x579C90U, 0x57AD44U, 0x57B5AEU, 0x57CEECU, 0x57D606U, 0x57E7D2U, 0x57FF38U, 0x580254U, 0x581ABEU, - 0x582B6AU, 0x583380U, 0x5848C2U, 0x585028U, 0x5861FCU, 0x587916U, 0x588F92U, 0x589778U, 0x58A6ACU, 0x58BE46U, - 0x58C504U, 0x58DDEEU, 0x58EC3AU, 0x58F4D0U, 0x590132U, 0x5919D8U, 0x59280CU, 0x5930E6U, 0x594BA4U, 0x59534EU, - 0x59629AU, 0x597A70U, 0x598CF4U, 0x59941EU, 0x59A5CAU, 0x59BD20U, 0x59C662U, 0x59DE88U, 0x59EF5CU, 0x59F7B6U, - 0x5A0498U, 0x5A1C72U, 0x5A2DA6U, 0x5A354CU, 0x5A4E0EU, 0x5A56E4U, 0x5A6730U, 0x5A7FDAU, 0x5A895EU, 0x5A91B4U, - 0x5AA060U, 0x5AB88AU, 0x5AC3C8U, 0x5ADB22U, 0x5AEAF6U, 0x5AF21CU, 0x5B07FEU, 0x5B1F14U, 0x5B2EC0U, 0x5B362AU, - 0x5B4D68U, 0x5B5582U, 0x5B6456U, 0x5B7CBCU, 0x5B8A38U, 0x5B92D2U, 0x5BA306U, 0x5BBBECU, 0x5BC0AEU, 0x5BD844U, - 0x5BE990U, 0x5BF17AU, 0x5C0FCCU, 0x5C1726U, 0x5C26F2U, 0x5C3E18U, 0x5C455AU, 0x5C5DB0U, 0x5C6C64U, 0x5C748EU, - 0x5C820AU, 0x5C9AE0U, 0x5CAB34U, 0x5CB3DEU, 0x5CC89CU, 0x5CD076U, 0x5CE1A2U, 0x5CF948U, 0x5D0CAAU, 0x5D1440U, - 0x5D2594U, 0x5D3D7EU, 0x5D463CU, 0x5D5ED6U, 0x5D6F02U, 0x5D77E8U, 0x5D816CU, 0x5D9986U, 0x5DA852U, 0x5DB0B8U, - 0x5DCBFAU, 0x5DD310U, 0x5DE2C4U, 0x5DFA2EU, 0x5E0900U, 0x5E11EAU, 0x5E203EU, 0x5E38D4U, 0x5E4396U, 0x5E5B7CU, - 0x5E6AA8U, 0x5E7242U, 0x5E84C6U, 0x5E9C2CU, 0x5EADF8U, 0x5EB512U, 0x5ECE50U, 0x5ED6BAU, 0x5EE76EU, 0x5EFF84U, - 0x5F0A66U, 0x5F128CU, 0x5F2358U, 0x5F3BB2U, 0x5F40F0U, 0x5F581AU, 0x5F69CEU, 0x5F7124U, 0x5F87A0U, 0x5F9F4AU, - 0x5FAE9EU, 0x5FB674U, 0x5FCD36U, 0x5FD5DCU, 0x5FE408U, 0x5FFCE2U, 0x600952U, 0x6011B8U, 0x60206CU, 0x603886U, - 0x6043C4U, 0x605B2EU, 0x606AFAU, 0x607210U, 0x608494U, 0x609C7EU, 0x60ADAAU, 0x60B540U, 0x60CE02U, 0x60D6E8U, - 0x60E73CU, 0x60FFD6U, 0x610A34U, 0x6112DEU, 0x61230AU, 0x613BE0U, 0x6140A2U, 0x615848U, 0x61699CU, 0x617176U, - 0x6187F2U, 0x619F18U, 0x61AECCU, 0x61B626U, 0x61CD64U, 0x61D58EU, 0x61E45AU, 0x61FCB0U, 0x620F9EU, 0x621774U, - 0x6226A0U, 0x623E4AU, 0x624508U, 0x625DE2U, 0x626C36U, 0x6274DCU, 0x628258U, 0x629AB2U, 0x62AB66U, 0x62B38CU, - 0x62C8CEU, 0x62D024U, 0x62E1F0U, 0x62F91AU, 0x630CF8U, 0x631412U, 0x6325C6U, 0x633D2CU, 0x63466EU, 0x635E84U, - 0x636F50U, 0x6377BAU, 0x63813EU, 0x6399D4U, 0x63A800U, 0x63B0EAU, 0x63CBA8U, 0x63D342U, 0x63E296U, 0x63FA7CU, - 0x6404CAU, 0x641C20U, 0x642DF4U, 0x64351EU, 0x644E5CU, 0x6456B6U, 0x646762U, 0x647F88U, 0x64890CU, 0x6491E6U, - 0x64A032U, 0x64B8D8U, 0x64C39AU, 0x64DB70U, 0x64EAA4U, 0x64F24EU, 0x6507ACU, 0x651F46U, 0x652E92U, 0x653678U, - 0x654D3AU, 0x6555D0U, 0x656404U, 0x657CEEU, 0x658A6AU, 0x659280U, 0x65A354U, 0x65BBBEU, 0x65C0FCU, 0x65D816U, - 0x65E9C2U, 0x65F128U, 0x660206U, 0x661AECU, 0x662B38U, 0x6633D2U, 0x664890U, 0x66507AU, 0x6661AEU, 0x667944U, - 0x668FC0U, 0x66972AU, 0x66A6FEU, 0x66BE14U, 0x66C556U, 0x66DDBCU, 0x66EC68U, 0x66F482U, 0x670160U, 0x67198AU, - 0x67285EU, 0x6730B4U, 0x674BF6U, 0x67531CU, 0x6762C8U, 0x677A22U, 0x678CA6U, 0x67944CU, 0x67A598U, 0x67BD72U, - 0x67C630U, 0x67DEDAU, 0x67EF0EU, 0x67F7E4U, 0x680A88U, 0x681262U, 0x6823B6U, 0x683B5CU, 0x68401EU, 0x6858F4U, - 0x686920U, 0x6871CAU, 0x68874EU, 0x689FA4U, 0x68AE70U, 0x68B69AU, 0x68CDD8U, 0x68D532U, 0x68E4E6U, 0x68FC0CU, - 0x6909EEU, 0x691104U, 0x6920D0U, 0x69383AU, 0x694378U, 0x695B92U, 0x696A46U, 0x6972ACU, 0x698428U, 0x699CC2U, - 0x69AD16U, 0x69B5FCU, 0x69CEBEU, 0x69D654U, 0x69E780U, 0x69FF6AU, 0x6A0C44U, 0x6A14AEU, 0x6A257AU, 0x6A3D90U, - 0x6A46D2U, 0x6A5E38U, 0x6A6FECU, 0x6A7706U, 0x6A8182U, 0x6A9968U, 0x6AA8BCU, 0x6AB056U, 0x6ACB14U, 0x6AD3FEU, - 0x6AE22AU, 0x6AFAC0U, 0x6B0F22U, 0x6B17C8U, 0x6B261CU, 0x6B3EF6U, 0x6B45B4U, 0x6B5D5EU, 0x6B6C8AU, 0x6B7460U, - 0x6B82E4U, 0x6B9A0EU, 0x6BABDAU, 0x6BB330U, 0x6BC872U, 0x6BD098U, 0x6BE14CU, 0x6BF9A6U, 0x6C0710U, 0x6C1FFAU, - 0x6C2E2EU, 0x6C36C4U, 0x6C4D86U, 0x6C556CU, 0x6C64B8U, 0x6C7C52U, 0x6C8AD6U, 0x6C923CU, 0x6CA3E8U, 0x6CBB02U, - 0x6CC040U, 0x6CD8AAU, 0x6CE97EU, 0x6CF194U, 0x6D0476U, 0x6D1C9CU, 0x6D2D48U, 0x6D35A2U, 0x6D4EE0U, 0x6D560AU, - 0x6D67DEU, 0x6D7F34U, 0x6D89B0U, 0x6D915AU, 0x6DA08EU, 0x6DB864U, 0x6DC326U, 0x6DDBCCU, 0x6DEA18U, 0x6DF2F2U, - 0x6E01DCU, 0x6E1936U, 0x6E28E2U, 0x6E3008U, 0x6E4B4AU, 0x6E53A0U, 0x6E6274U, 0x6E7A9EU, 0x6E8C1AU, 0x6E94F0U, - 0x6EA524U, 0x6EBDCEU, 0x6EC68CU, 0x6EDE66U, 0x6EEFB2U, 0x6EF758U, 0x6F02BAU, 0x6F1A50U, 0x6F2B84U, 0x6F336EU, - 0x6F482CU, 0x6F50C6U, 0x6F6112U, 0x6F79F8U, 0x6F8F7CU, 0x6F9796U, 0x6FA642U, 0x6FBEA8U, 0x6FC5EAU, 0x6FDD00U, - 0x6FECD4U, 0x6FF43EU, 0x700EE6U, 0x70160CU, 0x7027D8U, 0x703F32U, 0x704470U, 0x705C9AU, 0x706D4EU, 0x7075A4U, - 0x708320U, 0x709BCAU, 0x70AA1EU, 0x70B2F4U, 0x70C9B6U, 0x70D15CU, 0x70E088U, 0x70F862U, 0x710D80U, 0x71156AU, - 0x7124BEU, 0x713C54U, 0x714716U, 0x715FFCU, 0x716E28U, 0x7176C2U, 0x718046U, 0x7198ACU, 0x71A978U, 0x71B192U, - 0x71CAD0U, 0x71D23AU, 0x71E3EEU, 0x71FB04U, 0x72082AU, 0x7210C0U, 0x722114U, 0x7239FEU, 0x7242BCU, 0x725A56U, - 0x726B82U, 0x727368U, 0x7285ECU, 0x729D06U, 0x72ACD2U, 0x72B438U, 0x72CF7AU, 0x72D790U, 0x72E644U, 0x72FEAEU, - 0x730B4CU, 0x7313A6U, 0x732272U, 0x733A98U, 0x7341DAU, 0x735930U, 0x7368E4U, 0x73700EU, 0x73868AU, 0x739E60U, - 0x73AFB4U, 0x73B75EU, 0x73CC1CU, 0x73D4F6U, 0x73E522U, 0x73FDC8U, 0x74037EU, 0x741B94U, 0x742A40U, 0x7432AAU, - 0x7449E8U, 0x745102U, 0x7460D6U, 0x74783CU, 0x748EB8U, 0x749652U, 0x74A786U, 0x74BF6CU, 0x74C42EU, 0x74DCC4U, - 0x74ED10U, 0x74F5FAU, 0x750018U, 0x7518F2U, 0x752926U, 0x7531CCU, 0x754A8EU, 0x755264U, 0x7563B0U, 0x757B5AU, - 0x758DDEU, 0x759534U, 0x75A4E0U, 0x75BC0AU, 0x75C748U, 0x75DFA2U, 0x75EE76U, 0x75F69CU, 0x7605B2U, 0x761D58U, - 0x762C8CU, 0x763466U, 0x764F24U, 0x7657CEU, 0x76661AU, 0x767EF0U, 0x768874U, 0x76909EU, 0x76A14AU, 0x76B9A0U, - 0x76C2E2U, 0x76DA08U, 0x76EBDCU, 0x76F336U, 0x7706D4U, 0x771E3EU, 0x772FEAU, 0x773700U, 0x774C42U, 0x7754A8U, - 0x77657CU, 0x777D96U, 0x778B12U, 0x7793F8U, 0x77A22CU, 0x77BAC6U, 0x77C184U, 0x77D96EU, 0x77E8BAU, 0x77F050U, - 0x780D3CU, 0x7815D6U, 0x782402U, 0x783CE8U, 0x7847AAU, 0x785F40U, 0x786E94U, 0x78767EU, 0x7880FAU, 0x789810U, - 0x78A9C4U, 0x78B12EU, 0x78CA6CU, 0x78D286U, 0x78E352U, 0x78FBB8U, 0x790E5AU, 0x7916B0U, 0x792764U, 0x793F8EU, - 0x7944CCU, 0x795C26U, 0x796DF2U, 0x797518U, 0x79839CU, 0x799B76U, 0x79AAA2U, 0x79B248U, 0x79C90AU, 0x79D1E0U, - 0x79E034U, 0x79F8DEU, 0x7A0BF0U, 0x7A131AU, 0x7A22CEU, 0x7A3A24U, 0x7A4166U, 0x7A598CU, 0x7A6858U, 0x7A70B2U, - 0x7A8636U, 0x7A9EDCU, 0x7AAF08U, 0x7AB7E2U, 0x7ACCA0U, 0x7AD44AU, 0x7AE59EU, 0x7AFD74U, 0x7B0896U, 0x7B107CU, - 0x7B21A8U, 0x7B3942U, 0x7B4200U, 0x7B5AEAU, 0x7B6B3EU, 0x7B73D4U, 0x7B8550U, 0x7B9DBAU, 0x7BAC6EU, 0x7BB484U, - 0x7BCFC6U, 0x7BD72CU, 0x7BE6F8U, 0x7BFE12U, 0x7C00A4U, 0x7C184EU, 0x7C299AU, 0x7C3170U, 0x7C4A32U, 0x7C52D8U, - 0x7C630CU, 0x7C7BE6U, 0x7C8D62U, 0x7C9588U, 0x7CA45CU, 0x7CBCB6U, 0x7CC7F4U, 0x7CDF1EU, 0x7CEECAU, 0x7CF620U, - 0x7D03C2U, 0x7D1B28U, 0x7D2AFCU, 0x7D3216U, 0x7D4954U, 0x7D51BEU, 0x7D606AU, 0x7D7880U, 0x7D8E04U, 0x7D96EEU, - 0x7DA73AU, 0x7DBFD0U, 0x7DC492U, 0x7DDC78U, 0x7DEDACU, 0x7DF546U, 0x7E0668U, 0x7E1E82U, 0x7E2F56U, 0x7E37BCU, - 0x7E4CFEU, 0x7E5414U, 0x7E65C0U, 0x7E7D2AU, 0x7E8BAEU, 0x7E9344U, 0x7EA290U, 0x7EBA7AU, 0x7EC138U, 0x7ED9D2U, - 0x7EE806U, 0x7EF0ECU, 0x7F050EU, 0x7F1DE4U, 0x7F2C30U, 0x7F34DAU, 0x7F4F98U, 0x7F5772U, 0x7F66A6U, 0x7F7E4CU, - 0x7F88C8U, 0x7F9022U, 0x7FA1F6U, 0x7FB91CU, 0x7FC25EU, 0x7FDAB4U, 0x7FEB60U, 0x7FF38AU, 0x800C74U, 0x80149EU, - 0x80254AU, 0x803DA0U, 0x8046E2U, 0x805E08U, 0x806FDCU, 0x807736U, 0x8081B2U, 0x809958U, 0x80A88CU, 0x80B066U, - 0x80CB24U, 0x80D3CEU, 0x80E21AU, 0x80FAF0U, 0x810F12U, 0x8117F8U, 0x81262CU, 0x813EC6U, 0x814584U, 0x815D6EU, - 0x816CBAU, 0x817450U, 0x8182D4U, 0x819A3EU, 0x81ABEAU, 0x81B300U, 0x81C842U, 0x81D0A8U, 0x81E17CU, 0x81F996U, - 0x820AB8U, 0x821252U, 0x822386U, 0x823B6CU, 0x82402EU, 0x8258C4U, 0x826910U, 0x8271FAU, 0x82877EU, 0x829F94U, - 0x82AE40U, 0x82B6AAU, 0x82CDE8U, 0x82D502U, 0x82E4D6U, 0x82FC3CU, 0x8309DEU, 0x831134U, 0x8320E0U, 0x83380AU, - 0x834348U, 0x835BA2U, 0x836A76U, 0x83729CU, 0x838418U, 0x839CF2U, 0x83AD26U, 0x83B5CCU, 0x83CE8EU, 0x83D664U, - 0x83E7B0U, 0x83FF5AU, 0x8401ECU, 0x841906U, 0x8428D2U, 0x843038U, 0x844B7AU, 0x845390U, 0x846244U, 0x847AAEU, - 0x848C2AU, 0x8494C0U, 0x84A514U, 0x84BDFEU, 0x84C6BCU, 0x84DE56U, 0x84EF82U, 0x84F768U, 0x85028AU, 0x851A60U, - 0x852BB4U, 0x85335EU, 0x85481CU, 0x8550F6U, 0x856122U, 0x8579C8U, 0x858F4CU, 0x8597A6U, 0x85A672U, 0x85BE98U, - 0x85C5DAU, 0x85DD30U, 0x85ECE4U, 0x85F40EU, 0x860720U, 0x861FCAU, 0x862E1EU, 0x8636F4U, 0x864DB6U, 0x86555CU, - 0x866488U, 0x867C62U, 0x868AE6U, 0x86920CU, 0x86A3D8U, 0x86BB32U, 0x86C070U, 0x86D89AU, 0x86E94EU, 0x86F1A4U, - 0x870446U, 0x871CACU, 0x872D78U, 0x873592U, 0x874ED0U, 0x87563AU, 0x8767EEU, 0x877F04U, 0x878980U, 0x87916AU, - 0x87A0BEU, 0x87B854U, 0x87C316U, 0x87DBFCU, 0x87EA28U, 0x87F2C2U, 0x880FAEU, 0x881744U, 0x882690U, 0x883E7AU, - 0x884538U, 0x885DD2U, 0x886C06U, 0x8874ECU, 0x888268U, 0x889A82U, 0x88AB56U, 0x88B3BCU, 0x88C8FEU, 0x88D014U, - 0x88E1C0U, 0x88F92AU, 0x890CC8U, 0x891422U, 0x8925F6U, 0x893D1CU, 0x89465EU, 0x895EB4U, 0x896F60U, 0x89778AU, - 0x89810EU, 0x8999E4U, 0x89A830U, 0x89B0DAU, 0x89CB98U, 0x89D372U, 0x89E2A6U, 0x89FA4CU, 0x8A0962U, 0x8A1188U, - 0x8A205CU, 0x8A38B6U, 0x8A43F4U, 0x8A5B1EU, 0x8A6ACAU, 0x8A7220U, 0x8A84A4U, 0x8A9C4EU, 0x8AAD9AU, 0x8AB570U, - 0x8ACE32U, 0x8AD6D8U, 0x8AE70CU, 0x8AFFE6U, 0x8B0A04U, 0x8B12EEU, 0x8B233AU, 0x8B3BD0U, 0x8B4092U, 0x8B5878U, - 0x8B69ACU, 0x8B7146U, 0x8B87C2U, 0x8B9F28U, 0x8BAEFCU, 0x8BB616U, 0x8BCD54U, 0x8BD5BEU, 0x8BE46AU, 0x8BFC80U, - 0x8C0236U, 0x8C1ADCU, 0x8C2B08U, 0x8C33E2U, 0x8C48A0U, 0x8C504AU, 0x8C619EU, 0x8C7974U, 0x8C8FF0U, 0x8C971AU, - 0x8CA6CEU, 0x8CBE24U, 0x8CC566U, 0x8CDD8CU, 0x8CEC58U, 0x8CF4B2U, 0x8D0150U, 0x8D19BAU, 0x8D286EU, 0x8D3084U, - 0x8D4BC6U, 0x8D532CU, 0x8D62F8U, 0x8D7A12U, 0x8D8C96U, 0x8D947CU, 0x8DA5A8U, 0x8DBD42U, 0x8DC600U, 0x8DDEEAU, - 0x8DEF3EU, 0x8DF7D4U, 0x8E04FAU, 0x8E1C10U, 0x8E2DC4U, 0x8E352EU, 0x8E4E6CU, 0x8E5686U, 0x8E6752U, 0x8E7FB8U, - 0x8E893CU, 0x8E91D6U, 0x8EA002U, 0x8EB8E8U, 0x8EC3AAU, 0x8EDB40U, 0x8EEA94U, 0x8EF27EU, 0x8F079CU, 0x8F1F76U, - 0x8F2EA2U, 0x8F3648U, 0x8F4D0AU, 0x8F55E0U, 0x8F6434U, 0x8F7CDEU, 0x8F8A5AU, 0x8F92B0U, 0x8FA364U, 0x8FBB8EU, - 0x8FC0CCU, 0x8FD826U, 0x8FE9F2U, 0x8FF118U, 0x900BC0U, 0x90132AU, 0x9022FEU, 0x903A14U, 0x904156U, 0x9059BCU, - 0x906868U, 0x907082U, 0x908606U, 0x909EECU, 0x90AF38U, 0x90B7D2U, 0x90CC90U, 0x90D47AU, 0x90E5AEU, 0x90FD44U, - 0x9108A6U, 0x91104CU, 0x912198U, 0x913972U, 0x914230U, 0x915ADAU, 0x916B0EU, 0x9173E4U, 0x918560U, 0x919D8AU, - 0x91AC5EU, 0x91B4B4U, 0x91CFF6U, 0x91D71CU, 0x91E6C8U, 0x91FE22U, 0x920D0CU, 0x9215E6U, 0x922432U, 0x923CD8U, - 0x92479AU, 0x925F70U, 0x926EA4U, 0x92764EU, 0x9280CAU, 0x929820U, 0x92A9F4U, 0x92B11EU, 0x92CA5CU, 0x92D2B6U, - 0x92E362U, 0x92FB88U, 0x930E6AU, 0x931680U, 0x932754U, 0x933FBEU, 0x9344FCU, 0x935C16U, 0x936DC2U, 0x937528U, - 0x9383ACU, 0x939B46U, 0x93AA92U, 0x93B278U, 0x93C93AU, 0x93D1D0U, 0x93E004U, 0x93F8EEU, 0x940658U, 0x941EB2U, - 0x942F66U, 0x94378CU, 0x944CCEU, 0x945424U, 0x9465F0U, 0x947D1AU, 0x948B9EU, 0x949374U, 0x94A2A0U, 0x94BA4AU, - 0x94C108U, 0x94D9E2U, 0x94E836U, 0x94F0DCU, 0x95053EU, 0x951DD4U, 0x952C00U, 0x9534EAU, 0x954FA8U, 0x955742U, - 0x956696U, 0x957E7CU, 0x9588F8U, 0x959012U, 0x95A1C6U, 0x95B92CU, 0x95C26EU, 0x95DA84U, 0x95EB50U, 0x95F3BAU, - 0x960094U, 0x96187EU, 0x9629AAU, 0x963140U, 0x964A02U, 0x9652E8U, 0x96633CU, 0x967BD6U, 0x968D52U, 0x9695B8U, - 0x96A46CU, 0x96BC86U, 0x96C7C4U, 0x96DF2EU, 0x96EEFAU, 0x96F610U, 0x9703F2U, 0x971B18U, 0x972ACCU, 0x973226U, - 0x974964U, 0x97518EU, 0x97605AU, 0x9778B0U, 0x978E34U, 0x9796DEU, 0x97A70AU, 0x97BFE0U, 0x97C4A2U, 0x97DC48U, - 0x97ED9CU, 0x97F576U, 0x98081AU, 0x9810F0U, 0x982124U, 0x9839CEU, 0x98428CU, 0x985A66U, 0x986BB2U, 0x987358U, - 0x9885DCU, 0x989D36U, 0x98ACE2U, 0x98B408U, 0x98CF4AU, 0x98D7A0U, 0x98E674U, 0x98FE9EU, 0x990B7CU, 0x991396U, - 0x992242U, 0x993AA8U, 0x9941EAU, 0x995900U, 0x9968D4U, 0x99703EU, 0x9986BAU, 0x999E50U, 0x99AF84U, 0x99B76EU, - 0x99CC2CU, 0x99D4C6U, 0x99E512U, 0x99FDF8U, 0x9A0ED6U, 0x9A163CU, 0x9A27E8U, 0x9A3F02U, 0x9A4440U, 0x9A5CAAU, - 0x9A6D7EU, 0x9A7594U, 0x9A8310U, 0x9A9BFAU, 0x9AAA2EU, 0x9AB2C4U, 0x9AC986U, 0x9AD16CU, 0x9AE0B8U, 0x9AF852U, - 0x9B0DB0U, 0x9B155AU, 0x9B248EU, 0x9B3C64U, 0x9B4726U, 0x9B5FCCU, 0x9B6E18U, 0x9B76F2U, 0x9B8076U, 0x9B989CU, - 0x9BA948U, 0x9BB1A2U, 0x9BCAE0U, 0x9BD20AU, 0x9BE3DEU, 0x9BFB34U, 0x9C0582U, 0x9C1D68U, 0x9C2CBCU, 0x9C3456U, - 0x9C4F14U, 0x9C57FEU, 0x9C662AU, 0x9C7EC0U, 0x9C8844U, 0x9C90AEU, 0x9CA17AU, 0x9CB990U, 0x9CC2D2U, 0x9CDA38U, - 0x9CEBECU, 0x9CF306U, 0x9D06E4U, 0x9D1E0EU, 0x9D2FDAU, 0x9D3730U, 0x9D4C72U, 0x9D5498U, 0x9D654CU, 0x9D7DA6U, - 0x9D8B22U, 0x9D93C8U, 0x9DA21CU, 0x9DBAF6U, 0x9DC1B4U, 0x9DD95EU, 0x9DE88AU, 0x9DF060U, 0x9E034EU, 0x9E1BA4U, - 0x9E2A70U, 0x9E329AU, 0x9E49D8U, 0x9E5132U, 0x9E60E6U, 0x9E780CU, 0x9E8E88U, 0x9E9662U, 0x9EA7B6U, 0x9EBF5CU, - 0x9EC41EU, 0x9EDCF4U, 0x9EED20U, 0x9EF5CAU, 0x9F0028U, 0x9F18C2U, 0x9F2916U, 0x9F31FCU, 0x9F4ABEU, 0x9F5254U, - 0x9F6380U, 0x9F7B6AU, 0x9F8DEEU, 0x9F9504U, 0x9FA4D0U, 0x9FBC3AU, 0x9FC778U, 0x9FDF92U, 0x9FEE46U, 0x9FF6ACU, - 0xA0031CU, 0xA01BF6U, 0xA02A22U, 0xA032C8U, 0xA0498AU, 0xA05160U, 0xA060B4U, 0xA0785EU, 0xA08EDAU, 0xA09630U, - 0xA0A7E4U, 0xA0BF0EU, 0xA0C44CU, 0xA0DCA6U, 0xA0ED72U, 0xA0F598U, 0xA1007AU, 0xA11890U, 0xA12944U, 0xA131AEU, - 0xA14AECU, 0xA15206U, 0xA163D2U, 0xA17B38U, 0xA18DBCU, 0xA19556U, 0xA1A482U, 0xA1BC68U, 0xA1C72AU, 0xA1DFC0U, - 0xA1EE14U, 0xA1F6FEU, 0xA205D0U, 0xA21D3AU, 0xA22CEEU, 0xA23404U, 0xA24F46U, 0xA257ACU, 0xA26678U, 0xA27E92U, - 0xA28816U, 0xA290FCU, 0xA2A128U, 0xA2B9C2U, 0xA2C280U, 0xA2DA6AU, 0xA2EBBEU, 0xA2F354U, 0xA306B6U, 0xA31E5CU, - 0xA32F88U, 0xA33762U, 0xA34C20U, 0xA354CAU, 0xA3651EU, 0xA37DF4U, 0xA38B70U, 0xA3939AU, 0xA3A24EU, 0xA3BAA4U, - 0xA3C1E6U, 0xA3D90CU, 0xA3E8D8U, 0xA3F032U, 0xA40E84U, 0xA4166EU, 0xA427BAU, 0xA43F50U, 0xA44412U, 0xA45CF8U, - 0xA46D2CU, 0xA475C6U, 0xA48342U, 0xA49BA8U, 0xA4AA7CU, 0xA4B296U, 0xA4C9D4U, 0xA4D13EU, 0xA4E0EAU, 0xA4F800U, - 0xA50DE2U, 0xA51508U, 0xA524DCU, 0xA53C36U, 0xA54774U, 0xA55F9EU, 0xA56E4AU, 0xA576A0U, 0xA58024U, 0xA598CEU, - 0xA5A91AU, 0xA5B1F0U, 0xA5CAB2U, 0xA5D258U, 0xA5E38CU, 0xA5FB66U, 0xA60848U, 0xA610A2U, 0xA62176U, 0xA6399CU, - 0xA642DEU, 0xA65A34U, 0xA66BE0U, 0xA6730AU, 0xA6858EU, 0xA69D64U, 0xA6ACB0U, 0xA6B45AU, 0xA6CF18U, 0xA6D7F2U, - 0xA6E626U, 0xA6FECCU, 0xA70B2EU, 0xA713C4U, 0xA72210U, 0xA73AFAU, 0xA741B8U, 0xA75952U, 0xA76886U, 0xA7706CU, - 0xA786E8U, 0xA79E02U, 0xA7AFD6U, 0xA7B73CU, 0xA7CC7EU, 0xA7D494U, 0xA7E540U, 0xA7FDAAU, 0xA800C6U, 0xA8182CU, - 0xA829F8U, 0xA83112U, 0xA84A50U, 0xA852BAU, 0xA8636EU, 0xA87B84U, 0xA88D00U, 0xA895EAU, 0xA8A43EU, 0xA8BCD4U, - 0xA8C796U, 0xA8DF7CU, 0xA8EEA8U, 0xA8F642U, 0xA903A0U, 0xA91B4AU, 0xA92A9EU, 0xA93274U, 0xA94936U, 0xA951DCU, - 0xA96008U, 0xA978E2U, 0xA98E66U, 0xA9968CU, 0xA9A758U, 0xA9BFB2U, 0xA9C4F0U, 0xA9DC1AU, 0xA9EDCEU, 0xA9F524U, - 0xAA060AU, 0xAA1EE0U, 0xAA2F34U, 0xAA37DEU, 0xAA4C9CU, 0xAA5476U, 0xAA65A2U, 0xAA7D48U, 0xAA8BCCU, 0xAA9326U, - 0xAAA2F2U, 0xAABA18U, 0xAAC15AU, 0xAAD9B0U, 0xAAE864U, 0xAAF08EU, 0xAB056CU, 0xAB1D86U, 0xAB2C52U, 0xAB34B8U, - 0xAB4FFAU, 0xAB5710U, 0xAB66C4U, 0xAB7E2EU, 0xAB88AAU, 0xAB9040U, 0xABA194U, 0xABB97EU, 0xABC23CU, 0xABDAD6U, - 0xABEB02U, 0xABF3E8U, 0xAC0D5EU, 0xAC15B4U, 0xAC2460U, 0xAC3C8AU, 0xAC47C8U, 0xAC5F22U, 0xAC6EF6U, 0xAC761CU, - 0xAC8098U, 0xAC9872U, 0xACA9A6U, 0xACB14CU, 0xACCA0EU, 0xACD2E4U, 0xACE330U, 0xACFBDAU, 0xAD0E38U, 0xAD16D2U, - 0xAD2706U, 0xAD3FECU, 0xAD44AEU, 0xAD5C44U, 0xAD6D90U, 0xAD757AU, 0xAD83FEU, 0xAD9B14U, 0xADAAC0U, 0xADB22AU, - 0xADC968U, 0xADD182U, 0xADE056U, 0xADF8BCU, 0xAE0B92U, 0xAE1378U, 0xAE22ACU, 0xAE3A46U, 0xAE4104U, 0xAE59EEU, - 0xAE683AU, 0xAE70D0U, 0xAE8654U, 0xAE9EBEU, 0xAEAF6AU, 0xAEB780U, 0xAECCC2U, 0xAED428U, 0xAEE5FCU, 0xAEFD16U, - 0xAF08F4U, 0xAF101EU, 0xAF21CAU, 0xAF3920U, 0xAF4262U, 0xAF5A88U, 0xAF6B5CU, 0xAF73B6U, 0xAF8532U, 0xAF9DD8U, - 0xAFAC0CU, 0xAFB4E6U, 0xAFCFA4U, 0xAFD74EU, 0xAFE69AU, 0xAFFE70U, 0xB004A8U, 0xB01C42U, 0xB02D96U, 0xB0357CU, - 0xB04E3EU, 0xB056D4U, 0xB06700U, 0xB07FEAU, 0xB0896EU, 0xB09184U, 0xB0A050U, 0xB0B8BAU, 0xB0C3F8U, 0xB0DB12U, - 0xB0EAC6U, 0xB0F22CU, 0xB107CEU, 0xB11F24U, 0xB12EF0U, 0xB1361AU, 0xB14D58U, 0xB155B2U, 0xB16466U, 0xB17C8CU, - 0xB18A08U, 0xB192E2U, 0xB1A336U, 0xB1BBDCU, 0xB1C09EU, 0xB1D874U, 0xB1E9A0U, 0xB1F14AU, 0xB20264U, 0xB21A8EU, - 0xB22B5AU, 0xB233B0U, 0xB248F2U, 0xB25018U, 0xB261CCU, 0xB27926U, 0xB28FA2U, 0xB29748U, 0xB2A69CU, 0xB2BE76U, - 0xB2C534U, 0xB2DDDEU, 0xB2EC0AU, 0xB2F4E0U, 0xB30102U, 0xB319E8U, 0xB3283CU, 0xB330D6U, 0xB34B94U, 0xB3537EU, - 0xB362AAU, 0xB37A40U, 0xB38CC4U, 0xB3942EU, 0xB3A5FAU, 0xB3BD10U, 0xB3C652U, 0xB3DEB8U, 0xB3EF6CU, 0xB3F786U, - 0xB40930U, 0xB411DAU, 0xB4200EU, 0xB438E4U, 0xB443A6U, 0xB45B4CU, 0xB46A98U, 0xB47272U, 0xB484F6U, 0xB49C1CU, - 0xB4ADC8U, 0xB4B522U, 0xB4CE60U, 0xB4D68AU, 0xB4E75EU, 0xB4FFB4U, 0xB50A56U, 0xB512BCU, 0xB52368U, 0xB53B82U, - 0xB540C0U, 0xB5582AU, 0xB569FEU, 0xB57114U, 0xB58790U, 0xB59F7AU, 0xB5AEAEU, 0xB5B644U, 0xB5CD06U, 0xB5D5ECU, - 0xB5E438U, 0xB5FCD2U, 0xB60FFCU, 0xB61716U, 0xB626C2U, 0xB63E28U, 0xB6456AU, 0xB65D80U, 0xB66C54U, 0xB674BEU, - 0xB6823AU, 0xB69AD0U, 0xB6AB04U, 0xB6B3EEU, 0xB6C8ACU, 0xB6D046U, 0xB6E192U, 0xB6F978U, 0xB70C9AU, 0xB71470U, - 0xB725A4U, 0xB73D4EU, 0xB7460CU, 0xB75EE6U, 0xB76F32U, 0xB777D8U, 0xB7815CU, 0xB799B6U, 0xB7A862U, 0xB7B088U, - 0xB7CBCAU, 0xB7D320U, 0xB7E2F4U, 0xB7FA1EU, 0xB80772U, 0xB81F98U, 0xB82E4CU, 0xB836A6U, 0xB84DE4U, 0xB8550EU, - 0xB864DAU, 0xB87C30U, 0xB88AB4U, 0xB8925EU, 0xB8A38AU, 0xB8BB60U, 0xB8C022U, 0xB8D8C8U, 0xB8E91CU, 0xB8F1F6U, - 0xB90414U, 0xB91CFEU, 0xB92D2AU, 0xB935C0U, 0xB94E82U, 0xB95668U, 0xB967BCU, 0xB97F56U, 0xB989D2U, 0xB99138U, - 0xB9A0ECU, 0xB9B806U, 0xB9C344U, 0xB9DBAEU, 0xB9EA7AU, 0xB9F290U, 0xBA01BEU, 0xBA1954U, 0xBA2880U, 0xBA306AU, - 0xBA4B28U, 0xBA53C2U, 0xBA6216U, 0xBA7AFCU, 0xBA8C78U, 0xBA9492U, 0xBAA546U, 0xBABDACU, 0xBAC6EEU, 0xBADE04U, - 0xBAEFD0U, 0xBAF73AU, 0xBB02D8U, 0xBB1A32U, 0xBB2BE6U, 0xBB330CU, 0xBB484EU, 0xBB50A4U, 0xBB6170U, 0xBB799AU, - 0xBB8F1EU, 0xBB97F4U, 0xBBA620U, 0xBBBECAU, 0xBBC588U, 0xBBDD62U, 0xBBECB6U, 0xBBF45CU, 0xBC0AEAU, 0xBC1200U, - 0xBC23D4U, 0xBC3B3EU, 0xBC407CU, 0xBC5896U, 0xBC6942U, 0xBC71A8U, 0xBC872CU, 0xBC9FC6U, 0xBCAE12U, 0xBCB6F8U, - 0xBCCDBAU, 0xBCD550U, 0xBCE484U, 0xBCFC6EU, 0xBD098CU, 0xBD1166U, 0xBD20B2U, 0xBD3858U, 0xBD431AU, 0xBD5BF0U, - 0xBD6A24U, 0xBD72CEU, 0xBD844AU, 0xBD9CA0U, 0xBDAD74U, 0xBDB59EU, 0xBDCEDCU, 0xBDD636U, 0xBDE7E2U, 0xBDFF08U, - 0xBE0C26U, 0xBE14CCU, 0xBE2518U, 0xBE3DF2U, 0xBE46B0U, 0xBE5E5AU, 0xBE6F8EU, 0xBE7764U, 0xBE81E0U, 0xBE990AU, - 0xBEA8DEU, 0xBEB034U, 0xBECB76U, 0xBED39CU, 0xBEE248U, 0xBEFAA2U, 0xBF0F40U, 0xBF17AAU, 0xBF267EU, 0xBF3E94U, - 0xBF45D6U, 0xBF5D3CU, 0xBF6CE8U, 0xBF7402U, 0xBF8286U, 0xBF9A6CU, 0xBFABB8U, 0xBFB352U, 0xBFC810U, 0xBFD0FAU, - 0xBFE12EU, 0xBFF9C4U, 0xC00A4EU, 0xC012A4U, 0xC02370U, 0xC03B9AU, 0xC040D8U, 0xC05832U, 0xC069E6U, 0xC0710CU, - 0xC08788U, 0xC09F62U, 0xC0AEB6U, 0xC0B65CU, 0xC0CD1EU, 0xC0D5F4U, 0xC0E420U, 0xC0FCCAU, 0xC10928U, 0xC111C2U, - 0xC12016U, 0xC138FCU, 0xC143BEU, 0xC15B54U, 0xC16A80U, 0xC1726AU, 0xC184EEU, 0xC19C04U, 0xC1ADD0U, 0xC1B53AU, - 0xC1CE78U, 0xC1D692U, 0xC1E746U, 0xC1FFACU, 0xC20C82U, 0xC21468U, 0xC225BCU, 0xC23D56U, 0xC24614U, 0xC25EFEU, - 0xC26F2AU, 0xC277C0U, 0xC28144U, 0xC299AEU, 0xC2A87AU, 0xC2B090U, 0xC2CBD2U, 0xC2D338U, 0xC2E2ECU, 0xC2FA06U, - 0xC30FE4U, 0xC3170EU, 0xC326DAU, 0xC33E30U, 0xC34572U, 0xC35D98U, 0xC36C4CU, 0xC374A6U, 0xC38222U, 0xC39AC8U, - 0xC3AB1CU, 0xC3B3F6U, 0xC3C8B4U, 0xC3D05EU, 0xC3E18AU, 0xC3F960U, 0xC407D6U, 0xC41F3CU, 0xC42EE8U, 0xC43602U, - 0xC44D40U, 0xC455AAU, 0xC4647EU, 0xC47C94U, 0xC48A10U, 0xC492FAU, 0xC4A32EU, 0xC4BBC4U, 0xC4C086U, 0xC4D86CU, - 0xC4E9B8U, 0xC4F152U, 0xC504B0U, 0xC51C5AU, 0xC52D8EU, 0xC53564U, 0xC54E26U, 0xC556CCU, 0xC56718U, 0xC57FF2U, - 0xC58976U, 0xC5919CU, 0xC5A048U, 0xC5B8A2U, 0xC5C3E0U, 0xC5DB0AU, 0xC5EADEU, 0xC5F234U, 0xC6011AU, 0xC619F0U, - 0xC62824U, 0xC630CEU, 0xC64B8CU, 0xC65366U, 0xC662B2U, 0xC67A58U, 0xC68CDCU, 0xC69436U, 0xC6A5E2U, 0xC6BD08U, - 0xC6C64AU, 0xC6DEA0U, 0xC6EF74U, 0xC6F79EU, 0xC7027CU, 0xC71A96U, 0xC72B42U, 0xC733A8U, 0xC748EAU, 0xC75000U, - 0xC761D4U, 0xC7793EU, 0xC78FBAU, 0xC79750U, 0xC7A684U, 0xC7BE6EU, 0xC7C52CU, 0xC7DDC6U, 0xC7EC12U, 0xC7F4F8U, - 0xC80994U, 0xC8117EU, 0xC820AAU, 0xC83840U, 0xC84302U, 0xC85BE8U, 0xC86A3CU, 0xC872D6U, 0xC88452U, 0xC89CB8U, - 0xC8AD6CU, 0xC8B586U, 0xC8CEC4U, 0xC8D62EU, 0xC8E7FAU, 0xC8FF10U, 0xC90AF2U, 0xC91218U, 0xC923CCU, 0xC93B26U, - 0xC94064U, 0xC9588EU, 0xC9695AU, 0xC971B0U, 0xC98734U, 0xC99FDEU, 0xC9AE0AU, 0xC9B6E0U, 0xC9CDA2U, 0xC9D548U, - 0xC9E49CU, 0xC9FC76U, 0xCA0F58U, 0xCA17B2U, 0xCA2666U, 0xCA3E8CU, 0xCA45CEU, 0xCA5D24U, 0xCA6CF0U, 0xCA741AU, - 0xCA829EU, 0xCA9A74U, 0xCAABA0U, 0xCAB34AU, 0xCAC808U, 0xCAD0E2U, 0xCAE136U, 0xCAF9DCU, 0xCB0C3EU, 0xCB14D4U, - 0xCB2500U, 0xCB3DEAU, 0xCB46A8U, 0xCB5E42U, 0xCB6F96U, 0xCB777CU, 0xCB81F8U, 0xCB9912U, 0xCBA8C6U, 0xCBB02CU, - 0xCBCB6EU, 0xCBD384U, 0xCBE250U, 0xCBFABAU, 0xCC040CU, 0xCC1CE6U, 0xCC2D32U, 0xCC35D8U, 0xCC4E9AU, 0xCC5670U, - 0xCC67A4U, 0xCC7F4EU, 0xCC89CAU, 0xCC9120U, 0xCCA0F4U, 0xCCB81EU, 0xCCC35CU, 0xCCDBB6U, 0xCCEA62U, 0xCCF288U, - 0xCD076AU, 0xCD1F80U, 0xCD2E54U, 0xCD36BEU, 0xCD4DFCU, 0xCD5516U, 0xCD64C2U, 0xCD7C28U, 0xCD8AACU, 0xCD9246U, - 0xCDA392U, 0xCDBB78U, 0xCDC03AU, 0xCDD8D0U, 0xCDE904U, 0xCDF1EEU, 0xCE02C0U, 0xCE1A2AU, 0xCE2BFEU, 0xCE3314U, - 0xCE4856U, 0xCE50BCU, 0xCE6168U, 0xCE7982U, 0xCE8F06U, 0xCE97ECU, 0xCEA638U, 0xCEBED2U, 0xCEC590U, 0xCEDD7AU, - 0xCEECAEU, 0xCEF444U, 0xCF01A6U, 0xCF194CU, 0xCF2898U, 0xCF3072U, 0xCF4B30U, 0xCF53DAU, 0xCF620EU, 0xCF7AE4U, - 0xCF8C60U, 0xCF948AU, 0xCFA55EU, 0xCFBDB4U, 0xCFC6F6U, 0xCFDE1CU, 0xCFEFC8U, 0xCFF722U, 0xD00DFAU, 0xD01510U, - 0xD024C4U, 0xD03C2EU, 0xD0476CU, 0xD05F86U, 0xD06E52U, 0xD076B8U, 0xD0803CU, 0xD098D6U, 0xD0A902U, 0xD0B1E8U, - 0xD0CAAAU, 0xD0D240U, 0xD0E394U, 0xD0FB7EU, 0xD10E9CU, 0xD11676U, 0xD127A2U, 0xD13F48U, 0xD1440AU, 0xD15CE0U, - 0xD16D34U, 0xD175DEU, 0xD1835AU, 0xD19BB0U, 0xD1AA64U, 0xD1B28EU, 0xD1C9CCU, 0xD1D126U, 0xD1E0F2U, 0xD1F818U, - 0xD20B36U, 0xD213DCU, 0xD22208U, 0xD23AE2U, 0xD241A0U, 0xD2594AU, 0xD2689EU, 0xD27074U, 0xD286F0U, 0xD29E1AU, - 0xD2AFCEU, 0xD2B724U, 0xD2CC66U, 0xD2D48CU, 0xD2E558U, 0xD2FDB2U, 0xD30850U, 0xD310BAU, 0xD3216EU, 0xD33984U, - 0xD342C6U, 0xD35A2CU, 0xD36BF8U, 0xD37312U, 0xD38596U, 0xD39D7CU, 0xD3ACA8U, 0xD3B442U, 0xD3CF00U, 0xD3D7EAU, - 0xD3E63EU, 0xD3FED4U, 0xD40062U, 0xD41888U, 0xD4295CU, 0xD431B6U, 0xD44AF4U, 0xD4521EU, 0xD463CAU, 0xD47B20U, - 0xD48DA4U, 0xD4954EU, 0xD4A49AU, 0xD4BC70U, 0xD4C732U, 0xD4DFD8U, 0xD4EE0CU, 0xD4F6E6U, 0xD50304U, 0xD51BEEU, - 0xD52A3AU, 0xD532D0U, 0xD54992U, 0xD55178U, 0xD560ACU, 0xD57846U, 0xD58EC2U, 0xD59628U, 0xD5A7FCU, 0xD5BF16U, - 0xD5C454U, 0xD5DCBEU, 0xD5ED6AU, 0xD5F580U, 0xD606AEU, 0xD61E44U, 0xD62F90U, 0xD6377AU, 0xD64C38U, 0xD654D2U, - 0xD66506U, 0xD67DECU, 0xD68B68U, 0xD69382U, 0xD6A256U, 0xD6BABCU, 0xD6C1FEU, 0xD6D914U, 0xD6E8C0U, 0xD6F02AU, - 0xD705C8U, 0xD71D22U, 0xD72CF6U, 0xD7341CU, 0xD74F5EU, 0xD757B4U, 0xD76660U, 0xD77E8AU, 0xD7880EU, 0xD790E4U, - 0xD7A130U, 0xD7B9DAU, 0xD7C298U, 0xD7DA72U, 0xD7EBA6U, 0xD7F34CU, 0xD80E20U, 0xD816CAU, 0xD8271EU, 0xD83FF4U, - 0xD844B6U, 0xD85C5CU, 0xD86D88U, 0xD87562U, 0xD883E6U, 0xD89B0CU, 0xD8AAD8U, 0xD8B232U, 0xD8C970U, 0xD8D19AU, - 0xD8E04EU, 0xD8F8A4U, 0xD90D46U, 0xD915ACU, 0xD92478U, 0xD93C92U, 0xD947D0U, 0xD95F3AU, 0xD96EEEU, 0xD97604U, - 0xD98080U, 0xD9986AU, 0xD9A9BEU, 0xD9B154U, 0xD9CA16U, 0xD9D2FCU, 0xD9E328U, 0xD9FBC2U, 0xDA08ECU, 0xDA1006U, - 0xDA21D2U, 0xDA3938U, 0xDA427AU, 0xDA5A90U, 0xDA6B44U, 0xDA73AEU, 0xDA852AU, 0xDA9DC0U, 0xDAAC14U, 0xDAB4FEU, - 0xDACFBCU, 0xDAD756U, 0xDAE682U, 0xDAFE68U, 0xDB0B8AU, 0xDB1360U, 0xDB22B4U, 0xDB3A5EU, 0xDB411CU, 0xDB59F6U, - 0xDB6822U, 0xDB70C8U, 0xDB864CU, 0xDB9EA6U, 0xDBAF72U, 0xDBB798U, 0xDBCCDAU, 0xDBD430U, 0xDBE5E4U, 0xDBFD0EU, - 0xDC03B8U, 0xDC1B52U, 0xDC2A86U, 0xDC326CU, 0xDC492EU, 0xDC51C4U, 0xDC6010U, 0xDC78FAU, 0xDC8E7EU, 0xDC9694U, - 0xDCA740U, 0xDCBFAAU, 0xDCC4E8U, 0xDCDC02U, 0xDCEDD6U, 0xDCF53CU, 0xDD00DEU, 0xDD1834U, 0xDD29E0U, 0xDD310AU, - 0xDD4A48U, 0xDD52A2U, 0xDD6376U, 0xDD7B9CU, 0xDD8D18U, 0xDD95F2U, 0xDDA426U, 0xDDBCCCU, 0xDDC78EU, 0xDDDF64U, - 0xDDEEB0U, 0xDDF65AU, 0xDE0574U, 0xDE1D9EU, 0xDE2C4AU, 0xDE34A0U, 0xDE4FE2U, 0xDE5708U, 0xDE66DCU, 0xDE7E36U, - 0xDE88B2U, 0xDE9058U, 0xDEA18CU, 0xDEB966U, 0xDEC224U, 0xDEDACEU, 0xDEEB1AU, 0xDEF3F0U, 0xDF0612U, 0xDF1EF8U, - 0xDF2F2CU, 0xDF37C6U, 0xDF4C84U, 0xDF546EU, 0xDF65BAU, 0xDF7D50U, 0xDF8BD4U, 0xDF933EU, 0xDFA2EAU, 0xDFBA00U, - 0xDFC142U, 0xDFD9A8U, 0xDFE87CU, 0xDFF096U, 0xE00526U, 0xE01DCCU, 0xE02C18U, 0xE034F2U, 0xE04FB0U, 0xE0575AU, - 0xE0668EU, 0xE07E64U, 0xE088E0U, 0xE0900AU, 0xE0A1DEU, 0xE0B934U, 0xE0C276U, 0xE0DA9CU, 0xE0EB48U, 0xE0F3A2U, - 0xE10640U, 0xE11EAAU, 0xE12F7EU, 0xE13794U, 0xE14CD6U, 0xE1543CU, 0xE165E8U, 0xE17D02U, 0xE18B86U, 0xE1936CU, - 0xE1A2B8U, 0xE1BA52U, 0xE1C110U, 0xE1D9FAU, 0xE1E82EU, 0xE1F0C4U, 0xE203EAU, 0xE21B00U, 0xE22AD4U, 0xE2323EU, - 0xE2497CU, 0xE25196U, 0xE26042U, 0xE278A8U, 0xE28E2CU, 0xE296C6U, 0xE2A712U, 0xE2BFF8U, 0xE2C4BAU, 0xE2DC50U, - 0xE2ED84U, 0xE2F56EU, 0xE3008CU, 0xE31866U, 0xE329B2U, 0xE33158U, 0xE34A1AU, 0xE352F0U, 0xE36324U, 0xE37BCEU, - 0xE38D4AU, 0xE395A0U, 0xE3A474U, 0xE3BC9EU, 0xE3C7DCU, 0xE3DF36U, 0xE3EEE2U, 0xE3F608U, 0xE408BEU, 0xE41054U, - 0xE42180U, 0xE4396AU, 0xE44228U, 0xE45AC2U, 0xE46B16U, 0xE473FCU, 0xE48578U, 0xE49D92U, 0xE4AC46U, 0xE4B4ACU, - 0xE4CFEEU, 0xE4D704U, 0xE4E6D0U, 0xE4FE3AU, 0xE50BD8U, 0xE51332U, 0xE522E6U, 0xE53A0CU, 0xE5414EU, 0xE559A4U, - 0xE56870U, 0xE5709AU, 0xE5861EU, 0xE59EF4U, 0xE5AF20U, 0xE5B7CAU, 0xE5CC88U, 0xE5D462U, 0xE5E5B6U, 0xE5FD5CU, - 0xE60E72U, 0xE61698U, 0xE6274CU, 0xE63FA6U, 0xE644E4U, 0xE65C0EU, 0xE66DDAU, 0xE67530U, 0xE683B4U, 0xE69B5EU, - 0xE6AA8AU, 0xE6B260U, 0xE6C922U, 0xE6D1C8U, 0xE6E01CU, 0xE6F8F6U, 0xE70D14U, 0xE715FEU, 0xE7242AU, 0xE73CC0U, - 0xE74782U, 0xE75F68U, 0xE76EBCU, 0xE77656U, 0xE780D2U, 0xE79838U, 0xE7A9ECU, 0xE7B106U, 0xE7CA44U, 0xE7D2AEU, - 0xE7E37AU, 0xE7FB90U, 0xE806FCU, 0xE81E16U, 0xE82FC2U, 0xE83728U, 0xE84C6AU, 0xE85480U, 0xE86554U, 0xE87DBEU, - 0xE88B3AU, 0xE893D0U, 0xE8A204U, 0xE8BAEEU, 0xE8C1ACU, 0xE8D946U, 0xE8E892U, 0xE8F078U, 0xE9059AU, 0xE91D70U, - 0xE92CA4U, 0xE9344EU, 0xE94F0CU, 0xE957E6U, 0xE96632U, 0xE97ED8U, 0xE9885CU, 0xE990B6U, 0xE9A162U, 0xE9B988U, - 0xE9C2CAU, 0xE9DA20U, 0xE9EBF4U, 0xE9F31EU, 0xEA0030U, 0xEA18DAU, 0xEA290EU, 0xEA31E4U, 0xEA4AA6U, 0xEA524CU, - 0xEA6398U, 0xEA7B72U, 0xEA8DF6U, 0xEA951CU, 0xEAA4C8U, 0xEABC22U, 0xEAC760U, 0xEADF8AU, 0xEAEE5EU, 0xEAF6B4U, - 0xEB0356U, 0xEB1BBCU, 0xEB2A68U, 0xEB3282U, 0xEB49C0U, 0xEB512AU, 0xEB60FEU, 0xEB7814U, 0xEB8E90U, 0xEB967AU, - 0xEBA7AEU, 0xEBBF44U, 0xEBC406U, 0xEBDCECU, 0xEBED38U, 0xEBF5D2U, 0xEC0B64U, 0xEC138EU, 0xEC225AU, 0xEC3AB0U, - 0xEC41F2U, 0xEC5918U, 0xEC68CCU, 0xEC7026U, 0xEC86A2U, 0xEC9E48U, 0xECAF9CU, 0xECB776U, 0xECCC34U, 0xECD4DEU, - 0xECE50AU, 0xECFDE0U, 0xED0802U, 0xED10E8U, 0xED213CU, 0xED39D6U, 0xED4294U, 0xED5A7EU, 0xED6BAAU, 0xED7340U, - 0xED85C4U, 0xED9D2EU, 0xEDACFAU, 0xEDB410U, 0xEDCF52U, 0xEDD7B8U, 0xEDE66CU, 0xEDFE86U, 0xEE0DA8U, 0xEE1542U, - 0xEE2496U, 0xEE3C7CU, 0xEE473EU, 0xEE5FD4U, 0xEE6E00U, 0xEE76EAU, 0xEE806EU, 0xEE9884U, 0xEEA950U, 0xEEB1BAU, - 0xEECAF8U, 0xEED212U, 0xEEE3C6U, 0xEEFB2CU, 0xEF0ECEU, 0xEF1624U, 0xEF27F0U, 0xEF3F1AU, 0xEF4458U, 0xEF5CB2U, - 0xEF6D66U, 0xEF758CU, 0xEF8308U, 0xEF9BE2U, 0xEFAA36U, 0xEFB2DCU, 0xEFC99EU, 0xEFD174U, 0xEFE0A0U, 0xEFF84AU, - 0xF00292U, 0xF01A78U, 0xF02BACU, 0xF03346U, 0xF04804U, 0xF050EEU, 0xF0613AU, 0xF079D0U, 0xF08F54U, 0xF097BEU, - 0xF0A66AU, 0xF0BE80U, 0xF0C5C2U, 0xF0DD28U, 0xF0ECFCU, 0xF0F416U, 0xF101F4U, 0xF1191EU, 0xF128CAU, 0xF13020U, - 0xF14B62U, 0xF15388U, 0xF1625CU, 0xF17AB6U, 0xF18C32U, 0xF194D8U, 0xF1A50CU, 0xF1BDE6U, 0xF1C6A4U, 0xF1DE4EU, - 0xF1EF9AU, 0xF1F770U, 0xF2045EU, 0xF21CB4U, 0xF22D60U, 0xF2358AU, 0xF24EC8U, 0xF25622U, 0xF267F6U, 0xF27F1CU, - 0xF28998U, 0xF29172U, 0xF2A0A6U, 0xF2B84CU, 0xF2C30EU, 0xF2DBE4U, 0xF2EA30U, 0xF2F2DAU, 0xF30738U, 0xF31FD2U, - 0xF32E06U, 0xF336ECU, 0xF34DAEU, 0xF35544U, 0xF36490U, 0xF37C7AU, 0xF38AFEU, 0xF39214U, 0xF3A3C0U, 0xF3BB2AU, - 0xF3C068U, 0xF3D882U, 0xF3E956U, 0xF3F1BCU, 0xF40F0AU, 0xF417E0U, 0xF42634U, 0xF43EDEU, 0xF4459CU, 0xF45D76U, - 0xF46CA2U, 0xF47448U, 0xF482CCU, 0xF49A26U, 0xF4ABF2U, 0xF4B318U, 0xF4C85AU, 0xF4D0B0U, 0xF4E164U, 0xF4F98EU, - 0xF50C6CU, 0xF51486U, 0xF52552U, 0xF53DB8U, 0xF546FAU, 0xF55E10U, 0xF56FC4U, 0xF5772EU, 0xF581AAU, 0xF59940U, - 0xF5A894U, 0xF5B07EU, 0xF5CB3CU, 0xF5D3D6U, 0xF5E202U, 0xF5FAE8U, 0xF609C6U, 0xF6112CU, 0xF620F8U, 0xF63812U, - 0xF64350U, 0xF65BBAU, 0xF66A6EU, 0xF67284U, 0xF68400U, 0xF69CEAU, 0xF6AD3EU, 0xF6B5D4U, 0xF6CE96U, 0xF6D67CU, - 0xF6E7A8U, 0xF6FF42U, 0xF70AA0U, 0xF7124AU, 0xF7239EU, 0xF73B74U, 0xF74036U, 0xF758DCU, 0xF76908U, 0xF771E2U, - 0xF78766U, 0xF79F8CU, 0xF7AE58U, 0xF7B6B2U, 0xF7CDF0U, 0xF7D51AU, 0xF7E4CEU, 0xF7FC24U, 0xF80148U, 0xF819A2U, - 0xF82876U, 0xF8309CU, 0xF84BDEU, 0xF85334U, 0xF862E0U, 0xF87A0AU, 0xF88C8EU, 0xF89464U, 0xF8A5B0U, 0xF8BD5AU, - 0xF8C618U, 0xF8DEF2U, 0xF8EF26U, 0xF8F7CCU, 0xF9022EU, 0xF91AC4U, 0xF92B10U, 0xF933FAU, 0xF948B8U, 0xF95052U, - 0xF96186U, 0xF9796CU, 0xF98FE8U, 0xF99702U, 0xF9A6D6U, 0xF9BE3CU, 0xF9C57EU, 0xF9DD94U, 0xF9EC40U, 0xF9F4AAU, - 0xFA0784U, 0xFA1F6EU, 0xFA2EBAU, 0xFA3650U, 0xFA4D12U, 0xFA55F8U, 0xFA642CU, 0xFA7CC6U, 0xFA8A42U, 0xFA92A8U, - 0xFAA37CU, 0xFABB96U, 0xFAC0D4U, 0xFAD83EU, 0xFAE9EAU, 0xFAF100U, 0xFB04E2U, 0xFB1C08U, 0xFB2DDCU, 0xFB3536U, - 0xFB4E74U, 0xFB569EU, 0xFB674AU, 0xFB7FA0U, 0xFB8924U, 0xFB91CEU, 0xFBA01AU, 0xFBB8F0U, 0xFBC3B2U, 0xFBDB58U, - 0xFBEA8CU, 0xFBF266U, 0xFC0CD0U, 0xFC143AU, 0xFC25EEU, 0xFC3D04U, 0xFC4646U, 0xFC5EACU, 0xFC6F78U, 0xFC7792U, - 0xFC8116U, 0xFC99FCU, 0xFCA828U, 0xFCB0C2U, 0xFCCB80U, 0xFCD36AU, 0xFCE2BEU, 0xFCFA54U, 0xFD0FB6U, 0xFD175CU, - 0xFD2688U, 0xFD3E62U, 0xFD4520U, 0xFD5DCAU, 0xFD6C1EU, 0xFD74F4U, 0xFD8270U, 0xFD9A9AU, 0xFDAB4EU, 0xFDB3A4U, - 0xFDC8E6U, 0xFDD00CU, 0xFDE1D8U, 0xFDF932U, 0xFE0A1CU, 0xFE12F6U, 0xFE2322U, 0xFE3BC8U, 0xFE408AU, 0xFE5860U, - 0xFE69B4U, 0xFE715EU, 0xFE87DAU, 0xFE9F30U, 0xFEAEE4U, 0xFEB60EU, 0xFECD4CU, 0xFED5A6U, 0xFEE472U, 0xFEFC98U, - 0xFF097AU, 0xFF1190U, 0xFF2044U, 0xFF38AEU, 0xFF43ECU, 0xFF5B06U, 0xFF6AD2U, 0xFF7238U, 0xFF84BCU, 0xFF9C56U, - 0xFFAD82U, 0xFFB568U, 0xFFCE2AU, 0xFFD6C0U, 0xFFE714U, 0xFFFFFEU}; +const unsigned int ENCODING_TABLE_23127[] = +{ + 0x000000U, 0x0018EAU, 0x00293EU, 0x0031D4U, 0x004A96U, 0x00527CU, 0x0063A8U, 0x007B42U, 0x008DC6U, 0x00952CU, + 0x00A4F8U, 0x00BC12U, 0x00C750U, 0x00DFBAU, 0x00EE6EU, 0x00F684U, 0x010366U, 0x011B8CU, 0x012A58U, 0x0132B2U, + 0x0149F0U, 0x01511AU, 0x0160CEU, 0x017824U, 0x018EA0U, 0x01964AU, 0x01A79EU, 0x01BF74U, 0x01C436U, 0x01DCDCU, + 0x01ED08U, 0x01F5E2U, 0x0206CCU, 0x021E26U, 0x022FF2U, 0x023718U, 0x024C5AU, 0x0254B0U, 0x026564U, 0x027D8EU, + 0x028B0AU, 0x0293E0U, 0x02A234U, 0x02BADEU, 0x02C19CU, 0x02D976U, 0x02E8A2U, 0x02F048U, 0x0305AAU, 0x031D40U, + 0x032C94U, 0x03347EU, 0x034F3CU, 0x0357D6U, 0x036602U, 0x037EE8U, 0x03886CU, 0x039086U, 0x03A152U, 0x03B9B8U, + 0x03C2FAU, 0x03DA10U, 0x03EBC4U, 0x03F32EU, 0x040D98U, 0x041572U, 0x0424A6U, 0x043C4CU, 0x04470EU, 0x045FE4U, + 0x046E30U, 0x0476DAU, 0x04805EU, 0x0498B4U, 0x04A960U, 0x04B18AU, 0x04CAC8U, 0x04D222U, 0x04E3F6U, 0x04FB1CU, + 0x050EFEU, 0x051614U, 0x0527C0U, 0x053F2AU, 0x054468U, 0x055C82U, 0x056D56U, 0x0575BCU, 0x058338U, 0x059BD2U, + 0x05AA06U, 0x05B2ECU, 0x05C9AEU, 0x05D144U, 0x05E090U, 0x05F87AU, 0x060B54U, 0x0613BEU, 0x06226AU, 0x063A80U, + 0x0641C2U, 0x065928U, 0x0668FCU, 0x067016U, 0x068692U, 0x069E78U, 0x06AFACU, 0x06B746U, 0x06CC04U, 0x06D4EEU, + 0x06E53AU, 0x06FDD0U, 0x070832U, 0x0710D8U, 0x07210CU, 0x0739E6U, 0x0742A4U, 0x075A4EU, 0x076B9AU, 0x077370U, + 0x0785F4U, 0x079D1EU, 0x07ACCAU, 0x07B420U, 0x07CF62U, 0x07D788U, 0x07E65CU, 0x07FEB6U, 0x0803DAU, 0x081B30U, + 0x082AE4U, 0x08320EU, 0x08494CU, 0x0851A6U, 0x086072U, 0x087898U, 0x088E1CU, 0x0896F6U, 0x08A722U, 0x08BFC8U, + 0x08C48AU, 0x08DC60U, 0x08EDB4U, 0x08F55EU, 0x0900BCU, 0x091856U, 0x092982U, 0x093168U, 0x094A2AU, 0x0952C0U, + 0x096314U, 0x097BFEU, 0x098D7AU, 0x099590U, 0x09A444U, 0x09BCAEU, 0x09C7ECU, 0x09DF06U, 0x09EED2U, 0x09F638U, + 0x0A0516U, 0x0A1DFCU, 0x0A2C28U, 0x0A34C2U, 0x0A4F80U, 0x0A576AU, 0x0A66BEU, 0x0A7E54U, 0x0A88D0U, 0x0A903AU, + 0x0AA1EEU, 0x0AB904U, 0x0AC246U, 0x0ADAACU, 0x0AEB78U, 0x0AF392U, 0x0B0670U, 0x0B1E9AU, 0x0B2F4EU, 0x0B37A4U, + 0x0B4CE6U, 0x0B540CU, 0x0B65D8U, 0x0B7D32U, 0x0B8BB6U, 0x0B935CU, 0x0BA288U, 0x0BBA62U, 0x0BC120U, 0x0BD9CAU, + 0x0BE81EU, 0x0BF0F4U, 0x0C0E42U, 0x0C16A8U, 0x0C277CU, 0x0C3F96U, 0x0C44D4U, 0x0C5C3EU, 0x0C6DEAU, 0x0C7500U, + 0x0C8384U, 0x0C9B6EU, 0x0CAABAU, 0x0CB250U, 0x0CC912U, 0x0CD1F8U, 0x0CE02CU, 0x0CF8C6U, 0x0D0D24U, 0x0D15CEU, + 0x0D241AU, 0x0D3CF0U, 0x0D47B2U, 0x0D5F58U, 0x0D6E8CU, 0x0D7666U, 0x0D80E2U, 0x0D9808U, 0x0DA9DCU, 0x0DB136U, + 0x0DCA74U, 0x0DD29EU, 0x0DE34AU, 0x0DFBA0U, 0x0E088EU, 0x0E1064U, 0x0E21B0U, 0x0E395AU, 0x0E4218U, 0x0E5AF2U, + 0x0E6B26U, 0x0E73CCU, 0x0E8548U, 0x0E9DA2U, 0x0EAC76U, 0x0EB49CU, 0x0ECFDEU, 0x0ED734U, 0x0EE6E0U, 0x0EFE0AU, + 0x0F0BE8U, 0x0F1302U, 0x0F22D6U, 0x0F3A3CU, 0x0F417EU, 0x0F5994U, 0x0F6840U, 0x0F70AAU, 0x0F862EU, 0x0F9EC4U, + 0x0FAF10U, 0x0FB7FAU, 0x0FCCB8U, 0x0FD452U, 0x0FE586U, 0x0FFD6CU, 0x1007B4U, 0x101F5EU, 0x102E8AU, 0x103660U, + 0x104D22U, 0x1055C8U, 0x10641CU, 0x107CF6U, 0x108A72U, 0x109298U, 0x10A34CU, 0x10BBA6U, 0x10C0E4U, 0x10D80EU, + 0x10E9DAU, 0x10F130U, 0x1104D2U, 0x111C38U, 0x112DECU, 0x113506U, 0x114E44U, 0x1156AEU, 0x11677AU, 0x117F90U, + 0x118914U, 0x1191FEU, 0x11A02AU, 0x11B8C0U, 0x11C382U, 0x11DB68U, 0x11EABCU, 0x11F256U, 0x120178U, 0x121992U, + 0x122846U, 0x1230ACU, 0x124BEEU, 0x125304U, 0x1262D0U, 0x127A3AU, 0x128CBEU, 0x129454U, 0x12A580U, 0x12BD6AU, + 0x12C628U, 0x12DEC2U, 0x12EF16U, 0x12F7FCU, 0x13021EU, 0x131AF4U, 0x132B20U, 0x1333CAU, 0x134888U, 0x135062U, + 0x1361B6U, 0x13795CU, 0x138FD8U, 0x139732U, 0x13A6E6U, 0x13BE0CU, 0x13C54EU, 0x13DDA4U, 0x13EC70U, 0x13F49AU, + 0x140A2CU, 0x1412C6U, 0x142312U, 0x143BF8U, 0x1440BAU, 0x145850U, 0x146984U, 0x14716EU, 0x1487EAU, 0x149F00U, + 0x14AED4U, 0x14B63EU, 0x14CD7CU, 0x14D596U, 0x14E442U, 0x14FCA8U, 0x15094AU, 0x1511A0U, 0x152074U, 0x15389EU, + 0x1543DCU, 0x155B36U, 0x156AE2U, 0x157208U, 0x15848CU, 0x159C66U, 0x15ADB2U, 0x15B558U, 0x15CE1AU, 0x15D6F0U, + 0x15E724U, 0x15FFCEU, 0x160CE0U, 0x16140AU, 0x1625DEU, 0x163D34U, 0x164676U, 0x165E9CU, 0x166F48U, 0x1677A2U, + 0x168126U, 0x1699CCU, 0x16A818U, 0x16B0F2U, 0x16CBB0U, 0x16D35AU, 0x16E28EU, 0x16FA64U, 0x170F86U, 0x17176CU, + 0x1726B8U, 0x173E52U, 0x174510U, 0x175DFAU, 0x176C2EU, 0x1774C4U, 0x178240U, 0x179AAAU, 0x17AB7EU, 0x17B394U, + 0x17C8D6U, 0x17D03CU, 0x17E1E8U, 0x17F902U, 0x18046EU, 0x181C84U, 0x182D50U, 0x1835BAU, 0x184EF8U, 0x185612U, + 0x1867C6U, 0x187F2CU, 0x1889A8U, 0x189142U, 0x18A096U, 0x18B87CU, 0x18C33EU, 0x18DBD4U, 0x18EA00U, 0x18F2EAU, + 0x190708U, 0x191FE2U, 0x192E36U, 0x1936DCU, 0x194D9EU, 0x195574U, 0x1964A0U, 0x197C4AU, 0x198ACEU, 0x199224U, + 0x19A3F0U, 0x19BB1AU, 0x19C058U, 0x19D8B2U, 0x19E966U, 0x19F18CU, 0x1A02A2U, 0x1A1A48U, 0x1A2B9CU, 0x1A3376U, + 0x1A4834U, 0x1A50DEU, 0x1A610AU, 0x1A79E0U, 0x1A8F64U, 0x1A978EU, 0x1AA65AU, 0x1ABEB0U, 0x1AC5F2U, 0x1ADD18U, + 0x1AECCCU, 0x1AF426U, 0x1B01C4U, 0x1B192EU, 0x1B28FAU, 0x1B3010U, 0x1B4B52U, 0x1B53B8U, 0x1B626CU, 0x1B7A86U, + 0x1B8C02U, 0x1B94E8U, 0x1BA53CU, 0x1BBDD6U, 0x1BC694U, 0x1BDE7EU, 0x1BEFAAU, 0x1BF740U, 0x1C09F6U, 0x1C111CU, + 0x1C20C8U, 0x1C3822U, 0x1C4360U, 0x1C5B8AU, 0x1C6A5EU, 0x1C72B4U, 0x1C8430U, 0x1C9CDAU, 0x1CAD0EU, 0x1CB5E4U, + 0x1CCEA6U, 0x1CD64CU, 0x1CE798U, 0x1CFF72U, 0x1D0A90U, 0x1D127AU, 0x1D23AEU, 0x1D3B44U, 0x1D4006U, 0x1D58ECU, + 0x1D6938U, 0x1D71D2U, 0x1D8756U, 0x1D9FBCU, 0x1DAE68U, 0x1DB682U, 0x1DCDC0U, 0x1DD52AU, 0x1DE4FEU, 0x1DFC14U, + 0x1E0F3AU, 0x1E17D0U, 0x1E2604U, 0x1E3EEEU, 0x1E45ACU, 0x1E5D46U, 0x1E6C92U, 0x1E7478U, 0x1E82FCU, 0x1E9A16U, + 0x1EABC2U, 0x1EB328U, 0x1EC86AU, 0x1ED080U, 0x1EE154U, 0x1EF9BEU, 0x1F0C5CU, 0x1F14B6U, 0x1F2562U, 0x1F3D88U, + 0x1F46CAU, 0x1F5E20U, 0x1F6FF4U, 0x1F771EU, 0x1F819AU, 0x1F9970U, 0x1FA8A4U, 0x1FB04EU, 0x1FCB0CU, 0x1FD3E6U, + 0x1FE232U, 0x1FFAD8U, 0x200F68U, 0x201782U, 0x202656U, 0x203EBCU, 0x2045FEU, 0x205D14U, 0x206CC0U, 0x20742AU, + 0x2082AEU, 0x209A44U, 0x20AB90U, 0x20B37AU, 0x20C838U, 0x20D0D2U, 0x20E106U, 0x20F9ECU, 0x210C0EU, 0x2114E4U, + 0x212530U, 0x213DDAU, 0x214698U, 0x215E72U, 0x216FA6U, 0x21774CU, 0x2181C8U, 0x219922U, 0x21A8F6U, 0x21B01CU, + 0x21CB5EU, 0x21D3B4U, 0x21E260U, 0x21FA8AU, 0x2209A4U, 0x22114EU, 0x22209AU, 0x223870U, 0x224332U, 0x225BD8U, + 0x226A0CU, 0x2272E6U, 0x228462U, 0x229C88U, 0x22AD5CU, 0x22B5B6U, 0x22CEF4U, 0x22D61EU, 0x22E7CAU, 0x22FF20U, + 0x230AC2U, 0x231228U, 0x2323FCU, 0x233B16U, 0x234054U, 0x2358BEU, 0x23696AU, 0x237180U, 0x238704U, 0x239FEEU, + 0x23AE3AU, 0x23B6D0U, 0x23CD92U, 0x23D578U, 0x23E4ACU, 0x23FC46U, 0x2402F0U, 0x241A1AU, 0x242BCEU, 0x243324U, + 0x244866U, 0x24508CU, 0x246158U, 0x2479B2U, 0x248F36U, 0x2497DCU, 0x24A608U, 0x24BEE2U, 0x24C5A0U, 0x24DD4AU, + 0x24EC9EU, 0x24F474U, 0x250196U, 0x25197CU, 0x2528A8U, 0x253042U, 0x254B00U, 0x2553EAU, 0x25623EU, 0x257AD4U, + 0x258C50U, 0x2594BAU, 0x25A56EU, 0x25BD84U, 0x25C6C6U, 0x25DE2CU, 0x25EFF8U, 0x25F712U, 0x26043CU, 0x261CD6U, + 0x262D02U, 0x2635E8U, 0x264EAAU, 0x265640U, 0x266794U, 0x267F7EU, 0x2689FAU, 0x269110U, 0x26A0C4U, 0x26B82EU, + 0x26C36CU, 0x26DB86U, 0x26EA52U, 0x26F2B8U, 0x27075AU, 0x271FB0U, 0x272E64U, 0x27368EU, 0x274DCCU, 0x275526U, + 0x2764F2U, 0x277C18U, 0x278A9CU, 0x279276U, 0x27A3A2U, 0x27BB48U, 0x27C00AU, 0x27D8E0U, 0x27E934U, 0x27F1DEU, + 0x280CB2U, 0x281458U, 0x28258CU, 0x283D66U, 0x284624U, 0x285ECEU, 0x286F1AU, 0x2877F0U, 0x288174U, 0x28999EU, + 0x28A84AU, 0x28B0A0U, 0x28CBE2U, 0x28D308U, 0x28E2DCU, 0x28FA36U, 0x290FD4U, 0x29173EU, 0x2926EAU, 0x293E00U, + 0x294542U, 0x295DA8U, 0x296C7CU, 0x297496U, 0x298212U, 0x299AF8U, 0x29AB2CU, 0x29B3C6U, 0x29C884U, 0x29D06EU, + 0x29E1BAU, 0x29F950U, 0x2A0A7EU, 0x2A1294U, 0x2A2340U, 0x2A3BAAU, 0x2A40E8U, 0x2A5802U, 0x2A69D6U, 0x2A713CU, + 0x2A87B8U, 0x2A9F52U, 0x2AAE86U, 0x2AB66CU, 0x2ACD2EU, 0x2AD5C4U, 0x2AE410U, 0x2AFCFAU, 0x2B0918U, 0x2B11F2U, + 0x2B2026U, 0x2B38CCU, 0x2B438EU, 0x2B5B64U, 0x2B6AB0U, 0x2B725AU, 0x2B84DEU, 0x2B9C34U, 0x2BADE0U, 0x2BB50AU, + 0x2BCE48U, 0x2BD6A2U, 0x2BE776U, 0x2BFF9CU, 0x2C012AU, 0x2C19C0U, 0x2C2814U, 0x2C30FEU, 0x2C4BBCU, 0x2C5356U, + 0x2C6282U, 0x2C7A68U, 0x2C8CECU, 0x2C9406U, 0x2CA5D2U, 0x2CBD38U, 0x2CC67AU, 0x2CDE90U, 0x2CEF44U, 0x2CF7AEU, + 0x2D024CU, 0x2D1AA6U, 0x2D2B72U, 0x2D3398U, 0x2D48DAU, 0x2D5030U, 0x2D61E4U, 0x2D790EU, 0x2D8F8AU, 0x2D9760U, + 0x2DA6B4U, 0x2DBE5EU, 0x2DC51CU, 0x2DDDF6U, 0x2DEC22U, 0x2DF4C8U, 0x2E07E6U, 0x2E1F0CU, 0x2E2ED8U, 0x2E3632U, + 0x2E4D70U, 0x2E559AU, 0x2E644EU, 0x2E7CA4U, 0x2E8A20U, 0x2E92CAU, 0x2EA31EU, 0x2EBBF4U, 0x2EC0B6U, 0x2ED85CU, + 0x2EE988U, 0x2EF162U, 0x2F0480U, 0x2F1C6AU, 0x2F2DBEU, 0x2F3554U, 0x2F4E16U, 0x2F56FCU, 0x2F6728U, 0x2F7FC2U, + 0x2F8946U, 0x2F91ACU, 0x2FA078U, 0x2FB892U, 0x2FC3D0U, 0x2FDB3AU, 0x2FEAEEU, 0x2FF204U, 0x3008DCU, 0x301036U, + 0x3021E2U, 0x303908U, 0x30424AU, 0x305AA0U, 0x306B74U, 0x30739EU, 0x30851AU, 0x309DF0U, 0x30AC24U, 0x30B4CEU, + 0x30CF8CU, 0x30D766U, 0x30E6B2U, 0x30FE58U, 0x310BBAU, 0x311350U, 0x312284U, 0x313A6EU, 0x31412CU, 0x3159C6U, + 0x316812U, 0x3170F8U, 0x31867CU, 0x319E96U, 0x31AF42U, 0x31B7A8U, 0x31CCEAU, 0x31D400U, 0x31E5D4U, 0x31FD3EU, + 0x320E10U, 0x3216FAU, 0x32272EU, 0x323FC4U, 0x324486U, 0x325C6CU, 0x326DB8U, 0x327552U, 0x3283D6U, 0x329B3CU, + 0x32AAE8U, 0x32B202U, 0x32C940U, 0x32D1AAU, 0x32E07EU, 0x32F894U, 0x330D76U, 0x33159CU, 0x332448U, 0x333CA2U, + 0x3347E0U, 0x335F0AU, 0x336EDEU, 0x337634U, 0x3380B0U, 0x33985AU, 0x33A98EU, 0x33B164U, 0x33CA26U, 0x33D2CCU, + 0x33E318U, 0x33FBF2U, 0x340544U, 0x341DAEU, 0x342C7AU, 0x343490U, 0x344FD2U, 0x345738U, 0x3466ECU, 0x347E06U, + 0x348882U, 0x349068U, 0x34A1BCU, 0x34B956U, 0x34C214U, 0x34DAFEU, 0x34EB2AU, 0x34F3C0U, 0x350622U, 0x351EC8U, + 0x352F1CU, 0x3537F6U, 0x354CB4U, 0x35545EU, 0x35658AU, 0x357D60U, 0x358BE4U, 0x35930EU, 0x35A2DAU, 0x35BA30U, + 0x35C172U, 0x35D998U, 0x35E84CU, 0x35F0A6U, 0x360388U, 0x361B62U, 0x362AB6U, 0x36325CU, 0x36491EU, 0x3651F4U, + 0x366020U, 0x3678CAU, 0x368E4EU, 0x3696A4U, 0x36A770U, 0x36BF9AU, 0x36C4D8U, 0x36DC32U, 0x36EDE6U, 0x36F50CU, + 0x3700EEU, 0x371804U, 0x3729D0U, 0x37313AU, 0x374A78U, 0x375292U, 0x376346U, 0x377BACU, 0x378D28U, 0x3795C2U, + 0x37A416U, 0x37BCFCU, 0x37C7BEU, 0x37DF54U, 0x37EE80U, 0x37F66AU, 0x380B06U, 0x3813ECU, 0x382238U, 0x383AD2U, + 0x384190U, 0x38597AU, 0x3868AEU, 0x387044U, 0x3886C0U, 0x389E2AU, 0x38AFFEU, 0x38B714U, 0x38CC56U, 0x38D4BCU, + 0x38E568U, 0x38FD82U, 0x390860U, 0x39108AU, 0x39215EU, 0x3939B4U, 0x3942F6U, 0x395A1CU, 0x396BC8U, 0x397322U, + 0x3985A6U, 0x399D4CU, 0x39AC98U, 0x39B472U, 0x39CF30U, 0x39D7DAU, 0x39E60EU, 0x39FEE4U, 0x3A0DCAU, 0x3A1520U, + 0x3A24F4U, 0x3A3C1EU, 0x3A475CU, 0x3A5FB6U, 0x3A6E62U, 0x3A7688U, 0x3A800CU, 0x3A98E6U, 0x3AA932U, 0x3AB1D8U, + 0x3ACA9AU, 0x3AD270U, 0x3AE3A4U, 0x3AFB4EU, 0x3B0EACU, 0x3B1646U, 0x3B2792U, 0x3B3F78U, 0x3B443AU, 0x3B5CD0U, + 0x3B6D04U, 0x3B75EEU, 0x3B836AU, 0x3B9B80U, 0x3BAA54U, 0x3BB2BEU, 0x3BC9FCU, 0x3BD116U, 0x3BE0C2U, 0x3BF828U, + 0x3C069EU, 0x3C1E74U, 0x3C2FA0U, 0x3C374AU, 0x3C4C08U, 0x3C54E2U, 0x3C6536U, 0x3C7DDCU, 0x3C8B58U, 0x3C93B2U, + 0x3CA266U, 0x3CBA8CU, 0x3CC1CEU, 0x3CD924U, 0x3CE8F0U, 0x3CF01AU, 0x3D05F8U, 0x3D1D12U, 0x3D2CC6U, 0x3D342CU, + 0x3D4F6EU, 0x3D5784U, 0x3D6650U, 0x3D7EBAU, 0x3D883EU, 0x3D90D4U, 0x3DA100U, 0x3DB9EAU, 0x3DC2A8U, 0x3DDA42U, + 0x3DEB96U, 0x3DF37CU, 0x3E0052U, 0x3E18B8U, 0x3E296CU, 0x3E3186U, 0x3E4AC4U, 0x3E522EU, 0x3E63FAU, 0x3E7B10U, + 0x3E8D94U, 0x3E957EU, 0x3EA4AAU, 0x3EBC40U, 0x3EC702U, 0x3EDFE8U, 0x3EEE3CU, 0x3EF6D6U, 0x3F0334U, 0x3F1BDEU, + 0x3F2A0AU, 0x3F32E0U, 0x3F49A2U, 0x3F5148U, 0x3F609CU, 0x3F7876U, 0x3F8EF2U, 0x3F9618U, 0x3FA7CCU, 0x3FBF26U, + 0x3FC464U, 0x3FDC8EU, 0x3FED5AU, 0x3FF5B0U, 0x40063AU, 0x401ED0U, 0x402F04U, 0x4037EEU, 0x404CACU, 0x405446U, + 0x406592U, 0x407D78U, 0x408BFCU, 0x409316U, 0x40A2C2U, 0x40BA28U, 0x40C16AU, 0x40D980U, 0x40E854U, 0x40F0BEU, + 0x41055CU, 0x411DB6U, 0x412C62U, 0x413488U, 0x414FCAU, 0x415720U, 0x4166F4U, 0x417E1EU, 0x41889AU, 0x419070U, + 0x41A1A4U, 0x41B94EU, 0x41C20CU, 0x41DAE6U, 0x41EB32U, 0x41F3D8U, 0x4200F6U, 0x42181CU, 0x4229C8U, 0x423122U, + 0x424A60U, 0x42528AU, 0x42635EU, 0x427BB4U, 0x428D30U, 0x4295DAU, 0x42A40EU, 0x42BCE4U, 0x42C7A6U, 0x42DF4CU, + 0x42EE98U, 0x42F672U, 0x430390U, 0x431B7AU, 0x432AAEU, 0x433244U, 0x434906U, 0x4351ECU, 0x436038U, 0x4378D2U, + 0x438E56U, 0x4396BCU, 0x43A768U, 0x43BF82U, 0x43C4C0U, 0x43DC2AU, 0x43EDFEU, 0x43F514U, 0x440BA2U, 0x441348U, + 0x44229CU, 0x443A76U, 0x444134U, 0x4459DEU, 0x44680AU, 0x4470E0U, 0x448664U, 0x449E8EU, 0x44AF5AU, 0x44B7B0U, + 0x44CCF2U, 0x44D418U, 0x44E5CCU, 0x44FD26U, 0x4508C4U, 0x45102EU, 0x4521FAU, 0x453910U, 0x454252U, 0x455AB8U, + 0x456B6CU, 0x457386U, 0x458502U, 0x459DE8U, 0x45AC3CU, 0x45B4D6U, 0x45CF94U, 0x45D77EU, 0x45E6AAU, 0x45FE40U, + 0x460D6EU, 0x461584U, 0x462450U, 0x463CBAU, 0x4647F8U, 0x465F12U, 0x466EC6U, 0x46762CU, 0x4680A8U, 0x469842U, + 0x46A996U, 0x46B17CU, 0x46CA3EU, 0x46D2D4U, 0x46E300U, 0x46FBEAU, 0x470E08U, 0x4716E2U, 0x472736U, 0x473FDCU, + 0x47449EU, 0x475C74U, 0x476DA0U, 0x47754AU, 0x4783CEU, 0x479B24U, 0x47AAF0U, 0x47B21AU, 0x47C958U, 0x47D1B2U, + 0x47E066U, 0x47F88CU, 0x4805E0U, 0x481D0AU, 0x482CDEU, 0x483434U, 0x484F76U, 0x48579CU, 0x486648U, 0x487EA2U, + 0x488826U, 0x4890CCU, 0x48A118U, 0x48B9F2U, 0x48C2B0U, 0x48DA5AU, 0x48EB8EU, 0x48F364U, 0x490686U, 0x491E6CU, + 0x492FB8U, 0x493752U, 0x494C10U, 0x4954FAU, 0x49652EU, 0x497DC4U, 0x498B40U, 0x4993AAU, 0x49A27EU, 0x49BA94U, + 0x49C1D6U, 0x49D93CU, 0x49E8E8U, 0x49F002U, 0x4A032CU, 0x4A1BC6U, 0x4A2A12U, 0x4A32F8U, 0x4A49BAU, 0x4A5150U, + 0x4A6084U, 0x4A786EU, 0x4A8EEAU, 0x4A9600U, 0x4AA7D4U, 0x4ABF3EU, 0x4AC47CU, 0x4ADC96U, 0x4AED42U, 0x4AF5A8U, + 0x4B004AU, 0x4B18A0U, 0x4B2974U, 0x4B319EU, 0x4B4ADCU, 0x4B5236U, 0x4B63E2U, 0x4B7B08U, 0x4B8D8CU, 0x4B9566U, + 0x4BA4B2U, 0x4BBC58U, 0x4BC71AU, 0x4BDFF0U, 0x4BEE24U, 0x4BF6CEU, 0x4C0878U, 0x4C1092U, 0x4C2146U, 0x4C39ACU, + 0x4C42EEU, 0x4C5A04U, 0x4C6BD0U, 0x4C733AU, 0x4C85BEU, 0x4C9D54U, 0x4CAC80U, 0x4CB46AU, 0x4CCF28U, 0x4CD7C2U, + 0x4CE616U, 0x4CFEFCU, 0x4D0B1EU, 0x4D13F4U, 0x4D2220U, 0x4D3ACAU, 0x4D4188U, 0x4D5962U, 0x4D68B6U, 0x4D705CU, + 0x4D86D8U, 0x4D9E32U, 0x4DAFE6U, 0x4DB70CU, 0x4DCC4EU, 0x4DD4A4U, 0x4DE570U, 0x4DFD9AU, 0x4E0EB4U, 0x4E165EU, + 0x4E278AU, 0x4E3F60U, 0x4E4422U, 0x4E5CC8U, 0x4E6D1CU, 0x4E75F6U, 0x4E8372U, 0x4E9B98U, 0x4EAA4CU, 0x4EB2A6U, + 0x4EC9E4U, 0x4ED10EU, 0x4EE0DAU, 0x4EF830U, 0x4F0DD2U, 0x4F1538U, 0x4F24ECU, 0x4F3C06U, 0x4F4744U, 0x4F5FAEU, + 0x4F6E7AU, 0x4F7690U, 0x4F8014U, 0x4F98FEU, 0x4FA92AU, 0x4FB1C0U, 0x4FCA82U, 0x4FD268U, 0x4FE3BCU, 0x4FFB56U, + 0x50018EU, 0x501964U, 0x5028B0U, 0x50305AU, 0x504B18U, 0x5053F2U, 0x506226U, 0x507ACCU, 0x508C48U, 0x5094A2U, + 0x50A576U, 0x50BD9CU, 0x50C6DEU, 0x50DE34U, 0x50EFE0U, 0x50F70AU, 0x5102E8U, 0x511A02U, 0x512BD6U, 0x51333CU, + 0x51487EU, 0x515094U, 0x516140U, 0x5179AAU, 0x518F2EU, 0x5197C4U, 0x51A610U, 0x51BEFAU, 0x51C5B8U, 0x51DD52U, + 0x51EC86U, 0x51F46CU, 0x520742U, 0x521FA8U, 0x522E7CU, 0x523696U, 0x524DD4U, 0x52553EU, 0x5264EAU, 0x527C00U, + 0x528A84U, 0x52926EU, 0x52A3BAU, 0x52BB50U, 0x52C012U, 0x52D8F8U, 0x52E92CU, 0x52F1C6U, 0x530424U, 0x531CCEU, + 0x532D1AU, 0x5335F0U, 0x534EB2U, 0x535658U, 0x53678CU, 0x537F66U, 0x5389E2U, 0x539108U, 0x53A0DCU, 0x53B836U, + 0x53C374U, 0x53DB9EU, 0x53EA4AU, 0x53F2A0U, 0x540C16U, 0x5414FCU, 0x542528U, 0x543DC2U, 0x544680U, 0x545E6AU, + 0x546FBEU, 0x547754U, 0x5481D0U, 0x54993AU, 0x54A8EEU, 0x54B004U, 0x54CB46U, 0x54D3ACU, 0x54E278U, 0x54FA92U, + 0x550F70U, 0x55179AU, 0x55264EU, 0x553EA4U, 0x5545E6U, 0x555D0CU, 0x556CD8U, 0x557432U, 0x5582B6U, 0x559A5CU, + 0x55AB88U, 0x55B362U, 0x55C820U, 0x55D0CAU, 0x55E11EU, 0x55F9F4U, 0x560ADAU, 0x561230U, 0x5623E4U, 0x563B0EU, + 0x56404CU, 0x5658A6U, 0x566972U, 0x567198U, 0x56871CU, 0x569FF6U, 0x56AE22U, 0x56B6C8U, 0x56CD8AU, 0x56D560U, + 0x56E4B4U, 0x56FC5EU, 0x5709BCU, 0x571156U, 0x572082U, 0x573868U, 0x57432AU, 0x575BC0U, 0x576A14U, 0x5772FEU, + 0x57847AU, 0x579C90U, 0x57AD44U, 0x57B5AEU, 0x57CEECU, 0x57D606U, 0x57E7D2U, 0x57FF38U, 0x580254U, 0x581ABEU, + 0x582B6AU, 0x583380U, 0x5848C2U, 0x585028U, 0x5861FCU, 0x587916U, 0x588F92U, 0x589778U, 0x58A6ACU, 0x58BE46U, + 0x58C504U, 0x58DDEEU, 0x58EC3AU, 0x58F4D0U, 0x590132U, 0x5919D8U, 0x59280CU, 0x5930E6U, 0x594BA4U, 0x59534EU, + 0x59629AU, 0x597A70U, 0x598CF4U, 0x59941EU, 0x59A5CAU, 0x59BD20U, 0x59C662U, 0x59DE88U, 0x59EF5CU, 0x59F7B6U, + 0x5A0498U, 0x5A1C72U, 0x5A2DA6U, 0x5A354CU, 0x5A4E0EU, 0x5A56E4U, 0x5A6730U, 0x5A7FDAU, 0x5A895EU, 0x5A91B4U, + 0x5AA060U, 0x5AB88AU, 0x5AC3C8U, 0x5ADB22U, 0x5AEAF6U, 0x5AF21CU, 0x5B07FEU, 0x5B1F14U, 0x5B2EC0U, 0x5B362AU, + 0x5B4D68U, 0x5B5582U, 0x5B6456U, 0x5B7CBCU, 0x5B8A38U, 0x5B92D2U, 0x5BA306U, 0x5BBBECU, 0x5BC0AEU, 0x5BD844U, + 0x5BE990U, 0x5BF17AU, 0x5C0FCCU, 0x5C1726U, 0x5C26F2U, 0x5C3E18U, 0x5C455AU, 0x5C5DB0U, 0x5C6C64U, 0x5C748EU, + 0x5C820AU, 0x5C9AE0U, 0x5CAB34U, 0x5CB3DEU, 0x5CC89CU, 0x5CD076U, 0x5CE1A2U, 0x5CF948U, 0x5D0CAAU, 0x5D1440U, + 0x5D2594U, 0x5D3D7EU, 0x5D463CU, 0x5D5ED6U, 0x5D6F02U, 0x5D77E8U, 0x5D816CU, 0x5D9986U, 0x5DA852U, 0x5DB0B8U, + 0x5DCBFAU, 0x5DD310U, 0x5DE2C4U, 0x5DFA2EU, 0x5E0900U, 0x5E11EAU, 0x5E203EU, 0x5E38D4U, 0x5E4396U, 0x5E5B7CU, + 0x5E6AA8U, 0x5E7242U, 0x5E84C6U, 0x5E9C2CU, 0x5EADF8U, 0x5EB512U, 0x5ECE50U, 0x5ED6BAU, 0x5EE76EU, 0x5EFF84U, + 0x5F0A66U, 0x5F128CU, 0x5F2358U, 0x5F3BB2U, 0x5F40F0U, 0x5F581AU, 0x5F69CEU, 0x5F7124U, 0x5F87A0U, 0x5F9F4AU, + 0x5FAE9EU, 0x5FB674U, 0x5FCD36U, 0x5FD5DCU, 0x5FE408U, 0x5FFCE2U, 0x600952U, 0x6011B8U, 0x60206CU, 0x603886U, + 0x6043C4U, 0x605B2EU, 0x606AFAU, 0x607210U, 0x608494U, 0x609C7EU, 0x60ADAAU, 0x60B540U, 0x60CE02U, 0x60D6E8U, + 0x60E73CU, 0x60FFD6U, 0x610A34U, 0x6112DEU, 0x61230AU, 0x613BE0U, 0x6140A2U, 0x615848U, 0x61699CU, 0x617176U, + 0x6187F2U, 0x619F18U, 0x61AECCU, 0x61B626U, 0x61CD64U, 0x61D58EU, 0x61E45AU, 0x61FCB0U, 0x620F9EU, 0x621774U, + 0x6226A0U, 0x623E4AU, 0x624508U, 0x625DE2U, 0x626C36U, 0x6274DCU, 0x628258U, 0x629AB2U, 0x62AB66U, 0x62B38CU, + 0x62C8CEU, 0x62D024U, 0x62E1F0U, 0x62F91AU, 0x630CF8U, 0x631412U, 0x6325C6U, 0x633D2CU, 0x63466EU, 0x635E84U, + 0x636F50U, 0x6377BAU, 0x63813EU, 0x6399D4U, 0x63A800U, 0x63B0EAU, 0x63CBA8U, 0x63D342U, 0x63E296U, 0x63FA7CU, + 0x6404CAU, 0x641C20U, 0x642DF4U, 0x64351EU, 0x644E5CU, 0x6456B6U, 0x646762U, 0x647F88U, 0x64890CU, 0x6491E6U, + 0x64A032U, 0x64B8D8U, 0x64C39AU, 0x64DB70U, 0x64EAA4U, 0x64F24EU, 0x6507ACU, 0x651F46U, 0x652E92U, 0x653678U, + 0x654D3AU, 0x6555D0U, 0x656404U, 0x657CEEU, 0x658A6AU, 0x659280U, 0x65A354U, 0x65BBBEU, 0x65C0FCU, 0x65D816U, + 0x65E9C2U, 0x65F128U, 0x660206U, 0x661AECU, 0x662B38U, 0x6633D2U, 0x664890U, 0x66507AU, 0x6661AEU, 0x667944U, + 0x668FC0U, 0x66972AU, 0x66A6FEU, 0x66BE14U, 0x66C556U, 0x66DDBCU, 0x66EC68U, 0x66F482U, 0x670160U, 0x67198AU, + 0x67285EU, 0x6730B4U, 0x674BF6U, 0x67531CU, 0x6762C8U, 0x677A22U, 0x678CA6U, 0x67944CU, 0x67A598U, 0x67BD72U, + 0x67C630U, 0x67DEDAU, 0x67EF0EU, 0x67F7E4U, 0x680A88U, 0x681262U, 0x6823B6U, 0x683B5CU, 0x68401EU, 0x6858F4U, + 0x686920U, 0x6871CAU, 0x68874EU, 0x689FA4U, 0x68AE70U, 0x68B69AU, 0x68CDD8U, 0x68D532U, 0x68E4E6U, 0x68FC0CU, + 0x6909EEU, 0x691104U, 0x6920D0U, 0x69383AU, 0x694378U, 0x695B92U, 0x696A46U, 0x6972ACU, 0x698428U, 0x699CC2U, + 0x69AD16U, 0x69B5FCU, 0x69CEBEU, 0x69D654U, 0x69E780U, 0x69FF6AU, 0x6A0C44U, 0x6A14AEU, 0x6A257AU, 0x6A3D90U, + 0x6A46D2U, 0x6A5E38U, 0x6A6FECU, 0x6A7706U, 0x6A8182U, 0x6A9968U, 0x6AA8BCU, 0x6AB056U, 0x6ACB14U, 0x6AD3FEU, + 0x6AE22AU, 0x6AFAC0U, 0x6B0F22U, 0x6B17C8U, 0x6B261CU, 0x6B3EF6U, 0x6B45B4U, 0x6B5D5EU, 0x6B6C8AU, 0x6B7460U, + 0x6B82E4U, 0x6B9A0EU, 0x6BABDAU, 0x6BB330U, 0x6BC872U, 0x6BD098U, 0x6BE14CU, 0x6BF9A6U, 0x6C0710U, 0x6C1FFAU, + 0x6C2E2EU, 0x6C36C4U, 0x6C4D86U, 0x6C556CU, 0x6C64B8U, 0x6C7C52U, 0x6C8AD6U, 0x6C923CU, 0x6CA3E8U, 0x6CBB02U, + 0x6CC040U, 0x6CD8AAU, 0x6CE97EU, 0x6CF194U, 0x6D0476U, 0x6D1C9CU, 0x6D2D48U, 0x6D35A2U, 0x6D4EE0U, 0x6D560AU, + 0x6D67DEU, 0x6D7F34U, 0x6D89B0U, 0x6D915AU, 0x6DA08EU, 0x6DB864U, 0x6DC326U, 0x6DDBCCU, 0x6DEA18U, 0x6DF2F2U, + 0x6E01DCU, 0x6E1936U, 0x6E28E2U, 0x6E3008U, 0x6E4B4AU, 0x6E53A0U, 0x6E6274U, 0x6E7A9EU, 0x6E8C1AU, 0x6E94F0U, + 0x6EA524U, 0x6EBDCEU, 0x6EC68CU, 0x6EDE66U, 0x6EEFB2U, 0x6EF758U, 0x6F02BAU, 0x6F1A50U, 0x6F2B84U, 0x6F336EU, + 0x6F482CU, 0x6F50C6U, 0x6F6112U, 0x6F79F8U, 0x6F8F7CU, 0x6F9796U, 0x6FA642U, 0x6FBEA8U, 0x6FC5EAU, 0x6FDD00U, + 0x6FECD4U, 0x6FF43EU, 0x700EE6U, 0x70160CU, 0x7027D8U, 0x703F32U, 0x704470U, 0x705C9AU, 0x706D4EU, 0x7075A4U, + 0x708320U, 0x709BCAU, 0x70AA1EU, 0x70B2F4U, 0x70C9B6U, 0x70D15CU, 0x70E088U, 0x70F862U, 0x710D80U, 0x71156AU, + 0x7124BEU, 0x713C54U, 0x714716U, 0x715FFCU, 0x716E28U, 0x7176C2U, 0x718046U, 0x7198ACU, 0x71A978U, 0x71B192U, + 0x71CAD0U, 0x71D23AU, 0x71E3EEU, 0x71FB04U, 0x72082AU, 0x7210C0U, 0x722114U, 0x7239FEU, 0x7242BCU, 0x725A56U, + 0x726B82U, 0x727368U, 0x7285ECU, 0x729D06U, 0x72ACD2U, 0x72B438U, 0x72CF7AU, 0x72D790U, 0x72E644U, 0x72FEAEU, + 0x730B4CU, 0x7313A6U, 0x732272U, 0x733A98U, 0x7341DAU, 0x735930U, 0x7368E4U, 0x73700EU, 0x73868AU, 0x739E60U, + 0x73AFB4U, 0x73B75EU, 0x73CC1CU, 0x73D4F6U, 0x73E522U, 0x73FDC8U, 0x74037EU, 0x741B94U, 0x742A40U, 0x7432AAU, + 0x7449E8U, 0x745102U, 0x7460D6U, 0x74783CU, 0x748EB8U, 0x749652U, 0x74A786U, 0x74BF6CU, 0x74C42EU, 0x74DCC4U, + 0x74ED10U, 0x74F5FAU, 0x750018U, 0x7518F2U, 0x752926U, 0x7531CCU, 0x754A8EU, 0x755264U, 0x7563B0U, 0x757B5AU, + 0x758DDEU, 0x759534U, 0x75A4E0U, 0x75BC0AU, 0x75C748U, 0x75DFA2U, 0x75EE76U, 0x75F69CU, 0x7605B2U, 0x761D58U, + 0x762C8CU, 0x763466U, 0x764F24U, 0x7657CEU, 0x76661AU, 0x767EF0U, 0x768874U, 0x76909EU, 0x76A14AU, 0x76B9A0U, + 0x76C2E2U, 0x76DA08U, 0x76EBDCU, 0x76F336U, 0x7706D4U, 0x771E3EU, 0x772FEAU, 0x773700U, 0x774C42U, 0x7754A8U, + 0x77657CU, 0x777D96U, 0x778B12U, 0x7793F8U, 0x77A22CU, 0x77BAC6U, 0x77C184U, 0x77D96EU, 0x77E8BAU, 0x77F050U, + 0x780D3CU, 0x7815D6U, 0x782402U, 0x783CE8U, 0x7847AAU, 0x785F40U, 0x786E94U, 0x78767EU, 0x7880FAU, 0x789810U, + 0x78A9C4U, 0x78B12EU, 0x78CA6CU, 0x78D286U, 0x78E352U, 0x78FBB8U, 0x790E5AU, 0x7916B0U, 0x792764U, 0x793F8EU, + 0x7944CCU, 0x795C26U, 0x796DF2U, 0x797518U, 0x79839CU, 0x799B76U, 0x79AAA2U, 0x79B248U, 0x79C90AU, 0x79D1E0U, + 0x79E034U, 0x79F8DEU, 0x7A0BF0U, 0x7A131AU, 0x7A22CEU, 0x7A3A24U, 0x7A4166U, 0x7A598CU, 0x7A6858U, 0x7A70B2U, + 0x7A8636U, 0x7A9EDCU, 0x7AAF08U, 0x7AB7E2U, 0x7ACCA0U, 0x7AD44AU, 0x7AE59EU, 0x7AFD74U, 0x7B0896U, 0x7B107CU, + 0x7B21A8U, 0x7B3942U, 0x7B4200U, 0x7B5AEAU, 0x7B6B3EU, 0x7B73D4U, 0x7B8550U, 0x7B9DBAU, 0x7BAC6EU, 0x7BB484U, + 0x7BCFC6U, 0x7BD72CU, 0x7BE6F8U, 0x7BFE12U, 0x7C00A4U, 0x7C184EU, 0x7C299AU, 0x7C3170U, 0x7C4A32U, 0x7C52D8U, + 0x7C630CU, 0x7C7BE6U, 0x7C8D62U, 0x7C9588U, 0x7CA45CU, 0x7CBCB6U, 0x7CC7F4U, 0x7CDF1EU, 0x7CEECAU, 0x7CF620U, + 0x7D03C2U, 0x7D1B28U, 0x7D2AFCU, 0x7D3216U, 0x7D4954U, 0x7D51BEU, 0x7D606AU, 0x7D7880U, 0x7D8E04U, 0x7D96EEU, + 0x7DA73AU, 0x7DBFD0U, 0x7DC492U, 0x7DDC78U, 0x7DEDACU, 0x7DF546U, 0x7E0668U, 0x7E1E82U, 0x7E2F56U, 0x7E37BCU, + 0x7E4CFEU, 0x7E5414U, 0x7E65C0U, 0x7E7D2AU, 0x7E8BAEU, 0x7E9344U, 0x7EA290U, 0x7EBA7AU, 0x7EC138U, 0x7ED9D2U, + 0x7EE806U, 0x7EF0ECU, 0x7F050EU, 0x7F1DE4U, 0x7F2C30U, 0x7F34DAU, 0x7F4F98U, 0x7F5772U, 0x7F66A6U, 0x7F7E4CU, + 0x7F88C8U, 0x7F9022U, 0x7FA1F6U, 0x7FB91CU, 0x7FC25EU, 0x7FDAB4U, 0x7FEB60U, 0x7FF38AU, 0x800C74U, 0x80149EU, + 0x80254AU, 0x803DA0U, 0x8046E2U, 0x805E08U, 0x806FDCU, 0x807736U, 0x8081B2U, 0x809958U, 0x80A88CU, 0x80B066U, + 0x80CB24U, 0x80D3CEU, 0x80E21AU, 0x80FAF0U, 0x810F12U, 0x8117F8U, 0x81262CU, 0x813EC6U, 0x814584U, 0x815D6EU, + 0x816CBAU, 0x817450U, 0x8182D4U, 0x819A3EU, 0x81ABEAU, 0x81B300U, 0x81C842U, 0x81D0A8U, 0x81E17CU, 0x81F996U, + 0x820AB8U, 0x821252U, 0x822386U, 0x823B6CU, 0x82402EU, 0x8258C4U, 0x826910U, 0x8271FAU, 0x82877EU, 0x829F94U, + 0x82AE40U, 0x82B6AAU, 0x82CDE8U, 0x82D502U, 0x82E4D6U, 0x82FC3CU, 0x8309DEU, 0x831134U, 0x8320E0U, 0x83380AU, + 0x834348U, 0x835BA2U, 0x836A76U, 0x83729CU, 0x838418U, 0x839CF2U, 0x83AD26U, 0x83B5CCU, 0x83CE8EU, 0x83D664U, + 0x83E7B0U, 0x83FF5AU, 0x8401ECU, 0x841906U, 0x8428D2U, 0x843038U, 0x844B7AU, 0x845390U, 0x846244U, 0x847AAEU, + 0x848C2AU, 0x8494C0U, 0x84A514U, 0x84BDFEU, 0x84C6BCU, 0x84DE56U, 0x84EF82U, 0x84F768U, 0x85028AU, 0x851A60U, + 0x852BB4U, 0x85335EU, 0x85481CU, 0x8550F6U, 0x856122U, 0x8579C8U, 0x858F4CU, 0x8597A6U, 0x85A672U, 0x85BE98U, + 0x85C5DAU, 0x85DD30U, 0x85ECE4U, 0x85F40EU, 0x860720U, 0x861FCAU, 0x862E1EU, 0x8636F4U, 0x864DB6U, 0x86555CU, + 0x866488U, 0x867C62U, 0x868AE6U, 0x86920CU, 0x86A3D8U, 0x86BB32U, 0x86C070U, 0x86D89AU, 0x86E94EU, 0x86F1A4U, + 0x870446U, 0x871CACU, 0x872D78U, 0x873592U, 0x874ED0U, 0x87563AU, 0x8767EEU, 0x877F04U, 0x878980U, 0x87916AU, + 0x87A0BEU, 0x87B854U, 0x87C316U, 0x87DBFCU, 0x87EA28U, 0x87F2C2U, 0x880FAEU, 0x881744U, 0x882690U, 0x883E7AU, + 0x884538U, 0x885DD2U, 0x886C06U, 0x8874ECU, 0x888268U, 0x889A82U, 0x88AB56U, 0x88B3BCU, 0x88C8FEU, 0x88D014U, + 0x88E1C0U, 0x88F92AU, 0x890CC8U, 0x891422U, 0x8925F6U, 0x893D1CU, 0x89465EU, 0x895EB4U, 0x896F60U, 0x89778AU, + 0x89810EU, 0x8999E4U, 0x89A830U, 0x89B0DAU, 0x89CB98U, 0x89D372U, 0x89E2A6U, 0x89FA4CU, 0x8A0962U, 0x8A1188U, + 0x8A205CU, 0x8A38B6U, 0x8A43F4U, 0x8A5B1EU, 0x8A6ACAU, 0x8A7220U, 0x8A84A4U, 0x8A9C4EU, 0x8AAD9AU, 0x8AB570U, + 0x8ACE32U, 0x8AD6D8U, 0x8AE70CU, 0x8AFFE6U, 0x8B0A04U, 0x8B12EEU, 0x8B233AU, 0x8B3BD0U, 0x8B4092U, 0x8B5878U, + 0x8B69ACU, 0x8B7146U, 0x8B87C2U, 0x8B9F28U, 0x8BAEFCU, 0x8BB616U, 0x8BCD54U, 0x8BD5BEU, 0x8BE46AU, 0x8BFC80U, + 0x8C0236U, 0x8C1ADCU, 0x8C2B08U, 0x8C33E2U, 0x8C48A0U, 0x8C504AU, 0x8C619EU, 0x8C7974U, 0x8C8FF0U, 0x8C971AU, + 0x8CA6CEU, 0x8CBE24U, 0x8CC566U, 0x8CDD8CU, 0x8CEC58U, 0x8CF4B2U, 0x8D0150U, 0x8D19BAU, 0x8D286EU, 0x8D3084U, + 0x8D4BC6U, 0x8D532CU, 0x8D62F8U, 0x8D7A12U, 0x8D8C96U, 0x8D947CU, 0x8DA5A8U, 0x8DBD42U, 0x8DC600U, 0x8DDEEAU, + 0x8DEF3EU, 0x8DF7D4U, 0x8E04FAU, 0x8E1C10U, 0x8E2DC4U, 0x8E352EU, 0x8E4E6CU, 0x8E5686U, 0x8E6752U, 0x8E7FB8U, + 0x8E893CU, 0x8E91D6U, 0x8EA002U, 0x8EB8E8U, 0x8EC3AAU, 0x8EDB40U, 0x8EEA94U, 0x8EF27EU, 0x8F079CU, 0x8F1F76U, + 0x8F2EA2U, 0x8F3648U, 0x8F4D0AU, 0x8F55E0U, 0x8F6434U, 0x8F7CDEU, 0x8F8A5AU, 0x8F92B0U, 0x8FA364U, 0x8FBB8EU, + 0x8FC0CCU, 0x8FD826U, 0x8FE9F2U, 0x8FF118U, 0x900BC0U, 0x90132AU, 0x9022FEU, 0x903A14U, 0x904156U, 0x9059BCU, + 0x906868U, 0x907082U, 0x908606U, 0x909EECU, 0x90AF38U, 0x90B7D2U, 0x90CC90U, 0x90D47AU, 0x90E5AEU, 0x90FD44U, + 0x9108A6U, 0x91104CU, 0x912198U, 0x913972U, 0x914230U, 0x915ADAU, 0x916B0EU, 0x9173E4U, 0x918560U, 0x919D8AU, + 0x91AC5EU, 0x91B4B4U, 0x91CFF6U, 0x91D71CU, 0x91E6C8U, 0x91FE22U, 0x920D0CU, 0x9215E6U, 0x922432U, 0x923CD8U, + 0x92479AU, 0x925F70U, 0x926EA4U, 0x92764EU, 0x9280CAU, 0x929820U, 0x92A9F4U, 0x92B11EU, 0x92CA5CU, 0x92D2B6U, + 0x92E362U, 0x92FB88U, 0x930E6AU, 0x931680U, 0x932754U, 0x933FBEU, 0x9344FCU, 0x935C16U, 0x936DC2U, 0x937528U, + 0x9383ACU, 0x939B46U, 0x93AA92U, 0x93B278U, 0x93C93AU, 0x93D1D0U, 0x93E004U, 0x93F8EEU, 0x940658U, 0x941EB2U, + 0x942F66U, 0x94378CU, 0x944CCEU, 0x945424U, 0x9465F0U, 0x947D1AU, 0x948B9EU, 0x949374U, 0x94A2A0U, 0x94BA4AU, + 0x94C108U, 0x94D9E2U, 0x94E836U, 0x94F0DCU, 0x95053EU, 0x951DD4U, 0x952C00U, 0x9534EAU, 0x954FA8U, 0x955742U, + 0x956696U, 0x957E7CU, 0x9588F8U, 0x959012U, 0x95A1C6U, 0x95B92CU, 0x95C26EU, 0x95DA84U, 0x95EB50U, 0x95F3BAU, + 0x960094U, 0x96187EU, 0x9629AAU, 0x963140U, 0x964A02U, 0x9652E8U, 0x96633CU, 0x967BD6U, 0x968D52U, 0x9695B8U, + 0x96A46CU, 0x96BC86U, 0x96C7C4U, 0x96DF2EU, 0x96EEFAU, 0x96F610U, 0x9703F2U, 0x971B18U, 0x972ACCU, 0x973226U, + 0x974964U, 0x97518EU, 0x97605AU, 0x9778B0U, 0x978E34U, 0x9796DEU, 0x97A70AU, 0x97BFE0U, 0x97C4A2U, 0x97DC48U, + 0x97ED9CU, 0x97F576U, 0x98081AU, 0x9810F0U, 0x982124U, 0x9839CEU, 0x98428CU, 0x985A66U, 0x986BB2U, 0x987358U, + 0x9885DCU, 0x989D36U, 0x98ACE2U, 0x98B408U, 0x98CF4AU, 0x98D7A0U, 0x98E674U, 0x98FE9EU, 0x990B7CU, 0x991396U, + 0x992242U, 0x993AA8U, 0x9941EAU, 0x995900U, 0x9968D4U, 0x99703EU, 0x9986BAU, 0x999E50U, 0x99AF84U, 0x99B76EU, + 0x99CC2CU, 0x99D4C6U, 0x99E512U, 0x99FDF8U, 0x9A0ED6U, 0x9A163CU, 0x9A27E8U, 0x9A3F02U, 0x9A4440U, 0x9A5CAAU, + 0x9A6D7EU, 0x9A7594U, 0x9A8310U, 0x9A9BFAU, 0x9AAA2EU, 0x9AB2C4U, 0x9AC986U, 0x9AD16CU, 0x9AE0B8U, 0x9AF852U, + 0x9B0DB0U, 0x9B155AU, 0x9B248EU, 0x9B3C64U, 0x9B4726U, 0x9B5FCCU, 0x9B6E18U, 0x9B76F2U, 0x9B8076U, 0x9B989CU, + 0x9BA948U, 0x9BB1A2U, 0x9BCAE0U, 0x9BD20AU, 0x9BE3DEU, 0x9BFB34U, 0x9C0582U, 0x9C1D68U, 0x9C2CBCU, 0x9C3456U, + 0x9C4F14U, 0x9C57FEU, 0x9C662AU, 0x9C7EC0U, 0x9C8844U, 0x9C90AEU, 0x9CA17AU, 0x9CB990U, 0x9CC2D2U, 0x9CDA38U, + 0x9CEBECU, 0x9CF306U, 0x9D06E4U, 0x9D1E0EU, 0x9D2FDAU, 0x9D3730U, 0x9D4C72U, 0x9D5498U, 0x9D654CU, 0x9D7DA6U, + 0x9D8B22U, 0x9D93C8U, 0x9DA21CU, 0x9DBAF6U, 0x9DC1B4U, 0x9DD95EU, 0x9DE88AU, 0x9DF060U, 0x9E034EU, 0x9E1BA4U, + 0x9E2A70U, 0x9E329AU, 0x9E49D8U, 0x9E5132U, 0x9E60E6U, 0x9E780CU, 0x9E8E88U, 0x9E9662U, 0x9EA7B6U, 0x9EBF5CU, + 0x9EC41EU, 0x9EDCF4U, 0x9EED20U, 0x9EF5CAU, 0x9F0028U, 0x9F18C2U, 0x9F2916U, 0x9F31FCU, 0x9F4ABEU, 0x9F5254U, + 0x9F6380U, 0x9F7B6AU, 0x9F8DEEU, 0x9F9504U, 0x9FA4D0U, 0x9FBC3AU, 0x9FC778U, 0x9FDF92U, 0x9FEE46U, 0x9FF6ACU, + 0xA0031CU, 0xA01BF6U, 0xA02A22U, 0xA032C8U, 0xA0498AU, 0xA05160U, 0xA060B4U, 0xA0785EU, 0xA08EDAU, 0xA09630U, + 0xA0A7E4U, 0xA0BF0EU, 0xA0C44CU, 0xA0DCA6U, 0xA0ED72U, 0xA0F598U, 0xA1007AU, 0xA11890U, 0xA12944U, 0xA131AEU, + 0xA14AECU, 0xA15206U, 0xA163D2U, 0xA17B38U, 0xA18DBCU, 0xA19556U, 0xA1A482U, 0xA1BC68U, 0xA1C72AU, 0xA1DFC0U, + 0xA1EE14U, 0xA1F6FEU, 0xA205D0U, 0xA21D3AU, 0xA22CEEU, 0xA23404U, 0xA24F46U, 0xA257ACU, 0xA26678U, 0xA27E92U, + 0xA28816U, 0xA290FCU, 0xA2A128U, 0xA2B9C2U, 0xA2C280U, 0xA2DA6AU, 0xA2EBBEU, 0xA2F354U, 0xA306B6U, 0xA31E5CU, + 0xA32F88U, 0xA33762U, 0xA34C20U, 0xA354CAU, 0xA3651EU, 0xA37DF4U, 0xA38B70U, 0xA3939AU, 0xA3A24EU, 0xA3BAA4U, + 0xA3C1E6U, 0xA3D90CU, 0xA3E8D8U, 0xA3F032U, 0xA40E84U, 0xA4166EU, 0xA427BAU, 0xA43F50U, 0xA44412U, 0xA45CF8U, + 0xA46D2CU, 0xA475C6U, 0xA48342U, 0xA49BA8U, 0xA4AA7CU, 0xA4B296U, 0xA4C9D4U, 0xA4D13EU, 0xA4E0EAU, 0xA4F800U, + 0xA50DE2U, 0xA51508U, 0xA524DCU, 0xA53C36U, 0xA54774U, 0xA55F9EU, 0xA56E4AU, 0xA576A0U, 0xA58024U, 0xA598CEU, + 0xA5A91AU, 0xA5B1F0U, 0xA5CAB2U, 0xA5D258U, 0xA5E38CU, 0xA5FB66U, 0xA60848U, 0xA610A2U, 0xA62176U, 0xA6399CU, + 0xA642DEU, 0xA65A34U, 0xA66BE0U, 0xA6730AU, 0xA6858EU, 0xA69D64U, 0xA6ACB0U, 0xA6B45AU, 0xA6CF18U, 0xA6D7F2U, + 0xA6E626U, 0xA6FECCU, 0xA70B2EU, 0xA713C4U, 0xA72210U, 0xA73AFAU, 0xA741B8U, 0xA75952U, 0xA76886U, 0xA7706CU, + 0xA786E8U, 0xA79E02U, 0xA7AFD6U, 0xA7B73CU, 0xA7CC7EU, 0xA7D494U, 0xA7E540U, 0xA7FDAAU, 0xA800C6U, 0xA8182CU, + 0xA829F8U, 0xA83112U, 0xA84A50U, 0xA852BAU, 0xA8636EU, 0xA87B84U, 0xA88D00U, 0xA895EAU, 0xA8A43EU, 0xA8BCD4U, + 0xA8C796U, 0xA8DF7CU, 0xA8EEA8U, 0xA8F642U, 0xA903A0U, 0xA91B4AU, 0xA92A9EU, 0xA93274U, 0xA94936U, 0xA951DCU, + 0xA96008U, 0xA978E2U, 0xA98E66U, 0xA9968CU, 0xA9A758U, 0xA9BFB2U, 0xA9C4F0U, 0xA9DC1AU, 0xA9EDCEU, 0xA9F524U, + 0xAA060AU, 0xAA1EE0U, 0xAA2F34U, 0xAA37DEU, 0xAA4C9CU, 0xAA5476U, 0xAA65A2U, 0xAA7D48U, 0xAA8BCCU, 0xAA9326U, + 0xAAA2F2U, 0xAABA18U, 0xAAC15AU, 0xAAD9B0U, 0xAAE864U, 0xAAF08EU, 0xAB056CU, 0xAB1D86U, 0xAB2C52U, 0xAB34B8U, + 0xAB4FFAU, 0xAB5710U, 0xAB66C4U, 0xAB7E2EU, 0xAB88AAU, 0xAB9040U, 0xABA194U, 0xABB97EU, 0xABC23CU, 0xABDAD6U, + 0xABEB02U, 0xABF3E8U, 0xAC0D5EU, 0xAC15B4U, 0xAC2460U, 0xAC3C8AU, 0xAC47C8U, 0xAC5F22U, 0xAC6EF6U, 0xAC761CU, + 0xAC8098U, 0xAC9872U, 0xACA9A6U, 0xACB14CU, 0xACCA0EU, 0xACD2E4U, 0xACE330U, 0xACFBDAU, 0xAD0E38U, 0xAD16D2U, + 0xAD2706U, 0xAD3FECU, 0xAD44AEU, 0xAD5C44U, 0xAD6D90U, 0xAD757AU, 0xAD83FEU, 0xAD9B14U, 0xADAAC0U, 0xADB22AU, + 0xADC968U, 0xADD182U, 0xADE056U, 0xADF8BCU, 0xAE0B92U, 0xAE1378U, 0xAE22ACU, 0xAE3A46U, 0xAE4104U, 0xAE59EEU, + 0xAE683AU, 0xAE70D0U, 0xAE8654U, 0xAE9EBEU, 0xAEAF6AU, 0xAEB780U, 0xAECCC2U, 0xAED428U, 0xAEE5FCU, 0xAEFD16U, + 0xAF08F4U, 0xAF101EU, 0xAF21CAU, 0xAF3920U, 0xAF4262U, 0xAF5A88U, 0xAF6B5CU, 0xAF73B6U, 0xAF8532U, 0xAF9DD8U, + 0xAFAC0CU, 0xAFB4E6U, 0xAFCFA4U, 0xAFD74EU, 0xAFE69AU, 0xAFFE70U, 0xB004A8U, 0xB01C42U, 0xB02D96U, 0xB0357CU, + 0xB04E3EU, 0xB056D4U, 0xB06700U, 0xB07FEAU, 0xB0896EU, 0xB09184U, 0xB0A050U, 0xB0B8BAU, 0xB0C3F8U, 0xB0DB12U, + 0xB0EAC6U, 0xB0F22CU, 0xB107CEU, 0xB11F24U, 0xB12EF0U, 0xB1361AU, 0xB14D58U, 0xB155B2U, 0xB16466U, 0xB17C8CU, + 0xB18A08U, 0xB192E2U, 0xB1A336U, 0xB1BBDCU, 0xB1C09EU, 0xB1D874U, 0xB1E9A0U, 0xB1F14AU, 0xB20264U, 0xB21A8EU, + 0xB22B5AU, 0xB233B0U, 0xB248F2U, 0xB25018U, 0xB261CCU, 0xB27926U, 0xB28FA2U, 0xB29748U, 0xB2A69CU, 0xB2BE76U, + 0xB2C534U, 0xB2DDDEU, 0xB2EC0AU, 0xB2F4E0U, 0xB30102U, 0xB319E8U, 0xB3283CU, 0xB330D6U, 0xB34B94U, 0xB3537EU, + 0xB362AAU, 0xB37A40U, 0xB38CC4U, 0xB3942EU, 0xB3A5FAU, 0xB3BD10U, 0xB3C652U, 0xB3DEB8U, 0xB3EF6CU, 0xB3F786U, + 0xB40930U, 0xB411DAU, 0xB4200EU, 0xB438E4U, 0xB443A6U, 0xB45B4CU, 0xB46A98U, 0xB47272U, 0xB484F6U, 0xB49C1CU, + 0xB4ADC8U, 0xB4B522U, 0xB4CE60U, 0xB4D68AU, 0xB4E75EU, 0xB4FFB4U, 0xB50A56U, 0xB512BCU, 0xB52368U, 0xB53B82U, + 0xB540C0U, 0xB5582AU, 0xB569FEU, 0xB57114U, 0xB58790U, 0xB59F7AU, 0xB5AEAEU, 0xB5B644U, 0xB5CD06U, 0xB5D5ECU, + 0xB5E438U, 0xB5FCD2U, 0xB60FFCU, 0xB61716U, 0xB626C2U, 0xB63E28U, 0xB6456AU, 0xB65D80U, 0xB66C54U, 0xB674BEU, + 0xB6823AU, 0xB69AD0U, 0xB6AB04U, 0xB6B3EEU, 0xB6C8ACU, 0xB6D046U, 0xB6E192U, 0xB6F978U, 0xB70C9AU, 0xB71470U, + 0xB725A4U, 0xB73D4EU, 0xB7460CU, 0xB75EE6U, 0xB76F32U, 0xB777D8U, 0xB7815CU, 0xB799B6U, 0xB7A862U, 0xB7B088U, + 0xB7CBCAU, 0xB7D320U, 0xB7E2F4U, 0xB7FA1EU, 0xB80772U, 0xB81F98U, 0xB82E4CU, 0xB836A6U, 0xB84DE4U, 0xB8550EU, + 0xB864DAU, 0xB87C30U, 0xB88AB4U, 0xB8925EU, 0xB8A38AU, 0xB8BB60U, 0xB8C022U, 0xB8D8C8U, 0xB8E91CU, 0xB8F1F6U, + 0xB90414U, 0xB91CFEU, 0xB92D2AU, 0xB935C0U, 0xB94E82U, 0xB95668U, 0xB967BCU, 0xB97F56U, 0xB989D2U, 0xB99138U, + 0xB9A0ECU, 0xB9B806U, 0xB9C344U, 0xB9DBAEU, 0xB9EA7AU, 0xB9F290U, 0xBA01BEU, 0xBA1954U, 0xBA2880U, 0xBA306AU, + 0xBA4B28U, 0xBA53C2U, 0xBA6216U, 0xBA7AFCU, 0xBA8C78U, 0xBA9492U, 0xBAA546U, 0xBABDACU, 0xBAC6EEU, 0xBADE04U, + 0xBAEFD0U, 0xBAF73AU, 0xBB02D8U, 0xBB1A32U, 0xBB2BE6U, 0xBB330CU, 0xBB484EU, 0xBB50A4U, 0xBB6170U, 0xBB799AU, + 0xBB8F1EU, 0xBB97F4U, 0xBBA620U, 0xBBBECAU, 0xBBC588U, 0xBBDD62U, 0xBBECB6U, 0xBBF45CU, 0xBC0AEAU, 0xBC1200U, + 0xBC23D4U, 0xBC3B3EU, 0xBC407CU, 0xBC5896U, 0xBC6942U, 0xBC71A8U, 0xBC872CU, 0xBC9FC6U, 0xBCAE12U, 0xBCB6F8U, + 0xBCCDBAU, 0xBCD550U, 0xBCE484U, 0xBCFC6EU, 0xBD098CU, 0xBD1166U, 0xBD20B2U, 0xBD3858U, 0xBD431AU, 0xBD5BF0U, + 0xBD6A24U, 0xBD72CEU, 0xBD844AU, 0xBD9CA0U, 0xBDAD74U, 0xBDB59EU, 0xBDCEDCU, 0xBDD636U, 0xBDE7E2U, 0xBDFF08U, + 0xBE0C26U, 0xBE14CCU, 0xBE2518U, 0xBE3DF2U, 0xBE46B0U, 0xBE5E5AU, 0xBE6F8EU, 0xBE7764U, 0xBE81E0U, 0xBE990AU, + 0xBEA8DEU, 0xBEB034U, 0xBECB76U, 0xBED39CU, 0xBEE248U, 0xBEFAA2U, 0xBF0F40U, 0xBF17AAU, 0xBF267EU, 0xBF3E94U, + 0xBF45D6U, 0xBF5D3CU, 0xBF6CE8U, 0xBF7402U, 0xBF8286U, 0xBF9A6CU, 0xBFABB8U, 0xBFB352U, 0xBFC810U, 0xBFD0FAU, + 0xBFE12EU, 0xBFF9C4U, 0xC00A4EU, 0xC012A4U, 0xC02370U, 0xC03B9AU, 0xC040D8U, 0xC05832U, 0xC069E6U, 0xC0710CU, + 0xC08788U, 0xC09F62U, 0xC0AEB6U, 0xC0B65CU, 0xC0CD1EU, 0xC0D5F4U, 0xC0E420U, 0xC0FCCAU, 0xC10928U, 0xC111C2U, + 0xC12016U, 0xC138FCU, 0xC143BEU, 0xC15B54U, 0xC16A80U, 0xC1726AU, 0xC184EEU, 0xC19C04U, 0xC1ADD0U, 0xC1B53AU, + 0xC1CE78U, 0xC1D692U, 0xC1E746U, 0xC1FFACU, 0xC20C82U, 0xC21468U, 0xC225BCU, 0xC23D56U, 0xC24614U, 0xC25EFEU, + 0xC26F2AU, 0xC277C0U, 0xC28144U, 0xC299AEU, 0xC2A87AU, 0xC2B090U, 0xC2CBD2U, 0xC2D338U, 0xC2E2ECU, 0xC2FA06U, + 0xC30FE4U, 0xC3170EU, 0xC326DAU, 0xC33E30U, 0xC34572U, 0xC35D98U, 0xC36C4CU, 0xC374A6U, 0xC38222U, 0xC39AC8U, + 0xC3AB1CU, 0xC3B3F6U, 0xC3C8B4U, 0xC3D05EU, 0xC3E18AU, 0xC3F960U, 0xC407D6U, 0xC41F3CU, 0xC42EE8U, 0xC43602U, + 0xC44D40U, 0xC455AAU, 0xC4647EU, 0xC47C94U, 0xC48A10U, 0xC492FAU, 0xC4A32EU, 0xC4BBC4U, 0xC4C086U, 0xC4D86CU, + 0xC4E9B8U, 0xC4F152U, 0xC504B0U, 0xC51C5AU, 0xC52D8EU, 0xC53564U, 0xC54E26U, 0xC556CCU, 0xC56718U, 0xC57FF2U, + 0xC58976U, 0xC5919CU, 0xC5A048U, 0xC5B8A2U, 0xC5C3E0U, 0xC5DB0AU, 0xC5EADEU, 0xC5F234U, 0xC6011AU, 0xC619F0U, + 0xC62824U, 0xC630CEU, 0xC64B8CU, 0xC65366U, 0xC662B2U, 0xC67A58U, 0xC68CDCU, 0xC69436U, 0xC6A5E2U, 0xC6BD08U, + 0xC6C64AU, 0xC6DEA0U, 0xC6EF74U, 0xC6F79EU, 0xC7027CU, 0xC71A96U, 0xC72B42U, 0xC733A8U, 0xC748EAU, 0xC75000U, + 0xC761D4U, 0xC7793EU, 0xC78FBAU, 0xC79750U, 0xC7A684U, 0xC7BE6EU, 0xC7C52CU, 0xC7DDC6U, 0xC7EC12U, 0xC7F4F8U, + 0xC80994U, 0xC8117EU, 0xC820AAU, 0xC83840U, 0xC84302U, 0xC85BE8U, 0xC86A3CU, 0xC872D6U, 0xC88452U, 0xC89CB8U, + 0xC8AD6CU, 0xC8B586U, 0xC8CEC4U, 0xC8D62EU, 0xC8E7FAU, 0xC8FF10U, 0xC90AF2U, 0xC91218U, 0xC923CCU, 0xC93B26U, + 0xC94064U, 0xC9588EU, 0xC9695AU, 0xC971B0U, 0xC98734U, 0xC99FDEU, 0xC9AE0AU, 0xC9B6E0U, 0xC9CDA2U, 0xC9D548U, + 0xC9E49CU, 0xC9FC76U, 0xCA0F58U, 0xCA17B2U, 0xCA2666U, 0xCA3E8CU, 0xCA45CEU, 0xCA5D24U, 0xCA6CF0U, 0xCA741AU, + 0xCA829EU, 0xCA9A74U, 0xCAABA0U, 0xCAB34AU, 0xCAC808U, 0xCAD0E2U, 0xCAE136U, 0xCAF9DCU, 0xCB0C3EU, 0xCB14D4U, + 0xCB2500U, 0xCB3DEAU, 0xCB46A8U, 0xCB5E42U, 0xCB6F96U, 0xCB777CU, 0xCB81F8U, 0xCB9912U, 0xCBA8C6U, 0xCBB02CU, + 0xCBCB6EU, 0xCBD384U, 0xCBE250U, 0xCBFABAU, 0xCC040CU, 0xCC1CE6U, 0xCC2D32U, 0xCC35D8U, 0xCC4E9AU, 0xCC5670U, + 0xCC67A4U, 0xCC7F4EU, 0xCC89CAU, 0xCC9120U, 0xCCA0F4U, 0xCCB81EU, 0xCCC35CU, 0xCCDBB6U, 0xCCEA62U, 0xCCF288U, + 0xCD076AU, 0xCD1F80U, 0xCD2E54U, 0xCD36BEU, 0xCD4DFCU, 0xCD5516U, 0xCD64C2U, 0xCD7C28U, 0xCD8AACU, 0xCD9246U, + 0xCDA392U, 0xCDBB78U, 0xCDC03AU, 0xCDD8D0U, 0xCDE904U, 0xCDF1EEU, 0xCE02C0U, 0xCE1A2AU, 0xCE2BFEU, 0xCE3314U, + 0xCE4856U, 0xCE50BCU, 0xCE6168U, 0xCE7982U, 0xCE8F06U, 0xCE97ECU, 0xCEA638U, 0xCEBED2U, 0xCEC590U, 0xCEDD7AU, + 0xCEECAEU, 0xCEF444U, 0xCF01A6U, 0xCF194CU, 0xCF2898U, 0xCF3072U, 0xCF4B30U, 0xCF53DAU, 0xCF620EU, 0xCF7AE4U, + 0xCF8C60U, 0xCF948AU, 0xCFA55EU, 0xCFBDB4U, 0xCFC6F6U, 0xCFDE1CU, 0xCFEFC8U, 0xCFF722U, 0xD00DFAU, 0xD01510U, + 0xD024C4U, 0xD03C2EU, 0xD0476CU, 0xD05F86U, 0xD06E52U, 0xD076B8U, 0xD0803CU, 0xD098D6U, 0xD0A902U, 0xD0B1E8U, + 0xD0CAAAU, 0xD0D240U, 0xD0E394U, 0xD0FB7EU, 0xD10E9CU, 0xD11676U, 0xD127A2U, 0xD13F48U, 0xD1440AU, 0xD15CE0U, + 0xD16D34U, 0xD175DEU, 0xD1835AU, 0xD19BB0U, 0xD1AA64U, 0xD1B28EU, 0xD1C9CCU, 0xD1D126U, 0xD1E0F2U, 0xD1F818U, + 0xD20B36U, 0xD213DCU, 0xD22208U, 0xD23AE2U, 0xD241A0U, 0xD2594AU, 0xD2689EU, 0xD27074U, 0xD286F0U, 0xD29E1AU, + 0xD2AFCEU, 0xD2B724U, 0xD2CC66U, 0xD2D48CU, 0xD2E558U, 0xD2FDB2U, 0xD30850U, 0xD310BAU, 0xD3216EU, 0xD33984U, + 0xD342C6U, 0xD35A2CU, 0xD36BF8U, 0xD37312U, 0xD38596U, 0xD39D7CU, 0xD3ACA8U, 0xD3B442U, 0xD3CF00U, 0xD3D7EAU, + 0xD3E63EU, 0xD3FED4U, 0xD40062U, 0xD41888U, 0xD4295CU, 0xD431B6U, 0xD44AF4U, 0xD4521EU, 0xD463CAU, 0xD47B20U, + 0xD48DA4U, 0xD4954EU, 0xD4A49AU, 0xD4BC70U, 0xD4C732U, 0xD4DFD8U, 0xD4EE0CU, 0xD4F6E6U, 0xD50304U, 0xD51BEEU, + 0xD52A3AU, 0xD532D0U, 0xD54992U, 0xD55178U, 0xD560ACU, 0xD57846U, 0xD58EC2U, 0xD59628U, 0xD5A7FCU, 0xD5BF16U, + 0xD5C454U, 0xD5DCBEU, 0xD5ED6AU, 0xD5F580U, 0xD606AEU, 0xD61E44U, 0xD62F90U, 0xD6377AU, 0xD64C38U, 0xD654D2U, + 0xD66506U, 0xD67DECU, 0xD68B68U, 0xD69382U, 0xD6A256U, 0xD6BABCU, 0xD6C1FEU, 0xD6D914U, 0xD6E8C0U, 0xD6F02AU, + 0xD705C8U, 0xD71D22U, 0xD72CF6U, 0xD7341CU, 0xD74F5EU, 0xD757B4U, 0xD76660U, 0xD77E8AU, 0xD7880EU, 0xD790E4U, + 0xD7A130U, 0xD7B9DAU, 0xD7C298U, 0xD7DA72U, 0xD7EBA6U, 0xD7F34CU, 0xD80E20U, 0xD816CAU, 0xD8271EU, 0xD83FF4U, + 0xD844B6U, 0xD85C5CU, 0xD86D88U, 0xD87562U, 0xD883E6U, 0xD89B0CU, 0xD8AAD8U, 0xD8B232U, 0xD8C970U, 0xD8D19AU, + 0xD8E04EU, 0xD8F8A4U, 0xD90D46U, 0xD915ACU, 0xD92478U, 0xD93C92U, 0xD947D0U, 0xD95F3AU, 0xD96EEEU, 0xD97604U, + 0xD98080U, 0xD9986AU, 0xD9A9BEU, 0xD9B154U, 0xD9CA16U, 0xD9D2FCU, 0xD9E328U, 0xD9FBC2U, 0xDA08ECU, 0xDA1006U, + 0xDA21D2U, 0xDA3938U, 0xDA427AU, 0xDA5A90U, 0xDA6B44U, 0xDA73AEU, 0xDA852AU, 0xDA9DC0U, 0xDAAC14U, 0xDAB4FEU, + 0xDACFBCU, 0xDAD756U, 0xDAE682U, 0xDAFE68U, 0xDB0B8AU, 0xDB1360U, 0xDB22B4U, 0xDB3A5EU, 0xDB411CU, 0xDB59F6U, + 0xDB6822U, 0xDB70C8U, 0xDB864CU, 0xDB9EA6U, 0xDBAF72U, 0xDBB798U, 0xDBCCDAU, 0xDBD430U, 0xDBE5E4U, 0xDBFD0EU, + 0xDC03B8U, 0xDC1B52U, 0xDC2A86U, 0xDC326CU, 0xDC492EU, 0xDC51C4U, 0xDC6010U, 0xDC78FAU, 0xDC8E7EU, 0xDC9694U, + 0xDCA740U, 0xDCBFAAU, 0xDCC4E8U, 0xDCDC02U, 0xDCEDD6U, 0xDCF53CU, 0xDD00DEU, 0xDD1834U, 0xDD29E0U, 0xDD310AU, + 0xDD4A48U, 0xDD52A2U, 0xDD6376U, 0xDD7B9CU, 0xDD8D18U, 0xDD95F2U, 0xDDA426U, 0xDDBCCCU, 0xDDC78EU, 0xDDDF64U, + 0xDDEEB0U, 0xDDF65AU, 0xDE0574U, 0xDE1D9EU, 0xDE2C4AU, 0xDE34A0U, 0xDE4FE2U, 0xDE5708U, 0xDE66DCU, 0xDE7E36U, + 0xDE88B2U, 0xDE9058U, 0xDEA18CU, 0xDEB966U, 0xDEC224U, 0xDEDACEU, 0xDEEB1AU, 0xDEF3F0U, 0xDF0612U, 0xDF1EF8U, + 0xDF2F2CU, 0xDF37C6U, 0xDF4C84U, 0xDF546EU, 0xDF65BAU, 0xDF7D50U, 0xDF8BD4U, 0xDF933EU, 0xDFA2EAU, 0xDFBA00U, + 0xDFC142U, 0xDFD9A8U, 0xDFE87CU, 0xDFF096U, 0xE00526U, 0xE01DCCU, 0xE02C18U, 0xE034F2U, 0xE04FB0U, 0xE0575AU, + 0xE0668EU, 0xE07E64U, 0xE088E0U, 0xE0900AU, 0xE0A1DEU, 0xE0B934U, 0xE0C276U, 0xE0DA9CU, 0xE0EB48U, 0xE0F3A2U, + 0xE10640U, 0xE11EAAU, 0xE12F7EU, 0xE13794U, 0xE14CD6U, 0xE1543CU, 0xE165E8U, 0xE17D02U, 0xE18B86U, 0xE1936CU, + 0xE1A2B8U, 0xE1BA52U, 0xE1C110U, 0xE1D9FAU, 0xE1E82EU, 0xE1F0C4U, 0xE203EAU, 0xE21B00U, 0xE22AD4U, 0xE2323EU, + 0xE2497CU, 0xE25196U, 0xE26042U, 0xE278A8U, 0xE28E2CU, 0xE296C6U, 0xE2A712U, 0xE2BFF8U, 0xE2C4BAU, 0xE2DC50U, + 0xE2ED84U, 0xE2F56EU, 0xE3008CU, 0xE31866U, 0xE329B2U, 0xE33158U, 0xE34A1AU, 0xE352F0U, 0xE36324U, 0xE37BCEU, + 0xE38D4AU, 0xE395A0U, 0xE3A474U, 0xE3BC9EU, 0xE3C7DCU, 0xE3DF36U, 0xE3EEE2U, 0xE3F608U, 0xE408BEU, 0xE41054U, + 0xE42180U, 0xE4396AU, 0xE44228U, 0xE45AC2U, 0xE46B16U, 0xE473FCU, 0xE48578U, 0xE49D92U, 0xE4AC46U, 0xE4B4ACU, + 0xE4CFEEU, 0xE4D704U, 0xE4E6D0U, 0xE4FE3AU, 0xE50BD8U, 0xE51332U, 0xE522E6U, 0xE53A0CU, 0xE5414EU, 0xE559A4U, + 0xE56870U, 0xE5709AU, 0xE5861EU, 0xE59EF4U, 0xE5AF20U, 0xE5B7CAU, 0xE5CC88U, 0xE5D462U, 0xE5E5B6U, 0xE5FD5CU, + 0xE60E72U, 0xE61698U, 0xE6274CU, 0xE63FA6U, 0xE644E4U, 0xE65C0EU, 0xE66DDAU, 0xE67530U, 0xE683B4U, 0xE69B5EU, + 0xE6AA8AU, 0xE6B260U, 0xE6C922U, 0xE6D1C8U, 0xE6E01CU, 0xE6F8F6U, 0xE70D14U, 0xE715FEU, 0xE7242AU, 0xE73CC0U, + 0xE74782U, 0xE75F68U, 0xE76EBCU, 0xE77656U, 0xE780D2U, 0xE79838U, 0xE7A9ECU, 0xE7B106U, 0xE7CA44U, 0xE7D2AEU, + 0xE7E37AU, 0xE7FB90U, 0xE806FCU, 0xE81E16U, 0xE82FC2U, 0xE83728U, 0xE84C6AU, 0xE85480U, 0xE86554U, 0xE87DBEU, + 0xE88B3AU, 0xE893D0U, 0xE8A204U, 0xE8BAEEU, 0xE8C1ACU, 0xE8D946U, 0xE8E892U, 0xE8F078U, 0xE9059AU, 0xE91D70U, + 0xE92CA4U, 0xE9344EU, 0xE94F0CU, 0xE957E6U, 0xE96632U, 0xE97ED8U, 0xE9885CU, 0xE990B6U, 0xE9A162U, 0xE9B988U, + 0xE9C2CAU, 0xE9DA20U, 0xE9EBF4U, 0xE9F31EU, 0xEA0030U, 0xEA18DAU, 0xEA290EU, 0xEA31E4U, 0xEA4AA6U, 0xEA524CU, + 0xEA6398U, 0xEA7B72U, 0xEA8DF6U, 0xEA951CU, 0xEAA4C8U, 0xEABC22U, 0xEAC760U, 0xEADF8AU, 0xEAEE5EU, 0xEAF6B4U, + 0xEB0356U, 0xEB1BBCU, 0xEB2A68U, 0xEB3282U, 0xEB49C0U, 0xEB512AU, 0xEB60FEU, 0xEB7814U, 0xEB8E90U, 0xEB967AU, + 0xEBA7AEU, 0xEBBF44U, 0xEBC406U, 0xEBDCECU, 0xEBED38U, 0xEBF5D2U, 0xEC0B64U, 0xEC138EU, 0xEC225AU, 0xEC3AB0U, + 0xEC41F2U, 0xEC5918U, 0xEC68CCU, 0xEC7026U, 0xEC86A2U, 0xEC9E48U, 0xECAF9CU, 0xECB776U, 0xECCC34U, 0xECD4DEU, + 0xECE50AU, 0xECFDE0U, 0xED0802U, 0xED10E8U, 0xED213CU, 0xED39D6U, 0xED4294U, 0xED5A7EU, 0xED6BAAU, 0xED7340U, + 0xED85C4U, 0xED9D2EU, 0xEDACFAU, 0xEDB410U, 0xEDCF52U, 0xEDD7B8U, 0xEDE66CU, 0xEDFE86U, 0xEE0DA8U, 0xEE1542U, + 0xEE2496U, 0xEE3C7CU, 0xEE473EU, 0xEE5FD4U, 0xEE6E00U, 0xEE76EAU, 0xEE806EU, 0xEE9884U, 0xEEA950U, 0xEEB1BAU, + 0xEECAF8U, 0xEED212U, 0xEEE3C6U, 0xEEFB2CU, 0xEF0ECEU, 0xEF1624U, 0xEF27F0U, 0xEF3F1AU, 0xEF4458U, 0xEF5CB2U, + 0xEF6D66U, 0xEF758CU, 0xEF8308U, 0xEF9BE2U, 0xEFAA36U, 0xEFB2DCU, 0xEFC99EU, 0xEFD174U, 0xEFE0A0U, 0xEFF84AU, + 0xF00292U, 0xF01A78U, 0xF02BACU, 0xF03346U, 0xF04804U, 0xF050EEU, 0xF0613AU, 0xF079D0U, 0xF08F54U, 0xF097BEU, + 0xF0A66AU, 0xF0BE80U, 0xF0C5C2U, 0xF0DD28U, 0xF0ECFCU, 0xF0F416U, 0xF101F4U, 0xF1191EU, 0xF128CAU, 0xF13020U, + 0xF14B62U, 0xF15388U, 0xF1625CU, 0xF17AB6U, 0xF18C32U, 0xF194D8U, 0xF1A50CU, 0xF1BDE6U, 0xF1C6A4U, 0xF1DE4EU, + 0xF1EF9AU, 0xF1F770U, 0xF2045EU, 0xF21CB4U, 0xF22D60U, 0xF2358AU, 0xF24EC8U, 0xF25622U, 0xF267F6U, 0xF27F1CU, + 0xF28998U, 0xF29172U, 0xF2A0A6U, 0xF2B84CU, 0xF2C30EU, 0xF2DBE4U, 0xF2EA30U, 0xF2F2DAU, 0xF30738U, 0xF31FD2U, + 0xF32E06U, 0xF336ECU, 0xF34DAEU, 0xF35544U, 0xF36490U, 0xF37C7AU, 0xF38AFEU, 0xF39214U, 0xF3A3C0U, 0xF3BB2AU, + 0xF3C068U, 0xF3D882U, 0xF3E956U, 0xF3F1BCU, 0xF40F0AU, 0xF417E0U, 0xF42634U, 0xF43EDEU, 0xF4459CU, 0xF45D76U, + 0xF46CA2U, 0xF47448U, 0xF482CCU, 0xF49A26U, 0xF4ABF2U, 0xF4B318U, 0xF4C85AU, 0xF4D0B0U, 0xF4E164U, 0xF4F98EU, + 0xF50C6CU, 0xF51486U, 0xF52552U, 0xF53DB8U, 0xF546FAU, 0xF55E10U, 0xF56FC4U, 0xF5772EU, 0xF581AAU, 0xF59940U, + 0xF5A894U, 0xF5B07EU, 0xF5CB3CU, 0xF5D3D6U, 0xF5E202U, 0xF5FAE8U, 0xF609C6U, 0xF6112CU, 0xF620F8U, 0xF63812U, + 0xF64350U, 0xF65BBAU, 0xF66A6EU, 0xF67284U, 0xF68400U, 0xF69CEAU, 0xF6AD3EU, 0xF6B5D4U, 0xF6CE96U, 0xF6D67CU, + 0xF6E7A8U, 0xF6FF42U, 0xF70AA0U, 0xF7124AU, 0xF7239EU, 0xF73B74U, 0xF74036U, 0xF758DCU, 0xF76908U, 0xF771E2U, + 0xF78766U, 0xF79F8CU, 0xF7AE58U, 0xF7B6B2U, 0xF7CDF0U, 0xF7D51AU, 0xF7E4CEU, 0xF7FC24U, 0xF80148U, 0xF819A2U, + 0xF82876U, 0xF8309CU, 0xF84BDEU, 0xF85334U, 0xF862E0U, 0xF87A0AU, 0xF88C8EU, 0xF89464U, 0xF8A5B0U, 0xF8BD5AU, + 0xF8C618U, 0xF8DEF2U, 0xF8EF26U, 0xF8F7CCU, 0xF9022EU, 0xF91AC4U, 0xF92B10U, 0xF933FAU, 0xF948B8U, 0xF95052U, + 0xF96186U, 0xF9796CU, 0xF98FE8U, 0xF99702U, 0xF9A6D6U, 0xF9BE3CU, 0xF9C57EU, 0xF9DD94U, 0xF9EC40U, 0xF9F4AAU, + 0xFA0784U, 0xFA1F6EU, 0xFA2EBAU, 0xFA3650U, 0xFA4D12U, 0xFA55F8U, 0xFA642CU, 0xFA7CC6U, 0xFA8A42U, 0xFA92A8U, + 0xFAA37CU, 0xFABB96U, 0xFAC0D4U, 0xFAD83EU, 0xFAE9EAU, 0xFAF100U, 0xFB04E2U, 0xFB1C08U, 0xFB2DDCU, 0xFB3536U, + 0xFB4E74U, 0xFB569EU, 0xFB674AU, 0xFB7FA0U, 0xFB8924U, 0xFB91CEU, 0xFBA01AU, 0xFBB8F0U, 0xFBC3B2U, 0xFBDB58U, + 0xFBEA8CU, 0xFBF266U, 0xFC0CD0U, 0xFC143AU, 0xFC25EEU, 0xFC3D04U, 0xFC4646U, 0xFC5EACU, 0xFC6F78U, 0xFC7792U, + 0xFC8116U, 0xFC99FCU, 0xFCA828U, 0xFCB0C2U, 0xFCCB80U, 0xFCD36AU, 0xFCE2BEU, 0xFCFA54U, 0xFD0FB6U, 0xFD175CU, + 0xFD2688U, 0xFD3E62U, 0xFD4520U, 0xFD5DCAU, 0xFD6C1EU, 0xFD74F4U, 0xFD8270U, 0xFD9A9AU, 0xFDAB4EU, 0xFDB3A4U, + 0xFDC8E6U, 0xFDD00CU, 0xFDE1D8U, 0xFDF932U, 0xFE0A1CU, 0xFE12F6U, 0xFE2322U, 0xFE3BC8U, 0xFE408AU, 0xFE5860U, + 0xFE69B4U, 0xFE715EU, 0xFE87DAU, 0xFE9F30U, 0xFEAEE4U, 0xFEB60EU, 0xFECD4CU, 0xFED5A6U, 0xFEE472U, 0xFEFC98U, + 0xFF097AU, 0xFF1190U, 0xFF2044U, 0xFF38AEU, 0xFF43ECU, 0xFF5B06U, 0xFF6AD2U, 0xFF7238U, 0xFF84BCU, 0xFF9C56U, + 0xFFAD82U, 0xFFB568U, 0xFFCE2AU, 0xFFD6C0U, 0xFFE714U, 0xFFFFFEU +}; -static const unsigned int ENCODING_TABLE_24128[] = { - 0x000000U, 0x0018EBU, 0x00293EU, 0x0031D5U, 0x004A97U, 0x00527CU, 0x0063A9U, 0x007B42U, 0x008DC6U, 0x00952DU, - 0x00A4F8U, 0x00BC13U, 0x00C751U, 0x00DFBAU, 0x00EE6FU, 0x00F684U, 0x010367U, 0x011B8CU, 0x012A59U, 0x0132B2U, - 0x0149F0U, 0x01511BU, 0x0160CEU, 0x017825U, 0x018EA1U, 0x01964AU, 0x01A79FU, 0x01BF74U, 0x01C436U, 0x01DCDDU, - 0x01ED08U, 0x01F5E3U, 0x0206CDU, 0x021E26U, 0x022FF3U, 0x023718U, 0x024C5AU, 0x0254B1U, 0x026564U, 0x027D8FU, - 0x028B0BU, 0x0293E0U, 0x02A235U, 0x02BADEU, 0x02C19CU, 0x02D977U, 0x02E8A2U, 0x02F049U, 0x0305AAU, 0x031D41U, - 0x032C94U, 0x03347FU, 0x034F3DU, 0x0357D6U, 0x036603U, 0x037EE8U, 0x03886CU, 0x039087U, 0x03A152U, 0x03B9B9U, - 0x03C2FBU, 0x03DA10U, 0x03EBC5U, 0x03F32EU, 0x040D99U, 0x041572U, 0x0424A7U, 0x043C4CU, 0x04470EU, 0x045FE5U, - 0x046E30U, 0x0476DBU, 0x04805FU, 0x0498B4U, 0x04A961U, 0x04B18AU, 0x04CAC8U, 0x04D223U, 0x04E3F6U, 0x04FB1DU, - 0x050EFEU, 0x051615U, 0x0527C0U, 0x053F2BU, 0x054469U, 0x055C82U, 0x056D57U, 0x0575BCU, 0x058338U, 0x059BD3U, - 0x05AA06U, 0x05B2EDU, 0x05C9AFU, 0x05D144U, 0x05E091U, 0x05F87AU, 0x060B54U, 0x0613BFU, 0x06226AU, 0x063A81U, - 0x0641C3U, 0x065928U, 0x0668FDU, 0x067016U, 0x068692U, 0x069E79U, 0x06AFACU, 0x06B747U, 0x06CC05U, 0x06D4EEU, - 0x06E53BU, 0x06FDD0U, 0x070833U, 0x0710D8U, 0x07210DU, 0x0739E6U, 0x0742A4U, 0x075A4FU, 0x076B9AU, 0x077371U, - 0x0785F5U, 0x079D1EU, 0x07ACCBU, 0x07B420U, 0x07CF62U, 0x07D789U, 0x07E65CU, 0x07FEB7U, 0x0803DAU, 0x081B31U, - 0x082AE4U, 0x08320FU, 0x08494DU, 0x0851A6U, 0x086073U, 0x087898U, 0x088E1CU, 0x0896F7U, 0x08A722U, 0x08BFC9U, - 0x08C48BU, 0x08DC60U, 0x08EDB5U, 0x08F55EU, 0x0900BDU, 0x091856U, 0x092983U, 0x093168U, 0x094A2AU, 0x0952C1U, - 0x096314U, 0x097BFFU, 0x098D7BU, 0x099590U, 0x09A445U, 0x09BCAEU, 0x09C7ECU, 0x09DF07U, 0x09EED2U, 0x09F639U, - 0x0A0517U, 0x0A1DFCU, 0x0A2C29U, 0x0A34C2U, 0x0A4F80U, 0x0A576BU, 0x0A66BEU, 0x0A7E55U, 0x0A88D1U, 0x0A903AU, - 0x0AA1EFU, 0x0AB904U, 0x0AC246U, 0x0ADAADU, 0x0AEB78U, 0x0AF393U, 0x0B0670U, 0x0B1E9BU, 0x0B2F4EU, 0x0B37A5U, - 0x0B4CE7U, 0x0B540CU, 0x0B65D9U, 0x0B7D32U, 0x0B8BB6U, 0x0B935DU, 0x0BA288U, 0x0BBA63U, 0x0BC121U, 0x0BD9CAU, - 0x0BE81FU, 0x0BF0F4U, 0x0C0E43U, 0x0C16A8U, 0x0C277DU, 0x0C3F96U, 0x0C44D4U, 0x0C5C3FU, 0x0C6DEAU, 0x0C7501U, - 0x0C8385U, 0x0C9B6EU, 0x0CAABBU, 0x0CB250U, 0x0CC912U, 0x0CD1F9U, 0x0CE02CU, 0x0CF8C7U, 0x0D0D24U, 0x0D15CFU, - 0x0D241AU, 0x0D3CF1U, 0x0D47B3U, 0x0D5F58U, 0x0D6E8DU, 0x0D7666U, 0x0D80E2U, 0x0D9809U, 0x0DA9DCU, 0x0DB137U, - 0x0DCA75U, 0x0DD29EU, 0x0DE34BU, 0x0DFBA0U, 0x0E088EU, 0x0E1065U, 0x0E21B0U, 0x0E395BU, 0x0E4219U, 0x0E5AF2U, - 0x0E6B27U, 0x0E73CCU, 0x0E8548U, 0x0E9DA3U, 0x0EAC76U, 0x0EB49DU, 0x0ECFDFU, 0x0ED734U, 0x0EE6E1U, 0x0EFE0AU, - 0x0F0BE9U, 0x0F1302U, 0x0F22D7U, 0x0F3A3CU, 0x0F417EU, 0x0F5995U, 0x0F6840U, 0x0F70ABU, 0x0F862FU, 0x0F9EC4U, - 0x0FAF11U, 0x0FB7FAU, 0x0FCCB8U, 0x0FD453U, 0x0FE586U, 0x0FFD6DU, 0x1007B4U, 0x101F5FU, 0x102E8AU, 0x103661U, - 0x104D23U, 0x1055C8U, 0x10641DU, 0x107CF6U, 0x108A72U, 0x109299U, 0x10A34CU, 0x10BBA7U, 0x10C0E5U, 0x10D80EU, - 0x10E9DBU, 0x10F130U, 0x1104D3U, 0x111C38U, 0x112DEDU, 0x113506U, 0x114E44U, 0x1156AFU, 0x11677AU, 0x117F91U, - 0x118915U, 0x1191FEU, 0x11A02BU, 0x11B8C0U, 0x11C382U, 0x11DB69U, 0x11EABCU, 0x11F257U, 0x120179U, 0x121992U, - 0x122847U, 0x1230ACU, 0x124BEEU, 0x125305U, 0x1262D0U, 0x127A3BU, 0x128CBFU, 0x129454U, 0x12A581U, 0x12BD6AU, - 0x12C628U, 0x12DEC3U, 0x12EF16U, 0x12F7FDU, 0x13021EU, 0x131AF5U, 0x132B20U, 0x1333CBU, 0x134889U, 0x135062U, - 0x1361B7U, 0x13795CU, 0x138FD8U, 0x139733U, 0x13A6E6U, 0x13BE0DU, 0x13C54FU, 0x13DDA4U, 0x13EC71U, 0x13F49AU, - 0x140A2DU, 0x1412C6U, 0x142313U, 0x143BF8U, 0x1440BAU, 0x145851U, 0x146984U, 0x14716FU, 0x1487EBU, 0x149F00U, - 0x14AED5U, 0x14B63EU, 0x14CD7CU, 0x14D597U, 0x14E442U, 0x14FCA9U, 0x15094AU, 0x1511A1U, 0x152074U, 0x15389FU, - 0x1543DDU, 0x155B36U, 0x156AE3U, 0x157208U, 0x15848CU, 0x159C67U, 0x15ADB2U, 0x15B559U, 0x15CE1BU, 0x15D6F0U, - 0x15E725U, 0x15FFCEU, 0x160CE0U, 0x16140BU, 0x1625DEU, 0x163D35U, 0x164677U, 0x165E9CU, 0x166F49U, 0x1677A2U, - 0x168126U, 0x1699CDU, 0x16A818U, 0x16B0F3U, 0x16CBB1U, 0x16D35AU, 0x16E28FU, 0x16FA64U, 0x170F87U, 0x17176CU, - 0x1726B9U, 0x173E52U, 0x174510U, 0x175DFBU, 0x176C2EU, 0x1774C5U, 0x178241U, 0x179AAAU, 0x17AB7FU, 0x17B394U, - 0x17C8D6U, 0x17D03DU, 0x17E1E8U, 0x17F903U, 0x18046EU, 0x181C85U, 0x182D50U, 0x1835BBU, 0x184EF9U, 0x185612U, - 0x1867C7U, 0x187F2CU, 0x1889A8U, 0x189143U, 0x18A096U, 0x18B87DU, 0x18C33FU, 0x18DBD4U, 0x18EA01U, 0x18F2EAU, - 0x190709U, 0x191FE2U, 0x192E37U, 0x1936DCU, 0x194D9EU, 0x195575U, 0x1964A0U, 0x197C4BU, 0x198ACFU, 0x199224U, - 0x19A3F1U, 0x19BB1AU, 0x19C058U, 0x19D8B3U, 0x19E966U, 0x19F18DU, 0x1A02A3U, 0x1A1A48U, 0x1A2B9DU, 0x1A3376U, - 0x1A4834U, 0x1A50DFU, 0x1A610AU, 0x1A79E1U, 0x1A8F65U, 0x1A978EU, 0x1AA65BU, 0x1ABEB0U, 0x1AC5F2U, 0x1ADD19U, - 0x1AECCCU, 0x1AF427U, 0x1B01C4U, 0x1B192FU, 0x1B28FAU, 0x1B3011U, 0x1B4B53U, 0x1B53B8U, 0x1B626DU, 0x1B7A86U, - 0x1B8C02U, 0x1B94E9U, 0x1BA53CU, 0x1BBDD7U, 0x1BC695U, 0x1BDE7EU, 0x1BEFABU, 0x1BF740U, 0x1C09F7U, 0x1C111CU, - 0x1C20C9U, 0x1C3822U, 0x1C4360U, 0x1C5B8BU, 0x1C6A5EU, 0x1C72B5U, 0x1C8431U, 0x1C9CDAU, 0x1CAD0FU, 0x1CB5E4U, - 0x1CCEA6U, 0x1CD64DU, 0x1CE798U, 0x1CFF73U, 0x1D0A90U, 0x1D127BU, 0x1D23AEU, 0x1D3B45U, 0x1D4007U, 0x1D58ECU, - 0x1D6939U, 0x1D71D2U, 0x1D8756U, 0x1D9FBDU, 0x1DAE68U, 0x1DB683U, 0x1DCDC1U, 0x1DD52AU, 0x1DE4FFU, 0x1DFC14U, - 0x1E0F3AU, 0x1E17D1U, 0x1E2604U, 0x1E3EEFU, 0x1E45ADU, 0x1E5D46U, 0x1E6C93U, 0x1E7478U, 0x1E82FCU, 0x1E9A17U, - 0x1EABC2U, 0x1EB329U, 0x1EC86BU, 0x1ED080U, 0x1EE155U, 0x1EF9BEU, 0x1F0C5DU, 0x1F14B6U, 0x1F2563U, 0x1F3D88U, - 0x1F46CAU, 0x1F5E21U, 0x1F6FF4U, 0x1F771FU, 0x1F819BU, 0x1F9970U, 0x1FA8A5U, 0x1FB04EU, 0x1FCB0CU, 0x1FD3E7U, - 0x1FE232U, 0x1FFAD9U, 0x200F68U, 0x201783U, 0x202656U, 0x203EBDU, 0x2045FFU, 0x205D14U, 0x206CC1U, 0x20742AU, - 0x2082AEU, 0x209A45U, 0x20AB90U, 0x20B37BU, 0x20C839U, 0x20D0D2U, 0x20E107U, 0x20F9ECU, 0x210C0FU, 0x2114E4U, - 0x212531U, 0x213DDAU, 0x214698U, 0x215E73U, 0x216FA6U, 0x21774DU, 0x2181C9U, 0x219922U, 0x21A8F7U, 0x21B01CU, - 0x21CB5EU, 0x21D3B5U, 0x21E260U, 0x21FA8BU, 0x2209A5U, 0x22114EU, 0x22209BU, 0x223870U, 0x224332U, 0x225BD9U, - 0x226A0CU, 0x2272E7U, 0x228463U, 0x229C88U, 0x22AD5DU, 0x22B5B6U, 0x22CEF4U, 0x22D61FU, 0x22E7CAU, 0x22FF21U, - 0x230AC2U, 0x231229U, 0x2323FCU, 0x233B17U, 0x234055U, 0x2358BEU, 0x23696BU, 0x237180U, 0x238704U, 0x239FEFU, - 0x23AE3AU, 0x23B6D1U, 0x23CD93U, 0x23D578U, 0x23E4ADU, 0x23FC46U, 0x2402F1U, 0x241A1AU, 0x242BCFU, 0x243324U, - 0x244866U, 0x24508DU, 0x246158U, 0x2479B3U, 0x248F37U, 0x2497DCU, 0x24A609U, 0x24BEE2U, 0x24C5A0U, 0x24DD4BU, - 0x24EC9EU, 0x24F475U, 0x250196U, 0x25197DU, 0x2528A8U, 0x253043U, 0x254B01U, 0x2553EAU, 0x25623FU, 0x257AD4U, - 0x258C50U, 0x2594BBU, 0x25A56EU, 0x25BD85U, 0x25C6C7U, 0x25DE2CU, 0x25EFF9U, 0x25F712U, 0x26043CU, 0x261CD7U, - 0x262D02U, 0x2635E9U, 0x264EABU, 0x265640U, 0x266795U, 0x267F7EU, 0x2689FAU, 0x269111U, 0x26A0C4U, 0x26B82FU, - 0x26C36DU, 0x26DB86U, 0x26EA53U, 0x26F2B8U, 0x27075BU, 0x271FB0U, 0x272E65U, 0x27368EU, 0x274DCCU, 0x275527U, - 0x2764F2U, 0x277C19U, 0x278A9DU, 0x279276U, 0x27A3A3U, 0x27BB48U, 0x27C00AU, 0x27D8E1U, 0x27E934U, 0x27F1DFU, - 0x280CB2U, 0x281459U, 0x28258CU, 0x283D67U, 0x284625U, 0x285ECEU, 0x286F1BU, 0x2877F0U, 0x288174U, 0x28999FU, - 0x28A84AU, 0x28B0A1U, 0x28CBE3U, 0x28D308U, 0x28E2DDU, 0x28FA36U, 0x290FD5U, 0x29173EU, 0x2926EBU, 0x293E00U, - 0x294542U, 0x295DA9U, 0x296C7CU, 0x297497U, 0x298213U, 0x299AF8U, 0x29AB2DU, 0x29B3C6U, 0x29C884U, 0x29D06FU, - 0x29E1BAU, 0x29F951U, 0x2A0A7FU, 0x2A1294U, 0x2A2341U, 0x2A3BAAU, 0x2A40E8U, 0x2A5803U, 0x2A69D6U, 0x2A713DU, - 0x2A87B9U, 0x2A9F52U, 0x2AAE87U, 0x2AB66CU, 0x2ACD2EU, 0x2AD5C5U, 0x2AE410U, 0x2AFCFBU, 0x2B0918U, 0x2B11F3U, - 0x2B2026U, 0x2B38CDU, 0x2B438FU, 0x2B5B64U, 0x2B6AB1U, 0x2B725AU, 0x2B84DEU, 0x2B9C35U, 0x2BADE0U, 0x2BB50BU, - 0x2BCE49U, 0x2BD6A2U, 0x2BE777U, 0x2BFF9CU, 0x2C012BU, 0x2C19C0U, 0x2C2815U, 0x2C30FEU, 0x2C4BBCU, 0x2C5357U, - 0x2C6282U, 0x2C7A69U, 0x2C8CEDU, 0x2C9406U, 0x2CA5D3U, 0x2CBD38U, 0x2CC67AU, 0x2CDE91U, 0x2CEF44U, 0x2CF7AFU, - 0x2D024CU, 0x2D1AA7U, 0x2D2B72U, 0x2D3399U, 0x2D48DBU, 0x2D5030U, 0x2D61E5U, 0x2D790EU, 0x2D8F8AU, 0x2D9761U, - 0x2DA6B4U, 0x2DBE5FU, 0x2DC51DU, 0x2DDDF6U, 0x2DEC23U, 0x2DF4C8U, 0x2E07E6U, 0x2E1F0DU, 0x2E2ED8U, 0x2E3633U, - 0x2E4D71U, 0x2E559AU, 0x2E644FU, 0x2E7CA4U, 0x2E8A20U, 0x2E92CBU, 0x2EA31EU, 0x2EBBF5U, 0x2EC0B7U, 0x2ED85CU, - 0x2EE989U, 0x2EF162U, 0x2F0481U, 0x2F1C6AU, 0x2F2DBFU, 0x2F3554U, 0x2F4E16U, 0x2F56FDU, 0x2F6728U, 0x2F7FC3U, - 0x2F8947U, 0x2F91ACU, 0x2FA079U, 0x2FB892U, 0x2FC3D0U, 0x2FDB3BU, 0x2FEAEEU, 0x2FF205U, 0x3008DCU, 0x301037U, - 0x3021E2U, 0x303909U, 0x30424BU, 0x305AA0U, 0x306B75U, 0x30739EU, 0x30851AU, 0x309DF1U, 0x30AC24U, 0x30B4CFU, - 0x30CF8DU, 0x30D766U, 0x30E6B3U, 0x30FE58U, 0x310BBBU, 0x311350U, 0x312285U, 0x313A6EU, 0x31412CU, 0x3159C7U, - 0x316812U, 0x3170F9U, 0x31867DU, 0x319E96U, 0x31AF43U, 0x31B7A8U, 0x31CCEAU, 0x31D401U, 0x31E5D4U, 0x31FD3FU, - 0x320E11U, 0x3216FAU, 0x32272FU, 0x323FC4U, 0x324486U, 0x325C6DU, 0x326DB8U, 0x327553U, 0x3283D7U, 0x329B3CU, - 0x32AAE9U, 0x32B202U, 0x32C940U, 0x32D1ABU, 0x32E07EU, 0x32F895U, 0x330D76U, 0x33159DU, 0x332448U, 0x333CA3U, - 0x3347E1U, 0x335F0AU, 0x336EDFU, 0x337634U, 0x3380B0U, 0x33985BU, 0x33A98EU, 0x33B165U, 0x33CA27U, 0x33D2CCU, - 0x33E319U, 0x33FBF2U, 0x340545U, 0x341DAEU, 0x342C7BU, 0x343490U, 0x344FD2U, 0x345739U, 0x3466ECU, 0x347E07U, - 0x348883U, 0x349068U, 0x34A1BDU, 0x34B956U, 0x34C214U, 0x34DAFFU, 0x34EB2AU, 0x34F3C1U, 0x350622U, 0x351EC9U, - 0x352F1CU, 0x3537F7U, 0x354CB5U, 0x35545EU, 0x35658BU, 0x357D60U, 0x358BE4U, 0x35930FU, 0x35A2DAU, 0x35BA31U, - 0x35C173U, 0x35D998U, 0x35E84DU, 0x35F0A6U, 0x360388U, 0x361B63U, 0x362AB6U, 0x36325DU, 0x36491FU, 0x3651F4U, - 0x366021U, 0x3678CAU, 0x368E4EU, 0x3696A5U, 0x36A770U, 0x36BF9BU, 0x36C4D9U, 0x36DC32U, 0x36EDE7U, 0x36F50CU, - 0x3700EFU, 0x371804U, 0x3729D1U, 0x37313AU, 0x374A78U, 0x375293U, 0x376346U, 0x377BADU, 0x378D29U, 0x3795C2U, - 0x37A417U, 0x37BCFCU, 0x37C7BEU, 0x37DF55U, 0x37EE80U, 0x37F66BU, 0x380B06U, 0x3813EDU, 0x382238U, 0x383AD3U, - 0x384191U, 0x38597AU, 0x3868AFU, 0x387044U, 0x3886C0U, 0x389E2BU, 0x38AFFEU, 0x38B715U, 0x38CC57U, 0x38D4BCU, - 0x38E569U, 0x38FD82U, 0x390861U, 0x39108AU, 0x39215FU, 0x3939B4U, 0x3942F6U, 0x395A1DU, 0x396BC8U, 0x397323U, - 0x3985A7U, 0x399D4CU, 0x39AC99U, 0x39B472U, 0x39CF30U, 0x39D7DBU, 0x39E60EU, 0x39FEE5U, 0x3A0DCBU, 0x3A1520U, - 0x3A24F5U, 0x3A3C1EU, 0x3A475CU, 0x3A5FB7U, 0x3A6E62U, 0x3A7689U, 0x3A800DU, 0x3A98E6U, 0x3AA933U, 0x3AB1D8U, - 0x3ACA9AU, 0x3AD271U, 0x3AE3A4U, 0x3AFB4FU, 0x3B0EACU, 0x3B1647U, 0x3B2792U, 0x3B3F79U, 0x3B443BU, 0x3B5CD0U, - 0x3B6D05U, 0x3B75EEU, 0x3B836AU, 0x3B9B81U, 0x3BAA54U, 0x3BB2BFU, 0x3BC9FDU, 0x3BD116U, 0x3BE0C3U, 0x3BF828U, - 0x3C069FU, 0x3C1E74U, 0x3C2FA1U, 0x3C374AU, 0x3C4C08U, 0x3C54E3U, 0x3C6536U, 0x3C7DDDU, 0x3C8B59U, 0x3C93B2U, - 0x3CA267U, 0x3CBA8CU, 0x3CC1CEU, 0x3CD925U, 0x3CE8F0U, 0x3CF01BU, 0x3D05F8U, 0x3D1D13U, 0x3D2CC6U, 0x3D342DU, - 0x3D4F6FU, 0x3D5784U, 0x3D6651U, 0x3D7EBAU, 0x3D883EU, 0x3D90D5U, 0x3DA100U, 0x3DB9EBU, 0x3DC2A9U, 0x3DDA42U, - 0x3DEB97U, 0x3DF37CU, 0x3E0052U, 0x3E18B9U, 0x3E296CU, 0x3E3187U, 0x3E4AC5U, 0x3E522EU, 0x3E63FBU, 0x3E7B10U, - 0x3E8D94U, 0x3E957FU, 0x3EA4AAU, 0x3EBC41U, 0x3EC703U, 0x3EDFE8U, 0x3EEE3DU, 0x3EF6D6U, 0x3F0335U, 0x3F1BDEU, - 0x3F2A0BU, 0x3F32E0U, 0x3F49A2U, 0x3F5149U, 0x3F609CU, 0x3F7877U, 0x3F8EF3U, 0x3F9618U, 0x3FA7CDU, 0x3FBF26U, - 0x3FC464U, 0x3FDC8FU, 0x3FED5AU, 0x3FF5B1U, 0x40063BU, 0x401ED0U, 0x402F05U, 0x4037EEU, 0x404CACU, 0x405447U, - 0x406592U, 0x407D79U, 0x408BFDU, 0x409316U, 0x40A2C3U, 0x40BA28U, 0x40C16AU, 0x40D981U, 0x40E854U, 0x40F0BFU, - 0x41055CU, 0x411DB7U, 0x412C62U, 0x413489U, 0x414FCBU, 0x415720U, 0x4166F5U, 0x417E1EU, 0x41889AU, 0x419071U, - 0x41A1A4U, 0x41B94FU, 0x41C20DU, 0x41DAE6U, 0x41EB33U, 0x41F3D8U, 0x4200F6U, 0x42181DU, 0x4229C8U, 0x423123U, - 0x424A61U, 0x42528AU, 0x42635FU, 0x427BB4U, 0x428D30U, 0x4295DBU, 0x42A40EU, 0x42BCE5U, 0x42C7A7U, 0x42DF4CU, - 0x42EE99U, 0x42F672U, 0x430391U, 0x431B7AU, 0x432AAFU, 0x433244U, 0x434906U, 0x4351EDU, 0x436038U, 0x4378D3U, - 0x438E57U, 0x4396BCU, 0x43A769U, 0x43BF82U, 0x43C4C0U, 0x43DC2BU, 0x43EDFEU, 0x43F515U, 0x440BA2U, 0x441349U, - 0x44229CU, 0x443A77U, 0x444135U, 0x4459DEU, 0x44680BU, 0x4470E0U, 0x448664U, 0x449E8FU, 0x44AF5AU, 0x44B7B1U, - 0x44CCF3U, 0x44D418U, 0x44E5CDU, 0x44FD26U, 0x4508C5U, 0x45102EU, 0x4521FBU, 0x453910U, 0x454252U, 0x455AB9U, - 0x456B6CU, 0x457387U, 0x458503U, 0x459DE8U, 0x45AC3DU, 0x45B4D6U, 0x45CF94U, 0x45D77FU, 0x45E6AAU, 0x45FE41U, - 0x460D6FU, 0x461584U, 0x462451U, 0x463CBAU, 0x4647F8U, 0x465F13U, 0x466EC6U, 0x46762DU, 0x4680A9U, 0x469842U, - 0x46A997U, 0x46B17CU, 0x46CA3EU, 0x46D2D5U, 0x46E300U, 0x46FBEBU, 0x470E08U, 0x4716E3U, 0x472736U, 0x473FDDU, - 0x47449FU, 0x475C74U, 0x476DA1U, 0x47754AU, 0x4783CEU, 0x479B25U, 0x47AAF0U, 0x47B21BU, 0x47C959U, 0x47D1B2U, - 0x47E067U, 0x47F88CU, 0x4805E1U, 0x481D0AU, 0x482CDFU, 0x483434U, 0x484F76U, 0x48579DU, 0x486648U, 0x487EA3U, - 0x488827U, 0x4890CCU, 0x48A119U, 0x48B9F2U, 0x48C2B0U, 0x48DA5BU, 0x48EB8EU, 0x48F365U, 0x490686U, 0x491E6DU, - 0x492FB8U, 0x493753U, 0x494C11U, 0x4954FAU, 0x49652FU, 0x497DC4U, 0x498B40U, 0x4993ABU, 0x49A27EU, 0x49BA95U, - 0x49C1D7U, 0x49D93CU, 0x49E8E9U, 0x49F002U, 0x4A032CU, 0x4A1BC7U, 0x4A2A12U, 0x4A32F9U, 0x4A49BBU, 0x4A5150U, - 0x4A6085U, 0x4A786EU, 0x4A8EEAU, 0x4A9601U, 0x4AA7D4U, 0x4ABF3FU, 0x4AC47DU, 0x4ADC96U, 0x4AED43U, 0x4AF5A8U, - 0x4B004BU, 0x4B18A0U, 0x4B2975U, 0x4B319EU, 0x4B4ADCU, 0x4B5237U, 0x4B63E2U, 0x4B7B09U, 0x4B8D8DU, 0x4B9566U, - 0x4BA4B3U, 0x4BBC58U, 0x4BC71AU, 0x4BDFF1U, 0x4BEE24U, 0x4BF6CFU, 0x4C0878U, 0x4C1093U, 0x4C2146U, 0x4C39ADU, - 0x4C42EFU, 0x4C5A04U, 0x4C6BD1U, 0x4C733AU, 0x4C85BEU, 0x4C9D55U, 0x4CAC80U, 0x4CB46BU, 0x4CCF29U, 0x4CD7C2U, - 0x4CE617U, 0x4CFEFCU, 0x4D0B1FU, 0x4D13F4U, 0x4D2221U, 0x4D3ACAU, 0x4D4188U, 0x4D5963U, 0x4D68B6U, 0x4D705DU, - 0x4D86D9U, 0x4D9E32U, 0x4DAFE7U, 0x4DB70CU, 0x4DCC4EU, 0x4DD4A5U, 0x4DE570U, 0x4DFD9BU, 0x4E0EB5U, 0x4E165EU, - 0x4E278BU, 0x4E3F60U, 0x4E4422U, 0x4E5CC9U, 0x4E6D1CU, 0x4E75F7U, 0x4E8373U, 0x4E9B98U, 0x4EAA4DU, 0x4EB2A6U, - 0x4EC9E4U, 0x4ED10FU, 0x4EE0DAU, 0x4EF831U, 0x4F0DD2U, 0x4F1539U, 0x4F24ECU, 0x4F3C07U, 0x4F4745U, 0x4F5FAEU, - 0x4F6E7BU, 0x4F7690U, 0x4F8014U, 0x4F98FFU, 0x4FA92AU, 0x4FB1C1U, 0x4FCA83U, 0x4FD268U, 0x4FE3BDU, 0x4FFB56U, - 0x50018FU, 0x501964U, 0x5028B1U, 0x50305AU, 0x504B18U, 0x5053F3U, 0x506226U, 0x507ACDU, 0x508C49U, 0x5094A2U, - 0x50A577U, 0x50BD9CU, 0x50C6DEU, 0x50DE35U, 0x50EFE0U, 0x50F70BU, 0x5102E8U, 0x511A03U, 0x512BD6U, 0x51333DU, - 0x51487FU, 0x515094U, 0x516141U, 0x5179AAU, 0x518F2EU, 0x5197C5U, 0x51A610U, 0x51BEFBU, 0x51C5B9U, 0x51DD52U, - 0x51EC87U, 0x51F46CU, 0x520742U, 0x521FA9U, 0x522E7CU, 0x523697U, 0x524DD5U, 0x52553EU, 0x5264EBU, 0x527C00U, - 0x528A84U, 0x52926FU, 0x52A3BAU, 0x52BB51U, 0x52C013U, 0x52D8F8U, 0x52E92DU, 0x52F1C6U, 0x530425U, 0x531CCEU, - 0x532D1BU, 0x5335F0U, 0x534EB2U, 0x535659U, 0x53678CU, 0x537F67U, 0x5389E3U, 0x539108U, 0x53A0DDU, 0x53B836U, - 0x53C374U, 0x53DB9FU, 0x53EA4AU, 0x53F2A1U, 0x540C16U, 0x5414FDU, 0x542528U, 0x543DC3U, 0x544681U, 0x545E6AU, - 0x546FBFU, 0x547754U, 0x5481D0U, 0x54993BU, 0x54A8EEU, 0x54B005U, 0x54CB47U, 0x54D3ACU, 0x54E279U, 0x54FA92U, - 0x550F71U, 0x55179AU, 0x55264FU, 0x553EA4U, 0x5545E6U, 0x555D0DU, 0x556CD8U, 0x557433U, 0x5582B7U, 0x559A5CU, - 0x55AB89U, 0x55B362U, 0x55C820U, 0x55D0CBU, 0x55E11EU, 0x55F9F5U, 0x560ADBU, 0x561230U, 0x5623E5U, 0x563B0EU, - 0x56404CU, 0x5658A7U, 0x566972U, 0x567199U, 0x56871DU, 0x569FF6U, 0x56AE23U, 0x56B6C8U, 0x56CD8AU, 0x56D561U, - 0x56E4B4U, 0x56FC5FU, 0x5709BCU, 0x571157U, 0x572082U, 0x573869U, 0x57432BU, 0x575BC0U, 0x576A15U, 0x5772FEU, - 0x57847AU, 0x579C91U, 0x57AD44U, 0x57B5AFU, 0x57CEEDU, 0x57D606U, 0x57E7D3U, 0x57FF38U, 0x580255U, 0x581ABEU, - 0x582B6BU, 0x583380U, 0x5848C2U, 0x585029U, 0x5861FCU, 0x587917U, 0x588F93U, 0x589778U, 0x58A6ADU, 0x58BE46U, - 0x58C504U, 0x58DDEFU, 0x58EC3AU, 0x58F4D1U, 0x590132U, 0x5919D9U, 0x59280CU, 0x5930E7U, 0x594BA5U, 0x59534EU, - 0x59629BU, 0x597A70U, 0x598CF4U, 0x59941FU, 0x59A5CAU, 0x59BD21U, 0x59C663U, 0x59DE88U, 0x59EF5DU, 0x59F7B6U, - 0x5A0498U, 0x5A1C73U, 0x5A2DA6U, 0x5A354DU, 0x5A4E0FU, 0x5A56E4U, 0x5A6731U, 0x5A7FDAU, 0x5A895EU, 0x5A91B5U, - 0x5AA060U, 0x5AB88BU, 0x5AC3C9U, 0x5ADB22U, 0x5AEAF7U, 0x5AF21CU, 0x5B07FFU, 0x5B1F14U, 0x5B2EC1U, 0x5B362AU, - 0x5B4D68U, 0x5B5583U, 0x5B6456U, 0x5B7CBDU, 0x5B8A39U, 0x5B92D2U, 0x5BA307U, 0x5BBBECU, 0x5BC0AEU, 0x5BD845U, - 0x5BE990U, 0x5BF17BU, 0x5C0FCCU, 0x5C1727U, 0x5C26F2U, 0x5C3E19U, 0x5C455BU, 0x5C5DB0U, 0x5C6C65U, 0x5C748EU, - 0x5C820AU, 0x5C9AE1U, 0x5CAB34U, 0x5CB3DFU, 0x5CC89DU, 0x5CD076U, 0x5CE1A3U, 0x5CF948U, 0x5D0CABU, 0x5D1440U, - 0x5D2595U, 0x5D3D7EU, 0x5D463CU, 0x5D5ED7U, 0x5D6F02U, 0x5D77E9U, 0x5D816DU, 0x5D9986U, 0x5DA853U, 0x5DB0B8U, - 0x5DCBFAU, 0x5DD311U, 0x5DE2C4U, 0x5DFA2FU, 0x5E0901U, 0x5E11EAU, 0x5E203FU, 0x5E38D4U, 0x5E4396U, 0x5E5B7DU, - 0x5E6AA8U, 0x5E7243U, 0x5E84C7U, 0x5E9C2CU, 0x5EADF9U, 0x5EB512U, 0x5ECE50U, 0x5ED6BBU, 0x5EE76EU, 0x5EFF85U, - 0x5F0A66U, 0x5F128DU, 0x5F2358U, 0x5F3BB3U, 0x5F40F1U, 0x5F581AU, 0x5F69CFU, 0x5F7124U, 0x5F87A0U, 0x5F9F4BU, - 0x5FAE9EU, 0x5FB675U, 0x5FCD37U, 0x5FD5DCU, 0x5FE409U, 0x5FFCE2U, 0x600953U, 0x6011B8U, 0x60206DU, 0x603886U, - 0x6043C4U, 0x605B2FU, 0x606AFAU, 0x607211U, 0x608495U, 0x609C7EU, 0x60ADABU, 0x60B540U, 0x60CE02U, 0x60D6E9U, - 0x60E73CU, 0x60FFD7U, 0x610A34U, 0x6112DFU, 0x61230AU, 0x613BE1U, 0x6140A3U, 0x615848U, 0x61699DU, 0x617176U, - 0x6187F2U, 0x619F19U, 0x61AECCU, 0x61B627U, 0x61CD65U, 0x61D58EU, 0x61E45BU, 0x61FCB0U, 0x620F9EU, 0x621775U, - 0x6226A0U, 0x623E4BU, 0x624509U, 0x625DE2U, 0x626C37U, 0x6274DCU, 0x628258U, 0x629AB3U, 0x62AB66U, 0x62B38DU, - 0x62C8CFU, 0x62D024U, 0x62E1F1U, 0x62F91AU, 0x630CF9U, 0x631412U, 0x6325C7U, 0x633D2CU, 0x63466EU, 0x635E85U, - 0x636F50U, 0x6377BBU, 0x63813FU, 0x6399D4U, 0x63A801U, 0x63B0EAU, 0x63CBA8U, 0x63D343U, 0x63E296U, 0x63FA7DU, - 0x6404CAU, 0x641C21U, 0x642DF4U, 0x64351FU, 0x644E5DU, 0x6456B6U, 0x646763U, 0x647F88U, 0x64890CU, 0x6491E7U, - 0x64A032U, 0x64B8D9U, 0x64C39BU, 0x64DB70U, 0x64EAA5U, 0x64F24EU, 0x6507ADU, 0x651F46U, 0x652E93U, 0x653678U, - 0x654D3AU, 0x6555D1U, 0x656404U, 0x657CEFU, 0x658A6BU, 0x659280U, 0x65A355U, 0x65BBBEU, 0x65C0FCU, 0x65D817U, - 0x65E9C2U, 0x65F129U, 0x660207U, 0x661AECU, 0x662B39U, 0x6633D2U, 0x664890U, 0x66507BU, 0x6661AEU, 0x667945U, - 0x668FC1U, 0x66972AU, 0x66A6FFU, 0x66BE14U, 0x66C556U, 0x66DDBDU, 0x66EC68U, 0x66F483U, 0x670160U, 0x67198BU, - 0x67285EU, 0x6730B5U, 0x674BF7U, 0x67531CU, 0x6762C9U, 0x677A22U, 0x678CA6U, 0x67944DU, 0x67A598U, 0x67BD73U, - 0x67C631U, 0x67DEDAU, 0x67EF0FU, 0x67F7E4U, 0x680A89U, 0x681262U, 0x6823B7U, 0x683B5CU, 0x68401EU, 0x6858F5U, - 0x686920U, 0x6871CBU, 0x68874FU, 0x689FA4U, 0x68AE71U, 0x68B69AU, 0x68CDD8U, 0x68D533U, 0x68E4E6U, 0x68FC0DU, - 0x6909EEU, 0x691105U, 0x6920D0U, 0x69383BU, 0x694379U, 0x695B92U, 0x696A47U, 0x6972ACU, 0x698428U, 0x699CC3U, - 0x69AD16U, 0x69B5FDU, 0x69CEBFU, 0x69D654U, 0x69E781U, 0x69FF6AU, 0x6A0C44U, 0x6A14AFU, 0x6A257AU, 0x6A3D91U, - 0x6A46D3U, 0x6A5E38U, 0x6A6FEDU, 0x6A7706U, 0x6A8182U, 0x6A9969U, 0x6AA8BCU, 0x6AB057U, 0x6ACB15U, 0x6AD3FEU, - 0x6AE22BU, 0x6AFAC0U, 0x6B0F23U, 0x6B17C8U, 0x6B261DU, 0x6B3EF6U, 0x6B45B4U, 0x6B5D5FU, 0x6B6C8AU, 0x6B7461U, - 0x6B82E5U, 0x6B9A0EU, 0x6BABDBU, 0x6BB330U, 0x6BC872U, 0x6BD099U, 0x6BE14CU, 0x6BF9A7U, 0x6C0710U, 0x6C1FFBU, - 0x6C2E2EU, 0x6C36C5U, 0x6C4D87U, 0x6C556CU, 0x6C64B9U, 0x6C7C52U, 0x6C8AD6U, 0x6C923DU, 0x6CA3E8U, 0x6CBB03U, - 0x6CC041U, 0x6CD8AAU, 0x6CE97FU, 0x6CF194U, 0x6D0477U, 0x6D1C9CU, 0x6D2D49U, 0x6D35A2U, 0x6D4EE0U, 0x6D560BU, - 0x6D67DEU, 0x6D7F35U, 0x6D89B1U, 0x6D915AU, 0x6DA08FU, 0x6DB864U, 0x6DC326U, 0x6DDBCDU, 0x6DEA18U, 0x6DF2F3U, - 0x6E01DDU, 0x6E1936U, 0x6E28E3U, 0x6E3008U, 0x6E4B4AU, 0x6E53A1U, 0x6E6274U, 0x6E7A9FU, 0x6E8C1BU, 0x6E94F0U, - 0x6EA525U, 0x6EBDCEU, 0x6EC68CU, 0x6EDE67U, 0x6EEFB2U, 0x6EF759U, 0x6F02BAU, 0x6F1A51U, 0x6F2B84U, 0x6F336FU, - 0x6F482DU, 0x6F50C6U, 0x6F6113U, 0x6F79F8U, 0x6F8F7CU, 0x6F9797U, 0x6FA642U, 0x6FBEA9U, 0x6FC5EBU, 0x6FDD00U, - 0x6FECD5U, 0x6FF43EU, 0x700EE7U, 0x70160CU, 0x7027D9U, 0x703F32U, 0x704470U, 0x705C9BU, 0x706D4EU, 0x7075A5U, - 0x708321U, 0x709BCAU, 0x70AA1FU, 0x70B2F4U, 0x70C9B6U, 0x70D15DU, 0x70E088U, 0x70F863U, 0x710D80U, 0x71156BU, - 0x7124BEU, 0x713C55U, 0x714717U, 0x715FFCU, 0x716E29U, 0x7176C2U, 0x718046U, 0x7198ADU, 0x71A978U, 0x71B193U, - 0x71CAD1U, 0x71D23AU, 0x71E3EFU, 0x71FB04U, 0x72082AU, 0x7210C1U, 0x722114U, 0x7239FFU, 0x7242BDU, 0x725A56U, - 0x726B83U, 0x727368U, 0x7285ECU, 0x729D07U, 0x72ACD2U, 0x72B439U, 0x72CF7BU, 0x72D790U, 0x72E645U, 0x72FEAEU, - 0x730B4DU, 0x7313A6U, 0x732273U, 0x733A98U, 0x7341DAU, 0x735931U, 0x7368E4U, 0x73700FU, 0x73868BU, 0x739E60U, - 0x73AFB5U, 0x73B75EU, 0x73CC1CU, 0x73D4F7U, 0x73E522U, 0x73FDC9U, 0x74037EU, 0x741B95U, 0x742A40U, 0x7432ABU, - 0x7449E9U, 0x745102U, 0x7460D7U, 0x74783CU, 0x748EB8U, 0x749653U, 0x74A786U, 0x74BF6DU, 0x74C42FU, 0x74DCC4U, - 0x74ED11U, 0x74F5FAU, 0x750019U, 0x7518F2U, 0x752927U, 0x7531CCU, 0x754A8EU, 0x755265U, 0x7563B0U, 0x757B5BU, - 0x758DDFU, 0x759534U, 0x75A4E1U, 0x75BC0AU, 0x75C748U, 0x75DFA3U, 0x75EE76U, 0x75F69DU, 0x7605B3U, 0x761D58U, - 0x762C8DU, 0x763466U, 0x764F24U, 0x7657CFU, 0x76661AU, 0x767EF1U, 0x768875U, 0x76909EU, 0x76A14BU, 0x76B9A0U, - 0x76C2E2U, 0x76DA09U, 0x76EBDCU, 0x76F337U, 0x7706D4U, 0x771E3FU, 0x772FEAU, 0x773701U, 0x774C43U, 0x7754A8U, - 0x77657DU, 0x777D96U, 0x778B12U, 0x7793F9U, 0x77A22CU, 0x77BAC7U, 0x77C185U, 0x77D96EU, 0x77E8BBU, 0x77F050U, - 0x780D3DU, 0x7815D6U, 0x782403U, 0x783CE8U, 0x7847AAU, 0x785F41U, 0x786E94U, 0x78767FU, 0x7880FBU, 0x789810U, - 0x78A9C5U, 0x78B12EU, 0x78CA6CU, 0x78D287U, 0x78E352U, 0x78FBB9U, 0x790E5AU, 0x7916B1U, 0x792764U, 0x793F8FU, - 0x7944CDU, 0x795C26U, 0x796DF3U, 0x797518U, 0x79839CU, 0x799B77U, 0x79AAA2U, 0x79B249U, 0x79C90BU, 0x79D1E0U, - 0x79E035U, 0x79F8DEU, 0x7A0BF0U, 0x7A131BU, 0x7A22CEU, 0x7A3A25U, 0x7A4167U, 0x7A598CU, 0x7A6859U, 0x7A70B2U, - 0x7A8636U, 0x7A9EDDU, 0x7AAF08U, 0x7AB7E3U, 0x7ACCA1U, 0x7AD44AU, 0x7AE59FU, 0x7AFD74U, 0x7B0897U, 0x7B107CU, - 0x7B21A9U, 0x7B3942U, 0x7B4200U, 0x7B5AEBU, 0x7B6B3EU, 0x7B73D5U, 0x7B8551U, 0x7B9DBAU, 0x7BAC6FU, 0x7BB484U, - 0x7BCFC6U, 0x7BD72DU, 0x7BE6F8U, 0x7BFE13U, 0x7C00A4U, 0x7C184FU, 0x7C299AU, 0x7C3171U, 0x7C4A33U, 0x7C52D8U, - 0x7C630DU, 0x7C7BE6U, 0x7C8D62U, 0x7C9589U, 0x7CA45CU, 0x7CBCB7U, 0x7CC7F5U, 0x7CDF1EU, 0x7CEECBU, 0x7CF620U, - 0x7D03C3U, 0x7D1B28U, 0x7D2AFDU, 0x7D3216U, 0x7D4954U, 0x7D51BFU, 0x7D606AU, 0x7D7881U, 0x7D8E05U, 0x7D96EEU, - 0x7DA73BU, 0x7DBFD0U, 0x7DC492U, 0x7DDC79U, 0x7DEDACU, 0x7DF547U, 0x7E0669U, 0x7E1E82U, 0x7E2F57U, 0x7E37BCU, - 0x7E4CFEU, 0x7E5415U, 0x7E65C0U, 0x7E7D2BU, 0x7E8BAFU, 0x7E9344U, 0x7EA291U, 0x7EBA7AU, 0x7EC138U, 0x7ED9D3U, - 0x7EE806U, 0x7EF0EDU, 0x7F050EU, 0x7F1DE5U, 0x7F2C30U, 0x7F34DBU, 0x7F4F99U, 0x7F5772U, 0x7F66A7U, 0x7F7E4CU, - 0x7F88C8U, 0x7F9023U, 0x7FA1F6U, 0x7FB91DU, 0x7FC25FU, 0x7FDAB4U, 0x7FEB61U, 0x7FF38AU, 0x800C75U, 0x80149EU, - 0x80254BU, 0x803DA0U, 0x8046E2U, 0x805E09U, 0x806FDCU, 0x807737U, 0x8081B3U, 0x809958U, 0x80A88DU, 0x80B066U, - 0x80CB24U, 0x80D3CFU, 0x80E21AU, 0x80FAF1U, 0x810F12U, 0x8117F9U, 0x81262CU, 0x813EC7U, 0x814585U, 0x815D6EU, - 0x816CBBU, 0x817450U, 0x8182D4U, 0x819A3FU, 0x81ABEAU, 0x81B301U, 0x81C843U, 0x81D0A8U, 0x81E17DU, 0x81F996U, - 0x820AB8U, 0x821253U, 0x822386U, 0x823B6DU, 0x82402FU, 0x8258C4U, 0x826911U, 0x8271FAU, 0x82877EU, 0x829F95U, - 0x82AE40U, 0x82B6ABU, 0x82CDE9U, 0x82D502U, 0x82E4D7U, 0x82FC3CU, 0x8309DFU, 0x831134U, 0x8320E1U, 0x83380AU, - 0x834348U, 0x835BA3U, 0x836A76U, 0x83729DU, 0x838419U, 0x839CF2U, 0x83AD27U, 0x83B5CCU, 0x83CE8EU, 0x83D665U, - 0x83E7B0U, 0x83FF5BU, 0x8401ECU, 0x841907U, 0x8428D2U, 0x843039U, 0x844B7BU, 0x845390U, 0x846245U, 0x847AAEU, - 0x848C2AU, 0x8494C1U, 0x84A514U, 0x84BDFFU, 0x84C6BDU, 0x84DE56U, 0x84EF83U, 0x84F768U, 0x85028BU, 0x851A60U, - 0x852BB5U, 0x85335EU, 0x85481CU, 0x8550F7U, 0x856122U, 0x8579C9U, 0x858F4DU, 0x8597A6U, 0x85A673U, 0x85BE98U, - 0x85C5DAU, 0x85DD31U, 0x85ECE4U, 0x85F40FU, 0x860721U, 0x861FCAU, 0x862E1FU, 0x8636F4U, 0x864DB6U, 0x86555DU, - 0x866488U, 0x867C63U, 0x868AE7U, 0x86920CU, 0x86A3D9U, 0x86BB32U, 0x86C070U, 0x86D89BU, 0x86E94EU, 0x86F1A5U, - 0x870446U, 0x871CADU, 0x872D78U, 0x873593U, 0x874ED1U, 0x87563AU, 0x8767EFU, 0x877F04U, 0x878980U, 0x87916BU, - 0x87A0BEU, 0x87B855U, 0x87C317U, 0x87DBFCU, 0x87EA29U, 0x87F2C2U, 0x880FAFU, 0x881744U, 0x882691U, 0x883E7AU, - 0x884538U, 0x885DD3U, 0x886C06U, 0x8874EDU, 0x888269U, 0x889A82U, 0x88AB57U, 0x88B3BCU, 0x88C8FEU, 0x88D015U, - 0x88E1C0U, 0x88F92BU, 0x890CC8U, 0x891423U, 0x8925F6U, 0x893D1DU, 0x89465FU, 0x895EB4U, 0x896F61U, 0x89778AU, - 0x89810EU, 0x8999E5U, 0x89A830U, 0x89B0DBU, 0x89CB99U, 0x89D372U, 0x89E2A7U, 0x89FA4CU, 0x8A0962U, 0x8A1189U, - 0x8A205CU, 0x8A38B7U, 0x8A43F5U, 0x8A5B1EU, 0x8A6ACBU, 0x8A7220U, 0x8A84A4U, 0x8A9C4FU, 0x8AAD9AU, 0x8AB571U, - 0x8ACE33U, 0x8AD6D8U, 0x8AE70DU, 0x8AFFE6U, 0x8B0A05U, 0x8B12EEU, 0x8B233BU, 0x8B3BD0U, 0x8B4092U, 0x8B5879U, - 0x8B69ACU, 0x8B7147U, 0x8B87C3U, 0x8B9F28U, 0x8BAEFDU, 0x8BB616U, 0x8BCD54U, 0x8BD5BFU, 0x8BE46AU, 0x8BFC81U, - 0x8C0236U, 0x8C1ADDU, 0x8C2B08U, 0x8C33E3U, 0x8C48A1U, 0x8C504AU, 0x8C619FU, 0x8C7974U, 0x8C8FF0U, 0x8C971BU, - 0x8CA6CEU, 0x8CBE25U, 0x8CC567U, 0x8CDD8CU, 0x8CEC59U, 0x8CF4B2U, 0x8D0151U, 0x8D19BAU, 0x8D286FU, 0x8D3084U, - 0x8D4BC6U, 0x8D532DU, 0x8D62F8U, 0x8D7A13U, 0x8D8C97U, 0x8D947CU, 0x8DA5A9U, 0x8DBD42U, 0x8DC600U, 0x8DDEEBU, - 0x8DEF3EU, 0x8DF7D5U, 0x8E04FBU, 0x8E1C10U, 0x8E2DC5U, 0x8E352EU, 0x8E4E6CU, 0x8E5687U, 0x8E6752U, 0x8E7FB9U, - 0x8E893DU, 0x8E91D6U, 0x8EA003U, 0x8EB8E8U, 0x8EC3AAU, 0x8EDB41U, 0x8EEA94U, 0x8EF27FU, 0x8F079CU, 0x8F1F77U, - 0x8F2EA2U, 0x8F3649U, 0x8F4D0BU, 0x8F55E0U, 0x8F6435U, 0x8F7CDEU, 0x8F8A5AU, 0x8F92B1U, 0x8FA364U, 0x8FBB8FU, - 0x8FC0CDU, 0x8FD826U, 0x8FE9F3U, 0x8FF118U, 0x900BC1U, 0x90132AU, 0x9022FFU, 0x903A14U, 0x904156U, 0x9059BDU, - 0x906868U, 0x907083U, 0x908607U, 0x909EECU, 0x90AF39U, 0x90B7D2U, 0x90CC90U, 0x90D47BU, 0x90E5AEU, 0x90FD45U, - 0x9108A6U, 0x91104DU, 0x912198U, 0x913973U, 0x914231U, 0x915ADAU, 0x916B0FU, 0x9173E4U, 0x918560U, 0x919D8BU, - 0x91AC5EU, 0x91B4B5U, 0x91CFF7U, 0x91D71CU, 0x91E6C9U, 0x91FE22U, 0x920D0CU, 0x9215E7U, 0x922432U, 0x923CD9U, - 0x92479BU, 0x925F70U, 0x926EA5U, 0x92764EU, 0x9280CAU, 0x929821U, 0x92A9F4U, 0x92B11FU, 0x92CA5DU, 0x92D2B6U, - 0x92E363U, 0x92FB88U, 0x930E6BU, 0x931680U, 0x932755U, 0x933FBEU, 0x9344FCU, 0x935C17U, 0x936DC2U, 0x937529U, - 0x9383ADU, 0x939B46U, 0x93AA93U, 0x93B278U, 0x93C93AU, 0x93D1D1U, 0x93E004U, 0x93F8EFU, 0x940658U, 0x941EB3U, - 0x942F66U, 0x94378DU, 0x944CCFU, 0x945424U, 0x9465F1U, 0x947D1AU, 0x948B9EU, 0x949375U, 0x94A2A0U, 0x94BA4BU, - 0x94C109U, 0x94D9E2U, 0x94E837U, 0x94F0DCU, 0x95053FU, 0x951DD4U, 0x952C01U, 0x9534EAU, 0x954FA8U, 0x955743U, - 0x956696U, 0x957E7DU, 0x9588F9U, 0x959012U, 0x95A1C7U, 0x95B92CU, 0x95C26EU, 0x95DA85U, 0x95EB50U, 0x95F3BBU, - 0x960095U, 0x96187EU, 0x9629ABU, 0x963140U, 0x964A02U, 0x9652E9U, 0x96633CU, 0x967BD7U, 0x968D53U, 0x9695B8U, - 0x96A46DU, 0x96BC86U, 0x96C7C4U, 0x96DF2FU, 0x96EEFAU, 0x96F611U, 0x9703F2U, 0x971B19U, 0x972ACCU, 0x973227U, - 0x974965U, 0x97518EU, 0x97605BU, 0x9778B0U, 0x978E34U, 0x9796DFU, 0x97A70AU, 0x97BFE1U, 0x97C4A3U, 0x97DC48U, - 0x97ED9DU, 0x97F576U, 0x98081BU, 0x9810F0U, 0x982125U, 0x9839CEU, 0x98428CU, 0x985A67U, 0x986BB2U, 0x987359U, - 0x9885DDU, 0x989D36U, 0x98ACE3U, 0x98B408U, 0x98CF4AU, 0x98D7A1U, 0x98E674U, 0x98FE9FU, 0x990B7CU, 0x991397U, - 0x992242U, 0x993AA9U, 0x9941EBU, 0x995900U, 0x9968D5U, 0x99703EU, 0x9986BAU, 0x999E51U, 0x99AF84U, 0x99B76FU, - 0x99CC2DU, 0x99D4C6U, 0x99E513U, 0x99FDF8U, 0x9A0ED6U, 0x9A163DU, 0x9A27E8U, 0x9A3F03U, 0x9A4441U, 0x9A5CAAU, - 0x9A6D7FU, 0x9A7594U, 0x9A8310U, 0x9A9BFBU, 0x9AAA2EU, 0x9AB2C5U, 0x9AC987U, 0x9AD16CU, 0x9AE0B9U, 0x9AF852U, - 0x9B0DB1U, 0x9B155AU, 0x9B248FU, 0x9B3C64U, 0x9B4726U, 0x9B5FCDU, 0x9B6E18U, 0x9B76F3U, 0x9B8077U, 0x9B989CU, - 0x9BA949U, 0x9BB1A2U, 0x9BCAE0U, 0x9BD20BU, 0x9BE3DEU, 0x9BFB35U, 0x9C0582U, 0x9C1D69U, 0x9C2CBCU, 0x9C3457U, - 0x9C4F15U, 0x9C57FEU, 0x9C662BU, 0x9C7EC0U, 0x9C8844U, 0x9C90AFU, 0x9CA17AU, 0x9CB991U, 0x9CC2D3U, 0x9CDA38U, - 0x9CEBEDU, 0x9CF306U, 0x9D06E5U, 0x9D1E0EU, 0x9D2FDBU, 0x9D3730U, 0x9D4C72U, 0x9D5499U, 0x9D654CU, 0x9D7DA7U, - 0x9D8B23U, 0x9D93C8U, 0x9DA21DU, 0x9DBAF6U, 0x9DC1B4U, 0x9DD95FU, 0x9DE88AU, 0x9DF061U, 0x9E034FU, 0x9E1BA4U, - 0x9E2A71U, 0x9E329AU, 0x9E49D8U, 0x9E5133U, 0x9E60E6U, 0x9E780DU, 0x9E8E89U, 0x9E9662U, 0x9EA7B7U, 0x9EBF5CU, - 0x9EC41EU, 0x9EDCF5U, 0x9EED20U, 0x9EF5CBU, 0x9F0028U, 0x9F18C3U, 0x9F2916U, 0x9F31FDU, 0x9F4ABFU, 0x9F5254U, - 0x9F6381U, 0x9F7B6AU, 0x9F8DEEU, 0x9F9505U, 0x9FA4D0U, 0x9FBC3BU, 0x9FC779U, 0x9FDF92U, 0x9FEE47U, 0x9FF6ACU, - 0xA0031DU, 0xA01BF6U, 0xA02A23U, 0xA032C8U, 0xA0498AU, 0xA05161U, 0xA060B4U, 0xA0785FU, 0xA08EDBU, 0xA09630U, - 0xA0A7E5U, 0xA0BF0EU, 0xA0C44CU, 0xA0DCA7U, 0xA0ED72U, 0xA0F599U, 0xA1007AU, 0xA11891U, 0xA12944U, 0xA131AFU, - 0xA14AEDU, 0xA15206U, 0xA163D3U, 0xA17B38U, 0xA18DBCU, 0xA19557U, 0xA1A482U, 0xA1BC69U, 0xA1C72BU, 0xA1DFC0U, - 0xA1EE15U, 0xA1F6FEU, 0xA205D0U, 0xA21D3BU, 0xA22CEEU, 0xA23405U, 0xA24F47U, 0xA257ACU, 0xA26679U, 0xA27E92U, - 0xA28816U, 0xA290FDU, 0xA2A128U, 0xA2B9C3U, 0xA2C281U, 0xA2DA6AU, 0xA2EBBFU, 0xA2F354U, 0xA306B7U, 0xA31E5CU, - 0xA32F89U, 0xA33762U, 0xA34C20U, 0xA354CBU, 0xA3651EU, 0xA37DF5U, 0xA38B71U, 0xA3939AU, 0xA3A24FU, 0xA3BAA4U, - 0xA3C1E6U, 0xA3D90DU, 0xA3E8D8U, 0xA3F033U, 0xA40E84U, 0xA4166FU, 0xA427BAU, 0xA43F51U, 0xA44413U, 0xA45CF8U, - 0xA46D2DU, 0xA475C6U, 0xA48342U, 0xA49BA9U, 0xA4AA7CU, 0xA4B297U, 0xA4C9D5U, 0xA4D13EU, 0xA4E0EBU, 0xA4F800U, - 0xA50DE3U, 0xA51508U, 0xA524DDU, 0xA53C36U, 0xA54774U, 0xA55F9FU, 0xA56E4AU, 0xA576A1U, 0xA58025U, 0xA598CEU, - 0xA5A91BU, 0xA5B1F0U, 0xA5CAB2U, 0xA5D259U, 0xA5E38CU, 0xA5FB67U, 0xA60849U, 0xA610A2U, 0xA62177U, 0xA6399CU, - 0xA642DEU, 0xA65A35U, 0xA66BE0U, 0xA6730BU, 0xA6858FU, 0xA69D64U, 0xA6ACB1U, 0xA6B45AU, 0xA6CF18U, 0xA6D7F3U, - 0xA6E626U, 0xA6FECDU, 0xA70B2EU, 0xA713C5U, 0xA72210U, 0xA73AFBU, 0xA741B9U, 0xA75952U, 0xA76887U, 0xA7706CU, - 0xA786E8U, 0xA79E03U, 0xA7AFD6U, 0xA7B73DU, 0xA7CC7FU, 0xA7D494U, 0xA7E541U, 0xA7FDAAU, 0xA800C7U, 0xA8182CU, - 0xA829F9U, 0xA83112U, 0xA84A50U, 0xA852BBU, 0xA8636EU, 0xA87B85U, 0xA88D01U, 0xA895EAU, 0xA8A43FU, 0xA8BCD4U, - 0xA8C796U, 0xA8DF7DU, 0xA8EEA8U, 0xA8F643U, 0xA903A0U, 0xA91B4BU, 0xA92A9EU, 0xA93275U, 0xA94937U, 0xA951DCU, - 0xA96009U, 0xA978E2U, 0xA98E66U, 0xA9968DU, 0xA9A758U, 0xA9BFB3U, 0xA9C4F1U, 0xA9DC1AU, 0xA9EDCFU, 0xA9F524U, - 0xAA060AU, 0xAA1EE1U, 0xAA2F34U, 0xAA37DFU, 0xAA4C9DU, 0xAA5476U, 0xAA65A3U, 0xAA7D48U, 0xAA8BCCU, 0xAA9327U, - 0xAAA2F2U, 0xAABA19U, 0xAAC15BU, 0xAAD9B0U, 0xAAE865U, 0xAAF08EU, 0xAB056DU, 0xAB1D86U, 0xAB2C53U, 0xAB34B8U, - 0xAB4FFAU, 0xAB5711U, 0xAB66C4U, 0xAB7E2FU, 0xAB88ABU, 0xAB9040U, 0xABA195U, 0xABB97EU, 0xABC23CU, 0xABDAD7U, - 0xABEB02U, 0xABF3E9U, 0xAC0D5EU, 0xAC15B5U, 0xAC2460U, 0xAC3C8BU, 0xAC47C9U, 0xAC5F22U, 0xAC6EF7U, 0xAC761CU, - 0xAC8098U, 0xAC9873U, 0xACA9A6U, 0xACB14DU, 0xACCA0FU, 0xACD2E4U, 0xACE331U, 0xACFBDAU, 0xAD0E39U, 0xAD16D2U, - 0xAD2707U, 0xAD3FECU, 0xAD44AEU, 0xAD5C45U, 0xAD6D90U, 0xAD757BU, 0xAD83FFU, 0xAD9B14U, 0xADAAC1U, 0xADB22AU, - 0xADC968U, 0xADD183U, 0xADE056U, 0xADF8BDU, 0xAE0B93U, 0xAE1378U, 0xAE22ADU, 0xAE3A46U, 0xAE4104U, 0xAE59EFU, - 0xAE683AU, 0xAE70D1U, 0xAE8655U, 0xAE9EBEU, 0xAEAF6BU, 0xAEB780U, 0xAECCC2U, 0xAED429U, 0xAEE5FCU, 0xAEFD17U, - 0xAF08F4U, 0xAF101FU, 0xAF21CAU, 0xAF3921U, 0xAF4263U, 0xAF5A88U, 0xAF6B5DU, 0xAF73B6U, 0xAF8532U, 0xAF9DD9U, - 0xAFAC0CU, 0xAFB4E7U, 0xAFCFA5U, 0xAFD74EU, 0xAFE69BU, 0xAFFE70U, 0xB004A9U, 0xB01C42U, 0xB02D97U, 0xB0357CU, - 0xB04E3EU, 0xB056D5U, 0xB06700U, 0xB07FEBU, 0xB0896FU, 0xB09184U, 0xB0A051U, 0xB0B8BAU, 0xB0C3F8U, 0xB0DB13U, - 0xB0EAC6U, 0xB0F22DU, 0xB107CEU, 0xB11F25U, 0xB12EF0U, 0xB1361BU, 0xB14D59U, 0xB155B2U, 0xB16467U, 0xB17C8CU, - 0xB18A08U, 0xB192E3U, 0xB1A336U, 0xB1BBDDU, 0xB1C09FU, 0xB1D874U, 0xB1E9A1U, 0xB1F14AU, 0xB20264U, 0xB21A8FU, - 0xB22B5AU, 0xB233B1U, 0xB248F3U, 0xB25018U, 0xB261CDU, 0xB27926U, 0xB28FA2U, 0xB29749U, 0xB2A69CU, 0xB2BE77U, - 0xB2C535U, 0xB2DDDEU, 0xB2EC0BU, 0xB2F4E0U, 0xB30103U, 0xB319E8U, 0xB3283DU, 0xB330D6U, 0xB34B94U, 0xB3537FU, - 0xB362AAU, 0xB37A41U, 0xB38CC5U, 0xB3942EU, 0xB3A5FBU, 0xB3BD10U, 0xB3C652U, 0xB3DEB9U, 0xB3EF6CU, 0xB3F787U, - 0xB40930U, 0xB411DBU, 0xB4200EU, 0xB438E5U, 0xB443A7U, 0xB45B4CU, 0xB46A99U, 0xB47272U, 0xB484F6U, 0xB49C1DU, - 0xB4ADC8U, 0xB4B523U, 0xB4CE61U, 0xB4D68AU, 0xB4E75FU, 0xB4FFB4U, 0xB50A57U, 0xB512BCU, 0xB52369U, 0xB53B82U, - 0xB540C0U, 0xB5582BU, 0xB569FEU, 0xB57115U, 0xB58791U, 0xB59F7AU, 0xB5AEAFU, 0xB5B644U, 0xB5CD06U, 0xB5D5EDU, - 0xB5E438U, 0xB5FCD3U, 0xB60FFDU, 0xB61716U, 0xB626C3U, 0xB63E28U, 0xB6456AU, 0xB65D81U, 0xB66C54U, 0xB674BFU, - 0xB6823BU, 0xB69AD0U, 0xB6AB05U, 0xB6B3EEU, 0xB6C8ACU, 0xB6D047U, 0xB6E192U, 0xB6F979U, 0xB70C9AU, 0xB71471U, - 0xB725A4U, 0xB73D4FU, 0xB7460DU, 0xB75EE6U, 0xB76F33U, 0xB777D8U, 0xB7815CU, 0xB799B7U, 0xB7A862U, 0xB7B089U, - 0xB7CBCBU, 0xB7D320U, 0xB7E2F5U, 0xB7FA1EU, 0xB80773U, 0xB81F98U, 0xB82E4DU, 0xB836A6U, 0xB84DE4U, 0xB8550FU, - 0xB864DAU, 0xB87C31U, 0xB88AB5U, 0xB8925EU, 0xB8A38BU, 0xB8BB60U, 0xB8C022U, 0xB8D8C9U, 0xB8E91CU, 0xB8F1F7U, - 0xB90414U, 0xB91CFFU, 0xB92D2AU, 0xB935C1U, 0xB94E83U, 0xB95668U, 0xB967BDU, 0xB97F56U, 0xB989D2U, 0xB99139U, - 0xB9A0ECU, 0xB9B807U, 0xB9C345U, 0xB9DBAEU, 0xB9EA7BU, 0xB9F290U, 0xBA01BEU, 0xBA1955U, 0xBA2880U, 0xBA306BU, - 0xBA4B29U, 0xBA53C2U, 0xBA6217U, 0xBA7AFCU, 0xBA8C78U, 0xBA9493U, 0xBAA546U, 0xBABDADU, 0xBAC6EFU, 0xBADE04U, - 0xBAEFD1U, 0xBAF73AU, 0xBB02D9U, 0xBB1A32U, 0xBB2BE7U, 0xBB330CU, 0xBB484EU, 0xBB50A5U, 0xBB6170U, 0xBB799BU, - 0xBB8F1FU, 0xBB97F4U, 0xBBA621U, 0xBBBECAU, 0xBBC588U, 0xBBDD63U, 0xBBECB6U, 0xBBF45DU, 0xBC0AEAU, 0xBC1201U, - 0xBC23D4U, 0xBC3B3FU, 0xBC407DU, 0xBC5896U, 0xBC6943U, 0xBC71A8U, 0xBC872CU, 0xBC9FC7U, 0xBCAE12U, 0xBCB6F9U, - 0xBCCDBBU, 0xBCD550U, 0xBCE485U, 0xBCFC6EU, 0xBD098DU, 0xBD1166U, 0xBD20B3U, 0xBD3858U, 0xBD431AU, 0xBD5BF1U, - 0xBD6A24U, 0xBD72CFU, 0xBD844BU, 0xBD9CA0U, 0xBDAD75U, 0xBDB59EU, 0xBDCEDCU, 0xBDD637U, 0xBDE7E2U, 0xBDFF09U, - 0xBE0C27U, 0xBE14CCU, 0xBE2519U, 0xBE3DF2U, 0xBE46B0U, 0xBE5E5BU, 0xBE6F8EU, 0xBE7765U, 0xBE81E1U, 0xBE990AU, - 0xBEA8DFU, 0xBEB034U, 0xBECB76U, 0xBED39DU, 0xBEE248U, 0xBEFAA3U, 0xBF0F40U, 0xBF17ABU, 0xBF267EU, 0xBF3E95U, - 0xBF45D7U, 0xBF5D3CU, 0xBF6CE9U, 0xBF7402U, 0xBF8286U, 0xBF9A6DU, 0xBFABB8U, 0xBFB353U, 0xBFC811U, 0xBFD0FAU, - 0xBFE12FU, 0xBFF9C4U, 0xC00A4EU, 0xC012A5U, 0xC02370U, 0xC03B9BU, 0xC040D9U, 0xC05832U, 0xC069E7U, 0xC0710CU, - 0xC08788U, 0xC09F63U, 0xC0AEB6U, 0xC0B65DU, 0xC0CD1FU, 0xC0D5F4U, 0xC0E421U, 0xC0FCCAU, 0xC10929U, 0xC111C2U, - 0xC12017U, 0xC138FCU, 0xC143BEU, 0xC15B55U, 0xC16A80U, 0xC1726BU, 0xC184EFU, 0xC19C04U, 0xC1ADD1U, 0xC1B53AU, - 0xC1CE78U, 0xC1D693U, 0xC1E746U, 0xC1FFADU, 0xC20C83U, 0xC21468U, 0xC225BDU, 0xC23D56U, 0xC24614U, 0xC25EFFU, - 0xC26F2AU, 0xC277C1U, 0xC28145U, 0xC299AEU, 0xC2A87BU, 0xC2B090U, 0xC2CBD2U, 0xC2D339U, 0xC2E2ECU, 0xC2FA07U, - 0xC30FE4U, 0xC3170FU, 0xC326DAU, 0xC33E31U, 0xC34573U, 0xC35D98U, 0xC36C4DU, 0xC374A6U, 0xC38222U, 0xC39AC9U, - 0xC3AB1CU, 0xC3B3F7U, 0xC3C8B5U, 0xC3D05EU, 0xC3E18BU, 0xC3F960U, 0xC407D7U, 0xC41F3CU, 0xC42EE9U, 0xC43602U, - 0xC44D40U, 0xC455ABU, 0xC4647EU, 0xC47C95U, 0xC48A11U, 0xC492FAU, 0xC4A32FU, 0xC4BBC4U, 0xC4C086U, 0xC4D86DU, - 0xC4E9B8U, 0xC4F153U, 0xC504B0U, 0xC51C5BU, 0xC52D8EU, 0xC53565U, 0xC54E27U, 0xC556CCU, 0xC56719U, 0xC57FF2U, - 0xC58976U, 0xC5919DU, 0xC5A048U, 0xC5B8A3U, 0xC5C3E1U, 0xC5DB0AU, 0xC5EADFU, 0xC5F234U, 0xC6011AU, 0xC619F1U, - 0xC62824U, 0xC630CFU, 0xC64B8DU, 0xC65366U, 0xC662B3U, 0xC67A58U, 0xC68CDCU, 0xC69437U, 0xC6A5E2U, 0xC6BD09U, - 0xC6C64BU, 0xC6DEA0U, 0xC6EF75U, 0xC6F79EU, 0xC7027DU, 0xC71A96U, 0xC72B43U, 0xC733A8U, 0xC748EAU, 0xC75001U, - 0xC761D4U, 0xC7793FU, 0xC78FBBU, 0xC79750U, 0xC7A685U, 0xC7BE6EU, 0xC7C52CU, 0xC7DDC7U, 0xC7EC12U, 0xC7F4F9U, - 0xC80994U, 0xC8117FU, 0xC820AAU, 0xC83841U, 0xC84303U, 0xC85BE8U, 0xC86A3DU, 0xC872D6U, 0xC88452U, 0xC89CB9U, - 0xC8AD6CU, 0xC8B587U, 0xC8CEC5U, 0xC8D62EU, 0xC8E7FBU, 0xC8FF10U, 0xC90AF3U, 0xC91218U, 0xC923CDU, 0xC93B26U, - 0xC94064U, 0xC9588FU, 0xC9695AU, 0xC971B1U, 0xC98735U, 0xC99FDEU, 0xC9AE0BU, 0xC9B6E0U, 0xC9CDA2U, 0xC9D549U, - 0xC9E49CU, 0xC9FC77U, 0xCA0F59U, 0xCA17B2U, 0xCA2667U, 0xCA3E8CU, 0xCA45CEU, 0xCA5D25U, 0xCA6CF0U, 0xCA741BU, - 0xCA829FU, 0xCA9A74U, 0xCAABA1U, 0xCAB34AU, 0xCAC808U, 0xCAD0E3U, 0xCAE136U, 0xCAF9DDU, 0xCB0C3EU, 0xCB14D5U, - 0xCB2500U, 0xCB3DEBU, 0xCB46A9U, 0xCB5E42U, 0xCB6F97U, 0xCB777CU, 0xCB81F8U, 0xCB9913U, 0xCBA8C6U, 0xCBB02DU, - 0xCBCB6FU, 0xCBD384U, 0xCBE251U, 0xCBFABAU, 0xCC040DU, 0xCC1CE6U, 0xCC2D33U, 0xCC35D8U, 0xCC4E9AU, 0xCC5671U, - 0xCC67A4U, 0xCC7F4FU, 0xCC89CBU, 0xCC9120U, 0xCCA0F5U, 0xCCB81EU, 0xCCC35CU, 0xCCDBB7U, 0xCCEA62U, 0xCCF289U, - 0xCD076AU, 0xCD1F81U, 0xCD2E54U, 0xCD36BFU, 0xCD4DFDU, 0xCD5516U, 0xCD64C3U, 0xCD7C28U, 0xCD8AACU, 0xCD9247U, - 0xCDA392U, 0xCDBB79U, 0xCDC03BU, 0xCDD8D0U, 0xCDE905U, 0xCDF1EEU, 0xCE02C0U, 0xCE1A2BU, 0xCE2BFEU, 0xCE3315U, - 0xCE4857U, 0xCE50BCU, 0xCE6169U, 0xCE7982U, 0xCE8F06U, 0xCE97EDU, 0xCEA638U, 0xCEBED3U, 0xCEC591U, 0xCEDD7AU, - 0xCEECAFU, 0xCEF444U, 0xCF01A7U, 0xCF194CU, 0xCF2899U, 0xCF3072U, 0xCF4B30U, 0xCF53DBU, 0xCF620EU, 0xCF7AE5U, - 0xCF8C61U, 0xCF948AU, 0xCFA55FU, 0xCFBDB4U, 0xCFC6F6U, 0xCFDE1DU, 0xCFEFC8U, 0xCFF723U, 0xD00DFAU, 0xD01511U, - 0xD024C4U, 0xD03C2FU, 0xD0476DU, 0xD05F86U, 0xD06E53U, 0xD076B8U, 0xD0803CU, 0xD098D7U, 0xD0A902U, 0xD0B1E9U, - 0xD0CAABU, 0xD0D240U, 0xD0E395U, 0xD0FB7EU, 0xD10E9DU, 0xD11676U, 0xD127A3U, 0xD13F48U, 0xD1440AU, 0xD15CE1U, - 0xD16D34U, 0xD175DFU, 0xD1835BU, 0xD19BB0U, 0xD1AA65U, 0xD1B28EU, 0xD1C9CCU, 0xD1D127U, 0xD1E0F2U, 0xD1F819U, - 0xD20B37U, 0xD213DCU, 0xD22209U, 0xD23AE2U, 0xD241A0U, 0xD2594BU, 0xD2689EU, 0xD27075U, 0xD286F1U, 0xD29E1AU, - 0xD2AFCFU, 0xD2B724U, 0xD2CC66U, 0xD2D48DU, 0xD2E558U, 0xD2FDB3U, 0xD30850U, 0xD310BBU, 0xD3216EU, 0xD33985U, - 0xD342C7U, 0xD35A2CU, 0xD36BF9U, 0xD37312U, 0xD38596U, 0xD39D7DU, 0xD3ACA8U, 0xD3B443U, 0xD3CF01U, 0xD3D7EAU, - 0xD3E63FU, 0xD3FED4U, 0xD40063U, 0xD41888U, 0xD4295DU, 0xD431B6U, 0xD44AF4U, 0xD4521FU, 0xD463CAU, 0xD47B21U, - 0xD48DA5U, 0xD4954EU, 0xD4A49BU, 0xD4BC70U, 0xD4C732U, 0xD4DFD9U, 0xD4EE0CU, 0xD4F6E7U, 0xD50304U, 0xD51BEFU, - 0xD52A3AU, 0xD532D1U, 0xD54993U, 0xD55178U, 0xD560ADU, 0xD57846U, 0xD58EC2U, 0xD59629U, 0xD5A7FCU, 0xD5BF17U, - 0xD5C455U, 0xD5DCBEU, 0xD5ED6BU, 0xD5F580U, 0xD606AEU, 0xD61E45U, 0xD62F90U, 0xD6377BU, 0xD64C39U, 0xD654D2U, - 0xD66507U, 0xD67DECU, 0xD68B68U, 0xD69383U, 0xD6A256U, 0xD6BABDU, 0xD6C1FFU, 0xD6D914U, 0xD6E8C1U, 0xD6F02AU, - 0xD705C9U, 0xD71D22U, 0xD72CF7U, 0xD7341CU, 0xD74F5EU, 0xD757B5U, 0xD76660U, 0xD77E8BU, 0xD7880FU, 0xD790E4U, - 0xD7A131U, 0xD7B9DAU, 0xD7C298U, 0xD7DA73U, 0xD7EBA6U, 0xD7F34DU, 0xD80E20U, 0xD816CBU, 0xD8271EU, 0xD83FF5U, - 0xD844B7U, 0xD85C5CU, 0xD86D89U, 0xD87562U, 0xD883E6U, 0xD89B0DU, 0xD8AAD8U, 0xD8B233U, 0xD8C971U, 0xD8D19AU, - 0xD8E04FU, 0xD8F8A4U, 0xD90D47U, 0xD915ACU, 0xD92479U, 0xD93C92U, 0xD947D0U, 0xD95F3BU, 0xD96EEEU, 0xD97605U, - 0xD98081U, 0xD9986AU, 0xD9A9BFU, 0xD9B154U, 0xD9CA16U, 0xD9D2FDU, 0xD9E328U, 0xD9FBC3U, 0xDA08EDU, 0xDA1006U, - 0xDA21D3U, 0xDA3938U, 0xDA427AU, 0xDA5A91U, 0xDA6B44U, 0xDA73AFU, 0xDA852BU, 0xDA9DC0U, 0xDAAC15U, 0xDAB4FEU, - 0xDACFBCU, 0xDAD757U, 0xDAE682U, 0xDAFE69U, 0xDB0B8AU, 0xDB1361U, 0xDB22B4U, 0xDB3A5FU, 0xDB411DU, 0xDB59F6U, - 0xDB6823U, 0xDB70C8U, 0xDB864CU, 0xDB9EA7U, 0xDBAF72U, 0xDBB799U, 0xDBCCDBU, 0xDBD430U, 0xDBE5E5U, 0xDBFD0EU, - 0xDC03B9U, 0xDC1B52U, 0xDC2A87U, 0xDC326CU, 0xDC492EU, 0xDC51C5U, 0xDC6010U, 0xDC78FBU, 0xDC8E7FU, 0xDC9694U, - 0xDCA741U, 0xDCBFAAU, 0xDCC4E8U, 0xDCDC03U, 0xDCEDD6U, 0xDCF53DU, 0xDD00DEU, 0xDD1835U, 0xDD29E0U, 0xDD310BU, - 0xDD4A49U, 0xDD52A2U, 0xDD6377U, 0xDD7B9CU, 0xDD8D18U, 0xDD95F3U, 0xDDA426U, 0xDDBCCDU, 0xDDC78FU, 0xDDDF64U, - 0xDDEEB1U, 0xDDF65AU, 0xDE0574U, 0xDE1D9FU, 0xDE2C4AU, 0xDE34A1U, 0xDE4FE3U, 0xDE5708U, 0xDE66DDU, 0xDE7E36U, - 0xDE88B2U, 0xDE9059U, 0xDEA18CU, 0xDEB967U, 0xDEC225U, 0xDEDACEU, 0xDEEB1BU, 0xDEF3F0U, 0xDF0613U, 0xDF1EF8U, - 0xDF2F2DU, 0xDF37C6U, 0xDF4C84U, 0xDF546FU, 0xDF65BAU, 0xDF7D51U, 0xDF8BD5U, 0xDF933EU, 0xDFA2EBU, 0xDFBA00U, - 0xDFC142U, 0xDFD9A9U, 0xDFE87CU, 0xDFF097U, 0xE00526U, 0xE01DCDU, 0xE02C18U, 0xE034F3U, 0xE04FB1U, 0xE0575AU, - 0xE0668FU, 0xE07E64U, 0xE088E0U, 0xE0900BU, 0xE0A1DEU, 0xE0B935U, 0xE0C277U, 0xE0DA9CU, 0xE0EB49U, 0xE0F3A2U, - 0xE10641U, 0xE11EAAU, 0xE12F7FU, 0xE13794U, 0xE14CD6U, 0xE1543DU, 0xE165E8U, 0xE17D03U, 0xE18B87U, 0xE1936CU, - 0xE1A2B9U, 0xE1BA52U, 0xE1C110U, 0xE1D9FBU, 0xE1E82EU, 0xE1F0C5U, 0xE203EBU, 0xE21B00U, 0xE22AD5U, 0xE2323EU, - 0xE2497CU, 0xE25197U, 0xE26042U, 0xE278A9U, 0xE28E2DU, 0xE296C6U, 0xE2A713U, 0xE2BFF8U, 0xE2C4BAU, 0xE2DC51U, - 0xE2ED84U, 0xE2F56FU, 0xE3008CU, 0xE31867U, 0xE329B2U, 0xE33159U, 0xE34A1BU, 0xE352F0U, 0xE36325U, 0xE37BCEU, - 0xE38D4AU, 0xE395A1U, 0xE3A474U, 0xE3BC9FU, 0xE3C7DDU, 0xE3DF36U, 0xE3EEE3U, 0xE3F608U, 0xE408BFU, 0xE41054U, - 0xE42181U, 0xE4396AU, 0xE44228U, 0xE45AC3U, 0xE46B16U, 0xE473FDU, 0xE48579U, 0xE49D92U, 0xE4AC47U, 0xE4B4ACU, - 0xE4CFEEU, 0xE4D705U, 0xE4E6D0U, 0xE4FE3BU, 0xE50BD8U, 0xE51333U, 0xE522E6U, 0xE53A0DU, 0xE5414FU, 0xE559A4U, - 0xE56871U, 0xE5709AU, 0xE5861EU, 0xE59EF5U, 0xE5AF20U, 0xE5B7CBU, 0xE5CC89U, 0xE5D462U, 0xE5E5B7U, 0xE5FD5CU, - 0xE60E72U, 0xE61699U, 0xE6274CU, 0xE63FA7U, 0xE644E5U, 0xE65C0EU, 0xE66DDBU, 0xE67530U, 0xE683B4U, 0xE69B5FU, - 0xE6AA8AU, 0xE6B261U, 0xE6C923U, 0xE6D1C8U, 0xE6E01DU, 0xE6F8F6U, 0xE70D15U, 0xE715FEU, 0xE7242BU, 0xE73CC0U, - 0xE74782U, 0xE75F69U, 0xE76EBCU, 0xE77657U, 0xE780D3U, 0xE79838U, 0xE7A9EDU, 0xE7B106U, 0xE7CA44U, 0xE7D2AFU, - 0xE7E37AU, 0xE7FB91U, 0xE806FCU, 0xE81E17U, 0xE82FC2U, 0xE83729U, 0xE84C6BU, 0xE85480U, 0xE86555U, 0xE87DBEU, - 0xE88B3AU, 0xE893D1U, 0xE8A204U, 0xE8BAEFU, 0xE8C1ADU, 0xE8D946U, 0xE8E893U, 0xE8F078U, 0xE9059BU, 0xE91D70U, - 0xE92CA5U, 0xE9344EU, 0xE94F0CU, 0xE957E7U, 0xE96632U, 0xE97ED9U, 0xE9885DU, 0xE990B6U, 0xE9A163U, 0xE9B988U, - 0xE9C2CAU, 0xE9DA21U, 0xE9EBF4U, 0xE9F31FU, 0xEA0031U, 0xEA18DAU, 0xEA290FU, 0xEA31E4U, 0xEA4AA6U, 0xEA524DU, - 0xEA6398U, 0xEA7B73U, 0xEA8DF7U, 0xEA951CU, 0xEAA4C9U, 0xEABC22U, 0xEAC760U, 0xEADF8BU, 0xEAEE5EU, 0xEAF6B5U, - 0xEB0356U, 0xEB1BBDU, 0xEB2A68U, 0xEB3283U, 0xEB49C1U, 0xEB512AU, 0xEB60FFU, 0xEB7814U, 0xEB8E90U, 0xEB967BU, - 0xEBA7AEU, 0xEBBF45U, 0xEBC407U, 0xEBDCECU, 0xEBED39U, 0xEBF5D2U, 0xEC0B65U, 0xEC138EU, 0xEC225BU, 0xEC3AB0U, - 0xEC41F2U, 0xEC5919U, 0xEC68CCU, 0xEC7027U, 0xEC86A3U, 0xEC9E48U, 0xECAF9DU, 0xECB776U, 0xECCC34U, 0xECD4DFU, - 0xECE50AU, 0xECFDE1U, 0xED0802U, 0xED10E9U, 0xED213CU, 0xED39D7U, 0xED4295U, 0xED5A7EU, 0xED6BABU, 0xED7340U, - 0xED85C4U, 0xED9D2FU, 0xEDACFAU, 0xEDB411U, 0xEDCF53U, 0xEDD7B8U, 0xEDE66DU, 0xEDFE86U, 0xEE0DA8U, 0xEE1543U, - 0xEE2496U, 0xEE3C7DU, 0xEE473FU, 0xEE5FD4U, 0xEE6E01U, 0xEE76EAU, 0xEE806EU, 0xEE9885U, 0xEEA950U, 0xEEB1BBU, - 0xEECAF9U, 0xEED212U, 0xEEE3C7U, 0xEEFB2CU, 0xEF0ECFU, 0xEF1624U, 0xEF27F1U, 0xEF3F1AU, 0xEF4458U, 0xEF5CB3U, - 0xEF6D66U, 0xEF758DU, 0xEF8309U, 0xEF9BE2U, 0xEFAA37U, 0xEFB2DCU, 0xEFC99EU, 0xEFD175U, 0xEFE0A0U, 0xEFF84BU, - 0xF00292U, 0xF01A79U, 0xF02BACU, 0xF03347U, 0xF04805U, 0xF050EEU, 0xF0613BU, 0xF079D0U, 0xF08F54U, 0xF097BFU, - 0xF0A66AU, 0xF0BE81U, 0xF0C5C3U, 0xF0DD28U, 0xF0ECFDU, 0xF0F416U, 0xF101F5U, 0xF1191EU, 0xF128CBU, 0xF13020U, - 0xF14B62U, 0xF15389U, 0xF1625CU, 0xF17AB7U, 0xF18C33U, 0xF194D8U, 0xF1A50DU, 0xF1BDE6U, 0xF1C6A4U, 0xF1DE4FU, - 0xF1EF9AU, 0xF1F771U, 0xF2045FU, 0xF21CB4U, 0xF22D61U, 0xF2358AU, 0xF24EC8U, 0xF25623U, 0xF267F6U, 0xF27F1DU, - 0xF28999U, 0xF29172U, 0xF2A0A7U, 0xF2B84CU, 0xF2C30EU, 0xF2DBE5U, 0xF2EA30U, 0xF2F2DBU, 0xF30738U, 0xF31FD3U, - 0xF32E06U, 0xF336EDU, 0xF34DAFU, 0xF35544U, 0xF36491U, 0xF37C7AU, 0xF38AFEU, 0xF39215U, 0xF3A3C0U, 0xF3BB2BU, - 0xF3C069U, 0xF3D882U, 0xF3E957U, 0xF3F1BCU, 0xF40F0BU, 0xF417E0U, 0xF42635U, 0xF43EDEU, 0xF4459CU, 0xF45D77U, - 0xF46CA2U, 0xF47449U, 0xF482CDU, 0xF49A26U, 0xF4ABF3U, 0xF4B318U, 0xF4C85AU, 0xF4D0B1U, 0xF4E164U, 0xF4F98FU, - 0xF50C6CU, 0xF51487U, 0xF52552U, 0xF53DB9U, 0xF546FBU, 0xF55E10U, 0xF56FC5U, 0xF5772EU, 0xF581AAU, 0xF59941U, - 0xF5A894U, 0xF5B07FU, 0xF5CB3DU, 0xF5D3D6U, 0xF5E203U, 0xF5FAE8U, 0xF609C6U, 0xF6112DU, 0xF620F8U, 0xF63813U, - 0xF64351U, 0xF65BBAU, 0xF66A6FU, 0xF67284U, 0xF68400U, 0xF69CEBU, 0xF6AD3EU, 0xF6B5D5U, 0xF6CE97U, 0xF6D67CU, - 0xF6E7A9U, 0xF6FF42U, 0xF70AA1U, 0xF7124AU, 0xF7239FU, 0xF73B74U, 0xF74036U, 0xF758DDU, 0xF76908U, 0xF771E3U, - 0xF78767U, 0xF79F8CU, 0xF7AE59U, 0xF7B6B2U, 0xF7CDF0U, 0xF7D51BU, 0xF7E4CEU, 0xF7FC25U, 0xF80148U, 0xF819A3U, - 0xF82876U, 0xF8309DU, 0xF84BDFU, 0xF85334U, 0xF862E1U, 0xF87A0AU, 0xF88C8EU, 0xF89465U, 0xF8A5B0U, 0xF8BD5BU, - 0xF8C619U, 0xF8DEF2U, 0xF8EF27U, 0xF8F7CCU, 0xF9022FU, 0xF91AC4U, 0xF92B11U, 0xF933FAU, 0xF948B8U, 0xF95053U, - 0xF96186U, 0xF9796DU, 0xF98FE9U, 0xF99702U, 0xF9A6D7U, 0xF9BE3CU, 0xF9C57EU, 0xF9DD95U, 0xF9EC40U, 0xF9F4ABU, - 0xFA0785U, 0xFA1F6EU, 0xFA2EBBU, 0xFA3650U, 0xFA4D12U, 0xFA55F9U, 0xFA642CU, 0xFA7CC7U, 0xFA8A43U, 0xFA92A8U, - 0xFAA37DU, 0xFABB96U, 0xFAC0D4U, 0xFAD83FU, 0xFAE9EAU, 0xFAF101U, 0xFB04E2U, 0xFB1C09U, 0xFB2DDCU, 0xFB3537U, - 0xFB4E75U, 0xFB569EU, 0xFB674BU, 0xFB7FA0U, 0xFB8924U, 0xFB91CFU, 0xFBA01AU, 0xFBB8F1U, 0xFBC3B3U, 0xFBDB58U, - 0xFBEA8DU, 0xFBF266U, 0xFC0CD1U, 0xFC143AU, 0xFC25EFU, 0xFC3D04U, 0xFC4646U, 0xFC5EADU, 0xFC6F78U, 0xFC7793U, - 0xFC8117U, 0xFC99FCU, 0xFCA829U, 0xFCB0C2U, 0xFCCB80U, 0xFCD36BU, 0xFCE2BEU, 0xFCFA55U, 0xFD0FB6U, 0xFD175DU, - 0xFD2688U, 0xFD3E63U, 0xFD4521U, 0xFD5DCAU, 0xFD6C1FU, 0xFD74F4U, 0xFD8270U, 0xFD9A9BU, 0xFDAB4EU, 0xFDB3A5U, - 0xFDC8E7U, 0xFDD00CU, 0xFDE1D9U, 0xFDF932U, 0xFE0A1CU, 0xFE12F7U, 0xFE2322U, 0xFE3BC9U, 0xFE408BU, 0xFE5860U, - 0xFE69B5U, 0xFE715EU, 0xFE87DAU, 0xFE9F31U, 0xFEAEE4U, 0xFEB60FU, 0xFECD4DU, 0xFED5A6U, 0xFEE473U, 0xFEFC98U, - 0xFF097BU, 0xFF1190U, 0xFF2045U, 0xFF38AEU, 0xFF43ECU, 0xFF5B07U, 0xFF6AD2U, 0xFF7239U, 0xFF84BDU, 0xFF9C56U, - 0xFFAD83U, 0xFFB568U, 0xFFCE2AU, 0xFFD6C1U, 0xFFE714U, 0xFFFFFFU}; +static const unsigned int ENCODING_TABLE_24128[] = +{ + 0x000000U, 0x0018EBU, 0x00293EU, 0x0031D5U, 0x004A97U, 0x00527CU, 0x0063A9U, 0x007B42U, 0x008DC6U, 0x00952DU, + 0x00A4F8U, 0x00BC13U, 0x00C751U, 0x00DFBAU, 0x00EE6FU, 0x00F684U, 0x010367U, 0x011B8CU, 0x012A59U, 0x0132B2U, + 0x0149F0U, 0x01511BU, 0x0160CEU, 0x017825U, 0x018EA1U, 0x01964AU, 0x01A79FU, 0x01BF74U, 0x01C436U, 0x01DCDDU, + 0x01ED08U, 0x01F5E3U, 0x0206CDU, 0x021E26U, 0x022FF3U, 0x023718U, 0x024C5AU, 0x0254B1U, 0x026564U, 0x027D8FU, + 0x028B0BU, 0x0293E0U, 0x02A235U, 0x02BADEU, 0x02C19CU, 0x02D977U, 0x02E8A2U, 0x02F049U, 0x0305AAU, 0x031D41U, + 0x032C94U, 0x03347FU, 0x034F3DU, 0x0357D6U, 0x036603U, 0x037EE8U, 0x03886CU, 0x039087U, 0x03A152U, 0x03B9B9U, + 0x03C2FBU, 0x03DA10U, 0x03EBC5U, 0x03F32EU, 0x040D99U, 0x041572U, 0x0424A7U, 0x043C4CU, 0x04470EU, 0x045FE5U, + 0x046E30U, 0x0476DBU, 0x04805FU, 0x0498B4U, 0x04A961U, 0x04B18AU, 0x04CAC8U, 0x04D223U, 0x04E3F6U, 0x04FB1DU, + 0x050EFEU, 0x051615U, 0x0527C0U, 0x053F2BU, 0x054469U, 0x055C82U, 0x056D57U, 0x0575BCU, 0x058338U, 0x059BD3U, + 0x05AA06U, 0x05B2EDU, 0x05C9AFU, 0x05D144U, 0x05E091U, 0x05F87AU, 0x060B54U, 0x0613BFU, 0x06226AU, 0x063A81U, + 0x0641C3U, 0x065928U, 0x0668FDU, 0x067016U, 0x068692U, 0x069E79U, 0x06AFACU, 0x06B747U, 0x06CC05U, 0x06D4EEU, + 0x06E53BU, 0x06FDD0U, 0x070833U, 0x0710D8U, 0x07210DU, 0x0739E6U, 0x0742A4U, 0x075A4FU, 0x076B9AU, 0x077371U, + 0x0785F5U, 0x079D1EU, 0x07ACCBU, 0x07B420U, 0x07CF62U, 0x07D789U, 0x07E65CU, 0x07FEB7U, 0x0803DAU, 0x081B31U, + 0x082AE4U, 0x08320FU, 0x08494DU, 0x0851A6U, 0x086073U, 0x087898U, 0x088E1CU, 0x0896F7U, 0x08A722U, 0x08BFC9U, + 0x08C48BU, 0x08DC60U, 0x08EDB5U, 0x08F55EU, 0x0900BDU, 0x091856U, 0x092983U, 0x093168U, 0x094A2AU, 0x0952C1U, + 0x096314U, 0x097BFFU, 0x098D7BU, 0x099590U, 0x09A445U, 0x09BCAEU, 0x09C7ECU, 0x09DF07U, 0x09EED2U, 0x09F639U, + 0x0A0517U, 0x0A1DFCU, 0x0A2C29U, 0x0A34C2U, 0x0A4F80U, 0x0A576BU, 0x0A66BEU, 0x0A7E55U, 0x0A88D1U, 0x0A903AU, + 0x0AA1EFU, 0x0AB904U, 0x0AC246U, 0x0ADAADU, 0x0AEB78U, 0x0AF393U, 0x0B0670U, 0x0B1E9BU, 0x0B2F4EU, 0x0B37A5U, + 0x0B4CE7U, 0x0B540CU, 0x0B65D9U, 0x0B7D32U, 0x0B8BB6U, 0x0B935DU, 0x0BA288U, 0x0BBA63U, 0x0BC121U, 0x0BD9CAU, + 0x0BE81FU, 0x0BF0F4U, 0x0C0E43U, 0x0C16A8U, 0x0C277DU, 0x0C3F96U, 0x0C44D4U, 0x0C5C3FU, 0x0C6DEAU, 0x0C7501U, + 0x0C8385U, 0x0C9B6EU, 0x0CAABBU, 0x0CB250U, 0x0CC912U, 0x0CD1F9U, 0x0CE02CU, 0x0CF8C7U, 0x0D0D24U, 0x0D15CFU, + 0x0D241AU, 0x0D3CF1U, 0x0D47B3U, 0x0D5F58U, 0x0D6E8DU, 0x0D7666U, 0x0D80E2U, 0x0D9809U, 0x0DA9DCU, 0x0DB137U, + 0x0DCA75U, 0x0DD29EU, 0x0DE34BU, 0x0DFBA0U, 0x0E088EU, 0x0E1065U, 0x0E21B0U, 0x0E395BU, 0x0E4219U, 0x0E5AF2U, + 0x0E6B27U, 0x0E73CCU, 0x0E8548U, 0x0E9DA3U, 0x0EAC76U, 0x0EB49DU, 0x0ECFDFU, 0x0ED734U, 0x0EE6E1U, 0x0EFE0AU, + 0x0F0BE9U, 0x0F1302U, 0x0F22D7U, 0x0F3A3CU, 0x0F417EU, 0x0F5995U, 0x0F6840U, 0x0F70ABU, 0x0F862FU, 0x0F9EC4U, + 0x0FAF11U, 0x0FB7FAU, 0x0FCCB8U, 0x0FD453U, 0x0FE586U, 0x0FFD6DU, 0x1007B4U, 0x101F5FU, 0x102E8AU, 0x103661U, + 0x104D23U, 0x1055C8U, 0x10641DU, 0x107CF6U, 0x108A72U, 0x109299U, 0x10A34CU, 0x10BBA7U, 0x10C0E5U, 0x10D80EU, + 0x10E9DBU, 0x10F130U, 0x1104D3U, 0x111C38U, 0x112DEDU, 0x113506U, 0x114E44U, 0x1156AFU, 0x11677AU, 0x117F91U, + 0x118915U, 0x1191FEU, 0x11A02BU, 0x11B8C0U, 0x11C382U, 0x11DB69U, 0x11EABCU, 0x11F257U, 0x120179U, 0x121992U, + 0x122847U, 0x1230ACU, 0x124BEEU, 0x125305U, 0x1262D0U, 0x127A3BU, 0x128CBFU, 0x129454U, 0x12A581U, 0x12BD6AU, + 0x12C628U, 0x12DEC3U, 0x12EF16U, 0x12F7FDU, 0x13021EU, 0x131AF5U, 0x132B20U, 0x1333CBU, 0x134889U, 0x135062U, + 0x1361B7U, 0x13795CU, 0x138FD8U, 0x139733U, 0x13A6E6U, 0x13BE0DU, 0x13C54FU, 0x13DDA4U, 0x13EC71U, 0x13F49AU, + 0x140A2DU, 0x1412C6U, 0x142313U, 0x143BF8U, 0x1440BAU, 0x145851U, 0x146984U, 0x14716FU, 0x1487EBU, 0x149F00U, + 0x14AED5U, 0x14B63EU, 0x14CD7CU, 0x14D597U, 0x14E442U, 0x14FCA9U, 0x15094AU, 0x1511A1U, 0x152074U, 0x15389FU, + 0x1543DDU, 0x155B36U, 0x156AE3U, 0x157208U, 0x15848CU, 0x159C67U, 0x15ADB2U, 0x15B559U, 0x15CE1BU, 0x15D6F0U, + 0x15E725U, 0x15FFCEU, 0x160CE0U, 0x16140BU, 0x1625DEU, 0x163D35U, 0x164677U, 0x165E9CU, 0x166F49U, 0x1677A2U, + 0x168126U, 0x1699CDU, 0x16A818U, 0x16B0F3U, 0x16CBB1U, 0x16D35AU, 0x16E28FU, 0x16FA64U, 0x170F87U, 0x17176CU, + 0x1726B9U, 0x173E52U, 0x174510U, 0x175DFBU, 0x176C2EU, 0x1774C5U, 0x178241U, 0x179AAAU, 0x17AB7FU, 0x17B394U, + 0x17C8D6U, 0x17D03DU, 0x17E1E8U, 0x17F903U, 0x18046EU, 0x181C85U, 0x182D50U, 0x1835BBU, 0x184EF9U, 0x185612U, + 0x1867C7U, 0x187F2CU, 0x1889A8U, 0x189143U, 0x18A096U, 0x18B87DU, 0x18C33FU, 0x18DBD4U, 0x18EA01U, 0x18F2EAU, + 0x190709U, 0x191FE2U, 0x192E37U, 0x1936DCU, 0x194D9EU, 0x195575U, 0x1964A0U, 0x197C4BU, 0x198ACFU, 0x199224U, + 0x19A3F1U, 0x19BB1AU, 0x19C058U, 0x19D8B3U, 0x19E966U, 0x19F18DU, 0x1A02A3U, 0x1A1A48U, 0x1A2B9DU, 0x1A3376U, + 0x1A4834U, 0x1A50DFU, 0x1A610AU, 0x1A79E1U, 0x1A8F65U, 0x1A978EU, 0x1AA65BU, 0x1ABEB0U, 0x1AC5F2U, 0x1ADD19U, + 0x1AECCCU, 0x1AF427U, 0x1B01C4U, 0x1B192FU, 0x1B28FAU, 0x1B3011U, 0x1B4B53U, 0x1B53B8U, 0x1B626DU, 0x1B7A86U, + 0x1B8C02U, 0x1B94E9U, 0x1BA53CU, 0x1BBDD7U, 0x1BC695U, 0x1BDE7EU, 0x1BEFABU, 0x1BF740U, 0x1C09F7U, 0x1C111CU, + 0x1C20C9U, 0x1C3822U, 0x1C4360U, 0x1C5B8BU, 0x1C6A5EU, 0x1C72B5U, 0x1C8431U, 0x1C9CDAU, 0x1CAD0FU, 0x1CB5E4U, + 0x1CCEA6U, 0x1CD64DU, 0x1CE798U, 0x1CFF73U, 0x1D0A90U, 0x1D127BU, 0x1D23AEU, 0x1D3B45U, 0x1D4007U, 0x1D58ECU, + 0x1D6939U, 0x1D71D2U, 0x1D8756U, 0x1D9FBDU, 0x1DAE68U, 0x1DB683U, 0x1DCDC1U, 0x1DD52AU, 0x1DE4FFU, 0x1DFC14U, + 0x1E0F3AU, 0x1E17D1U, 0x1E2604U, 0x1E3EEFU, 0x1E45ADU, 0x1E5D46U, 0x1E6C93U, 0x1E7478U, 0x1E82FCU, 0x1E9A17U, + 0x1EABC2U, 0x1EB329U, 0x1EC86BU, 0x1ED080U, 0x1EE155U, 0x1EF9BEU, 0x1F0C5DU, 0x1F14B6U, 0x1F2563U, 0x1F3D88U, + 0x1F46CAU, 0x1F5E21U, 0x1F6FF4U, 0x1F771FU, 0x1F819BU, 0x1F9970U, 0x1FA8A5U, 0x1FB04EU, 0x1FCB0CU, 0x1FD3E7U, + 0x1FE232U, 0x1FFAD9U, 0x200F68U, 0x201783U, 0x202656U, 0x203EBDU, 0x2045FFU, 0x205D14U, 0x206CC1U, 0x20742AU, + 0x2082AEU, 0x209A45U, 0x20AB90U, 0x20B37BU, 0x20C839U, 0x20D0D2U, 0x20E107U, 0x20F9ECU, 0x210C0FU, 0x2114E4U, + 0x212531U, 0x213DDAU, 0x214698U, 0x215E73U, 0x216FA6U, 0x21774DU, 0x2181C9U, 0x219922U, 0x21A8F7U, 0x21B01CU, + 0x21CB5EU, 0x21D3B5U, 0x21E260U, 0x21FA8BU, 0x2209A5U, 0x22114EU, 0x22209BU, 0x223870U, 0x224332U, 0x225BD9U, + 0x226A0CU, 0x2272E7U, 0x228463U, 0x229C88U, 0x22AD5DU, 0x22B5B6U, 0x22CEF4U, 0x22D61FU, 0x22E7CAU, 0x22FF21U, + 0x230AC2U, 0x231229U, 0x2323FCU, 0x233B17U, 0x234055U, 0x2358BEU, 0x23696BU, 0x237180U, 0x238704U, 0x239FEFU, + 0x23AE3AU, 0x23B6D1U, 0x23CD93U, 0x23D578U, 0x23E4ADU, 0x23FC46U, 0x2402F1U, 0x241A1AU, 0x242BCFU, 0x243324U, + 0x244866U, 0x24508DU, 0x246158U, 0x2479B3U, 0x248F37U, 0x2497DCU, 0x24A609U, 0x24BEE2U, 0x24C5A0U, 0x24DD4BU, + 0x24EC9EU, 0x24F475U, 0x250196U, 0x25197DU, 0x2528A8U, 0x253043U, 0x254B01U, 0x2553EAU, 0x25623FU, 0x257AD4U, + 0x258C50U, 0x2594BBU, 0x25A56EU, 0x25BD85U, 0x25C6C7U, 0x25DE2CU, 0x25EFF9U, 0x25F712U, 0x26043CU, 0x261CD7U, + 0x262D02U, 0x2635E9U, 0x264EABU, 0x265640U, 0x266795U, 0x267F7EU, 0x2689FAU, 0x269111U, 0x26A0C4U, 0x26B82FU, + 0x26C36DU, 0x26DB86U, 0x26EA53U, 0x26F2B8U, 0x27075BU, 0x271FB0U, 0x272E65U, 0x27368EU, 0x274DCCU, 0x275527U, + 0x2764F2U, 0x277C19U, 0x278A9DU, 0x279276U, 0x27A3A3U, 0x27BB48U, 0x27C00AU, 0x27D8E1U, 0x27E934U, 0x27F1DFU, + 0x280CB2U, 0x281459U, 0x28258CU, 0x283D67U, 0x284625U, 0x285ECEU, 0x286F1BU, 0x2877F0U, 0x288174U, 0x28999FU, + 0x28A84AU, 0x28B0A1U, 0x28CBE3U, 0x28D308U, 0x28E2DDU, 0x28FA36U, 0x290FD5U, 0x29173EU, 0x2926EBU, 0x293E00U, + 0x294542U, 0x295DA9U, 0x296C7CU, 0x297497U, 0x298213U, 0x299AF8U, 0x29AB2DU, 0x29B3C6U, 0x29C884U, 0x29D06FU, + 0x29E1BAU, 0x29F951U, 0x2A0A7FU, 0x2A1294U, 0x2A2341U, 0x2A3BAAU, 0x2A40E8U, 0x2A5803U, 0x2A69D6U, 0x2A713DU, + 0x2A87B9U, 0x2A9F52U, 0x2AAE87U, 0x2AB66CU, 0x2ACD2EU, 0x2AD5C5U, 0x2AE410U, 0x2AFCFBU, 0x2B0918U, 0x2B11F3U, + 0x2B2026U, 0x2B38CDU, 0x2B438FU, 0x2B5B64U, 0x2B6AB1U, 0x2B725AU, 0x2B84DEU, 0x2B9C35U, 0x2BADE0U, 0x2BB50BU, + 0x2BCE49U, 0x2BD6A2U, 0x2BE777U, 0x2BFF9CU, 0x2C012BU, 0x2C19C0U, 0x2C2815U, 0x2C30FEU, 0x2C4BBCU, 0x2C5357U, + 0x2C6282U, 0x2C7A69U, 0x2C8CEDU, 0x2C9406U, 0x2CA5D3U, 0x2CBD38U, 0x2CC67AU, 0x2CDE91U, 0x2CEF44U, 0x2CF7AFU, + 0x2D024CU, 0x2D1AA7U, 0x2D2B72U, 0x2D3399U, 0x2D48DBU, 0x2D5030U, 0x2D61E5U, 0x2D790EU, 0x2D8F8AU, 0x2D9761U, + 0x2DA6B4U, 0x2DBE5FU, 0x2DC51DU, 0x2DDDF6U, 0x2DEC23U, 0x2DF4C8U, 0x2E07E6U, 0x2E1F0DU, 0x2E2ED8U, 0x2E3633U, + 0x2E4D71U, 0x2E559AU, 0x2E644FU, 0x2E7CA4U, 0x2E8A20U, 0x2E92CBU, 0x2EA31EU, 0x2EBBF5U, 0x2EC0B7U, 0x2ED85CU, + 0x2EE989U, 0x2EF162U, 0x2F0481U, 0x2F1C6AU, 0x2F2DBFU, 0x2F3554U, 0x2F4E16U, 0x2F56FDU, 0x2F6728U, 0x2F7FC3U, + 0x2F8947U, 0x2F91ACU, 0x2FA079U, 0x2FB892U, 0x2FC3D0U, 0x2FDB3BU, 0x2FEAEEU, 0x2FF205U, 0x3008DCU, 0x301037U, + 0x3021E2U, 0x303909U, 0x30424BU, 0x305AA0U, 0x306B75U, 0x30739EU, 0x30851AU, 0x309DF1U, 0x30AC24U, 0x30B4CFU, + 0x30CF8DU, 0x30D766U, 0x30E6B3U, 0x30FE58U, 0x310BBBU, 0x311350U, 0x312285U, 0x313A6EU, 0x31412CU, 0x3159C7U, + 0x316812U, 0x3170F9U, 0x31867DU, 0x319E96U, 0x31AF43U, 0x31B7A8U, 0x31CCEAU, 0x31D401U, 0x31E5D4U, 0x31FD3FU, + 0x320E11U, 0x3216FAU, 0x32272FU, 0x323FC4U, 0x324486U, 0x325C6DU, 0x326DB8U, 0x327553U, 0x3283D7U, 0x329B3CU, + 0x32AAE9U, 0x32B202U, 0x32C940U, 0x32D1ABU, 0x32E07EU, 0x32F895U, 0x330D76U, 0x33159DU, 0x332448U, 0x333CA3U, + 0x3347E1U, 0x335F0AU, 0x336EDFU, 0x337634U, 0x3380B0U, 0x33985BU, 0x33A98EU, 0x33B165U, 0x33CA27U, 0x33D2CCU, + 0x33E319U, 0x33FBF2U, 0x340545U, 0x341DAEU, 0x342C7BU, 0x343490U, 0x344FD2U, 0x345739U, 0x3466ECU, 0x347E07U, + 0x348883U, 0x349068U, 0x34A1BDU, 0x34B956U, 0x34C214U, 0x34DAFFU, 0x34EB2AU, 0x34F3C1U, 0x350622U, 0x351EC9U, + 0x352F1CU, 0x3537F7U, 0x354CB5U, 0x35545EU, 0x35658BU, 0x357D60U, 0x358BE4U, 0x35930FU, 0x35A2DAU, 0x35BA31U, + 0x35C173U, 0x35D998U, 0x35E84DU, 0x35F0A6U, 0x360388U, 0x361B63U, 0x362AB6U, 0x36325DU, 0x36491FU, 0x3651F4U, + 0x366021U, 0x3678CAU, 0x368E4EU, 0x3696A5U, 0x36A770U, 0x36BF9BU, 0x36C4D9U, 0x36DC32U, 0x36EDE7U, 0x36F50CU, + 0x3700EFU, 0x371804U, 0x3729D1U, 0x37313AU, 0x374A78U, 0x375293U, 0x376346U, 0x377BADU, 0x378D29U, 0x3795C2U, + 0x37A417U, 0x37BCFCU, 0x37C7BEU, 0x37DF55U, 0x37EE80U, 0x37F66BU, 0x380B06U, 0x3813EDU, 0x382238U, 0x383AD3U, + 0x384191U, 0x38597AU, 0x3868AFU, 0x387044U, 0x3886C0U, 0x389E2BU, 0x38AFFEU, 0x38B715U, 0x38CC57U, 0x38D4BCU, + 0x38E569U, 0x38FD82U, 0x390861U, 0x39108AU, 0x39215FU, 0x3939B4U, 0x3942F6U, 0x395A1DU, 0x396BC8U, 0x397323U, + 0x3985A7U, 0x399D4CU, 0x39AC99U, 0x39B472U, 0x39CF30U, 0x39D7DBU, 0x39E60EU, 0x39FEE5U, 0x3A0DCBU, 0x3A1520U, + 0x3A24F5U, 0x3A3C1EU, 0x3A475CU, 0x3A5FB7U, 0x3A6E62U, 0x3A7689U, 0x3A800DU, 0x3A98E6U, 0x3AA933U, 0x3AB1D8U, + 0x3ACA9AU, 0x3AD271U, 0x3AE3A4U, 0x3AFB4FU, 0x3B0EACU, 0x3B1647U, 0x3B2792U, 0x3B3F79U, 0x3B443BU, 0x3B5CD0U, + 0x3B6D05U, 0x3B75EEU, 0x3B836AU, 0x3B9B81U, 0x3BAA54U, 0x3BB2BFU, 0x3BC9FDU, 0x3BD116U, 0x3BE0C3U, 0x3BF828U, + 0x3C069FU, 0x3C1E74U, 0x3C2FA1U, 0x3C374AU, 0x3C4C08U, 0x3C54E3U, 0x3C6536U, 0x3C7DDDU, 0x3C8B59U, 0x3C93B2U, + 0x3CA267U, 0x3CBA8CU, 0x3CC1CEU, 0x3CD925U, 0x3CE8F0U, 0x3CF01BU, 0x3D05F8U, 0x3D1D13U, 0x3D2CC6U, 0x3D342DU, + 0x3D4F6FU, 0x3D5784U, 0x3D6651U, 0x3D7EBAU, 0x3D883EU, 0x3D90D5U, 0x3DA100U, 0x3DB9EBU, 0x3DC2A9U, 0x3DDA42U, + 0x3DEB97U, 0x3DF37CU, 0x3E0052U, 0x3E18B9U, 0x3E296CU, 0x3E3187U, 0x3E4AC5U, 0x3E522EU, 0x3E63FBU, 0x3E7B10U, + 0x3E8D94U, 0x3E957FU, 0x3EA4AAU, 0x3EBC41U, 0x3EC703U, 0x3EDFE8U, 0x3EEE3DU, 0x3EF6D6U, 0x3F0335U, 0x3F1BDEU, + 0x3F2A0BU, 0x3F32E0U, 0x3F49A2U, 0x3F5149U, 0x3F609CU, 0x3F7877U, 0x3F8EF3U, 0x3F9618U, 0x3FA7CDU, 0x3FBF26U, + 0x3FC464U, 0x3FDC8FU, 0x3FED5AU, 0x3FF5B1U, 0x40063BU, 0x401ED0U, 0x402F05U, 0x4037EEU, 0x404CACU, 0x405447U, + 0x406592U, 0x407D79U, 0x408BFDU, 0x409316U, 0x40A2C3U, 0x40BA28U, 0x40C16AU, 0x40D981U, 0x40E854U, 0x40F0BFU, + 0x41055CU, 0x411DB7U, 0x412C62U, 0x413489U, 0x414FCBU, 0x415720U, 0x4166F5U, 0x417E1EU, 0x41889AU, 0x419071U, + 0x41A1A4U, 0x41B94FU, 0x41C20DU, 0x41DAE6U, 0x41EB33U, 0x41F3D8U, 0x4200F6U, 0x42181DU, 0x4229C8U, 0x423123U, + 0x424A61U, 0x42528AU, 0x42635FU, 0x427BB4U, 0x428D30U, 0x4295DBU, 0x42A40EU, 0x42BCE5U, 0x42C7A7U, 0x42DF4CU, + 0x42EE99U, 0x42F672U, 0x430391U, 0x431B7AU, 0x432AAFU, 0x433244U, 0x434906U, 0x4351EDU, 0x436038U, 0x4378D3U, + 0x438E57U, 0x4396BCU, 0x43A769U, 0x43BF82U, 0x43C4C0U, 0x43DC2BU, 0x43EDFEU, 0x43F515U, 0x440BA2U, 0x441349U, + 0x44229CU, 0x443A77U, 0x444135U, 0x4459DEU, 0x44680BU, 0x4470E0U, 0x448664U, 0x449E8FU, 0x44AF5AU, 0x44B7B1U, + 0x44CCF3U, 0x44D418U, 0x44E5CDU, 0x44FD26U, 0x4508C5U, 0x45102EU, 0x4521FBU, 0x453910U, 0x454252U, 0x455AB9U, + 0x456B6CU, 0x457387U, 0x458503U, 0x459DE8U, 0x45AC3DU, 0x45B4D6U, 0x45CF94U, 0x45D77FU, 0x45E6AAU, 0x45FE41U, + 0x460D6FU, 0x461584U, 0x462451U, 0x463CBAU, 0x4647F8U, 0x465F13U, 0x466EC6U, 0x46762DU, 0x4680A9U, 0x469842U, + 0x46A997U, 0x46B17CU, 0x46CA3EU, 0x46D2D5U, 0x46E300U, 0x46FBEBU, 0x470E08U, 0x4716E3U, 0x472736U, 0x473FDDU, + 0x47449FU, 0x475C74U, 0x476DA1U, 0x47754AU, 0x4783CEU, 0x479B25U, 0x47AAF0U, 0x47B21BU, 0x47C959U, 0x47D1B2U, + 0x47E067U, 0x47F88CU, 0x4805E1U, 0x481D0AU, 0x482CDFU, 0x483434U, 0x484F76U, 0x48579DU, 0x486648U, 0x487EA3U, + 0x488827U, 0x4890CCU, 0x48A119U, 0x48B9F2U, 0x48C2B0U, 0x48DA5BU, 0x48EB8EU, 0x48F365U, 0x490686U, 0x491E6DU, + 0x492FB8U, 0x493753U, 0x494C11U, 0x4954FAU, 0x49652FU, 0x497DC4U, 0x498B40U, 0x4993ABU, 0x49A27EU, 0x49BA95U, + 0x49C1D7U, 0x49D93CU, 0x49E8E9U, 0x49F002U, 0x4A032CU, 0x4A1BC7U, 0x4A2A12U, 0x4A32F9U, 0x4A49BBU, 0x4A5150U, + 0x4A6085U, 0x4A786EU, 0x4A8EEAU, 0x4A9601U, 0x4AA7D4U, 0x4ABF3FU, 0x4AC47DU, 0x4ADC96U, 0x4AED43U, 0x4AF5A8U, + 0x4B004BU, 0x4B18A0U, 0x4B2975U, 0x4B319EU, 0x4B4ADCU, 0x4B5237U, 0x4B63E2U, 0x4B7B09U, 0x4B8D8DU, 0x4B9566U, + 0x4BA4B3U, 0x4BBC58U, 0x4BC71AU, 0x4BDFF1U, 0x4BEE24U, 0x4BF6CFU, 0x4C0878U, 0x4C1093U, 0x4C2146U, 0x4C39ADU, + 0x4C42EFU, 0x4C5A04U, 0x4C6BD1U, 0x4C733AU, 0x4C85BEU, 0x4C9D55U, 0x4CAC80U, 0x4CB46BU, 0x4CCF29U, 0x4CD7C2U, + 0x4CE617U, 0x4CFEFCU, 0x4D0B1FU, 0x4D13F4U, 0x4D2221U, 0x4D3ACAU, 0x4D4188U, 0x4D5963U, 0x4D68B6U, 0x4D705DU, + 0x4D86D9U, 0x4D9E32U, 0x4DAFE7U, 0x4DB70CU, 0x4DCC4EU, 0x4DD4A5U, 0x4DE570U, 0x4DFD9BU, 0x4E0EB5U, 0x4E165EU, + 0x4E278BU, 0x4E3F60U, 0x4E4422U, 0x4E5CC9U, 0x4E6D1CU, 0x4E75F7U, 0x4E8373U, 0x4E9B98U, 0x4EAA4DU, 0x4EB2A6U, + 0x4EC9E4U, 0x4ED10FU, 0x4EE0DAU, 0x4EF831U, 0x4F0DD2U, 0x4F1539U, 0x4F24ECU, 0x4F3C07U, 0x4F4745U, 0x4F5FAEU, + 0x4F6E7BU, 0x4F7690U, 0x4F8014U, 0x4F98FFU, 0x4FA92AU, 0x4FB1C1U, 0x4FCA83U, 0x4FD268U, 0x4FE3BDU, 0x4FFB56U, + 0x50018FU, 0x501964U, 0x5028B1U, 0x50305AU, 0x504B18U, 0x5053F3U, 0x506226U, 0x507ACDU, 0x508C49U, 0x5094A2U, + 0x50A577U, 0x50BD9CU, 0x50C6DEU, 0x50DE35U, 0x50EFE0U, 0x50F70BU, 0x5102E8U, 0x511A03U, 0x512BD6U, 0x51333DU, + 0x51487FU, 0x515094U, 0x516141U, 0x5179AAU, 0x518F2EU, 0x5197C5U, 0x51A610U, 0x51BEFBU, 0x51C5B9U, 0x51DD52U, + 0x51EC87U, 0x51F46CU, 0x520742U, 0x521FA9U, 0x522E7CU, 0x523697U, 0x524DD5U, 0x52553EU, 0x5264EBU, 0x527C00U, + 0x528A84U, 0x52926FU, 0x52A3BAU, 0x52BB51U, 0x52C013U, 0x52D8F8U, 0x52E92DU, 0x52F1C6U, 0x530425U, 0x531CCEU, + 0x532D1BU, 0x5335F0U, 0x534EB2U, 0x535659U, 0x53678CU, 0x537F67U, 0x5389E3U, 0x539108U, 0x53A0DDU, 0x53B836U, + 0x53C374U, 0x53DB9FU, 0x53EA4AU, 0x53F2A1U, 0x540C16U, 0x5414FDU, 0x542528U, 0x543DC3U, 0x544681U, 0x545E6AU, + 0x546FBFU, 0x547754U, 0x5481D0U, 0x54993BU, 0x54A8EEU, 0x54B005U, 0x54CB47U, 0x54D3ACU, 0x54E279U, 0x54FA92U, + 0x550F71U, 0x55179AU, 0x55264FU, 0x553EA4U, 0x5545E6U, 0x555D0DU, 0x556CD8U, 0x557433U, 0x5582B7U, 0x559A5CU, + 0x55AB89U, 0x55B362U, 0x55C820U, 0x55D0CBU, 0x55E11EU, 0x55F9F5U, 0x560ADBU, 0x561230U, 0x5623E5U, 0x563B0EU, + 0x56404CU, 0x5658A7U, 0x566972U, 0x567199U, 0x56871DU, 0x569FF6U, 0x56AE23U, 0x56B6C8U, 0x56CD8AU, 0x56D561U, + 0x56E4B4U, 0x56FC5FU, 0x5709BCU, 0x571157U, 0x572082U, 0x573869U, 0x57432BU, 0x575BC0U, 0x576A15U, 0x5772FEU, + 0x57847AU, 0x579C91U, 0x57AD44U, 0x57B5AFU, 0x57CEEDU, 0x57D606U, 0x57E7D3U, 0x57FF38U, 0x580255U, 0x581ABEU, + 0x582B6BU, 0x583380U, 0x5848C2U, 0x585029U, 0x5861FCU, 0x587917U, 0x588F93U, 0x589778U, 0x58A6ADU, 0x58BE46U, + 0x58C504U, 0x58DDEFU, 0x58EC3AU, 0x58F4D1U, 0x590132U, 0x5919D9U, 0x59280CU, 0x5930E7U, 0x594BA5U, 0x59534EU, + 0x59629BU, 0x597A70U, 0x598CF4U, 0x59941FU, 0x59A5CAU, 0x59BD21U, 0x59C663U, 0x59DE88U, 0x59EF5DU, 0x59F7B6U, + 0x5A0498U, 0x5A1C73U, 0x5A2DA6U, 0x5A354DU, 0x5A4E0FU, 0x5A56E4U, 0x5A6731U, 0x5A7FDAU, 0x5A895EU, 0x5A91B5U, + 0x5AA060U, 0x5AB88BU, 0x5AC3C9U, 0x5ADB22U, 0x5AEAF7U, 0x5AF21CU, 0x5B07FFU, 0x5B1F14U, 0x5B2EC1U, 0x5B362AU, + 0x5B4D68U, 0x5B5583U, 0x5B6456U, 0x5B7CBDU, 0x5B8A39U, 0x5B92D2U, 0x5BA307U, 0x5BBBECU, 0x5BC0AEU, 0x5BD845U, + 0x5BE990U, 0x5BF17BU, 0x5C0FCCU, 0x5C1727U, 0x5C26F2U, 0x5C3E19U, 0x5C455BU, 0x5C5DB0U, 0x5C6C65U, 0x5C748EU, + 0x5C820AU, 0x5C9AE1U, 0x5CAB34U, 0x5CB3DFU, 0x5CC89DU, 0x5CD076U, 0x5CE1A3U, 0x5CF948U, 0x5D0CABU, 0x5D1440U, + 0x5D2595U, 0x5D3D7EU, 0x5D463CU, 0x5D5ED7U, 0x5D6F02U, 0x5D77E9U, 0x5D816DU, 0x5D9986U, 0x5DA853U, 0x5DB0B8U, + 0x5DCBFAU, 0x5DD311U, 0x5DE2C4U, 0x5DFA2FU, 0x5E0901U, 0x5E11EAU, 0x5E203FU, 0x5E38D4U, 0x5E4396U, 0x5E5B7DU, + 0x5E6AA8U, 0x5E7243U, 0x5E84C7U, 0x5E9C2CU, 0x5EADF9U, 0x5EB512U, 0x5ECE50U, 0x5ED6BBU, 0x5EE76EU, 0x5EFF85U, + 0x5F0A66U, 0x5F128DU, 0x5F2358U, 0x5F3BB3U, 0x5F40F1U, 0x5F581AU, 0x5F69CFU, 0x5F7124U, 0x5F87A0U, 0x5F9F4BU, + 0x5FAE9EU, 0x5FB675U, 0x5FCD37U, 0x5FD5DCU, 0x5FE409U, 0x5FFCE2U, 0x600953U, 0x6011B8U, 0x60206DU, 0x603886U, + 0x6043C4U, 0x605B2FU, 0x606AFAU, 0x607211U, 0x608495U, 0x609C7EU, 0x60ADABU, 0x60B540U, 0x60CE02U, 0x60D6E9U, + 0x60E73CU, 0x60FFD7U, 0x610A34U, 0x6112DFU, 0x61230AU, 0x613BE1U, 0x6140A3U, 0x615848U, 0x61699DU, 0x617176U, + 0x6187F2U, 0x619F19U, 0x61AECCU, 0x61B627U, 0x61CD65U, 0x61D58EU, 0x61E45BU, 0x61FCB0U, 0x620F9EU, 0x621775U, + 0x6226A0U, 0x623E4BU, 0x624509U, 0x625DE2U, 0x626C37U, 0x6274DCU, 0x628258U, 0x629AB3U, 0x62AB66U, 0x62B38DU, + 0x62C8CFU, 0x62D024U, 0x62E1F1U, 0x62F91AU, 0x630CF9U, 0x631412U, 0x6325C7U, 0x633D2CU, 0x63466EU, 0x635E85U, + 0x636F50U, 0x6377BBU, 0x63813FU, 0x6399D4U, 0x63A801U, 0x63B0EAU, 0x63CBA8U, 0x63D343U, 0x63E296U, 0x63FA7DU, + 0x6404CAU, 0x641C21U, 0x642DF4U, 0x64351FU, 0x644E5DU, 0x6456B6U, 0x646763U, 0x647F88U, 0x64890CU, 0x6491E7U, + 0x64A032U, 0x64B8D9U, 0x64C39BU, 0x64DB70U, 0x64EAA5U, 0x64F24EU, 0x6507ADU, 0x651F46U, 0x652E93U, 0x653678U, + 0x654D3AU, 0x6555D1U, 0x656404U, 0x657CEFU, 0x658A6BU, 0x659280U, 0x65A355U, 0x65BBBEU, 0x65C0FCU, 0x65D817U, + 0x65E9C2U, 0x65F129U, 0x660207U, 0x661AECU, 0x662B39U, 0x6633D2U, 0x664890U, 0x66507BU, 0x6661AEU, 0x667945U, + 0x668FC1U, 0x66972AU, 0x66A6FFU, 0x66BE14U, 0x66C556U, 0x66DDBDU, 0x66EC68U, 0x66F483U, 0x670160U, 0x67198BU, + 0x67285EU, 0x6730B5U, 0x674BF7U, 0x67531CU, 0x6762C9U, 0x677A22U, 0x678CA6U, 0x67944DU, 0x67A598U, 0x67BD73U, + 0x67C631U, 0x67DEDAU, 0x67EF0FU, 0x67F7E4U, 0x680A89U, 0x681262U, 0x6823B7U, 0x683B5CU, 0x68401EU, 0x6858F5U, + 0x686920U, 0x6871CBU, 0x68874FU, 0x689FA4U, 0x68AE71U, 0x68B69AU, 0x68CDD8U, 0x68D533U, 0x68E4E6U, 0x68FC0DU, + 0x6909EEU, 0x691105U, 0x6920D0U, 0x69383BU, 0x694379U, 0x695B92U, 0x696A47U, 0x6972ACU, 0x698428U, 0x699CC3U, + 0x69AD16U, 0x69B5FDU, 0x69CEBFU, 0x69D654U, 0x69E781U, 0x69FF6AU, 0x6A0C44U, 0x6A14AFU, 0x6A257AU, 0x6A3D91U, + 0x6A46D3U, 0x6A5E38U, 0x6A6FEDU, 0x6A7706U, 0x6A8182U, 0x6A9969U, 0x6AA8BCU, 0x6AB057U, 0x6ACB15U, 0x6AD3FEU, + 0x6AE22BU, 0x6AFAC0U, 0x6B0F23U, 0x6B17C8U, 0x6B261DU, 0x6B3EF6U, 0x6B45B4U, 0x6B5D5FU, 0x6B6C8AU, 0x6B7461U, + 0x6B82E5U, 0x6B9A0EU, 0x6BABDBU, 0x6BB330U, 0x6BC872U, 0x6BD099U, 0x6BE14CU, 0x6BF9A7U, 0x6C0710U, 0x6C1FFBU, + 0x6C2E2EU, 0x6C36C5U, 0x6C4D87U, 0x6C556CU, 0x6C64B9U, 0x6C7C52U, 0x6C8AD6U, 0x6C923DU, 0x6CA3E8U, 0x6CBB03U, + 0x6CC041U, 0x6CD8AAU, 0x6CE97FU, 0x6CF194U, 0x6D0477U, 0x6D1C9CU, 0x6D2D49U, 0x6D35A2U, 0x6D4EE0U, 0x6D560BU, + 0x6D67DEU, 0x6D7F35U, 0x6D89B1U, 0x6D915AU, 0x6DA08FU, 0x6DB864U, 0x6DC326U, 0x6DDBCDU, 0x6DEA18U, 0x6DF2F3U, + 0x6E01DDU, 0x6E1936U, 0x6E28E3U, 0x6E3008U, 0x6E4B4AU, 0x6E53A1U, 0x6E6274U, 0x6E7A9FU, 0x6E8C1BU, 0x6E94F0U, + 0x6EA525U, 0x6EBDCEU, 0x6EC68CU, 0x6EDE67U, 0x6EEFB2U, 0x6EF759U, 0x6F02BAU, 0x6F1A51U, 0x6F2B84U, 0x6F336FU, + 0x6F482DU, 0x6F50C6U, 0x6F6113U, 0x6F79F8U, 0x6F8F7CU, 0x6F9797U, 0x6FA642U, 0x6FBEA9U, 0x6FC5EBU, 0x6FDD00U, + 0x6FECD5U, 0x6FF43EU, 0x700EE7U, 0x70160CU, 0x7027D9U, 0x703F32U, 0x704470U, 0x705C9BU, 0x706D4EU, 0x7075A5U, + 0x708321U, 0x709BCAU, 0x70AA1FU, 0x70B2F4U, 0x70C9B6U, 0x70D15DU, 0x70E088U, 0x70F863U, 0x710D80U, 0x71156BU, + 0x7124BEU, 0x713C55U, 0x714717U, 0x715FFCU, 0x716E29U, 0x7176C2U, 0x718046U, 0x7198ADU, 0x71A978U, 0x71B193U, + 0x71CAD1U, 0x71D23AU, 0x71E3EFU, 0x71FB04U, 0x72082AU, 0x7210C1U, 0x722114U, 0x7239FFU, 0x7242BDU, 0x725A56U, + 0x726B83U, 0x727368U, 0x7285ECU, 0x729D07U, 0x72ACD2U, 0x72B439U, 0x72CF7BU, 0x72D790U, 0x72E645U, 0x72FEAEU, + 0x730B4DU, 0x7313A6U, 0x732273U, 0x733A98U, 0x7341DAU, 0x735931U, 0x7368E4U, 0x73700FU, 0x73868BU, 0x739E60U, + 0x73AFB5U, 0x73B75EU, 0x73CC1CU, 0x73D4F7U, 0x73E522U, 0x73FDC9U, 0x74037EU, 0x741B95U, 0x742A40U, 0x7432ABU, + 0x7449E9U, 0x745102U, 0x7460D7U, 0x74783CU, 0x748EB8U, 0x749653U, 0x74A786U, 0x74BF6DU, 0x74C42FU, 0x74DCC4U, + 0x74ED11U, 0x74F5FAU, 0x750019U, 0x7518F2U, 0x752927U, 0x7531CCU, 0x754A8EU, 0x755265U, 0x7563B0U, 0x757B5BU, + 0x758DDFU, 0x759534U, 0x75A4E1U, 0x75BC0AU, 0x75C748U, 0x75DFA3U, 0x75EE76U, 0x75F69DU, 0x7605B3U, 0x761D58U, + 0x762C8DU, 0x763466U, 0x764F24U, 0x7657CFU, 0x76661AU, 0x767EF1U, 0x768875U, 0x76909EU, 0x76A14BU, 0x76B9A0U, + 0x76C2E2U, 0x76DA09U, 0x76EBDCU, 0x76F337U, 0x7706D4U, 0x771E3FU, 0x772FEAU, 0x773701U, 0x774C43U, 0x7754A8U, + 0x77657DU, 0x777D96U, 0x778B12U, 0x7793F9U, 0x77A22CU, 0x77BAC7U, 0x77C185U, 0x77D96EU, 0x77E8BBU, 0x77F050U, + 0x780D3DU, 0x7815D6U, 0x782403U, 0x783CE8U, 0x7847AAU, 0x785F41U, 0x786E94U, 0x78767FU, 0x7880FBU, 0x789810U, + 0x78A9C5U, 0x78B12EU, 0x78CA6CU, 0x78D287U, 0x78E352U, 0x78FBB9U, 0x790E5AU, 0x7916B1U, 0x792764U, 0x793F8FU, + 0x7944CDU, 0x795C26U, 0x796DF3U, 0x797518U, 0x79839CU, 0x799B77U, 0x79AAA2U, 0x79B249U, 0x79C90BU, 0x79D1E0U, + 0x79E035U, 0x79F8DEU, 0x7A0BF0U, 0x7A131BU, 0x7A22CEU, 0x7A3A25U, 0x7A4167U, 0x7A598CU, 0x7A6859U, 0x7A70B2U, + 0x7A8636U, 0x7A9EDDU, 0x7AAF08U, 0x7AB7E3U, 0x7ACCA1U, 0x7AD44AU, 0x7AE59FU, 0x7AFD74U, 0x7B0897U, 0x7B107CU, + 0x7B21A9U, 0x7B3942U, 0x7B4200U, 0x7B5AEBU, 0x7B6B3EU, 0x7B73D5U, 0x7B8551U, 0x7B9DBAU, 0x7BAC6FU, 0x7BB484U, + 0x7BCFC6U, 0x7BD72DU, 0x7BE6F8U, 0x7BFE13U, 0x7C00A4U, 0x7C184FU, 0x7C299AU, 0x7C3171U, 0x7C4A33U, 0x7C52D8U, + 0x7C630DU, 0x7C7BE6U, 0x7C8D62U, 0x7C9589U, 0x7CA45CU, 0x7CBCB7U, 0x7CC7F5U, 0x7CDF1EU, 0x7CEECBU, 0x7CF620U, + 0x7D03C3U, 0x7D1B28U, 0x7D2AFDU, 0x7D3216U, 0x7D4954U, 0x7D51BFU, 0x7D606AU, 0x7D7881U, 0x7D8E05U, 0x7D96EEU, + 0x7DA73BU, 0x7DBFD0U, 0x7DC492U, 0x7DDC79U, 0x7DEDACU, 0x7DF547U, 0x7E0669U, 0x7E1E82U, 0x7E2F57U, 0x7E37BCU, + 0x7E4CFEU, 0x7E5415U, 0x7E65C0U, 0x7E7D2BU, 0x7E8BAFU, 0x7E9344U, 0x7EA291U, 0x7EBA7AU, 0x7EC138U, 0x7ED9D3U, + 0x7EE806U, 0x7EF0EDU, 0x7F050EU, 0x7F1DE5U, 0x7F2C30U, 0x7F34DBU, 0x7F4F99U, 0x7F5772U, 0x7F66A7U, 0x7F7E4CU, + 0x7F88C8U, 0x7F9023U, 0x7FA1F6U, 0x7FB91DU, 0x7FC25FU, 0x7FDAB4U, 0x7FEB61U, 0x7FF38AU, 0x800C75U, 0x80149EU, + 0x80254BU, 0x803DA0U, 0x8046E2U, 0x805E09U, 0x806FDCU, 0x807737U, 0x8081B3U, 0x809958U, 0x80A88DU, 0x80B066U, + 0x80CB24U, 0x80D3CFU, 0x80E21AU, 0x80FAF1U, 0x810F12U, 0x8117F9U, 0x81262CU, 0x813EC7U, 0x814585U, 0x815D6EU, + 0x816CBBU, 0x817450U, 0x8182D4U, 0x819A3FU, 0x81ABEAU, 0x81B301U, 0x81C843U, 0x81D0A8U, 0x81E17DU, 0x81F996U, + 0x820AB8U, 0x821253U, 0x822386U, 0x823B6DU, 0x82402FU, 0x8258C4U, 0x826911U, 0x8271FAU, 0x82877EU, 0x829F95U, + 0x82AE40U, 0x82B6ABU, 0x82CDE9U, 0x82D502U, 0x82E4D7U, 0x82FC3CU, 0x8309DFU, 0x831134U, 0x8320E1U, 0x83380AU, + 0x834348U, 0x835BA3U, 0x836A76U, 0x83729DU, 0x838419U, 0x839CF2U, 0x83AD27U, 0x83B5CCU, 0x83CE8EU, 0x83D665U, + 0x83E7B0U, 0x83FF5BU, 0x8401ECU, 0x841907U, 0x8428D2U, 0x843039U, 0x844B7BU, 0x845390U, 0x846245U, 0x847AAEU, + 0x848C2AU, 0x8494C1U, 0x84A514U, 0x84BDFFU, 0x84C6BDU, 0x84DE56U, 0x84EF83U, 0x84F768U, 0x85028BU, 0x851A60U, + 0x852BB5U, 0x85335EU, 0x85481CU, 0x8550F7U, 0x856122U, 0x8579C9U, 0x858F4DU, 0x8597A6U, 0x85A673U, 0x85BE98U, + 0x85C5DAU, 0x85DD31U, 0x85ECE4U, 0x85F40FU, 0x860721U, 0x861FCAU, 0x862E1FU, 0x8636F4U, 0x864DB6U, 0x86555DU, + 0x866488U, 0x867C63U, 0x868AE7U, 0x86920CU, 0x86A3D9U, 0x86BB32U, 0x86C070U, 0x86D89BU, 0x86E94EU, 0x86F1A5U, + 0x870446U, 0x871CADU, 0x872D78U, 0x873593U, 0x874ED1U, 0x87563AU, 0x8767EFU, 0x877F04U, 0x878980U, 0x87916BU, + 0x87A0BEU, 0x87B855U, 0x87C317U, 0x87DBFCU, 0x87EA29U, 0x87F2C2U, 0x880FAFU, 0x881744U, 0x882691U, 0x883E7AU, + 0x884538U, 0x885DD3U, 0x886C06U, 0x8874EDU, 0x888269U, 0x889A82U, 0x88AB57U, 0x88B3BCU, 0x88C8FEU, 0x88D015U, + 0x88E1C0U, 0x88F92BU, 0x890CC8U, 0x891423U, 0x8925F6U, 0x893D1DU, 0x89465FU, 0x895EB4U, 0x896F61U, 0x89778AU, + 0x89810EU, 0x8999E5U, 0x89A830U, 0x89B0DBU, 0x89CB99U, 0x89D372U, 0x89E2A7U, 0x89FA4CU, 0x8A0962U, 0x8A1189U, + 0x8A205CU, 0x8A38B7U, 0x8A43F5U, 0x8A5B1EU, 0x8A6ACBU, 0x8A7220U, 0x8A84A4U, 0x8A9C4FU, 0x8AAD9AU, 0x8AB571U, + 0x8ACE33U, 0x8AD6D8U, 0x8AE70DU, 0x8AFFE6U, 0x8B0A05U, 0x8B12EEU, 0x8B233BU, 0x8B3BD0U, 0x8B4092U, 0x8B5879U, + 0x8B69ACU, 0x8B7147U, 0x8B87C3U, 0x8B9F28U, 0x8BAEFDU, 0x8BB616U, 0x8BCD54U, 0x8BD5BFU, 0x8BE46AU, 0x8BFC81U, + 0x8C0236U, 0x8C1ADDU, 0x8C2B08U, 0x8C33E3U, 0x8C48A1U, 0x8C504AU, 0x8C619FU, 0x8C7974U, 0x8C8FF0U, 0x8C971BU, + 0x8CA6CEU, 0x8CBE25U, 0x8CC567U, 0x8CDD8CU, 0x8CEC59U, 0x8CF4B2U, 0x8D0151U, 0x8D19BAU, 0x8D286FU, 0x8D3084U, + 0x8D4BC6U, 0x8D532DU, 0x8D62F8U, 0x8D7A13U, 0x8D8C97U, 0x8D947CU, 0x8DA5A9U, 0x8DBD42U, 0x8DC600U, 0x8DDEEBU, + 0x8DEF3EU, 0x8DF7D5U, 0x8E04FBU, 0x8E1C10U, 0x8E2DC5U, 0x8E352EU, 0x8E4E6CU, 0x8E5687U, 0x8E6752U, 0x8E7FB9U, + 0x8E893DU, 0x8E91D6U, 0x8EA003U, 0x8EB8E8U, 0x8EC3AAU, 0x8EDB41U, 0x8EEA94U, 0x8EF27FU, 0x8F079CU, 0x8F1F77U, + 0x8F2EA2U, 0x8F3649U, 0x8F4D0BU, 0x8F55E0U, 0x8F6435U, 0x8F7CDEU, 0x8F8A5AU, 0x8F92B1U, 0x8FA364U, 0x8FBB8FU, + 0x8FC0CDU, 0x8FD826U, 0x8FE9F3U, 0x8FF118U, 0x900BC1U, 0x90132AU, 0x9022FFU, 0x903A14U, 0x904156U, 0x9059BDU, + 0x906868U, 0x907083U, 0x908607U, 0x909EECU, 0x90AF39U, 0x90B7D2U, 0x90CC90U, 0x90D47BU, 0x90E5AEU, 0x90FD45U, + 0x9108A6U, 0x91104DU, 0x912198U, 0x913973U, 0x914231U, 0x915ADAU, 0x916B0FU, 0x9173E4U, 0x918560U, 0x919D8BU, + 0x91AC5EU, 0x91B4B5U, 0x91CFF7U, 0x91D71CU, 0x91E6C9U, 0x91FE22U, 0x920D0CU, 0x9215E7U, 0x922432U, 0x923CD9U, + 0x92479BU, 0x925F70U, 0x926EA5U, 0x92764EU, 0x9280CAU, 0x929821U, 0x92A9F4U, 0x92B11FU, 0x92CA5DU, 0x92D2B6U, + 0x92E363U, 0x92FB88U, 0x930E6BU, 0x931680U, 0x932755U, 0x933FBEU, 0x9344FCU, 0x935C17U, 0x936DC2U, 0x937529U, + 0x9383ADU, 0x939B46U, 0x93AA93U, 0x93B278U, 0x93C93AU, 0x93D1D1U, 0x93E004U, 0x93F8EFU, 0x940658U, 0x941EB3U, + 0x942F66U, 0x94378DU, 0x944CCFU, 0x945424U, 0x9465F1U, 0x947D1AU, 0x948B9EU, 0x949375U, 0x94A2A0U, 0x94BA4BU, + 0x94C109U, 0x94D9E2U, 0x94E837U, 0x94F0DCU, 0x95053FU, 0x951DD4U, 0x952C01U, 0x9534EAU, 0x954FA8U, 0x955743U, + 0x956696U, 0x957E7DU, 0x9588F9U, 0x959012U, 0x95A1C7U, 0x95B92CU, 0x95C26EU, 0x95DA85U, 0x95EB50U, 0x95F3BBU, + 0x960095U, 0x96187EU, 0x9629ABU, 0x963140U, 0x964A02U, 0x9652E9U, 0x96633CU, 0x967BD7U, 0x968D53U, 0x9695B8U, + 0x96A46DU, 0x96BC86U, 0x96C7C4U, 0x96DF2FU, 0x96EEFAU, 0x96F611U, 0x9703F2U, 0x971B19U, 0x972ACCU, 0x973227U, + 0x974965U, 0x97518EU, 0x97605BU, 0x9778B0U, 0x978E34U, 0x9796DFU, 0x97A70AU, 0x97BFE1U, 0x97C4A3U, 0x97DC48U, + 0x97ED9DU, 0x97F576U, 0x98081BU, 0x9810F0U, 0x982125U, 0x9839CEU, 0x98428CU, 0x985A67U, 0x986BB2U, 0x987359U, + 0x9885DDU, 0x989D36U, 0x98ACE3U, 0x98B408U, 0x98CF4AU, 0x98D7A1U, 0x98E674U, 0x98FE9FU, 0x990B7CU, 0x991397U, + 0x992242U, 0x993AA9U, 0x9941EBU, 0x995900U, 0x9968D5U, 0x99703EU, 0x9986BAU, 0x999E51U, 0x99AF84U, 0x99B76FU, + 0x99CC2DU, 0x99D4C6U, 0x99E513U, 0x99FDF8U, 0x9A0ED6U, 0x9A163DU, 0x9A27E8U, 0x9A3F03U, 0x9A4441U, 0x9A5CAAU, + 0x9A6D7FU, 0x9A7594U, 0x9A8310U, 0x9A9BFBU, 0x9AAA2EU, 0x9AB2C5U, 0x9AC987U, 0x9AD16CU, 0x9AE0B9U, 0x9AF852U, + 0x9B0DB1U, 0x9B155AU, 0x9B248FU, 0x9B3C64U, 0x9B4726U, 0x9B5FCDU, 0x9B6E18U, 0x9B76F3U, 0x9B8077U, 0x9B989CU, + 0x9BA949U, 0x9BB1A2U, 0x9BCAE0U, 0x9BD20BU, 0x9BE3DEU, 0x9BFB35U, 0x9C0582U, 0x9C1D69U, 0x9C2CBCU, 0x9C3457U, + 0x9C4F15U, 0x9C57FEU, 0x9C662BU, 0x9C7EC0U, 0x9C8844U, 0x9C90AFU, 0x9CA17AU, 0x9CB991U, 0x9CC2D3U, 0x9CDA38U, + 0x9CEBEDU, 0x9CF306U, 0x9D06E5U, 0x9D1E0EU, 0x9D2FDBU, 0x9D3730U, 0x9D4C72U, 0x9D5499U, 0x9D654CU, 0x9D7DA7U, + 0x9D8B23U, 0x9D93C8U, 0x9DA21DU, 0x9DBAF6U, 0x9DC1B4U, 0x9DD95FU, 0x9DE88AU, 0x9DF061U, 0x9E034FU, 0x9E1BA4U, + 0x9E2A71U, 0x9E329AU, 0x9E49D8U, 0x9E5133U, 0x9E60E6U, 0x9E780DU, 0x9E8E89U, 0x9E9662U, 0x9EA7B7U, 0x9EBF5CU, + 0x9EC41EU, 0x9EDCF5U, 0x9EED20U, 0x9EF5CBU, 0x9F0028U, 0x9F18C3U, 0x9F2916U, 0x9F31FDU, 0x9F4ABFU, 0x9F5254U, + 0x9F6381U, 0x9F7B6AU, 0x9F8DEEU, 0x9F9505U, 0x9FA4D0U, 0x9FBC3BU, 0x9FC779U, 0x9FDF92U, 0x9FEE47U, 0x9FF6ACU, + 0xA0031DU, 0xA01BF6U, 0xA02A23U, 0xA032C8U, 0xA0498AU, 0xA05161U, 0xA060B4U, 0xA0785FU, 0xA08EDBU, 0xA09630U, + 0xA0A7E5U, 0xA0BF0EU, 0xA0C44CU, 0xA0DCA7U, 0xA0ED72U, 0xA0F599U, 0xA1007AU, 0xA11891U, 0xA12944U, 0xA131AFU, + 0xA14AEDU, 0xA15206U, 0xA163D3U, 0xA17B38U, 0xA18DBCU, 0xA19557U, 0xA1A482U, 0xA1BC69U, 0xA1C72BU, 0xA1DFC0U, + 0xA1EE15U, 0xA1F6FEU, 0xA205D0U, 0xA21D3BU, 0xA22CEEU, 0xA23405U, 0xA24F47U, 0xA257ACU, 0xA26679U, 0xA27E92U, + 0xA28816U, 0xA290FDU, 0xA2A128U, 0xA2B9C3U, 0xA2C281U, 0xA2DA6AU, 0xA2EBBFU, 0xA2F354U, 0xA306B7U, 0xA31E5CU, + 0xA32F89U, 0xA33762U, 0xA34C20U, 0xA354CBU, 0xA3651EU, 0xA37DF5U, 0xA38B71U, 0xA3939AU, 0xA3A24FU, 0xA3BAA4U, + 0xA3C1E6U, 0xA3D90DU, 0xA3E8D8U, 0xA3F033U, 0xA40E84U, 0xA4166FU, 0xA427BAU, 0xA43F51U, 0xA44413U, 0xA45CF8U, + 0xA46D2DU, 0xA475C6U, 0xA48342U, 0xA49BA9U, 0xA4AA7CU, 0xA4B297U, 0xA4C9D5U, 0xA4D13EU, 0xA4E0EBU, 0xA4F800U, + 0xA50DE3U, 0xA51508U, 0xA524DDU, 0xA53C36U, 0xA54774U, 0xA55F9FU, 0xA56E4AU, 0xA576A1U, 0xA58025U, 0xA598CEU, + 0xA5A91BU, 0xA5B1F0U, 0xA5CAB2U, 0xA5D259U, 0xA5E38CU, 0xA5FB67U, 0xA60849U, 0xA610A2U, 0xA62177U, 0xA6399CU, + 0xA642DEU, 0xA65A35U, 0xA66BE0U, 0xA6730BU, 0xA6858FU, 0xA69D64U, 0xA6ACB1U, 0xA6B45AU, 0xA6CF18U, 0xA6D7F3U, + 0xA6E626U, 0xA6FECDU, 0xA70B2EU, 0xA713C5U, 0xA72210U, 0xA73AFBU, 0xA741B9U, 0xA75952U, 0xA76887U, 0xA7706CU, + 0xA786E8U, 0xA79E03U, 0xA7AFD6U, 0xA7B73DU, 0xA7CC7FU, 0xA7D494U, 0xA7E541U, 0xA7FDAAU, 0xA800C7U, 0xA8182CU, + 0xA829F9U, 0xA83112U, 0xA84A50U, 0xA852BBU, 0xA8636EU, 0xA87B85U, 0xA88D01U, 0xA895EAU, 0xA8A43FU, 0xA8BCD4U, + 0xA8C796U, 0xA8DF7DU, 0xA8EEA8U, 0xA8F643U, 0xA903A0U, 0xA91B4BU, 0xA92A9EU, 0xA93275U, 0xA94937U, 0xA951DCU, + 0xA96009U, 0xA978E2U, 0xA98E66U, 0xA9968DU, 0xA9A758U, 0xA9BFB3U, 0xA9C4F1U, 0xA9DC1AU, 0xA9EDCFU, 0xA9F524U, + 0xAA060AU, 0xAA1EE1U, 0xAA2F34U, 0xAA37DFU, 0xAA4C9DU, 0xAA5476U, 0xAA65A3U, 0xAA7D48U, 0xAA8BCCU, 0xAA9327U, + 0xAAA2F2U, 0xAABA19U, 0xAAC15BU, 0xAAD9B0U, 0xAAE865U, 0xAAF08EU, 0xAB056DU, 0xAB1D86U, 0xAB2C53U, 0xAB34B8U, + 0xAB4FFAU, 0xAB5711U, 0xAB66C4U, 0xAB7E2FU, 0xAB88ABU, 0xAB9040U, 0xABA195U, 0xABB97EU, 0xABC23CU, 0xABDAD7U, + 0xABEB02U, 0xABF3E9U, 0xAC0D5EU, 0xAC15B5U, 0xAC2460U, 0xAC3C8BU, 0xAC47C9U, 0xAC5F22U, 0xAC6EF7U, 0xAC761CU, + 0xAC8098U, 0xAC9873U, 0xACA9A6U, 0xACB14DU, 0xACCA0FU, 0xACD2E4U, 0xACE331U, 0xACFBDAU, 0xAD0E39U, 0xAD16D2U, + 0xAD2707U, 0xAD3FECU, 0xAD44AEU, 0xAD5C45U, 0xAD6D90U, 0xAD757BU, 0xAD83FFU, 0xAD9B14U, 0xADAAC1U, 0xADB22AU, + 0xADC968U, 0xADD183U, 0xADE056U, 0xADF8BDU, 0xAE0B93U, 0xAE1378U, 0xAE22ADU, 0xAE3A46U, 0xAE4104U, 0xAE59EFU, + 0xAE683AU, 0xAE70D1U, 0xAE8655U, 0xAE9EBEU, 0xAEAF6BU, 0xAEB780U, 0xAECCC2U, 0xAED429U, 0xAEE5FCU, 0xAEFD17U, + 0xAF08F4U, 0xAF101FU, 0xAF21CAU, 0xAF3921U, 0xAF4263U, 0xAF5A88U, 0xAF6B5DU, 0xAF73B6U, 0xAF8532U, 0xAF9DD9U, + 0xAFAC0CU, 0xAFB4E7U, 0xAFCFA5U, 0xAFD74EU, 0xAFE69BU, 0xAFFE70U, 0xB004A9U, 0xB01C42U, 0xB02D97U, 0xB0357CU, + 0xB04E3EU, 0xB056D5U, 0xB06700U, 0xB07FEBU, 0xB0896FU, 0xB09184U, 0xB0A051U, 0xB0B8BAU, 0xB0C3F8U, 0xB0DB13U, + 0xB0EAC6U, 0xB0F22DU, 0xB107CEU, 0xB11F25U, 0xB12EF0U, 0xB1361BU, 0xB14D59U, 0xB155B2U, 0xB16467U, 0xB17C8CU, + 0xB18A08U, 0xB192E3U, 0xB1A336U, 0xB1BBDDU, 0xB1C09FU, 0xB1D874U, 0xB1E9A1U, 0xB1F14AU, 0xB20264U, 0xB21A8FU, + 0xB22B5AU, 0xB233B1U, 0xB248F3U, 0xB25018U, 0xB261CDU, 0xB27926U, 0xB28FA2U, 0xB29749U, 0xB2A69CU, 0xB2BE77U, + 0xB2C535U, 0xB2DDDEU, 0xB2EC0BU, 0xB2F4E0U, 0xB30103U, 0xB319E8U, 0xB3283DU, 0xB330D6U, 0xB34B94U, 0xB3537FU, + 0xB362AAU, 0xB37A41U, 0xB38CC5U, 0xB3942EU, 0xB3A5FBU, 0xB3BD10U, 0xB3C652U, 0xB3DEB9U, 0xB3EF6CU, 0xB3F787U, + 0xB40930U, 0xB411DBU, 0xB4200EU, 0xB438E5U, 0xB443A7U, 0xB45B4CU, 0xB46A99U, 0xB47272U, 0xB484F6U, 0xB49C1DU, + 0xB4ADC8U, 0xB4B523U, 0xB4CE61U, 0xB4D68AU, 0xB4E75FU, 0xB4FFB4U, 0xB50A57U, 0xB512BCU, 0xB52369U, 0xB53B82U, + 0xB540C0U, 0xB5582BU, 0xB569FEU, 0xB57115U, 0xB58791U, 0xB59F7AU, 0xB5AEAFU, 0xB5B644U, 0xB5CD06U, 0xB5D5EDU, + 0xB5E438U, 0xB5FCD3U, 0xB60FFDU, 0xB61716U, 0xB626C3U, 0xB63E28U, 0xB6456AU, 0xB65D81U, 0xB66C54U, 0xB674BFU, + 0xB6823BU, 0xB69AD0U, 0xB6AB05U, 0xB6B3EEU, 0xB6C8ACU, 0xB6D047U, 0xB6E192U, 0xB6F979U, 0xB70C9AU, 0xB71471U, + 0xB725A4U, 0xB73D4FU, 0xB7460DU, 0xB75EE6U, 0xB76F33U, 0xB777D8U, 0xB7815CU, 0xB799B7U, 0xB7A862U, 0xB7B089U, + 0xB7CBCBU, 0xB7D320U, 0xB7E2F5U, 0xB7FA1EU, 0xB80773U, 0xB81F98U, 0xB82E4DU, 0xB836A6U, 0xB84DE4U, 0xB8550FU, + 0xB864DAU, 0xB87C31U, 0xB88AB5U, 0xB8925EU, 0xB8A38BU, 0xB8BB60U, 0xB8C022U, 0xB8D8C9U, 0xB8E91CU, 0xB8F1F7U, + 0xB90414U, 0xB91CFFU, 0xB92D2AU, 0xB935C1U, 0xB94E83U, 0xB95668U, 0xB967BDU, 0xB97F56U, 0xB989D2U, 0xB99139U, + 0xB9A0ECU, 0xB9B807U, 0xB9C345U, 0xB9DBAEU, 0xB9EA7BU, 0xB9F290U, 0xBA01BEU, 0xBA1955U, 0xBA2880U, 0xBA306BU, + 0xBA4B29U, 0xBA53C2U, 0xBA6217U, 0xBA7AFCU, 0xBA8C78U, 0xBA9493U, 0xBAA546U, 0xBABDADU, 0xBAC6EFU, 0xBADE04U, + 0xBAEFD1U, 0xBAF73AU, 0xBB02D9U, 0xBB1A32U, 0xBB2BE7U, 0xBB330CU, 0xBB484EU, 0xBB50A5U, 0xBB6170U, 0xBB799BU, + 0xBB8F1FU, 0xBB97F4U, 0xBBA621U, 0xBBBECAU, 0xBBC588U, 0xBBDD63U, 0xBBECB6U, 0xBBF45DU, 0xBC0AEAU, 0xBC1201U, + 0xBC23D4U, 0xBC3B3FU, 0xBC407DU, 0xBC5896U, 0xBC6943U, 0xBC71A8U, 0xBC872CU, 0xBC9FC7U, 0xBCAE12U, 0xBCB6F9U, + 0xBCCDBBU, 0xBCD550U, 0xBCE485U, 0xBCFC6EU, 0xBD098DU, 0xBD1166U, 0xBD20B3U, 0xBD3858U, 0xBD431AU, 0xBD5BF1U, + 0xBD6A24U, 0xBD72CFU, 0xBD844BU, 0xBD9CA0U, 0xBDAD75U, 0xBDB59EU, 0xBDCEDCU, 0xBDD637U, 0xBDE7E2U, 0xBDFF09U, + 0xBE0C27U, 0xBE14CCU, 0xBE2519U, 0xBE3DF2U, 0xBE46B0U, 0xBE5E5BU, 0xBE6F8EU, 0xBE7765U, 0xBE81E1U, 0xBE990AU, + 0xBEA8DFU, 0xBEB034U, 0xBECB76U, 0xBED39DU, 0xBEE248U, 0xBEFAA3U, 0xBF0F40U, 0xBF17ABU, 0xBF267EU, 0xBF3E95U, + 0xBF45D7U, 0xBF5D3CU, 0xBF6CE9U, 0xBF7402U, 0xBF8286U, 0xBF9A6DU, 0xBFABB8U, 0xBFB353U, 0xBFC811U, 0xBFD0FAU, + 0xBFE12FU, 0xBFF9C4U, 0xC00A4EU, 0xC012A5U, 0xC02370U, 0xC03B9BU, 0xC040D9U, 0xC05832U, 0xC069E7U, 0xC0710CU, + 0xC08788U, 0xC09F63U, 0xC0AEB6U, 0xC0B65DU, 0xC0CD1FU, 0xC0D5F4U, 0xC0E421U, 0xC0FCCAU, 0xC10929U, 0xC111C2U, + 0xC12017U, 0xC138FCU, 0xC143BEU, 0xC15B55U, 0xC16A80U, 0xC1726BU, 0xC184EFU, 0xC19C04U, 0xC1ADD1U, 0xC1B53AU, + 0xC1CE78U, 0xC1D693U, 0xC1E746U, 0xC1FFADU, 0xC20C83U, 0xC21468U, 0xC225BDU, 0xC23D56U, 0xC24614U, 0xC25EFFU, + 0xC26F2AU, 0xC277C1U, 0xC28145U, 0xC299AEU, 0xC2A87BU, 0xC2B090U, 0xC2CBD2U, 0xC2D339U, 0xC2E2ECU, 0xC2FA07U, + 0xC30FE4U, 0xC3170FU, 0xC326DAU, 0xC33E31U, 0xC34573U, 0xC35D98U, 0xC36C4DU, 0xC374A6U, 0xC38222U, 0xC39AC9U, + 0xC3AB1CU, 0xC3B3F7U, 0xC3C8B5U, 0xC3D05EU, 0xC3E18BU, 0xC3F960U, 0xC407D7U, 0xC41F3CU, 0xC42EE9U, 0xC43602U, + 0xC44D40U, 0xC455ABU, 0xC4647EU, 0xC47C95U, 0xC48A11U, 0xC492FAU, 0xC4A32FU, 0xC4BBC4U, 0xC4C086U, 0xC4D86DU, + 0xC4E9B8U, 0xC4F153U, 0xC504B0U, 0xC51C5BU, 0xC52D8EU, 0xC53565U, 0xC54E27U, 0xC556CCU, 0xC56719U, 0xC57FF2U, + 0xC58976U, 0xC5919DU, 0xC5A048U, 0xC5B8A3U, 0xC5C3E1U, 0xC5DB0AU, 0xC5EADFU, 0xC5F234U, 0xC6011AU, 0xC619F1U, + 0xC62824U, 0xC630CFU, 0xC64B8DU, 0xC65366U, 0xC662B3U, 0xC67A58U, 0xC68CDCU, 0xC69437U, 0xC6A5E2U, 0xC6BD09U, + 0xC6C64BU, 0xC6DEA0U, 0xC6EF75U, 0xC6F79EU, 0xC7027DU, 0xC71A96U, 0xC72B43U, 0xC733A8U, 0xC748EAU, 0xC75001U, + 0xC761D4U, 0xC7793FU, 0xC78FBBU, 0xC79750U, 0xC7A685U, 0xC7BE6EU, 0xC7C52CU, 0xC7DDC7U, 0xC7EC12U, 0xC7F4F9U, + 0xC80994U, 0xC8117FU, 0xC820AAU, 0xC83841U, 0xC84303U, 0xC85BE8U, 0xC86A3DU, 0xC872D6U, 0xC88452U, 0xC89CB9U, + 0xC8AD6CU, 0xC8B587U, 0xC8CEC5U, 0xC8D62EU, 0xC8E7FBU, 0xC8FF10U, 0xC90AF3U, 0xC91218U, 0xC923CDU, 0xC93B26U, + 0xC94064U, 0xC9588FU, 0xC9695AU, 0xC971B1U, 0xC98735U, 0xC99FDEU, 0xC9AE0BU, 0xC9B6E0U, 0xC9CDA2U, 0xC9D549U, + 0xC9E49CU, 0xC9FC77U, 0xCA0F59U, 0xCA17B2U, 0xCA2667U, 0xCA3E8CU, 0xCA45CEU, 0xCA5D25U, 0xCA6CF0U, 0xCA741BU, + 0xCA829FU, 0xCA9A74U, 0xCAABA1U, 0xCAB34AU, 0xCAC808U, 0xCAD0E3U, 0xCAE136U, 0xCAF9DDU, 0xCB0C3EU, 0xCB14D5U, + 0xCB2500U, 0xCB3DEBU, 0xCB46A9U, 0xCB5E42U, 0xCB6F97U, 0xCB777CU, 0xCB81F8U, 0xCB9913U, 0xCBA8C6U, 0xCBB02DU, + 0xCBCB6FU, 0xCBD384U, 0xCBE251U, 0xCBFABAU, 0xCC040DU, 0xCC1CE6U, 0xCC2D33U, 0xCC35D8U, 0xCC4E9AU, 0xCC5671U, + 0xCC67A4U, 0xCC7F4FU, 0xCC89CBU, 0xCC9120U, 0xCCA0F5U, 0xCCB81EU, 0xCCC35CU, 0xCCDBB7U, 0xCCEA62U, 0xCCF289U, + 0xCD076AU, 0xCD1F81U, 0xCD2E54U, 0xCD36BFU, 0xCD4DFDU, 0xCD5516U, 0xCD64C3U, 0xCD7C28U, 0xCD8AACU, 0xCD9247U, + 0xCDA392U, 0xCDBB79U, 0xCDC03BU, 0xCDD8D0U, 0xCDE905U, 0xCDF1EEU, 0xCE02C0U, 0xCE1A2BU, 0xCE2BFEU, 0xCE3315U, + 0xCE4857U, 0xCE50BCU, 0xCE6169U, 0xCE7982U, 0xCE8F06U, 0xCE97EDU, 0xCEA638U, 0xCEBED3U, 0xCEC591U, 0xCEDD7AU, + 0xCEECAFU, 0xCEF444U, 0xCF01A7U, 0xCF194CU, 0xCF2899U, 0xCF3072U, 0xCF4B30U, 0xCF53DBU, 0xCF620EU, 0xCF7AE5U, + 0xCF8C61U, 0xCF948AU, 0xCFA55FU, 0xCFBDB4U, 0xCFC6F6U, 0xCFDE1DU, 0xCFEFC8U, 0xCFF723U, 0xD00DFAU, 0xD01511U, + 0xD024C4U, 0xD03C2FU, 0xD0476DU, 0xD05F86U, 0xD06E53U, 0xD076B8U, 0xD0803CU, 0xD098D7U, 0xD0A902U, 0xD0B1E9U, + 0xD0CAABU, 0xD0D240U, 0xD0E395U, 0xD0FB7EU, 0xD10E9DU, 0xD11676U, 0xD127A3U, 0xD13F48U, 0xD1440AU, 0xD15CE1U, + 0xD16D34U, 0xD175DFU, 0xD1835BU, 0xD19BB0U, 0xD1AA65U, 0xD1B28EU, 0xD1C9CCU, 0xD1D127U, 0xD1E0F2U, 0xD1F819U, + 0xD20B37U, 0xD213DCU, 0xD22209U, 0xD23AE2U, 0xD241A0U, 0xD2594BU, 0xD2689EU, 0xD27075U, 0xD286F1U, 0xD29E1AU, + 0xD2AFCFU, 0xD2B724U, 0xD2CC66U, 0xD2D48DU, 0xD2E558U, 0xD2FDB3U, 0xD30850U, 0xD310BBU, 0xD3216EU, 0xD33985U, + 0xD342C7U, 0xD35A2CU, 0xD36BF9U, 0xD37312U, 0xD38596U, 0xD39D7DU, 0xD3ACA8U, 0xD3B443U, 0xD3CF01U, 0xD3D7EAU, + 0xD3E63FU, 0xD3FED4U, 0xD40063U, 0xD41888U, 0xD4295DU, 0xD431B6U, 0xD44AF4U, 0xD4521FU, 0xD463CAU, 0xD47B21U, + 0xD48DA5U, 0xD4954EU, 0xD4A49BU, 0xD4BC70U, 0xD4C732U, 0xD4DFD9U, 0xD4EE0CU, 0xD4F6E7U, 0xD50304U, 0xD51BEFU, + 0xD52A3AU, 0xD532D1U, 0xD54993U, 0xD55178U, 0xD560ADU, 0xD57846U, 0xD58EC2U, 0xD59629U, 0xD5A7FCU, 0xD5BF17U, + 0xD5C455U, 0xD5DCBEU, 0xD5ED6BU, 0xD5F580U, 0xD606AEU, 0xD61E45U, 0xD62F90U, 0xD6377BU, 0xD64C39U, 0xD654D2U, + 0xD66507U, 0xD67DECU, 0xD68B68U, 0xD69383U, 0xD6A256U, 0xD6BABDU, 0xD6C1FFU, 0xD6D914U, 0xD6E8C1U, 0xD6F02AU, + 0xD705C9U, 0xD71D22U, 0xD72CF7U, 0xD7341CU, 0xD74F5EU, 0xD757B5U, 0xD76660U, 0xD77E8BU, 0xD7880FU, 0xD790E4U, + 0xD7A131U, 0xD7B9DAU, 0xD7C298U, 0xD7DA73U, 0xD7EBA6U, 0xD7F34DU, 0xD80E20U, 0xD816CBU, 0xD8271EU, 0xD83FF5U, + 0xD844B7U, 0xD85C5CU, 0xD86D89U, 0xD87562U, 0xD883E6U, 0xD89B0DU, 0xD8AAD8U, 0xD8B233U, 0xD8C971U, 0xD8D19AU, + 0xD8E04FU, 0xD8F8A4U, 0xD90D47U, 0xD915ACU, 0xD92479U, 0xD93C92U, 0xD947D0U, 0xD95F3BU, 0xD96EEEU, 0xD97605U, + 0xD98081U, 0xD9986AU, 0xD9A9BFU, 0xD9B154U, 0xD9CA16U, 0xD9D2FDU, 0xD9E328U, 0xD9FBC3U, 0xDA08EDU, 0xDA1006U, + 0xDA21D3U, 0xDA3938U, 0xDA427AU, 0xDA5A91U, 0xDA6B44U, 0xDA73AFU, 0xDA852BU, 0xDA9DC0U, 0xDAAC15U, 0xDAB4FEU, + 0xDACFBCU, 0xDAD757U, 0xDAE682U, 0xDAFE69U, 0xDB0B8AU, 0xDB1361U, 0xDB22B4U, 0xDB3A5FU, 0xDB411DU, 0xDB59F6U, + 0xDB6823U, 0xDB70C8U, 0xDB864CU, 0xDB9EA7U, 0xDBAF72U, 0xDBB799U, 0xDBCCDBU, 0xDBD430U, 0xDBE5E5U, 0xDBFD0EU, + 0xDC03B9U, 0xDC1B52U, 0xDC2A87U, 0xDC326CU, 0xDC492EU, 0xDC51C5U, 0xDC6010U, 0xDC78FBU, 0xDC8E7FU, 0xDC9694U, + 0xDCA741U, 0xDCBFAAU, 0xDCC4E8U, 0xDCDC03U, 0xDCEDD6U, 0xDCF53DU, 0xDD00DEU, 0xDD1835U, 0xDD29E0U, 0xDD310BU, + 0xDD4A49U, 0xDD52A2U, 0xDD6377U, 0xDD7B9CU, 0xDD8D18U, 0xDD95F3U, 0xDDA426U, 0xDDBCCDU, 0xDDC78FU, 0xDDDF64U, + 0xDDEEB1U, 0xDDF65AU, 0xDE0574U, 0xDE1D9FU, 0xDE2C4AU, 0xDE34A1U, 0xDE4FE3U, 0xDE5708U, 0xDE66DDU, 0xDE7E36U, + 0xDE88B2U, 0xDE9059U, 0xDEA18CU, 0xDEB967U, 0xDEC225U, 0xDEDACEU, 0xDEEB1BU, 0xDEF3F0U, 0xDF0613U, 0xDF1EF8U, + 0xDF2F2DU, 0xDF37C6U, 0xDF4C84U, 0xDF546FU, 0xDF65BAU, 0xDF7D51U, 0xDF8BD5U, 0xDF933EU, 0xDFA2EBU, 0xDFBA00U, + 0xDFC142U, 0xDFD9A9U, 0xDFE87CU, 0xDFF097U, 0xE00526U, 0xE01DCDU, 0xE02C18U, 0xE034F3U, 0xE04FB1U, 0xE0575AU, + 0xE0668FU, 0xE07E64U, 0xE088E0U, 0xE0900BU, 0xE0A1DEU, 0xE0B935U, 0xE0C277U, 0xE0DA9CU, 0xE0EB49U, 0xE0F3A2U, + 0xE10641U, 0xE11EAAU, 0xE12F7FU, 0xE13794U, 0xE14CD6U, 0xE1543DU, 0xE165E8U, 0xE17D03U, 0xE18B87U, 0xE1936CU, + 0xE1A2B9U, 0xE1BA52U, 0xE1C110U, 0xE1D9FBU, 0xE1E82EU, 0xE1F0C5U, 0xE203EBU, 0xE21B00U, 0xE22AD5U, 0xE2323EU, + 0xE2497CU, 0xE25197U, 0xE26042U, 0xE278A9U, 0xE28E2DU, 0xE296C6U, 0xE2A713U, 0xE2BFF8U, 0xE2C4BAU, 0xE2DC51U, + 0xE2ED84U, 0xE2F56FU, 0xE3008CU, 0xE31867U, 0xE329B2U, 0xE33159U, 0xE34A1BU, 0xE352F0U, 0xE36325U, 0xE37BCEU, + 0xE38D4AU, 0xE395A1U, 0xE3A474U, 0xE3BC9FU, 0xE3C7DDU, 0xE3DF36U, 0xE3EEE3U, 0xE3F608U, 0xE408BFU, 0xE41054U, + 0xE42181U, 0xE4396AU, 0xE44228U, 0xE45AC3U, 0xE46B16U, 0xE473FDU, 0xE48579U, 0xE49D92U, 0xE4AC47U, 0xE4B4ACU, + 0xE4CFEEU, 0xE4D705U, 0xE4E6D0U, 0xE4FE3BU, 0xE50BD8U, 0xE51333U, 0xE522E6U, 0xE53A0DU, 0xE5414FU, 0xE559A4U, + 0xE56871U, 0xE5709AU, 0xE5861EU, 0xE59EF5U, 0xE5AF20U, 0xE5B7CBU, 0xE5CC89U, 0xE5D462U, 0xE5E5B7U, 0xE5FD5CU, + 0xE60E72U, 0xE61699U, 0xE6274CU, 0xE63FA7U, 0xE644E5U, 0xE65C0EU, 0xE66DDBU, 0xE67530U, 0xE683B4U, 0xE69B5FU, + 0xE6AA8AU, 0xE6B261U, 0xE6C923U, 0xE6D1C8U, 0xE6E01DU, 0xE6F8F6U, 0xE70D15U, 0xE715FEU, 0xE7242BU, 0xE73CC0U, + 0xE74782U, 0xE75F69U, 0xE76EBCU, 0xE77657U, 0xE780D3U, 0xE79838U, 0xE7A9EDU, 0xE7B106U, 0xE7CA44U, 0xE7D2AFU, + 0xE7E37AU, 0xE7FB91U, 0xE806FCU, 0xE81E17U, 0xE82FC2U, 0xE83729U, 0xE84C6BU, 0xE85480U, 0xE86555U, 0xE87DBEU, + 0xE88B3AU, 0xE893D1U, 0xE8A204U, 0xE8BAEFU, 0xE8C1ADU, 0xE8D946U, 0xE8E893U, 0xE8F078U, 0xE9059BU, 0xE91D70U, + 0xE92CA5U, 0xE9344EU, 0xE94F0CU, 0xE957E7U, 0xE96632U, 0xE97ED9U, 0xE9885DU, 0xE990B6U, 0xE9A163U, 0xE9B988U, + 0xE9C2CAU, 0xE9DA21U, 0xE9EBF4U, 0xE9F31FU, 0xEA0031U, 0xEA18DAU, 0xEA290FU, 0xEA31E4U, 0xEA4AA6U, 0xEA524DU, + 0xEA6398U, 0xEA7B73U, 0xEA8DF7U, 0xEA951CU, 0xEAA4C9U, 0xEABC22U, 0xEAC760U, 0xEADF8BU, 0xEAEE5EU, 0xEAF6B5U, + 0xEB0356U, 0xEB1BBDU, 0xEB2A68U, 0xEB3283U, 0xEB49C1U, 0xEB512AU, 0xEB60FFU, 0xEB7814U, 0xEB8E90U, 0xEB967BU, + 0xEBA7AEU, 0xEBBF45U, 0xEBC407U, 0xEBDCECU, 0xEBED39U, 0xEBF5D2U, 0xEC0B65U, 0xEC138EU, 0xEC225BU, 0xEC3AB0U, + 0xEC41F2U, 0xEC5919U, 0xEC68CCU, 0xEC7027U, 0xEC86A3U, 0xEC9E48U, 0xECAF9DU, 0xECB776U, 0xECCC34U, 0xECD4DFU, + 0xECE50AU, 0xECFDE1U, 0xED0802U, 0xED10E9U, 0xED213CU, 0xED39D7U, 0xED4295U, 0xED5A7EU, 0xED6BABU, 0xED7340U, + 0xED85C4U, 0xED9D2FU, 0xEDACFAU, 0xEDB411U, 0xEDCF53U, 0xEDD7B8U, 0xEDE66DU, 0xEDFE86U, 0xEE0DA8U, 0xEE1543U, + 0xEE2496U, 0xEE3C7DU, 0xEE473FU, 0xEE5FD4U, 0xEE6E01U, 0xEE76EAU, 0xEE806EU, 0xEE9885U, 0xEEA950U, 0xEEB1BBU, + 0xEECAF9U, 0xEED212U, 0xEEE3C7U, 0xEEFB2CU, 0xEF0ECFU, 0xEF1624U, 0xEF27F1U, 0xEF3F1AU, 0xEF4458U, 0xEF5CB3U, + 0xEF6D66U, 0xEF758DU, 0xEF8309U, 0xEF9BE2U, 0xEFAA37U, 0xEFB2DCU, 0xEFC99EU, 0xEFD175U, 0xEFE0A0U, 0xEFF84BU, + 0xF00292U, 0xF01A79U, 0xF02BACU, 0xF03347U, 0xF04805U, 0xF050EEU, 0xF0613BU, 0xF079D0U, 0xF08F54U, 0xF097BFU, + 0xF0A66AU, 0xF0BE81U, 0xF0C5C3U, 0xF0DD28U, 0xF0ECFDU, 0xF0F416U, 0xF101F5U, 0xF1191EU, 0xF128CBU, 0xF13020U, + 0xF14B62U, 0xF15389U, 0xF1625CU, 0xF17AB7U, 0xF18C33U, 0xF194D8U, 0xF1A50DU, 0xF1BDE6U, 0xF1C6A4U, 0xF1DE4FU, + 0xF1EF9AU, 0xF1F771U, 0xF2045FU, 0xF21CB4U, 0xF22D61U, 0xF2358AU, 0xF24EC8U, 0xF25623U, 0xF267F6U, 0xF27F1DU, + 0xF28999U, 0xF29172U, 0xF2A0A7U, 0xF2B84CU, 0xF2C30EU, 0xF2DBE5U, 0xF2EA30U, 0xF2F2DBU, 0xF30738U, 0xF31FD3U, + 0xF32E06U, 0xF336EDU, 0xF34DAFU, 0xF35544U, 0xF36491U, 0xF37C7AU, 0xF38AFEU, 0xF39215U, 0xF3A3C0U, 0xF3BB2BU, + 0xF3C069U, 0xF3D882U, 0xF3E957U, 0xF3F1BCU, 0xF40F0BU, 0xF417E0U, 0xF42635U, 0xF43EDEU, 0xF4459CU, 0xF45D77U, + 0xF46CA2U, 0xF47449U, 0xF482CDU, 0xF49A26U, 0xF4ABF3U, 0xF4B318U, 0xF4C85AU, 0xF4D0B1U, 0xF4E164U, 0xF4F98FU, + 0xF50C6CU, 0xF51487U, 0xF52552U, 0xF53DB9U, 0xF546FBU, 0xF55E10U, 0xF56FC5U, 0xF5772EU, 0xF581AAU, 0xF59941U, + 0xF5A894U, 0xF5B07FU, 0xF5CB3DU, 0xF5D3D6U, 0xF5E203U, 0xF5FAE8U, 0xF609C6U, 0xF6112DU, 0xF620F8U, 0xF63813U, + 0xF64351U, 0xF65BBAU, 0xF66A6FU, 0xF67284U, 0xF68400U, 0xF69CEBU, 0xF6AD3EU, 0xF6B5D5U, 0xF6CE97U, 0xF6D67CU, + 0xF6E7A9U, 0xF6FF42U, 0xF70AA1U, 0xF7124AU, 0xF7239FU, 0xF73B74U, 0xF74036U, 0xF758DDU, 0xF76908U, 0xF771E3U, + 0xF78767U, 0xF79F8CU, 0xF7AE59U, 0xF7B6B2U, 0xF7CDF0U, 0xF7D51BU, 0xF7E4CEU, 0xF7FC25U, 0xF80148U, 0xF819A3U, + 0xF82876U, 0xF8309DU, 0xF84BDFU, 0xF85334U, 0xF862E1U, 0xF87A0AU, 0xF88C8EU, 0xF89465U, 0xF8A5B0U, 0xF8BD5BU, + 0xF8C619U, 0xF8DEF2U, 0xF8EF27U, 0xF8F7CCU, 0xF9022FU, 0xF91AC4U, 0xF92B11U, 0xF933FAU, 0xF948B8U, 0xF95053U, + 0xF96186U, 0xF9796DU, 0xF98FE9U, 0xF99702U, 0xF9A6D7U, 0xF9BE3CU, 0xF9C57EU, 0xF9DD95U, 0xF9EC40U, 0xF9F4ABU, + 0xFA0785U, 0xFA1F6EU, 0xFA2EBBU, 0xFA3650U, 0xFA4D12U, 0xFA55F9U, 0xFA642CU, 0xFA7CC7U, 0xFA8A43U, 0xFA92A8U, + 0xFAA37DU, 0xFABB96U, 0xFAC0D4U, 0xFAD83FU, 0xFAE9EAU, 0xFAF101U, 0xFB04E2U, 0xFB1C09U, 0xFB2DDCU, 0xFB3537U, + 0xFB4E75U, 0xFB569EU, 0xFB674BU, 0xFB7FA0U, 0xFB8924U, 0xFB91CFU, 0xFBA01AU, 0xFBB8F1U, 0xFBC3B3U, 0xFBDB58U, + 0xFBEA8DU, 0xFBF266U, 0xFC0CD1U, 0xFC143AU, 0xFC25EFU, 0xFC3D04U, 0xFC4646U, 0xFC5EADU, 0xFC6F78U, 0xFC7793U, + 0xFC8117U, 0xFC99FCU, 0xFCA829U, 0xFCB0C2U, 0xFCCB80U, 0xFCD36BU, 0xFCE2BEU, 0xFCFA55U, 0xFD0FB6U, 0xFD175DU, + 0xFD2688U, 0xFD3E63U, 0xFD4521U, 0xFD5DCAU, 0xFD6C1FU, 0xFD74F4U, 0xFD8270U, 0xFD9A9BU, 0xFDAB4EU, 0xFDB3A5U, + 0xFDC8E7U, 0xFDD00CU, 0xFDE1D9U, 0xFDF932U, 0xFE0A1CU, 0xFE12F7U, 0xFE2322U, 0xFE3BC9U, 0xFE408BU, 0xFE5860U, + 0xFE69B5U, 0xFE715EU, 0xFE87DAU, 0xFE9F31U, 0xFEAEE4U, 0xFEB60FU, 0xFECD4DU, 0xFED5A6U, 0xFEE473U, 0xFEFC98U, + 0xFF097BU, 0xFF1190U, 0xFF2045U, 0xFF38AEU, 0xFF43ECU, 0xFF5B07U, 0xFF6AD2U, 0xFF7239U, 0xFF84BDU, 0xFF9C56U, + 0xFFAD83U, 0xFFB568U, 0xFFCE2AU, 0xFFD6C1U, 0xFFE714U, 0xFFFFFFU +}; -static const unsigned int DECODING_TABLE_23127[] = { - 0x000000U, 0x000001U, 0x000002U, 0x000003U, 0x000004U, 0x000005U, 0x000006U, 0x000007U, 0x000008U, 0x000009U, - 0x00000AU, 0x00000BU, 0x00000CU, 0x00000DU, 0x00000EU, 0x024020U, 0x000010U, 0x000011U, 0x000012U, 0x000013U, - 0x000014U, 0x000015U, 0x000016U, 0x412000U, 0x000018U, 0x000019U, 0x00001AU, 0x180800U, 0x00001CU, 0x200300U, - 0x048040U, 0x001480U, 0x000020U, 0x000021U, 0x000022U, 0x000023U, 0x000024U, 0x000025U, 0x000026U, 0x024008U, - 0x000028U, 0x000029U, 0x00002AU, 0x024004U, 0x00002CU, 0x024002U, 0x024001U, 0x024000U, 0x000030U, 0x000031U, - 0x000032U, 0x008180U, 0x000034U, 0x000C40U, 0x301000U, 0x0C0200U, 0x000038U, 0x043000U, 0x400600U, 0x210040U, - 0x090080U, 0x508000U, 0x002900U, 0x024010U, 0x000040U, 0x000041U, 0x000042U, 0x000043U, 0x000044U, 0x000045U, - 0x000046U, 0x280080U, 0x000048U, 0x000049U, 0x00004AU, 0x002500U, 0x00004CU, 0x111000U, 0x048010U, 0x400A00U, - 0x000050U, 0x000051U, 0x000052U, 0x021200U, 0x000054U, 0x000C20U, 0x048008U, 0x104100U, 0x000058U, 0x404080U, - 0x048004U, 0x210020U, 0x048002U, 0x0A2000U, 0x048000U, 0x048001U, 0x000060U, 0x000061U, 0x000062U, 0x540000U, - 0x000064U, 0x000C10U, 0x010300U, 0x00B000U, 0x000068U, 0x088200U, 0x001880U, 0x210010U, 0x602000U, 0x040180U, - 0x180400U, 0x024040U, 0x000070U, 0x000C04U, 0x086000U, 0x210008U, 0x000C01U, 0x000C00U, 0x420080U, 0x000C02U, - 0x120100U, 0x210002U, 0x210001U, 0x210000U, 0x005200U, 0x000C08U, 0x048020U, 0x210004U, 0x000080U, 0x000081U, - 0x000082U, 0x000083U, 0x000084U, 0x000085U, 0x000086U, 0x280040U, 0x000088U, 0x000089U, 0x00008AU, 0x050200U, - 0x00008CU, 0x00A800U, 0x500100U, 0x001410U, 0x000090U, 0x000091U, 0x000092U, 0x008120U, 0x000094U, 0x160000U, - 0x004A00U, 0x001408U, 0x000098U, 0x404040U, 0x222000U, 0x001404U, 0x090020U, 0x001402U, 0x001401U, 0x001400U, - 0x0000A0U, 0x0000A1U, 0x0000A2U, 0x008110U, 0x0000A4U, 0x401200U, 0x042400U, 0x110800U, 0x0000A8U, 0x300400U, - 0x001840U, 0x482000U, 0x090010U, 0x040140U, 0x208200U, 0x024080U, 0x0000B0U, 0x008102U, 0x008101U, 0x008100U, - 0x090008U, 0x206000U, 0x420040U, 0x008104U, 0x090004U, 0x020A00U, 0x144000U, 0x008108U, 0x090000U, 0x090001U, - 0x090002U, 0x001420U, 0x0000C0U, 0x0000C1U, 0x0000C2U, 0x280004U, 0x0000C4U, 0x280002U, 0x280001U, 0x280000U, - 0x0000C8U, 0x404010U, 0x001820U, 0x128000U, 0x020600U, 0x040120U, 0x016000U, 0x280008U, 0x0000D0U, 0x404008U, - 0x110400U, 0x042800U, 0x003100U, 0x018200U, 0x420020U, 0x280010U, 0x404001U, 0x404000U, 0x080300U, 0x404002U, - 0x300800U, 0x404004U, 0x048080U, 0x001440U, 0x0000E0U, 0x032000U, 0x001808U, 0x004600U, 0x10C000U, 0x040108U, - 0x420010U, 0x280020U, 0x001802U, 0x040104U, 0x001800U, 0x001801U, 0x040101U, 0x040100U, 0x001804U, 0x040102U, - 0x240200U, 0x181000U, 0x420004U, 0x008140U, 0x420002U, 0x000C80U, 0x420000U, 0x420001U, 0x00A400U, 0x404020U, - 0x001810U, 0x210080U, 0x090040U, 0x040110U, 0x420008U, 0x102200U, 0x000100U, 0x000101U, 0x000102U, 0x000103U, - 0x000104U, 0x000105U, 0x000106U, 0x041800U, 0x000108U, 0x000109U, 0x00010AU, 0x002440U, 0x00010CU, 0x200210U, - 0x500080U, 0x098000U, 0x000110U, 0x000111U, 0x000112U, 0x0080A0U, 0x000114U, 0x200208U, 0x0A0400U, 0x104040U, - 0x000118U, 0x200204U, 0x015000U, 0x460000U, 0x200201U, 0x200200U, 0x002820U, 0x200202U, 0x000120U, 0x000121U, - 0x000122U, 0x008090U, 0x000124U, 0x182000U, 0x010240U, 0x600400U, 0x000128U, 0x410800U, 0x2C0000U, 0x101200U, - 0x009400U, 0x0400C0U, 0x002810U, 0x024100U, 0x000130U, 0x008082U, 0x008081U, 0x008080U, 0x444000U, 0x031000U, - 0x002808U, 0x008084U, 0x120040U, 0x084400U, 0x002804U, 0x008088U, 0x002802U, 0x200220U, 0x002800U, 0x002801U, - 0x000140U, 0x000141U, 0x000142U, 0x002408U, 0x000144U, 0x428000U, 0x010220U, 0x104010U, 0x000148U, 0x002402U, - 0x002401U, 0x002400U, 0x084800U, 0x0400A0U, 0x221000U, 0x002404U, 0x000150U, 0x0D0000U, 0x600800U, 0x104004U, - 0x003080U, 0x104002U, 0x104001U, 0x104000U, 0x120020U, 0x009800U, 0x080280U, 0x002410U, 0x410400U, 0x200240U, - 0x048100U, 0x104008U, 0x000160U, 0x205000U, 0x010204U, 0x0A0800U, 0x010202U, 0x040088U, 0x010200U, 0x010201U, - 0x120010U, 0x040084U, 0x40C000U, 0x002420U, 0x040081U, 0x040080U, 0x010208U, 0x040082U, 0x120008U, 0x402200U, - 0x041400U, 0x0080C0U, 0x288000U, 0x000D00U, 0x010210U, 0x104020U, 0x120000U, 0x120001U, 0x120002U, 0x210100U, - 0x120004U, 0x040090U, 0x002840U, 0x481000U, 0x000180U, 0x000181U, 0x000182U, 0x008030U, 0x000184U, 0x014400U, - 0x500008U, 0x022200U, 0x000188U, 0x0A1000U, 0x500004U, 0x204800U, 0x500002U, 0x040060U, 0x500000U, 0x500001U, - 0x000190U, 0x008022U, 0x008021U, 0x008020U, 0x003040U, 0x480800U, 0x250000U, 0x008024U, 0x040C00U, 0x112000U, - 0x080240U, 0x008028U, 0x02C000U, 0x200280U, 0x500010U, 0x001500U, 0x0001A0U, 0x008012U, 0x008011U, 0x008010U, - 0x220800U, 0x040048U, 0x085000U, 0x008014U, 0x006200U, 0x040044U, 0x030400U, 0x008018U, 0x040041U, 0x040040U, - 0x500020U, 0x040042U, 0x008003U, 0x008002U, 0x008001U, 0x008000U, 0x100600U, 0x008006U, 0x008005U, 0x008004U, - 0x601000U, 0x00800AU, 0x008009U, 0x008008U, 0x090100U, 0x040050U, 0x002880U, 0x00800CU, 0x0001C0U, 0x100A00U, - 0x064000U, 0x411000U, 0x003010U, 0x040028U, 0x008C00U, 0x280100U, 0x218000U, 0x040024U, 0x080210U, 0x002480U, - 0x040021U, 0x040020U, 0x500040U, 0x040022U, 0x003004U, 0x220400U, 0x080208U, 0x008060U, 0x003000U, 0x003001U, - 0x003002U, 0x104080U, 0x080202U, 0x404100U, 0x080200U, 0x080201U, 0x003008U, 0x040030U, 0x080204U, 0x030800U, - 0x480400U, 0x04000CU, 0x302000U, 0x008050U, 0x040009U, 0x040008U, 0x010280U, 0x04000AU, 0x040005U, 0x040004U, - 0x001900U, 0x040006U, 0x040001U, 0x040000U, 0x040003U, 0x040002U, 0x014800U, 0x008042U, 0x008041U, 0x008040U, - 0x003020U, 0x040018U, 0x420100U, 0x008044U, 0x120080U, 0x040014U, 0x080220U, 0x008048U, 0x040011U, 0x040010U, - 0x204400U, 0x040012U, 0x000200U, 0x000201U, 0x000202U, 0x000203U, 0x000204U, 0x000205U, 0x000206U, 0x108400U, - 0x000208U, 0x000209U, 0x00020AU, 0x050080U, 0x00020CU, 0x200110U, 0x083000U, 0x400840U, 0x000210U, 0x000211U, - 0x000212U, 0x021040U, 0x000214U, 0x200108U, 0x004880U, 0x0C0020U, 0x000218U, 0x200104U, 0x400420U, 0x00E000U, - 0x200101U, 0x200100U, 0x130000U, 0x200102U, 0x000220U, 0x000221U, 0x000222U, 0x202800U, 0x000224U, 0x401080U, - 0x010140U, 0x0C0010U, 0x000228U, 0x088040U, 0x400410U, 0x101100U, 0x140800U, 0x012400U, 0x208080U, 0x024200U, - 0x000230U, 0x114000U, 0x400408U, 0x0C0004U, 0x02A000U, 0x0C0002U, 0x0C0001U, 0x0C0000U, 0x400402U, 0x020880U, - 0x400400U, 0x400401U, 0x005040U, 0x200120U, 0x400404U, 0x0C0008U, 0x000240U, 0x000241U, 0x000242U, 0x021010U, - 0x000244U, 0x046000U, 0x010120U, 0x400808U, 0x000248U, 0x088020U, 0x304000U, 0x400804U, 0x020480U, 0x400802U, - 0x400801U, 0x400800U, 0x000250U, 0x021002U, 0x021001U, 0x021000U, 0x580000U, 0x018080U, 0x202400U, 0x021004U, - 0x012800U, 0x140400U, 0x080180U, 0x021008U, 0x005020U, 0x200140U, 0x048200U, 0x400810U, 0x000260U, 0x088008U, - 0x010104U, 0x004480U, 0x010102U, 0x320000U, 0x010100U, 0x010101U, 0x088001U, 0x088000U, 0x062000U, 0x088002U, - 0x005010U, 0x088004U, 0x010108U, 0x400820U, 0x240080U, 0x402100U, 0x108800U, 0x021020U, 0x005008U, 0x000E00U, - 0x010110U, 0x0C0040U, 0x005004U, 0x088010U, 0x400440U, 0x210200U, 0x005000U, 0x005001U, 0x005002U, 0x102080U, - 0x000280U, 0x000281U, 0x000282U, 0x050008U, 0x000284U, 0x401020U, 0x004810U, 0x022100U, 0x000288U, 0x050002U, - 0x050001U, 0x050000U, 0x020440U, 0x184000U, 0x208020U, 0x050004U, 0x000290U, 0x082400U, 0x004804U, 0x700000U, - 0x004802U, 0x018040U, 0x004800U, 0x004801U, 0x109000U, 0x020820U, 0x080140U, 0x050010U, 0x442000U, 0x200180U, - 0x004808U, 0x001600U, 0x0002A0U, 0x401004U, 0x1A0000U, 0x004440U, 0x401001U, 0x401000U, 0x208008U, 0x401002U, - 0x006100U, 0x020810U, 0x208004U, 0x050020U, 0x208002U, 0x401008U, 0x208000U, 0x208001U, 0x240040U, 0x020808U, - 0x013000U, 0x008300U, 0x100500U, 0x401010U, 0x004820U, 0x0C0080U, 0x020801U, 0x020800U, 0x400480U, 0x020802U, - 0x090200U, 0x020804U, 0x208010U, 0x102040U, 0x0002C0U, 0x100900U, 0x40A000U, 0x004420U, 0x020408U, 0x018010U, - 0x141000U, 0x280200U, 0x020404U, 0x203000U, 0x080110U, 0x050040U, 0x020400U, 0x020401U, 0x020402U, 0x400880U, - 0x240020U, 0x018004U, 0x080108U, 0x021080U, 0x018001U, 0x018000U, 0x004840U, 0x018002U, 0x080102U, 0x404200U, - 0x080100U, 0x080101U, 0x020410U, 0x018008U, 0x080104U, 0x102020U, 0x240010U, 0x004402U, 0x004401U, 0x004400U, - 0x082800U, 0x401040U, 0x010180U, 0x004404U, 0x510000U, 0x088080U, 0x001A00U, 0x004408U, 0x020420U, 0x040300U, - 0x208040U, 0x102010U, 0x240000U, 0x240001U, 0x240002U, 0x004410U, 0x240004U, 0x018020U, 0x420200U, 0x102008U, - 0x240008U, 0x020840U, 0x080120U, 0x102004U, 0x005080U, 0x102002U, 0x102001U, 0x102000U, 0x000300U, 0x000301U, - 0x000302U, 0x484000U, 0x000304U, 0x200018U, 0x010060U, 0x022080U, 0x000308U, 0x200014U, 0x028800U, 0x101020U, - 0x200011U, 0x200010U, 0x044400U, 0x200012U, 0x000310U, 0x20000CU, 0x142000U, 0x010C00U, 0x200009U, 0x200008U, - 0x409000U, 0x20000AU, 0x200005U, 0x200004U, 0x0800C0U, 0x200006U, 0x200001U, 0x200000U, 0x200003U, 0x200002U, - 0x000320U, 0x060400U, 0x010044U, 0x101008U, 0x010042U, 0x00C800U, 0x010040U, 0x010041U, 0x006080U, 0x101002U, - 0x101001U, 0x101000U, 0x4A0000U, 0x200030U, 0x010048U, 0x101004U, 0x081800U, 0x402040U, 0x224000U, 0x008280U, - 0x100480U, 0x200028U, 0x010050U, 0x0C0100U, 0x058000U, 0x200024U, 0x400500U, 0x101010U, 0x200021U, 0x200020U, - 0x002A00U, 0x200022U, 0x000340U, 0x100880U, 0x010024U, 0x248000U, 0x010022U, 0x081400U, 0x010020U, 0x010021U, - 0x441000U, 0x034000U, 0x080090U, 0x002600U, 0x10A000U, 0x200050U, 0x010028U, 0x400900U, 0x00C400U, 0x402020U, - 0x080088U, 0x021100U, 0x060800U, 0x200048U, 0x010030U, 0x104200U, 0x080082U, 0x200044U, 0x080080U, 0x080081U, - 0x200041U, 0x200040U, 0x080084U, 0x200042U, 0x010006U, 0x402010U, 0x010004U, 0x010005U, 0x010002U, 0x010003U, - 0x010000U, 0x010001U, 0x200C00U, 0x088100U, 0x01000CU, 0x101040U, 0x01000AU, 0x040280U, 0x010008U, 0x010009U, - 0x402001U, 0x402000U, 0x010014U, 0x402002U, 0x010012U, 0x402004U, 0x010010U, 0x010011U, 0x120200U, 0x402008U, - 0x0800A0U, 0x044800U, 0x005100U, 0x200060U, 0x010018U, 0x028400U, 0x000380U, 0x100840U, 0x201400U, 0x022004U, - 0x0C8000U, 0x022002U, 0x022001U, 0x022000U, 0x006020U, 0x408400U, 0x080050U, 0x050100U, 0x011800U, 0x200090U, - 0x500200U, 0x022008U, 0x430000U, 0x045000U, 0x080048U, 0x008220U, 0x100420U, 0x200088U, 0x004900U, 0x022010U, - 0x080042U, 0x200084U, 0x080040U, 0x080041U, 0x200081U, 0x200080U, 0x080044U, 0x200082U, 0x006008U, 0x290000U, - 0x440800U, 0x008210U, 0x100410U, 0x401100U, 0x0100C0U, 0x022020U, 0x006000U, 0x006001U, 0x006002U, 0x101080U, - 0x006004U, 0x040240U, 0x208100U, 0x080C00U, 0x100404U, 0x008202U, 0x008201U, 0x008200U, 0x100400U, 0x100401U, - 0x100402U, 0x008204U, 0x006010U, 0x020900U, 0x080060U, 0x008208U, 0x100408U, 0x2000A0U, 0x061000U, 0x414000U, - 0x100801U, 0x100800U, 0x080018U, 0x100802U, 0x604000U, 0x100804U, 0x0100A0U, 0x022040U, 0x080012U, 0x100808U, - 0x080010U, 0x080011U, 0x020500U, 0x040220U, 0x080014U, 0x00D000U, 0x08000AU, 0x100810U, 0x080008U, 0x080009U, - 0x003200U, 0x018100U, 0x08000CU, 0x440400U, 0x080002U, 0x080003U, 0x080000U, 0x080001U, 0x080006U, 0x2000C0U, - 0x080004U, 0x080005U, 0x029000U, 0x100820U, 0x010084U, 0x004500U, 0x010082U, 0x040208U, 0x010080U, 0x010081U, - 0x006040U, 0x040204U, 0x080030U, 0x620000U, 0x040201U, 0x040200U, 0x010088U, 0x040202U, 0x240100U, 0x402080U, - 0x080028U, 0x008240U, 0x100440U, 0x0A4000U, 0x010090U, 0x201800U, 0x080022U, 0x011400U, 0x080020U, 0x080021U, - 0x408800U, 0x040210U, 0x080024U, 0x102100U, 0x000400U, 0x000401U, 0x000402U, 0x000403U, 0x000404U, 0x000405U, - 0x000406U, 0x108200U, 0x000408U, 0x000409U, 0x00040AU, 0x002140U, 0x00040CU, 0x4C0000U, 0x210800U, 0x001090U, - 0x000410U, 0x000411U, 0x000412U, 0x244000U, 0x000414U, 0x000860U, 0x0A0100U, 0x001088U, 0x000418U, 0x038000U, - 0x400220U, 0x001084U, 0x106000U, 0x001082U, 0x001081U, 0x001080U, 0x000420U, 0x000421U, 0x000422U, 0x091000U, - 0x000424U, 0x000850U, 0x042080U, 0x600100U, 0x000428U, 0x300080U, 0x400210U, 0x048800U, 0x009100U, 0x012200U, - 0x180040U, 0x024400U, 0x000430U, 0x000844U, 0x400208U, 0x122000U, 0x000841U, 0x000840U, 0x01C000U, 0x000842U, - 0x400202U, 0x084100U, 0x400200U, 0x400201U, 0x260000U, 0x000848U, 0x400204U, 0x0010A0U, 0x000440U, 0x000441U, - 0x000442U, 0x002108U, 0x000444U, 0x000830U, 0x405000U, 0x070000U, 0x000448U, 0x002102U, 0x002101U, 0x002100U, - 0x020280U, 0x20C000U, 0x180020U, 0x002104U, 0x000450U, 0x000824U, 0x110080U, 0x488000U, 0x000821U, 0x000820U, - 0x202200U, 0x000822U, 0x281000U, 0x140200U, 0x024800U, 0x002110U, 0x410100U, 0x000828U, 0x048400U, 0x0010C0U, - 0x000460U, 0x000814U, 0x228000U, 0x004280U, 0x000811U, 0x000810U, 0x180008U, 0x000812U, 0x054000U, 0x421000U, - 0x180004U, 0x002120U, 0x180002U, 0x000818U, 0x180000U, 0x180001U, 0x000805U, 0x000804U, 0x041100U, 0x000806U, - 0x000801U, 0x000800U, 0x000803U, 0x000802U, 0x00A080U, 0x00080CU, 0x400240U, 0x210400U, 0x000809U, 0x000808U, - 0x180010U, 0x00080AU, 0x000480U, 0x000481U, 0x000482U, 0x420800U, 0x000484U, 0x014100U, 0x042020U, 0x001018U, - 0x000488U, 0x300020U, 0x08C000U, 0x001014U, 0x020240U, 0x001012U, 0x001011U, 0x001010U, 0x000490U, 0x082200U, - 0x110040U, 0x00100CU, 0x608000U, 0x00100AU, 0x001009U, 0x001008U, 0x040900U, 0x001006U, 0x001005U, 0x001004U, - 0x001003U, 0x001002U, 0x001001U, 0x001000U, 0x0004A0U, 0x300008U, 0x042004U, 0x004240U, 0x042002U, 0x0A8000U, - 0x042000U, 0x042001U, 0x300001U, 0x300000U, 0x030100U, 0x300002U, 0x404800U, 0x300004U, 0x042008U, 0x001030U, - 0x025000U, 0x450000U, 0x280800U, 0x008500U, 0x100300U, 0x0008C0U, 0x042010U, 0x001028U, 0x00A040U, 0x300010U, - 0x400280U, 0x001024U, 0x090400U, 0x001022U, 0x001021U, 0x001020U, 0x0004C0U, 0x049000U, 0x110010U, 0x004220U, - 0x020208U, 0x502000U, 0x008900U, 0x280400U, 0x020204U, 0x090800U, 0x640000U, 0x002180U, 0x020200U, 0x020201U, - 0x020202U, 0x001050U, 0x110002U, 0x220100U, 0x110000U, 0x110001U, 0x0C4000U, 0x0008A0U, 0x110004U, 0x001048U, - 0x00A020U, 0x404400U, 0x110008U, 0x001044U, 0x020210U, 0x001042U, 0x001041U, 0x001040U, 0x480100U, 0x004202U, - 0x004201U, 0x004200U, 0x211000U, 0x000890U, 0x042040U, 0x004204U, 0x00A010U, 0x300040U, 0x001C00U, 0x004208U, - 0x020220U, 0x040500U, 0x180080U, 0x418000U, 0x00A008U, 0x000884U, 0x110020U, 0x004210U, 0x000881U, 0x000880U, - 0x420400U, 0x000882U, 0x00A000U, 0x00A001U, 0x00A002U, 0x0E0000U, 0x00A004U, 0x000888U, 0x204100U, 0x001060U, - 0x000500U, 0x000501U, 0x000502U, 0x002048U, 0x000504U, 0x014080U, 0x0A0010U, 0x600020U, 0x000508U, 0x002042U, - 0x002041U, 0x002040U, 0x009020U, 0x120800U, 0x044200U, 0x002044U, 0x000510U, 0x501000U, 0x0A0004U, 0x010A00U, - 0x0A0002U, 0x04A000U, 0x0A0000U, 0x0A0001U, 0x040880U, 0x084020U, 0x308000U, 0x002050U, 0x410040U, 0x200600U, - 0x0A0008U, 0x001180U, 0x000520U, 0x060200U, 0x104800U, 0x600004U, 0x009008U, 0x600002U, 0x600001U, 0x600000U, - 0x009004U, 0x084010U, 0x030080U, 0x002060U, 0x009000U, 0x009001U, 0x009002U, 0x600008U, 0x212000U, 0x084008U, - 0x041040U, 0x008480U, 0x100280U, 0x000940U, 0x0A0020U, 0x600010U, 0x084001U, 0x084000U, 0x400300U, 0x084002U, - 0x009010U, 0x084004U, 0x002C00U, 0x150000U, 0x000540U, 0x00200AU, 0x002009U, 0x002008U, 0x340000U, 0x081200U, - 0x008880U, 0x00200CU, 0x002003U, 0x002002U, 0x002001U, 0x002000U, 0x410010U, 0x002006U, 0x002005U, 0x002004U, - 0x00C200U, 0x220080U, 0x041020U, 0x002018U, 0x410008U, 0x000920U, 0x0A0040U, 0x104400U, 0x410004U, 0x002012U, - 0x002011U, 0x002010U, 0x410000U, 0x410001U, 0x410002U, 0x002014U, 0x480080U, 0x118000U, 0x041010U, 0x002028U, - 0x026000U, 0x000910U, 0x010600U, 0x600040U, 0x200A00U, 0x002022U, 0x002021U, 0x002020U, 0x009040U, 0x040480U, - 0x180100U, 0x002024U, 0x041002U, 0x000904U, 0x041000U, 0x041001U, 0x000901U, 0x000900U, 0x041004U, 0x000902U, - 0x120400U, 0x084040U, 0x041008U, 0x002030U, 0x410020U, 0x000908U, 0x204080U, 0x028200U, 0x000580U, 0x014004U, - 0x201200U, 0x1C0000U, 0x014001U, 0x014000U, 0x008840U, 0x014002U, 0x040810U, 0x408200U, 0x030020U, 0x0020C0U, - 0x282000U, 0x014008U, 0x500400U, 0x001110U, 0x040808U, 0x220040U, 0x406000U, 0x008420U, 0x100220U, 0x014010U, - 0x0A0080U, 0x001108U, 0x040800U, 0x040801U, 0x040802U, 0x001104U, 0x040804U, 0x001102U, 0x001101U, 0x001100U, - 0x480040U, 0x003800U, 0x030008U, 0x008410U, 0x100210U, 0x014020U, 0x042100U, 0x600080U, 0x030002U, 0x300100U, - 0x030000U, 0x030001U, 0x009080U, 0x040440U, 0x030004U, 0x080A00U, 0x100204U, 0x008402U, 0x008401U, 0x008400U, - 0x100200U, 0x100201U, 0x100202U, 0x008404U, 0x040820U, 0x084080U, 0x030010U, 0x008408U, 0x100208U, 0x422000U, - 0x204040U, 0x001120U, 0x480020U, 0x220010U, 0x008804U, 0x002088U, 0x008802U, 0x014040U, 0x008800U, 0x008801U, - 0x105000U, 0x002082U, 0x002081U, 0x002080U, 0x020300U, 0x040420U, 0x008808U, 0x002084U, 0x220001U, 0x220000U, - 0x110100U, 0x220002U, 0x003400U, 0x220004U, 0x008810U, 0x440200U, 0x040840U, 0x220008U, 0x080600U, 0x002090U, - 0x410080U, 0x188000U, 0x204020U, 0x001140U, 0x480000U, 0x480001U, 0x480002U, 0x004300U, 0x480004U, 0x040408U, - 0x008820U, 0x121000U, 0x480008U, 0x040404U, 0x030040U, 0x0020A0U, 0x040401U, 0x040400U, 0x204010U, 0x040402U, - 0x480010U, 0x220020U, 0x041080U, 0x008440U, 0x100240U, 0x000980U, 0x204008U, 0x092000U, 0x00A100U, 0x011200U, - 0x204004U, 0x500800U, 0x204002U, 0x040410U, 0x204000U, 0x204001U, 0x000600U, 0x000601U, 0x000602U, 0x108004U, - 0x000604U, 0x108002U, 0x108001U, 0x108000U, 0x000608U, 0x005800U, 0x400030U, 0x2A0000U, 0x0200C0U, 0x012020U, - 0x044100U, 0x108008U, 0x000610U, 0x082080U, 0x400028U, 0x010900U, 0x051000U, 0x424000U, 0x202040U, 0x108010U, - 0x400022U, 0x140040U, 0x400020U, 0x400021U, 0x088800U, 0x200500U, 0x400024U, 0x001280U, 0x000620U, 0x060100U, - 0x400018U, 0x0040C0U, 0x284000U, 0x012008U, 0x021800U, 0x108020U, 0x400012U, 0x012004U, 0x400010U, 0x400011U, - 0x012001U, 0x012000U, 0x400014U, 0x012002U, 0x40000AU, 0x209000U, 0x400008U, 0x400009U, 0x100180U, 0x000A40U, - 0x40000CU, 0x0C0400U, 0x400002U, 0x400003U, 0x400000U, 0x400001U, 0x400006U, 0x012010U, 0x400004U, 0x400005U, - 0x000640U, 0x610000U, 0x0C0800U, 0x0040A0U, 0x020088U, 0x081100U, 0x202010U, 0x108040U, 0x020084U, 0x140010U, - 0x019000U, 0x002300U, 0x020080U, 0x020081U, 0x020082U, 0x400C00U, 0x00C100U, 0x140008U, 0x202004U, 0x021400U, - 0x202002U, 0x000A20U, 0x202000U, 0x202001U, 0x140001U, 0x140000U, 0x400060U, 0x140002U, 0x020090U, 0x140004U, - 0x202008U, 0x094000U, 0x103000U, 0x004082U, 0x004081U, 0x004080U, 0x448000U, 0x000A10U, 0x010500U, 0x004084U, - 0x200900U, 0x088400U, 0x400050U, 0x004088U, 0x0200A0U, 0x012040U, 0x180200U, 0x241000U, 0x0B0000U, 0x000A04U, - 0x400048U, 0x004090U, 0x000A01U, 0x000A00U, 0x202020U, 0x000A02U, 0x400042U, 0x140020U, 0x400040U, 0x400041U, - 0x005400U, 0x000A08U, 0x400044U, 0x028100U, 0x000680U, 0x082010U, 0x201100U, 0x004060U, 0x020048U, 0x240800U, - 0x490000U, 0x108080U, 0x020044U, 0x408100U, 0x102800U, 0x050400U, 0x020040U, 0x020041U, 0x020042U, 0x001210U, - 0x082001U, 0x082000U, 0x068000U, 0x082002U, 0x100120U, 0x082004U, 0x004C00U, 0x001208U, 0x214000U, 0x082008U, - 0x4000A0U, 0x001204U, 0x020050U, 0x001202U, 0x001201U, 0x001200U, 0x018800U, 0x004042U, 0x004041U, 0x004040U, - 0x100110U, 0x401400U, 0x042200U, 0x004044U, 0x0C1000U, 0x300200U, 0x400090U, 0x004048U, 0x020060U, 0x012080U, - 0x208400U, 0x080900U, 0x100104U, 0x082020U, 0x400088U, 0x004050U, 0x100100U, 0x100101U, 0x100102U, 0x230000U, - 0x400082U, 0x020C00U, 0x400080U, 0x400081U, 0x100108U, 0x04C000U, 0x400084U, 0x001220U, 0x02000CU, 0x004022U, - 0x004021U, 0x004020U, 0x020008U, 0x020009U, 0x02000AU, 0x004024U, 0x020004U, 0x020005U, 0x020006U, 0x004028U, - 0x020000U, 0x020001U, 0x020002U, 0x020003U, 0x401800U, 0x082040U, 0x110200U, 0x004030U, 0x020018U, 0x018400U, - 0x202080U, 0x440100U, 0x020014U, 0x140080U, 0x080500U, 0x208800U, 0x020010U, 0x020011U, 0x020012U, 0x001240U, - 0x004003U, 0x004002U, 0x004001U, 0x004000U, 0x020028U, 0x004006U, 0x004005U, 0x004004U, 0x020024U, 0x00400AU, - 0x004009U, 0x004008U, 0x020020U, 0x020021U, 0x020022U, 0x00400CU, 0x240400U, 0x004012U, 0x004011U, 0x004010U, - 0x100140U, 0x000A80U, 0x089000U, 0x004014U, 0x00A200U, 0x011100U, 0x4000C0U, 0x004018U, 0x020030U, 0x680000U, - 0x050800U, 0x102400U, 0x000700U, 0x060020U, 0x201080U, 0x010810U, 0x402800U, 0x081040U, 0x044008U, 0x108100U, - 0x190000U, 0x408080U, 0x044004U, 0x002240U, 0x044002U, 0x200410U, 0x044000U, 0x044001U, 0x00C040U, 0x010802U, - 0x010801U, 0x010800U, 0x1000A0U, 0x200408U, 0x0A0200U, 0x010804U, 0x023000U, 0x200404U, 0x400120U, 0x010808U, - 0x200401U, 0x200400U, 0x044010U, 0x200402U, 0x060001U, 0x060000U, 0x08A000U, 0x060002U, 0x100090U, 0x060004U, - 0x010440U, 0x600200U, 0x200840U, 0x060008U, 0x400110U, 0x101400U, 0x009200U, 0x012100U, 0x044020U, 0x080880U, - 0x100084U, 0x060010U, 0x400108U, 0x010820U, 0x100080U, 0x100081U, 0x100082U, 0x007000U, 0x400102U, 0x084200U, - 0x400100U, 0x400101U, 0x100088U, 0x200420U, 0x400104U, 0x028040U, 0x00C010U, 0x081004U, 0x520000U, 0x002208U, - 0x081001U, 0x081000U, 0x010420U, 0x081002U, 0x200820U, 0x002202U, 0x002201U, 0x002200U, 0x020180U, 0x081008U, - 0x044040U, 0x002204U, 0x00C000U, 0x00C001U, 0x00C002U, 0x010840U, 0x00C004U, 0x081010U, 0x202100U, 0x440080U, - 0x00C008U, 0x140100U, 0x080480U, 0x002210U, 0x410200U, 0x200440U, 0x101800U, 0x028020U, 0x200808U, 0x060040U, - 0x010404U, 0x004180U, 0x010402U, 0x081020U, 0x010400U, 0x010401U, 0x200800U, 0x200801U, 0x200802U, 0x002220U, - 0x200804U, 0x504000U, 0x010408U, 0x028010U, 0x00C020U, 0x402400U, 0x041200U, 0x380000U, 0x1000C0U, 0x000B00U, - 0x010410U, 0x028008U, 0x200810U, 0x011080U, 0x400140U, 0x028004U, 0x0C2000U, 0x028002U, 0x028001U, 0x028000U, - 0x201002U, 0x408008U, 0x201000U, 0x201001U, 0x100030U, 0x014200U, 0x201004U, 0x022400U, 0x408001U, 0x408000U, - 0x201008U, 0x408002U, 0x020140U, 0x408004U, 0x044080U, 0x080820U, 0x100024U, 0x082100U, 0x201010U, 0x010880U, - 0x100020U, 0x100021U, 0x100022U, 0x440040U, 0x040A00U, 0x408010U, 0x080440U, 0x124000U, 0x100028U, 0x200480U, - 0x01A000U, 0x001300U, 0x100014U, 0x060080U, 0x201020U, 0x004140U, 0x100010U, 0x100011U, 0x100012U, 0x080808U, - 0x006400U, 0x408020U, 0x030200U, 0x080804U, 0x100018U, 0x080802U, 0x080801U, 0x080800U, 0x100004U, 0x100005U, - 0x100006U, 0x008600U, 0x100000U, 0x100001U, 0x100002U, 0x100003U, 0x10000CU, 0x011040U, 0x400180U, 0x242000U, - 0x100008U, 0x100009U, 0x10000AU, 0x080810U, 0x052000U, 0x100C00U, 0x201040U, 0x004120U, 0x020108U, 0x081080U, - 0x008A00U, 0x440010U, 0x020104U, 0x408040U, 0x080410U, 0x002280U, 0x020100U, 0x020101U, 0x020102U, 0x310000U, - 0x00C080U, 0x220200U, 0x080408U, 0x440004U, 0x100060U, 0x440002U, 0x440001U, 0x440000U, 0x080402U, 0x011020U, - 0x080400U, 0x080401U, 0x020110U, 0x006800U, 0x080404U, 0x440008U, 0x480200U, 0x004102U, 0x004101U, 0x004100U, - 0x100050U, 0x20A000U, 0x010480U, 0x004104U, 0x200880U, 0x011010U, 0x148000U, 0x004108U, 0x020120U, 0x040600U, - 0x403000U, 0x080840U, 0x100044U, 0x011008U, 0x022800U, 0x004110U, 0x100040U, 0x100041U, 0x100042U, 0x440020U, - 0x011001U, 0x011000U, 0x080420U, 0x011002U, 0x100048U, 0x011004U, 0x204200U, 0x028080U}; +static const unsigned int DECODING_TABLE_23127[] = +{ + 0x000000U, 0x000001U, 0x000002U, 0x000003U, 0x000004U, 0x000005U, 0x000006U, 0x000007U, 0x000008U, 0x000009U, + 0x00000AU, 0x00000BU, 0x00000CU, 0x00000DU, 0x00000EU, 0x024020U, 0x000010U, 0x000011U, 0x000012U, 0x000013U, + 0x000014U, 0x000015U, 0x000016U, 0x412000U, 0x000018U, 0x000019U, 0x00001AU, 0x180800U, 0x00001CU, 0x200300U, + 0x048040U, 0x001480U, 0x000020U, 0x000021U, 0x000022U, 0x000023U, 0x000024U, 0x000025U, 0x000026U, 0x024008U, + 0x000028U, 0x000029U, 0x00002AU, 0x024004U, 0x00002CU, 0x024002U, 0x024001U, 0x024000U, 0x000030U, 0x000031U, + 0x000032U, 0x008180U, 0x000034U, 0x000C40U, 0x301000U, 0x0C0200U, 0x000038U, 0x043000U, 0x400600U, 0x210040U, + 0x090080U, 0x508000U, 0x002900U, 0x024010U, 0x000040U, 0x000041U, 0x000042U, 0x000043U, 0x000044U, 0x000045U, + 0x000046U, 0x280080U, 0x000048U, 0x000049U, 0x00004AU, 0x002500U, 0x00004CU, 0x111000U, 0x048010U, 0x400A00U, + 0x000050U, 0x000051U, 0x000052U, 0x021200U, 0x000054U, 0x000C20U, 0x048008U, 0x104100U, 0x000058U, 0x404080U, + 0x048004U, 0x210020U, 0x048002U, 0x0A2000U, 0x048000U, 0x048001U, 0x000060U, 0x000061U, 0x000062U, 0x540000U, + 0x000064U, 0x000C10U, 0x010300U, 0x00B000U, 0x000068U, 0x088200U, 0x001880U, 0x210010U, 0x602000U, 0x040180U, + 0x180400U, 0x024040U, 0x000070U, 0x000C04U, 0x086000U, 0x210008U, 0x000C01U, 0x000C00U, 0x420080U, 0x000C02U, + 0x120100U, 0x210002U, 0x210001U, 0x210000U, 0x005200U, 0x000C08U, 0x048020U, 0x210004U, 0x000080U, 0x000081U, + 0x000082U, 0x000083U, 0x000084U, 0x000085U, 0x000086U, 0x280040U, 0x000088U, 0x000089U, 0x00008AU, 0x050200U, + 0x00008CU, 0x00A800U, 0x500100U, 0x001410U, 0x000090U, 0x000091U, 0x000092U, 0x008120U, 0x000094U, 0x160000U, + 0x004A00U, 0x001408U, 0x000098U, 0x404040U, 0x222000U, 0x001404U, 0x090020U, 0x001402U, 0x001401U, 0x001400U, + 0x0000A0U, 0x0000A1U, 0x0000A2U, 0x008110U, 0x0000A4U, 0x401200U, 0x042400U, 0x110800U, 0x0000A8U, 0x300400U, + 0x001840U, 0x482000U, 0x090010U, 0x040140U, 0x208200U, 0x024080U, 0x0000B0U, 0x008102U, 0x008101U, 0x008100U, + 0x090008U, 0x206000U, 0x420040U, 0x008104U, 0x090004U, 0x020A00U, 0x144000U, 0x008108U, 0x090000U, 0x090001U, + 0x090002U, 0x001420U, 0x0000C0U, 0x0000C1U, 0x0000C2U, 0x280004U, 0x0000C4U, 0x280002U, 0x280001U, 0x280000U, + 0x0000C8U, 0x404010U, 0x001820U, 0x128000U, 0x020600U, 0x040120U, 0x016000U, 0x280008U, 0x0000D0U, 0x404008U, + 0x110400U, 0x042800U, 0x003100U, 0x018200U, 0x420020U, 0x280010U, 0x404001U, 0x404000U, 0x080300U, 0x404002U, + 0x300800U, 0x404004U, 0x048080U, 0x001440U, 0x0000E0U, 0x032000U, 0x001808U, 0x004600U, 0x10C000U, 0x040108U, + 0x420010U, 0x280020U, 0x001802U, 0x040104U, 0x001800U, 0x001801U, 0x040101U, 0x040100U, 0x001804U, 0x040102U, + 0x240200U, 0x181000U, 0x420004U, 0x008140U, 0x420002U, 0x000C80U, 0x420000U, 0x420001U, 0x00A400U, 0x404020U, + 0x001810U, 0x210080U, 0x090040U, 0x040110U, 0x420008U, 0x102200U, 0x000100U, 0x000101U, 0x000102U, 0x000103U, + 0x000104U, 0x000105U, 0x000106U, 0x041800U, 0x000108U, 0x000109U, 0x00010AU, 0x002440U, 0x00010CU, 0x200210U, + 0x500080U, 0x098000U, 0x000110U, 0x000111U, 0x000112U, 0x0080A0U, 0x000114U, 0x200208U, 0x0A0400U, 0x104040U, + 0x000118U, 0x200204U, 0x015000U, 0x460000U, 0x200201U, 0x200200U, 0x002820U, 0x200202U, 0x000120U, 0x000121U, + 0x000122U, 0x008090U, 0x000124U, 0x182000U, 0x010240U, 0x600400U, 0x000128U, 0x410800U, 0x2C0000U, 0x101200U, + 0x009400U, 0x0400C0U, 0x002810U, 0x024100U, 0x000130U, 0x008082U, 0x008081U, 0x008080U, 0x444000U, 0x031000U, + 0x002808U, 0x008084U, 0x120040U, 0x084400U, 0x002804U, 0x008088U, 0x002802U, 0x200220U, 0x002800U, 0x002801U, + 0x000140U, 0x000141U, 0x000142U, 0x002408U, 0x000144U, 0x428000U, 0x010220U, 0x104010U, 0x000148U, 0x002402U, + 0x002401U, 0x002400U, 0x084800U, 0x0400A0U, 0x221000U, 0x002404U, 0x000150U, 0x0D0000U, 0x600800U, 0x104004U, + 0x003080U, 0x104002U, 0x104001U, 0x104000U, 0x120020U, 0x009800U, 0x080280U, 0x002410U, 0x410400U, 0x200240U, + 0x048100U, 0x104008U, 0x000160U, 0x205000U, 0x010204U, 0x0A0800U, 0x010202U, 0x040088U, 0x010200U, 0x010201U, + 0x120010U, 0x040084U, 0x40C000U, 0x002420U, 0x040081U, 0x040080U, 0x010208U, 0x040082U, 0x120008U, 0x402200U, + 0x041400U, 0x0080C0U, 0x288000U, 0x000D00U, 0x010210U, 0x104020U, 0x120000U, 0x120001U, 0x120002U, 0x210100U, + 0x120004U, 0x040090U, 0x002840U, 0x481000U, 0x000180U, 0x000181U, 0x000182U, 0x008030U, 0x000184U, 0x014400U, + 0x500008U, 0x022200U, 0x000188U, 0x0A1000U, 0x500004U, 0x204800U, 0x500002U, 0x040060U, 0x500000U, 0x500001U, + 0x000190U, 0x008022U, 0x008021U, 0x008020U, 0x003040U, 0x480800U, 0x250000U, 0x008024U, 0x040C00U, 0x112000U, + 0x080240U, 0x008028U, 0x02C000U, 0x200280U, 0x500010U, 0x001500U, 0x0001A0U, 0x008012U, 0x008011U, 0x008010U, + 0x220800U, 0x040048U, 0x085000U, 0x008014U, 0x006200U, 0x040044U, 0x030400U, 0x008018U, 0x040041U, 0x040040U, + 0x500020U, 0x040042U, 0x008003U, 0x008002U, 0x008001U, 0x008000U, 0x100600U, 0x008006U, 0x008005U, 0x008004U, + 0x601000U, 0x00800AU, 0x008009U, 0x008008U, 0x090100U, 0x040050U, 0x002880U, 0x00800CU, 0x0001C0U, 0x100A00U, + 0x064000U, 0x411000U, 0x003010U, 0x040028U, 0x008C00U, 0x280100U, 0x218000U, 0x040024U, 0x080210U, 0x002480U, + 0x040021U, 0x040020U, 0x500040U, 0x040022U, 0x003004U, 0x220400U, 0x080208U, 0x008060U, 0x003000U, 0x003001U, + 0x003002U, 0x104080U, 0x080202U, 0x404100U, 0x080200U, 0x080201U, 0x003008U, 0x040030U, 0x080204U, 0x030800U, + 0x480400U, 0x04000CU, 0x302000U, 0x008050U, 0x040009U, 0x040008U, 0x010280U, 0x04000AU, 0x040005U, 0x040004U, + 0x001900U, 0x040006U, 0x040001U, 0x040000U, 0x040003U, 0x040002U, 0x014800U, 0x008042U, 0x008041U, 0x008040U, + 0x003020U, 0x040018U, 0x420100U, 0x008044U, 0x120080U, 0x040014U, 0x080220U, 0x008048U, 0x040011U, 0x040010U, + 0x204400U, 0x040012U, 0x000200U, 0x000201U, 0x000202U, 0x000203U, 0x000204U, 0x000205U, 0x000206U, 0x108400U, + 0x000208U, 0x000209U, 0x00020AU, 0x050080U, 0x00020CU, 0x200110U, 0x083000U, 0x400840U, 0x000210U, 0x000211U, + 0x000212U, 0x021040U, 0x000214U, 0x200108U, 0x004880U, 0x0C0020U, 0x000218U, 0x200104U, 0x400420U, 0x00E000U, + 0x200101U, 0x200100U, 0x130000U, 0x200102U, 0x000220U, 0x000221U, 0x000222U, 0x202800U, 0x000224U, 0x401080U, + 0x010140U, 0x0C0010U, 0x000228U, 0x088040U, 0x400410U, 0x101100U, 0x140800U, 0x012400U, 0x208080U, 0x024200U, + 0x000230U, 0x114000U, 0x400408U, 0x0C0004U, 0x02A000U, 0x0C0002U, 0x0C0001U, 0x0C0000U, 0x400402U, 0x020880U, + 0x400400U, 0x400401U, 0x005040U, 0x200120U, 0x400404U, 0x0C0008U, 0x000240U, 0x000241U, 0x000242U, 0x021010U, + 0x000244U, 0x046000U, 0x010120U, 0x400808U, 0x000248U, 0x088020U, 0x304000U, 0x400804U, 0x020480U, 0x400802U, + 0x400801U, 0x400800U, 0x000250U, 0x021002U, 0x021001U, 0x021000U, 0x580000U, 0x018080U, 0x202400U, 0x021004U, + 0x012800U, 0x140400U, 0x080180U, 0x021008U, 0x005020U, 0x200140U, 0x048200U, 0x400810U, 0x000260U, 0x088008U, + 0x010104U, 0x004480U, 0x010102U, 0x320000U, 0x010100U, 0x010101U, 0x088001U, 0x088000U, 0x062000U, 0x088002U, + 0x005010U, 0x088004U, 0x010108U, 0x400820U, 0x240080U, 0x402100U, 0x108800U, 0x021020U, 0x005008U, 0x000E00U, + 0x010110U, 0x0C0040U, 0x005004U, 0x088010U, 0x400440U, 0x210200U, 0x005000U, 0x005001U, 0x005002U, 0x102080U, + 0x000280U, 0x000281U, 0x000282U, 0x050008U, 0x000284U, 0x401020U, 0x004810U, 0x022100U, 0x000288U, 0x050002U, + 0x050001U, 0x050000U, 0x020440U, 0x184000U, 0x208020U, 0x050004U, 0x000290U, 0x082400U, 0x004804U, 0x700000U, + 0x004802U, 0x018040U, 0x004800U, 0x004801U, 0x109000U, 0x020820U, 0x080140U, 0x050010U, 0x442000U, 0x200180U, + 0x004808U, 0x001600U, 0x0002A0U, 0x401004U, 0x1A0000U, 0x004440U, 0x401001U, 0x401000U, 0x208008U, 0x401002U, + 0x006100U, 0x020810U, 0x208004U, 0x050020U, 0x208002U, 0x401008U, 0x208000U, 0x208001U, 0x240040U, 0x020808U, + 0x013000U, 0x008300U, 0x100500U, 0x401010U, 0x004820U, 0x0C0080U, 0x020801U, 0x020800U, 0x400480U, 0x020802U, + 0x090200U, 0x020804U, 0x208010U, 0x102040U, 0x0002C0U, 0x100900U, 0x40A000U, 0x004420U, 0x020408U, 0x018010U, + 0x141000U, 0x280200U, 0x020404U, 0x203000U, 0x080110U, 0x050040U, 0x020400U, 0x020401U, 0x020402U, 0x400880U, + 0x240020U, 0x018004U, 0x080108U, 0x021080U, 0x018001U, 0x018000U, 0x004840U, 0x018002U, 0x080102U, 0x404200U, + 0x080100U, 0x080101U, 0x020410U, 0x018008U, 0x080104U, 0x102020U, 0x240010U, 0x004402U, 0x004401U, 0x004400U, + 0x082800U, 0x401040U, 0x010180U, 0x004404U, 0x510000U, 0x088080U, 0x001A00U, 0x004408U, 0x020420U, 0x040300U, + 0x208040U, 0x102010U, 0x240000U, 0x240001U, 0x240002U, 0x004410U, 0x240004U, 0x018020U, 0x420200U, 0x102008U, + 0x240008U, 0x020840U, 0x080120U, 0x102004U, 0x005080U, 0x102002U, 0x102001U, 0x102000U, 0x000300U, 0x000301U, + 0x000302U, 0x484000U, 0x000304U, 0x200018U, 0x010060U, 0x022080U, 0x000308U, 0x200014U, 0x028800U, 0x101020U, + 0x200011U, 0x200010U, 0x044400U, 0x200012U, 0x000310U, 0x20000CU, 0x142000U, 0x010C00U, 0x200009U, 0x200008U, + 0x409000U, 0x20000AU, 0x200005U, 0x200004U, 0x0800C0U, 0x200006U, 0x200001U, 0x200000U, 0x200003U, 0x200002U, + 0x000320U, 0x060400U, 0x010044U, 0x101008U, 0x010042U, 0x00C800U, 0x010040U, 0x010041U, 0x006080U, 0x101002U, + 0x101001U, 0x101000U, 0x4A0000U, 0x200030U, 0x010048U, 0x101004U, 0x081800U, 0x402040U, 0x224000U, 0x008280U, + 0x100480U, 0x200028U, 0x010050U, 0x0C0100U, 0x058000U, 0x200024U, 0x400500U, 0x101010U, 0x200021U, 0x200020U, + 0x002A00U, 0x200022U, 0x000340U, 0x100880U, 0x010024U, 0x248000U, 0x010022U, 0x081400U, 0x010020U, 0x010021U, + 0x441000U, 0x034000U, 0x080090U, 0x002600U, 0x10A000U, 0x200050U, 0x010028U, 0x400900U, 0x00C400U, 0x402020U, + 0x080088U, 0x021100U, 0x060800U, 0x200048U, 0x010030U, 0x104200U, 0x080082U, 0x200044U, 0x080080U, 0x080081U, + 0x200041U, 0x200040U, 0x080084U, 0x200042U, 0x010006U, 0x402010U, 0x010004U, 0x010005U, 0x010002U, 0x010003U, + 0x010000U, 0x010001U, 0x200C00U, 0x088100U, 0x01000CU, 0x101040U, 0x01000AU, 0x040280U, 0x010008U, 0x010009U, + 0x402001U, 0x402000U, 0x010014U, 0x402002U, 0x010012U, 0x402004U, 0x010010U, 0x010011U, 0x120200U, 0x402008U, + 0x0800A0U, 0x044800U, 0x005100U, 0x200060U, 0x010018U, 0x028400U, 0x000380U, 0x100840U, 0x201400U, 0x022004U, + 0x0C8000U, 0x022002U, 0x022001U, 0x022000U, 0x006020U, 0x408400U, 0x080050U, 0x050100U, 0x011800U, 0x200090U, + 0x500200U, 0x022008U, 0x430000U, 0x045000U, 0x080048U, 0x008220U, 0x100420U, 0x200088U, 0x004900U, 0x022010U, + 0x080042U, 0x200084U, 0x080040U, 0x080041U, 0x200081U, 0x200080U, 0x080044U, 0x200082U, 0x006008U, 0x290000U, + 0x440800U, 0x008210U, 0x100410U, 0x401100U, 0x0100C0U, 0x022020U, 0x006000U, 0x006001U, 0x006002U, 0x101080U, + 0x006004U, 0x040240U, 0x208100U, 0x080C00U, 0x100404U, 0x008202U, 0x008201U, 0x008200U, 0x100400U, 0x100401U, + 0x100402U, 0x008204U, 0x006010U, 0x020900U, 0x080060U, 0x008208U, 0x100408U, 0x2000A0U, 0x061000U, 0x414000U, + 0x100801U, 0x100800U, 0x080018U, 0x100802U, 0x604000U, 0x100804U, 0x0100A0U, 0x022040U, 0x080012U, 0x100808U, + 0x080010U, 0x080011U, 0x020500U, 0x040220U, 0x080014U, 0x00D000U, 0x08000AU, 0x100810U, 0x080008U, 0x080009U, + 0x003200U, 0x018100U, 0x08000CU, 0x440400U, 0x080002U, 0x080003U, 0x080000U, 0x080001U, 0x080006U, 0x2000C0U, + 0x080004U, 0x080005U, 0x029000U, 0x100820U, 0x010084U, 0x004500U, 0x010082U, 0x040208U, 0x010080U, 0x010081U, + 0x006040U, 0x040204U, 0x080030U, 0x620000U, 0x040201U, 0x040200U, 0x010088U, 0x040202U, 0x240100U, 0x402080U, + 0x080028U, 0x008240U, 0x100440U, 0x0A4000U, 0x010090U, 0x201800U, 0x080022U, 0x011400U, 0x080020U, 0x080021U, + 0x408800U, 0x040210U, 0x080024U, 0x102100U, 0x000400U, 0x000401U, 0x000402U, 0x000403U, 0x000404U, 0x000405U, + 0x000406U, 0x108200U, 0x000408U, 0x000409U, 0x00040AU, 0x002140U, 0x00040CU, 0x4C0000U, 0x210800U, 0x001090U, + 0x000410U, 0x000411U, 0x000412U, 0x244000U, 0x000414U, 0x000860U, 0x0A0100U, 0x001088U, 0x000418U, 0x038000U, + 0x400220U, 0x001084U, 0x106000U, 0x001082U, 0x001081U, 0x001080U, 0x000420U, 0x000421U, 0x000422U, 0x091000U, + 0x000424U, 0x000850U, 0x042080U, 0x600100U, 0x000428U, 0x300080U, 0x400210U, 0x048800U, 0x009100U, 0x012200U, + 0x180040U, 0x024400U, 0x000430U, 0x000844U, 0x400208U, 0x122000U, 0x000841U, 0x000840U, 0x01C000U, 0x000842U, + 0x400202U, 0x084100U, 0x400200U, 0x400201U, 0x260000U, 0x000848U, 0x400204U, 0x0010A0U, 0x000440U, 0x000441U, + 0x000442U, 0x002108U, 0x000444U, 0x000830U, 0x405000U, 0x070000U, 0x000448U, 0x002102U, 0x002101U, 0x002100U, + 0x020280U, 0x20C000U, 0x180020U, 0x002104U, 0x000450U, 0x000824U, 0x110080U, 0x488000U, 0x000821U, 0x000820U, + 0x202200U, 0x000822U, 0x281000U, 0x140200U, 0x024800U, 0x002110U, 0x410100U, 0x000828U, 0x048400U, 0x0010C0U, + 0x000460U, 0x000814U, 0x228000U, 0x004280U, 0x000811U, 0x000810U, 0x180008U, 0x000812U, 0x054000U, 0x421000U, + 0x180004U, 0x002120U, 0x180002U, 0x000818U, 0x180000U, 0x180001U, 0x000805U, 0x000804U, 0x041100U, 0x000806U, + 0x000801U, 0x000800U, 0x000803U, 0x000802U, 0x00A080U, 0x00080CU, 0x400240U, 0x210400U, 0x000809U, 0x000808U, + 0x180010U, 0x00080AU, 0x000480U, 0x000481U, 0x000482U, 0x420800U, 0x000484U, 0x014100U, 0x042020U, 0x001018U, + 0x000488U, 0x300020U, 0x08C000U, 0x001014U, 0x020240U, 0x001012U, 0x001011U, 0x001010U, 0x000490U, 0x082200U, + 0x110040U, 0x00100CU, 0x608000U, 0x00100AU, 0x001009U, 0x001008U, 0x040900U, 0x001006U, 0x001005U, 0x001004U, + 0x001003U, 0x001002U, 0x001001U, 0x001000U, 0x0004A0U, 0x300008U, 0x042004U, 0x004240U, 0x042002U, 0x0A8000U, + 0x042000U, 0x042001U, 0x300001U, 0x300000U, 0x030100U, 0x300002U, 0x404800U, 0x300004U, 0x042008U, 0x001030U, + 0x025000U, 0x450000U, 0x280800U, 0x008500U, 0x100300U, 0x0008C0U, 0x042010U, 0x001028U, 0x00A040U, 0x300010U, + 0x400280U, 0x001024U, 0x090400U, 0x001022U, 0x001021U, 0x001020U, 0x0004C0U, 0x049000U, 0x110010U, 0x004220U, + 0x020208U, 0x502000U, 0x008900U, 0x280400U, 0x020204U, 0x090800U, 0x640000U, 0x002180U, 0x020200U, 0x020201U, + 0x020202U, 0x001050U, 0x110002U, 0x220100U, 0x110000U, 0x110001U, 0x0C4000U, 0x0008A0U, 0x110004U, 0x001048U, + 0x00A020U, 0x404400U, 0x110008U, 0x001044U, 0x020210U, 0x001042U, 0x001041U, 0x001040U, 0x480100U, 0x004202U, + 0x004201U, 0x004200U, 0x211000U, 0x000890U, 0x042040U, 0x004204U, 0x00A010U, 0x300040U, 0x001C00U, 0x004208U, + 0x020220U, 0x040500U, 0x180080U, 0x418000U, 0x00A008U, 0x000884U, 0x110020U, 0x004210U, 0x000881U, 0x000880U, + 0x420400U, 0x000882U, 0x00A000U, 0x00A001U, 0x00A002U, 0x0E0000U, 0x00A004U, 0x000888U, 0x204100U, 0x001060U, + 0x000500U, 0x000501U, 0x000502U, 0x002048U, 0x000504U, 0x014080U, 0x0A0010U, 0x600020U, 0x000508U, 0x002042U, + 0x002041U, 0x002040U, 0x009020U, 0x120800U, 0x044200U, 0x002044U, 0x000510U, 0x501000U, 0x0A0004U, 0x010A00U, + 0x0A0002U, 0x04A000U, 0x0A0000U, 0x0A0001U, 0x040880U, 0x084020U, 0x308000U, 0x002050U, 0x410040U, 0x200600U, + 0x0A0008U, 0x001180U, 0x000520U, 0x060200U, 0x104800U, 0x600004U, 0x009008U, 0x600002U, 0x600001U, 0x600000U, + 0x009004U, 0x084010U, 0x030080U, 0x002060U, 0x009000U, 0x009001U, 0x009002U, 0x600008U, 0x212000U, 0x084008U, + 0x041040U, 0x008480U, 0x100280U, 0x000940U, 0x0A0020U, 0x600010U, 0x084001U, 0x084000U, 0x400300U, 0x084002U, + 0x009010U, 0x084004U, 0x002C00U, 0x150000U, 0x000540U, 0x00200AU, 0x002009U, 0x002008U, 0x340000U, 0x081200U, + 0x008880U, 0x00200CU, 0x002003U, 0x002002U, 0x002001U, 0x002000U, 0x410010U, 0x002006U, 0x002005U, 0x002004U, + 0x00C200U, 0x220080U, 0x041020U, 0x002018U, 0x410008U, 0x000920U, 0x0A0040U, 0x104400U, 0x410004U, 0x002012U, + 0x002011U, 0x002010U, 0x410000U, 0x410001U, 0x410002U, 0x002014U, 0x480080U, 0x118000U, 0x041010U, 0x002028U, + 0x026000U, 0x000910U, 0x010600U, 0x600040U, 0x200A00U, 0x002022U, 0x002021U, 0x002020U, 0x009040U, 0x040480U, + 0x180100U, 0x002024U, 0x041002U, 0x000904U, 0x041000U, 0x041001U, 0x000901U, 0x000900U, 0x041004U, 0x000902U, + 0x120400U, 0x084040U, 0x041008U, 0x002030U, 0x410020U, 0x000908U, 0x204080U, 0x028200U, 0x000580U, 0x014004U, + 0x201200U, 0x1C0000U, 0x014001U, 0x014000U, 0x008840U, 0x014002U, 0x040810U, 0x408200U, 0x030020U, 0x0020C0U, + 0x282000U, 0x014008U, 0x500400U, 0x001110U, 0x040808U, 0x220040U, 0x406000U, 0x008420U, 0x100220U, 0x014010U, + 0x0A0080U, 0x001108U, 0x040800U, 0x040801U, 0x040802U, 0x001104U, 0x040804U, 0x001102U, 0x001101U, 0x001100U, + 0x480040U, 0x003800U, 0x030008U, 0x008410U, 0x100210U, 0x014020U, 0x042100U, 0x600080U, 0x030002U, 0x300100U, + 0x030000U, 0x030001U, 0x009080U, 0x040440U, 0x030004U, 0x080A00U, 0x100204U, 0x008402U, 0x008401U, 0x008400U, + 0x100200U, 0x100201U, 0x100202U, 0x008404U, 0x040820U, 0x084080U, 0x030010U, 0x008408U, 0x100208U, 0x422000U, + 0x204040U, 0x001120U, 0x480020U, 0x220010U, 0x008804U, 0x002088U, 0x008802U, 0x014040U, 0x008800U, 0x008801U, + 0x105000U, 0x002082U, 0x002081U, 0x002080U, 0x020300U, 0x040420U, 0x008808U, 0x002084U, 0x220001U, 0x220000U, + 0x110100U, 0x220002U, 0x003400U, 0x220004U, 0x008810U, 0x440200U, 0x040840U, 0x220008U, 0x080600U, 0x002090U, + 0x410080U, 0x188000U, 0x204020U, 0x001140U, 0x480000U, 0x480001U, 0x480002U, 0x004300U, 0x480004U, 0x040408U, + 0x008820U, 0x121000U, 0x480008U, 0x040404U, 0x030040U, 0x0020A0U, 0x040401U, 0x040400U, 0x204010U, 0x040402U, + 0x480010U, 0x220020U, 0x041080U, 0x008440U, 0x100240U, 0x000980U, 0x204008U, 0x092000U, 0x00A100U, 0x011200U, + 0x204004U, 0x500800U, 0x204002U, 0x040410U, 0x204000U, 0x204001U, 0x000600U, 0x000601U, 0x000602U, 0x108004U, + 0x000604U, 0x108002U, 0x108001U, 0x108000U, 0x000608U, 0x005800U, 0x400030U, 0x2A0000U, 0x0200C0U, 0x012020U, + 0x044100U, 0x108008U, 0x000610U, 0x082080U, 0x400028U, 0x010900U, 0x051000U, 0x424000U, 0x202040U, 0x108010U, + 0x400022U, 0x140040U, 0x400020U, 0x400021U, 0x088800U, 0x200500U, 0x400024U, 0x001280U, 0x000620U, 0x060100U, + 0x400018U, 0x0040C0U, 0x284000U, 0x012008U, 0x021800U, 0x108020U, 0x400012U, 0x012004U, 0x400010U, 0x400011U, + 0x012001U, 0x012000U, 0x400014U, 0x012002U, 0x40000AU, 0x209000U, 0x400008U, 0x400009U, 0x100180U, 0x000A40U, + 0x40000CU, 0x0C0400U, 0x400002U, 0x400003U, 0x400000U, 0x400001U, 0x400006U, 0x012010U, 0x400004U, 0x400005U, + 0x000640U, 0x610000U, 0x0C0800U, 0x0040A0U, 0x020088U, 0x081100U, 0x202010U, 0x108040U, 0x020084U, 0x140010U, + 0x019000U, 0x002300U, 0x020080U, 0x020081U, 0x020082U, 0x400C00U, 0x00C100U, 0x140008U, 0x202004U, 0x021400U, + 0x202002U, 0x000A20U, 0x202000U, 0x202001U, 0x140001U, 0x140000U, 0x400060U, 0x140002U, 0x020090U, 0x140004U, + 0x202008U, 0x094000U, 0x103000U, 0x004082U, 0x004081U, 0x004080U, 0x448000U, 0x000A10U, 0x010500U, 0x004084U, + 0x200900U, 0x088400U, 0x400050U, 0x004088U, 0x0200A0U, 0x012040U, 0x180200U, 0x241000U, 0x0B0000U, 0x000A04U, + 0x400048U, 0x004090U, 0x000A01U, 0x000A00U, 0x202020U, 0x000A02U, 0x400042U, 0x140020U, 0x400040U, 0x400041U, + 0x005400U, 0x000A08U, 0x400044U, 0x028100U, 0x000680U, 0x082010U, 0x201100U, 0x004060U, 0x020048U, 0x240800U, + 0x490000U, 0x108080U, 0x020044U, 0x408100U, 0x102800U, 0x050400U, 0x020040U, 0x020041U, 0x020042U, 0x001210U, + 0x082001U, 0x082000U, 0x068000U, 0x082002U, 0x100120U, 0x082004U, 0x004C00U, 0x001208U, 0x214000U, 0x082008U, + 0x4000A0U, 0x001204U, 0x020050U, 0x001202U, 0x001201U, 0x001200U, 0x018800U, 0x004042U, 0x004041U, 0x004040U, + 0x100110U, 0x401400U, 0x042200U, 0x004044U, 0x0C1000U, 0x300200U, 0x400090U, 0x004048U, 0x020060U, 0x012080U, + 0x208400U, 0x080900U, 0x100104U, 0x082020U, 0x400088U, 0x004050U, 0x100100U, 0x100101U, 0x100102U, 0x230000U, + 0x400082U, 0x020C00U, 0x400080U, 0x400081U, 0x100108U, 0x04C000U, 0x400084U, 0x001220U, 0x02000CU, 0x004022U, + 0x004021U, 0x004020U, 0x020008U, 0x020009U, 0x02000AU, 0x004024U, 0x020004U, 0x020005U, 0x020006U, 0x004028U, + 0x020000U, 0x020001U, 0x020002U, 0x020003U, 0x401800U, 0x082040U, 0x110200U, 0x004030U, 0x020018U, 0x018400U, + 0x202080U, 0x440100U, 0x020014U, 0x140080U, 0x080500U, 0x208800U, 0x020010U, 0x020011U, 0x020012U, 0x001240U, + 0x004003U, 0x004002U, 0x004001U, 0x004000U, 0x020028U, 0x004006U, 0x004005U, 0x004004U, 0x020024U, 0x00400AU, + 0x004009U, 0x004008U, 0x020020U, 0x020021U, 0x020022U, 0x00400CU, 0x240400U, 0x004012U, 0x004011U, 0x004010U, + 0x100140U, 0x000A80U, 0x089000U, 0x004014U, 0x00A200U, 0x011100U, 0x4000C0U, 0x004018U, 0x020030U, 0x680000U, + 0x050800U, 0x102400U, 0x000700U, 0x060020U, 0x201080U, 0x010810U, 0x402800U, 0x081040U, 0x044008U, 0x108100U, + 0x190000U, 0x408080U, 0x044004U, 0x002240U, 0x044002U, 0x200410U, 0x044000U, 0x044001U, 0x00C040U, 0x010802U, + 0x010801U, 0x010800U, 0x1000A0U, 0x200408U, 0x0A0200U, 0x010804U, 0x023000U, 0x200404U, 0x400120U, 0x010808U, + 0x200401U, 0x200400U, 0x044010U, 0x200402U, 0x060001U, 0x060000U, 0x08A000U, 0x060002U, 0x100090U, 0x060004U, + 0x010440U, 0x600200U, 0x200840U, 0x060008U, 0x400110U, 0x101400U, 0x009200U, 0x012100U, 0x044020U, 0x080880U, + 0x100084U, 0x060010U, 0x400108U, 0x010820U, 0x100080U, 0x100081U, 0x100082U, 0x007000U, 0x400102U, 0x084200U, + 0x400100U, 0x400101U, 0x100088U, 0x200420U, 0x400104U, 0x028040U, 0x00C010U, 0x081004U, 0x520000U, 0x002208U, + 0x081001U, 0x081000U, 0x010420U, 0x081002U, 0x200820U, 0x002202U, 0x002201U, 0x002200U, 0x020180U, 0x081008U, + 0x044040U, 0x002204U, 0x00C000U, 0x00C001U, 0x00C002U, 0x010840U, 0x00C004U, 0x081010U, 0x202100U, 0x440080U, + 0x00C008U, 0x140100U, 0x080480U, 0x002210U, 0x410200U, 0x200440U, 0x101800U, 0x028020U, 0x200808U, 0x060040U, + 0x010404U, 0x004180U, 0x010402U, 0x081020U, 0x010400U, 0x010401U, 0x200800U, 0x200801U, 0x200802U, 0x002220U, + 0x200804U, 0x504000U, 0x010408U, 0x028010U, 0x00C020U, 0x402400U, 0x041200U, 0x380000U, 0x1000C0U, 0x000B00U, + 0x010410U, 0x028008U, 0x200810U, 0x011080U, 0x400140U, 0x028004U, 0x0C2000U, 0x028002U, 0x028001U, 0x028000U, + 0x201002U, 0x408008U, 0x201000U, 0x201001U, 0x100030U, 0x014200U, 0x201004U, 0x022400U, 0x408001U, 0x408000U, + 0x201008U, 0x408002U, 0x020140U, 0x408004U, 0x044080U, 0x080820U, 0x100024U, 0x082100U, 0x201010U, 0x010880U, + 0x100020U, 0x100021U, 0x100022U, 0x440040U, 0x040A00U, 0x408010U, 0x080440U, 0x124000U, 0x100028U, 0x200480U, + 0x01A000U, 0x001300U, 0x100014U, 0x060080U, 0x201020U, 0x004140U, 0x100010U, 0x100011U, 0x100012U, 0x080808U, + 0x006400U, 0x408020U, 0x030200U, 0x080804U, 0x100018U, 0x080802U, 0x080801U, 0x080800U, 0x100004U, 0x100005U, + 0x100006U, 0x008600U, 0x100000U, 0x100001U, 0x100002U, 0x100003U, 0x10000CU, 0x011040U, 0x400180U, 0x242000U, + 0x100008U, 0x100009U, 0x10000AU, 0x080810U, 0x052000U, 0x100C00U, 0x201040U, 0x004120U, 0x020108U, 0x081080U, + 0x008A00U, 0x440010U, 0x020104U, 0x408040U, 0x080410U, 0x002280U, 0x020100U, 0x020101U, 0x020102U, 0x310000U, + 0x00C080U, 0x220200U, 0x080408U, 0x440004U, 0x100060U, 0x440002U, 0x440001U, 0x440000U, 0x080402U, 0x011020U, + 0x080400U, 0x080401U, 0x020110U, 0x006800U, 0x080404U, 0x440008U, 0x480200U, 0x004102U, 0x004101U, 0x004100U, + 0x100050U, 0x20A000U, 0x010480U, 0x004104U, 0x200880U, 0x011010U, 0x148000U, 0x004108U, 0x020120U, 0x040600U, + 0x403000U, 0x080840U, 0x100044U, 0x011008U, 0x022800U, 0x004110U, 0x100040U, 0x100041U, 0x100042U, 0x440020U, + 0x011001U, 0x011000U, 0x080420U, 0x011002U, 0x100048U, 0x011004U, 0x204200U, 0x028080U +}; #define X22 0x00400000 /* vector representation of X^{22} */ #define X11 0x00000800 /* vector representation of X^{11} */ @@ -1055,54 +1061,56 @@ static unsigned int get_syndrome_23127(unsigned int pattern) * obtain its syndrome in decoding. */ { - unsigned int aux = X22; + unsigned int aux = X22; - if (pattern >= X11) { - while (pattern & MASK12) { - while (!(aux & pattern)) - aux = aux >> 1; + if (pattern >= X11) + { + while (pattern & MASK12) + { + while (!(aux & pattern)) + aux = aux >> 1; - pattern ^= (aux / X11) * GENPOL; - } - } + pattern ^= (aux / X11) * GENPOL; + } + } - return pattern; + return pattern; } unsigned int CGolay24128::encode23127(unsigned int data) { - return ENCODING_TABLE_23127[data]; + return ENCODING_TABLE_23127[data]; } unsigned int CGolay24128::encode24128(unsigned int data) { - return ENCODING_TABLE_24128[data]; + return ENCODING_TABLE_24128[data]; } unsigned int CGolay24128::decode23127(unsigned int code) { - unsigned int syndrome = ::get_syndrome_23127(code); - unsigned int error_pattern = DECODING_TABLE_23127[syndrome]; + unsigned int syndrome = ::get_syndrome_23127(code); + unsigned int error_pattern = DECODING_TABLE_23127[syndrome]; - code ^= error_pattern; + code ^= error_pattern; - return code >> 11; + return code >> 11; } unsigned int CGolay24128::decode24128(unsigned int code) { - return decode23127(code >> 1); + return decode23127(code >> 1); } unsigned int CGolay24128::decode24128(unsigned char* bytes) { - assert(bytes != nullptr); + assert(bytes != nullptr); - unsigned int code = bytes[0U]; - code <<= 8; - code |= bytes[1U]; - code <<= 8; - code |= bytes[2U]; + unsigned int code = bytes[0U]; + code <<= 8; + code |= bytes[1U]; + code <<= 8; + code |= bytes[2U]; - return decode23127(code >> 1); + return decode23127(code >> 1); } diff --git a/src/cgolay24128.h b/src/cgolay24128.h index c8eb3c2..6c820d1 100644 --- a/src/cgolay24128.h +++ b/src/cgolay24128.h @@ -19,14 +19,15 @@ #ifndef Golay24128_H #define Golay24128_H -class CGolay24128 { +class CGolay24128 +{ public: - static unsigned int encode23127(unsigned int data); - static unsigned int encode24128(unsigned int data); - - static unsigned int decode23127(unsigned int code); - static unsigned int decode24128(unsigned int code); - static unsigned int decode24128(unsigned char* bytes); + static unsigned int encode23127(unsigned int data); + static unsigned int encode24128(unsigned int data); + + static unsigned int decode23127(unsigned int code); + static unsigned int decode24128(unsigned int code); + static unsigned int decode24128(unsigned char* bytes); }; #endif diff --git a/src/chamming.cpp b/src/chamming.cpp index f6fa10a..5cf720d 100644 --- a/src/chamming.cpp +++ b/src/chamming.cpp @@ -24,326 +24,511 @@ // Hamming (15,11,3) check a boolean data array bool CHamming::decode15113_1(bool* d) { - assert(d != nullptr); - - // Calculate the parity it should have - bool c0 = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[6]; - bool c1 = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[7] ^ d[8] ^ d[9]; - bool c2 = d[0] ^ d[1] ^ d[4] ^ d[5] ^ d[7] ^ d[8] ^ d[10]; - bool c3 = d[0] ^ d[2] ^ d[4] ^ d[6] ^ d[7] ^ d[9] ^ d[10]; - - unsigned char n = 0U; - n |= (c0 != d[11]) ? 0x01U : 0x00U; - n |= (c1 != d[12]) ? 0x02U : 0x00U; - n |= (c2 != d[13]) ? 0x04U : 0x00U; - n |= (c3 != d[14]) ? 0x08U : 0x00U; - - switch (n) - { - // Parity bit errors - case 0x01U: d[11] = !d[11]; return true; - case 0x02U: d[12] = !d[12]; return true; - case 0x04U: d[13] = !d[13]; return true; - case 0x08U: d[14] = !d[14]; return true; - - // Data bit errors - case 0x0FU: d[0] = !d[0]; return true; - case 0x07U: d[1] = !d[1]; return true; - case 0x0BU: d[2] = !d[2]; return true; - case 0x03U: d[3] = !d[3]; return true; - case 0x0DU: d[4] = !d[4]; return true; - case 0x05U: d[5] = !d[5]; return true; - case 0x09U: d[6] = !d[6]; return true; - case 0x0EU: d[7] = !d[7]; return true; - case 0x06U: d[8] = !d[8]; return true; - case 0x0AU: d[9] = !d[9]; return true; - case 0x0CU: d[10] = !d[10]; return true; - - // No bit errors - default: return false; - } + assert(d != nullptr); + + // Calculate the parity it should have + bool c0 = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[6]; + bool c1 = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[7] ^ d[8] ^ d[9]; + bool c2 = d[0] ^ d[1] ^ d[4] ^ d[5] ^ d[7] ^ d[8] ^ d[10]; + bool c3 = d[0] ^ d[2] ^ d[4] ^ d[6] ^ d[7] ^ d[9] ^ d[10]; + + unsigned char n = 0U; + n |= (c0 != d[11]) ? 0x01U : 0x00U; + n |= (c1 != d[12]) ? 0x02U : 0x00U; + n |= (c2 != d[13]) ? 0x04U : 0x00U; + n |= (c3 != d[14]) ? 0x08U : 0x00U; + + switch (n) + { + // Parity bit errors + case 0x01U: + d[11] = !d[11]; + return true; + case 0x02U: + d[12] = !d[12]; + return true; + case 0x04U: + d[13] = !d[13]; + return true; + case 0x08U: + d[14] = !d[14]; + return true; + + // Data bit errors + case 0x0FU: + d[0] = !d[0]; + return true; + case 0x07U: + d[1] = !d[1]; + return true; + case 0x0BU: + d[2] = !d[2]; + return true; + case 0x03U: + d[3] = !d[3]; + return true; + case 0x0DU: + d[4] = !d[4]; + return true; + case 0x05U: + d[5] = !d[5]; + return true; + case 0x09U: + d[6] = !d[6]; + return true; + case 0x0EU: + d[7] = !d[7]; + return true; + case 0x06U: + d[8] = !d[8]; + return true; + case 0x0AU: + d[9] = !d[9]; + return true; + case 0x0CU: + d[10] = !d[10]; + return true; + + // No bit errors + default: + return false; + } } void CHamming::encode15113_1(bool* d) { - assert(d != nullptr); + assert(d != nullptr); - // Calculate the checksum this row should have - d[11] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[6]; - d[12] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[7] ^ d[8] ^ d[9]; - d[13] = d[0] ^ d[1] ^ d[4] ^ d[5] ^ d[7] ^ d[8] ^ d[10]; - d[14] = d[0] ^ d[2] ^ d[4] ^ d[6] ^ d[7] ^ d[9] ^ d[10]; + // Calculate the checksum this row should have + d[11] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[6]; + d[12] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[7] ^ d[8] ^ d[9]; + d[13] = d[0] ^ d[1] ^ d[4] ^ d[5] ^ d[7] ^ d[8] ^ d[10]; + d[14] = d[0] ^ d[2] ^ d[4] ^ d[6] ^ d[7] ^ d[9] ^ d[10]; } // Hamming (15,11,3) check a boolean data array bool CHamming::decode15113_2(bool* d) { - assert(d != nullptr); - - // Calculate the checksum this row should have - bool c0 = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[5] ^ d[7] ^ d[8]; - bool c1 = d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[6] ^ d[8] ^ d[9]; - bool c2 = d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[7] ^ d[9] ^ d[10]; - bool c3 = d[0] ^ d[1] ^ d[2] ^ d[4] ^ d[6] ^ d[7] ^ d[10]; - - unsigned char n = 0x00U; - n |= (c0 != d[11]) ? 0x01U : 0x00U; - n |= (c1 != d[12]) ? 0x02U : 0x00U; - n |= (c2 != d[13]) ? 0x04U : 0x00U; - n |= (c3 != d[14]) ? 0x08U : 0x00U; - - switch (n) { - // Parity bit errors - case 0x01U: d[11] = !d[11]; return true; - case 0x02U: d[12] = !d[12]; return true; - case 0x04U: d[13] = !d[13]; return true; - case 0x08U: d[14] = !d[14]; return true; - - // Data bit errors - case 0x09U: d[0] = !d[0]; return true; - case 0x0BU: d[1] = !d[1]; return true; - case 0x0FU: d[2] = !d[2]; return true; - case 0x07U: d[3] = !d[3]; return true; - case 0x0EU: d[4] = !d[4]; return true; - case 0x05U: d[5] = !d[5]; return true; - case 0x0AU: d[6] = !d[6]; return true; - case 0x0DU: d[7] = !d[7]; return true; - case 0x03U: d[8] = !d[8]; return true; - case 0x06U: d[9] = !d[9]; return true; - case 0x0CU: d[10] = !d[10]; return true; - - // No bit errors - default: return false; - } + assert(d != nullptr); + + // Calculate the checksum this row should have + bool c0 = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[5] ^ d[7] ^ d[8]; + bool c1 = d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[6] ^ d[8] ^ d[9]; + bool c2 = d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[7] ^ d[9] ^ d[10]; + bool c3 = d[0] ^ d[1] ^ d[2] ^ d[4] ^ d[6] ^ d[7] ^ d[10]; + + unsigned char n = 0x00U; + n |= (c0 != d[11]) ? 0x01U : 0x00U; + n |= (c1 != d[12]) ? 0x02U : 0x00U; + n |= (c2 != d[13]) ? 0x04U : 0x00U; + n |= (c3 != d[14]) ? 0x08U : 0x00U; + + switch (n) + { + // Parity bit errors + case 0x01U: + d[11] = !d[11]; + return true; + case 0x02U: + d[12] = !d[12]; + return true; + case 0x04U: + d[13] = !d[13]; + return true; + case 0x08U: + d[14] = !d[14]; + return true; + + // Data bit errors + case 0x09U: + d[0] = !d[0]; + return true; + case 0x0BU: + d[1] = !d[1]; + return true; + case 0x0FU: + d[2] = !d[2]; + return true; + case 0x07U: + d[3] = !d[3]; + return true; + case 0x0EU: + d[4] = !d[4]; + return true; + case 0x05U: + d[5] = !d[5]; + return true; + case 0x0AU: + d[6] = !d[6]; + return true; + case 0x0DU: + d[7] = !d[7]; + return true; + case 0x03U: + d[8] = !d[8]; + return true; + case 0x06U: + d[9] = !d[9]; + return true; + case 0x0CU: + d[10] = !d[10]; + return true; + + // No bit errors + default: + return false; + } } void CHamming::encode15113_2(bool* d) { - assert(d != nullptr); + assert(d != nullptr); - // Calculate the checksum this row should have - d[11] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[5] ^ d[7] ^ d[8]; - d[12] = d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[6] ^ d[8] ^ d[9]; - d[13] = d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[7] ^ d[9] ^ d[10]; - d[14] = d[0] ^ d[1] ^ d[2] ^ d[4] ^ d[6] ^ d[7] ^ d[10]; + // Calculate the checksum this row should have + d[11] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[5] ^ d[7] ^ d[8]; + d[12] = d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[6] ^ d[8] ^ d[9]; + d[13] = d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[7] ^ d[9] ^ d[10]; + d[14] = d[0] ^ d[1] ^ d[2] ^ d[4] ^ d[6] ^ d[7] ^ d[10]; } // Hamming (13,9,3) check a boolean data array bool CHamming::decode1393(bool* d) { - assert(d != nullptr); - - // Calculate the checksum this column should have - bool c0 = d[0] ^ d[1] ^ d[3] ^ d[5] ^ d[6]; - bool c1 = d[0] ^ d[1] ^ d[2] ^ d[4] ^ d[6] ^ d[7]; - bool c2 = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[5] ^ d[7] ^ d[8]; - bool c3 = d[0] ^ d[2] ^ d[4] ^ d[5] ^ d[8]; - - unsigned char n = 0x00U; - n |= (c0 != d[9]) ? 0x01U : 0x00U; - n |= (c1 != d[10]) ? 0x02U : 0x00U; - n |= (c2 != d[11]) ? 0x04U : 0x00U; - n |= (c3 != d[12]) ? 0x08U : 0x00U; - - switch (n) { - // Parity bit errors - case 0x01U: d[9] = !d[9]; return true; - case 0x02U: d[10] = !d[10]; return true; - case 0x04U: d[11] = !d[11]; return true; - case 0x08U: d[12] = !d[12]; return true; - - // Data bit erros - case 0x0FU: d[0] = !d[0]; return true; - case 0x07U: d[1] = !d[1]; return true; - case 0x0EU: d[2] = !d[2]; return true; - case 0x05U: d[3] = !d[3]; return true; - case 0x0AU: d[4] = !d[4]; return true; - case 0x0DU: d[5] = !d[5]; return true; - case 0x03U: d[6] = !d[6]; return true; - case 0x06U: d[7] = !d[7]; return true; - case 0x0CU: d[8] = !d[8]; return true; - - // No bit errors - default: return false; - } + assert(d != nullptr); + + // Calculate the checksum this column should have + bool c0 = d[0] ^ d[1] ^ d[3] ^ d[5] ^ d[6]; + bool c1 = d[0] ^ d[1] ^ d[2] ^ d[4] ^ d[6] ^ d[7]; + bool c2 = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[5] ^ d[7] ^ d[8]; + bool c3 = d[0] ^ d[2] ^ d[4] ^ d[5] ^ d[8]; + + unsigned char n = 0x00U; + n |= (c0 != d[9]) ? 0x01U : 0x00U; + n |= (c1 != d[10]) ? 0x02U : 0x00U; + n |= (c2 != d[11]) ? 0x04U : 0x00U; + n |= (c3 != d[12]) ? 0x08U : 0x00U; + + switch (n) + { + // Parity bit errors + case 0x01U: + d[9] = !d[9]; + return true; + case 0x02U: + d[10] = !d[10]; + return true; + case 0x04U: + d[11] = !d[11]; + return true; + case 0x08U: + d[12] = !d[12]; + return true; + + // Data bit erros + case 0x0FU: + d[0] = !d[0]; + return true; + case 0x07U: + d[1] = !d[1]; + return true; + case 0x0EU: + d[2] = !d[2]; + return true; + case 0x05U: + d[3] = !d[3]; + return true; + case 0x0AU: + d[4] = !d[4]; + return true; + case 0x0DU: + d[5] = !d[5]; + return true; + case 0x03U: + d[6] = !d[6]; + return true; + case 0x06U: + d[7] = !d[7]; + return true; + case 0x0CU: + d[8] = !d[8]; + return true; + + // No bit errors + default: + return false; + } } void CHamming::encode1393(bool* d) { - assert(d != nullptr); + assert(d != nullptr); - // Calculate the checksum this column should have - d[9] = d[0] ^ d[1] ^ d[3] ^ d[5] ^ d[6]; - d[10] = d[0] ^ d[1] ^ d[2] ^ d[4] ^ d[6] ^ d[7]; - d[11] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[5] ^ d[7] ^ d[8]; - d[12] = d[0] ^ d[2] ^ d[4] ^ d[5] ^ d[8]; + // Calculate the checksum this column should have + d[9] = d[0] ^ d[1] ^ d[3] ^ d[5] ^ d[6]; + d[10] = d[0] ^ d[1] ^ d[2] ^ d[4] ^ d[6] ^ d[7]; + d[11] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[5] ^ d[7] ^ d[8]; + d[12] = d[0] ^ d[2] ^ d[4] ^ d[5] ^ d[8]; } // Hamming (10,6,3) check a boolean data array bool CHamming::decode1063(bool* d) { - assert(d != nullptr); - - // Calculate the checksum this column should have - bool c0 = d[0] ^ d[1] ^ d[2] ^ d[5]; - bool c1 = d[0] ^ d[1] ^ d[3] ^ d[5]; - bool c2 = d[0] ^ d[2] ^ d[3] ^ d[4]; - bool c3 = d[1] ^ d[2] ^ d[3] ^ d[4]; - - unsigned char n = 0x00U; - n |= (c0 != d[6]) ? 0x01U : 0x00U; - n |= (c1 != d[7]) ? 0x02U : 0x00U; - n |= (c2 != d[8]) ? 0x04U : 0x00U; - n |= (c3 != d[9]) ? 0x08U : 0x00U; - - switch (n) { - // Parity bit errors - case 0x01U: d[6] = !d[6]; return true; - case 0x02U: d[7] = !d[7]; return true; - case 0x04U: d[8] = !d[8]; return true; - case 0x08U: d[9] = !d[9]; return true; - - // Data bit erros - case 0x07U: d[0] = !d[0]; return true; - case 0x0BU: d[1] = !d[1]; return true; - case 0x0DU: d[2] = !d[2]; return true; - case 0x0EU: d[3] = !d[3]; return true; - case 0x0CU: d[4] = !d[4]; return true; - case 0x03U: d[5] = !d[5]; return true; - - // No bit errors - default: return false; - } + assert(d != nullptr); + + // Calculate the checksum this column should have + bool c0 = d[0] ^ d[1] ^ d[2] ^ d[5]; + bool c1 = d[0] ^ d[1] ^ d[3] ^ d[5]; + bool c2 = d[0] ^ d[2] ^ d[3] ^ d[4]; + bool c3 = d[1] ^ d[2] ^ d[3] ^ d[4]; + + unsigned char n = 0x00U; + n |= (c0 != d[6]) ? 0x01U : 0x00U; + n |= (c1 != d[7]) ? 0x02U : 0x00U; + n |= (c2 != d[8]) ? 0x04U : 0x00U; + n |= (c3 != d[9]) ? 0x08U : 0x00U; + + switch (n) + { + // Parity bit errors + case 0x01U: + d[6] = !d[6]; + return true; + case 0x02U: + d[7] = !d[7]; + return true; + case 0x04U: + d[8] = !d[8]; + return true; + case 0x08U: + d[9] = !d[9]; + return true; + + // Data bit erros + case 0x07U: + d[0] = !d[0]; + return true; + case 0x0BU: + d[1] = !d[1]; + return true; + case 0x0DU: + d[2] = !d[2]; + return true; + case 0x0EU: + d[3] = !d[3]; + return true; + case 0x0CU: + d[4] = !d[4]; + return true; + case 0x03U: + d[5] = !d[5]; + return true; + + // No bit errors + default: + return false; + } } void CHamming::encode1063(bool* d) { - assert(d != nullptr); + assert(d != nullptr); - // Calculate the checksum this column should have - d[6] = d[0] ^ d[1] ^ d[2] ^ d[5]; - d[7] = d[0] ^ d[1] ^ d[3] ^ d[5]; - d[8] = d[0] ^ d[2] ^ d[3] ^ d[4]; - d[9] = d[1] ^ d[2] ^ d[3] ^ d[4]; + // Calculate the checksum this column should have + d[6] = d[0] ^ d[1] ^ d[2] ^ d[5]; + d[7] = d[0] ^ d[1] ^ d[3] ^ d[5]; + d[8] = d[0] ^ d[2] ^ d[3] ^ d[4]; + d[9] = d[1] ^ d[2] ^ d[3] ^ d[4]; } // A Hamming (16,11,4) Check bool CHamming::decode16114(bool* d) { - assert(d != nullptr); - - // Calculate the checksum this column should have - bool c0 = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[5] ^ d[7] ^ d[8]; - bool c1 = d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[6] ^ d[8] ^ d[9]; - bool c2 = d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[7] ^ d[9] ^ d[10]; - bool c3 = d[0] ^ d[1] ^ d[2] ^ d[4] ^ d[6] ^ d[7] ^ d[10]; - bool c4 = d[0] ^ d[2] ^ d[5] ^ d[6] ^ d[8] ^ d[9] ^ d[10]; - - // Compare these with the actual bits - unsigned char n = 0x00U; - n |= (c0 != d[11]) ? 0x01U : 0x00U; - n |= (c1 != d[12]) ? 0x02U : 0x00U; - n |= (c2 != d[13]) ? 0x04U : 0x00U; - n |= (c3 != d[14]) ? 0x08U : 0x00U; - n |= (c4 != d[15]) ? 0x10U : 0x00U; - - switch (n) { - // Parity bit errors - case 0x01U: d[11] = !d[11]; return true; - case 0x02U: d[12] = !d[12]; return true; - case 0x04U: d[13] = !d[13]; return true; - case 0x08U: d[14] = !d[14]; return true; - case 0x10U: d[15] = !d[15]; return true; - - // Data bit errors - case 0x19U: d[0] = !d[0]; return true; - case 0x0BU: d[1] = !d[1]; return true; - case 0x1FU: d[2] = !d[2]; return true; - case 0x07U: d[3] = !d[3]; return true; - case 0x0EU: d[4] = !d[4]; return true; - case 0x15U: d[5] = !d[5]; return true; - case 0x1AU: d[6] = !d[6]; return true; - case 0x0DU: d[7] = !d[7]; return true; - case 0x13U: d[8] = !d[8]; return true; - case 0x16U: d[9] = !d[9]; return true; - case 0x1CU: d[10] = !d[10]; return true; - - // No bit errors - case 0x00U: return true; - - // Unrecoverable errors - default: return false; - } + assert(d != nullptr); + + // Calculate the checksum this column should have + bool c0 = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[5] ^ d[7] ^ d[8]; + bool c1 = d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[6] ^ d[8] ^ d[9]; + bool c2 = d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[7] ^ d[9] ^ d[10]; + bool c3 = d[0] ^ d[1] ^ d[2] ^ d[4] ^ d[6] ^ d[7] ^ d[10]; + bool c4 = d[0] ^ d[2] ^ d[5] ^ d[6] ^ d[8] ^ d[9] ^ d[10]; + + // Compare these with the actual bits + unsigned char n = 0x00U; + n |= (c0 != d[11]) ? 0x01U : 0x00U; + n |= (c1 != d[12]) ? 0x02U : 0x00U; + n |= (c2 != d[13]) ? 0x04U : 0x00U; + n |= (c3 != d[14]) ? 0x08U : 0x00U; + n |= (c4 != d[15]) ? 0x10U : 0x00U; + + switch (n) + { + // Parity bit errors + case 0x01U: + d[11] = !d[11]; + return true; + case 0x02U: + d[12] = !d[12]; + return true; + case 0x04U: + d[13] = !d[13]; + return true; + case 0x08U: + d[14] = !d[14]; + return true; + case 0x10U: + d[15] = !d[15]; + return true; + + // Data bit errors + case 0x19U: + d[0] = !d[0]; + return true; + case 0x0BU: + d[1] = !d[1]; + return true; + case 0x1FU: + d[2] = !d[2]; + return true; + case 0x07U: + d[3] = !d[3]; + return true; + case 0x0EU: + d[4] = !d[4]; + return true; + case 0x15U: + d[5] = !d[5]; + return true; + case 0x1AU: + d[6] = !d[6]; + return true; + case 0x0DU: + d[7] = !d[7]; + return true; + case 0x13U: + d[8] = !d[8]; + return true; + case 0x16U: + d[9] = !d[9]; + return true; + case 0x1CU: + d[10] = !d[10]; + return true; + + // No bit errors + case 0x00U: + return true; + + // Unrecoverable errors + default: + return false; + } } void CHamming::encode16114(bool* d) { - assert(d != nullptr); + assert(d != nullptr); - d[11] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[5] ^ d[7] ^ d[8]; - d[12] = d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[6] ^ d[8] ^ d[9]; - d[13] = d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[7] ^ d[9] ^ d[10]; - d[14] = d[0] ^ d[1] ^ d[2] ^ d[4] ^ d[6] ^ d[7] ^ d[10]; - d[15] = d[0] ^ d[2] ^ d[5] ^ d[6] ^ d[8] ^ d[9] ^ d[10]; + d[11] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[5] ^ d[7] ^ d[8]; + d[12] = d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[6] ^ d[8] ^ d[9]; + d[13] = d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[7] ^ d[9] ^ d[10]; + d[14] = d[0] ^ d[1] ^ d[2] ^ d[4] ^ d[6] ^ d[7] ^ d[10]; + d[15] = d[0] ^ d[2] ^ d[5] ^ d[6] ^ d[8] ^ d[9] ^ d[10]; } // A Hamming (17,12,3) Check bool CHamming::decode17123(bool* d) { - assert(d != nullptr); - - // Calculate the checksum this column should have - bool c0 = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[6] ^ d[7] ^ d[9]; - bool c1 = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[7] ^ d[8] ^ d[10]; - bool c2 = d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[8] ^ d[9] ^ d[11]; - bool c3 = d[0] ^ d[1] ^ d[4] ^ d[5] ^ d[7] ^ d[10]; - bool c4 = d[0] ^ d[1] ^ d[2] ^ d[5] ^ d[6] ^ d[8] ^ d[11]; - - // Compare these with the actual bits - unsigned char n = 0x00U; - n |= (c0 != d[12]) ? 0x01U : 0x00U; - n |= (c1 != d[13]) ? 0x02U : 0x00U; - n |= (c2 != d[14]) ? 0x04U : 0x00U; - n |= (c3 != d[15]) ? 0x08U : 0x00U; - n |= (c4 != d[16]) ? 0x10U : 0x00U; - - switch (n) { - // Parity bit errors - case 0x01U: d[12] = !d[12]; return true; - case 0x02U: d[13] = !d[13]; return true; - case 0x04U: d[14] = !d[14]; return true; - case 0x08U: d[15] = !d[15]; return true; - case 0x10U: d[16] = !d[16]; return true; - - // Data bit errors - case 0x1BU: d[0] = !d[0]; return true; - case 0x1FU: d[1] = !d[1]; return true; - case 0x17U: d[2] = !d[2]; return true; - case 0x07U: d[3] = !d[3]; return true; - case 0x0EU: d[4] = !d[4]; return true; - case 0x1CU: d[5] = !d[5]; return true; - case 0x11U: d[6] = !d[6]; return true; - case 0x0BU: d[7] = !d[7]; return true; - case 0x16U: d[8] = !d[8]; return true; - case 0x05U: d[9] = !d[9]; return true; - case 0x0AU: d[10] = !d[10]; return true; - case 0x14U: d[11] = !d[11]; return true; - - // No bit errors - case 0x00U: return true; - - // Unrecoverable errors - default: return false; - } + assert(d != nullptr); + + // Calculate the checksum this column should have + bool c0 = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[6] ^ d[7] ^ d[9]; + bool c1 = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[7] ^ d[8] ^ d[10]; + bool c2 = d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[8] ^ d[9] ^ d[11]; + bool c3 = d[0] ^ d[1] ^ d[4] ^ d[5] ^ d[7] ^ d[10]; + bool c4 = d[0] ^ d[1] ^ d[2] ^ d[5] ^ d[6] ^ d[8] ^ d[11]; + + // Compare these with the actual bits + unsigned char n = 0x00U; + n |= (c0 != d[12]) ? 0x01U : 0x00U; + n |= (c1 != d[13]) ? 0x02U : 0x00U; + n |= (c2 != d[14]) ? 0x04U : 0x00U; + n |= (c3 != d[15]) ? 0x08U : 0x00U; + n |= (c4 != d[16]) ? 0x10U : 0x00U; + + switch (n) + { + // Parity bit errors + case 0x01U: + d[12] = !d[12]; + return true; + case 0x02U: + d[13] = !d[13]; + return true; + case 0x04U: + d[14] = !d[14]; + return true; + case 0x08U: + d[15] = !d[15]; + return true; + case 0x10U: + d[16] = !d[16]; + return true; + + // Data bit errors + case 0x1BU: + d[0] = !d[0]; + return true; + case 0x1FU: + d[1] = !d[1]; + return true; + case 0x17U: + d[2] = !d[2]; + return true; + case 0x07U: + d[3] = !d[3]; + return true; + case 0x0EU: + d[4] = !d[4]; + return true; + case 0x1CU: + d[5] = !d[5]; + return true; + case 0x11U: + d[6] = !d[6]; + return true; + case 0x0BU: + d[7] = !d[7]; + return true; + case 0x16U: + d[8] = !d[8]; + return true; + case 0x05U: + d[9] = !d[9]; + return true; + case 0x0AU: + d[10] = !d[10]; + return true; + case 0x14U: + d[11] = !d[11]; + return true; + + // No bit errors + case 0x00U: + return true; + + // Unrecoverable errors + default: + return false; + } } void CHamming::encode17123(bool* d) { - assert(d != nullptr); + assert(d != nullptr); - d[12] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[6] ^ d[7] ^ d[9]; - d[13] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[7] ^ d[8] ^ d[10]; - d[14] = d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[8] ^ d[9] ^ d[11]; - d[15] = d[0] ^ d[1] ^ d[4] ^ d[5] ^ d[7] ^ d[10]; - d[16] = d[0] ^ d[1] ^ d[2] ^ d[5] ^ d[6] ^ d[8] ^ d[11]; + d[12] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[6] ^ d[7] ^ d[9]; + d[13] = d[0] ^ d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[7] ^ d[8] ^ d[10]; + d[14] = d[1] ^ d[2] ^ d[3] ^ d[4] ^ d[5] ^ d[8] ^ d[9] ^ d[11]; + d[15] = d[0] ^ d[1] ^ d[4] ^ d[5] ^ d[7] ^ d[10]; + d[16] = d[0] ^ d[1] ^ d[2] ^ d[5] ^ d[6] ^ d[8] ^ d[11]; } diff --git a/src/chamming.h b/src/chamming.h index bf6b626..069b256 100644 --- a/src/chamming.h +++ b/src/chamming.h @@ -19,25 +19,26 @@ #ifndef Hamming_H #define Hamming_H -class CHamming { +class CHamming +{ public: - static void encode15113_1(bool* d); - static bool decode15113_1(bool* d); - - static void encode15113_2(bool* d); - static bool decode15113_2(bool* d); - - static void encode1393(bool* d); - static bool decode1393(bool* d); - - static void encode1063(bool* d); - static bool decode1063(bool* d); - - static void encode16114(bool* d); - static bool decode16114(bool* d); - - static void encode17123(bool* d); - static bool decode17123(bool* d); + static void encode15113_1(bool* d); + static bool decode15113_1(bool* d); + + static void encode15113_2(bool* d); + static bool decode15113_2(bool* d); + + static void encode1393(bool* d); + static bool decode1393(bool* d); + + static void encode1063(bool* d); + static bool decode1063(bool* d); + + static void encode16114(bool* d); + static bool decode16114(bool* d); + + static void encode17123(bool* d); + static bool decode17123(bool* d); }; #endif diff --git a/src/cip.cpp b/src/cip.cpp index ba8307c..6feafca 100644 --- a/src/cip.cpp +++ b/src/cip.cpp @@ -39,7 +39,8 @@ CIp::CIp(const char *address, int family, int type, uint16_t port) : is_set(true bzero(&hints, sizeof(struct addrinfo)); hints.ai_family = family; hints.ai_socktype = type; - if (0 == getaddrinfo(address, (port ? std::to_string(port).c_str() : nullptr), &hints, &result)) { + if (0 == getaddrinfo(address, (port ? std::to_string(port).c_str() : nullptr), &hints, &result)) + { memcpy(&addr, result->ai_addr, result->ai_addrlen); addr.ss_family = result->ai_family; freeaddrinfo(result); @@ -248,7 +249,8 @@ uint16_t CIp::GetPort() const { auto addr6 = (struct sockaddr_in6 *)&addr; return ntohs(addr6->sin6_port); - } else + } + else return 0; } diff --git a/src/cip.h b/src/cip.h index 3277783..5f7976b 100644 --- a/src/cip.h +++ b/src/cip.h @@ -52,7 +52,7 @@ public: const char *GetAddress() const; operator const char *() const { return GetAddress(); } friend std::ostream &operator<<(std::ostream &stream, const CIp &Ip); - int GetFamily() const; + int GetFamily() const; uint16_t GetPort() const; size_t GetSize() const; uint32_t GetAddr() const; diff --git a/src/cnotification.cpp b/src/cnotification.cpp index a1b7d0d..02009bd 100644 --- a/src/cnotification.cpp +++ b/src/cnotification.cpp @@ -30,17 +30,17 @@ CNotification::CNotification() { - // init variables - m_iId = NOTIFICATION_NONE; + // init variables + m_iId = NOTIFICATION_NONE; } CNotification::CNotification(int iId) { - m_iId = iId; + m_iId = iId; } CNotification::CNotification(int iId, const CCallsign &Callsign) { - m_iId = iId; - m_Callsign = Callsign; + m_iId = iId; + m_Callsign = Callsign; } diff --git a/src/cnotification.h b/src/cnotification.h index fae7b00..d066ea8 100644 --- a/src/cnotification.h +++ b/src/cnotification.h @@ -44,19 +44,19 @@ class CNotification { public: - // constructor - CNotification(); - CNotification(int); - CNotification(int, const CCallsign &); + // constructor + CNotification(); + CNotification(int); + CNotification(int, const CCallsign &); - // get - int GetId(void) const { return m_iId; } - const CCallsign &GetCallsign(void) const { return m_Callsign; } + // get + int GetId(void) const { return m_iId; } + const CCallsign &GetCallsign(void) const { return m_Callsign; } protected: - // data - int m_iId; - CCallsign m_Callsign; + // data + int m_iId; + CCallsign m_Callsign; }; diff --git a/src/cnotificationqueue.h b/src/cnotificationqueue.h index 533a47a..553ef6f 100644 --- a/src/cnotificationqueue.h +++ b/src/cnotificationqueue.h @@ -42,25 +42,25 @@ class CNotificationQueue { public: - // constructor - CNotificationQueue() {} + // constructor + CNotificationQueue() {} - // destructor - ~CNotificationQueue() {} + // destructor + ~CNotificationQueue() {} - // lock - void Lock() { m_Mutex.lock(); } - void Unlock() { m_Mutex.unlock(); } + // lock + void Lock() { m_Mutex.lock(); } + void Unlock() { m_Mutex.unlock(); } - // pass thru + // pass thru CNotification front() { return queue.front(); } void pop() { queue.pop(); } void push(CNotification note) { queue.push(note); } bool empty() const { return queue.empty(); } protected: - // data - std::mutex m_Mutex; + // data + std::mutex m_Mutex; std::queue queue; }; diff --git a/src/cpacket.cpp b/src/cpacket.cpp index 94bf645..d82e2a8 100644 --- a/src/cpacket.cpp +++ b/src/cpacket.cpp @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- #include "main.h" @@ -32,75 +32,75 @@ CPacket::CPacket() { - m_uiStreamId = 0; - m_uiDstarPacketId = 0; - m_uiDmrPacketId = 0; - m_uiDmrPacketSubid = 0; - m_uiYsfPacketId = 0; - m_uiYsfPacketSubId = 0; - m_uiYsfPacketFrameId = 0; - m_uiModuleId = ' '; - m_uiOriginId = ORIGIN_LOCAL; + m_uiStreamId = 0; + m_uiDstarPacketId = 0; + m_uiDmrPacketId = 0; + m_uiDmrPacketSubid = 0; + m_uiYsfPacketId = 0; + m_uiYsfPacketSubId = 0; + m_uiYsfPacketFrameId = 0; + m_uiModuleId = ' '; + m_uiOriginId = ORIGIN_LOCAL; }; // dstar contrsuctor CPacket::CPacket(uint16 sid, uint8 dstarpid) { - m_uiStreamId = sid; - m_uiDstarPacketId = dstarpid; - m_uiDmrPacketId = 0xFF; - m_uiDmrPacketSubid = 0xFF; - m_uiYsfPacketId = 0xFF; - m_uiYsfPacketSubId = 0xFF; - m_uiYsfPacketFrameId = 0xFF; - m_uiModuleId = ' '; - m_uiOriginId = ORIGIN_LOCAL; + m_uiStreamId = sid; + m_uiDstarPacketId = dstarpid; + m_uiDmrPacketId = 0xFF; + m_uiDmrPacketSubid = 0xFF; + m_uiYsfPacketId = 0xFF; + m_uiYsfPacketSubId = 0xFF; + m_uiYsfPacketFrameId = 0xFF; + m_uiModuleId = ' '; + m_uiOriginId = ORIGIN_LOCAL; }; // dmr constructor CPacket::CPacket(uint16 sid, uint8 dmrpid, uint8 dmrspid) { - m_uiStreamId = sid; - m_uiDmrPacketId = dmrpid; - m_uiDmrPacketSubid = dmrspid; - m_uiDstarPacketId = 0xFF; - m_uiYsfPacketId = 0xFF; - m_uiYsfPacketSubId = 0xFF; - m_uiYsfPacketFrameId = 0xFF; - m_uiModuleId = ' '; - m_uiOriginId = ORIGIN_LOCAL; + m_uiStreamId = sid; + m_uiDmrPacketId = dmrpid; + m_uiDmrPacketSubid = dmrspid; + m_uiDstarPacketId = 0xFF; + m_uiYsfPacketId = 0xFF; + m_uiYsfPacketSubId = 0xFF; + m_uiYsfPacketFrameId = 0xFF; + m_uiModuleId = ' '; + m_uiOriginId = ORIGIN_LOCAL; }; // ysf constructor CPacket::CPacket(uint16 sid, uint8 ysfpid, uint8 ysfsubpid, uint8 ysffrid) { - m_uiStreamId = sid; - m_uiYsfPacketId = ysfpid; - m_uiYsfPacketSubId = ysfsubpid; - m_uiYsfPacketFrameId = ysffrid; - m_uiDstarPacketId = 0xFF; - m_uiDmrPacketId = 0xFF; - m_uiDmrPacketSubid = 0xFF; - m_uiModuleId = ' '; - m_uiOriginId = ORIGIN_LOCAL; + m_uiStreamId = sid; + m_uiYsfPacketId = ysfpid; + m_uiYsfPacketSubId = ysfsubpid; + m_uiYsfPacketFrameId = ysffrid; + m_uiDstarPacketId = 0xFF; + m_uiDmrPacketId = 0xFF; + m_uiDmrPacketSubid = 0xFF; + m_uiModuleId = ' '; + m_uiOriginId = ORIGIN_LOCAL; } // xlx constructor CPacket::CPacket(uint16 sid, uint8 dstarpid, uint8 dmrpid, uint8 dmrsubpid, uint8 ysfpid, uint8 ysfsubpid, uint8 ysffrid) { - m_uiStreamId = sid; - m_uiDstarPacketId = dstarpid; - m_uiDmrPacketId = dmrpid; - m_uiDmrPacketSubid = dmrsubpid; - m_uiYsfPacketId = ysfpid; - m_uiYsfPacketSubId = ysfsubpid; - m_uiYsfPacketFrameId = ysffrid; - m_uiModuleId = ' '; - m_uiOriginId = ORIGIN_LOCAL; + m_uiStreamId = sid; + m_uiDstarPacketId = dstarpid; + m_uiDmrPacketId = dmrpid; + m_uiDmrPacketSubid = dmrsubpid; + m_uiYsfPacketId = ysfpid; + m_uiYsfPacketSubId = ysfsubpid; + m_uiYsfPacketFrameId = ysffrid; + m_uiModuleId = ' '; + m_uiOriginId = ORIGIN_LOCAL; } //////////////////////////////////////////////////////////////////////////////////////// @@ -108,7 +108,7 @@ CPacket::CPacket(uint16 sid, uint8 dstarpid, uint8 dmrpid, uint8 dmrsubpid, uint CPacket *CPacket::Duplicate(void) const { - return new CPacket(*this); + return new CPacket(*this); } @@ -117,27 +117,27 @@ CPacket *CPacket::Duplicate(void) const void CPacket::UpdatePids(uint32 pid) { - // called while phusing this packet in a stream queue - // so now packet sequence number is known and undefined pids can be updated - // this is needed as dtsar & dmt pids are different and cannot be - // derived from each other - - // dstar pid needs update ? - if ( m_uiDstarPacketId == 0xFF ) - { - m_uiDstarPacketId = (pid % 21); - } - // dmr pids need update ? - if ( m_uiDmrPacketId == 0xFF ) - { - m_uiDmrPacketId = ((pid / 3) % 6); - m_uiDmrPacketSubid = ((pid % 3) + 1); - } - // ysf pids need update ? - if ( m_uiYsfPacketId == 0xFF ) - { - m_uiYsfPacketId = ((pid / 5) % 8); - m_uiYsfPacketSubId = pid % 5; - m_uiYsfPacketFrameId = ((pid / 5) & 0x7FU) << 1; - } + // called while phusing this packet in a stream queue + // so now packet sequence number is known and undefined pids can be updated + // this is needed as dtsar & dmt pids are different and cannot be + // derived from each other + + // dstar pid needs update ? + if ( m_uiDstarPacketId == 0xFF ) + { + m_uiDstarPacketId = (pid % 21); + } + // dmr pids need update ? + if ( m_uiDmrPacketId == 0xFF ) + { + m_uiDmrPacketId = ((pid / 3) % 6); + m_uiDmrPacketSubid = ((pid % 3) + 1); + } + // ysf pids need update ? + if ( m_uiYsfPacketId == 0xFF ) + { + m_uiYsfPacketId = ((pid / 5) % 8); + m_uiYsfPacketSubId = pid % 5; + m_uiYsfPacketFrameId = ((pid / 5) & 0x7FU) << 1; + } } diff --git a/src/cpacket.h b/src/cpacket.h index eddcd39..f74fe0a 100644 --- a/src/cpacket.h +++ b/src/cpacket.h @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- #ifndef cpacket_h @@ -38,55 +38,55 @@ class CPacket { public: - // constructor - CPacket(); - CPacket(uint16 sid, uint8 dstarpid); - CPacket(uint16 sid, uint8 dmrpid, uint8 dmrsubpid); - CPacket(uint16 sid, uint8 ysfpid, uint8 ysfsubpid, uint8 ysfsubpidmax); - CPacket(uint16 sid, uint8 dstarpid, uint8 dmrpid, uint8 dmrsubpid, uint8 ysfpid, uint8 ysfsubpid, uint8 ysfsubpidmax); - - // destructor - virtual ~CPacket() {}; - - // virtual duplication - virtual CPacket *Duplicate(void) const; - - // identity - virtual bool IsDvHeader(void) const { return false; } - virtual bool IsDvFrame(void) const { return false; } - virtual bool IsLastPacket(void) const { return false; } - virtual bool HaveTranscodableAmbe(void) const { return false; } - - // get - virtual bool IsValid(void) const { return true; } - uint16 GetStreamId(void) const { return m_uiStreamId; } - uint8 GetPacketId(void) const { return m_uiDstarPacketId; } - uint8 GetDstarPacketId(void) const { return m_uiDstarPacketId; } - uint8 GetDmrPacketId(void) const { return m_uiDmrPacketId; } - uint8 GetDmrPacketSubid(void) const { return m_uiDmrPacketSubid; } - uint8 GetYsfPacketId(void) const { return m_uiYsfPacketId; } - uint8 GetYsfPacketSubId(void) const { return m_uiYsfPacketSubId; } - uint8 GetYsfPacketFrameId(void) const { return m_uiYsfPacketFrameId; } - uint8 GetModuleId(void) const { return m_uiModuleId; } - bool IsLocalOrigin(void) const { return (m_uiOriginId == ORIGIN_LOCAL); } - - // set - void UpdatePids(uint32); - void SetModuleId(uint8 uiId) { m_uiModuleId = uiId; } - void SetLocalOrigin(void) { m_uiOriginId = ORIGIN_LOCAL; } - void SetRemotePeerOrigin(void) { m_uiOriginId = ORIGIN_PEER; } - + // constructor + CPacket(); + CPacket(uint16 sid, uint8 dstarpid); + CPacket(uint16 sid, uint8 dmrpid, uint8 dmrsubpid); + CPacket(uint16 sid, uint8 ysfpid, uint8 ysfsubpid, uint8 ysfsubpidmax); + CPacket(uint16 sid, uint8 dstarpid, uint8 dmrpid, uint8 dmrsubpid, uint8 ysfpid, uint8 ysfsubpid, uint8 ysfsubpidmax); + + // destructor + virtual ~CPacket() {}; + + // virtual duplication + virtual CPacket *Duplicate(void) const; + + // identity + virtual bool IsDvHeader(void) const { return false; } + virtual bool IsDvFrame(void) const { return false; } + virtual bool IsLastPacket(void) const { return false; } + virtual bool HaveTranscodableAmbe(void) const { return false; } + + // get + virtual bool IsValid(void) const { return true; } + uint16 GetStreamId(void) const { return m_uiStreamId; } + uint8 GetPacketId(void) const { return m_uiDstarPacketId; } + uint8 GetDstarPacketId(void) const { return m_uiDstarPacketId; } + uint8 GetDmrPacketId(void) const { return m_uiDmrPacketId; } + uint8 GetDmrPacketSubid(void) const { return m_uiDmrPacketSubid; } + uint8 GetYsfPacketId(void) const { return m_uiYsfPacketId; } + uint8 GetYsfPacketSubId(void) const { return m_uiYsfPacketSubId; } + uint8 GetYsfPacketFrameId(void) const { return m_uiYsfPacketFrameId; } + uint8 GetModuleId(void) const { return m_uiModuleId; } + bool IsLocalOrigin(void) const { return (m_uiOriginId == ORIGIN_LOCAL); } + + // set + void UpdatePids(uint32); + void SetModuleId(uint8 uiId) { m_uiModuleId = uiId; } + void SetLocalOrigin(void) { m_uiOriginId = ORIGIN_LOCAL; } + void SetRemotePeerOrigin(void) { m_uiOriginId = ORIGIN_PEER; } + protected: - // data - uint16 m_uiStreamId; - uint8 m_uiDstarPacketId; - uint8 m_uiDmrPacketId; - uint8 m_uiDmrPacketSubid; - uint8 m_uiYsfPacketId; - uint8 m_uiYsfPacketSubId; - uint8 m_uiYsfPacketFrameId; - uint8 m_uiModuleId; - uint8 m_uiOriginId; + // data + uint16 m_uiStreamId; + uint8 m_uiDstarPacketId; + uint8 m_uiDmrPacketId; + uint8 m_uiDmrPacketSubid; + uint8 m_uiYsfPacketId; + uint8 m_uiYsfPacketSubId; + uint8 m_uiYsfPacketFrameId; + uint8 m_uiModuleId; + uint8 m_uiOriginId; }; diff --git a/src/cpacketqueue.h b/src/cpacketqueue.h index 5e2bbb5..9de49bb 100644 --- a/src/cpacketqueue.h +++ b/src/cpacketqueue.h @@ -39,11 +39,11 @@ class CClient; class CPacketQueue { public: - // constructor - CPacketQueue() {} + // constructor + CPacketQueue() {} - // destructor - ~CPacketQueue() + // destructor + ~CPacketQueue() { Lock(); while (! queue.empty()) @@ -54,9 +54,9 @@ public: Unlock(); } - // lock - void Lock() { m_Mutex.lock(); } - void Unlock() { m_Mutex.unlock(); } + // lock + void Lock() { m_Mutex.lock(); } + void Unlock() { m_Mutex.unlock(); } // pass thru CPacket *front() { return queue.front(); } @@ -65,13 +65,13 @@ public: bool empty() const { return queue.empty(); } protected: - // status - bool m_bOpen; - uint16 m_uiStreamId; - std::mutex m_Mutex; + // status + bool m_bOpen; + uint16 m_uiStreamId; + std::mutex m_Mutex; - // owner - CClient *m_Client; + // owner + CClient *m_Client; std::queue queue; }; diff --git a/src/cpacketstream.cpp b/src/cpacketstream.cpp index 9475471..d65d35f 100644 --- a/src/cpacketstream.cpp +++ b/src/cpacketstream.cpp @@ -30,12 +30,12 @@ CPacketStream::CPacketStream() { - m_bOpen = false; - m_uiStreamId = 0; - m_uiPacketCntr = 0; - m_OwnerClient = nullptr; + m_bOpen = false; + m_uiStreamId = 0; + m_uiPacketCntr = 0; + m_OwnerClient = nullptr; #ifdef TRANSCODER_IP - m_CodecStream = nullptr; + m_CodecStream = nullptr; #endif } @@ -44,38 +44,38 @@ CPacketStream::CPacketStream() bool CPacketStream::Open(const CDvHeaderPacket &DvHeader, std::shared_ptrclient) { - bool ok = false; + bool ok = false; - // not already open? - if ( !m_bOpen ) - { - // update status - m_bOpen = true; - m_uiStreamId = DvHeader.GetStreamId(); - m_uiPacketCntr = 0; - m_DvHeader = DvHeader; - m_OwnerClient = client; - m_LastPacketTime.Now(); + // not already open? + if ( !m_bOpen ) + { + // update status + m_bOpen = true; + m_uiStreamId = DvHeader.GetStreamId(); + m_uiPacketCntr = 0; + m_DvHeader = DvHeader; + m_OwnerClient = client; + m_LastPacketTime.Now(); #ifdef TRANSCODER_IP if (std::string::npos != std::string(TRANSCODED_MODULES).find(DvHeader.GetRpt2Module())) m_CodecStream = g_Transcoder.GetStream(this, client->GetCodec()); else m_CodecStream = g_Transcoder.GetStream(this, CODEC_NONE); #endif - ok = true; - } - return ok; + ok = true; + } + return ok; } void CPacketStream::Close(void) { - // update status - m_bOpen = false; - m_uiStreamId = 0; - m_OwnerClient = nullptr; + // update status + m_bOpen = false; + m_uiStreamId = 0; + m_OwnerClient = nullptr; #ifdef TRANSCODER_IP - g_Transcoder.ReleaseStream(m_CodecStream); - m_CodecStream = nullptr; + g_Transcoder.ReleaseStream(m_CodecStream); + m_CodecStream = nullptr; #endif } @@ -84,52 +84,52 @@ void CPacketStream::Close(void) void CPacketStream::Push(CPacket *Packet) { - // update stream dependent packet data - m_LastPacketTime.Now(); - Packet->UpdatePids(m_uiPacketCntr++); - // transcoder avaliable ? + // update stream dependent packet data + m_LastPacketTime.Now(); + Packet->UpdatePids(m_uiPacketCntr++); + // transcoder avaliable ? #ifdef TRANSCODER_IP - if ( m_CodecStream != nullptr ) - { - // todo: verify no possibilty of double lock here - m_CodecStream->Lock(); - { - // transcoder ready & frame need transcoding ? - if ( m_CodecStream->IsConnected() && Packet->HaveTranscodableAmbe() ) - { - // yes, push packet to trancoder queue - // trancoder will push it after transcoding - // is completed - m_CodecStream->push(Packet); - } - else - { - // no, just bypass tarnscoder - push(Packet); - } - } - m_CodecStream->Unlock(); - } - else + if ( m_CodecStream != nullptr ) + { + // todo: verify no possibilty of double lock here + m_CodecStream->Lock(); + { + // transcoder ready & frame need transcoding ? + if ( m_CodecStream->IsConnected() && Packet->HaveTranscodableAmbe() ) + { + // yes, push packet to trancoder queue + // trancoder will push it after transcoding + // is completed + m_CodecStream->push(Packet); + } + else + { + // no, just bypass tarnscoder + push(Packet); + } + } + m_CodecStream->Unlock(); + } + else #endif - { - // otherwise, push direct push - push(Packet); - } + { + // otherwise, push direct push + push(Packet); + } } bool CPacketStream::IsEmpty(void) const { #ifdef TRANSCODER_IP - bool bEmpty = empty(); - // also check no packets still in Codec stream's queue - if ( bEmpty && (m_CodecStream != nullptr) ) - { - bEmpty = m_CodecStream->IsEmpty(); - } + bool bEmpty = empty(); + // also check no packets still in Codec stream's queue + if ( bEmpty && (m_CodecStream != nullptr) ) + { + bEmpty = m_CodecStream->IsEmpty(); + } - // done - return bEmpty; + // done + return bEmpty; #else return empty(); #endif @@ -140,9 +140,9 @@ bool CPacketStream::IsEmpty(void) const const CIp *CPacketStream::GetOwnerIp(void) { - if ( m_OwnerClient != nullptr ) - { - return &(m_OwnerClient->GetIp()); - } - return nullptr; + if ( m_OwnerClient != nullptr ) + { + return &(m_OwnerClient->GetIp()); + } + return nullptr; } diff --git a/src/cpacketstream.h b/src/cpacketstream.h index c7619f5..4707d0e 100644 --- a/src/cpacketstream.h +++ b/src/cpacketstream.h @@ -41,39 +41,39 @@ class CPacketStream : public CPacketQueue { public: - // constructor - CPacketStream(); + // constructor + CPacketStream(); - // destructor - virtual ~CPacketStream() {} + // destructor + virtual ~CPacketStream() {} - // open / close - bool Open(const CDvHeaderPacket &, std::shared_ptr); - void Close(void); + // open / close + bool Open(const CDvHeaderPacket &, std::shared_ptr); + void Close(void); - // push & pop - void Push(CPacket *); - void Tickle(void) { m_LastPacketTime.Now(); } - bool IsEmpty(void) const; + // push & pop + void Push(CPacket *); + void Tickle(void) { m_LastPacketTime.Now(); } + bool IsEmpty(void) const; - // get - std::shared_ptr GetOwnerClient(void) { return m_OwnerClient; } - const CIp *GetOwnerIp(void); - bool IsExpired(void) const { return (m_LastPacketTime.DurationSinceNow() > STREAM_TIMEOUT); } - bool IsOpen(void) const { return m_bOpen; } - uint16 GetStreamId(void) const { return m_uiStreamId; } - const CCallsign &GetUserCallsign(void) const { return m_DvHeader.GetMyCallsign(); } + // get + std::shared_ptr GetOwnerClient(void) { return m_OwnerClient; } + const CIp *GetOwnerIp(void); + bool IsExpired(void) const { return (m_LastPacketTime.DurationSinceNow() > STREAM_TIMEOUT); } + bool IsOpen(void) const { return m_bOpen; } + uint16 GetStreamId(void) const { return m_uiStreamId; } + const CCallsign &GetUserCallsign(void) const { return m_DvHeader.GetMyCallsign(); } protected: - // data - bool m_bOpen; - uint16 m_uiStreamId; - uint32 m_uiPacketCntr; - std::shared_ptr m_OwnerClient; - CTimePoint m_LastPacketTime; - CDvHeaderPacket m_DvHeader; + // data + bool m_bOpen; + uint16 m_uiStreamId; + uint32 m_uiPacketCntr; + std::shared_ptr m_OwnerClient; + CTimePoint m_LastPacketTime; + CDvHeaderPacket m_DvHeader; #ifdef TRANSCODER_IP - CCodecStream *m_CodecStream; + CCodecStream *m_CodecStream; #endif }; diff --git a/src/cpeer.cpp b/src/cpeer.cpp index 20c28de..2a849f4 100644 --- a/src/cpeer.cpp +++ b/src/cpeer.cpp @@ -35,21 +35,21 @@ CPeer::CPeer() { - ::memset(m_ReflectorModules, 0, sizeof(m_ReflectorModules)); - m_ConnectTime = std::time(nullptr); - m_LastHeardTime = std::time(nullptr); + ::memset(m_ReflectorModules, 0, sizeof(m_ReflectorModules)); + m_ConnectTime = std::time(nullptr); + m_LastHeardTime = std::time(nullptr); } CPeer::CPeer(const CCallsign &callsign, const CIp &ip, const char *modules, const CVersion &version) { - m_Callsign = callsign; - m_Ip = ip; - ::memset(m_ReflectorModules, 0, sizeof(m_ReflectorModules)); - ::strncpy(m_ReflectorModules, modules, sizeof(m_ReflectorModules)-1); - m_Version = version; - m_LastKeepaliveTime.Now(); - m_ConnectTime = std::time(nullptr); - m_LastHeardTime = std::time(nullptr); + m_Callsign = callsign; + m_Ip = ip; + ::memset(m_ReflectorModules, 0, sizeof(m_ReflectorModules)); + ::strncpy(m_ReflectorModules, modules, sizeof(m_ReflectorModules)-1); + m_Version = version; + m_LastKeepaliveTime.Now(); + m_ConnectTime = std::time(nullptr); + m_LastHeardTime = std::time(nullptr); } //////////////////////////////////////////////////////////////////////////////////////// @@ -57,7 +57,7 @@ CPeer::CPeer(const CCallsign &callsign, const CIp &ip, const char *modules, cons CPeer::~CPeer() { - m_Clients.clear(); + m_Clients.clear(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -65,26 +65,26 @@ CPeer::~CPeer() bool CPeer::operator ==(const CPeer &peer) const { - if (peer.m_Callsign != m_Callsign) + if (peer.m_Callsign != m_Callsign) return false; - if (peer.m_Ip != m_Ip) + if (peer.m_Ip != m_Ip) return false; - if (! (peer.m_Version == m_Version)) + if (! (peer.m_Version == m_Version)) return false; auto it1 = cbegin(); auto it2 = peer.cbegin(); - while (true) - { + while (true) + { if (it1==cend() && it2==peer.cend()) break; if (it1==cend() || it2==peer.cend()) return false; if (*it1 != *it2) return false; - it1++; + it1++; it2++; - } - return true; + } + return true; } @@ -93,21 +93,21 @@ bool CPeer::operator ==(const CPeer &peer) const bool CPeer::IsAMaster(void) const { - for ( auto it=cbegin(); it!=cend(); it++ ) - { - if ((*it)->IsAMaster()) + for ( auto it=cbegin(); it!=cend(); it++ ) + { + if ((*it)->IsAMaster()) return true; - } - return false; + } + return false; } void CPeer::Alive(void) { - m_LastKeepaliveTime.Now();; - for ( auto it=begin(); it!=end(); it++ ) - { - (*it)->Alive(); - } + m_LastKeepaliveTime.Now(); + for ( auto it=begin(); it!=end(); it++ ) + { + (*it)->Alive(); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -115,37 +115,37 @@ void CPeer::Alive(void) void CPeer::WriteXml(std::ofstream &xmlFile) { - xmlFile << "" << std::endl; - xmlFile << "\t" << m_Callsign << "" << std::endl; - xmlFile << "\t" << m_Ip.GetAddress() << "" << std::endl; - xmlFile << "\t" << m_ReflectorModules << "" << std::endl; - xmlFile << "\t" << GetProtocolName() << "" << std::endl; - char mbstr[100]; - if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_ConnectTime))) - { - xmlFile << "\t" << mbstr << "" << std::endl; - } - if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime))) - { - xmlFile << "\t" << mbstr << "" << std::endl; - } - xmlFile << "" << std::endl; + xmlFile << "" << std::endl; + xmlFile << "\t" << m_Callsign << "" << std::endl; + xmlFile << "\t" << m_Ip.GetAddress() << "" << std::endl; + xmlFile << "\t" << m_ReflectorModules << "" << std::endl; + xmlFile << "\t" << GetProtocolName() << "" << std::endl; + char mbstr[100]; + if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_ConnectTime))) + { + xmlFile << "\t" << mbstr << "" << std::endl; + } + if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime))) + { + xmlFile << "\t" << mbstr << "" << std::endl; + } + xmlFile << "" << std::endl; } void CPeer::GetJsonObject(char *Buffer) { - char sz[512]; - char mbstr[100]; - char cs[16]; - - if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime))) - { - m_Callsign.GetCallsignString(cs); - - ::sprintf(sz, "{\"callsign\":\"%s\",\"linkedto\":\"%s\",\"time\":\"%s\"}", - cs, - m_ReflectorModules, - mbstr); - ::strcat(Buffer, sz); - } + char sz[512]; + char mbstr[100]; + char cs[16]; + + if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime))) + { + m_Callsign.GetCallsignString(cs); + + ::sprintf(sz, "{\"callsign\":\"%s\",\"linkedto\":\"%s\",\"time\":\"%s\"}", + cs, + m_ReflectorModules, + mbstr); + ::strcat(Buffer, sz); + } } diff --git a/src/cpeer.h b/src/cpeer.h index 0ce1004..6db0cda 100644 --- a/src/cpeer.h +++ b/src/cpeer.h @@ -41,61 +41,61 @@ class CPeer { public: - // constructors - CPeer(); - CPeer(const CCallsign &, const CIp &, const char *, const CVersion &); - CPeer(const CPeer &) = delete; + // constructors + CPeer(); + CPeer(const CCallsign &, const CIp &, const char *, const CVersion &); + CPeer(const CPeer &) = delete; - // destructor - virtual ~CPeer(); + // destructor + virtual ~CPeer(); - // operators - bool operator ==(const CPeer &) const; + // operators + bool operator ==(const CPeer &) const; - // get - const CCallsign &GetCallsign(void) const { return m_Callsign; } - const CIp &GetIp(void) const { return m_Ip; } - char *GetReflectorModules(void) { return m_ReflectorModules; } + // get + const CCallsign &GetCallsign(void) const { return m_Callsign; } + const CIp &GetIp(void) const { return m_Ip; } + char *GetReflectorModules(void) { return m_ReflectorModules; } - // set + // set - // identity - virtual int GetProtocol(void) const { return PROTOCOL_NONE; } - virtual int GetProtocolRevision(void) const { return 0; } - virtual const char *GetProtocolName(void) const { return "none"; } + // identity + virtual int GetProtocol(void) const { return PROTOCOL_NONE; } + virtual int GetProtocolRevision(void) const { return 0; } + virtual const char *GetProtocolName(void) const { return "none"; } - // status - virtual bool IsAMaster(void) const; - virtual void Alive(void); - virtual bool IsAlive(void) const { return false; } - virtual void Heard(void) { m_LastHeardTime = std::time(nullptr); } + // status + virtual bool IsAMaster(void) const; + virtual void Alive(void); + virtual bool IsAlive(void) const { return false; } + virtual void Heard(void) { m_LastHeardTime = std::time(nullptr); } - // clients access - int GetNbClients(void) const { return (int)m_Clients.size(); } - void ClearClients(void) { m_Clients.clear(); } + // clients access + int GetNbClients(void) const { return (int)m_Clients.size(); } + void ClearClients(void) { m_Clients.clear(); } // pass-thru std::list>::iterator begin() { return m_Clients.begin(); } std::list>::iterator end() { return m_Clients.end(); } - std::list>::const_iterator cbegin() const { return m_Clients.cbegin(); } + std::list>::const_iterator cbegin() const { return m_Clients.cbegin(); } std::list>::const_iterator cend() const { return m_Clients.cend(); } - // reporting - virtual void WriteXml(std::ofstream &); - virtual void GetJsonObject(char *); + // reporting + virtual void WriteXml(std::ofstream &); + virtual void GetJsonObject(char *); protected: - // data - CCallsign m_Callsign; - CIp m_Ip; - char m_ReflectorModules[27]; - CVersion m_Version; - std::list> m_Clients; - - // status - CTimePoint m_LastKeepaliveTime; - std::time_t m_ConnectTime; - std::time_t m_LastHeardTime; + // data + CCallsign m_Callsign; + CIp m_Ip; + char m_ReflectorModules[27]; + CVersion m_Version; + std::list> m_Clients; + + // status + CTimePoint m_LastKeepaliveTime; + std::time_t m_ConnectTime; + std::time_t m_LastHeardTime; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cpeercallsignlist.cpp b/src/cpeercallsignlist.cpp index b78fd32..237d2d3 100644 --- a/src/cpeercallsignlist.cpp +++ b/src/cpeercallsignlist.cpp @@ -32,62 +32,62 @@ bool CPeerCallsignList::LoadFromFile(const char *filename) { - bool ok = false; - char sz[256]; + bool ok = false; + char sz[256]; - // and load - std::ifstream file (filename); - if ( file.is_open() ) - { - Lock(); + // and load + std::ifstream file (filename); + if ( file.is_open() ) + { + Lock(); - // empty list - m_Callsigns.clear(); - // fill with file content - while ( file.getline(sz, sizeof(sz)).good() ) - { - // remove leading & trailing spaces - char *szt = TrimWhiteSpaces(sz); + // empty list + m_Callsigns.clear(); + // fill with file content + while ( file.getline(sz, sizeof(sz)).good() ) + { + // remove leading & trailing spaces + char *szt = TrimWhiteSpaces(sz); - // crack it - if ( (::strlen(szt) > 0) && (szt[0] != '#') ) - { - // 1st token is callsign - if ( (szt = ::strtok(szt, " ,\t")) != nullptr ) - { - CCallsign callsign(szt); - // 2nd token is ip - char *szip; - if ( (szip = ::strtok(nullptr, " ,\t")) != nullptr ) - { - // 3rd token is modules list - if ( (szt = ::strtok(nullptr, " ,\t")) != nullptr ) - { - // and load - m_Callsigns.push_back(CCallsignListItem(callsign, szip, szt)); - } - } - } - } - } - // close file - file.close(); + // crack it + if ( (::strlen(szt) > 0) && (szt[0] != '#') ) + { + // 1st token is callsign + if ( (szt = ::strtok(szt, " ,\t")) != nullptr ) + { + CCallsign callsign(szt); + // 2nd token is ip + char *szip; + if ( (szip = ::strtok(nullptr, " ,\t")) != nullptr ) + { + // 3rd token is modules list + if ( (szt = ::strtok(nullptr, " ,\t")) != nullptr ) + { + // and load + m_Callsigns.push_back(CCallsignListItem(callsign, szip, szt)); + } + } + } + } + } + // close file + file.close(); - // keep file path - m_Filename = filename; + // keep file path + m_Filename = filename; - // update time - GetLastModTime(&m_LastModTime); + // update time + GetLastModTime(&m_LastModTime); - // and done - Unlock(); - ok = true; - std::cout << "Gatekeeper loaded " << m_Callsigns.size() << " lines from " << filename << std::endl; - } - else - { - std::cout << "Gatekeeper cannot find " << filename << std::endl; - } + // and done + Unlock(); + ok = true; + std::cout << "Gatekeeper loaded " << m_Callsigns.size() << " lines from " << filename << std::endl; + } + else + { + std::cout << "Gatekeeper cannot find " << filename << std::endl; + } - return ok; + return ok; } diff --git a/src/cpeercallsignlist.h b/src/cpeercallsignlist.h index 6472283..70cbd5f 100644 --- a/src/cpeercallsignlist.h +++ b/src/cpeercallsignlist.h @@ -36,14 +36,14 @@ class CPeerCallsignList : public CCallsignList { public: - // constructor - CPeerCallsignList() {} + // constructor + CPeerCallsignList() {} - // destructor - virtual ~CPeerCallsignList() {} + // destructor + virtual ~CPeerCallsignList() {} - // file io - bool LoadFromFile(const char *); + // file io + bool LoadFromFile(const char *); }; diff --git a/src/cpeers.cpp b/src/cpeers.cpp index 7e7c045..438d582 100644 --- a/src/cpeers.cpp +++ b/src/cpeers.cpp @@ -39,9 +39,9 @@ CPeers::CPeers() {} CPeers::~CPeers() { - m_Mutex.lock(); - m_Peers.clear(); - m_Mutex.unlock(); + m_Mutex.lock(); + m_Peers.clear(); + m_Mutex.unlock(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -49,23 +49,22 @@ CPeers::~CPeers() void CPeers::AddPeer(std::shared_ptr peer) { - // first check if peer already exists - for ( auto it=begin(); it!=end(); it++ ) - { - if (*peer == *(*it)) - // if found, just do nothing - // so *peer keep pointing on a valid object - // on function return - { - // delete new one - return; - } - } - - // if not, append to the vector + // first check if peer already exists + for ( auto it=begin(); it!=end(); it++ ) + { + if (*peer == *(*it)) + // if found, just do nothing + // so *peer keep pointing on a valid object + // on function return + { + // delete new one + return; + } + } + + // if not, append to the vector m_Peers.push_back(peer); - std::cout << "New peer " << peer->GetCallsign() << " at " << peer->GetIp() - << " added with protocol " << peer->GetProtocolName() << std::endl; + std::cout << "New peer " << peer->GetCallsign() << " at " << peer->GetIp() << " added with protocol " << peer->GetProtocolName() << std::endl; // and append all peer's client to reflector client list // it is double lock safe to lock Clients list after Peers list CClients *clients = g_Reflector.GetClients(); @@ -81,11 +80,11 @@ void CPeers::AddPeer(std::shared_ptr peer) void CPeers::RemovePeer(std::shared_ptr peer) { - // look for the client - for ( auto pit=begin(); pit!=end(); /*increment done in body */ ) - { - // compare object pointers - if (( *pit == peer ) && ( !(*pit)->IsAMaster() )) + // look for the client + for ( auto pit=begin(); pit!=end(); /*increment done in body */ ) + { + // compare object pointers + if (( *pit == peer ) && ( !(*pit)->IsAMaster() )) { // remove all clients from reflector client list // it is double lock safe to lock Clients list after Peers list @@ -109,7 +108,7 @@ void CPeers::RemovePeer(std::shared_ptr peer) { pit++; } - } + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -117,44 +116,41 @@ void CPeers::RemovePeer(std::shared_ptr peer) std::shared_ptr CPeers::FindPeer(const CIp &Ip, int Protocol) { - for ( auto it=begin(); it!=end(); it++ ) - { - if ( ((*it)->GetIp() == Ip) && ((*it)->GetProtocol() == Protocol)) - { - return *it; - } - } - - return nullptr; + for ( auto it=begin(); it!=end(); it++ ) + { + if ( ((*it)->GetIp() == Ip) && ((*it)->GetProtocol() == Protocol)) + { + return *it; + } + } + + return nullptr; } std::shared_ptr CPeers::FindPeer(const CCallsign &Callsign, const CIp &Ip, int Protocol) { - for ( auto it=begin(); it!=end(); it++ ) - { - if ( (*it)->GetCallsign().HasSameCallsign(Callsign) && - ((*it)->GetIp() == Ip) && - ((*it)->GetProtocol() == Protocol) ) - { - return *it; - } - } - - return nullptr; + for ( auto it=begin(); it!=end(); it++ ) + { + if ( (*it)->GetCallsign().HasSameCallsign(Callsign) && ((*it)->GetIp() == Ip) && ((*it)->GetProtocol() == Protocol) ) + { + return *it; + } + } + + return nullptr; } std::shared_ptr CPeers::FindPeer(const CCallsign &Callsign, int Protocol) { - for ( auto it=begin(); it!=end(); it++ ) - { - if ( ((*it)->GetProtocol() == Protocol) && - (*it)->GetCallsign().HasSameCallsign(Callsign) ) - { - return *it; - } - } - - return nullptr; + for ( auto it=begin(); it!=end(); it++ ) + { + if ( ((*it)->GetProtocol() == Protocol) && (*it)->GetCallsign().HasSameCallsign(Callsign) ) + { + return *it; + } + } + + return nullptr; } @@ -163,13 +159,13 @@ std::shared_ptr CPeers::FindPeer(const CCallsign &Callsign, int Protocol) std::shared_ptr CPeers::FindNextPeer(int Protocol, std::list>::iterator &it) { - while ( it!=end() ) - { - if ( (*it)->GetProtocol() == Protocol ) - { - return *it++; - } + while ( it!=end() ) + { + if ( (*it)->GetProtocol() == Protocol ) + { + return *it++; + } it++; - } - return nullptr; + } + return nullptr; } diff --git a/src/cpeers.h b/src/cpeers.h index 9d54423..3e4a5fa 100644 --- a/src/cpeers.h +++ b/src/cpeers.h @@ -39,20 +39,20 @@ class CPeers { public: - // constructors - CPeers(); + // constructors + CPeers(); - // destructors - virtual ~CPeers(); + // destructors + virtual ~CPeers(); - // locks - void Lock(void) { m_Mutex.lock(); } - void Unlock(void) { m_Mutex.unlock(); } + // locks + void Lock(void) { m_Mutex.lock(); } + void Unlock(void) { m_Mutex.unlock(); } - // manage peers - int GetSize(void) const { return (int)m_Peers.size(); } - void AddPeer(std::shared_ptr); - void RemovePeer(std::shared_ptr); + // manage peers + int GetSize(void) const { return (int)m_Peers.size(); } + void AddPeer(std::shared_ptr); + void RemovePeer(std::shared_ptr); // pass-thru std::list>::iterator begin() { return m_Peers.begin(); } @@ -60,18 +60,18 @@ public: std::list>::const_iterator cbegin() const { return m_Peers.cbegin(); } std::list>::const_iterator cend() const { return m_Peers.cend(); } - // find peers - std::shared_ptr FindPeer(const CIp &, int); - std::shared_ptr FindPeer(const CCallsign &, const CIp &, int); - std::shared_ptr FindPeer(const CCallsign &, int); + // find peers + std::shared_ptr FindPeer(const CIp &, int); + std::shared_ptr FindPeer(const CCallsign &, const CIp &, int); + std::shared_ptr FindPeer(const CCallsign &, int); - // iterate on peers - std::shared_ptr FindNextPeer(int, std::list>::iterator &); + // iterate on peers + std::shared_ptr FindNextPeer(int, std::list>::iterator &); protected: - // data - std::mutex m_Mutex; - std::list> m_Peers; + // data + std::mutex m_Mutex; + std::list> m_Peers; }; diff --git a/src/cprotocol.cpp b/src/cprotocol.cpp index 9204154..be3e298 100644 --- a/src/cprotocol.cpp +++ b/src/cprotocol.cpp @@ -41,26 +41,26 @@ CProtocol::CProtocol() : keep_running(true), m_pThread(nullptr) {} CProtocol::~CProtocol() { - // kill threads - keep_running = false; - if ( m_pThread != nullptr ) - { - m_pThread->join(); - delete m_pThread; + // kill threads + keep_running = false; + if ( m_pThread != nullptr ) + { + m_pThread->join(); + delete m_pThread; m_pThread = nullptr; - } + } // Close sockets m_Socket6.Close(); m_Socket4.Close(); - // empty queue - m_Queue.Lock(); - while ( !m_Queue.empty() ) - { - m_Queue.pop(); - } - m_Queue.Unlock(); + // empty queue + m_Queue.Lock(); + while ( !m_Queue.empty() ) + { + m_Queue.pop(); + } + m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -68,17 +68,17 @@ CProtocol::~CProtocol() bool CProtocol::Initialize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6) { - // init reflector apparent callsign - m_ReflectorCallsign = g_Reflector.GetCallsign(); + // init reflector apparent callsign + m_ReflectorCallsign = g_Reflector.GetCallsign(); - // reset stop flag - keep_running = true; + // reset stop flag + keep_running = true; - // update the reflector callsign + // update the reflector callsign if (type) - m_ReflectorCallsign.PatchCallsign(0, (const uint8 *)type, 3); + m_ReflectorCallsign.PatchCallsign(0, (const uint8 *)type, 3); - // create our sockets + // create our sockets #ifdef LISTEN_IPV4 if (has_ipv4) { @@ -106,7 +106,7 @@ bool CProtocol::Initialize(const char *type, const uint16 port, const bool has_i } #endif - // start thread; + // start thread; m_pThread = new std::thread(CProtocol::Thread, this); if (m_pThread == nullptr) { @@ -116,8 +116,8 @@ bool CProtocol::Initialize(const char *type, const uint16 port, const bool has_i return false; } - // done - return true; + // done + return true; } void CProtocol::Thread(CProtocol *This) @@ -130,13 +130,13 @@ void CProtocol::Thread(CProtocol *This) void CProtocol::Close(void) { - keep_running = false; - if ( m_pThread != nullptr ) - { - m_pThread->join(); - delete m_pThread; - m_pThread = nullptr; - } + keep_running = false; + if ( m_pThread != nullptr ) + { + m_pThread->join(); + delete m_pThread; + m_pThread = nullptr; + } m_Socket4.Close(); m_Socket6.Close(); } @@ -146,27 +146,27 @@ void CProtocol::Close(void) bool CProtocol::EncodeDvPacket(const CPacket &packet, CBuffer *buffer) const { - bool ok = false; - if ( packet.IsDvFrame() ) - { - if ( packet.IsLastPacket() ) - { - ok = EncodeDvLastFramePacket((const CDvLastFramePacket &)packet, buffer); - } - else - { - ok = EncodeDvFramePacket((const CDvFramePacket &)packet, buffer); - } - } - else if ( packet.IsDvHeader() ) - { - ok = EncodeDvHeaderPacket((const CDvHeaderPacket &)packet, buffer); - } - else - { - buffer->clear(); - } - return ok; + bool ok = false; + if ( packet.IsDvFrame() ) + { + if ( packet.IsLastPacket() ) + { + ok = EncodeDvLastFramePacket((const CDvLastFramePacket &)packet, buffer); + } + else + { + ok = EncodeDvFramePacket((const CDvFramePacket &)packet, buffer); + } + } + else if ( packet.IsDvHeader() ) + { + ok = EncodeDvHeaderPacket((const CDvHeaderPacket &)packet, buffer); + } + else + { + buffer->clear(); + } + return ok; } //////////////////////////////////////////////////////////////////////////////////////// @@ -174,42 +174,42 @@ bool CProtocol::EncodeDvPacket(const CPacket &packet, CBuffer *buffer) const void CProtocol::OnDvFramePacketIn(CDvFramePacket *Frame, const CIp *Ip) { - // find the stream - CPacketStream *stream = GetStream(Frame->GetStreamId(), Ip); - if ( stream == nullptr ) + // find the stream + CPacketStream *stream = GetStream(Frame->GetStreamId(), Ip); + if ( stream == nullptr ) { std::cout << "Deleting orphaned Frame with ID " << Frame->GetStreamId() << " on " << *Ip << std::endl; delete Frame; } else - { - //std::cout << "DV frame" << "from " << *Ip << std::endl; - // and push - stream->Lock(); - stream->Push(Frame); - stream->Unlock(); - } + { + //std::cout << "DV frame" << "from " << *Ip << std::endl; + // and push + stream->Lock(); + stream->Push(Frame); + stream->Unlock(); + } } void CProtocol::OnDvLastFramePacketIn(CDvLastFramePacket *Frame, const CIp *Ip) { - // find the stream - CPacketStream *stream = GetStream(Frame->GetStreamId(), Ip); - if ( stream == nullptr ) + // find the stream + CPacketStream *stream = GetStream(Frame->GetStreamId(), Ip); + if ( stream == nullptr ) { std::cout << "Deleting orphaned Last Frame with ID " << Frame->GetStreamId() << " on " << *Ip << std::endl; delete Frame; } else - { - // push - stream->Lock(); - stream->Push(Frame); - stream->Unlock(); - - // and close the stream - g_Reflector.CloseStream(stream); - } + { + // push + stream->Lock(); + stream->Push(Frame); + stream->Unlock(); + + // and close the stream + g_Reflector.CloseStream(stream); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -217,43 +217,43 @@ void CProtocol::OnDvLastFramePacketIn(CDvLastFramePacket *Frame, const CIp *Ip) CPacketStream *CProtocol::GetStream(uint16 uiStreamId, const CIp *Ip) { - for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ ) - { - if ( (*it)->GetStreamId() == uiStreamId ) - { - // if Ip not nullptr, also check if IP match - if ( (Ip != nullptr) && ((*it)->GetOwnerIp() != nullptr) ) - { - if ( *Ip == *((*it)->GetOwnerIp()) ) - { - return *it; - } - } - } - } - // done - return nullptr; + for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ ) + { + if ( (*it)->GetStreamId() == uiStreamId ) + { + // if Ip not nullptr, also check if IP match + if ( (Ip != nullptr) && ((*it)->GetOwnerIp() != nullptr) ) + { + if ( *Ip == *((*it)->GetOwnerIp()) ) + { + return *it; + } + } + } + } + // done + return nullptr; } void CProtocol::CheckStreamsTimeout(void) { - for ( auto it=m_Streams.begin(); it!=m_Streams.end(); ) - { - // time out ? - (*it)->Lock(); - if ( (*it)->IsExpired() ) - { - // yes, close it - (*it)->Unlock(); - g_Reflector.CloseStream(*it); - // and remove it - it = m_Streams.erase(it); - } - else - { - (*it++)->Unlock(); - } - } + for ( auto it=m_Streams.begin(); it!=m_Streams.end(); ) + { + // time out ? + (*it)->Lock(); + if ( (*it)->IsExpired() ) + { + // yes, close it + (*it)->Unlock(); + g_Reflector.CloseStream(*it); + // and remove it + it = m_Streams.erase(it); + } + else + { + (*it++)->Unlock(); + } + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -261,14 +261,14 @@ void CProtocol::CheckStreamsTimeout(void) void CProtocol::HandleQueue(void) { - // the default protocol just keep queue empty - m_Queue.Lock(); - while ( !m_Queue.empty() ) - { - delete m_Queue.front(); - m_Queue.pop(); - } - m_Queue.Unlock(); + // the default protocol just keep queue empty + m_Queue.Lock(); + while ( !m_Queue.empty() ) + { + delete m_Queue.front(); + m_Queue.pop(); + } + m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -276,17 +276,17 @@ void CProtocol::HandleQueue(void) bool CProtocol::IsNumber(char c) const { - return ((c >= '0') && (c <= '9')); + return ((c >= '0') && (c <= '9')); } bool CProtocol::IsLetter(char c) const { - return ((c >= 'A') && (c <= 'Z')); + return ((c >= 'A') && (c <= 'Z')); } bool CProtocol::IsSpace(char c) const { - return (c == ' '); + return (c == ' '); } //////////////////////////////////////////////////////////////////////////////////////// @@ -294,12 +294,12 @@ bool CProtocol::IsSpace(char c) const char CProtocol::DmrDstIdToModule(uint32 tg) const { - return ((char)((tg % 26)-1) + 'A'); + return ((char)((tg % 26)-1) + 'A'); } uint32 CProtocol::ModuleToDmrDestId(char m) const { - return (uint32)(m - 'A')+1; + return (uint32)(m - 'A')+1; } //////////////////////////////////////////////////////////////////////////////////////// @@ -357,60 +357,64 @@ bool CProtocol::ReceiveDS(CBuffer &buf, CIp &ip, int time_ms) void CProtocol::Send(const CBuffer &buf, const CIp &Ip) const { - switch (Ip.GetFamily()) { - case AF_INET: - m_Socket4.Send(buf, Ip); - break; - case AF_INET6: - m_Socket6.Send(buf, Ip); - break; - default: - std::cerr << "Wrong family: " << Ip.GetFamily() << std::endl; - break; + switch (Ip.GetFamily()) + { + case AF_INET: + m_Socket4.Send(buf, Ip); + break; + case AF_INET6: + m_Socket6.Send(buf, Ip); + break; + default: + std::cerr << "Wrong family: " << Ip.GetFamily() << std::endl; + break; } } void CProtocol::Send(const char *buf, const CIp &Ip) const { - switch (Ip.GetFamily()) { - case AF_INET: - m_Socket4.Send(buf, Ip); - break; - case AF_INET6: - m_Socket6.Send(buf, Ip); - break; - default: - std::cerr << "ERROR: wrong family: " << Ip.GetFamily() << std::endl; - break; + switch (Ip.GetFamily()) + { + case AF_INET: + m_Socket4.Send(buf, Ip); + break; + case AF_INET6: + m_Socket6.Send(buf, Ip); + break; + default: + std::cerr << "ERROR: wrong family: " << Ip.GetFamily() << std::endl; + break; } } void CProtocol::Send(const CBuffer &buf, const CIp &Ip, uint16_t port) const { - switch (Ip.GetFamily()) { - case AF_INET: - m_Socket4.Send(buf, Ip, port); - break; - case AF_INET6: - m_Socket6.Send(buf, Ip, port); - break; - default: - std::cerr << "Wrong family: " << Ip.GetFamily() << " on port " << port << std::endl; - break; + switch (Ip.GetFamily()) + { + case AF_INET: + m_Socket4.Send(buf, Ip, port); + break; + case AF_INET6: + m_Socket6.Send(buf, Ip, port); + break; + default: + std::cerr << "Wrong family: " << Ip.GetFamily() << " on port " << port << std::endl; + break; } } void CProtocol::Send(const char *buf, const CIp &Ip, uint16_t port) const { - switch (Ip.GetFamily()) { - case AF_INET: - m_Socket4.Send(buf, Ip, port); - break; - case AF_INET6: - m_Socket6.Send(buf, Ip, port); - break; - default: - std::cerr << "Wrong family: " << Ip.GetFamily() << " on port " << port << std::endl; - break; + switch (Ip.GetFamily()) + { + case AF_INET: + m_Socket4.Send(buf, Ip, port); + break; + case AF_INET6: + m_Socket6.Send(buf, Ip, port); + break; + default: + std::cerr << "Wrong family: " << Ip.GetFamily() << " on port " << port << std::endl; + break; } } diff --git a/src/cprotocol.h b/src/cprotocol.h index 876d333..db88dff 100644 --- a/src/cprotocol.h +++ b/src/cprotocol.h @@ -70,57 +70,57 @@ class CProtocol { public: - // constructor - CProtocol(); + // constructor + CProtocol(); - // destructor - virtual ~CProtocol(); + // destructor + virtual ~CProtocol(); - // initialization - virtual bool Initialize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); - virtual void Close(void); + // initialization + virtual bool Initialize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); + virtual void Close(void); - // queue - CPacketQueue *GetQueue(void) { m_Queue.Lock(); return &m_Queue; } - void ReleaseQueue(void) { m_Queue.Unlock(); } + // queue + CPacketQueue *GetQueue(void) { m_Queue.Lock(); return &m_Queue; } + void ReleaseQueue(void) { m_Queue.Unlock(); } - // get - const CCallsign &GetReflectorCallsign(void)const { return m_ReflectorCallsign; } + // get + const CCallsign &GetReflectorCallsign(void)const { return m_ReflectorCallsign; } - // task - static void Thread(CProtocol *); - virtual void Task(void) = 0; + // task + static void Thread(CProtocol *); + virtual void Task(void) = 0; protected: - // packet encoding helpers - virtual bool EncodeDvPacket(const CPacket &, CBuffer *) const; - virtual bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const { return false; } - virtual bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const { return false; } - virtual bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const { return false; } + // packet encoding helpers + virtual bool EncodeDvPacket(const CPacket &, CBuffer *) const; + virtual bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const { return false; } + virtual bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const { return false; } + virtual bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const { return false; } - // stream helpers - virtual bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &) { return false; } - virtual void OnDvFramePacketIn(CDvFramePacket *, const CIp * = nullptr); - virtual void OnDvLastFramePacketIn(CDvLastFramePacket *, const CIp * = nullptr); + // stream helpers + virtual bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &) { return false; } + virtual void OnDvFramePacketIn(CDvFramePacket *, const CIp * = nullptr); + virtual void OnDvLastFramePacketIn(CDvLastFramePacket *, const CIp * = nullptr); - // stream handle helpers - CPacketStream *GetStream(uint16, const CIp * = nullptr); - void CheckStreamsTimeout(void); + // stream handle helpers + CPacketStream *GetStream(uint16, const CIp * = nullptr); + void CheckStreamsTimeout(void); - // queue helper - virtual void HandleQueue(void); + // queue helper + virtual void HandleQueue(void); - // keepalive helpers - virtual void HandleKeepalives(void) {} + // keepalive helpers + virtual void HandleKeepalives(void) {} - // syntax helper - bool IsNumber(char) const; - bool IsLetter(char) const; - bool IsSpace(char) const; + // syntax helper + bool IsNumber(char) const; + bool IsLetter(char) const; + bool IsSpace(char) const; - // dmr DstId to Module helper - virtual char DmrDstIdToModule(uint32) const; - virtual uint32 ModuleToDmrDestId(char) const; + // dmr DstId to Module helper + virtual char DmrDstIdToModule(uint32) const; + virtual uint32 ModuleToDmrDestId(char) const; bool Receive6(CBuffer &buf, CIp &Ip, int time_ms); bool Receive4(CBuffer &buf, CIp &Ip, int time_ms); @@ -131,25 +131,25 @@ protected: void Send(const CBuffer &buf, const CIp &Ip, uint16 port) const; void Send(const char *buf, const CIp &Ip, uint16 port) const; - // socket - CUdpSocket m_Socket4; + // socket + CUdpSocket m_Socket4; CUdpSocket m_Socket6; - // streams - std::list m_Streams; + // streams + std::list m_Streams; - // queue - CPacketQueue m_Queue; + // queue + CPacketQueue m_Queue; - // thread - std::atomic keep_running; - std::thread *m_pThread; + // thread + std::atomic keep_running; + std::thread *m_pThread; - // identity - CCallsign m_ReflectorCallsign; + // identity + CCallsign m_ReflectorCallsign; - // debug - CTimePoint m_DebugTimer; + // debug + CTimePoint m_DebugTimer; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cprotocols.cpp b/src/cprotocols.cpp index 9fc9336..b6116a9 100644 --- a/src/cprotocols.cpp +++ b/src/cprotocols.cpp @@ -43,7 +43,7 @@ CProtocols::~CProtocols() { - Close(); + Close(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -51,8 +51,8 @@ CProtocols::~CProtocols() bool CProtocols::Init(void) { - m_Mutex.lock(); - { + m_Mutex.lock(); + { m_Protocols.emplace_back(std::unique_ptr(new CDextraProtocol)); if (! m_Protocols.back()->Initialize("XRF", DEXTRA_PORT, DSTAR_IPV4, DSTAR_IPV6)) return false; @@ -89,16 +89,16 @@ bool CProtocols::Init(void) return false; #endif - } - m_Mutex.unlock(); + } + m_Mutex.unlock(); - // done - return true; + // done + return true; } void CProtocols::Close(void) { - m_Mutex.lock(); + m_Mutex.lock(); m_Protocols.clear(); - m_Mutex.unlock(); + m_Mutex.unlock(); } diff --git a/src/cprotocols.h b/src/cprotocols.h index a126f93..8ad2102 100644 --- a/src/cprotocols.h +++ b/src/cprotocols.h @@ -38,23 +38,23 @@ class CProtocols { public: - // destructors - ~CProtocols(); + // destructors + ~CProtocols(); - // initialization - bool Init(void); - void Close(void); + // initialization + bool Init(void); + void Close(void); void Lock(void) { m_Mutex.lock(); } void Unlock(void) { m_Mutex.unlock(); } - // pass-thru + // pass-thru std::list>::iterator begin() { return m_Protocols.begin(); } - std::list>::iterator end() { return m_Protocols.end(); } + std::list>::iterator end() { return m_Protocols.end(); } protected: - // data - std::mutex m_Mutex; - std::list> m_Protocols; + // data + std::mutex m_Mutex; + std::list> m_Protocols; }; diff --git a/src/cqr1676.cpp b/src/cqr1676.cpp index 6ea3e31..9f243dc 100644 --- a/src/cqr1676.cpp +++ b/src/cqr1676.cpp @@ -22,41 +22,45 @@ #include const unsigned int ENCODING_TABLE_1676[] = -{0x0000U, 0x0273U, 0x04E5U, 0x0696U, 0x09C9U, 0x0BBAU, 0x0D2CU, 0x0F5FU, 0x11E2U, 0x1391U, 0x1507U, 0x1774U, - 0x182BU, 0x1A58U, 0x1CCEU, 0x1EBDU, 0x21B7U, 0x23C4U, 0x2552U, 0x2721U, 0x287EU, 0x2A0DU, 0x2C9BU, 0x2EE8U, - 0x3055U, 0x3226U, 0x34B0U, 0x36C3U, 0x399CU, 0x3BEFU, 0x3D79U, 0x3F0AU, 0x411EU, 0x436DU, 0x45FBU, 0x4788U, - 0x48D7U, 0x4AA4U, 0x4C32U, 0x4E41U, 0x50FCU, 0x528FU, 0x5419U, 0x566AU, 0x5935U, 0x5B46U, 0x5DD0U, 0x5FA3U, - 0x60A9U, 0x62DAU, 0x644CU, 0x663FU, 0x6960U, 0x6B13U, 0x6D85U, 0x6FF6U, 0x714BU, 0x7338U, 0x75AEU, 0x77DDU, - 0x7882U, 0x7AF1U, 0x7C67U, 0x7E14U, 0x804FU, 0x823CU, 0x84AAU, 0x86D9U, 0x8986U, 0x8BF5U, 0x8D63U, 0x8F10U, - 0x91ADU, 0x93DEU, 0x9548U, 0x973BU, 0x9864U, 0x9A17U, 0x9C81U, 0x9EF2U, 0xA1F8U, 0xA38BU, 0xA51DU, 0xA76EU, - 0xA831U, 0xAA42U, 0xACD4U, 0xAEA7U, 0xB01AU, 0xB269U, 0xB4FFU, 0xB68CU, 0xB9D3U, 0xBBA0U, 0xBD36U, 0xBF45U, - 0xC151U, 0xC322U, 0xC5B4U, 0xC7C7U, 0xC898U, 0xCAEBU, 0xCC7DU, 0xCE0EU, 0xD0B3U, 0xD2C0U, 0xD456U, 0xD625U, - 0xD97AU, 0xDB09U, 0xDD9FU, 0xDFECU, 0xE0E6U, 0xE295U, 0xE403U, 0xE670U, 0xE92FU, 0xEB5CU, 0xEDCAU, 0xEFB9U, - 0xF104U, 0xF377U, 0xF5E1U, 0xF792U, 0xF8CDU, 0xFABEU, 0xFC28U, 0xFE5BU}; +{ + 0x0000U, 0x0273U, 0x04E5U, 0x0696U, 0x09C9U, 0x0BBAU, 0x0D2CU, 0x0F5FU, 0x11E2U, 0x1391U, 0x1507U, 0x1774U, + 0x182BU, 0x1A58U, 0x1CCEU, 0x1EBDU, 0x21B7U, 0x23C4U, 0x2552U, 0x2721U, 0x287EU, 0x2A0DU, 0x2C9BU, 0x2EE8U, + 0x3055U, 0x3226U, 0x34B0U, 0x36C3U, 0x399CU, 0x3BEFU, 0x3D79U, 0x3F0AU, 0x411EU, 0x436DU, 0x45FBU, 0x4788U, + 0x48D7U, 0x4AA4U, 0x4C32U, 0x4E41U, 0x50FCU, 0x528FU, 0x5419U, 0x566AU, 0x5935U, 0x5B46U, 0x5DD0U, 0x5FA3U, + 0x60A9U, 0x62DAU, 0x644CU, 0x663FU, 0x6960U, 0x6B13U, 0x6D85U, 0x6FF6U, 0x714BU, 0x7338U, 0x75AEU, 0x77DDU, + 0x7882U, 0x7AF1U, 0x7C67U, 0x7E14U, 0x804FU, 0x823CU, 0x84AAU, 0x86D9U, 0x8986U, 0x8BF5U, 0x8D63U, 0x8F10U, + 0x91ADU, 0x93DEU, 0x9548U, 0x973BU, 0x9864U, 0x9A17U, 0x9C81U, 0x9EF2U, 0xA1F8U, 0xA38BU, 0xA51DU, 0xA76EU, + 0xA831U, 0xAA42U, 0xACD4U, 0xAEA7U, 0xB01AU, 0xB269U, 0xB4FFU, 0xB68CU, 0xB9D3U, 0xBBA0U, 0xBD36U, 0xBF45U, + 0xC151U, 0xC322U, 0xC5B4U, 0xC7C7U, 0xC898U, 0xCAEBU, 0xCC7DU, 0xCE0EU, 0xD0B3U, 0xD2C0U, 0xD456U, 0xD625U, + 0xD97AU, 0xDB09U, 0xDD9FU, 0xDFECU, 0xE0E6U, 0xE295U, 0xE403U, 0xE670U, 0xE92FU, 0xEB5CU, 0xEDCAU, 0xEFB9U, + 0xF104U, 0xF377U, 0xF5E1U, 0xF792U, 0xF8CDU, 0xFABEU, 0xFC28U, 0xFE5BU +}; const unsigned int DECODING_TABLE_1576[] = -{0x0000U, 0x0001U, 0x0002U, 0x0003U, 0x0004U, 0x0005U, 0x0006U, 0x4020U, 0x0008U, 0x0009U, 0x000AU, 0x000BU, - 0x000CU, 0x000DU, 0x2081U, 0x2080U, 0x0010U, 0x0011U, 0x0012U, 0x0013U, 0x0014U, 0x0C00U, 0x0016U, 0x0C02U, - 0x0018U, 0x0120U, 0x001AU, 0x0122U, 0x4102U, 0x0124U, 0x4100U, 0x4101U, 0x0020U, 0x0021U, 0x0022U, 0x4004U, - 0x0024U, 0x4002U, 0x4001U, 0x4000U, 0x0028U, 0x0110U, 0x1800U, 0x1801U, 0x002CU, 0x400AU, 0x4009U, 0x4008U, - 0x0030U, 0x0108U, 0x0240U, 0x0241U, 0x0034U, 0x4012U, 0x4011U, 0x4010U, 0x0101U, 0x0100U, 0x0103U, 0x0102U, - 0x0105U, 0x0104U, 0x1401U, 0x1400U, 0x0040U, 0x0041U, 0x0042U, 0x0043U, 0x0044U, 0x0045U, 0x0046U, 0x4060U, - 0x0048U, 0x0049U, 0x0301U, 0x0300U, 0x004CU, 0x1600U, 0x0305U, 0x0304U, 0x0050U, 0x0051U, 0x0220U, 0x0221U, - 0x3000U, 0x4200U, 0x3002U, 0x4202U, 0x0058U, 0x1082U, 0x1081U, 0x1080U, 0x3008U, 0x4208U, 0x2820U, 0x1084U, - 0x0060U, 0x0061U, 0x0210U, 0x0211U, 0x0480U, 0x0481U, 0x4041U, 0x4040U, 0x0068U, 0x2402U, 0x2401U, 0x2400U, - 0x0488U, 0x3100U, 0x2810U, 0x2404U, 0x0202U, 0x0880U, 0x0200U, 0x0201U, 0x0206U, 0x0884U, 0x0204U, 0x0205U, - 0x0141U, 0x0140U, 0x0208U, 0x0209U, 0x2802U, 0x0144U, 0x2800U, 0x2801U, 0x0080U, 0x0081U, 0x0082U, 0x0A00U, - 0x0084U, 0x0085U, 0x2009U, 0x2008U, 0x0088U, 0x0089U, 0x2005U, 0x2004U, 0x2003U, 0x2002U, 0x2001U, 0x2000U, - 0x0090U, 0x0091U, 0x0092U, 0x1048U, 0x0602U, 0x0C80U, 0x0600U, 0x0601U, 0x0098U, 0x1042U, 0x1041U, 0x1040U, - 0x2013U, 0x2012U, 0x2011U, 0x2010U, 0x00A0U, 0x00A1U, 0x00A2U, 0x4084U, 0x0440U, 0x0441U, 0x4081U, 0x4080U, - 0x6000U, 0x1200U, 0x6002U, 0x1202U, 0x6004U, 0x2022U, 0x2021U, 0x2020U, 0x0841U, 0x0840U, 0x2104U, 0x0842U, - 0x2102U, 0x0844U, 0x2100U, 0x2101U, 0x0181U, 0x0180U, 0x0B00U, 0x0182U, 0x5040U, 0x0184U, 0x2108U, 0x2030U, - 0x00C0U, 0x00C1U, 0x4401U, 0x4400U, 0x0420U, 0x0421U, 0x0422U, 0x4404U, 0x0900U, 0x0901U, 0x1011U, 0x1010U, - 0x0904U, 0x2042U, 0x2041U, 0x2040U, 0x0821U, 0x0820U, 0x1009U, 0x1008U, 0x4802U, 0x0824U, 0x4800U, 0x4801U, - 0x1003U, 0x1002U, 0x1001U, 0x1000U, 0x0501U, 0x0500U, 0x1005U, 0x1004U, 0x0404U, 0x0810U, 0x1100U, 0x1101U, - 0x0400U, 0x0401U, 0x0402U, 0x0403U, 0x040CU, 0x0818U, 0x1108U, 0x1030U, 0x0408U, 0x0409U, 0x040AU, 0x2060U, - 0x0801U, 0x0800U, 0x0280U, 0x0802U, 0x0410U, 0x0804U, 0x0412U, 0x0806U, 0x0809U, 0x0808U, 0x1021U, 0x1020U, - 0x5000U, 0x2200U, 0x5002U, 0x2202U}; +{ + 0x0000U, 0x0001U, 0x0002U, 0x0003U, 0x0004U, 0x0005U, 0x0006U, 0x4020U, 0x0008U, 0x0009U, 0x000AU, 0x000BU, + 0x000CU, 0x000DU, 0x2081U, 0x2080U, 0x0010U, 0x0011U, 0x0012U, 0x0013U, 0x0014U, 0x0C00U, 0x0016U, 0x0C02U, + 0x0018U, 0x0120U, 0x001AU, 0x0122U, 0x4102U, 0x0124U, 0x4100U, 0x4101U, 0x0020U, 0x0021U, 0x0022U, 0x4004U, + 0x0024U, 0x4002U, 0x4001U, 0x4000U, 0x0028U, 0x0110U, 0x1800U, 0x1801U, 0x002CU, 0x400AU, 0x4009U, 0x4008U, + 0x0030U, 0x0108U, 0x0240U, 0x0241U, 0x0034U, 0x4012U, 0x4011U, 0x4010U, 0x0101U, 0x0100U, 0x0103U, 0x0102U, + 0x0105U, 0x0104U, 0x1401U, 0x1400U, 0x0040U, 0x0041U, 0x0042U, 0x0043U, 0x0044U, 0x0045U, 0x0046U, 0x4060U, + 0x0048U, 0x0049U, 0x0301U, 0x0300U, 0x004CU, 0x1600U, 0x0305U, 0x0304U, 0x0050U, 0x0051U, 0x0220U, 0x0221U, + 0x3000U, 0x4200U, 0x3002U, 0x4202U, 0x0058U, 0x1082U, 0x1081U, 0x1080U, 0x3008U, 0x4208U, 0x2820U, 0x1084U, + 0x0060U, 0x0061U, 0x0210U, 0x0211U, 0x0480U, 0x0481U, 0x4041U, 0x4040U, 0x0068U, 0x2402U, 0x2401U, 0x2400U, + 0x0488U, 0x3100U, 0x2810U, 0x2404U, 0x0202U, 0x0880U, 0x0200U, 0x0201U, 0x0206U, 0x0884U, 0x0204U, 0x0205U, + 0x0141U, 0x0140U, 0x0208U, 0x0209U, 0x2802U, 0x0144U, 0x2800U, 0x2801U, 0x0080U, 0x0081U, 0x0082U, 0x0A00U, + 0x0084U, 0x0085U, 0x2009U, 0x2008U, 0x0088U, 0x0089U, 0x2005U, 0x2004U, 0x2003U, 0x2002U, 0x2001U, 0x2000U, + 0x0090U, 0x0091U, 0x0092U, 0x1048U, 0x0602U, 0x0C80U, 0x0600U, 0x0601U, 0x0098U, 0x1042U, 0x1041U, 0x1040U, + 0x2013U, 0x2012U, 0x2011U, 0x2010U, 0x00A0U, 0x00A1U, 0x00A2U, 0x4084U, 0x0440U, 0x0441U, 0x4081U, 0x4080U, + 0x6000U, 0x1200U, 0x6002U, 0x1202U, 0x6004U, 0x2022U, 0x2021U, 0x2020U, 0x0841U, 0x0840U, 0x2104U, 0x0842U, + 0x2102U, 0x0844U, 0x2100U, 0x2101U, 0x0181U, 0x0180U, 0x0B00U, 0x0182U, 0x5040U, 0x0184U, 0x2108U, 0x2030U, + 0x00C0U, 0x00C1U, 0x4401U, 0x4400U, 0x0420U, 0x0421U, 0x0422U, 0x4404U, 0x0900U, 0x0901U, 0x1011U, 0x1010U, + 0x0904U, 0x2042U, 0x2041U, 0x2040U, 0x0821U, 0x0820U, 0x1009U, 0x1008U, 0x4802U, 0x0824U, 0x4800U, 0x4801U, + 0x1003U, 0x1002U, 0x1001U, 0x1000U, 0x0501U, 0x0500U, 0x1005U, 0x1004U, 0x0404U, 0x0810U, 0x1100U, 0x1101U, + 0x0400U, 0x0401U, 0x0402U, 0x0403U, 0x040CU, 0x0818U, 0x1108U, 0x1030U, 0x0408U, 0x0409U, 0x040AU, 0x2060U, + 0x0801U, 0x0800U, 0x0280U, 0x0802U, 0x0410U, 0x0804U, 0x0412U, 0x0806U, 0x0809U, 0x0808U, 0x1021U, 0x1020U, + 0x5000U, 0x2200U, 0x5002U, 0x2202U +}; #define X14 0x00004000 /* vector representation of X^{14} */ #define X8 0x00000100 /* vector representation of X^{8} */ @@ -74,41 +78,43 @@ unsigned int CQR1676::getSyndrome1576(unsigned int pattern) * obtain its syndrome in decoding. */ { - unsigned int aux = X14; + unsigned int aux = X14; - if (pattern >= X8) { - while (pattern & MASK7) { - while (!(aux & pattern)) - aux = aux >> 1; + if (pattern >= X8) + { + while (pattern & MASK7) + { + while (!(aux & pattern)) + aux = aux >> 1; - pattern ^= (aux / X8) * GENPOL; - } - } + pattern ^= (aux / X8) * GENPOL; + } + } - return pattern; + return pattern; } // Compute the EMB against a precomputed list of correct words void CQR1676::encode(unsigned char* data) { - assert(data != nullptr); + assert(data != nullptr); - unsigned int value = (data[0U] >> 1) & 0x7FU; - unsigned int cksum = ENCODING_TABLE_1676[value]; + unsigned int value = (data[0U] >> 1) & 0x7FU; + unsigned int cksum = ENCODING_TABLE_1676[value]; - data[0U] = cksum >> 8; - data[1U] = cksum & 0xFFU; + data[0U] = cksum >> 8; + data[1U] = cksum & 0xFFU; } unsigned char CQR1676::decode(const unsigned char* data) { - assert(data != nullptr); + assert(data != nullptr); - unsigned int code = (data[0U] << 7) + (data[1U] >> 1); - unsigned int syndrome = getSyndrome1576(code); - unsigned int error_pattern = DECODING_TABLE_1576[syndrome]; + unsigned int code = (data[0U] << 7) + (data[1U] >> 1); + unsigned int syndrome = getSyndrome1576(code); + unsigned int error_pattern = DECODING_TABLE_1576[syndrome]; - code ^= error_pattern; + code ^= error_pattern; - return code >> 7; + return code >> 7; } diff --git a/src/cqr1676.h b/src/cqr1676.h index 59dd524..31c874d 100644 --- a/src/cqr1676.h +++ b/src/cqr1676.h @@ -19,14 +19,15 @@ #ifndef QR1676_H #define QR1676_H -class CQR1676 { +class CQR1676 +{ public: - static void encode(unsigned char* data); - - static unsigned char decode(const unsigned char* data); - + static void encode(unsigned char* data); + + static unsigned char decode(const unsigned char* data); + private: - static unsigned int getSyndrome1576(unsigned int pattern); + static unsigned int getSyndrome1576(unsigned int pattern); }; #endif diff --git a/src/crawsocket.cpp b/src/crawsocket.cpp index de8514b..b0d8305 100644 --- a/src/crawsocket.cpp +++ b/src/crawsocket.cpp @@ -33,7 +33,7 @@ CRawSocket::CRawSocket() { - m_Socket = -1; + m_Socket = -1; } //////////////////////////////////////////////////////////////////////////////////////// @@ -41,10 +41,10 @@ CRawSocket::CRawSocket() CRawSocket::~CRawSocket() { - if ( m_Socket != -1 ) - { - Close(); - } + if ( m_Socket != -1 ) + { + Close(); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -52,29 +52,29 @@ CRawSocket::~CRawSocket() bool CRawSocket::Open(uint16 uiProto) { - bool open = false; - int on = 1; - - // create socket - m_Socket = socket(AF_INET,SOCK_RAW,uiProto); - if ( m_Socket != -1 ) - { - fcntl(m_Socket, F_SETFL, O_NONBLOCK); - open = true; - m_Proto = uiProto; - } - - // done - return open; + bool open = false; + int on = 1; + + // create socket + m_Socket = socket(AF_INET,SOCK_RAW,uiProto); + if ( m_Socket != -1 ) + { + fcntl(m_Socket, F_SETFL, O_NONBLOCK); + open = true; + m_Proto = uiProto; + } + + // done + return open; } void CRawSocket::Close(void) { - if ( m_Socket != -1 ) - { - close(m_Socket); - m_Socket = -1; - } + if ( m_Socket != -1 ) + { + close(m_Socket); + m_Socket = -1; + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -82,43 +82,43 @@ void CRawSocket::Close(void) int CRawSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout) { - struct sockaddr_in Sin; - fd_set FdSet; - unsigned int uiFromLen = sizeof(struct sockaddr_in); - int iRecvLen = -1; - struct timeval tv; - - // socket valid ? - if ( m_Socket != -1 ) - { - // allocate buffer - Buffer->resize(UDP_BUFFER_LENMAX); - - // control socket - FD_ZERO(&FdSet); - FD_SET(m_Socket, &FdSet); - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - select(m_Socket + 1, &FdSet, 0, 0, &tv); - - // read - iRecvLen = (int)recvfrom(m_Socket, - (void *)Buffer->data(), RAW_BUFFER_LENMAX, - 0, (struct sockaddr *)&Sin, &uiFromLen); - - // handle - if ( iRecvLen != -1 ) - { - // adjust buffer size - Buffer->resize(iRecvLen); - - // get IP - memcpy(Ip->GetPointer(), &Sin, sizeof(struct sockaddr_in)); - } - } - - // done - return iRecvLen; + struct sockaddr_in Sin; + fd_set FdSet; + unsigned int uiFromLen = sizeof(struct sockaddr_in); + int iRecvLen = -1; + struct timeval tv; + + // socket valid ? + if ( m_Socket != -1 ) + { + // allocate buffer + Buffer->resize(UDP_BUFFER_LENMAX); + + // control socket + FD_ZERO(&FdSet); + FD_SET(m_Socket, &FdSet); + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + select(m_Socket + 1, &FdSet, 0, 0, &tv); + + // read + iRecvLen = (int)recvfrom(m_Socket, + (void *)Buffer->data(), RAW_BUFFER_LENMAX, + 0, (struct sockaddr *)&Sin, &uiFromLen); + + // handle + if ( iRecvLen != -1 ) + { + // adjust buffer size + Buffer->resize(iRecvLen); + + // get IP + memcpy(Ip->GetPointer(), &Sin, sizeof(struct sockaddr_in)); + } + } + + // done + return iRecvLen; } // protocol specific @@ -127,30 +127,30 @@ int CRawSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout) int CRawSocket::IcmpReceive(CBuffer *Buffer, CIp *Ip, int timeout) { - int iIcmpType = -1; - int iRecv; + int iIcmpType = -1; + int iRecv; - if (m_Proto == IPPROTO_ICMP) - { - iRecv = Receive(Buffer, Ip, timeout); + if (m_Proto == IPPROTO_ICMP) + { + iRecv = Receive(Buffer, Ip, timeout); - if (iRecv >= (int)(sizeof(struct ip) + sizeof(struct icmp))) - { - struct ip *iph = (struct ip *)Buffer->data(); - int iphdrlen = iph->ip_hl * 4; - struct icmp *icmph = (struct icmp *)((unsigned char *)iph + iphdrlen); - struct ip *remote_iph = (struct ip *)((unsigned char *)icmph + 8); + if (iRecv >= (int)(sizeof(struct ip) + sizeof(struct icmp))) + { + struct ip *iph = (struct ip *)Buffer->data(); + int iphdrlen = iph->ip_hl * 4; + struct icmp *icmph = (struct icmp *)((unsigned char *)iph + iphdrlen); + struct ip *remote_iph = (struct ip *)((unsigned char *)icmph + 8); - iIcmpType = icmph->icmp_type; + iIcmpType = icmph->icmp_type; - struct sockaddr_in Sin; - bzero(&Sin, sizeof(Sin)); - Sin.sin_family = AF_INET; - Sin.sin_addr.s_addr = remote_iph->ip_dst.s_addr; + struct sockaddr_in Sin; + bzero(&Sin, sizeof(Sin)); + Sin.sin_family = AF_INET; + Sin.sin_addr.s_addr = remote_iph->ip_dst.s_addr; - memcpy(Ip->GetPointer(), &Sin, sizeof(struct sockaddr_in)); + memcpy(Ip->GetPointer(), &Sin, sizeof(struct sockaddr_in)); - } - } - return iIcmpType; + } + } + return iIcmpType; } diff --git a/src/crawsocket.h b/src/crawsocket.h index 1de0f8a..c52cafe 100644 --- a/src/crawsocket.h +++ b/src/crawsocket.h @@ -19,11 +19,11 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- // Description: -// Raw socket access class with protocol specific +// Raw socket access class with protocol specific #ifndef crawsocket_h @@ -53,46 +53,46 @@ class CRawSocket { public: - // constructor - CRawSocket(); - - // destructor - ~CRawSocket(); - - // open & close - bool Open(uint16); - void Close(void); - int GetSocket(void) { return m_Socket; } - - // read - - // if ETH_P_ALL is used, the received data buffer will hold - // the ethernet header (struct ethhdr) followed by the IP header (struct iphdr), - // the protocol header (e.g tcp, udp, icmp) and the data. - // For specific protocols, the data content may vary depending on the protocol - // Returns the number of received bytes in buffer - - int Receive(CBuffer *, CIp *, int); - - // ICMP receive helper - // parameters: - // buffer - packet receive buffer (starting with ip header) - // ip - remote address (filled in on receive) - // timeout - receive timeout in msec - // return value: - // ICMP type, -1 if nothing was received - - int IcmpReceive(CBuffer *, CIp *, int); - - // write - // no write support - complexity makes it out of scope for now - // to be added if needed + // constructor + CRawSocket(); + + // destructor + ~CRawSocket(); + + // open & close + bool Open(uint16); + void Close(void); + int GetSocket(void) { return m_Socket; } + + // read + + // if ETH_P_ALL is used, the received data buffer will hold + // the ethernet header (struct ethhdr) followed by the IP header (struct iphdr), + // the protocol header (e.g tcp, udp, icmp) and the data. + // For specific protocols, the data content may vary depending on the protocol + // Returns the number of received bytes in buffer + + int Receive(CBuffer *, CIp *, int); + + // ICMP receive helper + // parameters: + // buffer - packet receive buffer (starting with ip header) + // ip - remote address (filled in on receive) + // timeout - receive timeout in msec + // return value: + // ICMP type, -1 if nothing was received + + int IcmpReceive(CBuffer *, CIp *, int); + + // write + // no write support - complexity makes it out of scope for now + // to be added if needed protected: - // data - int m_Socket; - int m_Proto; - struct sockaddr_in m_SocketAddr; + // data + int m_Socket; + int m_Proto; + struct sockaddr_in m_SocketAddr; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/creflector.cpp b/src/creflector.cpp index cf57f1b..b010748 100644 --- a/src/creflector.cpp +++ b/src/creflector.cpp @@ -38,31 +38,31 @@ CReflector::CReflector() { - keep_running = true; - m_XmlReportThread = nullptr; - m_JsonReportThread = nullptr; - for ( int i = 0; i < NB_OF_MODULES; i++ ) - { - m_RouterThreads[i] = nullptr; - } + keep_running = true; + m_XmlReportThread = nullptr; + m_JsonReportThread = nullptr; + for ( int i = 0; i < NB_OF_MODULES; i++ ) + { + m_RouterThreads[i] = nullptr; + } #ifdef DEBUG_DUMPFILE - m_DebugFile.open("/Users/jeanluc/Desktop/xlxdebug.txt"); + m_DebugFile.open("/Users/jeanluc/Desktop/xlxdebug.txt"); #endif } CReflector::CReflector(const CCallsign &callsign) { #ifdef DEBUG_DUMPFILE - m_DebugFile.close(); + m_DebugFile.close(); #endif - keep_running = true; - m_XmlReportThread = nullptr; - m_JsonReportThread = nullptr; - for ( int i = 0; i < NB_OF_MODULES; i++ ) - { - m_RouterThreads[i] = nullptr; - } - m_Callsign = callsign; + keep_running = true; + m_XmlReportThread = nullptr; + m_JsonReportThread = nullptr; + for ( int i = 0; i < NB_OF_MODULES; i++ ) + { + m_RouterThreads[i] = nullptr; + } + m_Callsign = callsign; } //////////////////////////////////////////////////////////////////////////////////////// @@ -70,25 +70,25 @@ CReflector::CReflector(const CCallsign &callsign) CReflector::~CReflector() { - keep_running = false; - if ( m_XmlReportThread != nullptr ) - { - m_XmlReportThread->join(); - delete m_XmlReportThread; - } - if ( m_JsonReportThread != nullptr ) - { - m_JsonReportThread->join(); - delete m_JsonReportThread; - } - for ( int i = 0; i < NB_OF_MODULES; i++ ) - { - if ( m_RouterThreads[i] != nullptr ) - { - m_RouterThreads[i]->join(); - delete m_RouterThreads[i]; - } - } + keep_running = false; + if ( m_XmlReportThread != nullptr ) + { + m_XmlReportThread->join(); + delete m_XmlReportThread; + } + if ( m_JsonReportThread != nullptr ) + { + m_JsonReportThread->join(); + delete m_JsonReportThread; + } + for ( int i = 0; i < NB_OF_MODULES; i++ ) + { + if ( m_RouterThreads[i] != nullptr ) + { + m_RouterThreads[i]->join(); + delete m_RouterThreads[i]; + } + } } @@ -97,28 +97,28 @@ CReflector::~CReflector() bool CReflector::Start(void) { - // let's go! - keep_running = true; + // let's go! + keep_running = true; - // init gate keeper. It can only return true! - g_GateKeeper.Init(); + // init gate keeper. It can only return true! + g_GateKeeper.Init(); #ifndef NO_XLX - // init dmrid directory. No need to check the return value. - g_DmridDir.Init(); + // init dmrid directory. No need to check the return value. + g_DmridDir.Init(); - // init wiresx node directory. Likewise with the return vale. - g_YsfNodeDir.Init(); + // init wiresx node directory. Likewise with the return vale. + g_YsfNodeDir.Init(); #ifdef TRANSCODER_IP - // init the transcoder - if (! g_Transcoder.Init()) + // init the transcoder + if (! g_Transcoder.Init()) return false; #endif #endif - // create protocols - if (! m_Protocols.Init()) + // create protocols + if (! m_Protocols.Init()) { m_Protocols.Close(); return false; @@ -133,57 +133,57 @@ bool CReflector::Start(void) // start the reporting threads m_XmlReportThread = new std::thread(CReflector::XmlReportThread, this); #ifdef JSON_MONITOR - m_JsonReportThread = new std::thread(CReflector::JsonReportThread, this); + m_JsonReportThread = new std::thread(CReflector::JsonReportThread, this); #endif - return true; + return true; } void CReflector::Stop(void) { - // stop & delete all threads - keep_running = false; - - // stop & delete report threads - if ( m_XmlReportThread != nullptr ) - { - m_XmlReportThread->join(); - delete m_XmlReportThread; - m_XmlReportThread = nullptr; - } - if ( m_JsonReportThread != nullptr ) - { - m_JsonReportThread->join(); - delete m_JsonReportThread; - m_JsonReportThread = nullptr; - } - - // stop & delete all router thread - for ( int i = 0; i < NB_OF_MODULES; i++ ) - { - if ( m_RouterThreads[i] != nullptr ) - { - m_RouterThreads[i]->join(); - delete m_RouterThreads[i]; - m_RouterThreads[i] = nullptr; - } - } - - // close protocols - m_Protocols.Close(); - - // close gatekeeper - g_GateKeeper.Close(); + // stop & delete all threads + keep_running = false; + + // stop & delete report threads + if ( m_XmlReportThread != nullptr ) + { + m_XmlReportThread->join(); + delete m_XmlReportThread; + m_XmlReportThread = nullptr; + } + if ( m_JsonReportThread != nullptr ) + { + m_JsonReportThread->join(); + delete m_JsonReportThread; + m_JsonReportThread = nullptr; + } + + // stop & delete all router thread + for ( int i = 0; i < NB_OF_MODULES; i++ ) + { + if ( m_RouterThreads[i] != nullptr ) + { + m_RouterThreads[i]->join(); + delete m_RouterThreads[i]; + m_RouterThreads[i] = nullptr; + } + } + + // close protocols + m_Protocols.Close(); + + // close gatekeeper + g_GateKeeper.Close(); #ifdef TRANSCODER_IP - // close transcoder - g_Transcoder.Close(); + // close transcoder + g_Transcoder.Close(); #endif #ifndef NO_XLX - // close databases - g_DmridDir.Close(); - g_YsfNodeDir.Close(); + // close databases + g_DmridDir.Close(); + g_YsfNodeDir.Close(); #endif } @@ -192,125 +192,126 @@ void CReflector::Stop(void) bool CReflector::IsStreaming(char module) { - return false; + return false; } CPacketStream *CReflector::OpenStream(CDvHeaderPacket *DvHeader, std::shared_ptrclient) { - CPacketStream *retStream = nullptr; - - // clients MUST have bee locked by the caller - // so we can freely access it within the fuction - - // check sid is not nullptr - if ( DvHeader->GetStreamId() != 0 ) - { - // check if client is valid candidate - if ( m_Clients.IsClient(client) && !client->IsAMaster() ) - { - // check if no stream with same streamid already open - // to prevent loops - if ( !IsStreamOpen(DvHeader) ) - { - // get the module's queue - char module = DvHeader->GetRpt2Module(); - CPacketStream *stream = GetStream(module); - if ( stream != nullptr ) - { - // lock it - stream->Lock(); - // is it available ? - if ( stream->Open(*DvHeader, client) ) - { - // stream open, mark client as master - // so that it can't be deleted - client->SetMasterOfModule(module); - - // update last heard time - client->Heard(); - retStream = stream; - - // and push header packet - stream->Push(DvHeader); - - // report + CPacketStream *retStream = nullptr; + + // clients MUST have bee locked by the caller + // so we can freely access it within the fuction + + // check sid is not nullptr + if ( DvHeader->GetStreamId() != 0 ) + { + // check if client is valid candidate + if ( m_Clients.IsClient(client) && !client->IsAMaster() ) + { + // check if no stream with same streamid already open + // to prevent loops + if ( !IsStreamOpen(DvHeader) ) + { + // get the module's queue + char module = DvHeader->GetRpt2Module(); + CPacketStream *stream = GetStream(module); + if ( stream != nullptr ) + { + // lock it + stream->Lock(); + // is it available ? + if ( stream->Open(*DvHeader, client) ) + { + // stream open, mark client as master + // so that it can't be deleted + client->SetMasterOfModule(module); + + // update last heard time + client->Heard(); + retStream = stream; + + // and push header packet + stream->Push(DvHeader); + + // report std::cout << "Opening stream on module " << module << " for client " << client->GetCallsign() << " with sid " << DvHeader->GetStreamId() << " by user " << DvHeader->GetMyCallsign() << std::endl; - // notify - g_Reflector.OnStreamOpen(stream->GetUserCallsign()); - - } - // unlock now - stream->Unlock(); - } - } - else - { - // report - std::cerr << "Detected stream loop on module " << DvHeader->GetRpt2Module() << " for client " << client->GetCallsign() << " with sid " << DvHeader->GetStreamId() << std::endl; - } - } - } - - // done - return retStream; + // notify + g_Reflector.OnStreamOpen(stream->GetUserCallsign()); + + } + // unlock now + stream->Unlock(); + } + } + else + { + // report + std::cerr << "Detected stream loop on module " << DvHeader->GetRpt2Module() << " for client " << client->GetCallsign() << " with sid " << DvHeader->GetStreamId() << std::endl; + } + } + } + + // done + return retStream; } void CReflector::CloseStream(CPacketStream *stream) { - // - if ( stream != nullptr ) - { - // wait queue is empty - // this waits forever - bool bEmpty = false; - do - { - stream->Lock(); - // do not use stream->IsEmpty() has this "may" never succeed - // and anyway, the DvLastFramPacket short-circuit the transcoder - // loop queues - bEmpty = stream->empty(); - stream->Unlock(); - if ( !bEmpty ) - { - // wait a bit - CTimePoint::TaskSleepFor(10); - } - } while (!bEmpty); - - // lock clients - GetClients(); - - // lock stream - stream->Lock(); - - // get and check the master - std::shared_ptrclient = stream->GetOwnerClient(); - if ( client != nullptr ) - { - // client no longer a master - client->NotAMaster(); - - // notify - g_Reflector.OnStreamClose(stream->GetUserCallsign()); - - std::cout << "Closing stream of module " << GetStreamModule(stream) << std::endl; - } - - // release clients - ReleaseClients(); - - // unlock before closing - // to avoid double lock in assiociated - // codecstream close/thread-join - stream->Unlock(); - - // and stop the queue - stream->Close(); - - - } + // + if ( stream != nullptr ) + { + // wait queue is empty + // this waits forever + bool bEmpty = false; + do + { + stream->Lock(); + // do not use stream->IsEmpty() has this "may" never succeed + // and anyway, the DvLastFramPacket short-circuit the transcoder + // loop queues + bEmpty = stream->empty(); + stream->Unlock(); + if ( !bEmpty ) + { + // wait a bit + CTimePoint::TaskSleepFor(10); + } + } + while (!bEmpty); + + // lock clients + GetClients(); + + // lock stream + stream->Lock(); + + // get and check the master + std::shared_ptrclient = stream->GetOwnerClient(); + if ( client != nullptr ) + { + // client no longer a master + client->NotAMaster(); + + // notify + g_Reflector.OnStreamClose(stream->GetUserCallsign()); + + std::cout << "Closing stream of module " << GetStreamModule(stream) << std::endl; + } + + // release clients + ReleaseClients(); + + // unlock before closing + // to avoid double lock in assiociated + // codecstream close/thread-join + stream->Unlock(); + + // and stop the queue + stream->Close(); + + + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -318,66 +319,66 @@ void CReflector::CloseStream(CPacketStream *stream) void CReflector::RouterThread(CReflector *This, CPacketStream *streamIn) { - // get our module - uint8 uiModuleId = This->GetStreamModule(streamIn); - - // get on input queue - CPacket *packet; - - while (This->keep_running) - { - // any packet in our input queue ? - streamIn->Lock(); - if ( !streamIn->empty() ) - { - // get the packet - packet = streamIn->front(); - streamIn->pop(); - } - else - { - packet = nullptr; - } - streamIn->Unlock(); - - // route it - if ( packet != nullptr ) - { - // set origin - packet->SetModuleId(uiModuleId); - - // iterate on all protocols + // get our module + uint8 uiModuleId = This->GetStreamModule(streamIn); + + // get on input queue + CPacket *packet; + + while (This->keep_running) + { + // any packet in our input queue ? + streamIn->Lock(); + if ( !streamIn->empty() ) + { + // get the packet + packet = streamIn->front(); + streamIn->pop(); + } + else + { + packet = nullptr; + } + streamIn->Unlock(); + + // route it + if ( packet != nullptr ) + { + // set origin + packet->SetModuleId(uiModuleId); + + // iterate on all protocols This->m_Protocols.Lock(); - for ( auto it=This->m_Protocols.begin(); it!=This->m_Protocols.end(); it++ ) - { - // duplicate packet - CPacket *packetClone = packet->Duplicate(); - - // if packet is header, update RPT2 according to protocol - if ( packetClone->IsDvHeader() ) - { - // get our callsign - CCallsign csRPT = (*it)->GetReflectorCallsign(); - csRPT.SetModule(This->GetStreamModule(streamIn)); - ((CDvHeaderPacket *)packetClone)->SetRpt2Callsign(csRPT); - } - - // and push it - CPacketQueue *queue = (*it)->GetQueue(); - queue->push(packetClone); - (*it)->ReleaseQueue(); - } + for ( auto it=This->m_Protocols.begin(); it!=This->m_Protocols.end(); it++ ) + { + // duplicate packet + CPacket *packetClone = packet->Duplicate(); + + // if packet is header, update RPT2 according to protocol + if ( packetClone->IsDvHeader() ) + { + // get our callsign + CCallsign csRPT = (*it)->GetReflectorCallsign(); + csRPT.SetModule(This->GetStreamModule(streamIn)); + ((CDvHeaderPacket *)packetClone)->SetRpt2Callsign(csRPT); + } + + // and push it + CPacketQueue *queue = (*it)->GetQueue(); + queue->push(packetClone); + (*it)->ReleaseQueue(); + } This->m_Protocols.Unlock(); - // done - delete packet; - packet = nullptr; - } - else - { - // wait a bit - CTimePoint::TaskSleepFor(10); - } - } + // done + delete packet; + packet = nullptr; + } + else + { + // wait a bit + CTimePoint::TaskSleepFor(10); + } + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -385,123 +386,123 @@ void CReflector::RouterThread(CReflector *This, CPacketStream *streamIn) void CReflector::XmlReportThread(CReflector *This) { - while (This->keep_running) - { - // report to xml file - std::ofstream xmlFile; - xmlFile.open(XML_PATH, std::ios::out | std::ios::trunc); - if ( xmlFile.is_open() ) - { - // write xml file - This->WriteXmlFile(xmlFile); - - // and close file - xmlFile.close(); - } + while (This->keep_running) + { + // report to xml file + std::ofstream xmlFile; + xmlFile.open(XML_PATH, std::ios::out | std::ios::trunc); + if ( xmlFile.is_open() ) + { + // write xml file + This->WriteXmlFile(xmlFile); + + // and close file + xmlFile.close(); + } #ifndef DEBUG_NO_ERROR_ON_XML_OPEN_FAIL - else - { - std::cout << "Failed to open " << XML_PATH << std::endl; - } + else + { + std::cout << "Failed to open " << XML_PATH << std::endl; + } #endif - // and wait a bit + // and wait a bit for (int i=0; i< XML_UPDATE_PERIOD && This->keep_running; i++) - CTimePoint::TaskSleepFor(1000); - } + CTimePoint::TaskSleepFor(1000); + } } #ifdef JSON_MONITOR void CReflector::JsonReportThread(CReflector *This) { - CUdpSocket Socket; - CBuffer Buffer; - CIp Ip; - bool bOn; - - // init variable - bOn = false; - - // create listening socket - if ( Socket.Open(JSON_PORT) ) - { - // and loop - while (This->keep_running) - { - // any command ? - if ( Socket.Receive(Buffer, Ip, 50) ) - { - // check verb - if ( Buffer.Compare((uint8 *)"hello", 5) == 0 ) - { - std::cout << "Monitor socket connected with " << Ip << std::endl; - - // connected - bOn = true; - - // announce ourselves - This->SendJsonReflectorObject(Socket, Ip); + CUdpSocket Socket; + CBuffer Buffer; + CIp Ip; + bool bOn; + + // init variable + bOn = false; + + // create listening socket + if ( Socket.Open(JSON_PORT) ) + { + // and loop + while (This->keep_running) + { + // any command ? + if ( Socket.Receive(Buffer, Ip, 50) ) + { + // check verb + if ( Buffer.Compare((uint8 *)"hello", 5) == 0 ) + { + std::cout << "Monitor socket connected with " << Ip << std::endl; + + // connected + bOn = true; + + // announce ourselves + This->SendJsonReflectorObject(Socket, Ip); // dump tables This->SendJsonNodesObject(Socket, Ip); This->SendJsonStationsObject(Socket, Ip); - } - else if ( Buffer.Compare((uint8 *)"bye", 3) == 0 ) - { - std::cout << "Monitor socket disconnected" << std::endl; - - // diconnected - bOn = false; - } - } - - // any notifications ? - CNotification notification; - This->m_Notifications.Lock(); - if ( !This->m_Notifications.empty() ) - { - // get the packet - notification = This->m_Notifications.front(); - This->m_Notifications.pop(); - } - This->m_Notifications.Unlock(); - - // handle it - if ( bOn ) - { - switch ( notification.GetId() ) - { - case NOTIFICATION_CLIENTS: - case NOTIFICATION_PEERS: - //std::cout << "Monitor updating nodes table" << std::endl; - This->SendJsonNodesObject(Socket, Ip); - break; - case NOTIFICATION_USERS: - //std::cout << "Monitor updating stations table" << std::endl; - This->SendJsonStationsObject(Socket, Ip); - break; - case NOTIFICATION_STREAM_OPEN: - //std::cout << "Monitor notify station " << notification.GetCallsign() << "going ON air" << std::endl; - This->SendJsonStationsObject(Socket, Ip); - This->SendJsonOnairObject(Socket, Ip, notification.GetCallsign()); - break; - case NOTIFICATION_STREAM_CLOSE: - //std::cout << "Monitor notify station " << notification.GetCallsign() << "going OFF air" << std::endl; - This->SendJsonOffairObject(Socket, Ip, notification.GetCallsign()); - break; - case NOTIFICATION_NONE: - default: - // nothing to do, just sleep a bit - CTimePoint::TaskSleepFor(250); - break; - } - } - } - } - else - { - std::cout << "Error creating monitor socket" << std::endl; - } + } + else if ( Buffer.Compare((uint8 *)"bye", 3) == 0 ) + { + std::cout << "Monitor socket disconnected" << std::endl; + + // diconnected + bOn = false; + } + } + + // any notifications ? + CNotification notification; + This->m_Notifications.Lock(); + if ( !This->m_Notifications.empty() ) + { + // get the packet + notification = This->m_Notifications.front(); + This->m_Notifications.pop(); + } + This->m_Notifications.Unlock(); + + // handle it + if ( bOn ) + { + switch ( notification.GetId() ) + { + case NOTIFICATION_CLIENTS: + case NOTIFICATION_PEERS: + //std::cout << "Monitor updating nodes table" << std::endl; + This->SendJsonNodesObject(Socket, Ip); + break; + case NOTIFICATION_USERS: + //std::cout << "Monitor updating stations table" << std::endl; + This->SendJsonStationsObject(Socket, Ip); + break; + case NOTIFICATION_STREAM_OPEN: + //std::cout << "Monitor notify station " << notification.GetCallsign() << "going ON air" << std::endl; + This->SendJsonStationsObject(Socket, Ip); + This->SendJsonOnairObject(Socket, Ip, notification.GetCallsign()); + break; + case NOTIFICATION_STREAM_CLOSE: + //std::cout << "Monitor notify station " << notification.GetCallsign() << "going OFF air" << std::endl; + This->SendJsonOffairObject(Socket, Ip, notification.GetCallsign()); + break; + case NOTIFICATION_NONE: + default: + // nothing to do, just sleep a bit + CTimePoint::TaskSleepFor(250); + break; + } + } + } + } + else + { + std::cout << "Error creating monitor socket" << std::endl; + } } #endif @@ -510,47 +511,47 @@ void CReflector::JsonReportThread(CReflector *This) void CReflector::OnPeersChanged(void) { - CNotification notification(NOTIFICATION_PEERS); + CNotification notification(NOTIFICATION_PEERS); - m_Notifications.Lock(); - m_Notifications.push(notification); - m_Notifications.Unlock(); + m_Notifications.Lock(); + m_Notifications.push(notification); + m_Notifications.Unlock(); } void CReflector::OnClientsChanged(void) { - CNotification notification(NOTIFICATION_CLIENTS); + CNotification notification(NOTIFICATION_CLIENTS); - m_Notifications.Lock(); - m_Notifications.push(notification); - m_Notifications.Unlock(); + m_Notifications.Lock(); + m_Notifications.push(notification); + m_Notifications.Unlock(); } void CReflector::OnUsersChanged(void) { - CNotification notification(NOTIFICATION_USERS); + CNotification notification(NOTIFICATION_USERS); - m_Notifications.Lock(); - m_Notifications.push(notification); - m_Notifications.Unlock(); + m_Notifications.Lock(); + m_Notifications.push(notification); + m_Notifications.Unlock(); } void CReflector::OnStreamOpen(const CCallsign &callsign) { - CNotification notification(NOTIFICATION_STREAM_OPEN, callsign); + CNotification notification(NOTIFICATION_STREAM_OPEN, callsign); - m_Notifications.Lock(); - m_Notifications.push(notification); - m_Notifications.Unlock(); + m_Notifications.Lock(); + m_Notifications.push(notification); + m_Notifications.Unlock(); } void CReflector::OnStreamClose(const CCallsign &callsign) { - CNotification notification(NOTIFICATION_STREAM_CLOSE, callsign); + CNotification notification(NOTIFICATION_STREAM_CLOSE, callsign); - m_Notifications.Lock(); - m_Notifications.push(notification); - m_Notifications.Unlock(); + m_Notifications.Lock(); + m_Notifications.push(notification); + m_Notifications.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -558,47 +559,47 @@ void CReflector::OnStreamClose(const CCallsign &callsign) int CReflector::GetModuleIndex(char module) const { - int i = (int)module - (int)'A'; - if ( (i < 0) || (i >= NB_OF_MODULES) ) - { - i = -1; - } - return i; + int i = (int)module - (int)'A'; + if ( (i < 0) || (i >= NB_OF_MODULES) ) + { + i = -1; + } + return i; } CPacketStream *CReflector::GetStream(char module) { - CPacketStream *stream = nullptr; - int i = GetModuleIndex(module); - if ( i >= 0 ) - { - stream = &(m_Streams[i]); - } - return stream; + CPacketStream *stream = nullptr; + int i = GetModuleIndex(module); + if ( i >= 0 ) + { + stream = &(m_Streams[i]); + } + return stream; } bool CReflector::IsStreamOpen(const CDvHeaderPacket *DvHeader) { - bool open = false; - for ( unsigned i = 0; (i < m_Streams.size()) && !open; i++ ) - { - open = ( (m_Streams[i].GetStreamId() == DvHeader->GetStreamId()) && - (m_Streams[i].IsOpen())); - } - return open; + bool open = false; + for ( unsigned i = 0; (i < m_Streams.size()) && !open; i++ ) + { + open = ( (m_Streams[i].GetStreamId() == DvHeader->GetStreamId()) && + (m_Streams[i].IsOpen())); + } + return open; } char CReflector::GetStreamModule(CPacketStream *stream) { - char module = ' '; - for ( unsigned i = 0; (i < m_Streams.size()) && (module == ' '); i++ ) - { - if ( &(m_Streams[i]) == stream ) - { - module = GetModuleLetter(i); - } - } - return module; + char module = ' '; + for ( unsigned i = 0; (i < m_Streams.size()) && (module == ' '); i++ ) + { + if ( &(m_Streams[i]) == stream ) + { + module = GetModuleLetter(i); + } + } + return module; } //////////////////////////////////////////////////////////////////////////////////////// @@ -606,55 +607,55 @@ char CReflector::GetStreamModule(CPacketStream *stream) void CReflector::WriteXmlFile(std::ofstream &xmlFile) { - // write header - xmlFile << "" << std::endl; - - // software version - char sz[64]; - ::sprintf(sz, "%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION); - xmlFile << "" << sz << "" << std::endl; - - // linked peers - xmlFile << "<" << m_Callsign << "linked peers>" << std::endl; - // lock - CPeers *peers = GetPeers(); - // iterate on peers - for ( auto pit=peers->cbegin(); pit!=peers->cend(); pit++ ) - { - (*pit)->WriteXml(xmlFile); - } - // unlock - ReleasePeers(); - xmlFile << "" << std::endl; - - // linked nodes - xmlFile << "<" << m_Callsign << "linked nodes>" << std::endl; - // lock - CClients *clients = GetClients(); - // iterate on clients - for ( auto cit=clients->cbegin(); cit!=clients->cend(); cit++ ) - { - if ( (*cit)->IsNode() ) - { - (*cit)->WriteXml(xmlFile); - } - } - // unlock - ReleaseClients(); - xmlFile << "" << std::endl; - - // last heard users - xmlFile << "<" << m_Callsign << "heard users>" << std::endl; - // lock - CUsers *users = GetUsers(); - // iterate on users - for ( auto it=users->begin(); it!=users->end(); it++ ) - { - (*it).WriteXml(xmlFile); - } - // unlock - ReleaseUsers(); - xmlFile << "" << std::endl; + // write header + xmlFile << "" << std::endl; + + // software version + char sz[64]; + ::sprintf(sz, "%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION); + xmlFile << "" << sz << "" << std::endl; + + // linked peers + xmlFile << "<" << m_Callsign << "linked peers>" << std::endl; + // lock + CPeers *peers = GetPeers(); + // iterate on peers + for ( auto pit=peers->cbegin(); pit!=peers->cend(); pit++ ) + { + (*pit)->WriteXml(xmlFile); + } + // unlock + ReleasePeers(); + xmlFile << "" << std::endl; + + // linked nodes + xmlFile << "<" << m_Callsign << "linked nodes>" << std::endl; + // lock + CClients *clients = GetClients(); + // iterate on clients + for ( auto cit=clients->cbegin(); cit!=clients->cend(); cit++ ) + { + if ( (*cit)->IsNode() ) + { + (*cit)->WriteXml(xmlFile); + } + } + // unlock + ReleaseClients(); + xmlFile << "" << std::endl; + + // last heard users + xmlFile << "<" << m_Callsign << "heard users>" << std::endl; + // lock + CUsers *users = GetUsers(); + // iterate on users + for ( auto it=users->begin(); it!=users->end(); it++ ) + { + (*it).WriteXml(xmlFile); + } + // unlock + ReleaseUsers(); + xmlFile << "" << std::endl; } @@ -665,28 +666,28 @@ void CReflector::WriteXmlFile(std::ofstream &xmlFile) void CReflector::SendJsonReflectorObject(CUdpSocket &Socket, CIp &Ip) { char Buffer[1024]; - char cs[CALLSIGN_LEN+1]; - char mod[8] = "\"A\""; + char cs[CALLSIGN_LEN+1]; + char mod[8] = "\"A\""; - // get reflector callsign - m_Callsign.GetCallsign((uint8 *)cs); - cs[CALLSIGN_LEN] = 0; + // get reflector callsign + m_Callsign.GetCallsign((uint8 *)cs); + cs[CALLSIGN_LEN] = 0; // build string ::sprintf(Buffer, "{\"reflector\":\"%s\",\"modules\":[", cs); - for ( int i = 0; i < NB_OF_MODULES; i++ ) - { - ::strcat(Buffer, mod); - mod[1]++; - if ( i < NB_OF_MODULES-1 ) - { - ::strcat(Buffer, ","); - } - } - ::strcat(Buffer, "]}"); - - // and send - Socket.Send(Buffer, Ip); + for ( int i = 0; i < NB_OF_MODULES; i++ ) + { + ::strcat(Buffer, mod); + mod[1]++; + if ( i < NB_OF_MODULES-1 ) + { + ::strcat(Buffer, ","); + } + } + ::strcat(Buffer, "]}"); + + // and send + Socket.Send(Buffer, Ip); } #define JSON_NBMAX_NODES 250 @@ -695,81 +696,81 @@ void CReflector::SendJsonNodesObject(CUdpSocket &Socket, CIp &Ip) { char Buffer[12+(JSON_NBMAX_NODES*94)]; - // nodes object table - ::sprintf(Buffer, "{\"nodes\":["); - // lock - CClients *clients = GetClients(); - // iterate on clients - for ( auto it=clients->cbegin(); it!=clients->cend(); ) - { - (*it++)->GetJsonObject(Buffer); - if ( it != clients->cend() ) - { - ::strcat(Buffer, ","); - } - } - // unlock - ReleaseClients(); - ::strcat(Buffer, "]}"); - - // and send - //std::cout << Buffer << std::endl; - Socket.Send(Buffer, Ip); + // nodes object table + ::sprintf(Buffer, "{\"nodes\":["); + // lock + CClients *clients = GetClients(); + // iterate on clients + for ( auto it=clients->cbegin(); it!=clients->cend(); ) + { + (*it++)->GetJsonObject(Buffer); + if ( it != clients->cend() ) + { + ::strcat(Buffer, ","); + } + } + // unlock + ReleaseClients(); + ::strcat(Buffer, "]}"); + + // and send + //std::cout << Buffer << std::endl; + Socket.Send(Buffer, Ip); } void CReflector::SendJsonStationsObject(CUdpSocket &Socket, CIp &Ip) { char Buffer[15+(LASTHEARD_USERS_MAX_SIZE*94)]; - // stations object table - ::sprintf(Buffer, "{\"stations\":["); - - // lock - CUsers *users = GetUsers(); - // iterate on users - for ( auto it=users->begin(); it!=users->end(); ) - { - (*it++).GetJsonObject(Buffer); - if ( it != users->end() ) - { - ::strcat(Buffer, ","); - } - } - // unlock - ReleaseUsers(); - - ::strcat(Buffer, "]}"); - - // and send - //std::cout << Buffer << std::endl; - Socket.Send(Buffer, Ip); + // stations object table + ::sprintf(Buffer, "{\"stations\":["); + + // lock + CUsers *users = GetUsers(); + // iterate on users + for ( auto it=users->begin(); it!=users->end(); ) + { + (*it++).GetJsonObject(Buffer); + if ( it != users->end() ) + { + ::strcat(Buffer, ","); + } + } + // unlock + ReleaseUsers(); + + ::strcat(Buffer, "]}"); + + // and send + //std::cout << Buffer << std::endl; + Socket.Send(Buffer, Ip); } void CReflector::SendJsonOnairObject(CUdpSocket &Socket, CIp &Ip, const CCallsign &Callsign) { - char Buffer[128]; - char sz[CALLSIGN_LEN+1]; + char Buffer[128]; + char sz[CALLSIGN_LEN+1]; - // onair object - Callsign.GetCallsignString(sz); - ::sprintf(Buffer, "{\"onair\":\"%s\"}", sz); + // onair object + Callsign.GetCallsignString(sz); + ::sprintf(Buffer, "{\"onair\":\"%s\"}", sz); - // and send - //std::cout << Buffer << std::endl; - Socket.Send(Buffer, Ip); + // and send + //std::cout << Buffer << std::endl; + Socket.Send(Buffer, Ip); } void CReflector::SendJsonOffairObject(CUdpSocket &Socket, CIp &Ip, const CCallsign &Callsign) { - char Buffer[128]; - char sz[CALLSIGN_LEN+1]; + char Buffer[128]; + char sz[CALLSIGN_LEN+1]; - // offair object - Callsign.GetCallsignString(sz); - ::sprintf(Buffer, "{\"offair\":\"%s\"}", sz); + // offair object + Callsign.GetCallsignString(sz); + ::sprintf(Buffer, "{\"offair\":\"%s\"}", sz); - // and send - //std::cout << Buffer << std::endl; - Socket.Send(Buffer, Ip); + // and send + //std::cout << Buffer << std::endl; + Socket.Send(Buffer, Ip); } #endif diff --git a/src/creflector.h b/src/creflector.h index 485ca6a..8ae51e6 100644 --- a/src/creflector.h +++ b/src/creflector.h @@ -48,95 +48,95 @@ class CReflector { public: - // constructor - CReflector(); - CReflector(const CCallsign &); + // constructor + CReflector(); + CReflector(const CCallsign &); - // destructor - virtual ~CReflector(); + // destructor + virtual ~CReflector(); - // settings - void SetCallsign(const CCallsign &callsign) { m_Callsign = callsign; } - const CCallsign &GetCallsign(void) const { return m_Callsign; } + // settings + void SetCallsign(const CCallsign &callsign) { m_Callsign = callsign; } + const CCallsign &GetCallsign(void) const { return m_Callsign; } #ifdef LISTEN_IPV4 - void SetListenIPv4(const char *a, const int n) { memset(m_IPv4, 0, n); strncpy(m_IPv4, a, n-1); } - const char *GetListenIPv4(void) const { return m_IPv4; } + void SetListenIPv4(const char *a, const int n) { memset(m_IPv4, 0, n); strncpy(m_IPv4, a, n-1); } + const char *GetListenIPv4(void) const { return m_IPv4; } #endif #ifdef LISTEN_IPV6 - void SetListenIPv6(const char *a, const int n) { memset(m_IPv6, 0, n); strncpy(m_IPv6, a, n-1); } - const char *GetListenIPv6(void) const { return m_IPv6; } + void SetListenIPv6(const char *a, const int n) { memset(m_IPv6, 0, n); strncpy(m_IPv6, a, n-1); } + const char *GetListenIPv6(void) const { return m_IPv6; } #endif #ifdef TRANSCODER_IP - void SetTranscoderIp(const char *a, const int n) { memset(m_AmbedIp, 0, n); strncpy(m_AmbedIp, a, n-1); } - const char *GetTranscoderIp(void) const { return m_AmbedIp; } + void SetTranscoderIp(const char *a, const int n) { memset(m_AmbedIp, 0, n); strncpy(m_AmbedIp, a, n-1); } + const char *GetTranscoderIp(void) const { return m_AmbedIp; } #endif - // operation - bool Start(void); - void Stop(void); + // operation + bool Start(void); + void Stop(void); - // clients - CClients *GetClients(void) { m_Clients.Lock(); return &m_Clients; } - void ReleaseClients(void) { m_Clients.Unlock(); } + // clients + CClients *GetClients(void) { m_Clients.Lock(); return &m_Clients; } + void ReleaseClients(void) { m_Clients.Unlock(); } - // peers - CPeers *GetPeers(void) { m_Peers.Lock(); return &m_Peers; } - void ReleasePeers(void) { m_Peers.Unlock(); } + // peers + CPeers *GetPeers(void) { m_Peers.Lock(); return &m_Peers; } + void ReleasePeers(void) { m_Peers.Unlock(); } - // stream opening & closing - CPacketStream *OpenStream(CDvHeaderPacket *, std::shared_ptr); - bool IsStreaming(char); - void CloseStream(CPacketStream *); + // stream opening & closing + CPacketStream *OpenStream(CDvHeaderPacket *, std::shared_ptr); + bool IsStreaming(char); + void CloseStream(CPacketStream *); - // users - CUsers *GetUsers(void) { m_Users.Lock(); return &m_Users; } - void ReleaseUsers(void) { m_Users.Unlock(); } + // users + CUsers *GetUsers(void) { m_Users.Lock(); return &m_Users; } + void ReleaseUsers(void) { m_Users.Unlock(); } - // get - bool IsValidModule(char c) const { return (GetModuleIndex(c) >= 0); } - int GetModuleIndex(char) const; - char GetModuleLetter(int i) const { return 'A' + (char)i; } + // get + bool IsValidModule(char c) const { return (GetModuleIndex(c) >= 0); } + int GetModuleIndex(char) const; + char GetModuleLetter(int i) const { return 'A' + (char)i; } - // notifications - void OnPeersChanged(void); - void OnClientsChanged(void); - void OnUsersChanged(void); - void OnStreamOpen(const CCallsign &); - void OnStreamClose(const CCallsign &); + // notifications + void OnPeersChanged(void); + void OnClientsChanged(void); + void OnUsersChanged(void); + void OnStreamOpen(const CCallsign &); + void OnStreamClose(const CCallsign &); protected: - // threads - static void RouterThread(CReflector *, CPacketStream *); - static void XmlReportThread(CReflector *); + // threads + static void RouterThread(CReflector *, CPacketStream *); + static void XmlReportThread(CReflector *); #ifdef JSON_MONITOR - static void JsonReportThread(CReflector *); + static void JsonReportThread(CReflector *); #endif - // streams - CPacketStream *GetStream(char); - bool IsStreamOpen(const CDvHeaderPacket *); - char GetStreamModule(CPacketStream *); + // streams + CPacketStream *GetStream(char); + bool IsStreamOpen(const CDvHeaderPacket *); + char GetStreamModule(CPacketStream *); - // xml helpers - void WriteXmlFile(std::ofstream &); + // xml helpers + void WriteXmlFile(std::ofstream &); #ifdef JSON_MONITOR - // json helpers - void SendJsonReflectorObject(CUdpSocket &, CIp &); - void SendJsonNodesObject(CUdpSocket &, CIp &); - void SendJsonStationsObject(CUdpSocket &, CIp &); - void SendJsonOnairObject(CUdpSocket &, CIp &, const CCallsign &); - void SendJsonOffairObject(CUdpSocket &, CIp &, const CCallsign &); + // json helpers + void SendJsonReflectorObject(CUdpSocket &, CIp &); + void SendJsonNodesObject(CUdpSocket &, CIp &); + void SendJsonStationsObject(CUdpSocket &, CIp &); + void SendJsonOnairObject(CUdpSocket &, CIp &, const CCallsign &); + void SendJsonOffairObject(CUdpSocket &, CIp &, const CCallsign &); #endif protected: - // identity - CCallsign m_Callsign; + // identity + CCallsign m_Callsign; #ifdef LISTEN_IPV4 - char m_IPv4[INET_ADDRSTRLEN]; + char m_IPv4[INET_ADDRSTRLEN]; #endif #ifdef LISTEN_IPV6 char m_IPv6[INET6_ADDRSTRLEN]; @@ -145,27 +145,27 @@ protected: char m_AmbedIp[INET6_ADDRSTRLEN]; #endif - // objects - CUsers m_Users; // sorted list of lastheard stations - CClients m_Clients; // list of linked repeaters/nodes/peers's modules - CPeers m_Peers; // list of linked peers - CProtocols m_Protocols; // list of supported protocol handlers + // objects + CUsers m_Users; // sorted list of lastheard stations + CClients m_Clients; // list of linked repeaters/nodes/peers's modules + CPeers m_Peers; // list of linked peers + CProtocols m_Protocols; // list of supported protocol handlers - // queues - std::array m_Streams; + // queues + std::array m_Streams; - // threads - std::atomic keep_running; - std::array m_RouterThreads; - std::thread *m_XmlReportThread; - std::thread *m_JsonReportThread; + // threads + std::atomic keep_running; + std::array m_RouterThreads; + std::thread *m_XmlReportThread; + std::thread *m_JsonReportThread; - // notifications - CNotificationQueue m_Notifications; + // notifications + CNotificationQueue m_Notifications; public: #ifdef DEBUG_DUMPFILE - std::ofstream m_DebugFile; + std::ofstream m_DebugFile; #endif }; diff --git a/src/crs129.cpp b/src/crs129.cpp index 39e8d4e..9f87700 100644 --- a/src/crs129.cpp +++ b/src/crs129.cpp @@ -30,68 +30,72 @@ const unsigned int NPAR = 3U; /* Generator Polynomial */ const unsigned char POLY[] = {64U, 56U, 14U, 1U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U}; -const unsigned char EXP_TABLE[] = { - 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, 0x1DU, 0x3AU, 0x74U, 0xE8U, 0xCDU, 0x87U, 0x13U, 0x26U, - 0x4CU, 0x98U, 0x2DU, 0x5AU, 0xB4U, 0x75U, 0xEAU, 0xC9U, 0x8FU, 0x03U, 0x06U, 0x0CU, 0x18U, 0x30U, 0x60U, 0xC0U, - 0x9DU, 0x27U, 0x4EU, 0x9CU, 0x25U, 0x4AU, 0x94U, 0x35U, 0x6AU, 0xD4U, 0xB5U, 0x77U, 0xEEU, 0xC1U, 0x9FU, 0x23U, - 0x46U, 0x8CU, 0x05U, 0x0AU, 0x14U, 0x28U, 0x50U, 0xA0U, 0x5DU, 0xBAU, 0x69U, 0xD2U, 0xB9U, 0x6FU, 0xDEU, 0xA1U, - 0x5FU, 0xBEU, 0x61U, 0xC2U, 0x99U, 0x2FU, 0x5EU, 0xBCU, 0x65U, 0xCAU, 0x89U, 0x0FU, 0x1EU, 0x3CU, 0x78U, 0xF0U, - 0xFDU, 0xE7U, 0xD3U, 0xBBU, 0x6BU, 0xD6U, 0xB1U, 0x7FU, 0xFEU, 0xE1U, 0xDFU, 0xA3U, 0x5BU, 0xB6U, 0x71U, 0xE2U, - 0xD9U, 0xAFU, 0x43U, 0x86U, 0x11U, 0x22U, 0x44U, 0x88U, 0x0DU, 0x1AU, 0x34U, 0x68U, 0xD0U, 0xBDU, 0x67U, 0xCEU, - 0x81U, 0x1FU, 0x3EU, 0x7CU, 0xF8U, 0xEDU, 0xC7U, 0x93U, 0x3BU, 0x76U, 0xECU, 0xC5U, 0x97U, 0x33U, 0x66U, 0xCCU, - 0x85U, 0x17U, 0x2EU, 0x5CU, 0xB8U, 0x6DU, 0xDAU, 0xA9U, 0x4FU, 0x9EU, 0x21U, 0x42U, 0x84U, 0x15U, 0x2AU, 0x54U, - 0xA8U, 0x4DU, 0x9AU, 0x29U, 0x52U, 0xA4U, 0x55U, 0xAAU, 0x49U, 0x92U, 0x39U, 0x72U, 0xE4U, 0xD5U, 0xB7U, 0x73U, - 0xE6U, 0xD1U, 0xBFU, 0x63U, 0xC6U, 0x91U, 0x3FU, 0x7EU, 0xFCU, 0xE5U, 0xD7U, 0xB3U, 0x7BU, 0xF6U, 0xF1U, 0xFFU, - 0xE3U, 0xDBU, 0xABU, 0x4BU, 0x96U, 0x31U, 0x62U, 0xC4U, 0x95U, 0x37U, 0x6EU, 0xDCU, 0xA5U, 0x57U, 0xAEU, 0x41U, - 0x82U, 0x19U, 0x32U, 0x64U, 0xC8U, 0x8DU, 0x07U, 0x0EU, 0x1CU, 0x38U, 0x70U, 0xE0U, 0xDDU, 0xA7U, 0x53U, 0xA6U, - 0x51U, 0xA2U, 0x59U, 0xB2U, 0x79U, 0xF2U, 0xF9U, 0xEFU, 0xC3U, 0x9BU, 0x2BU, 0x56U, 0xACU, 0x45U, 0x8AU, 0x09U, - 0x12U, 0x24U, 0x48U, 0x90U, 0x3DU, 0x7AU, 0xF4U, 0xF5U, 0xF7U, 0xF3U, 0xFBU, 0xEBU, 0xCBU, 0x8BU, 0x0BU, 0x16U, - 0x2CU, 0x58U, 0xB0U, 0x7DU, 0xFAU, 0xE9U, 0xCFU, 0x83U, 0x1BU, 0x36U, 0x6CU, 0xD8U, 0xADU, 0x47U, 0x8EU, 0x01U, - 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, 0x1DU, 0x3AU, 0x74U, 0xE8U, 0xCDU, 0x87U, 0x13U, 0x26U, 0x4CU, - 0x98U, 0x2DU, 0x5AU, 0xB4U, 0x75U, 0xEAU, 0xC9U, 0x8FU, 0x03U, 0x06U, 0x0CU, 0x18U, 0x30U, 0x60U, 0xC0U, 0x9DU, - 0x27U, 0x4EU, 0x9CU, 0x25U, 0x4AU, 0x94U, 0x35U, 0x6AU, 0xD4U, 0xB5U, 0x77U, 0xEEU, 0xC1U, 0x9FU, 0x23U, 0x46U, - 0x8CU, 0x05U, 0x0AU, 0x14U, 0x28U, 0x50U, 0xA0U, 0x5DU, 0xBAU, 0x69U, 0xD2U, 0xB9U, 0x6FU, 0xDEU, 0xA1U, 0x5FU, - 0xBEU, 0x61U, 0xC2U, 0x99U, 0x2FU, 0x5EU, 0xBCU, 0x65U, 0xCAU, 0x89U, 0x0FU, 0x1EU, 0x3CU, 0x78U, 0xF0U, 0xFDU, - 0xE7U, 0xD3U, 0xBBU, 0x6BU, 0xD6U, 0xB1U, 0x7FU, 0xFEU, 0xE1U, 0xDFU, 0xA3U, 0x5BU, 0xB6U, 0x71U, 0xE2U, 0xD9U, - 0xAFU, 0x43U, 0x86U, 0x11U, 0x22U, 0x44U, 0x88U, 0x0DU, 0x1AU, 0x34U, 0x68U, 0xD0U, 0xBDU, 0x67U, 0xCEU, 0x81U, - 0x1FU, 0x3EU, 0x7CU, 0xF8U, 0xEDU, 0xC7U, 0x93U, 0x3BU, 0x76U, 0xECU, 0xC5U, 0x97U, 0x33U, 0x66U, 0xCCU, 0x85U, - 0x17U, 0x2EU, 0x5CU, 0xB8U, 0x6DU, 0xDAU, 0xA9U, 0x4FU, 0x9EU, 0x21U, 0x42U, 0x84U, 0x15U, 0x2AU, 0x54U, 0xA8U, - 0x4DU, 0x9AU, 0x29U, 0x52U, 0xA4U, 0x55U, 0xAAU, 0x49U, 0x92U, 0x39U, 0x72U, 0xE4U, 0xD5U, 0xB7U, 0x73U, 0xE6U, - 0xD1U, 0xBFU, 0x63U, 0xC6U, 0x91U, 0x3FU, 0x7EU, 0xFCU, 0xE5U, 0xD7U, 0xB3U, 0x7BU, 0xF6U, 0xF1U, 0xFFU, 0xE3U, - 0xDBU, 0xABU, 0x4BU, 0x96U, 0x31U, 0x62U, 0xC4U, 0x95U, 0x37U, 0x6EU, 0xDCU, 0xA5U, 0x57U, 0xAEU, 0x41U, 0x82U, - 0x19U, 0x32U, 0x64U, 0xC8U, 0x8DU, 0x07U, 0x0EU, 0x1CU, 0x38U, 0x70U, 0xE0U, 0xDDU, 0xA7U, 0x53U, 0xA6U, 0x51U, - 0xA2U, 0x59U, 0xB2U, 0x79U, 0xF2U, 0xF9U, 0xEFU, 0xC3U, 0x9BU, 0x2BU, 0x56U, 0xACU, 0x45U, 0x8AU, 0x09U, 0x12U, - 0x24U, 0x48U, 0x90U, 0x3DU, 0x7AU, 0xF4U, 0xF5U, 0xF7U, 0xF3U, 0xFBU, 0xEBU, 0xCBU, 0x8BU, 0x0BU, 0x16U, 0x2CU, - 0x58U, 0xB0U, 0x7DU, 0xFAU, 0xE9U, 0xCFU, 0x83U, 0x1BU, 0x36U, 0x6CU, 0xD8U, 0xADU, 0x47U, 0x8EU, 0x01U, 0x00U}; - -const unsigned char LOG_TABLE[] = { - 0x00U, 0x00U, 0x01U, 0x19U, 0x02U, 0x32U, 0x1AU, 0xC6U, 0x03U, 0xDFU, 0x33U, 0xEEU, 0x1BU, 0x68U, 0xC7U, 0x4BU, - 0x04U, 0x64U, 0xE0U, 0x0EU, 0x34U, 0x8DU, 0xEFU, 0x81U, 0x1CU, 0xC1U, 0x69U, 0xF8U, 0xC8U, 0x08U, 0x4CU, 0x71U, - 0x05U, 0x8AU, 0x65U, 0x2FU, 0xE1U, 0x24U, 0x0FU, 0x21U, 0x35U, 0x93U, 0x8EU, 0xDAU, 0xF0U, 0x12U, 0x82U, 0x45U, - 0x1DU, 0xB5U, 0xC2U, 0x7DU, 0x6AU, 0x27U, 0xF9U, 0xB9U, 0xC9U, 0x9AU, 0x09U, 0x78U, 0x4DU, 0xE4U, 0x72U, 0xA6U, - 0x06U, 0xBFU, 0x8BU, 0x62U, 0x66U, 0xDDU, 0x30U, 0xFDU, 0xE2U, 0x98U, 0x25U, 0xB3U, 0x10U, 0x91U, 0x22U, 0x88U, - 0x36U, 0xD0U, 0x94U, 0xCEU, 0x8FU, 0x96U, 0xDBU, 0xBDU, 0xF1U, 0xD2U, 0x13U, 0x5CU, 0x83U, 0x38U, 0x46U, 0x40U, - 0x1EU, 0x42U, 0xB6U, 0xA3U, 0xC3U, 0x48U, 0x7EU, 0x6EU, 0x6BU, 0x3AU, 0x28U, 0x54U, 0xFAU, 0x85U, 0xBAU, 0x3DU, - 0xCAU, 0x5EU, 0x9BU, 0x9FU, 0x0AU, 0x15U, 0x79U, 0x2BU, 0x4EU, 0xD4U, 0xE5U, 0xACU, 0x73U, 0xF3U, 0xA7U, 0x57U, - 0x07U, 0x70U, 0xC0U, 0xF7U, 0x8CU, 0x80U, 0x63U, 0x0DU, 0x67U, 0x4AU, 0xDEU, 0xEDU, 0x31U, 0xC5U, 0xFEU, 0x18U, - 0xE3U, 0xA5U, 0x99U, 0x77U, 0x26U, 0xB8U, 0xB4U, 0x7CU, 0x11U, 0x44U, 0x92U, 0xD9U, 0x23U, 0x20U, 0x89U, 0x2EU, - 0x37U, 0x3FU, 0xD1U, 0x5BU, 0x95U, 0xBCU, 0xCFU, 0xCDU, 0x90U, 0x87U, 0x97U, 0xB2U, 0xDCU, 0xFCU, 0xBEU, 0x61U, - 0xF2U, 0x56U, 0xD3U, 0xABU, 0x14U, 0x2AU, 0x5DU, 0x9EU, 0x84U, 0x3CU, 0x39U, 0x53U, 0x47U, 0x6DU, 0x41U, 0xA2U, - 0x1FU, 0x2DU, 0x43U, 0xD8U, 0xB7U, 0x7BU, 0xA4U, 0x76U, 0xC4U, 0x17U, 0x49U, 0xECU, 0x7FU, 0x0CU, 0x6FU, 0xF6U, - 0x6CU, 0xA1U, 0x3BU, 0x52U, 0x29U, 0x9DU, 0x55U, 0xAAU, 0xFBU, 0x60U, 0x86U, 0xB1U, 0xBBU, 0xCCU, 0x3EU, 0x5AU, - 0xCBU, 0x59U, 0x5FU, 0xB0U, 0x9CU, 0xA9U, 0xA0U, 0x51U, 0x0BU, 0xF5U, 0x16U, 0xEBU, 0x7AU, 0x75U, 0x2CU, 0xD7U, - 0x4FU, 0xAEU, 0xD5U, 0xE9U, 0xE6U, 0xE7U, 0xADU, 0xE8U, 0x74U, 0xD6U, 0xF4U, 0xEAU, 0xA8U, 0x50U, 0x58U, 0xAFU}; +const unsigned char EXP_TABLE[] = +{ + 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, 0x1DU, 0x3AU, 0x74U, 0xE8U, 0xCDU, 0x87U, 0x13U, 0x26U, + 0x4CU, 0x98U, 0x2DU, 0x5AU, 0xB4U, 0x75U, 0xEAU, 0xC9U, 0x8FU, 0x03U, 0x06U, 0x0CU, 0x18U, 0x30U, 0x60U, 0xC0U, + 0x9DU, 0x27U, 0x4EU, 0x9CU, 0x25U, 0x4AU, 0x94U, 0x35U, 0x6AU, 0xD4U, 0xB5U, 0x77U, 0xEEU, 0xC1U, 0x9FU, 0x23U, + 0x46U, 0x8CU, 0x05U, 0x0AU, 0x14U, 0x28U, 0x50U, 0xA0U, 0x5DU, 0xBAU, 0x69U, 0xD2U, 0xB9U, 0x6FU, 0xDEU, 0xA1U, + 0x5FU, 0xBEU, 0x61U, 0xC2U, 0x99U, 0x2FU, 0x5EU, 0xBCU, 0x65U, 0xCAU, 0x89U, 0x0FU, 0x1EU, 0x3CU, 0x78U, 0xF0U, + 0xFDU, 0xE7U, 0xD3U, 0xBBU, 0x6BU, 0xD6U, 0xB1U, 0x7FU, 0xFEU, 0xE1U, 0xDFU, 0xA3U, 0x5BU, 0xB6U, 0x71U, 0xE2U, + 0xD9U, 0xAFU, 0x43U, 0x86U, 0x11U, 0x22U, 0x44U, 0x88U, 0x0DU, 0x1AU, 0x34U, 0x68U, 0xD0U, 0xBDU, 0x67U, 0xCEU, + 0x81U, 0x1FU, 0x3EU, 0x7CU, 0xF8U, 0xEDU, 0xC7U, 0x93U, 0x3BU, 0x76U, 0xECU, 0xC5U, 0x97U, 0x33U, 0x66U, 0xCCU, + 0x85U, 0x17U, 0x2EU, 0x5CU, 0xB8U, 0x6DU, 0xDAU, 0xA9U, 0x4FU, 0x9EU, 0x21U, 0x42U, 0x84U, 0x15U, 0x2AU, 0x54U, + 0xA8U, 0x4DU, 0x9AU, 0x29U, 0x52U, 0xA4U, 0x55U, 0xAAU, 0x49U, 0x92U, 0x39U, 0x72U, 0xE4U, 0xD5U, 0xB7U, 0x73U, + 0xE6U, 0xD1U, 0xBFU, 0x63U, 0xC6U, 0x91U, 0x3FU, 0x7EU, 0xFCU, 0xE5U, 0xD7U, 0xB3U, 0x7BU, 0xF6U, 0xF1U, 0xFFU, + 0xE3U, 0xDBU, 0xABU, 0x4BU, 0x96U, 0x31U, 0x62U, 0xC4U, 0x95U, 0x37U, 0x6EU, 0xDCU, 0xA5U, 0x57U, 0xAEU, 0x41U, + 0x82U, 0x19U, 0x32U, 0x64U, 0xC8U, 0x8DU, 0x07U, 0x0EU, 0x1CU, 0x38U, 0x70U, 0xE0U, 0xDDU, 0xA7U, 0x53U, 0xA6U, + 0x51U, 0xA2U, 0x59U, 0xB2U, 0x79U, 0xF2U, 0xF9U, 0xEFU, 0xC3U, 0x9BU, 0x2BU, 0x56U, 0xACU, 0x45U, 0x8AU, 0x09U, + 0x12U, 0x24U, 0x48U, 0x90U, 0x3DU, 0x7AU, 0xF4U, 0xF5U, 0xF7U, 0xF3U, 0xFBU, 0xEBU, 0xCBU, 0x8BU, 0x0BU, 0x16U, + 0x2CU, 0x58U, 0xB0U, 0x7DU, 0xFAU, 0xE9U, 0xCFU, 0x83U, 0x1BU, 0x36U, 0x6CU, 0xD8U, 0xADU, 0x47U, 0x8EU, 0x01U, + 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, 0x1DU, 0x3AU, 0x74U, 0xE8U, 0xCDU, 0x87U, 0x13U, 0x26U, 0x4CU, + 0x98U, 0x2DU, 0x5AU, 0xB4U, 0x75U, 0xEAU, 0xC9U, 0x8FU, 0x03U, 0x06U, 0x0CU, 0x18U, 0x30U, 0x60U, 0xC0U, 0x9DU, + 0x27U, 0x4EU, 0x9CU, 0x25U, 0x4AU, 0x94U, 0x35U, 0x6AU, 0xD4U, 0xB5U, 0x77U, 0xEEU, 0xC1U, 0x9FU, 0x23U, 0x46U, + 0x8CU, 0x05U, 0x0AU, 0x14U, 0x28U, 0x50U, 0xA0U, 0x5DU, 0xBAU, 0x69U, 0xD2U, 0xB9U, 0x6FU, 0xDEU, 0xA1U, 0x5FU, + 0xBEU, 0x61U, 0xC2U, 0x99U, 0x2FU, 0x5EU, 0xBCU, 0x65U, 0xCAU, 0x89U, 0x0FU, 0x1EU, 0x3CU, 0x78U, 0xF0U, 0xFDU, + 0xE7U, 0xD3U, 0xBBU, 0x6BU, 0xD6U, 0xB1U, 0x7FU, 0xFEU, 0xE1U, 0xDFU, 0xA3U, 0x5BU, 0xB6U, 0x71U, 0xE2U, 0xD9U, + 0xAFU, 0x43U, 0x86U, 0x11U, 0x22U, 0x44U, 0x88U, 0x0DU, 0x1AU, 0x34U, 0x68U, 0xD0U, 0xBDU, 0x67U, 0xCEU, 0x81U, + 0x1FU, 0x3EU, 0x7CU, 0xF8U, 0xEDU, 0xC7U, 0x93U, 0x3BU, 0x76U, 0xECU, 0xC5U, 0x97U, 0x33U, 0x66U, 0xCCU, 0x85U, + 0x17U, 0x2EU, 0x5CU, 0xB8U, 0x6DU, 0xDAU, 0xA9U, 0x4FU, 0x9EU, 0x21U, 0x42U, 0x84U, 0x15U, 0x2AU, 0x54U, 0xA8U, + 0x4DU, 0x9AU, 0x29U, 0x52U, 0xA4U, 0x55U, 0xAAU, 0x49U, 0x92U, 0x39U, 0x72U, 0xE4U, 0xD5U, 0xB7U, 0x73U, 0xE6U, + 0xD1U, 0xBFU, 0x63U, 0xC6U, 0x91U, 0x3FU, 0x7EU, 0xFCU, 0xE5U, 0xD7U, 0xB3U, 0x7BU, 0xF6U, 0xF1U, 0xFFU, 0xE3U, + 0xDBU, 0xABU, 0x4BU, 0x96U, 0x31U, 0x62U, 0xC4U, 0x95U, 0x37U, 0x6EU, 0xDCU, 0xA5U, 0x57U, 0xAEU, 0x41U, 0x82U, + 0x19U, 0x32U, 0x64U, 0xC8U, 0x8DU, 0x07U, 0x0EU, 0x1CU, 0x38U, 0x70U, 0xE0U, 0xDDU, 0xA7U, 0x53U, 0xA6U, 0x51U, + 0xA2U, 0x59U, 0xB2U, 0x79U, 0xF2U, 0xF9U, 0xEFU, 0xC3U, 0x9BU, 0x2BU, 0x56U, 0xACU, 0x45U, 0x8AU, 0x09U, 0x12U, + 0x24U, 0x48U, 0x90U, 0x3DU, 0x7AU, 0xF4U, 0xF5U, 0xF7U, 0xF3U, 0xFBU, 0xEBU, 0xCBU, 0x8BU, 0x0BU, 0x16U, 0x2CU, + 0x58U, 0xB0U, 0x7DU, 0xFAU, 0xE9U, 0xCFU, 0x83U, 0x1BU, 0x36U, 0x6CU, 0xD8U, 0xADU, 0x47U, 0x8EU, 0x01U, 0x00U +}; + +const unsigned char LOG_TABLE[] = +{ + 0x00U, 0x00U, 0x01U, 0x19U, 0x02U, 0x32U, 0x1AU, 0xC6U, 0x03U, 0xDFU, 0x33U, 0xEEU, 0x1BU, 0x68U, 0xC7U, 0x4BU, + 0x04U, 0x64U, 0xE0U, 0x0EU, 0x34U, 0x8DU, 0xEFU, 0x81U, 0x1CU, 0xC1U, 0x69U, 0xF8U, 0xC8U, 0x08U, 0x4CU, 0x71U, + 0x05U, 0x8AU, 0x65U, 0x2FU, 0xE1U, 0x24U, 0x0FU, 0x21U, 0x35U, 0x93U, 0x8EU, 0xDAU, 0xF0U, 0x12U, 0x82U, 0x45U, + 0x1DU, 0xB5U, 0xC2U, 0x7DU, 0x6AU, 0x27U, 0xF9U, 0xB9U, 0xC9U, 0x9AU, 0x09U, 0x78U, 0x4DU, 0xE4U, 0x72U, 0xA6U, + 0x06U, 0xBFU, 0x8BU, 0x62U, 0x66U, 0xDDU, 0x30U, 0xFDU, 0xE2U, 0x98U, 0x25U, 0xB3U, 0x10U, 0x91U, 0x22U, 0x88U, + 0x36U, 0xD0U, 0x94U, 0xCEU, 0x8FU, 0x96U, 0xDBU, 0xBDU, 0xF1U, 0xD2U, 0x13U, 0x5CU, 0x83U, 0x38U, 0x46U, 0x40U, + 0x1EU, 0x42U, 0xB6U, 0xA3U, 0xC3U, 0x48U, 0x7EU, 0x6EU, 0x6BU, 0x3AU, 0x28U, 0x54U, 0xFAU, 0x85U, 0xBAU, 0x3DU, + 0xCAU, 0x5EU, 0x9BU, 0x9FU, 0x0AU, 0x15U, 0x79U, 0x2BU, 0x4EU, 0xD4U, 0xE5U, 0xACU, 0x73U, 0xF3U, 0xA7U, 0x57U, + 0x07U, 0x70U, 0xC0U, 0xF7U, 0x8CU, 0x80U, 0x63U, 0x0DU, 0x67U, 0x4AU, 0xDEU, 0xEDU, 0x31U, 0xC5U, 0xFEU, 0x18U, + 0xE3U, 0xA5U, 0x99U, 0x77U, 0x26U, 0xB8U, 0xB4U, 0x7CU, 0x11U, 0x44U, 0x92U, 0xD9U, 0x23U, 0x20U, 0x89U, 0x2EU, + 0x37U, 0x3FU, 0xD1U, 0x5BU, 0x95U, 0xBCU, 0xCFU, 0xCDU, 0x90U, 0x87U, 0x97U, 0xB2U, 0xDCU, 0xFCU, 0xBEU, 0x61U, + 0xF2U, 0x56U, 0xD3U, 0xABU, 0x14U, 0x2AU, 0x5DU, 0x9EU, 0x84U, 0x3CU, 0x39U, 0x53U, 0x47U, 0x6DU, 0x41U, 0xA2U, + 0x1FU, 0x2DU, 0x43U, 0xD8U, 0xB7U, 0x7BU, 0xA4U, 0x76U, 0xC4U, 0x17U, 0x49U, 0xECU, 0x7FU, 0x0CU, 0x6FU, 0xF6U, + 0x6CU, 0xA1U, 0x3BU, 0x52U, 0x29U, 0x9DU, 0x55U, 0xAAU, 0xFBU, 0x60U, 0x86U, 0xB1U, 0xBBU, 0xCCU, 0x3EU, 0x5AU, + 0xCBU, 0x59U, 0x5FU, 0xB0U, 0x9CU, 0xA9U, 0xA0U, 0x51U, 0x0BU, 0xF5U, 0x16U, 0xEBU, 0x7AU, 0x75U, 0x2CU, 0xD7U, + 0x4FU, 0xAEU, 0xD5U, 0xE9U, 0xE6U, 0xE7U, 0xADU, 0xE8U, 0x74U, 0xD6U, 0xF4U, 0xEAU, 0xA8U, 0x50U, 0x58U, 0xAFU +}; /* multiplication using logarithms */ static unsigned char gmult(unsigned char a, unsigned char b) { - if (a == 0U || b == 0U) - return 0U; + if (a == 0U || b == 0U) + return 0U; - unsigned int i = LOG_TABLE[a]; - unsigned int j = LOG_TABLE[b]; + unsigned int i = LOG_TABLE[a]; + unsigned int j = LOG_TABLE[b]; - return EXP_TABLE[i + j]; + return EXP_TABLE[i + j]; } /* Simulate a LFSR with generator polynomial for n byte RS code. @@ -101,29 +105,30 @@ static unsigned char gmult(unsigned char a, unsigned char b) */ void CRS129::encode(const unsigned char* msg, unsigned int nbytes, unsigned char* parity) { - assert(msg != nullptr); - assert(parity != nullptr); + assert(msg != nullptr); + assert(parity != nullptr); - for (unsigned int i = 0U; i < NPAR + 1U; i++) - parity[i] = 0x00U; + for (unsigned int i = 0U; i < NPAR + 1U; i++) + parity[i] = 0x00U; - for (unsigned int i = 0U; i < nbytes; i++) { - unsigned char dbyte = msg[i] ^ parity[NPAR - 1U]; + for (unsigned int i = 0U; i < nbytes; i++) + { + unsigned char dbyte = msg[i] ^ parity[NPAR - 1U]; - for (int j = NPAR - 1; j > 0; j--) - parity[j] = parity[j - 1] ^ ::gmult(POLY[j], dbyte); + for (int j = NPAR - 1; j > 0; j--) + parity[j] = parity[j - 1] ^ ::gmult(POLY[j], dbyte); - parity[0] = ::gmult(POLY[0], dbyte); - } + parity[0] = ::gmult(POLY[0], dbyte); + } } // Reed-Solomon (12,9) check bool CRS129::check(const unsigned char* in) { - assert(in != nullptr); + assert(in != nullptr); - unsigned char parity[4U]; - encode(in, 9U, parity); + unsigned char parity[4U]; + encode(in, 9U, parity); - return in[9U] == parity[2U] && in[10U] == parity[1U] && in[11U] == parity[0U]; + return in[9U] == parity[2U] && in[10U] == parity[1U] && in[11U] == parity[0U]; } diff --git a/src/crs129.h b/src/crs129.h index 57fb848..60f99bd 100644 --- a/src/crs129.h +++ b/src/crs129.h @@ -22,9 +22,9 @@ class CRS129 { public: - static bool check(const unsigned char* in); - - static void encode(const unsigned char* msg, unsigned int nbytes, unsigned char* parity); + static bool check(const unsigned char* in); + + static void encode(const unsigned char* msg, unsigned int nbytes, unsigned char* parity); }; #endif diff --git a/src/csemaphore.cpp b/src/csemaphore.cpp index 3b91e82..380f735 100644 --- a/src/csemaphore.cpp +++ b/src/csemaphore.cpp @@ -30,8 +30,8 @@ CSemaphore::CSemaphore() { - // Initialized as locked. - m_Count = 0; + // Initialized as locked. + m_Count = 0; } //////////////////////////////////////////////////////////////////////////////////////// @@ -39,34 +39,34 @@ CSemaphore::CSemaphore() void CSemaphore::Reset(void) { - std::unique_lock lock(m_Mutex); - m_Count = 0; + std::unique_lock lock(m_Mutex); + m_Count = 0; } void CSemaphore::Notify(void) { - std::unique_lock lock(m_Mutex); - m_Count++; - m_Condition.notify_one(); + std::unique_lock lock(m_Mutex); + m_Count++; + m_Condition.notify_one(); } void CSemaphore::Wait(void) { - std::unique_lock lock(m_Mutex); - m_Condition.wait(lock, [&]{ return m_Count > 0; }); - m_Count--; + std::unique_lock lock(m_Mutex); + m_Condition.wait(lock, [&] { return m_Count > 0; }); + m_Count--; } bool CSemaphore::WaitFor(uint ms) { - std::chrono::milliseconds timespan(ms); - std::unique_lock lock(m_Mutex); - auto ok = m_Condition.wait_for(lock, timespan, [&]{ return m_Count > 0; }); - if ( ok ) - { - m_Count--; - } - return ok; - + std::chrono::milliseconds timespan(ms); + std::unique_lock lock(m_Mutex); + auto ok = m_Condition.wait_for(lock, timespan, [&] { return m_Count > 0; }); + if ( ok ) + { + m_Count--; + } + return ok; + } diff --git a/src/csemaphore.h b/src/csemaphore.h index 0729512..c0470a2 100644 --- a/src/csemaphore.h +++ b/src/csemaphore.h @@ -32,23 +32,23 @@ class CSemaphore { public: - // constructor - CSemaphore(); - - // destructor - virtual ~CSemaphore() {}; - - // operation - void Reset(void); - void Notify(void); - void Wait(void); - bool WaitFor(uint); - + // constructor + CSemaphore(); + + // destructor + virtual ~CSemaphore() {}; + + // operation + void Reset(void); + void Notify(void); + void Wait(void); + bool WaitFor(uint); + protected: - // data - std::mutex m_Mutex; - std::condition_variable m_Condition; - size_t m_Count; + // data + std::mutex m_Mutex; + std::condition_variable m_Condition; + size_t m_Count; }; diff --git a/src/ctimepoint.cpp b/src/ctimepoint.cpp index 41b59f0..bf69c22 100644 --- a/src/ctimepoint.cpp +++ b/src/ctimepoint.cpp @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- #include "main.h" @@ -30,7 +30,7 @@ CTimePoint::CTimePoint() { - m_TimePoint = std::chrono::steady_clock::now(); + m_TimePoint = std::chrono::steady_clock::now(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -38,9 +38,9 @@ CTimePoint::CTimePoint() double CTimePoint::DurationSinceNow(void) const { - std::chrono::steady_clock::time_point Now = std::chrono::steady_clock::now(); - std::chrono::steady_clock::duration time_span = (Now - m_TimePoint); - return double(time_span.count()) * std::chrono::steady_clock::period::num / std::chrono::steady_clock::period::den; + std::chrono::steady_clock::time_point Now = std::chrono::steady_clock::now(); + std::chrono::steady_clock::duration time_span = (Now - m_TimePoint); + return double(time_span.count()) * std::chrono::steady_clock::period::num / std::chrono::steady_clock::period::den; } //////////////////////////////////////////////////////////////////////////////////////// @@ -48,6 +48,6 @@ double CTimePoint::DurationSinceNow(void) const void CTimePoint::TaskSleepFor(uint ms) { - std::chrono::milliseconds timespan(ms); - std::this_thread::sleep_for(timespan); + std::chrono::milliseconds timespan(ms); + std::this_thread::sleep_for(timespan); } diff --git a/src/ctimepoint.h b/src/ctimepoint.h index 209e8c7..7c5ca17 100644 --- a/src/ctimepoint.h +++ b/src/ctimepoint.h @@ -19,7 +19,7 @@ // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License -// along with Foobar. If not, see . +// along with Foobar. If not, see . // ---------------------------------------------------------------------------- #ifndef ctimepoint_h @@ -32,22 +32,22 @@ class CTimePoint : public std::chrono::steady_clock::time_point { public: - // constructor - CTimePoint(); - - // destructor - virtual ~CTimePoint() {} - - // operation - void Now(void) { m_TimePoint = std::chrono::steady_clock::now(); } - double DurationSinceNow(void) const; - - // task - static void TaskSleepFor(uint); - + // constructor + CTimePoint(); + + // destructor + virtual ~CTimePoint() {} + + // operation + void Now(void) { m_TimePoint = std::chrono::steady_clock::now(); } + double DurationSinceNow(void) const; + + // task + static void TaskSleepFor(uint); + protected: - // data - std::chrono::steady_clock::time_point m_TimePoint; + // data + std::chrono::steady_clock::time_point m_TimePoint; }; diff --git a/src/ctranscoder.cpp b/src/ctranscoder.cpp index 2ec6809..e457419 100644 --- a/src/ctranscoder.cpp +++ b/src/ctranscoder.cpp @@ -46,14 +46,14 @@ CTranscoder g_Transcoder; CTranscoder::CTranscoder() { - keep_running = true; - m_pThread = nullptr; - m_bConnected = false; - m_LastKeepaliveTime.Now(); - m_LastActivityTime.Now(); - m_bStreamOpened = false; - m_StreamidOpenStream = 0; - m_PortOpenStream = 0; + keep_running = true; + m_pThread = nullptr; + m_bConnected = false; + m_LastKeepaliveTime.Now(); + m_LastActivityTime.Now(); + m_bStreamOpened = false; + m_StreamidOpenStream = 0; + m_PortOpenStream = 0; } //////////////////////////////////////////////////////////////////////////////////////// @@ -61,7 +61,7 @@ CTranscoder::CTranscoder() CTranscoder::~CTranscoder() { - Close(); + Close(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -69,8 +69,8 @@ CTranscoder::~CTranscoder() bool CTranscoder::Init(void) { - // create address to the transcoder - auto s = g_Reflector.GetTranscoderIp(); + // create address to the transcoder + auto s = g_Reflector.GetTranscoderIp(); m_Ip.Initialize(strchr(s, ':') ? AF_INET6 : AF_INET, TRANSCODER_PORT, s); // does the user not want to use a transcoder? @@ -92,10 +92,11 @@ bool CTranscoder::Init(void) #endif CIp tc(m_Ip.GetFamily(), TRANSCODER_PORT, s); - // create our socket + // create our socket if (tc.IsSet()) { - if (! m_Socket.Open(tc)) { + if (! m_Socket.Open(tc)) + { std::cerr << "Error opening socket on port UDP" << TRANSCODER_PORT << " on ip " << m_Ip << std::endl; return false; } @@ -107,38 +108,38 @@ bool CTranscoder::Init(void) return false; } - // start thread - keep_running = true; - m_pThread = new std::thread(CTranscoder::Thread, this); + // start thread + keep_running = true; + m_pThread = new std::thread(CTranscoder::Thread, this); - return true; + return true; } void CTranscoder::Close(void) { - // close socket - m_Socket.Close(); - - // close all streams - m_Mutex.lock(); - { - for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ ) - { - delete *it; - } - m_Streams.clear(); - - } - m_Mutex.unlock(); - - // kill threads - keep_running = false; - if ( m_pThread != nullptr ) - { - m_pThread->join(); - delete m_pThread; - m_pThread = nullptr; - } + // close socket + m_Socket.Close(); + + // close all streams + m_Mutex.lock(); + { + for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ ) + { + delete *it; + } + m_Streams.clear(); + + } + m_Mutex.unlock(); + + // kill threads + keep_running = false; + if ( m_pThread != nullptr ) + { + m_pThread->join(); + delete m_pThread; + m_pThread = nullptr; + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -146,171 +147,171 @@ void CTranscoder::Close(void) void CTranscoder::Thread(CTranscoder *This) { - while (This->keep_running) - { - This->Task(); - } + while (This->keep_running) + { + This->Task(); + } } void CTranscoder::Task(void) { - CBuffer Buffer; - CIp Ip; - uint16 StreamId; - uint16 Port; - - // anything coming in from codec server ? - //if ( (m_Socket.Receive(&Buffer, &Ip, 20) != -1) && (Ip == m_Ip) ) - if ( m_Socket.Receive(Buffer, Ip, 20) ) - { - m_LastActivityTime.Now(); - - // crack packet - if ( IsValidStreamDescrPacket(Buffer, &StreamId, &Port) ) - { - //std::cout << "Transcoder stream " << (int) StreamId << " descr packet " << std::endl; - m_bStreamOpened = true; - m_StreamidOpenStream = StreamId; - m_PortOpenStream = Port; - m_SemaphoreOpenStream.Notify(); - } - else if ( IsValidNoStreamAvailablePacket(Buffer) ) - { - m_bStreamOpened = false; - m_SemaphoreOpenStream.Notify(); - } - else if ( IsValidKeepAlivePacket(Buffer) ) - { - if ( !m_bConnected ) - { - std::cout << "Transcoder connected at " << Ip << std::endl; - } - m_bConnected = true; - } - - } - - // keep client alive - if ( m_LastKeepaliveTime.DurationSinceNow() > TRANSCODER_KEEPALIVE_PERIOD ) - { - // - HandleKeepalives(); - - // update time - m_LastKeepaliveTime.Now(); - } - } + CBuffer Buffer; + CIp Ip; + uint16 StreamId; + uint16 Port; + + // anything coming in from codec server ? + //if ( (m_Socket.Receive(&Buffer, &Ip, 20) != -1) && (Ip == m_Ip) ) + if ( m_Socket.Receive(Buffer, Ip, 20) ) + { + m_LastActivityTime.Now(); + + // crack packet + if ( IsValidStreamDescrPacket(Buffer, &StreamId, &Port) ) + { + //std::cout << "Transcoder stream " << (int) StreamId << " descr packet " << std::endl; + m_bStreamOpened = true; + m_StreamidOpenStream = StreamId; + m_PortOpenStream = Port; + m_SemaphoreOpenStream.Notify(); + } + else if ( IsValidNoStreamAvailablePacket(Buffer) ) + { + m_bStreamOpened = false; + m_SemaphoreOpenStream.Notify(); + } + else if ( IsValidKeepAlivePacket(Buffer) ) + { + if ( !m_bConnected ) + { + std::cout << "Transcoder connected at " << Ip << std::endl; + } + m_bConnected = true; + } + + } + + // keep client alive + if ( m_LastKeepaliveTime.DurationSinceNow() > TRANSCODER_KEEPALIVE_PERIOD ) + { + // + HandleKeepalives(); + + // update time + m_LastKeepaliveTime.Now(); + } +} //////////////////////////////////////////////////////////////////////////////////////// // manage streams CCodecStream *CTranscoder::GetStream(CPacketStream *PacketStream, uint8 uiCodecIn) { - CBuffer Buffer; - - CCodecStream *stream = nullptr; - - // do we need transcoding - if ( uiCodecIn != CODEC_NONE ) - { - // are we connected to server - if ( m_bConnected ) - { - // yes, post openstream request - EncodeOpenstreamPacket(&Buffer, uiCodecIn, (uiCodecIn == CODEC_AMBEPLUS) ? CODEC_AMBE2PLUS : CODEC_AMBEPLUS); - m_Socket.Send(Buffer, m_Ip, TRANSCODER_PORT); - - // wait relpy here - if ( m_SemaphoreOpenStream.WaitFor(AMBED_OPENSTREAM_TIMEOUT) ) - { - if ( m_bStreamOpened ) - { - std::cout << "ambed openstream ok" << std::endl; - - // create stream object - stream = new CCodecStream(PacketStream, m_StreamidOpenStream, uiCodecIn, (uiCodecIn == CODEC_AMBEPLUS) ? CODEC_AMBE2PLUS : CODEC_AMBEPLUS); - - // init it - if ( stream->Init(m_PortOpenStream) ) - { - // and append to list - Lock(); - m_Streams.push_back(stream); - Unlock(); - } - else - { - // send close packet - EncodeClosestreamPacket(&Buffer, stream->GetStreamId()); - m_Socket.Send(Buffer, m_Ip, TRANSCODER_PORT); - // and delete - delete stream; - stream = nullptr; - } - } - else - { - std::cout << "ambed openstream failed (no suitable channel available)" << std::endl; - } - } - else - { - std::cout << "ambed openstream timeout" << std::endl; - } - - } - } - return stream; + CBuffer Buffer; + + CCodecStream *stream = nullptr; + + // do we need transcoding + if ( uiCodecIn != CODEC_NONE ) + { + // are we connected to server + if ( m_bConnected ) + { + // yes, post openstream request + EncodeOpenstreamPacket(&Buffer, uiCodecIn, (uiCodecIn == CODEC_AMBEPLUS) ? CODEC_AMBE2PLUS : CODEC_AMBEPLUS); + m_Socket.Send(Buffer, m_Ip, TRANSCODER_PORT); + + // wait relpy here + if ( m_SemaphoreOpenStream.WaitFor(AMBED_OPENSTREAM_TIMEOUT) ) + { + if ( m_bStreamOpened ) + { + std::cout << "ambed openstream ok" << std::endl; + + // create stream object + stream = new CCodecStream(PacketStream, m_StreamidOpenStream, uiCodecIn, (uiCodecIn == CODEC_AMBEPLUS) ? CODEC_AMBE2PLUS : CODEC_AMBEPLUS); + + // init it + if ( stream->Init(m_PortOpenStream) ) + { + // and append to list + Lock(); + m_Streams.push_back(stream); + Unlock(); + } + else + { + // send close packet + EncodeClosestreamPacket(&Buffer, stream->GetStreamId()); + m_Socket.Send(Buffer, m_Ip, TRANSCODER_PORT); + // and delete + delete stream; + stream = nullptr; + } + } + else + { + std::cout << "ambed openstream failed (no suitable channel available)" << std::endl; + } + } + else + { + std::cout << "ambed openstream timeout" << std::endl; + } + + } + } + return stream; } void CTranscoder::ReleaseStream(CCodecStream *stream) { - CBuffer Buffer; - - if ( stream != nullptr ) - { - // look for the stream - bool found = false; - Lock(); - { - for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ ) - { - // compare object pointers - if ( (*it) == stream ) - { - // send close packet - EncodeClosestreamPacket(&Buffer, (*it)->GetStreamId()); - m_Socket.Send(Buffer, m_Ip, TRANSCODER_PORT); - - // display stats - if ( (*it)->GetPingMin() >= 0.0 ) - { - char sz[256]; - sprintf(sz, "ambed stats (ms) : %.1f/%.1f/%.1f", - (*it)->GetPingMin() * 1000.0, - (*it)->GetPingAve() * 1000.0, - (*it)->GetPingMax() * 1000.0); - std::cout << sz << std::endl; - } - if ( (*it)->GetTimeoutPackets() > 0 ) - { - char sz[256]; - sprintf(sz, "ambed %d of %d packets timed out", - (*it)->GetTimeoutPackets(), - (*it)->GetTotalPackets()); - std::cout << sz << std::endl; - } - - // and close it - (*it)->Close(); - delete (*it); - m_Streams.erase(it); - break; - } - } - } - Unlock(); - } + CBuffer Buffer; + + if ( stream != nullptr ) + { + // look for the stream + bool found = false; + Lock(); + { + for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ ) + { + // compare object pointers + if ( (*it) == stream ) + { + // send close packet + EncodeClosestreamPacket(&Buffer, (*it)->GetStreamId()); + m_Socket.Send(Buffer, m_Ip, TRANSCODER_PORT); + + // display stats + if ( (*it)->GetPingMin() >= 0.0 ) + { + char sz[256]; + sprintf(sz, "ambed stats (ms) : %.1f/%.1f/%.1f", + (*it)->GetPingMin() * 1000.0, + (*it)->GetPingAve() * 1000.0, + (*it)->GetPingMax() * 1000.0); + std::cout << sz << std::endl; + } + if ( (*it)->GetTimeoutPackets() > 0 ) + { + char sz[256]; + sprintf(sz, "ambed %d of %d packets timed out", + (*it)->GetTimeoutPackets(), + (*it)->GetTotalPackets()); + std::cout << sz << std::endl; + } + + // and close it + (*it)->Close(); + delete (*it); + m_Streams.erase(it); + break; + } + } + } + Unlock(); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -318,19 +319,19 @@ void CTranscoder::ReleaseStream(CCodecStream *stream) void CTranscoder::HandleKeepalives(void) { - CBuffer keepalive; - - // send keepalive - EncodeKeepAlivePacket(&keepalive); - m_Socket.Send(keepalive, m_Ip, TRANSCODER_PORT); - - // check if still with us - if ( m_bConnected && (m_LastActivityTime.DurationSinceNow() >= TRANSCODER_KEEPALIVE_TIMEOUT) ) - { - // no, disconnect - m_bConnected = false; - std::cout << "Transcoder keepalive timeout" << std::endl; - } + CBuffer keepalive; + + // send keepalive + EncodeKeepAlivePacket(&keepalive); + m_Socket.Send(keepalive, m_Ip, TRANSCODER_PORT); + + // check if still with us + if ( m_bConnected && (m_LastActivityTime.DurationSinceNow() >= TRANSCODER_KEEPALIVE_TIMEOUT) ) + { + // no, disconnect + m_bConnected = false; + std::cout << "Transcoder keepalive timeout" << std::endl; + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -338,37 +339,37 @@ void CTranscoder::HandleKeepalives(void) bool CTranscoder::IsValidKeepAlivePacket(const CBuffer &Buffer) { - uint8 tag[] = { 'A','M','B','E','D','P','O','N','G' }; - - bool valid = false; - if ( (Buffer.size() == 9) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - valid = true; - } - return valid; + uint8 tag[] = { 'A','M','B','E','D','P','O','N','G' }; + + bool valid = false; + if ( (Buffer.size() == 9) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + valid = true; + } + return valid; } bool CTranscoder::IsValidStreamDescrPacket(const CBuffer &Buffer, uint16 *Id, uint16 *Port) { - uint8 tag[] = { 'A','M','B','E','D','S','T','D' }; - - bool valid = false; - if ( (Buffer.size() == 14) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - *Id = *(uint16 *)(&Buffer.data()[8]); - *Port = *(uint16 *)(&Buffer.data()[10]); - // uint8 CodecIn = Buffer.data()[12]; - // uint8 CodecOut = Buffer.data()[13]; - valid = true; - } - return valid; + uint8 tag[] = { 'A','M','B','E','D','S','T','D' }; + + bool valid = false; + if ( (Buffer.size() == 14) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + *Id = *(uint16 *)(&Buffer.data()[8]); + *Port = *(uint16 *)(&Buffer.data()[10]); + // uint8 CodecIn = Buffer.data()[12]; + // uint8 CodecOut = Buffer.data()[13]; + valid = true; + } + return valid; } bool CTranscoder::IsValidNoStreamAvailablePacket(const CBuffer&Buffer) { - uint8 tag[] = { 'A','M','B','E','D','B','U','S','Y' }; + uint8 tag[] = { 'A','M','B','E','D','B','U','S','Y' }; - return ( (Buffer.size() == 9) && (Buffer.Compare(tag, sizeof(tag)) == 0) ); + return ( (Buffer.size() == 9) && (Buffer.Compare(tag, sizeof(tag)) == 0) ); } @@ -377,26 +378,26 @@ bool CTranscoder::IsValidNoStreamAvailablePacket(const CBuffer&Buffer) void CTranscoder::EncodeKeepAlivePacket(CBuffer *Buffer) { - uint8 tag[] = { 'A','M','B','E','D','P','I','N','G' }; + uint8 tag[] = { 'A','M','B','E','D','P','I','N','G' }; - Buffer->Set(tag, sizeof(tag)); - Buffer->Append((uint8 *)(const char *)g_Reflector.GetCallsign(), CALLSIGN_LEN); + Buffer->Set(tag, sizeof(tag)); + Buffer->Append((uint8 *)(const char *)g_Reflector.GetCallsign(), CALLSIGN_LEN); } void CTranscoder::EncodeOpenstreamPacket(CBuffer *Buffer, uint8 uiCodecIn, uint8 uiCodecOut) { - uint8 tag[] = { 'A','M','B','E','D','O','S' }; + uint8 tag[] = { 'A','M','B','E','D','O','S' }; - Buffer->Set(tag, sizeof(tag)); - Buffer->Append((uint8 *)(const char *)g_Reflector.GetCallsign(), CALLSIGN_LEN); - Buffer->Append((uint8)uiCodecIn); - Buffer->Append((uint8)uiCodecOut); + Buffer->Set(tag, sizeof(tag)); + Buffer->Append((uint8 *)(const char *)g_Reflector.GetCallsign(), CALLSIGN_LEN); + Buffer->Append((uint8)uiCodecIn); + Buffer->Append((uint8)uiCodecOut); } void CTranscoder::EncodeClosestreamPacket(CBuffer *Buffer, uint16 uiStreamId) { - uint8 tag[] = { 'A','M','B','E','D','C','S' }; + uint8 tag[] = { 'A','M','B','E','D','C','S' }; - Buffer->Set(tag, sizeof(tag)); - Buffer->Append((uint16)uiStreamId); + Buffer->Set(tag, sizeof(tag)); + Buffer->Append((uint16)uiStreamId); } diff --git a/src/ctranscoder.h b/src/ctranscoder.h index cf9f8ca..f49a129 100644 --- a/src/ctranscoder.h +++ b/src/ctranscoder.h @@ -42,68 +42,68 @@ class CPacketStream; class CTranscoder { public: - // constructor - CTranscoder(); + // constructor + CTranscoder(); - // destructor - virtual ~CTranscoder(); + // destructor + virtual ~CTranscoder(); - // initialization - bool Init(void); - void Close(void); + // initialization + bool Init(void); + void Close(void); - // locks - void Lock(void) { m_Mutex.lock(); } - void Unlock(void) { m_Mutex.unlock(); } + // locks + void Lock(void) { m_Mutex.lock(); } + void Unlock(void) { m_Mutex.unlock(); } - // status - bool IsConnected(void) const { return m_bConnected; } + // status + bool IsConnected(void) const { return m_bConnected; } - // manage streams - CCodecStream *GetStream(CPacketStream *, uint8); - void ReleaseStream(CCodecStream *); + // manage streams + CCodecStream *GetStream(CPacketStream *, uint8); + void ReleaseStream(CCodecStream *); - // task - static void Thread(CTranscoder *); - void Task(void); + // task + static void Thread(CTranscoder *); + void Task(void); protected: - // keepalive helpers - void HandleKeepalives(void); + // keepalive helpers + void HandleKeepalives(void); - // packet decoding helpers - bool IsValidKeepAlivePacket(const CBuffer &); - bool IsValidStreamDescrPacket(const CBuffer &, uint16 *, uint16 *); - bool IsValidNoStreamAvailablePacket(const CBuffer&); + // packet decoding helpers + bool IsValidKeepAlivePacket(const CBuffer &); + bool IsValidStreamDescrPacket(const CBuffer &, uint16 *, uint16 *); + bool IsValidNoStreamAvailablePacket(const CBuffer&); - // packet encoding helpers - void EncodeKeepAlivePacket(CBuffer *); - void EncodeOpenstreamPacket(CBuffer *, uint8, uint8); - void EncodeClosestreamPacket(CBuffer *, uint16); + // packet encoding helpers + void EncodeKeepAlivePacket(CBuffer *); + void EncodeOpenstreamPacket(CBuffer *, uint8, uint8); + void EncodeClosestreamPacket(CBuffer *, uint16); protected: - // streams - std::mutex m_Mutex; - std::list m_Streams; - - // sync objects for Openstream - CSemaphore m_SemaphoreOpenStream; - bool m_bStreamOpened; - uint16 m_StreamidOpenStream; - uint16 m_PortOpenStream; - - // thread - std::atomic keep_running; - std::thread *m_pThread; - - // socket - CIp m_Ip; - CUdpSocket m_Socket; - bool m_bConnected; - - // time - CTimePoint m_LastKeepaliveTime; - CTimePoint m_LastActivityTime; + // streams + std::mutex m_Mutex; + std::list m_Streams; + + // sync objects for Openstream + CSemaphore m_SemaphoreOpenStream; + bool m_bStreamOpened; + uint16 m_StreamidOpenStream; + uint16 m_PortOpenStream; + + // thread + std::atomic keep_running; + std::thread *m_pThread; + + // socket + CIp m_Ip; + CUdpSocket m_Socket; + bool m_bConnected; + + // time + CTimePoint m_LastKeepaliveTime; + CTimePoint m_LastActivityTime; }; diff --git a/src/cudpmsgsocket.cpp b/src/cudpmsgsocket.cpp index 2178981..ad94156 100644 --- a/src/cudpmsgsocket.cpp +++ b/src/cudpmsgsocket.cpp @@ -30,13 +30,13 @@ // open bool CUdpMsgSocket::Open(const CIp &ip) { - bool ret; - int on = 1; + bool ret; + int on = 1; - ret = CUdpSocket::Open(ip); - setsockopt(m_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on, sizeof(on)); + ret = CUdpSocket::Open(ip); + setsockopt(m_fd, IPPROTO_IP, IP_PKTINFO, (char *)&on, sizeof(on)); - return ret; + return ret; } @@ -45,72 +45,73 @@ bool CUdpMsgSocket::Open(const CIp &ip) int CUdpMsgSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout) { - struct sockaddr_in Sin; - fd_set FdSet; - unsigned int uiFromLen = sizeof(struct sockaddr_in); - int iRecvLen = -1; - struct timeval tv; - - struct msghdr Msg; - struct iovec Iov[1]; - - union { - struct cmsghdr cm; - unsigned char pktinfo_sizer[sizeof(struct cmsghdr) + sizeof(struct in_pktinfo)]; - } Control; - - // socket valid ? - if ( m_fd != -1 ) - { - // allocate buffer - Buffer->resize(UDP_MSG_BUFFER_LENMAX); - - //prepare msghdr - bzero(&Msg, sizeof(Msg)); - Iov[0].iov_base = Buffer->data(); - Iov[0].iov_len = UDP_MSG_BUFFER_LENMAX; - - bzero(&Sin, sizeof(Sin)); - Msg.msg_name = &Sin; - Msg.msg_namelen = sizeof(Sin); - Msg.msg_iov = Iov; - Msg.msg_iovlen = 1; - Msg.msg_control = &Control; - Msg.msg_controllen = sizeof(Control); - - // control socket - FD_ZERO(&FdSet); - FD_SET(m_fd, &FdSet); - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - select(m_fd + 1, &FdSet, 0, 0, &tv); - - // read - iRecvLen = (int)recvmsg(m_fd, &Msg, 0); - - // handle - if ( iRecvLen != -1 ) - { - // adjust buffer size - Buffer->resize(iRecvLen); - - // get IP + struct sockaddr_in Sin; + fd_set FdSet; + unsigned int uiFromLen = sizeof(struct sockaddr_in); + int iRecvLen = -1; + struct timeval tv; + + struct msghdr Msg; + struct iovec Iov[1]; + + union + { + struct cmsghdr cm; + unsigned char pktinfo_sizer[sizeof(struct cmsghdr) + sizeof(struct in_pktinfo)]; + } Control; + + // socket valid ? + if ( m_fd != -1 ) + { + // allocate buffer + Buffer->resize(UDP_MSG_BUFFER_LENMAX); + + //prepare msghdr + bzero(&Msg, sizeof(Msg)); + Iov[0].iov_base = Buffer->data(); + Iov[0].iov_len = UDP_MSG_BUFFER_LENMAX; + + bzero(&Sin, sizeof(Sin)); + Msg.msg_name = &Sin; + Msg.msg_namelen = sizeof(Sin); + Msg.msg_iov = Iov; + Msg.msg_iovlen = 1; + Msg.msg_control = &Control; + Msg.msg_controllen = sizeof(Control); + + // control socket + FD_ZERO(&FdSet); + FD_SET(m_fd, &FdSet); + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + select(m_fd + 1, &FdSet, 0, 0, &tv); + + // read + iRecvLen = (int)recvmsg(m_fd, &Msg, 0); + + // handle + if ( iRecvLen != -1 ) + { + // adjust buffer size + Buffer->resize(iRecvLen); + + // get IP if (AF_INET == m_addr.GetFamily()) memcpy(Ip->GetPointer(), &Sin, sizeof(struct sockaddr_in)); - // get local IP - struct cmsghdr *Cmsg; - for (Cmsg = CMSG_FIRSTHDR(&Msg); Cmsg != nullptr; Cmsg = CMSG_NXTHDR(&Msg, Cmsg)) - { - if (Cmsg->cmsg_level == IPPROTO_IP && Cmsg->cmsg_type == IP_PKTINFO) - { - struct in_pktinfo *PktInfo = (struct in_pktinfo *)CMSG_DATA(Cmsg); - m_LocalAddr.s_addr = PktInfo->ipi_spec_dst.s_addr; - } - } - } - } - - // done - return iRecvLen; + // get local IP + struct cmsghdr *Cmsg; + for (Cmsg = CMSG_FIRSTHDR(&Msg); Cmsg != nullptr; Cmsg = CMSG_NXTHDR(&Msg, Cmsg)) + { + if (Cmsg->cmsg_level == IPPROTO_IP && Cmsg->cmsg_type == IP_PKTINFO) + { + struct in_pktinfo *PktInfo = (struct in_pktinfo *)CMSG_DATA(Cmsg); + m_LocalAddr.s_addr = PktInfo->ipi_spec_dst.s_addr; + } + } + } + } + + // done + return iRecvLen; } diff --git a/src/cudpmsgsocket.h b/src/cudpmsgsocket.h index 32bb512..ae23781 100644 --- a/src/cudpmsgsocket.h +++ b/src/cudpmsgsocket.h @@ -39,17 +39,17 @@ class CUdpMsgSocket : public CUdpSocket { public: - // open - bool Open(const CIp &ip); + // open + bool Open(const CIp &ip); - // read - int Receive(CBuffer *, CIp *, int); + // read + int Receive(CBuffer *, CIp *, int); - struct in_addr *GetLocalAddr(void) { return &m_LocalAddr; } + struct in_addr *GetLocalAddr(void) { return &m_LocalAddr; } protected: - // data - struct in_addr m_LocalAddr; + // data + struct in_addr m_LocalAddr; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cudpsocket.cpp b/src/cudpsocket.cpp index 4ce9447..3f21906 100644 --- a/src/cudpsocket.cpp +++ b/src/cudpsocket.cpp @@ -83,7 +83,8 @@ bool CUdpSocket::Open(const CIp &Ip) return false; } - if (0 == m_addr.GetPort()) { // get the assigned port for an ephemeral port request + if (0 == m_addr.GetPort()) // get the assigned port for an ephemeral port request + { CIp a; socklen_t len = sizeof(struct sockaddr_storage); if (getsockname(m_fd, a.GetPointer(), &len)) diff --git a/src/cuser.cpp b/src/cuser.cpp index 502827b..0feaf33 100644 --- a/src/cuser.cpp +++ b/src/cuser.cpp @@ -32,25 +32,25 @@ CUser::CUser() { - m_LastHeardTime = std::time(nullptr); + m_LastHeardTime = std::time(nullptr); } CUser::CUser(const CCallsign &my, const CCallsign &rpt1, const CCallsign &rpt2, const CCallsign &xlx) { - m_My = my; - m_Rpt1 = rpt1; - m_Rpt2 = rpt2; - m_Xlx = xlx; - m_LastHeardTime = std::time(nullptr); + m_My = my; + m_Rpt1 = rpt1; + m_Rpt2 = rpt2; + m_Xlx = xlx; + m_LastHeardTime = std::time(nullptr); } CUser::CUser(const CUser &user) { - m_My = user.m_My; - m_Rpt1 = user.m_Rpt1; - m_Rpt2 = user.m_Rpt2; - m_Xlx = user.m_Xlx; - m_LastHeardTime = user.m_LastHeardTime; + m_My = user.m_My; + m_Rpt1 = user.m_Rpt1; + m_Rpt2 = user.m_Rpt2; + m_Xlx = user.m_Xlx; + m_LastHeardTime = user.m_LastHeardTime; } //////////////////////////////////////////////////////////////////////////////////////// @@ -58,14 +58,14 @@ CUser::CUser(const CUser &user) bool CUser::operator ==(const CUser &user) const { - return ((user.m_My == m_My) && (user.m_Rpt1 == m_Rpt1) && (user.m_Rpt2 == m_Rpt2) && (user.m_Xlx == m_Xlx)); + return ((user.m_My == m_My) && (user.m_Rpt1 == m_Rpt1) && (user.m_Rpt2 == m_Rpt2) && (user.m_Xlx == m_Xlx)); } bool CUser::operator <(const CUser &user) const { - // smallest is youngest - return (std::difftime(m_LastHeardTime, user.m_LastHeardTime) > 0); + // smallest is youngest + return (std::difftime(m_LastHeardTime, user.m_LastHeardTime) > 0); } //////////////////////////////////////////////////////////////////////////////////////// @@ -73,37 +73,37 @@ bool CUser::operator <(const CUser &user) const void CUser::WriteXml(std::ofstream &xmlFile) { - xmlFile << "" << std::endl; - xmlFile << "\t" << m_My << "" << std::endl; - xmlFile << "\t" << m_Rpt1 << "" << std::endl; - xmlFile << "\t" << m_Rpt2.GetModule() << "" << std::endl; - xmlFile << "\t" << m_Xlx << "" << std::endl; - - char mbstr[100]; - if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime))) - { - xmlFile << "\t" << mbstr << "" << std::endl; - } - xmlFile << "" << std::endl; + xmlFile << "" << std::endl; + xmlFile << "\t" << m_My << "" << std::endl; + xmlFile << "\t" << m_Rpt1 << "" << std::endl; + xmlFile << "\t" << m_Rpt2.GetModule() << "" << std::endl; + xmlFile << "\t" << m_Xlx << "" << std::endl; + + char mbstr[100]; + if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime))) + { + xmlFile << "\t" << mbstr << "" << std::endl; + } + xmlFile << "" << std::endl; } void CUser::GetJsonObject(char *Buffer) { - char sz[512]; - char mbstr[100]; - char my[16]; - char rpt1[16]; - - if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime))) - { - m_My.GetCallsignString(my); - m_Rpt1.GetCallsignString(rpt1); - - ::sprintf(sz, "{\"callsign\":\"%s\",\"node\":\"%s\",\"module\":\"%c\",\"time\":\"%s\"}", - my, - rpt1, - m_Rpt1.GetModule(), - mbstr); - ::strcat(Buffer, sz); - } + char sz[512]; + char mbstr[100]; + char my[16]; + char rpt1[16]; + + if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime))) + { + m_My.GetCallsignString(my); + m_Rpt1.GetCallsignString(rpt1); + + ::sprintf(sz, "{\"callsign\":\"%s\",\"node\":\"%s\",\"module\":\"%c\",\"time\":\"%s\"}", + my, + rpt1, + m_Rpt1.GetModule(), + mbstr); + ::strcat(Buffer, sz); + } } diff --git a/src/cuser.h b/src/cuser.h index 1ef667a..b73bd4d 100644 --- a/src/cuser.h +++ b/src/cuser.h @@ -33,32 +33,32 @@ class CUser { public: - // constructor - CUser(); - CUser(const CCallsign &, const CCallsign &, const CCallsign &, const CCallsign &); - CUser(const CUser &); + // constructor + CUser(); + CUser(const CCallsign &, const CCallsign &, const CCallsign &, const CCallsign &); + CUser(const CUser &); - // destructor - ~CUser() {} + // destructor + ~CUser() {} - // operation - void HeardNow(void) { m_LastHeardTime = std::time(nullptr); } + // operation + void HeardNow(void) { m_LastHeardTime = std::time(nullptr); } - // operators - bool operator ==(const CUser &) const; - bool operator <(const CUser &) const; + // operators + bool operator ==(const CUser &) const; + bool operator <(const CUser &) const; - // reporting - void WriteXml(std::ofstream &); - void GetJsonObject(char *); + // reporting + void WriteXml(std::ofstream &); + void GetJsonObject(char *); protected: - // data - CCallsign m_My; - CCallsign m_Rpt1; - CCallsign m_Rpt2; - CCallsign m_Xlx; - std::time_t m_LastHeardTime; + // data + CCallsign m_My; + CCallsign m_Rpt1; + CCallsign m_Rpt2; + CCallsign m_Xlx; + std::time_t m_LastHeardTime; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cusers.cpp b/src/cusers.cpp index fbb7271..6736f80 100644 --- a/src/cusers.cpp +++ b/src/cusers.cpp @@ -37,17 +37,17 @@ CUsers::CUsers() {} void CUsers::AddUser(const CUser &user) { - // add - m_Users.push_front(user); + // add + m_Users.push_front(user); - // if list size too big, remove oldest - if ( m_Users.size() >= (LASTHEARD_USERS_MAX_SIZE-1) ) - { - m_Users.resize(m_Users.size()-1); - } + // if list size too big, remove oldest + if ( m_Users.size() >= (LASTHEARD_USERS_MAX_SIZE-1) ) + { + m_Users.resize(m_Users.size()-1); + } - // notify - g_Reflector.OnUsersChanged(); + // notify + g_Reflector.OnUsersChanged(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -55,22 +55,22 @@ void CUsers::AddUser(const CUser &user) void CUsers::Hearing(const CCallsign &my, const CCallsign &rpt1, const CCallsign &rpt2) { - Hearing(my, rpt1, rpt2, g_Reflector.GetCallsign()); + Hearing(my, rpt1, rpt2, g_Reflector.GetCallsign()); } void CUsers::Hearing(const CCallsign &my, const CCallsign &rpt1, const CCallsign &rpt2, const CCallsign &xlx) { - CUser heard(my, rpt1, rpt2, xlx); + CUser heard(my, rpt1, rpt2, xlx); - // first check if this user is already listed. If so, erase him. - for ( auto it=begin(); it!=end(); it++ ) - { - if (*it == heard) - { - m_Users.erase(it); + // first check if this user is already listed. If so, erase him. + for ( auto it=begin(); it!=end(); it++ ) + { + if (*it == heard) + { + m_Users.erase(it); break; - } - } + } + } - AddUser(heard); + AddUser(heard); } diff --git a/src/cusers.h b/src/cusers.h index 0227f32..8464050 100644 --- a/src/cusers.h +++ b/src/cusers.h @@ -33,32 +33,32 @@ class CUsers { public: - // constructor - CUsers(); + // constructor + CUsers(); - // destructor - virtual ~CUsers() {} + // destructor + virtual ~CUsers() {} - // locks - void Lock(void) { m_Mutex.lock(); } - void Unlock(void) { m_Mutex.unlock(); } + // locks + void Lock(void) { m_Mutex.lock(); } + void Unlock(void) { m_Mutex.unlock(); } - // management - int GetSize(void) const { return (int)m_Users.size(); } - void AddUser(const CUser &); + // management + int GetSize(void) const { return (int)m_Users.size(); } + void AddUser(const CUser &); // pass-thru std::list::iterator begin() { return m_Users.begin(); } std::list::iterator end() { return m_Users.end(); } - // operation - void Hearing(const CCallsign &, const CCallsign &, const CCallsign &); - void Hearing(const CCallsign &, const CCallsign &, const CCallsign &, const CCallsign &); + // operation + void Hearing(const CCallsign &, const CCallsign &, const CCallsign &); + void Hearing(const CCallsign &, const CCallsign &, const CCallsign &, const CCallsign &); protected: - // data - std::mutex m_Mutex; - std::list m_Users; + // data + std::mutex m_Mutex; + std::list m_Users; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cutils.cpp b/src/cutils.cpp index 32108a9..fe84e45 100644 --- a/src/cutils.cpp +++ b/src/cutils.cpp @@ -18,56 +18,56 @@ void CUtils::byteToBitsBE(unsigned char byte, bool* bits) { - assert(bits != nullptr); + assert(bits != nullptr); - bits[0U] = (byte & 0x80U) == 0x80U; - bits[1U] = (byte & 0x40U) == 0x40U; - bits[2U] = (byte & 0x20U) == 0x20U; - bits[3U] = (byte & 0x10U) == 0x10U; - bits[4U] = (byte & 0x08U) == 0x08U; - bits[5U] = (byte & 0x04U) == 0x04U; - bits[6U] = (byte & 0x02U) == 0x02U; - bits[7U] = (byte & 0x01U) == 0x01U; + bits[0U] = (byte & 0x80U) == 0x80U; + bits[1U] = (byte & 0x40U) == 0x40U; + bits[2U] = (byte & 0x20U) == 0x20U; + bits[3U] = (byte & 0x10U) == 0x10U; + bits[4U] = (byte & 0x08U) == 0x08U; + bits[5U] = (byte & 0x04U) == 0x04U; + bits[6U] = (byte & 0x02U) == 0x02U; + bits[7U] = (byte & 0x01U) == 0x01U; } void CUtils::byteToBitsLE(unsigned char byte, bool* bits) { - assert(bits != nullptr); + assert(bits != nullptr); - bits[0U] = (byte & 0x01U) == 0x01U; - bits[1U] = (byte & 0x02U) == 0x02U; - bits[2U] = (byte & 0x04U) == 0x04U; - bits[3U] = (byte & 0x08U) == 0x08U; - bits[4U] = (byte & 0x10U) == 0x10U; - bits[5U] = (byte & 0x20U) == 0x20U; - bits[6U] = (byte & 0x40U) == 0x40U; - bits[7U] = (byte & 0x80U) == 0x80U; + bits[0U] = (byte & 0x01U) == 0x01U; + bits[1U] = (byte & 0x02U) == 0x02U; + bits[2U] = (byte & 0x04U) == 0x04U; + bits[3U] = (byte & 0x08U) == 0x08U; + bits[4U] = (byte & 0x10U) == 0x10U; + bits[5U] = (byte & 0x20U) == 0x20U; + bits[6U] = (byte & 0x40U) == 0x40U; + bits[7U] = (byte & 0x80U) == 0x80U; } void CUtils::bitsToByteBE(const bool* bits, unsigned char& byte) { - assert(bits != nullptr); + assert(bits != nullptr); - byte = bits[0U] ? 0x80U : 0x00U; - byte |= bits[1U] ? 0x40U : 0x00U; - byte |= bits[2U] ? 0x20U : 0x00U; - byte |= bits[3U] ? 0x10U : 0x00U; - byte |= bits[4U] ? 0x08U : 0x00U; - byte |= bits[5U] ? 0x04U : 0x00U; - byte |= bits[6U] ? 0x02U : 0x00U; - byte |= bits[7U] ? 0x01U : 0x00U; + byte = bits[0U] ? 0x80U : 0x00U; + byte |= bits[1U] ? 0x40U : 0x00U; + byte |= bits[2U] ? 0x20U : 0x00U; + byte |= bits[3U] ? 0x10U : 0x00U; + byte |= bits[4U] ? 0x08U : 0x00U; + byte |= bits[5U] ? 0x04U : 0x00U; + byte |= bits[6U] ? 0x02U : 0x00U; + byte |= bits[7U] ? 0x01U : 0x00U; } void CUtils::bitsToByteLE(const bool* bits, unsigned char& byte) { - assert(bits != nullptr); + assert(bits != nullptr); - byte = bits[0U] ? 0x01U : 0x00U; - byte |= bits[1U] ? 0x02U : 0x00U; - byte |= bits[2U] ? 0x04U : 0x00U; - byte |= bits[3U] ? 0x08U : 0x00U; - byte |= bits[4U] ? 0x10U : 0x00U; - byte |= bits[5U] ? 0x20U : 0x00U; - byte |= bits[6U] ? 0x40U : 0x00U; - byte |= bits[7U] ? 0x80U : 0x00U; + byte = bits[0U] ? 0x01U : 0x00U; + byte |= bits[1U] ? 0x02U : 0x00U; + byte |= bits[2U] ? 0x04U : 0x00U; + byte |= bits[3U] ? 0x08U : 0x00U; + byte |= bits[4U] ? 0x10U : 0x00U; + byte |= bits[5U] ? 0x20U : 0x00U; + byte |= bits[6U] ? 0x40U : 0x00U; + byte |= bits[7U] ? 0x80U : 0x00U; } diff --git a/src/cutils.h b/src/cutils.h index 555a774..0c1cb8c 100644 --- a/src/cutils.h +++ b/src/cutils.h @@ -16,14 +16,15 @@ #include -class CUtils { +class CUtils +{ public: - static void byteToBitsBE(unsigned char byte, bool* bits); - static void byteToBitsLE(unsigned char byte, bool* bits); - - static void bitsToByteBE(const bool* bits, unsigned char& byte); - static void bitsToByteLE(const bool* bits, unsigned char& byte); - + static void byteToBitsBE(unsigned char byte, bool* bits); + static void byteToBitsLE(unsigned char byte, bool* bits); + + static void bitsToByteBE(const bool* bits, unsigned char& byte); + static void bitsToByteLE(const bool* bits, unsigned char& byte); + private: }; diff --git a/src/cversion.cpp b/src/cversion.cpp index 1bbb62c..a5a29d4 100644 --- a/src/cversion.cpp +++ b/src/cversion.cpp @@ -30,16 +30,16 @@ CVersion::CVersion() { - m_iMajor = 0; - m_iMinor = 0; - m_iRevision = 0; + m_iMajor = 0; + m_iMinor = 0; + m_iRevision = 0; } CVersion::CVersion(int iMajor, int iMinor, int iRevision) { - m_iMajor = iMajor; - m_iMinor = iMinor; - m_iRevision = iRevision; + m_iMajor = iMajor; + m_iMinor = iMinor; + m_iRevision = iRevision; } //////////////////////////////////////////////////////////////////////////////////////// @@ -47,25 +47,25 @@ CVersion::CVersion(int iMajor, int iMinor, int iRevision) bool CVersion::IsEqualOrHigherTo(const CVersion &version) const { - if ( m_iMajor > version.m_iMajor ) - { - return true; - } - else if ( m_iMajor == version.m_iMajor ) - { - if ( m_iMinor > version.m_iMinor ) - { - return true; - } - else if ( m_iMinor == version.m_iMinor ) - { - if ( m_iRevision >= version.m_iRevision ) - { - return true; - } - } - } - return false; + if ( m_iMajor > version.m_iMajor ) + { + return true; + } + else if ( m_iMajor == version.m_iMajor ) + { + if ( m_iMinor > version.m_iMinor ) + { + return true; + } + else if ( m_iMinor == version.m_iMinor ) + { + if ( m_iRevision >= version.m_iRevision ) + { + return true; + } + } + } + return false; } //////////////////////////////////////////////////////////////////////////////////////// @@ -73,7 +73,7 @@ bool CVersion::IsEqualOrHigherTo(const CVersion &version) const bool CVersion::operator ==(const CVersion &Version) const { - return ( (Version.m_iMajor == m_iMajor) && - (Version.m_iMinor == m_iMinor) && - (Version.m_iRevision == m_iRevision )) ; + return ( (Version.m_iMajor == m_iMajor) && + (Version.m_iMinor == m_iMinor) && + (Version.m_iRevision == m_iRevision )) ; } diff --git a/src/cversion.h b/src/cversion.h index e281677..8c86d3a 100644 --- a/src/cversion.h +++ b/src/cversion.h @@ -33,26 +33,26 @@ class CVersion { public: - // constructor - CVersion(); - CVersion(int, int, int); + // constructor + CVersion(); + CVersion(int, int, int); - // get - int GetMajor(void) const { return m_iMajor; } - int GetMinor(void) const { return m_iMinor; } - int GetRevision(void) const { return m_iRevision; } + // get + int GetMajor(void) const { return m_iMajor; } + int GetMinor(void) const { return m_iMinor; } + int GetRevision(void) const { return m_iRevision; } - // comparaison - bool IsEqualOrHigherTo(const CVersion &) const; + // comparaison + bool IsEqualOrHigherTo(const CVersion &) const; - // operator - bool operator ==(const CVersion &) const; + // operator + bool operator ==(const CVersion &) const; protected: - // data - int m_iMajor; - int m_iMinor; - int m_iRevision; + // data + int m_iMajor; + int m_iMinor; + int m_iRevision; }; diff --git a/src/cwiresxcmd.cpp b/src/cwiresxcmd.cpp index 2779039..91b2cf6 100644 --- a/src/cwiresxcmd.cpp +++ b/src/cwiresxcmd.cpp @@ -31,15 +31,15 @@ CWiresxCmd::CWiresxCmd() { - m_iCmd = WIRESX_CMD_UNKNOWN; - m_Time.Now(); + m_iCmd = WIRESX_CMD_UNKNOWN; + m_Time.Now(); } CWiresxCmd::CWiresxCmd(const CIp &Ip, const CCallsign &Callsign, int iCmd, int iArg) { - m_Ip = Ip; - m_Callsign = Callsign; - m_iCmd = iCmd; - m_iArg = iArg; - m_Time.Now(); + m_Ip = Ip; + m_Callsign = Callsign; + m_iCmd = iCmd; + m_iArg = iArg; + m_Time.Now(); } diff --git a/src/cwiresxcmd.h b/src/cwiresxcmd.h index 6acc3bc..e97752c 100644 --- a/src/cwiresxcmd.h +++ b/src/cwiresxcmd.h @@ -47,24 +47,24 @@ class CWiresxCmd { public: - // constructor - CWiresxCmd(); - CWiresxCmd(const CIp &, const CCallsign &, int, int); + // constructor + CWiresxCmd(); + CWiresxCmd(const CIp &, const CCallsign &, int, int); - // get - const CCallsign &GetCallsign(void) const { return m_Callsign; } - const CIp &GetIp(void) const { return m_Ip; } - int GetCmd(void) const { return m_iCmd; } - int GetArg(void) const { return m_iArg; } - const CTimePoint &GetTime(void) const { return m_Time; } + // get + const CCallsign &GetCallsign(void) const { return m_Callsign; } + const CIp &GetIp(void) const { return m_Ip; } + int GetCmd(void) const { return m_iCmd; } + int GetArg(void) const { return m_iArg; } + const CTimePoint &GetTime(void) const { return m_Time; } protected: - // data - CIp m_Ip; - CCallsign m_Callsign; - int m_iCmd; - int m_iArg; - CTimePoint m_Time; + // data + CIp m_Ip; + CCallsign m_Callsign; + int m_iCmd; + int m_iArg; + CTimePoint m_Time; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cwiresxcmdhandler.cpp b/src/cwiresxcmdhandler.cpp index 5d6334e..a99dbc8 100644 --- a/src/cwiresxcmdhandler.cpp +++ b/src/cwiresxcmdhandler.cpp @@ -39,9 +39,9 @@ CWiresxCmdHandler::CWiresxCmdHandler() { - m_seqNo = 0; - keep_running = true; - m_pThread = nullptr; + m_seqNo = 0; + keep_running = true; + m_pThread = nullptr; } @@ -50,22 +50,22 @@ CWiresxCmdHandler::CWiresxCmdHandler() CWiresxCmdHandler::~CWiresxCmdHandler() { - // kill threads - keep_running = false; - if ( m_pThread != nullptr ) - { - m_pThread->join(); - delete m_pThread; + // kill threads + keep_running = false; + if ( m_pThread != nullptr ) + { + m_pThread->join(); + delete m_pThread; m_pThread = nullptr; - } - - // empty queue - m_CmdQueue.Lock(); - while ( !m_CmdQueue.empty() ) - { - m_CmdQueue.pop(); - } - m_CmdQueue.Unlock(); + } + + // empty queue + m_CmdQueue.Lock(); + while ( !m_CmdQueue.empty() ) + { + m_CmdQueue.pop(); + } + m_CmdQueue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -73,30 +73,30 @@ CWiresxCmdHandler::~CWiresxCmdHandler() bool CWiresxCmdHandler::Init(void) { - // fill our wiresx info - m_ReflectorWiresxInfo.SetCallsign(g_Reflector.GetCallsign()); - m_ReflectorWiresxInfo.SetNode(g_Reflector.GetCallsign()); - m_ReflectorWiresxInfo.SetName("Reflector"); + // fill our wiresx info + m_ReflectorWiresxInfo.SetCallsign(g_Reflector.GetCallsign()); + m_ReflectorWiresxInfo.SetNode(g_Reflector.GetCallsign()); + m_ReflectorWiresxInfo.SetName("Reflector"); - // reset stop flag - keep_running = true; + // reset stop flag + keep_running = true; - // start thread; - m_pThread = new std::thread(CWiresxCmdHandler::Thread, this); + // start thread; + m_pThread = new std::thread(CWiresxCmdHandler::Thread, this); - // done - return true; + // done + return true; } void CWiresxCmdHandler::Close(void) { - keep_running = false; - if ( m_pThread != nullptr ) - { - m_pThread->join(); - delete m_pThread; - m_pThread = nullptr; - } + keep_running = false; + if ( m_pThread != nullptr ) + { + m_pThread->join(); + delete m_pThread; + m_pThread = nullptr; + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -104,10 +104,10 @@ void CWiresxCmdHandler::Close(void) void CWiresxCmdHandler::Thread(CWiresxCmdHandler *This) { - while (This->keep_running) - { - This->Task(); - } + while (This->keep_running) + { + This->Task(); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -115,115 +115,115 @@ void CWiresxCmdHandler::Thread(CWiresxCmdHandler *This) void CWiresxCmdHandler::Task(void) { - CWiresxInfo Info; - CWiresxCmd Cmd; - uint32 uiNodeTxFreq; - uint32 uiNodeRxFreq; - char cModule; - bool bCmd; - - // anything to do ? - bCmd = false; - m_CmdQueue.Lock(); - { - // any cmd in our queue ? - if ( !m_CmdQueue.empty() ) - { - // yes, get the command - Cmd = m_CmdQueue.front(); - // check that the command is at least one second old - // so that the so delayed processing of the command - // introduce the delay the radio needs to switch - // from tx to rx - if ( Cmd.GetTime().DurationSinceNow() >= WIRESX_REPLY_DELAY ) - { - m_CmdQueue.pop(); - bCmd = true; - } - } - } - m_CmdQueue.Unlock(); - - - // handle it - if ( bCmd ) - { - // fill our info object - Info = m_ReflectorWiresxInfo; - g_YsfNodeDir.FindFrequencies(Cmd.GetCallsign(), &uiNodeTxFreq, &uiNodeRxFreq); - Info.SetFrequencies(uiNodeTxFreq, uiNodeRxFreq); - - // find our client and the module it's currentlink linked to - cModule = ' '; - CClients *clients = g_Reflector.GetClients(); - std::shared_ptrclient = clients->FindClient(Cmd.GetCallsign(), Cmd.GetIp(), PROTOCOL_YSF); - if ( client != nullptr ) - { - cModule = client->GetReflectorModule(); - } - g_Reflector.ReleaseClients(); - - // and crack the cmd - switch ( Cmd.GetCmd() ) - { - case WIRESX_CMD_DX_REQ: - std::cout << "Wires-X DX_REQ command from " << Cmd.GetCallsign() << " at " << Cmd.GetIp() << std::endl; - // reply - ReplyToWiresxDxReqPacket(Cmd.GetIp(), Info, cModule); - break; - case WIRESX_CMD_ALL_REQ: - case WIRESX_CMD_SEARCH_REQ: - std::cout << "Wires-X ALL_REQ command from " << Cmd.GetCallsign() << " at " << Cmd.GetIp() << std::endl; - // reply - ReplyToWiresxAllReqPacket(Cmd.GetIp(), Info, Cmd.GetArg()); - break; - case WIRESX_CMD_CONN_REQ: - if ( (Cmd.GetArg() >= 1) && (Cmd.GetArg() <= NB_OF_MODULES) ) - { - cModule = 'A' + (char)(Cmd.GetArg() - 1); - std::cout << "Wires-X CONN_REQ command to link on module " << cModule << " from " << Cmd.GetCallsign() << " at " << Cmd.GetIp() << std::endl; - // acknowledge - ReplyToWiresxConnReqPacket(Cmd.GetIp(), Info, cModule); - // change client's module - CClients *clients = g_Reflector.GetClients(); - std::shared_ptrclient = clients->FindClient(Cmd.GetCallsign(), Cmd.GetIp(), PROTOCOL_YSF); - if ( client != nullptr ) - { - client->SetReflectorModule(cModule); - } - g_Reflector.ReleaseClients(); - } - else - { - std::cout << "Wires-X CONN_REQ command with illegal argument from " << Cmd.GetCallsign() << " at " << Cmd.GetIp() << std::endl; - } - break; - case WIRESX_CMD_DISC_REQ: - std::cout << "Wires-X DISC_REQ command from " << Cmd.GetCallsign() << " at " << Cmd.GetIp() << std::endl; - // and reply - ReplyToWiresxDiscReqPacket(Cmd.GetIp(), Info); - // change client's module - { - CClients *clients = g_Reflector.GetClients(); - std::shared_ptrclient = clients->FindClient(Cmd.GetCallsign(), Cmd.GetIp(), PROTOCOL_YSF); - if ( client != nullptr ) - { - client->SetReflectorModule(' '); - } - g_Reflector.ReleaseClients(); - } - break; - case WIRESX_CMD_UNKNOWN: - default: - std::cout << "Wires-X non implemented command from " << Cmd.GetCallsign() << " at " << Cmd.GetIp() << std::endl; - break; - } - } - else - { - // if nothing to do, sleep a bit - CTimePoint::TaskSleepFor(10); - } + CWiresxInfo Info; + CWiresxCmd Cmd; + uint32 uiNodeTxFreq; + uint32 uiNodeRxFreq; + char cModule; + bool bCmd; + + // anything to do ? + bCmd = false; + m_CmdQueue.Lock(); + { + // any cmd in our queue ? + if ( !m_CmdQueue.empty() ) + { + // yes, get the command + Cmd = m_CmdQueue.front(); + // check that the command is at least one second old + // so that the so delayed processing of the command + // introduce the delay the radio needs to switch + // from tx to rx + if ( Cmd.GetTime().DurationSinceNow() >= WIRESX_REPLY_DELAY ) + { + m_CmdQueue.pop(); + bCmd = true; + } + } + } + m_CmdQueue.Unlock(); + + + // handle it + if ( bCmd ) + { + // fill our info object + Info = m_ReflectorWiresxInfo; + g_YsfNodeDir.FindFrequencies(Cmd.GetCallsign(), &uiNodeTxFreq, &uiNodeRxFreq); + Info.SetFrequencies(uiNodeTxFreq, uiNodeRxFreq); + + // find our client and the module it's currentlink linked to + cModule = ' '; + CClients *clients = g_Reflector.GetClients(); + std::shared_ptrclient = clients->FindClient(Cmd.GetCallsign(), Cmd.GetIp(), PROTOCOL_YSF); + if ( client != nullptr ) + { + cModule = client->GetReflectorModule(); + } + g_Reflector.ReleaseClients(); + + // and crack the cmd + switch ( Cmd.GetCmd() ) + { + case WIRESX_CMD_DX_REQ: + std::cout << "Wires-X DX_REQ command from " << Cmd.GetCallsign() << " at " << Cmd.GetIp() << std::endl; + // reply + ReplyToWiresxDxReqPacket(Cmd.GetIp(), Info, cModule); + break; + case WIRESX_CMD_ALL_REQ: + case WIRESX_CMD_SEARCH_REQ: + std::cout << "Wires-X ALL_REQ command from " << Cmd.GetCallsign() << " at " << Cmd.GetIp() << std::endl; + // reply + ReplyToWiresxAllReqPacket(Cmd.GetIp(), Info, Cmd.GetArg()); + break; + case WIRESX_CMD_CONN_REQ: + if ( (Cmd.GetArg() >= 1) && (Cmd.GetArg() <= NB_OF_MODULES) ) + { + cModule = 'A' + (char)(Cmd.GetArg() - 1); + std::cout << "Wires-X CONN_REQ command to link on module " << cModule << " from " << Cmd.GetCallsign() << " at " << Cmd.GetIp() << std::endl; + // acknowledge + ReplyToWiresxConnReqPacket(Cmd.GetIp(), Info, cModule); + // change client's module + CClients *clients = g_Reflector.GetClients(); + std::shared_ptrclient = clients->FindClient(Cmd.GetCallsign(), Cmd.GetIp(), PROTOCOL_YSF); + if ( client != nullptr ) + { + client->SetReflectorModule(cModule); + } + g_Reflector.ReleaseClients(); + } + else + { + std::cout << "Wires-X CONN_REQ command with illegal argument from " << Cmd.GetCallsign() << " at " << Cmd.GetIp() << std::endl; + } + break; + case WIRESX_CMD_DISC_REQ: + std::cout << "Wires-X DISC_REQ command from " << Cmd.GetCallsign() << " at " << Cmd.GetIp() << std::endl; + // and reply + ReplyToWiresxDiscReqPacket(Cmd.GetIp(), Info); + // change client's module + { + CClients *clients = g_Reflector.GetClients(); + std::shared_ptrclient = clients->FindClient(Cmd.GetCallsign(), Cmd.GetIp(), PROTOCOL_YSF); + if ( client != nullptr ) + { + client->SetReflectorModule(' '); + } + g_Reflector.ReleaseClients(); + } + break; + case WIRESX_CMD_UNKNOWN: + default: + std::cout << "Wires-X non implemented command from " << Cmd.GetCallsign() << " at " << Cmd.GetIp() << std::endl; + break; + } + } + else + { + // if nothing to do, sleep a bit + CTimePoint::TaskSleepFor(10); + } } @@ -232,307 +232,307 @@ void CWiresxCmdHandler::Task(void) bool CWiresxCmdHandler::ReplyToWiresxDxReqPacket(const CIp &Ip, const CWiresxInfo &WiresxInfo, char Module) { - uint8 DX_RESP[] = {0x5DU, 0x51U, 0x5FU, 0x26U}; - bool ok; - uint8 data[150U]; - uint8 RoomId; - bool IsLinked; - - // linked module - // module A == 0 - IsLinked = (Module != ' '); - RoomId = (uint8)(Module - 'A'); - - // fill data buffer - ::memset(data, 0x00U, 150U); - ::memset(data, ' ', 128U); - // seq no - data[0U] = m_seqNo; - // command - ::memcpy(data + 1U, DX_RESP, 4U); - // node info - ::memcpy(data + 5U, WiresxInfo.GetId(), 5U); - ::memcpy(data + 10U, WiresxInfo.GetNode(), 10U); - ::memcpy(data + 20U, WiresxInfo.GetName(), 14U); - // linked room - if (!IsLinked) - { - data[34U] = '1'; - data[35U] = '2'; - // no room linked - data[57U] = '0'; - data[58U] = '0'; - data[59U] = '0'; - } - else - { - data[34U] = '1'; - data[35U] = '5'; - // linked room - char item[16U]; - // refl->m_id - ::sprintf(item, "%05d", 4001U + RoomId); - ::memcpy(data + 36U, item, 5U); - // refl->name - ::memset(item, ' ', 16U); - ::memcpy(item, "MODULE", 6U); // K2IE fix for U/C only radios - item[7] = 'A' + RoomId; - ::memcpy(data + 41U, item, 16U); - // refl->count - ::sprintf(item, "%03d", RoomId + 1); - ::memcpy(data + 57U, item, 3U); - // other - ::memset(data + 60U, ' ', 10U); - // refl->m_desc - ::memcpy(data + 70U, "Description ", 14U); - } - - // frequencies - { - unsigned int offset; - char sign; - if (WiresxInfo.GetTxFrequency() >= WiresxInfo.GetRxFrequency()) - { - offset = WiresxInfo.GetTxFrequency() - WiresxInfo.GetRxFrequency(); - sign = '-'; - } - else - { - offset = WiresxInfo.GetRxFrequency() - WiresxInfo.GetTxFrequency(); - sign = '+'; - } - unsigned int freqHz = WiresxInfo.GetTxFrequency() % 1000000U; - unsigned int freqkHz = (freqHz + 500U) / 1000U; - - char freq[30U]; - ::sprintf(freq, "%05u.%03u000%c%03u.%06u", - WiresxInfo.GetTxFrequency() / 1000000U, - freqkHz, sign, offset / 1000000U, offset % 1000000U); - - ::memcpy(data + 84U, freq, 23U); - } - - // EOD & CRC - data[127U] = 0x03U; - data[128U] = CCRC::addCRC(data, 128U); - - // and encode the reply - CBuffer Data; - Data.Set(data, 129U); - ok = EncodeAndSendWiresxPacket(Ip, Data, WiresxInfo); - - // done - m_seqNo++; - return ok; + uint8 DX_RESP[] = {0x5DU, 0x51U, 0x5FU, 0x26U}; + bool ok; + uint8 data[150U]; + uint8 RoomId; + bool IsLinked; + + // linked module + // module A == 0 + IsLinked = (Module != ' '); + RoomId = (uint8)(Module - 'A'); + + // fill data buffer + ::memset(data, 0x00U, 150U); + ::memset(data, ' ', 128U); + // seq no + data[0U] = m_seqNo; + // command + ::memcpy(data + 1U, DX_RESP, 4U); + // node info + ::memcpy(data + 5U, WiresxInfo.GetId(), 5U); + ::memcpy(data + 10U, WiresxInfo.GetNode(), 10U); + ::memcpy(data + 20U, WiresxInfo.GetName(), 14U); + // linked room + if (!IsLinked) + { + data[34U] = '1'; + data[35U] = '2'; + // no room linked + data[57U] = '0'; + data[58U] = '0'; + data[59U] = '0'; + } + else + { + data[34U] = '1'; + data[35U] = '5'; + // linked room + char item[16U]; + // refl->m_id + ::sprintf(item, "%05d", 4001U + RoomId); + ::memcpy(data + 36U, item, 5U); + // refl->name + ::memset(item, ' ', 16U); + ::memcpy(item, "MODULE", 6U); // K2IE fix for U/C only radios + item[7] = 'A' + RoomId; + ::memcpy(data + 41U, item, 16U); + // refl->count + ::sprintf(item, "%03d", RoomId + 1); + ::memcpy(data + 57U, item, 3U); + // other + ::memset(data + 60U, ' ', 10U); + // refl->m_desc + ::memcpy(data + 70U, "Description ", 14U); + } + + // frequencies + { + unsigned int offset; + char sign; + if (WiresxInfo.GetTxFrequency() >= WiresxInfo.GetRxFrequency()) + { + offset = WiresxInfo.GetTxFrequency() - WiresxInfo.GetRxFrequency(); + sign = '-'; + } + else + { + offset = WiresxInfo.GetRxFrequency() - WiresxInfo.GetTxFrequency(); + sign = '+'; + } + unsigned int freqHz = WiresxInfo.GetTxFrequency() % 1000000U; + unsigned int freqkHz = (freqHz + 500U) / 1000U; + + char freq[30U]; + ::sprintf(freq, "%05u.%03u000%c%03u.%06u", + WiresxInfo.GetTxFrequency() / 1000000U, + freqkHz, sign, offset / 1000000U, offset % 1000000U); + + ::memcpy(data + 84U, freq, 23U); + } + + // EOD & CRC + data[127U] = 0x03U; + data[128U] = CCRC::addCRC(data, 128U); + + // and encode the reply + CBuffer Data; + Data.Set(data, 129U); + ok = EncodeAndSendWiresxPacket(Ip, Data, WiresxInfo); + + // done + m_seqNo++; + return ok; } bool CWiresxCmdHandler::ReplyToWiresxAllReqPacket(const CIp &Ip, const CWiresxInfo &WiresxInfo, int Start) { - bool ok = false; - uint8 ALL_RESP[] = {0x5DU, 0x46U, 0x5FU, 0x29U}; - uint8 data[1100U]; - - // fill data buffer - ::memset(data, 0x00U, 1100U); - // seq no - data[0U] = m_seqNo; - // command - ::memcpy(data + 1U, ALL_RESP, 4U); - data[5U] = '2'; - data[6U] = '1'; - // node info - ::memcpy(data + 7U, WiresxInfo.GetId(), 5U); - ::memcpy(data + 12U, WiresxInfo.GetNode(), 10U); - - // number of entries - uint total = NB_OF_MODULES; - uint n = NB_OF_MODULES - Start; - if (n > 20U) - n = 20U; - ::sprintf((char*)(data + 22U), "%03u%03u", n, total); - data[28U] = 0x0DU; - - // entries - uint offset = 29U; - for ( uint i = 0; i < n; i++ ) - { - char item[16U]; - // module A == 0 - int RoomId = i + Start; - - // prepare - ::memset(data + offset, ' ', 50U); - data[offset + 0U] = '5'; - - // refl->m_id - ::sprintf(item, "%05d", 4001U + RoomId); - ::memcpy(data + offset + 1U, item, 5U); - // refl->name - ::memset(item, ' ', 16U); - ::memcpy(item, "MODULE", 6U); // K2IE fix for U/C only radios - item[7] = 'A' + RoomId; - ::memcpy(data + offset + 6U, item, 16U); - // refl->count - ::sprintf(item, "%03d", RoomId + 1); - ::memcpy(data + offset + 22U, item, 3U); - // other - ::memset(data + offset + 25U, ' ', 10U); - // refl->m_desc - ::memcpy(data + offset + 35U, "Description ", 14U); - data[offset + 49U] = 0x0DU; - // next - offset += 50U; - } - - // the following is a workaround for FT2D which - // do not accept less than 20 items frames. - // first send a 'patched' frame - if ( n < 20 ) - { - // FT2D workaround - uint offset2 = offset; - // patch the remaining - uint k = 1029U - offset2; - ::memset(data+offset2, ' ', k); - offset2 += k; - - // EOD + CRC - data[offset2 + 0U] = 0x03U; - data[offset2 + 1U] = CCRC::addCRC(data, offset2 + 1U); - offset2 += 2U; - - // and encode the reply - CBuffer Data; - Data.Set(data, offset2 + 2U); - ok = EncodeAndSendWiresxPacket(Ip, Data, WiresxInfo); - } - - - // and next repeat with normal frame - { - // EOD + CRC - data[offset + 0U] = 0x03U; - data[offset + 1U] = CCRC::addCRC(data, offset + 1U); - offset += 2U; - - // patch the remaining - //uint k = 1031U - offset; - //::memset(data+offset, ' ', k); - //offset += k; - - // and encode the reply - CBuffer Data; - Data.Set(data, offset + 2U); - ok = EncodeAndSendWiresxPacket(Ip, Data, WiresxInfo); - } - - - // done - m_seqNo++; - return ok; + bool ok = false; + uint8 ALL_RESP[] = {0x5DU, 0x46U, 0x5FU, 0x29U}; + uint8 data[1100U]; + + // fill data buffer + ::memset(data, 0x00U, 1100U); + // seq no + data[0U] = m_seqNo; + // command + ::memcpy(data + 1U, ALL_RESP, 4U); + data[5U] = '2'; + data[6U] = '1'; + // node info + ::memcpy(data + 7U, WiresxInfo.GetId(), 5U); + ::memcpy(data + 12U, WiresxInfo.GetNode(), 10U); + + // number of entries + uint total = NB_OF_MODULES; + uint n = NB_OF_MODULES - Start; + if (n > 20U) + n = 20U; + ::sprintf((char*)(data + 22U), "%03u%03u", n, total); + data[28U] = 0x0DU; + + // entries + uint offset = 29U; + for ( uint i = 0; i < n; i++ ) + { + char item[16U]; + // module A == 0 + int RoomId = i + Start; + + // prepare + ::memset(data + offset, ' ', 50U); + data[offset + 0U] = '5'; + + // refl->m_id + ::sprintf(item, "%05d", 4001U + RoomId); + ::memcpy(data + offset + 1U, item, 5U); + // refl->name + ::memset(item, ' ', 16U); + ::memcpy(item, "MODULE", 6U); // K2IE fix for U/C only radios + item[7] = 'A' + RoomId; + ::memcpy(data + offset + 6U, item, 16U); + // refl->count + ::sprintf(item, "%03d", RoomId + 1); + ::memcpy(data + offset + 22U, item, 3U); + // other + ::memset(data + offset + 25U, ' ', 10U); + // refl->m_desc + ::memcpy(data + offset + 35U, "Description ", 14U); + data[offset + 49U] = 0x0DU; + // next + offset += 50U; + } + + // the following is a workaround for FT2D which + // do not accept less than 20 items frames. + // first send a 'patched' frame + if ( n < 20 ) + { + // FT2D workaround + uint offset2 = offset; + // patch the remaining + uint k = 1029U - offset2; + ::memset(data+offset2, ' ', k); + offset2 += k; + + // EOD + CRC + data[offset2 + 0U] = 0x03U; + data[offset2 + 1U] = CCRC::addCRC(data, offset2 + 1U); + offset2 += 2U; + + // and encode the reply + CBuffer Data; + Data.Set(data, offset2 + 2U); + ok = EncodeAndSendWiresxPacket(Ip, Data, WiresxInfo); + } + + + // and next repeat with normal frame + { + // EOD + CRC + data[offset + 0U] = 0x03U; + data[offset + 1U] = CCRC::addCRC(data, offset + 1U); + offset += 2U; + + // patch the remaining + //uint k = 1031U - offset; + //::memset(data+offset, ' ', k); + //offset += k; + + // and encode the reply + CBuffer Data; + Data.Set(data, offset + 2U); + ok = EncodeAndSendWiresxPacket(Ip, Data, WiresxInfo); + } + + + // done + m_seqNo++; + return ok; } bool CWiresxCmdHandler::ReplyToWiresxConnReqPacket(const CIp &Ip, const CWiresxInfo &WiresxInfo, char Module) { - uint8 CONN_RESP[] = {0x5DU, 0x41U, 0x5FU, 0x26U}; - bool ok = false; - uint8 data[110U]; - uint RoomId; - - // linked room - // Module A == 0 - RoomId = (uint8)(Module - 'A'); - - // prepare buffer - ::memset(data, 0x00U, 110U); - ::memset(data, ' ', 90U); - - // seq no - data[0U] = m_seqNo; - // command - ::memcpy(data + 1U, CONN_RESP, 4U); - // node info - ::memcpy(data + 5U, WiresxInfo.GetId(), 5U); - ::memcpy(data + 10U, WiresxInfo.GetNode(), 10U); - ::memcpy(data + 20U, WiresxInfo.GetName(), 14U); - data[34U] = '1'; - data[35U] = '5'; - // entry info - { - char item[16U]; - - // refl->m_id - ::sprintf(item, "%05d", 4001U + RoomId); - ::memcpy(data + 36U, item, 5U); - // refl->name - ::memset(item, ' ', 16U); - ::memcpy(item, "MODULE", 6U); // K2IE fix for U/C only radios - item[7] = 'A' + RoomId; - ::memcpy(data + 41U, item, 16U); - // refl->count - ::sprintf(item, "%03d", RoomId + 1); - ::memcpy(data + 57U, item, 3U); - // refl->m_desc - ::memcpy(data + 70U, "Description ", 14U); - } - data[84U] = '0'; - data[85U] = '0'; - data[86U] = '0'; - data[87U] = '0'; - data[88U] = '0'; - - // EOD + CRC - data[89U] = 0x03U; - data[90U] = CCRC::addCRC(data, 90U); - - // and encode the reply - CBuffer Data; - Data.Set(data, 91U); - ok = EncodeAndSendWiresxPacket(Ip, Data, WiresxInfo); - - // done - m_seqNo++; - return ok; + uint8 CONN_RESP[] = {0x5DU, 0x41U, 0x5FU, 0x26U}; + bool ok = false; + uint8 data[110U]; + uint RoomId; + + // linked room + // Module A == 0 + RoomId = (uint8)(Module - 'A'); + + // prepare buffer + ::memset(data, 0x00U, 110U); + ::memset(data, ' ', 90U); + + // seq no + data[0U] = m_seqNo; + // command + ::memcpy(data + 1U, CONN_RESP, 4U); + // node info + ::memcpy(data + 5U, WiresxInfo.GetId(), 5U); + ::memcpy(data + 10U, WiresxInfo.GetNode(), 10U); + ::memcpy(data + 20U, WiresxInfo.GetName(), 14U); + data[34U] = '1'; + data[35U] = '5'; + // entry info + { + char item[16U]; + + // refl->m_id + ::sprintf(item, "%05d", 4001U + RoomId); + ::memcpy(data + 36U, item, 5U); + // refl->name + ::memset(item, ' ', 16U); + ::memcpy(item, "MODULE", 6U); // K2IE fix for U/C only radios + item[7] = 'A' + RoomId; + ::memcpy(data + 41U, item, 16U); + // refl->count + ::sprintf(item, "%03d", RoomId + 1); + ::memcpy(data + 57U, item, 3U); + // refl->m_desc + ::memcpy(data + 70U, "Description ", 14U); + } + data[84U] = '0'; + data[85U] = '0'; + data[86U] = '0'; + data[87U] = '0'; + data[88U] = '0'; + + // EOD + CRC + data[89U] = 0x03U; + data[90U] = CCRC::addCRC(data, 90U); + + // and encode the reply + CBuffer Data; + Data.Set(data, 91U); + ok = EncodeAndSendWiresxPacket(Ip, Data, WiresxInfo); + + // done + m_seqNo++; + return ok; } bool CWiresxCmdHandler::ReplyToWiresxDiscReqPacket(const CIp &Ip, const CWiresxInfo &WiresxInfo) { - uint8 DISC_RESP[] = {0x5DU, 0x41U, 0x5FU, 0x26U}; - bool ok = false; - uint8 data[110U]; - - // prepare buffer - ::memset(data, 0x00U, 110U); - ::memset(data, ' ', 90U); - - // seq no - data[0U] = m_seqNo; - // command - ::memcpy(data + 1U, DISC_RESP, 4U); - // node info - ::memcpy(data + 5U, WiresxInfo.GetId(), 5U); - ::memcpy(data + 10U, WiresxInfo.GetNode(), 10U); - ::memcpy(data + 20U, WiresxInfo.GetName(), 14U); - // data - data[34U] = '1'; - data[35U] = '2'; - - data[57U] = '0'; - data[58U] = '0'; - data[59U] = '0'; - - // EOD + CRC - data[89U] = 0x03U; - data[90U] = CCRC::addCRC(data, 90U); - - // and encode the reply - CBuffer Data; - Data.Set(data, 91U); - ok = EncodeAndSendWiresxPacket(Ip, Data, WiresxInfo); - - // done - m_seqNo++; - return ok; + uint8 DISC_RESP[] = {0x5DU, 0x41U, 0x5FU, 0x26U}; + bool ok = false; + uint8 data[110U]; + + // prepare buffer + ::memset(data, 0x00U, 110U); + ::memset(data, ' ', 90U); + + // seq no + data[0U] = m_seqNo; + // command + ::memcpy(data + 1U, DISC_RESP, 4U); + // node info + ::memcpy(data + 5U, WiresxInfo.GetId(), 5U); + ::memcpy(data + 10U, WiresxInfo.GetNode(), 10U); + ::memcpy(data + 20U, WiresxInfo.GetName(), 14U); + // data + data[34U] = '1'; + data[35U] = '2'; + + data[57U] = '0'; + data[58U] = '0'; + data[59U] = '0'; + + // EOD + CRC + data[89U] = 0x03U; + data[90U] = CCRC::addCRC(data, 90U); + + // and encode the reply + CBuffer Data; + Data.Set(data, 91U); + ok = EncodeAndSendWiresxPacket(Ip, Data, WiresxInfo); + + // done + m_seqNo++; + return ok; } @@ -542,170 +542,170 @@ bool CWiresxCmdHandler::ReplyToWiresxDiscReqPacket(const CIp &Ip, const CWiresxI bool CWiresxCmdHandler::EncodeAndSendWiresxPacket(const CIp &Ip, const CBuffer &DataOrg, const CWiresxInfo &WiresxInfo) { - uint8 DEFAULT_FICH[] = {0x20U, 0x00U, 0x01U, 0x00U}; - uint8 NET_HEADER[] = "YSFD ALL "; - CYSFFICH fich; - CYSFPayload payload; - uint8 buffer[200U]; - - - CBuffer Data(DataOrg); - - // seq no - uint8 seqNo = 0U; - - // calculate bt and adjust length - uint length = (uint)Data.size(); - uint8 bt = 0; - if (length > 260U) - { - bt = 1U; - bt += (length - 260U) / 259U; - length += bt; - } - if (length > 20U) - { - uint blocks = (length - 20U) / 40U; - if ((length % 40U) > 0U) - blocks++; - length = blocks * 40U + 20U; - } - else - { - length = 20U; - } - if ( length > (uint)Data.size() ) - { - Data.Append((uint8)0x20U, (int)(length - (uint)Data.size())); - } - - // ft - uint8 ft = WiresxCalcFt(length, 0U); - - // Write the header - { - //header - ::memcpy(buffer, NET_HEADER, 34U); - ::memcpy(buffer + 4U, WiresxInfo.GetCallsign(), 10U); - ::memcpy(buffer + 14U, WiresxInfo.GetNode(), 10U); - // sync - ::memcpy(buffer + 35U, YSF_SYNC_BYTES, YSF_SYNC_LENGTH_BYTES); - // Fich - fich.load(DEFAULT_FICH); - fich.setFI(YSF_FI_HEADER); - fich.setBT(bt); - fich.setFT(ft); - fich.encode(buffer + 35U + 5U); - // payload - payload.writeDataFRModeData1(WiresxInfo.GetCsd1(), buffer + 35U); - payload.writeDataFRModeData2(WiresxInfo.GetCsd2(), buffer + 35U); - // seqno - buffer[34U] = seqNo; - seqNo += 2U; - // and post it - SendPacket(Ip, buffer); - } - - // write the payload - fich.setFI(YSF_FI_COMMUNICATIONS); - uint offset = 0; - for ( uint8 bn = 0; bn <= bt; bn++ ) - { - for ( uint8 fn = 0; fn <= ft; fn++ ) - { - // fich - fich.setFT(ft); - fich.setFN(fn); - fich.setBT(bt); - fich.setBN(bn); - fich.encode(buffer + 35U + 5U); - // seq no - buffer[34U] = seqNo; - seqNo += 2U; - // data - //if ( (bn == 0) && (fn == 0) ) - if ( fn == 0 ) - { - payload.writeDataFRModeData1(WiresxInfo.GetCsd1(), buffer + 35); - payload.writeDataFRModeData2(WiresxInfo.GetCsd2(), buffer + 35); - } - //else if ( (bn == 0) && (fn == 1) ) - else if ( fn == 1 ) - { - if ( bn == 0 ) - { - payload.writeDataFRModeData1(WiresxInfo.GetCsd3(), buffer + 35); - payload.writeDataFRModeData2(Data.data() + offset, buffer + 35); - offset += 20; - } - else - { - uint8 temp[20U]; - temp[0U] = 0x00U; - ::memcpy(temp + 1U, Data.data() + offset, 19U); - payload.writeDataFRModeData2(temp, buffer + 35U); - offset += 19U; - } - } - else - { - payload.writeDataFRModeData1(Data.data() + offset, buffer + 35); - offset += 20; - payload.writeDataFRModeData2(Data.data() + offset, buffer + 35); - offset += 20; - } - // and post it - SendPacket(Ip, buffer); - // and some delay before next packet - CTimePoint::TaskSleepFor(100); - } - } - - // Write the trailer - { - // fich - fich.setFI(YSF_FI_TERMINATOR); - fich.setFN(ft); - fich.setBN(bt); - fich.encode(buffer + 35U + 5U); - // payload - payload.writeDataFRModeData1(WiresxInfo.GetCsd1(), buffer + 35U); - payload.writeDataFRModeData2(WiresxInfo.GetCsd2(), buffer + 35U); - // seq no - buffer[34U] = seqNo | 0x01U; - // and post it - SendPacket(Ip, buffer); - } - - // done - return true; + uint8 DEFAULT_FICH[] = {0x20U, 0x00U, 0x01U, 0x00U}; + uint8 NET_HEADER[] = "YSFD ALL "; + CYSFFICH fich; + CYSFPayload payload; + uint8 buffer[200U]; + + + CBuffer Data(DataOrg); + + // seq no + uint8 seqNo = 0U; + + // calculate bt and adjust length + uint length = (uint)Data.size(); + uint8 bt = 0; + if (length > 260U) + { + bt = 1U; + bt += (length - 260U) / 259U; + length += bt; + } + if (length > 20U) + { + uint blocks = (length - 20U) / 40U; + if ((length % 40U) > 0U) + blocks++; + length = blocks * 40U + 20U; + } + else + { + length = 20U; + } + if ( length > (uint)Data.size() ) + { + Data.Append((uint8)0x20U, (int)(length - (uint)Data.size())); + } + + // ft + uint8 ft = WiresxCalcFt(length, 0U); + + // Write the header + { + //header + ::memcpy(buffer, NET_HEADER, 34U); + ::memcpy(buffer + 4U, WiresxInfo.GetCallsign(), 10U); + ::memcpy(buffer + 14U, WiresxInfo.GetNode(), 10U); + // sync + ::memcpy(buffer + 35U, YSF_SYNC_BYTES, YSF_SYNC_LENGTH_BYTES); + // Fich + fich.load(DEFAULT_FICH); + fich.setFI(YSF_FI_HEADER); + fich.setBT(bt); + fich.setFT(ft); + fich.encode(buffer + 35U + 5U); + // payload + payload.writeDataFRModeData1(WiresxInfo.GetCsd1(), buffer + 35U); + payload.writeDataFRModeData2(WiresxInfo.GetCsd2(), buffer + 35U); + // seqno + buffer[34U] = seqNo; + seqNo += 2U; + // and post it + SendPacket(Ip, buffer); + } + + // write the payload + fich.setFI(YSF_FI_COMMUNICATIONS); + uint offset = 0; + for ( uint8 bn = 0; bn <= bt; bn++ ) + { + for ( uint8 fn = 0; fn <= ft; fn++ ) + { + // fich + fich.setFT(ft); + fich.setFN(fn); + fich.setBT(bt); + fich.setBN(bn); + fich.encode(buffer + 35U + 5U); + // seq no + buffer[34U] = seqNo; + seqNo += 2U; + // data + //if ( (bn == 0) && (fn == 0) ) + if ( fn == 0 ) + { + payload.writeDataFRModeData1(WiresxInfo.GetCsd1(), buffer + 35); + payload.writeDataFRModeData2(WiresxInfo.GetCsd2(), buffer + 35); + } + //else if ( (bn == 0) && (fn == 1) ) + else if ( fn == 1 ) + { + if ( bn == 0 ) + { + payload.writeDataFRModeData1(WiresxInfo.GetCsd3(), buffer + 35); + payload.writeDataFRModeData2(Data.data() + offset, buffer + 35); + offset += 20; + } + else + { + uint8 temp[20U]; + temp[0U] = 0x00U; + ::memcpy(temp + 1U, Data.data() + offset, 19U); + payload.writeDataFRModeData2(temp, buffer + 35U); + offset += 19U; + } + } + else + { + payload.writeDataFRModeData1(Data.data() + offset, buffer + 35); + offset += 20; + payload.writeDataFRModeData2(Data.data() + offset, buffer + 35); + offset += 20; + } + // and post it + SendPacket(Ip, buffer); + // and some delay before next packet + CTimePoint::TaskSleepFor(100); + } + } + + // Write the trailer + { + // fich + fich.setFI(YSF_FI_TERMINATOR); + fich.setFN(ft); + fich.setBN(bt); + fich.encode(buffer + 35U + 5U); + // payload + payload.writeDataFRModeData1(WiresxInfo.GetCsd1(), buffer + 35U); + payload.writeDataFRModeData2(WiresxInfo.GetCsd2(), buffer + 35U); + // seq no + buffer[34U] = seqNo | 0x01U; + // and post it + SendPacket(Ip, buffer); + } + + // done + return true; } uint8 CWiresxCmdHandler::WiresxCalcFt(uint length, uint offset) const { - length -= offset; - if (length > 220U) return 7U; - if (length > 180U) return 6U; - if (length > 140U) return 5U; - if (length > 100U) return 4U; - if (length > 60U) return 3U; - if (length > 20U) return 2U; - return 1U; + length -= offset; + if (length > 220U) return 7U; + if (length > 180U) return 6U; + if (length > 140U) return 5U; + if (length > 100U) return 4U; + if (length > 60U) return 3U; + if (length > 20U) return 2U; + return 1U; } void CWiresxCmdHandler::SendPacket(const CIp &Ip, uint8 *Buffer) { - //CBuffer packet(Buffer, 155); - //DebugTestDecodePacket(packet); - - // and push in queue - m_PacketQueue.Lock(); - { - m_PacketQueue.push(CWiresxPacket(CBuffer(Buffer, 155), Ip)); - } - m_PacketQueue.Unlock(); + //CBuffer packet(Buffer, 155); + //DebugTestDecodePacket(packet); + + // and push in queue + m_PacketQueue.Lock(); + { + m_PacketQueue.push(CWiresxPacket(CBuffer(Buffer, 155), Ip)); + } + m_PacketQueue.Unlock(); } @@ -715,61 +715,61 @@ void CWiresxCmdHandler::SendPacket(const CIp &Ip, uint8 *Buffer) #ifdef DEBUG_DUMPFILE bool CWiresxCmdHandler::DebugTestDecodePacket(const CBuffer &Buffer) { - uint8 tag[] = { 'Y','S','F','D' }; - static uint8 command[4098]; - static int len; - CYSFFICH Fich; - CYSFPayload payload; - CBuffer dump; - bool valid = false; - - if ( (Buffer.size() == 155) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - // decode YSH fich - if ( Fich.decode(&(Buffer.data()[40])) ) - { - std::cout << (int)Fich.getDT() << "," - << (int)Fich.getFI() << "," - << (int)Fich.getBN() << "," - << (int)Fich.getBT() << "," - << (int)Fich.getFN() << "," - << (int)Fich.getFT() << " : "; - - switch ( Fich.getFI() ) - { - case YSF_FI_HEADER: - len = 0; - ::memset(command, 0x00, sizeof(command)); - std::cout << "Header" << std::endl; - break; - case YSF_FI_TERMINATOR: - std::cout << "Trailer" << std::endl; - std::cout << "length of payload : " << len << std::endl; - dump.Set(command, len); - dump.DebugDump(g_Reflector.m_DebugFile); - dump.DebugDumpAscii(g_Reflector.m_DebugFile); - break; - case YSF_FI_COMMUNICATIONS: - if ( Fich.getDT() == YSF_DT_DATA_FR_MODE ) - { - valid = payload.readDataFRModeData1(&(Buffer.data()[35]), command + len); - len += 20; - valid &= payload.readDataFRModeData2(&(Buffer.data()[35]), command + len); - len += 20; - std::cout << "decoded ok" << std::endl; - } - break; - } - } - else - { - std::cout << "invalid fich in packet" << std::endl; - } - } - else - { - std::cout << "invalid size packet" << std::endl; - } - return valid; + uint8 tag[] = { 'Y','S','F','D' }; + static uint8 command[4098]; + static int len; + CYSFFICH Fich; + CYSFPayload payload; + CBuffer dump; + bool valid = false; + + if ( (Buffer.size() == 155) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + // decode YSH fich + if ( Fich.decode(&(Buffer.data()[40])) ) + { + std::cout << (int)Fich.getDT() << "," + << (int)Fich.getFI() << "," + << (int)Fich.getBN() << "," + << (int)Fich.getBT() << "," + << (int)Fich.getFN() << "," + << (int)Fich.getFT() << " : "; + + switch ( Fich.getFI() ) + { + case YSF_FI_HEADER: + len = 0; + ::memset(command, 0x00, sizeof(command)); + std::cout << "Header" << std::endl; + break; + case YSF_FI_TERMINATOR: + std::cout << "Trailer" << std::endl; + std::cout << "length of payload : " << len << std::endl; + dump.Set(command, len); + dump.DebugDump(g_Reflector.m_DebugFile); + dump.DebugDumpAscii(g_Reflector.m_DebugFile); + break; + case YSF_FI_COMMUNICATIONS: + if ( Fich.getDT() == YSF_DT_DATA_FR_MODE ) + { + valid = payload.readDataFRModeData1(&(Buffer.data()[35]), command + len); + len += 20; + valid &= payload.readDataFRModeData2(&(Buffer.data()[35]), command + len); + len += 20; + std::cout << "decoded ok" << std::endl; + } + break; + } + } + else + { + std::cout << "invalid fich in packet" << std::endl; + } + } + else + { + std::cout << "invalid size packet" << std::endl; + } + return valid; } #endif diff --git a/src/cwiresxcmdhandler.h b/src/cwiresxcmdhandler.h index ae9ce05..5cd2e8f 100644 --- a/src/cwiresxcmdhandler.h +++ b/src/cwiresxcmdhandler.h @@ -39,55 +39,55 @@ class CWiresxCmdHandler { public: - // constructor - CWiresxCmdHandler(); + // constructor + CWiresxCmdHandler(); - // destructor - virtual ~CWiresxCmdHandler(); + // destructor + virtual ~CWiresxCmdHandler(); - // initialization - virtual bool Init(void); - virtual void Close(void); + // initialization + virtual bool Init(void); + virtual void Close(void); - // queues - CWiresxCmdQueue *GetCmdQueue(void) { m_CmdQueue.Lock(); return &m_CmdQueue; } - void ReleaseCmdQueue(void) { m_CmdQueue.Unlock(); } - CWiresxPacketQueue *GetPacketQueue(void) { m_PacketQueue.Lock(); return &m_PacketQueue; } - void ReleasePacketQueue(void) { m_PacketQueue.Unlock(); } + // queues + CWiresxCmdQueue *GetCmdQueue(void) { m_CmdQueue.Lock(); return &m_CmdQueue; } + void ReleaseCmdQueue(void) { m_CmdQueue.Unlock(); } + CWiresxPacketQueue *GetPacketQueue(void) { m_PacketQueue.Lock(); return &m_PacketQueue; } + void ReleasePacketQueue(void) { m_PacketQueue.Unlock(); } - // get + // get - // task - static void Thread(CWiresxCmdHandler *); - virtual void Task(void); + // task + static void Thread(CWiresxCmdHandler *); + virtual void Task(void); protected: - // packet encoding - bool ReplyToWiresxDxReqPacket(const CIp &, const CWiresxInfo &, char); - bool ReplyToWiresxAllReqPacket(const CIp &, const CWiresxInfo &, int); - bool ReplyToWiresxConnReqPacket(const CIp &, const CWiresxInfo &, char); - bool ReplyToWiresxDiscReqPacket(const CIp &, const CWiresxInfo &); + // packet encoding + bool ReplyToWiresxDxReqPacket(const CIp &, const CWiresxInfo &, char); + bool ReplyToWiresxAllReqPacket(const CIp &, const CWiresxInfo &, int); + bool ReplyToWiresxConnReqPacket(const CIp &, const CWiresxInfo &, char); + bool ReplyToWiresxDiscReqPacket(const CIp &, const CWiresxInfo &); - // packet encoding helpers - bool EncodeAndSendWiresxPacket(const CIp &, const CBuffer &, const CWiresxInfo &); - uint8 WiresxCalcFt(uint, uint) const; - void SendPacket(const CIp &, uint8 *); + // packet encoding helpers + bool EncodeAndSendWiresxPacket(const CIp &, const CBuffer &, const CWiresxInfo &); + uint8 WiresxCalcFt(uint, uint) const; + void SendPacket(const CIp &, uint8 *); - // debug - bool DebugTestDecodePacket(const CBuffer &); + // debug + bool DebugTestDecodePacket(const CBuffer &); protected: - // data - CWiresxInfo m_ReflectorWiresxInfo; - uint8_t m_seqNo; + // data + CWiresxInfo m_ReflectorWiresxInfo; + uint8_t m_seqNo; - // queues - CWiresxCmdQueue m_CmdQueue; - CWiresxPacketQueue m_PacketQueue; + // queues + CWiresxCmdQueue m_CmdQueue; + CWiresxPacketQueue m_PacketQueue; - // thread - std::atomic keep_running; - std::thread *m_pThread; + // thread + std::atomic keep_running; + std::thread *m_pThread; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cwiresxcmdqueue.h b/src/cwiresxcmdqueue.h index 7567d30..f8fb4fd 100644 --- a/src/cwiresxcmdqueue.h +++ b/src/cwiresxcmdqueue.h @@ -37,15 +37,15 @@ class CWiresxCmdQueue { public: - // constructor - CWiresxCmdQueue() {} + // constructor + CWiresxCmdQueue() {} - // destructor - ~CWiresxCmdQueue() {} + // destructor + ~CWiresxCmdQueue() {} - // lock - void Lock() { m_Mutex.lock(); } - void Unlock() { m_Mutex.unlock(); } + // lock + void Lock() { m_Mutex.lock(); } + void Unlock() { m_Mutex.unlock(); } // pass thru CWiresxCmd front() { return queue.front(); } @@ -54,8 +54,8 @@ public: bool empty() const { return queue.empty(); } protected: - // status - std::mutex m_Mutex; + // status + std::mutex m_Mutex; std::queue queue; }; diff --git a/src/cwiresxinfo.cpp b/src/cwiresxinfo.cpp index b2aacc8..1c50f45 100644 --- a/src/cwiresxinfo.cpp +++ b/src/cwiresxinfo.cpp @@ -33,16 +33,16 @@ CWiresxInfo::CWiresxInfo() { - ::memset(m_callsign, ' ', YSF_CALLSIGN_LENGTH); - ::memset(m_node, ' ', YSF_CALLSIGN_LENGTH); - ::memset(m_name, ' ', 14); - ::memset(m_id, ' ', 6); - m_txFrequency = 0U; - m_rxFrequency = 0U; - - ::memset(m_csd1, '*', 20U); - ::memset(m_csd2, ' ', 20U); - ::memset(m_csd3, ' ', 20U); + ::memset(m_callsign, ' ', YSF_CALLSIGN_LENGTH); + ::memset(m_node, ' ', YSF_CALLSIGN_LENGTH); + ::memset(m_name, ' ', 14); + ::memset(m_id, ' ', 6); + m_txFrequency = 0U; + m_rxFrequency = 0U; + + ::memset(m_csd1, '*', 20U); + ::memset(m_csd2, ' ', 20U); + ::memset(m_csd3, ' ', 20U); } @@ -51,29 +51,29 @@ CWiresxInfo::CWiresxInfo() void CWiresxInfo::SetCallsign(const CCallsign &callsign) { - ::memset(m_callsign, ' ', YSF_CALLSIGN_LENGTH); - callsign.GetCallsign(m_callsign); - UpdateCsds(); + ::memset(m_callsign, ' ', YSF_CALLSIGN_LENGTH); + callsign.GetCallsign(m_callsign); + UpdateCsds(); } void CWiresxInfo::SetNode(const char *node) { - ::memset(m_node, ' ', YSF_CALLSIGN_LENGTH); - ::memcpy(m_node, node, MIN(::strlen(node), YSF_CALLSIGN_LENGTH)); - UpdateCsds(); + ::memset(m_node, ' ', YSF_CALLSIGN_LENGTH); + ::memcpy(m_node, node, MIN(::strlen(node), YSF_CALLSIGN_LENGTH)); + UpdateCsds(); } void CWiresxInfo::SetName(const char *name) { - ::memset(m_name, ' ', 14); - ::memcpy(m_name, name, MIN(::strlen(name), 14)); - UpdateId(); + ::memset(m_name, ' ', 14); + ::memcpy(m_name, name, MIN(::strlen(name), 14)); + UpdateId(); } void CWiresxInfo::SetFrequencies(uint txFreq, uint rxFreq) { - m_txFrequency = txFreq; - m_rxFrequency = rxFreq; + m_txFrequency = txFreq; + m_rxFrequency = rxFreq; } //////////////////////////////////////////////////////////////////////////////////////// @@ -81,27 +81,27 @@ void CWiresxInfo::SetFrequencies(uint txFreq, uint rxFreq) void CWiresxInfo::UpdateCsds(void) { - ::memset(m_csd1, '*', 20U); - ::memset(m_csd2, ' ', 20U); - ::memset(m_csd3, ' ', 20U); - ::memcpy(m_csd1 + 10U, m_node, 10U); - ::memcpy(m_csd2 + 0U, m_callsign, 10U); - ::memcpy(m_csd3 + 0U, m_id, 5U); - ::memcpy(m_csd3 + 15U, m_id, 5U); + ::memset(m_csd1, '*', 20U); + ::memset(m_csd2, ' ', 20U); + ::memset(m_csd3, ' ', 20U); + ::memcpy(m_csd1 + 10U, m_node, 10U); + ::memcpy(m_csd2 + 0U, m_callsign, 10U); + ::memcpy(m_csd3 + 0U, m_id, 5U); + ::memcpy(m_csd3 + 15U, m_id, 5U); } void CWiresxInfo::UpdateId(void) { - uint hash = 0U; - for (uint i = 0U; i < 14; i++) - { - hash += m_name[i]; - hash += (hash << 10); - hash ^= (hash >> 6); - } - hash += (hash << 3); - hash ^= (hash >> 11); - hash += (hash << 15); - ::sprintf((char *)m_id, "%05u", hash % 100000U); - UpdateCsds(); + uint hash = 0U; + for (uint i = 0U; i < 14; i++) + { + hash += m_name[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + ::sprintf((char *)m_id, "%05u", hash % 100000U); + UpdateCsds(); } diff --git a/src/cwiresxinfo.h b/src/cwiresxinfo.h index 18207ef..4a6a3a0 100644 --- a/src/cwiresxinfo.h +++ b/src/cwiresxinfo.h @@ -31,45 +31,45 @@ class CWiresxInfo { public: - // constructor - CWiresxInfo(); - - // destructor - virtual ~CWiresxInfo() {} - - // get - const uint8 *GetCallsign(void) const { return m_callsign; } - const uint8 *GetNode(void) const { return m_node; } - const uint8 *GetName(void) const { return m_name; } - const uint8 *GetId(void) const { return m_id; } - uint GetTxFrequency(void) const { return m_txFrequency; } - uint GetRxFrequency(void) const { return m_rxFrequency; } - const uint8 *GetCsd1(void) const { return m_csd1; } - const uint8 *GetCsd2(void) const { return m_csd2; } - const uint8 *GetCsd3(void) const { return m_csd3; } - - // set - void SetCallsign(const CCallsign &); - void SetNode(const char *); - void SetName(const char *); - void SetFrequencies(uint, uint); - - // uodates - void UpdateCsds(void); - void UpdateId(void); - + // constructor + CWiresxInfo(); + + // destructor + virtual ~CWiresxInfo() {} + + // get + const uint8 *GetCallsign(void) const { return m_callsign; } + const uint8 *GetNode(void) const { return m_node; } + const uint8 *GetName(void) const { return m_name; } + const uint8 *GetId(void) const { return m_id; } + uint GetTxFrequency(void) const { return m_txFrequency; } + uint GetRxFrequency(void) const { return m_rxFrequency; } + const uint8 *GetCsd1(void) const { return m_csd1; } + const uint8 *GetCsd2(void) const { return m_csd2; } + const uint8 *GetCsd3(void) const { return m_csd3; } + + // set + void SetCallsign(const CCallsign &); + void SetNode(const char *); + void SetName(const char *); + void SetFrequencies(uint, uint); + + // uodates + void UpdateCsds(void); + void UpdateId(void); + protected: - // data - uint8 m_callsign[YSF_CALLSIGN_LENGTH]; - uint8 m_node[YSF_CALLSIGN_LENGTH]; - uint8 m_name[14]; - uint8 m_id[6]; - uint m_txFrequency; - uint m_rxFrequency; + // data + uint8 m_callsign[YSF_CALLSIGN_LENGTH]; + uint8 m_node[YSF_CALLSIGN_LENGTH]; + uint8 m_name[14]; + uint8 m_id[6]; + uint m_txFrequency; + uint m_rxFrequency; - uint8 m_csd1[20]; - uint8 m_csd2[20]; - uint8 m_csd3[20]; + uint8 m_csd1[20]; + uint8 m_csd2[20]; + uint8 m_csd3[20]; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cwiresxpacket.h b/src/cwiresxpacket.h index 6e9f44b..3534fc6 100644 --- a/src/cwiresxpacket.h +++ b/src/cwiresxpacket.h @@ -34,21 +34,21 @@ class CWiresxPacket { public: - // constructor - CWiresxPacket() {} - CWiresxPacket(const CBuffer &Buffer, const CIp &Ip) { m_Buffer = Buffer; m_Ip = Ip; } - - // destructor - virtual ~CWiresxPacket() {} - - // get - const CBuffer &GetBuffer(void) const { return m_Buffer; } - const CIp &GetIp(void) const { return m_Ip; } - + // constructor + CWiresxPacket() {} + CWiresxPacket(const CBuffer &Buffer, const CIp &Ip) { m_Buffer = Buffer; m_Ip = Ip; } + + // destructor + virtual ~CWiresxPacket() {} + + // get + const CBuffer &GetBuffer(void) const { return m_Buffer; } + const CIp &GetIp(void) const { return m_Ip; } + protected: - // data - CBuffer m_Buffer; - CIp m_Ip; + // data + CBuffer m_Buffer; + CIp m_Ip; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cwiresxpacketqueue.h b/src/cwiresxpacketqueue.h index 95afc04..c4a2c98 100644 --- a/src/cwiresxpacketqueue.h +++ b/src/cwiresxpacketqueue.h @@ -36,15 +36,15 @@ class CWiresxPacketQueue { public: - // constructor - CWiresxPacketQueue() {} + // constructor + CWiresxPacketQueue() {} - // destructor - ~CWiresxPacketQueue() {} + // destructor + ~CWiresxPacketQueue() {} - // lock - void Lock() { m_Mutex.lock(); } - void Unlock() { m_Mutex.unlock(); } + // lock + void Lock() { m_Mutex.lock(); } + void Unlock() { m_Mutex.unlock(); } // pass thru CWiresxPacket front() { return queue.front(); } @@ -53,8 +53,8 @@ public: bool empty() const { return queue.empty(); } protected: - // status - std::mutex m_Mutex; + // status + std::mutex m_Mutex; std::queue queue; }; diff --git a/src/cxlxclient.cpp b/src/cxlxclient.cpp index 2d32b29..b44ebe2 100644 --- a/src/cxlxclient.cpp +++ b/src/cxlxclient.cpp @@ -32,19 +32,19 @@ CXlxClient::CXlxClient() { - m_ProtRev = XLX_PROTOCOL_REVISION_0; + m_ProtRev = XLX_PROTOCOL_REVISION_0; } CXlxClient::CXlxClient(const CCallsign &callsign, const CIp &ip, char reflectorModule, int protRev) -: CClient(callsign, ip, reflectorModule) + : CClient(callsign, ip, reflectorModule) { - m_ProtRev = protRev; + m_ProtRev = protRev; } CXlxClient::CXlxClient(const CXlxClient &client) -: CClient(client) + : CClient(client) { - m_ProtRev = client.m_ProtRev; + m_ProtRev = client.m_ProtRev; } //////////////////////////////////////////////////////////////////////////////////////// @@ -52,20 +52,20 @@ CXlxClient::CXlxClient(const CXlxClient &client) int CXlxClient::GetCodec(void) const { - int codec; - - switch ( GetProtocolRevision() ) - { - case XLX_PROTOCOL_REVISION_0: - case XLX_PROTOCOL_REVISION_1: - default: - codec = CODEC_AMBEPLUS; - break; - case XLX_PROTOCOL_REVISION_2: - codec = CODEC_NONE; - break; - } - return codec; + int codec; + + switch ( GetProtocolRevision() ) + { + case XLX_PROTOCOL_REVISION_0: + case XLX_PROTOCOL_REVISION_1: + default: + codec = CODEC_AMBEPLUS; + break; + case XLX_PROTOCOL_REVISION_2: + codec = CODEC_NONE; + break; + } + return codec; } //////////////////////////////////////////////////////////////////////////////////////// @@ -73,6 +73,6 @@ int CXlxClient::GetCodec(void) const bool CXlxClient::IsAlive(void) const { - return (m_LastKeepaliveTime.DurationSinceNow() < XLX_KEEPALIVE_TIMEOUT); + return (m_LastKeepaliveTime.DurationSinceNow() < XLX_KEEPALIVE_TIMEOUT); } diff --git a/src/cxlxclient.h b/src/cxlxclient.h index ae15045..cc67f1c 100644 --- a/src/cxlxclient.h +++ b/src/cxlxclient.h @@ -42,30 +42,30 @@ class CXlxClient : public CClient { public: - // constructors - CXlxClient(); - CXlxClient(const CCallsign &, const CIp &, char = ' ', int = XLX_PROTOCOL_REVISION_0); - CXlxClient(const CXlxClient &); - - // destructor - virtual ~CXlxClient() {}; - - // identity - int GetProtocol(void) const { return PROTOCOL_XLX; } - int GetProtocolRevision(void) const { return m_ProtRev; } - const char *GetProtocolName(void) const { return "XLX"; } - int GetCodec(void) const; - bool IsPeer(void) const { return true; } - - // status - bool IsAlive(void) const; + // constructors + CXlxClient(); + CXlxClient(const CCallsign &, const CIp &, char = ' ', int = XLX_PROTOCOL_REVISION_0); + CXlxClient(const CXlxClient &); + + // destructor + virtual ~CXlxClient() {}; + + // identity + int GetProtocol(void) const { return PROTOCOL_XLX; } + int GetProtocolRevision(void) const { return m_ProtRev; } + const char *GetProtocolName(void) const { return "XLX"; } + int GetCodec(void) const; + bool IsPeer(void) const { return true; } + + // status + bool IsAlive(void) const; + + // reporting + void WriteXml(std::ofstream &) {} - // reporting - void WriteXml(std::ofstream &) {} - protected: - // data - int m_ProtRev; + // data + int m_ProtRev; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cxlxpeer.cpp b/src/cxlxpeer.cpp index c5b2b73..59bbcfd 100644 --- a/src/cxlxpeer.cpp +++ b/src/cxlxpeer.cpp @@ -39,18 +39,18 @@ CXlxPeer::CXlxPeer() } CXlxPeer::CXlxPeer(const CCallsign &callsign, const CIp &ip, const char *modules, const CVersion &version) -: CPeer(callsign, ip, modules, version) + : CPeer(callsign, ip, modules, version) { - // get protocol revision - int protrev = GetProtocolRevision(version); - //std::cout << "Adding XLX peer with protocol revision " << protrev << std::endl; + // get protocol revision + int protrev = GetProtocolRevision(version); + //std::cout << "Adding XLX peer with protocol revision " << protrev << std::endl; - // and construct all xlx clients - for ( unsigned i = 0; i < ::strlen(modules); i++ ) - { - // create and append to vector - m_Clients.push_back(std::make_shared(callsign, ip, modules[i], protrev)); - } + // and construct all xlx clients + for ( unsigned i = 0; i < ::strlen(modules); i++ ) + { + // create and append to vector + m_Clients.push_back(std::make_shared(callsign, ip, modules[i], protrev)); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -58,7 +58,7 @@ CXlxPeer::CXlxPeer(const CCallsign &callsign, const CIp &ip, const char *modules bool CXlxPeer::IsAlive(void) const { - return (m_LastKeepaliveTime.DurationSinceNow() < XLX_KEEPALIVE_TIMEOUT); + return (m_LastKeepaliveTime.DurationSinceNow() < XLX_KEEPALIVE_TIMEOUT); } //////////////////////////////////////////////////////////////////////////////////////// @@ -66,15 +66,15 @@ bool CXlxPeer::IsAlive(void) const int CXlxPeer::GetProtocolRevision(const CVersion &version) { - int protrev = XLX_PROTOCOL_REVISION_0; + int protrev = XLX_PROTOCOL_REVISION_0; - if ( version.IsEqualOrHigherTo(CVersion(2,2,0)) ) - { - protrev = XLX_PROTOCOL_REVISION_2; - } - else if ( version.IsEqualOrHigherTo(CVersion(1,4,0)) ) - { - protrev = XLX_PROTOCOL_REVISION_1; - } - return protrev; + if ( version.IsEqualOrHigherTo(CVersion(2,2,0)) ) + { + protrev = XLX_PROTOCOL_REVISION_2; + } + else if ( version.IsEqualOrHigherTo(CVersion(1,4,0)) ) + { + protrev = XLX_PROTOCOL_REVISION_1; + } + return protrev; } diff --git a/src/cxlxpeer.h b/src/cxlxpeer.h index 8447302..ccbc1c0 100644 --- a/src/cxlxpeer.h +++ b/src/cxlxpeer.h @@ -38,20 +38,20 @@ class CXlxPeer : public CPeer { public: - // constructors - CXlxPeer(); - CXlxPeer(const CCallsign &, const CIp &, const char *, const CVersion &); - CXlxPeer(const CXlxPeer &) = delete; + // constructors + CXlxPeer(); + CXlxPeer(const CCallsign &, const CIp &, const char *, const CVersion &); + CXlxPeer(const CXlxPeer &) = delete; - // status - bool IsAlive(void) const; + // status + bool IsAlive(void) const; - // identity - int GetProtocol(void) const { return PROTOCOL_XLX; } - const char *GetProtocolName(void) const { return "XLX"; } + // identity + int GetProtocol(void) const { return PROTOCOL_XLX; } + const char *GetProtocolName(void) const { return "XLX"; } - // revision helper - static int GetProtocolRevision(const CVersion &); + // revision helper + static int GetProtocolRevision(const CVersion &); }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cxlxprotocol.cpp b/src/cxlxprotocol.cpp index 06fd52f..7a703a1 100644 --- a/src/cxlxprotocol.cpp +++ b/src/cxlxprotocol.cpp @@ -37,15 +37,15 @@ bool CXlxProtocol::Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6) { - if (! CProtocol::Initialize(type, port, has_ipv4, has_ipv6)) + if (! CProtocol::Initialize(type, port, has_ipv4, has_ipv6)) return false; - // update time - m_LastKeepaliveTime.Now(); - m_LastPeersLinkTime.Now(); + // update time + m_LastKeepaliveTime.Now(); + m_LastPeersLinkTime.Now(); - // done - return true; + // done + return true; } //////////////////////////////////////////////////////////////////////////////////////// @@ -53,16 +53,16 @@ bool CXlxProtocol::Initalize(const char *type, const uint16 port, const bool has void CXlxProtocol::Task(void) { - CBuffer Buffer; - CIp Ip; - CCallsign Callsign; - char Modules[27]; - CVersion Version; - CDvHeaderPacket *Header; - CDvFramePacket *Frame; - CDvLastFramePacket *LastFrame; - - // any incoming packet ? + CBuffer Buffer; + CIp Ip; + CCallsign Callsign; + char Modules[27]; + CVersion Version; + CDvHeaderPacket *Header; + CDvFramePacket *Frame; + CDvLastFramePacket *LastFrame; + + // any incoming packet ? #if XLX_IPV6==true #if XLX_IPV4==true if ( ReceiveDS(Buffer, Ip, 20) ) @@ -72,169 +72,169 @@ void CXlxProtocol::Task(void) #else if ( Receive4(Buffer, Ip, 20) ) #endif - { - // crack the packet - if ( (Frame = IsValidDvFramePacket(Buffer)) != nullptr ) - { - //std::cout << "XLX (DExtra) DV frame" << std::endl; - - // handle it - OnDvFramePacketIn(Frame, &Ip); - } - else if ( (Header = IsValidDvHeaderPacket(Buffer)) != nullptr ) - { - //std::cout << "XLX (DExtra) DV header:" << std::endl << *Header << std::endl; - //std::cout << "XLX (DExtra) DV header on module " << Header->GetRpt2Module() << std::endl; - - // callsign muted? - if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip) ) - { - // handle it - OnDvHeaderPacketIn(Header, Ip); - } - else - { - delete Header; - } - } - else if ( (LastFrame = IsValidDvLastFramePacket(Buffer)) != nullptr ) - { - //std::cout << "XLX (DExtra) DV last frame" << std::endl; - - // handle it - OnDvLastFramePacketIn(LastFrame, &Ip); - } - else if ( IsValidConnectPacket(Buffer, &Callsign, Modules, &Version) ) - { - std::cout << "XLX (" - << Version.GetMajor() << "." << Version.GetMinor() << "." << Version.GetRevision() - << ") connect packet for modules " << Modules - << " from " << Callsign << " at " << Ip << std::endl; - - // callsign authorized? - if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_XLX, Modules) ) - { - // acknowledge connecting request - // following is version dependent - switch ( GetConnectingPeerProtocolRevision(Callsign, Version) ) - { - case XLX_PROTOCOL_REVISION_0: - { - // already connected ? - CPeers *peers = g_Reflector.GetPeers(); - if ( peers->FindPeer(Callsign, Ip, PROTOCOL_XLX) == nullptr ) - { - // acknowledge the request - EncodeConnectAckPacket(&Buffer, Modules); - Send(Buffer, Ip); - } - g_Reflector.ReleasePeers(); - - } - break; - case XLX_PROTOCOL_REVISION_1: - case XLX_PROTOCOL_REVISION_2: - default: - // acknowledge the request - EncodeConnectAckPacket(&Buffer, Modules); - Send(Buffer, Ip); - break; - } - } - else - { - // deny the request - EncodeConnectNackPacket(&Buffer); - Send(Buffer, Ip); - } - } - else if ( IsValidAckPacket(Buffer, &Callsign, Modules, &Version) ) - { - std::cout << "XLX ack packet for modules " << Modules << " from " << Callsign << " at " << Ip << std::endl; - - // callsign authorized? - if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_XLX, Modules) ) - { - // already connected ? - CPeers *peers = g_Reflector.GetPeers(); - if ( peers->FindPeer(Callsign, Ip, PROTOCOL_XLX) == nullptr ) - { - // create the new peer - // this also create one client per module - std::shared_ptrpeer = CreateNewPeer(Callsign, Ip, Modules, Version); - - // append the peer to reflector peer list - // this also add all new clients to reflector client list - peers->AddPeer(peer); - } - g_Reflector.ReleasePeers(); - } - } - else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) - { - std::cout << "XLX disconnect packet from " << Callsign << " at " << Ip << std::endl; - - // find peer - CPeers *peers = g_Reflector.GetPeers(); - std::shared_ptrpeer = peers->FindPeer(Ip, PROTOCOL_XLX); - if ( peer != nullptr ) - { - // remove it from reflector peer list - // this also remove all concerned clients from reflector client list - // and delete them - peers->RemovePeer(peer); - } - g_Reflector.ReleasePeers(); - } - else if ( IsValidNackPacket(Buffer, &Callsign) ) - { - std::cout << "XLX nack packet from " << Callsign << " at " << Ip << std::endl; - } - else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) - { - //std::cout << "XLX keepalive packet from " << Callsign << " at " << Ip << std::endl; - - // find peer - CPeers *peers = g_Reflector.GetPeers(); - std::shared_ptrpeer = peers->FindPeer(Ip, PROTOCOL_XLX); - if ( peer != nullptr ) - { - // keep it alive - peer->Alive(); - } - g_Reflector.ReleasePeers(); - } - else - { - std::cout << "XLX packet (" << Buffer.size() << ")" << std::endl; - } - } - - // handle end of streaming timeout - CheckStreamsTimeout(); - - // handle queue from reflector - HandleQueue(); - - // keep alive - if ( m_LastKeepaliveTime.DurationSinceNow() > XLX_KEEPALIVE_PERIOD ) - { - // handle keep alives - HandleKeepalives(); - - // update time - m_LastKeepaliveTime.Now(); - } - - // peer connections - if ( m_LastPeersLinkTime.DurationSinceNow() > XLX_RECONNECT_PERIOD ) - { - // handle remote peers connections - HandlePeerLinks(); - - // update time - m_LastPeersLinkTime.Now(); - } + { + // crack the packet + if ( (Frame = IsValidDvFramePacket(Buffer)) != nullptr ) + { + //std::cout << "XLX (DExtra) DV frame" << std::endl; + + // handle it + OnDvFramePacketIn(Frame, &Ip); + } + else if ( (Header = IsValidDvHeaderPacket(Buffer)) != nullptr ) + { + //std::cout << "XLX (DExtra) DV header:" << std::endl << *Header << std::endl; + //std::cout << "XLX (DExtra) DV header on module " << Header->GetRpt2Module() << std::endl; + + // callsign muted? + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip) ) + { + // handle it + OnDvHeaderPacketIn(Header, Ip); + } + else + { + delete Header; + } + } + else if ( (LastFrame = IsValidDvLastFramePacket(Buffer)) != nullptr ) + { + //std::cout << "XLX (DExtra) DV last frame" << std::endl; + + // handle it + OnDvLastFramePacketIn(LastFrame, &Ip); + } + else if ( IsValidConnectPacket(Buffer, &Callsign, Modules, &Version) ) + { + std::cout << "XLX (" + << Version.GetMajor() << "." << Version.GetMinor() << "." << Version.GetRevision() + << ") connect packet for modules " << Modules + << " from " << Callsign << " at " << Ip << std::endl; + + // callsign authorized? + if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_XLX, Modules) ) + { + // acknowledge connecting request + // following is version dependent + switch ( GetConnectingPeerProtocolRevision(Callsign, Version) ) + { + case XLX_PROTOCOL_REVISION_0: + { + // already connected ? + CPeers *peers = g_Reflector.GetPeers(); + if ( peers->FindPeer(Callsign, Ip, PROTOCOL_XLX) == nullptr ) + { + // acknowledge the request + EncodeConnectAckPacket(&Buffer, Modules); + Send(Buffer, Ip); + } + g_Reflector.ReleasePeers(); + + } + break; + case XLX_PROTOCOL_REVISION_1: + case XLX_PROTOCOL_REVISION_2: + default: + // acknowledge the request + EncodeConnectAckPacket(&Buffer, Modules); + Send(Buffer, Ip); + break; + } + } + else + { + // deny the request + EncodeConnectNackPacket(&Buffer); + Send(Buffer, Ip); + } + } + else if ( IsValidAckPacket(Buffer, &Callsign, Modules, &Version) ) + { + std::cout << "XLX ack packet for modules " << Modules << " from " << Callsign << " at " << Ip << std::endl; + + // callsign authorized? + if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_XLX, Modules) ) + { + // already connected ? + CPeers *peers = g_Reflector.GetPeers(); + if ( peers->FindPeer(Callsign, Ip, PROTOCOL_XLX) == nullptr ) + { + // create the new peer + // this also create one client per module + std::shared_ptrpeer = CreateNewPeer(Callsign, Ip, Modules, Version); + + // append the peer to reflector peer list + // this also add all new clients to reflector client list + peers->AddPeer(peer); + } + g_Reflector.ReleasePeers(); + } + } + else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) + { + std::cout << "XLX disconnect packet from " << Callsign << " at " << Ip << std::endl; + + // find peer + CPeers *peers = g_Reflector.GetPeers(); + std::shared_ptrpeer = peers->FindPeer(Ip, PROTOCOL_XLX); + if ( peer != nullptr ) + { + // remove it from reflector peer list + // this also remove all concerned clients from reflector client list + // and delete them + peers->RemovePeer(peer); + } + g_Reflector.ReleasePeers(); + } + else if ( IsValidNackPacket(Buffer, &Callsign) ) + { + std::cout << "XLX nack packet from " << Callsign << " at " << Ip << std::endl; + } + else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) + { + //std::cout << "XLX keepalive packet from " << Callsign << " at " << Ip << std::endl; + + // find peer + CPeers *peers = g_Reflector.GetPeers(); + std::shared_ptrpeer = peers->FindPeer(Ip, PROTOCOL_XLX); + if ( peer != nullptr ) + { + // keep it alive + peer->Alive(); + } + g_Reflector.ReleasePeers(); + } + else + { + std::cout << "XLX packet (" << Buffer.size() << ")" << std::endl; + } + } + + // handle end of streaming timeout + CheckStreamsTimeout(); + + // handle queue from reflector + HandleQueue(); + + // keep alive + if ( m_LastKeepaliveTime.DurationSinceNow() > XLX_KEEPALIVE_PERIOD ) + { + // handle keep alives + HandleKeepalives(); + + // update time + m_LastKeepaliveTime.Now(); + } + + // peer connections + if ( m_LastPeersLinkTime.DurationSinceNow() > XLX_RECONNECT_PERIOD ) + { + // handle remote peers connections + HandlePeerLinks(); + + // update time + m_LastPeersLinkTime.Now(); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -242,70 +242,70 @@ void CXlxProtocol::Task(void) void CXlxProtocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) - { - // get the packet - CPacket *packet = m_Queue.front(); - m_Queue.pop(); - - // check if origin of packet is local - // if not, do not stream it out as it will cause - // network loop between linked XLX peers - if ( packet->IsLocalOrigin() ) - { - // encode it - CBuffer buffer; - if ( EncodeDvPacket(*packet, &buffer) ) - { - // encode revision dependent version - CBuffer bufferLegacy = buffer; - if ( packet->IsDvFrame() && (bufferLegacy.size() == 45) ) - { - bufferLegacy.resize(27); - } - - // and push it to all our clients linked to the module and who are not streaming in - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_XLX, it)) != nullptr ) - { - // is this client busy ? - if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) ) - { - // no, send the packet - // this is protocol revision dependent - switch ( client->GetProtocolRevision() ) - { - case XLX_PROTOCOL_REVISION_0: - case XLX_PROTOCOL_REVISION_1: - Send(bufferLegacy, client->GetIp()); - break; - case XLX_PROTOCOL_REVISION_2: - default: + m_Queue.Lock(); + while ( !m_Queue.empty() ) + { + // get the packet + CPacket *packet = m_Queue.front(); + m_Queue.pop(); + + // check if origin of packet is local + // if not, do not stream it out as it will cause + // network loop between linked XLX peers + if ( packet->IsLocalOrigin() ) + { + // encode it + CBuffer buffer; + if ( EncodeDvPacket(*packet, &buffer) ) + { + // encode revision dependent version + CBuffer bufferLegacy = buffer; + if ( packet->IsDvFrame() && (bufferLegacy.size() == 45) ) + { + bufferLegacy.resize(27); + } + + // and push it to all our clients linked to the module and who are not streaming in + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_XLX, it)) != nullptr ) + { + // is this client busy ? + if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) ) + { + // no, send the packet + // this is protocol revision dependent + switch ( client->GetProtocolRevision() ) + { + case XLX_PROTOCOL_REVISION_0: + case XLX_PROTOCOL_REVISION_1: + Send(bufferLegacy, client->GetIp()); + break; + case XLX_PROTOCOL_REVISION_2: + default: #ifdef TRANSCODER_IP - if ( g_Transcoder.IsConnected() ) - { - Send(buffer, client->GetIp()); - } - else + if ( g_Transcoder.IsConnected() ) + { + Send(buffer, client->GetIp()); + } + else #endif - { - Send(bufferLegacy, client->GetIp()); - } - break; - } - } - } - g_Reflector.ReleaseClients(); - } - } - - // done - delete packet; - } - m_Queue.Unlock(); + { + Send(bufferLegacy, client->GetIp()); + } + break; + } + } + } + g_Reflector.ReleaseClients(); + } + } + + // done + delete packet; + } + m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -313,41 +313,41 @@ void CXlxProtocol::HandleQueue(void) void CXlxProtocol::HandleKeepalives(void) { - // DExtra protocol sends and monitors keepalives packets - // event if the client is currently streaming - // so, send keepalives to all - CBuffer keepalive; - EncodeKeepAlivePacket(&keepalive); - - // iterate on peers - CPeers *peers = g_Reflector.GetPeers(); - auto pit = peers->begin(); - std::shared_ptrpeer = nullptr; - while ( (peer = peers->FindNextPeer(PROTOCOL_XLX, pit)) != nullptr ) - { - // send keepalive - Send(keepalive, peer->GetIp()); - - // client busy ? - if ( peer->IsAMaster() ) - { - // yes, just tickle it - peer->Alive(); - } - // otherwise check if still with us - else if ( !peer->IsAlive() ) - { - // no, disconnect - CBuffer disconnect; - EncodeDisconnectPacket(&disconnect); - Send(disconnect, peer->GetIp()); - - // remove it - std::cout << "XLX peer " << peer->GetCallsign() << " keepalive timeout" << std::endl; - peers->RemovePeer(peer); - } - } - g_Reflector.ReleasePeers(); + // DExtra protocol sends and monitors keepalives packets + // event if the client is currently streaming + // so, send keepalives to all + CBuffer keepalive; + EncodeKeepAlivePacket(&keepalive); + + // iterate on peers + CPeers *peers = g_Reflector.GetPeers(); + auto pit = peers->begin(); + std::shared_ptrpeer = nullptr; + while ( (peer = peers->FindNextPeer(PROTOCOL_XLX, pit)) != nullptr ) + { + // send keepalive + Send(keepalive, peer->GetIp()); + + // client busy ? + if ( peer->IsAMaster() ) + { + // yes, just tickle it + peer->Alive(); + } + // otherwise check if still with us + else if ( !peer->IsAlive() ) + { + // no, disconnect + CBuffer disconnect; + EncodeDisconnectPacket(&disconnect); + Send(disconnect, peer->GetIp()); + + // remove it + std::cout << "XLX peer " << peer->GetCallsign() << " keepalive timeout" << std::endl; + peers->RemovePeer(peer); + } + } + g_Reflector.ReleasePeers(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -355,49 +355,49 @@ void CXlxProtocol::HandleKeepalives(void) void CXlxProtocol::HandlePeerLinks(void) { - CBuffer buffer; - - // get the list of peers - CPeerCallsignList *list = g_GateKeeper.GetPeerList(); - CPeers *peers = g_Reflector.GetPeers(); - - // check if all our connected peers are still listed by gatekeeper - // if not, disconnect - auto pit = peers->begin(); - std::shared_ptrpeer = nullptr; - while ( (peer = peers->FindNextPeer(PROTOCOL_XLX, pit)) != nullptr ) - { - if ( list->FindListItem(peer->GetCallsign()) == nullptr ) - { - // send disconnect packet - EncodeDisconnectPacket(&buffer); - Send(buffer, peer->GetIp()); - std::cout << "Sending disconnect packet to XLX peer " << peer->GetCallsign() << std::endl; - // remove client - peers->RemovePeer(peer); - } - } - - // check if all ours peers listed by gatekeeper are connected - // if not, connect or reconnect - for ( auto it=list->begin(); it!=list->end(); it++ ) - { - if ( (*it).GetCallsign().HasSameCallsignWithWildcard(CCallsign("XRF*")) ) - continue; - if ( peers->FindPeer((*it).GetCallsign(), PROTOCOL_XLX) == nullptr ) - { - // resolve again peer's IP in case it's a dynamic IP - (*it).ResolveIp(); - // send connect packet to re-initiate peer link - EncodeConnectPacket(&buffer, (*it).GetModules()); - Send(buffer, (*it).GetIp(), XLX_PORT); - std::cout << "Sending connect packet to XLX peer " << (*it).GetCallsign() << " @ " << (*it).GetIp() << " for modules " << (*it).GetModules() << std::endl; - } - } - - // done - g_Reflector.ReleasePeers(); - g_GateKeeper.ReleasePeerList(); + CBuffer buffer; + + // get the list of peers + CPeerCallsignList *list = g_GateKeeper.GetPeerList(); + CPeers *peers = g_Reflector.GetPeers(); + + // check if all our connected peers are still listed by gatekeeper + // if not, disconnect + auto pit = peers->begin(); + std::shared_ptrpeer = nullptr; + while ( (peer = peers->FindNextPeer(PROTOCOL_XLX, pit)) != nullptr ) + { + if ( list->FindListItem(peer->GetCallsign()) == nullptr ) + { + // send disconnect packet + EncodeDisconnectPacket(&buffer); + Send(buffer, peer->GetIp()); + std::cout << "Sending disconnect packet to XLX peer " << peer->GetCallsign() << std::endl; + // remove client + peers->RemovePeer(peer); + } + } + + // check if all ours peers listed by gatekeeper are connected + // if not, connect or reconnect + for ( auto it=list->begin(); it!=list->end(); it++ ) + { + if ( (*it).GetCallsign().HasSameCallsignWithWildcard(CCallsign("XRF*")) ) + continue; + if ( peers->FindPeer((*it).GetCallsign(), PROTOCOL_XLX) == nullptr ) + { + // resolve again peer's IP in case it's a dynamic IP + (*it).ResolveIp(); + // send connect packet to re-initiate peer link + EncodeConnectPacket(&buffer, (*it).GetModules()); + Send(buffer, (*it).GetIp(), XLX_PORT); + std::cout << "Sending connect packet to XLX peer " << (*it).GetCallsign() << " @ " << (*it).GetIp() << " for modules " << (*it).GetModules() << std::endl; + } + } + + // done + g_Reflector.ReleasePeers(); + g_GateKeeper.ReleasePeerList(); } @@ -406,74 +406,74 @@ void CXlxProtocol::HandlePeerLinks(void) bool CXlxProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip) { - bool newstream = false; - CCallsign peer; - - // todo: verify Packet.GetModuleId() is in authorized list of XLX of origin - // todo: do the same for DVFrame and DVLAstFrame packets - - // tag packet as remote peer origin - Header->SetRemotePeerOrigin(); - - // find the stream - CPacketStream *stream = GetStream(Header->GetStreamId()); - if ( stream == nullptr ) - { - // no stream open yet, open a new one - // find this client - std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_XLX, Header->GetRpt2Module()); - if ( client != nullptr ) - { - // and try to open the stream - if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) - { - // keep the handle - m_Streams.push_back(stream); - newstream = true; - } - // get origin - peer = client->GetCallsign(); - } - // release - g_Reflector.ReleaseClients(); - } - else - { - // stream already open - // skip packet, but tickle the stream - stream->Tickle(); - } - - // update last heard - g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), Header->GetRpt1Callsign(), Header->GetRpt2Callsign(), peer); - g_Reflector.ReleaseUsers(); - - // delete header if needed - if ( !newstream ) - { - delete Header; - } - - // done - return newstream; + bool newstream = false; + CCallsign peer; + + // todo: verify Packet.GetModuleId() is in authorized list of XLX of origin + // todo: do the same for DVFrame and DVLAstFrame packets + + // tag packet as remote peer origin + Header->SetRemotePeerOrigin(); + + // find the stream + CPacketStream *stream = GetStream(Header->GetStreamId()); + if ( stream == nullptr ) + { + // no stream open yet, open a new one + // find this client + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_XLX, Header->GetRpt2Module()); + if ( client != nullptr ) + { + // and try to open the stream + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) + { + // keep the handle + m_Streams.push_back(stream); + newstream = true; + } + // get origin + peer = client->GetCallsign(); + } + // release + g_Reflector.ReleaseClients(); + } + else + { + // stream already open + // skip packet, but tickle the stream + stream->Tickle(); + } + + // update last heard + g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), Header->GetRpt1Callsign(), Header->GetRpt2Callsign(), peer); + g_Reflector.ReleaseUsers(); + + // delete header if needed + if ( !newstream ) + { + delete Header; + } + + // done + return newstream; } void CXlxProtocol::OnDvFramePacketIn(CDvFramePacket *DvFrame, const CIp *Ip) { - // tag packet as remote peer origin - DvFrame->SetRemotePeerOrigin(); + // tag packet as remote peer origin + DvFrame->SetRemotePeerOrigin(); - // anc call base class - CDextraProtocol::OnDvFramePacketIn(DvFrame, Ip); + // anc call base class + CDextraProtocol::OnDvFramePacketIn(DvFrame, Ip); } void CXlxProtocol::OnDvLastFramePacketIn(CDvLastFramePacket *DvFrame, const CIp *Ip) { - // tag packet as remote peer origin - DvFrame->SetRemotePeerOrigin(); + // tag packet as remote peer origin + DvFrame->SetRemotePeerOrigin(); - // anc call base class - CDextraProtocol::OnDvLastFramePacketIn(DvFrame, Ip); + // anc call base class + CDextraProtocol::OnDvLastFramePacketIn(DvFrame, Ip); } @@ -482,138 +482,138 @@ void CXlxProtocol::OnDvLastFramePacketIn(CDvLastFramePacket *DvFrame, const CIp bool CXlxProtocol::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *callsign) { - bool valid = false; - if (Buffer.size() == 9) - { - callsign->SetCallsign(Buffer.data(), 8); - valid = callsign->IsValid(); - } - return valid; + bool valid = false; + if (Buffer.size() == 9) + { + callsign->SetCallsign(Buffer.data(), 8); + valid = callsign->IsValid(); + } + return valid; } bool CXlxProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsign, char *modules, CVersion *version) { - bool valid = false; - if ((Buffer.size() == 39) && (Buffer.data()[0] == 'L') && (Buffer.data()[38] == 0)) - { - callsign->SetCallsign((const uint8 *)&(Buffer.data()[1]), 8); - ::strcpy(modules, (const char *)&(Buffer.data()[12])); - valid = callsign->IsValid(); - *version = CVersion(Buffer.data()[9], Buffer.data()[10], Buffer.data()[11]); - for ( unsigned i = 0; i < ::strlen(modules); i++ ) - { - valid &= IsLetter(modules[i]); - } - } - return valid; + bool valid = false; + if ((Buffer.size() == 39) && (Buffer.data()[0] == 'L') && (Buffer.data()[38] == 0)) + { + callsign->SetCallsign((const uint8 *)&(Buffer.data()[1]), 8); + ::strcpy(modules, (const char *)&(Buffer.data()[12])); + valid = callsign->IsValid(); + *version = CVersion(Buffer.data()[9], Buffer.data()[10], Buffer.data()[11]); + for ( unsigned i = 0; i < ::strlen(modules); i++ ) + { + valid &= IsLetter(modules[i]); + } + } + return valid; } bool CXlxProtocol::IsValidDisconnectPacket(const CBuffer &Buffer, CCallsign *callsign) { - bool valid = false; - if ((Buffer.size() == 10) && (Buffer.data()[0] == 'U') && (Buffer.data()[9] == 0)) - { - callsign->SetCallsign((const uint8 *)&(Buffer.data()[1]), 8); - valid = callsign->IsValid(); - } - return valid; + bool valid = false; + if ((Buffer.size() == 10) && (Buffer.data()[0] == 'U') && (Buffer.data()[9] == 0)) + { + callsign->SetCallsign((const uint8 *)&(Buffer.data()[1]), 8); + valid = callsign->IsValid(); + } + return valid; } bool CXlxProtocol::IsValidAckPacket(const CBuffer &Buffer, CCallsign *callsign, char *modules, CVersion *version) { - bool valid = false; - if ((Buffer.size() == 39) && (Buffer.data()[0] == 'A') && (Buffer.data()[38] == 0)) - { - callsign->SetCallsign((const uint8 *)&(Buffer.data()[1]), 8); - ::strcpy(modules, (const char *)&(Buffer.data()[12])); - valid = callsign->IsValid(); - *version = CVersion(Buffer.data()[9], Buffer.data()[10], Buffer.data()[11]); - for ( unsigned i = 0; i < ::strlen(modules); i++ ) - { - valid &= IsLetter(modules[i]); - } - } - return valid; + bool valid = false; + if ((Buffer.size() == 39) && (Buffer.data()[0] == 'A') && (Buffer.data()[38] == 0)) + { + callsign->SetCallsign((const uint8 *)&(Buffer.data()[1]), 8); + ::strcpy(modules, (const char *)&(Buffer.data()[12])); + valid = callsign->IsValid(); + *version = CVersion(Buffer.data()[9], Buffer.data()[10], Buffer.data()[11]); + for ( unsigned i = 0; i < ::strlen(modules); i++ ) + { + valid &= IsLetter(modules[i]); + } + } + return valid; } bool CXlxProtocol::IsValidNackPacket(const CBuffer &Buffer, CCallsign *callsign) { - bool valid = false; - if ((Buffer.size() == 10) && (Buffer.data()[0] == 'N') && (Buffer.data()[9] == 0)) - { - callsign->SetCallsign((const uint8 *)&(Buffer.data()[1]), 8); - valid = callsign->IsValid(); - } - return valid; + bool valid = false; + if ((Buffer.size() == 10) && (Buffer.data()[0] == 'N') && (Buffer.data()[9] == 0)) + { + callsign->SetCallsign((const uint8 *)&(Buffer.data()[1]), 8); + valid = callsign->IsValid(); + } + return valid; } CDvFramePacket *CXlxProtocol::IsValidDvFramePacket(const CBuffer &Buffer) { - CDvFramePacket *dvframe = nullptr; - - // base class first (protocol revision 1 and lower) - dvframe = CDextraProtocol::IsValidDvFramePacket(Buffer); - - // otherwise try protocol revision 2 - if ( (dvframe == nullptr) && - (Buffer.size() == 45) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) && - (Buffer.data()[4] == 0x20) && (Buffer.data()[8] == 0x20) && - ((Buffer.data()[14] & 0x40) == 0) ) - { - // create packet - dvframe = new CDvFramePacket( - // sid - *((uint16 *)&(Buffer.data()[12])), - // dstar - Buffer.data()[14], &(Buffer.data()[15]), &(Buffer.data()[24]), - // dmr - Buffer.data()[27], Buffer.data()[28], &(Buffer.data()[29]), &(Buffer.data()[38])); - - // check validity of packet - if ( !dvframe->IsValid() ) - { - delete dvframe; - dvframe = nullptr; - } - } - - // done - return dvframe; + CDvFramePacket *dvframe = nullptr; + + // base class first (protocol revision 1 and lower) + dvframe = CDextraProtocol::IsValidDvFramePacket(Buffer); + + // otherwise try protocol revision 2 + if ( (dvframe == nullptr) && + (Buffer.size() == 45) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) && + (Buffer.data()[4] == 0x20) && (Buffer.data()[8] == 0x20) && + ((Buffer.data()[14] & 0x40) == 0) ) + { + // create packet + dvframe = new CDvFramePacket( + // sid + *((uint16 *)&(Buffer.data()[12])), + // dstar + Buffer.data()[14], &(Buffer.data()[15]), &(Buffer.data()[24]), + // dmr + Buffer.data()[27], Buffer.data()[28], &(Buffer.data()[29]), &(Buffer.data()[38])); + + // check validity of packet + if ( !dvframe->IsValid() ) + { + delete dvframe; + dvframe = nullptr; + } + } + + // done + return dvframe; } CDvLastFramePacket *CXlxProtocol::IsValidDvLastFramePacket(const CBuffer &Buffer) { - CDvLastFramePacket *dvframe = nullptr; - - // base class first (protocol revision 1 and lower) - dvframe = CDextraProtocol::IsValidDvLastFramePacket(Buffer); - - // otherwise try protocol revision 2 - if ( (dvframe == nullptr) && - (Buffer.size() == 45) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) && - (Buffer.data()[4] == 0x20) && (Buffer.data()[8] == 0x20) && - ((Buffer.data()[14] & 0x40) != 0) ) - { - // create packet - dvframe = new CDvLastFramePacket( - // sid - *((uint16 *)&(Buffer.data()[12])), - // dstar - Buffer.data()[14], &(Buffer.data()[15]), &(Buffer.data()[24]), - // dmr - Buffer.data()[27], Buffer.data()[28], &(Buffer.data()[29]), &(Buffer.data()[38])); - - // check validity of packet - if ( !dvframe->IsValid() ) - { - delete dvframe; - dvframe = nullptr; - } - } - - // done - return dvframe; + CDvLastFramePacket *dvframe = nullptr; + + // base class first (protocol revision 1 and lower) + dvframe = CDextraProtocol::IsValidDvLastFramePacket(Buffer); + + // otherwise try protocol revision 2 + if ( (dvframe == nullptr) && + (Buffer.size() == 45) && (Buffer.Compare((uint8 *)"DSVT", 4) == 0) && + (Buffer.data()[4] == 0x20) && (Buffer.data()[8] == 0x20) && + ((Buffer.data()[14] & 0x40) != 0) ) + { + // create packet + dvframe = new CDvLastFramePacket( + // sid + *((uint16 *)&(Buffer.data()[12])), + // dstar + Buffer.data()[14], &(Buffer.data()[15]), &(Buffer.data()[24]), + // dmr + Buffer.data()[27], Buffer.data()[28], &(Buffer.data()[29]), &(Buffer.data()[38])); + + // check validity of packet + if ( !dvframe->IsValid() ) + { + delete dvframe; + dvframe = nullptr; + } + } + + // done + return dvframe; } //////////////////////////////////////////////////////////////////////////////////////// @@ -621,107 +621,107 @@ CDvLastFramePacket *CXlxProtocol::IsValidDvLastFramePacket(const CBuffer &Buffer void CXlxProtocol::EncodeKeepAlivePacket(CBuffer *Buffer) { - Buffer->Set(GetReflectorCallsign()); + Buffer->Set(GetReflectorCallsign()); } void CXlxProtocol::EncodeConnectPacket(CBuffer *Buffer, const char *Modules) { - uint8 tag[] = { 'L' }; - - // tag - Buffer->Set(tag, sizeof(tag)); - // our callsign - Buffer->resize(Buffer->size()+8); - g_Reflector.GetCallsign().GetCallsign(Buffer->data()+1); - // our version - Buffer->Append((uint8)VERSION_MAJOR); - Buffer->Append((uint8)VERSION_MINOR); - Buffer->Append((uint8)VERSION_REVISION); - // the modules we share - Buffer->Append(Modules); - Buffer->resize(39); + uint8 tag[] = { 'L' }; + + // tag + Buffer->Set(tag, sizeof(tag)); + // our callsign + Buffer->resize(Buffer->size()+8); + g_Reflector.GetCallsign().GetCallsign(Buffer->data()+1); + // our version + Buffer->Append((uint8)VERSION_MAJOR); + Buffer->Append((uint8)VERSION_MINOR); + Buffer->Append((uint8)VERSION_REVISION); + // the modules we share + Buffer->Append(Modules); + Buffer->resize(39); } void CXlxProtocol::EncodeDisconnectPacket(CBuffer *Buffer) { - uint8 tag[] = { 'U' }; - - // tag - Buffer->Set(tag, sizeof(tag)); - // our callsign - Buffer->resize(Buffer->size()+8); - g_Reflector.GetCallsign().GetCallsign(Buffer->data()+1); - Buffer->Append((uint8)0); + uint8 tag[] = { 'U' }; + + // tag + Buffer->Set(tag, sizeof(tag)); + // our callsign + Buffer->resize(Buffer->size()+8); + g_Reflector.GetCallsign().GetCallsign(Buffer->data()+1); + Buffer->Append((uint8)0); } void CXlxProtocol::EncodeConnectAckPacket(CBuffer *Buffer, const char *Modules) { - uint8 tag[] = { 'A' }; - - // tag - Buffer->Set(tag, sizeof(tag)); - // our callsign - Buffer->resize(Buffer->size()+8); - g_Reflector.GetCallsign().GetCallsign(Buffer->data()+1); - // our version - Buffer->Append((uint8)VERSION_MAJOR); - Buffer->Append((uint8)VERSION_MINOR); - Buffer->Append((uint8)VERSION_REVISION); - // the modules we share - Buffer->Append(Modules); - Buffer->resize(39); + uint8 tag[] = { 'A' }; + + // tag + Buffer->Set(tag, sizeof(tag)); + // our callsign + Buffer->resize(Buffer->size()+8); + g_Reflector.GetCallsign().GetCallsign(Buffer->data()+1); + // our version + Buffer->Append((uint8)VERSION_MAJOR); + Buffer->Append((uint8)VERSION_MINOR); + Buffer->Append((uint8)VERSION_REVISION); + // the modules we share + Buffer->Append(Modules); + Buffer->resize(39); } void CXlxProtocol::EncodeConnectNackPacket(CBuffer *Buffer) { - uint8 tag[] = { 'N' }; - - // tag - Buffer->Set(tag, sizeof(tag)); - // our callsign - Buffer->resize(Buffer->size()+8); - g_Reflector.GetCallsign().GetCallsign(Buffer->data()+1); - Buffer->Append((uint8)0); + uint8 tag[] = { 'N' }; + + // tag + Buffer->Set(tag, sizeof(tag)); + // our callsign + Buffer->resize(Buffer->size()+8); + g_Reflector.GetCallsign().GetCallsign(Buffer->data()+1); + Buffer->Append((uint8)0); } bool CXlxProtocol::EncodeDvFramePacket(const CDvFramePacket &Packet, CBuffer *Buffer) const { - uint8 tag[] = { 'D','S','V','T',0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; + uint8 tag[] = { 'D','S','V','T',0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; - Buffer->Set(tag, sizeof(tag)); - Buffer->Append(Packet.GetStreamId()); - Buffer->Append((uint8)(Packet.GetDstarPacketId() % 21)); - Buffer->Append((uint8 *)Packet.GetAmbe(), AMBE_SIZE); - Buffer->Append((uint8 *)Packet.GetDvData(), DVDATA_SIZE); + Buffer->Set(tag, sizeof(tag)); + Buffer->Append(Packet.GetStreamId()); + Buffer->Append((uint8)(Packet.GetDstarPacketId() % 21)); + Buffer->Append((uint8 *)Packet.GetAmbe(), AMBE_SIZE); + Buffer->Append((uint8 *)Packet.GetDvData(), DVDATA_SIZE); - Buffer->Append((uint8)Packet.GetDmrPacketId()); - Buffer->Append((uint8)Packet.GetDmrPacketSubid()); - Buffer->Append((uint8 *)Packet.GetAmbePlus(), AMBEPLUS_SIZE); - Buffer->Append((uint8 *)Packet.GetDvSync(), DVSYNC_SIZE); + Buffer->Append((uint8)Packet.GetDmrPacketId()); + Buffer->Append((uint8)Packet.GetDmrPacketSubid()); + Buffer->Append((uint8 *)Packet.GetAmbePlus(), AMBEPLUS_SIZE); + Buffer->Append((uint8 *)Packet.GetDvSync(), DVSYNC_SIZE); - return true; + return true; } bool CXlxProtocol::EncodeDvLastFramePacket(const CDvLastFramePacket &Packet, CBuffer *Buffer) const { - uint8 tag[] = { 'D','S','V','T',0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; - uint8 dstarambe[] = { 0x55,0xC8,0x7A,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8 dstardvdata[] = { 0x25,0x1A,0xC6 }; + uint8 tag[] = { 'D','S','V','T',0x20,0x00,0x00,0x00,0x20,0x00,0x01,0x02 }; + uint8 dstarambe[] = { 0x55,0xC8,0x7A,0x00,0x00,0x00,0x00,0x00,0x00 }; + uint8 dstardvdata[] = { 0x25,0x1A,0xC6 }; - Buffer->Set(tag, sizeof(tag)); - Buffer->Append(Packet.GetStreamId()); - Buffer->Append((uint8)((Packet.GetPacketId() % 21) | 0x40)); - Buffer->Append(dstarambe, sizeof(dstarambe)); - Buffer->Append(dstardvdata, sizeof(dstardvdata)); + Buffer->Set(tag, sizeof(tag)); + Buffer->Append(Packet.GetStreamId()); + Buffer->Append((uint8)((Packet.GetPacketId() % 21) | 0x40)); + Buffer->Append(dstarambe, sizeof(dstarambe)); + Buffer->Append(dstardvdata, sizeof(dstardvdata)); - Buffer->Append((uint8)Packet.GetDmrPacketId()); - Buffer->Append((uint8)Packet.GetDmrPacketSubid()); - Buffer->Append((uint8 *)Packet.GetAmbePlus(), AMBEPLUS_SIZE); - Buffer->Append((uint8 *)Packet.GetDvSync(), DVSYNC_SIZE); + Buffer->Append((uint8)Packet.GetDmrPacketId()); + Buffer->Append((uint8)Packet.GetDmrPacketSubid()); + Buffer->Append((uint8 *)Packet.GetAmbePlus(), AMBEPLUS_SIZE); + Buffer->Append((uint8 *)Packet.GetDvSync(), DVSYNC_SIZE); - return true; + return true; } //////////////////////////////////////////////////////////////////////////////////////// @@ -729,32 +729,32 @@ bool CXlxProtocol::EncodeDvLastFramePacket(const CDvLastFramePacket &Packet, CBu int CXlxProtocol::GetConnectingPeerProtocolRevision(const CCallsign &Callsign, const CVersion &Version) { - int protrev; - - // BM ? - if ( Callsign.HasSameCallsignWithWildcard(CCallsign("BM*")) ) - { - protrev = CBmPeer::GetProtocolRevision(Version); - } - // otherwise, assume native xlx - else - { - protrev = CXlxPeer::GetProtocolRevision(Version); - } - - // done - return protrev; + int protrev; + + // BM ? + if ( Callsign.HasSameCallsignWithWildcard(CCallsign("BM*")) ) + { + protrev = CBmPeer::GetProtocolRevision(Version); + } + // otherwise, assume native xlx + else + { + protrev = CXlxPeer::GetProtocolRevision(Version); + } + + // done + return protrev; } std::shared_ptr CXlxProtocol::CreateNewPeer(const CCallsign &Callsign, const CIp &Ip, char *Modules, const CVersion &Version) { - // BM ? - if ( Callsign.HasSameCallsignWithWildcard(CCallsign("BM*")) ) - { + // BM ? + if ( Callsign.HasSameCallsignWithWildcard(CCallsign("BM*")) ) + { return std::make_shared(Callsign, Ip, Modules, Version); - } - else - { - return std::make_shared(Callsign, Ip, Modules, Version); - } + } + else + { + return std::make_shared(Callsign, Ip, Modules, Version); + } } diff --git a/src/cxlxprotocol.h b/src/cxlxprotocol.h index 4b55e6e..b05eca7 100644 --- a/src/cxlxprotocol.h +++ b/src/cxlxprotocol.h @@ -40,51 +40,51 @@ class CPeer; class CXlxProtocol : public CDextraProtocol { public: - // initialization - bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); + // initialization + bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); - // task - void Task(void); + // task + void Task(void); protected: - // queue helper - void HandleQueue(void); + // queue helper + void HandleQueue(void); - // keepalive helpers - void HandlePeerLinks(void); - void HandleKeepalives(void); + // keepalive helpers + void HandlePeerLinks(void); + void HandleKeepalives(void); - // stream helpers - bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); - void OnDvFramePacketIn(CDvFramePacket *, const CIp * = nullptr); - void OnDvLastFramePacketIn(CDvLastFramePacket *, const CIp * = nullptr); + // stream helpers + bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); + void OnDvFramePacketIn(CDvFramePacket *, const CIp * = nullptr); + void OnDvLastFramePacketIn(CDvLastFramePacket *, const CIp * = nullptr); - // packet decoding helpers - bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); - bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, CVersion *); - bool IsValidDisconnectPacket(const CBuffer &, CCallsign *); - bool IsValidAckPacket(const CBuffer &, CCallsign *, char *, CVersion *); - bool IsValidNackPacket(const CBuffer &, CCallsign *); - CDvFramePacket *IsValidDvFramePacket(const CBuffer &); - CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &); + // packet decoding helpers + bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); + bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, CVersion *); + bool IsValidDisconnectPacket(const CBuffer &, CCallsign *); + bool IsValidAckPacket(const CBuffer &, CCallsign *, char *, CVersion *); + bool IsValidNackPacket(const CBuffer &, CCallsign *); + CDvFramePacket *IsValidDvFramePacket(const CBuffer &); + CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &); - // packet encoding helpers - void EncodeKeepAlivePacket(CBuffer *); - void EncodeConnectPacket(CBuffer *, const char *); - void EncodeDisconnectPacket(CBuffer *); - void EncodeConnectAckPacket(CBuffer *, const char *); - void EncodeConnectNackPacket(CBuffer *); - bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; - bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; + // packet encoding helpers + void EncodeKeepAlivePacket(CBuffer *); + void EncodeConnectPacket(CBuffer *, const char *); + void EncodeDisconnectPacket(CBuffer *); + void EncodeConnectAckPacket(CBuffer *, const char *); + void EncodeConnectNackPacket(CBuffer *); + bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; + bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; - // protocol revision helper - int GetConnectingPeerProtocolRevision(const CCallsign &, const CVersion &); - std::shared_ptrCreateNewPeer(const CCallsign &, const CIp &, char *, const CVersion &); + // protocol revision helper + int GetConnectingPeerProtocolRevision(const CCallsign &, const CVersion &); + std::shared_ptrCreateNewPeer(const CCallsign &, const CIp &, char *, const CVersion &); protected: - // time - CTimePoint m_LastKeepaliveTime; - CTimePoint m_LastPeersLinkTime; + // time + CTimePoint m_LastKeepaliveTime; + CTimePoint m_LastPeersLinkTime; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cysfclient.cpp b/src/cysfclient.cpp index fd28c9f..2ec7922 100644 --- a/src/cysfclient.cpp +++ b/src/cysfclient.cpp @@ -34,12 +34,12 @@ CYsfClient::CYsfClient() } CYsfClient::CYsfClient(const CCallsign &callsign, const CIp &ip, char reflectorModule) - : CClient(callsign, ip, reflectorModule) + : CClient(callsign, ip, reflectorModule) { } CYsfClient::CYsfClient(const CYsfClient &client) - : CClient(client) + : CClient(client) { } @@ -48,5 +48,5 @@ CYsfClient::CYsfClient(const CYsfClient &client) bool CYsfClient::IsAlive(void) const { - return (m_LastKeepaliveTime.DurationSinceNow() < YSF_KEEPALIVE_TIMEOUT); + return (m_LastKeepaliveTime.DurationSinceNow() < YSF_KEEPALIVE_TIMEOUT); } diff --git a/src/cysfclient.h b/src/cysfclient.h index 7fb11d2..c31372d 100644 --- a/src/cysfclient.h +++ b/src/cysfclient.h @@ -37,22 +37,22 @@ class CYsfClient : public CClient { public: - // constructors - CYsfClient(); - CYsfClient(const CCallsign &, const CIp &, char = ' '); - CYsfClient(const CYsfClient &); - - // destructor - virtual ~CYsfClient() {}; - - // identity - int GetProtocol(void) const { return PROTOCOL_YSF; } - const char *GetProtocolName(void) const { return "YSF"; } - int GetCodec(void) const { return CODEC_AMBE2PLUS; } - bool IsNode(void) const { return true; } - - // status - bool IsAlive(void) const; + // constructors + CYsfClient(); + CYsfClient(const CCallsign &, const CIp &, char = ' '); + CYsfClient(const CYsfClient &); + + // destructor + virtual ~CYsfClient() {}; + + // identity + int GetProtocol(void) const { return PROTOCOL_YSF; } + const char *GetProtocolName(void) const { return "YSF"; } + int GetCodec(void) const { return CODEC_AMBE2PLUS; } + bool IsNode(void) const { return true; } + + // status + bool IsAlive(void) const; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cysfconvolution.cpp b/src/cysfconvolution.cpp index 6a1f0cf..ff41276 100644 --- a/src/cysfconvolution.cpp +++ b/src/cysfconvolution.cpp @@ -36,106 +36,109 @@ const uint32_t M = 2U; const unsigned int K = 5U; CYSFConvolution::CYSFConvolution() : -m_metrics1(nullptr), -m_metrics2(nullptr), -m_oldMetrics(nullptr), -m_newMetrics(nullptr), -m_decisions(nullptr), -m_dp(nullptr) + m_metrics1(nullptr), + m_metrics2(nullptr), + m_oldMetrics(nullptr), + m_newMetrics(nullptr), + m_decisions(nullptr), + m_dp(nullptr) { - m_metrics1 = new uint16_t[16U]; - m_metrics2 = new uint16_t[16U]; - m_decisions = new uint64_t[180U]; + m_metrics1 = new uint16_t[16U]; + m_metrics2 = new uint16_t[16U]; + m_decisions = new uint64_t[180U]; } CYSFConvolution::~CYSFConvolution() { - delete[] m_metrics1; - delete[] m_metrics2; - delete[] m_decisions; + delete[] m_metrics1; + delete[] m_metrics2; + delete[] m_decisions; } void CYSFConvolution::start() { - ::memset(m_metrics1, 0x00U, NUM_OF_STATES * sizeof(uint16_t)); - ::memset(m_metrics2, 0x00U, NUM_OF_STATES * sizeof(uint16_t)); + ::memset(m_metrics1, 0x00U, NUM_OF_STATES * sizeof(uint16_t)); + ::memset(m_metrics2, 0x00U, NUM_OF_STATES * sizeof(uint16_t)); - m_oldMetrics = m_metrics1; - m_newMetrics = m_metrics2; - m_dp = m_decisions; + m_oldMetrics = m_metrics1; + m_newMetrics = m_metrics2; + m_dp = m_decisions; } void CYSFConvolution::decode(uint8_t s0, uint8_t s1) { - *m_dp = 0U; + *m_dp = 0U; - for (uint8_t i = 0U; i < NUM_OF_STATES_D2; i++) { - uint8_t j = i * 2U; + for (uint8_t i = 0U; i < NUM_OF_STATES_D2; i++) + { + uint8_t j = i * 2U; - uint16_t metric = (BRANCH_TABLE1[i] ^ s0) + (BRANCH_TABLE2[i] ^ s1); + uint16_t metric = (BRANCH_TABLE1[i] ^ s0) + (BRANCH_TABLE2[i] ^ s1); - uint16_t m0 = m_oldMetrics[i] + metric; - uint16_t m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + (M - metric); - uint8_t decision0 = (m0 >= m1) ? 1U : 0U; - m_newMetrics[j + 0U] = decision0 != 0U ? m1 : m0; + uint16_t m0 = m_oldMetrics[i] + metric; + uint16_t m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + (M - metric); + uint8_t decision0 = (m0 >= m1) ? 1U : 0U; + m_newMetrics[j + 0U] = decision0 != 0U ? m1 : m0; - m0 = m_oldMetrics[i] + (M - metric); - m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + metric; - uint8_t decision1 = (m0 >= m1) ? 1U : 0U; - m_newMetrics[j + 1U] = decision1 != 0U ? m1 : m0; + m0 = m_oldMetrics[i] + (M - metric); + m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + metric; + uint8_t decision1 = (m0 >= m1) ? 1U : 0U; + m_newMetrics[j + 1U] = decision1 != 0U ? m1 : m0; - *m_dp |= (uint64_t(decision1) << (j + 1U)) | (uint64_t(decision0) << (j + 0U)); - } + *m_dp |= (uint64_t(decision1) << (j + 1U)) | (uint64_t(decision0) << (j + 0U)); + } - ++m_dp; + ++m_dp; - assert((m_dp - m_decisions) <= 180); + assert((m_dp - m_decisions) <= 180); - uint16_t* tmp = m_oldMetrics; - m_oldMetrics = m_newMetrics; - m_newMetrics = tmp; + uint16_t* tmp = m_oldMetrics; + m_oldMetrics = m_newMetrics; + m_newMetrics = tmp; } void CYSFConvolution::chainback(unsigned char* out, unsigned int nBits) { - assert(out != nullptr); + assert(out != nullptr); - uint32_t state = 0U; + uint32_t state = 0U; - while (nBits-- > 0) { - --m_dp; + while (nBits-- > 0) + { + --m_dp; - uint32_t i = state >> (9 - K); - uint8_t bit = uint8_t(*m_dp >> i) & 1; - state = (bit << 7) | (state >> 1); + uint32_t i = state >> (9 - K); + uint8_t bit = uint8_t(*m_dp >> i) & 1; + state = (bit << 7) | (state >> 1); - WRITE_BIT1(out, nBits, bit != 0U); - } + WRITE_BIT1(out, nBits, bit != 0U); + } } void CYSFConvolution::encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const { - assert(in != nullptr); - assert(out != nullptr); - assert(nBits > 0U); - - uint8_t d1 = 0U, d2 = 0U, d3 = 0U, d4 = 0U; - uint32_t k = 0U; - for (unsigned int i = 0U; i < nBits; i++) { - uint8_t d = READ_BIT1(in, i) ? 1U : 0U; - - uint8_t g1 = (d + d3 + d4) & 1; - uint8_t g2 = (d + d1 + d2 + d4) & 1; - - d4 = d3; - d3 = d2; - d2 = d1; - d1 = d; - - WRITE_BIT1(out, k, g1 != 0U); - k++; - - WRITE_BIT1(out, k, g2 != 0U); - k++; - } + assert(in != nullptr); + assert(out != nullptr); + assert(nBits > 0U); + + uint8_t d1 = 0U, d2 = 0U, d3 = 0U, d4 = 0U; + uint32_t k = 0U; + for (unsigned int i = 0U; i < nBits; i++) + { + uint8_t d = READ_BIT1(in, i) ? 1U : 0U; + + uint8_t g1 = (d + d3 + d4) & 1; + uint8_t g2 = (d + d1 + d2 + d4) & 1; + + d4 = d3; + d3 = d2; + d2 = d1; + d1 = d; + + WRITE_BIT1(out, k, g1 != 0U); + k++; + + WRITE_BIT1(out, k, g2 != 0U); + k++; + } } diff --git a/src/cysfconvolution.h b/src/cysfconvolution.h index b681472..082eeda 100644 --- a/src/cysfconvolution.h +++ b/src/cysfconvolution.h @@ -23,24 +23,25 @@ #include -class CYSFConvolution { +class CYSFConvolution +{ public: - CYSFConvolution(); - ~CYSFConvolution(); - - void start(); - void decode(uint8_t s0, uint8_t s1); - void chainback(unsigned char* out, unsigned int nBits); - - void encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const; - + CYSFConvolution(); + ~CYSFConvolution(); + + void start(); + void decode(uint8_t s0, uint8_t s1); + void chainback(unsigned char* out, unsigned int nBits); + + void encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const; + private: - uint16_t* m_metrics1; - uint16_t* m_metrics2; - uint16_t* m_oldMetrics; - uint16_t* m_newMetrics; - uint64_t* m_decisions; - uint64_t* m_dp; + uint16_t* m_metrics1; + uint16_t* m_metrics2; + uint16_t* m_oldMetrics; + uint16_t* m_newMetrics; + uint64_t* m_decisions; + uint64_t* m_dp; }; #endif diff --git a/src/cysffich.cpp b/src/cysffich.cpp index aea571c..68378dd 100644 --- a/src/cysffich.cpp +++ b/src/cysffich.cpp @@ -33,275 +33,279 @@ const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U #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]) -const unsigned int INTERLEAVE_TABLE[] = { - 0U, 40U, 80U, 120U, 160U, - 2U, 42U, 82U, 122U, 162U, - 4U, 44U, 84U, 124U, 164U, - 6U, 46U, 86U, 126U, 166U, - 8U, 48U, 88U, 128U, 168U, - 10U, 50U, 90U, 130U, 170U, - 12U, 52U, 92U, 132U, 172U, - 14U, 54U, 94U, 134U, 174U, - 16U, 56U, 96U, 136U, 176U, - 18U, 58U, 98U, 138U, 178U, - 20U, 60U, 100U, 140U, 180U, - 22U, 62U, 102U, 142U, 182U, - 24U, 64U, 104U, 144U, 184U, - 26U, 66U, 106U, 146U, 186U, - 28U, 68U, 108U, 148U, 188U, - 30U, 70U, 110U, 150U, 190U, - 32U, 72U, 112U, 152U, 192U, - 34U, 74U, 114U, 154U, 194U, - 36U, 76U, 116U, 156U, 196U, - 38U, 78U, 118U, 158U, 198U}; +const unsigned int INTERLEAVE_TABLE[] = +{ + 0U, 40U, 80U, 120U, 160U, + 2U, 42U, 82U, 122U, 162U, + 4U, 44U, 84U, 124U, 164U, + 6U, 46U, 86U, 126U, 166U, + 8U, 48U, 88U, 128U, 168U, + 10U, 50U, 90U, 130U, 170U, + 12U, 52U, 92U, 132U, 172U, + 14U, 54U, 94U, 134U, 174U, + 16U, 56U, 96U, 136U, 176U, + 18U, 58U, 98U, 138U, 178U, + 20U, 60U, 100U, 140U, 180U, + 22U, 62U, 102U, 142U, 182U, + 24U, 64U, 104U, 144U, 184U, + 26U, 66U, 106U, 146U, 186U, + 28U, 68U, 108U, 148U, 188U, + 30U, 70U, 110U, 150U, 190U, + 32U, 72U, 112U, 152U, 192U, + 34U, 74U, 114U, 154U, 194U, + 36U, 76U, 116U, 156U, 196U, + 38U, 78U, 118U, 158U, 198U +}; CYSFFICH::CYSFFICH() : -m_fich(nullptr) + m_fich(nullptr) { - m_fich = new unsigned char[6U]; - ::memset(m_fich, 0U, 6U); + m_fich = new unsigned char[6U]; + ::memset(m_fich, 0U, 6U); } CYSFFICH::~CYSFFICH() { - delete[] m_fich; + delete[] m_fich; } bool CYSFFICH::decode(const unsigned char* bytes) { - assert(bytes != nullptr); + assert(bytes != nullptr); - CYSFConvolution viterbi; - viterbi.start(); + CYSFConvolution viterbi; + viterbi.start(); - // Deinterleave the FICH and send bits to the Viterbi decoder - for (unsigned int i = 0U; i < 100U; i++) { - unsigned int n = INTERLEAVE_TABLE[i]; - uint8_t s0 = READ_BIT1(bytes, n) ? 1U : 0U; + // Deinterleave the FICH and send bits to the Viterbi decoder + for (unsigned int i = 0U; i < 100U; i++) + { + unsigned int n = INTERLEAVE_TABLE[i]; + uint8_t s0 = READ_BIT1(bytes, n) ? 1U : 0U; - n++; - uint8_t s1 = READ_BIT1(bytes, n) ? 1U : 0U; + n++; + uint8_t s1 = READ_BIT1(bytes, n) ? 1U : 0U; - viterbi.decode(s0, s1); - } + viterbi.decode(s0, s1); + } - unsigned char output[13U]; - viterbi.chainback(output, 96U); + unsigned char output[13U]; + viterbi.chainback(output, 96U); - unsigned int b0 = CGolay24128::decode24128(output + 0U); - unsigned int b1 = CGolay24128::decode24128(output + 3U); - unsigned int b2 = CGolay24128::decode24128(output + 6U); - unsigned int b3 = CGolay24128::decode24128(output + 9U); + unsigned int b0 = CGolay24128::decode24128(output + 0U); + unsigned int b1 = CGolay24128::decode24128(output + 3U); + unsigned int b2 = CGolay24128::decode24128(output + 6U); + unsigned int b3 = CGolay24128::decode24128(output + 9U); - m_fich[0U] = (b0 >> 4) & 0xFFU; - m_fich[1U] = ((b0 << 4) & 0xF0U) | ((b1 >> 8) & 0x0FU); - m_fich[2U] = (b1 >> 0) & 0xFFU; - m_fich[3U] = (b2 >> 4) & 0xFFU; - m_fich[4U] = ((b2 << 4) & 0xF0U) | ((b3 >> 8) & 0x0FU); - m_fich[5U] = (b3 >> 0) & 0xFFU; + m_fich[0U] = (b0 >> 4) & 0xFFU; + m_fich[1U] = ((b0 << 4) & 0xF0U) | ((b1 >> 8) & 0x0FU); + m_fich[2U] = (b1 >> 0) & 0xFFU; + m_fich[3U] = (b2 >> 4) & 0xFFU; + m_fich[4U] = ((b2 << 4) & 0xF0U) | ((b3 >> 8) & 0x0FU); + m_fich[5U] = (b3 >> 0) & 0xFFU; - return CCRC::checkCCITT162(m_fich, 6U); + return CCRC::checkCCITT162(m_fich, 6U); } void CYSFFICH::encode(unsigned char* bytes) { - assert(bytes != nullptr); - - CCRC::addCCITT162(m_fich, 6U); - - unsigned int b0 = ((m_fich[0U] << 4) & 0xFF0U) | ((m_fich[1U] >> 4) & 0x00FU); - unsigned int b1 = ((m_fich[1U] << 8) & 0xF00U) | ((m_fich[2U] >> 0) & 0x0FFU); - unsigned int b2 = ((m_fich[3U] << 4) & 0xFF0U) | ((m_fich[4U] >> 4) & 0x00FU); - unsigned int b3 = ((m_fich[4U] << 8) & 0xF00U) | ((m_fich[5U] >> 0) & 0x0FFU); - - unsigned int c0 = CGolay24128::encode24128(b0); - unsigned int c1 = CGolay24128::encode24128(b1); - unsigned int c2 = CGolay24128::encode24128(b2); - unsigned int c3 = CGolay24128::encode24128(b3); - - unsigned char conv[13U]; - conv[0U] = (c0 >> 16) & 0xFFU; - conv[1U] = (c0 >> 8) & 0xFFU; - conv[2U] = (c0 >> 0) & 0xFFU; - conv[3U] = (c1 >> 16) & 0xFFU; - conv[4U] = (c1 >> 8) & 0xFFU; - conv[5U] = (c1 >> 0) & 0xFFU; - conv[6U] = (c2 >> 16) & 0xFFU; - conv[7U] = (c2 >> 8) & 0xFFU; - conv[8U] = (c2 >> 0) & 0xFFU; - conv[9U] = (c3 >> 16) & 0xFFU; - conv[10U] = (c3 >> 8) & 0xFFU; - conv[11U] = (c3 >> 0) & 0xFFU; - conv[12U] = 0x00U; - - CYSFConvolution convolution; - unsigned char convolved[25U]; - convolution.encode(conv, convolved, 100U); - - unsigned int j = 0U; - for (unsigned int i = 0U; i < 100U; i++) { - unsigned int n = INTERLEAVE_TABLE[i]; - - bool s0 = READ_BIT1(convolved, j) != 0U; - j++; - - bool s1 = READ_BIT1(convolved, j) != 0U; - j++; - - WRITE_BIT1(bytes, n, s0); - - n++; - WRITE_BIT1(bytes, n, s1); - } + assert(bytes != nullptr); + + CCRC::addCCITT162(m_fich, 6U); + + unsigned int b0 = ((m_fich[0U] << 4) & 0xFF0U) | ((m_fich[1U] >> 4) & 0x00FU); + unsigned int b1 = ((m_fich[1U] << 8) & 0xF00U) | ((m_fich[2U] >> 0) & 0x0FFU); + unsigned int b2 = ((m_fich[3U] << 4) & 0xFF0U) | ((m_fich[4U] >> 4) & 0x00FU); + unsigned int b3 = ((m_fich[4U] << 8) & 0xF00U) | ((m_fich[5U] >> 0) & 0x0FFU); + + unsigned int c0 = CGolay24128::encode24128(b0); + unsigned int c1 = CGolay24128::encode24128(b1); + unsigned int c2 = CGolay24128::encode24128(b2); + unsigned int c3 = CGolay24128::encode24128(b3); + + unsigned char conv[13U]; + conv[0U] = (c0 >> 16) & 0xFFU; + conv[1U] = (c0 >> 8) & 0xFFU; + conv[2U] = (c0 >> 0) & 0xFFU; + conv[3U] = (c1 >> 16) & 0xFFU; + conv[4U] = (c1 >> 8) & 0xFFU; + conv[5U] = (c1 >> 0) & 0xFFU; + conv[6U] = (c2 >> 16) & 0xFFU; + conv[7U] = (c2 >> 8) & 0xFFU; + conv[8U] = (c2 >> 0) & 0xFFU; + conv[9U] = (c3 >> 16) & 0xFFU; + conv[10U] = (c3 >> 8) & 0xFFU; + conv[11U] = (c3 >> 0) & 0xFFU; + conv[12U] = 0x00U; + + CYSFConvolution convolution; + unsigned char convolved[25U]; + convolution.encode(conv, convolved, 100U); + + unsigned int j = 0U; + for (unsigned int i = 0U; i < 100U; i++) + { + unsigned int n = INTERLEAVE_TABLE[i]; + + bool s0 = READ_BIT1(convolved, j) != 0U; + j++; + + bool s1 = READ_BIT1(convolved, j) != 0U; + j++; + + WRITE_BIT1(bytes, n, s0); + + n++; + WRITE_BIT1(bytes, n, s1); + } } unsigned char CYSFFICH::getFI() const { - return (m_fich[0U] >> 6) & 0x03U; + return (m_fich[0U] >> 6) & 0x03U; } unsigned char CYSFFICH::getCS() const { - return (m_fich[0U] >> 4) & 0x03U; + return (m_fich[0U] >> 4) & 0x03U; } unsigned char CYSFFICH::getCM() const { - return (m_fich[0U] >> 2) & 0x03U; + return (m_fich[0U] >> 2) & 0x03U; } unsigned char CYSFFICH::getBN() const { - return m_fich[0U] & 0x03U; + return m_fich[0U] & 0x03U; } unsigned char CYSFFICH::getBT() const { - return (m_fich[1U] >> 6) & 0x03U; + return (m_fich[1U] >> 6) & 0x03U; } unsigned char CYSFFICH::getFN() const { - return (m_fich[1U] >> 3) & 0x07U; + return (m_fich[1U] >> 3) & 0x07U; } unsigned char CYSFFICH::getFT() const { - return m_fich[1U] & 0x07U; + return m_fich[1U] & 0x07U; } unsigned char CYSFFICH::getDT() const { - return m_fich[2U] & 0x03U; + return m_fich[2U] & 0x03U; } unsigned char CYSFFICH::getMR() const { - return (m_fich[2U] >> 3) & 0x03U; + return (m_fich[2U] >> 3) & 0x03U; } bool CYSFFICH::getDev() const { - return (m_fich[2U] & 0x40U) == 0x40U; + return (m_fich[2U] & 0x40U) == 0x40U; } bool CYSFFICH::getSQL() const { - return (m_fich[3U] & 0x80U) == 0x80U; + return (m_fich[3U] & 0x80U) == 0x80U; } unsigned char CYSFFICH::getSQ() const { - return m_fich[3U] & 0x7FU; + return m_fich[3U] & 0x7FU; } void CYSFFICH::setFI(unsigned char fi) { - m_fich[0U] &= 0x3FU; - m_fich[0U] |= (fi << 6) & 0xC0U; + m_fich[0U] &= 0x3FU; + m_fich[0U] |= (fi << 6) & 0xC0U; } void CYSFFICH::setCS(unsigned char cs) { - m_fich[0U] &= 0xCFU; - m_fich[0U] |= (cs << 4) & 0x30U; + m_fich[0U] &= 0xCFU; + m_fich[0U] |= (cs << 4) & 0x30U; } void CYSFFICH::setCM(unsigned char cm) { - m_fich[0U] &= 0xF3U; - m_fich[0U] |= (cm << 2) & 0x0CU; + m_fich[0U] &= 0xF3U; + m_fich[0U] |= (cm << 2) & 0x0CU; } void CYSFFICH::setFN(unsigned char fn) { - m_fich[1U] &= 0xC7U; - m_fich[1U] |= (fn << 3) & 0x38U; + m_fich[1U] &= 0xC7U; + m_fich[1U] |= (fn << 3) & 0x38U; } void CYSFFICH::setFT(unsigned char ft) { - m_fich[1U] &= 0xF8U; - m_fich[1U] |= ft & 0x07U; + m_fich[1U] &= 0xF8U; + m_fich[1U] |= ft & 0x07U; } void CYSFFICH::setMR(unsigned char mr) { - m_fich[2U] &= 0xC7U; - m_fich[2U] |= (mr << 3) & 0x38U; + m_fich[2U] &= 0xC7U; + m_fich[2U] |= (mr << 3) & 0x38U; } void CYSFFICH::setVoIP(bool on) { - if (on) - m_fich[2U] |= 0x04U; - else - m_fich[2U] &= 0xFBU; + if (on) + m_fich[2U] |= 0x04U; + else + m_fich[2U] &= 0xFBU; } void CYSFFICH::setDev(bool on) { - if (on) - m_fich[2U] |= 0x40U; - else - m_fich[2U] &= 0xBFU; + if (on) + m_fich[2U] |= 0x40U; + else + m_fich[2U] &= 0xBFU; } void CYSFFICH::setDT(unsigned char dt) { - m_fich[2U] &= 0xFCU; - m_fich[2U] |= dt & 0x03U; + m_fich[2U] &= 0xFCU; + m_fich[2U] |= dt & 0x03U; } void CYSFFICH::setSQL(bool on) { - if (on) - m_fich[3U] |= 0x80U; - else - m_fich[3U] &= 0x7FU; + if (on) + m_fich[3U] |= 0x80U; + else + m_fich[3U] &= 0x7FU; } void CYSFFICH::setSQ(unsigned char sq) { - m_fich[3U] &= 0x80U; - m_fich[3U] |= sq & 0x7FU; + m_fich[3U] &= 0x80U; + m_fich[3U] |= sq & 0x7FU; } void CYSFFICH::setBN(unsigned char bn) { - m_fich[0U] &= 0xFCU; - m_fich[0U] |= bn & 0x03U; + m_fich[0U] &= 0xFCU; + m_fich[0U] |= bn & 0x03U; } void CYSFFICH::setBT(unsigned char bt) { - m_fich[1U] &= 0x3FU; - m_fich[1U] |= (bt << 6) & 0xC0U; + m_fich[1U] &= 0x3FU; + m_fich[1U] |= (bt << 6) & 0xC0U; } void CYSFFICH::load(const unsigned char* fich) { - assert(fich != nullptr); + assert(fich != nullptr); - ::memcpy(m_fich, fich, 4U); + ::memcpy(m_fich, fich, 4U); } diff --git a/src/cysffich.h b/src/cysffich.h index 7adcad8..41f8b44 100644 --- a/src/cysffich.h +++ b/src/cysffich.h @@ -20,46 +20,47 @@ #if !defined(YSFFICH_H) #define YSFFICH_H -class CYSFFICH { +class CYSFFICH +{ public: - CYSFFICH(); - ~CYSFFICH(); - - bool decode(const unsigned char* bytes); - - void encode(unsigned char* bytes); - - unsigned char getFI() const; - unsigned char getCS() const; - unsigned char getCM() const; - unsigned char getBN() const; - unsigned char getBT() const; - unsigned char getFN() const; - unsigned char getFT() const; - unsigned char getDT() const; - unsigned char getMR() const; - bool getDev() const; - bool getSQL() const; - unsigned char getSQ() const; - - void setFI(unsigned char fi); - void setCS(unsigned char cs); - void setCM(unsigned char cm); - void setFN(unsigned char fn); - void setFT(unsigned char ft); - void setBN(unsigned char bn); - void setBT(unsigned char bt); - void setDT(unsigned char dt); - void setMR(unsigned char mr); - void setVoIP(bool set); - void setDev(bool set); - void setSQL(bool set); - void setSQ(unsigned char sq); - - void load(const unsigned char* fich); - + CYSFFICH(); + ~CYSFFICH(); + + bool decode(const unsigned char* bytes); + + void encode(unsigned char* bytes); + + unsigned char getFI() const; + unsigned char getCS() const; + unsigned char getCM() const; + unsigned char getBN() const; + unsigned char getBT() const; + unsigned char getFN() const; + unsigned char getFT() const; + unsigned char getDT() const; + unsigned char getMR() const; + bool getDev() const; + bool getSQL() const; + unsigned char getSQ() const; + + void setFI(unsigned char fi); + void setCS(unsigned char cs); + void setCM(unsigned char cm); + void setFN(unsigned char fn); + void setFT(unsigned char ft); + void setBN(unsigned char bn); + void setBT(unsigned char bt); + void setDT(unsigned char dt); + void setMR(unsigned char mr); + void setVoIP(bool set); + void setDev(bool set); + void setSQL(bool set); + void setSQ(unsigned char sq); + + void load(const unsigned char* fich); + private: - unsigned char* m_fich; + unsigned char* m_fich; }; #endif diff --git a/src/cysfnode.cpp b/src/cysfnode.cpp index e97f98f..724de2b 100644 --- a/src/cysfnode.cpp +++ b/src/cysfnode.cpp @@ -32,22 +32,22 @@ CYsfNode::CYsfNode() { - m_uiTxFreq = 0; - m_uiRxFreq = 0; + m_uiTxFreq = 0; + m_uiRxFreq = 0; } CYsfNode::CYsfNode(const CCallsign &callsign, uint32 txfreq, uint32 rxfreq) { - m_Callsign = callsign; - m_uiTxFreq = txfreq; - m_uiRxFreq = rxfreq; + m_Callsign = callsign; + m_uiTxFreq = txfreq; + m_uiRxFreq = rxfreq; } CYsfNode::CYsfNode(const CYsfNode &node) { - m_Callsign = node.m_Callsign; - m_uiTxFreq = node.m_uiTxFreq; - m_uiRxFreq = node.m_uiRxFreq; + m_Callsign = node.m_Callsign; + m_uiTxFreq = node.m_uiTxFreq; + m_uiRxFreq = node.m_uiRxFreq; } @@ -56,5 +56,5 @@ CYsfNode::CYsfNode(const CYsfNode &node) bool CYsfNode::IsValid(void) const { - return m_Callsign.IsValid(); + return m_Callsign.IsValid(); } diff --git a/src/cysfnode.h b/src/cysfnode.h index 65fb6e6..468e9c7 100644 --- a/src/cysfnode.h +++ b/src/cysfnode.h @@ -38,24 +38,24 @@ class CYsfNode { public: - // constructor - CYsfNode(); - CYsfNode(const CCallsign &, uint32, uint32); - CYsfNode(const CYsfNode &); - - // destructor - virtual ~CYsfNode() {} - - // get - uint32 GetTxFrequency(void) const { return m_uiTxFreq; } - uint32 GetRxFrequency(void) const { return m_uiRxFreq; } - bool IsValid(void) const; - + // constructor + CYsfNode(); + CYsfNode(const CCallsign &, uint32, uint32); + CYsfNode(const CYsfNode &); + + // destructor + virtual ~CYsfNode() {} + + // get + uint32 GetTxFrequency(void) const { return m_uiTxFreq; } + uint32 GetRxFrequency(void) const { return m_uiRxFreq; } + bool IsValid(void) const; + protected: - // data - CCallsign m_Callsign; - uint32 m_uiTxFreq; - uint32 m_uiRxFreq; + // data + CCallsign m_Callsign; + uint32 m_uiTxFreq; + uint32 m_uiRxFreq; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cysfnodedir.cpp b/src/cysfnodedir.cpp index 1762a51..487d4c2 100644 --- a/src/cysfnodedir.cpp +++ b/src/cysfnodedir.cpp @@ -33,20 +33,20 @@ CYsfNodeDir::CYsfNodeDir() { - keep_running = true; - m_pThread = nullptr; + keep_running = true; + m_pThread = nullptr; } CYsfNodeDir::~CYsfNodeDir() { - // kill threads - keep_running = false; - if ( m_pThread != nullptr ) - { - m_pThread->join(); - delete m_pThread; + // kill threads + keep_running = false; + if ( m_pThread != nullptr ) + { + m_pThread->join(); + delete m_pThread; m_pThread = nullptr; - } + } } @@ -55,27 +55,27 @@ CYsfNodeDir::~CYsfNodeDir() bool CYsfNodeDir::Init(void) { - // load content - Reload(); + // load content + Reload(); - // reset run flag - keep_running = true; + // reset run flag + keep_running = true; - // start thread; - m_pThread = new std::thread(CYsfNodeDir::Thread, this); + // start thread; + m_pThread = new std::thread(CYsfNodeDir::Thread, this); - return true; + return true; } void CYsfNodeDir::Close(void) { - keep_running = false; - if ( m_pThread != nullptr ) - { - m_pThread->join(); - delete m_pThread; - m_pThread = nullptr; - } + keep_running = false; + if ( m_pThread != nullptr ) + { + m_pThread->join(); + delete m_pThread; + m_pThread = nullptr; + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -83,18 +83,18 @@ void CYsfNodeDir::Close(void) void CYsfNodeDir::Thread(CYsfNodeDir *This) { - while (This->keep_running) - { - // Wait YSFNODEDB_REFRESH_RATE minutes + while (This->keep_running) + { + // Wait YSFNODEDB_REFRESH_RATE minutes for (int i=0; i<30*YSFNODEDB_REFRESH_RATE && This->keep_running; i++) - CTimePoint::TaskSleepFor(2000); - - // have lists files changed ? - if ( This->NeedReload() ) - { - This->Reload(); - } - } + CTimePoint::TaskSleepFor(2000); + + // have lists files changed ? + if ( This->NeedReload() ) + { + This->Reload(); + } + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -102,18 +102,18 @@ void CYsfNodeDir::Thread(CYsfNodeDir *This) bool CYsfNodeDir::Reload(void) { - CBuffer buffer; - bool ok = false; - - if ( LoadContent(&buffer) ) - { - Lock(); - { - ok = RefreshContent(buffer); - } - Unlock(); - } - return ok; + CBuffer buffer; + bool ok = false; + + if ( LoadContent(&buffer) ) + { + Lock(); + { + ok = RefreshContent(buffer); + } + Unlock(); + } + return ok; } //////////////////////////////////////////////////////////////////////////////////////// @@ -121,17 +121,17 @@ bool CYsfNodeDir::Reload(void) bool CYsfNodeDir::FindFrequencies(const CCallsign &callsign, uint32 *txfreq, uint32 *rxfreq) { - auto found = find(callsign); - if ( found != end() ) - { - *txfreq = found->second.GetTxFrequency(); - *rxfreq = found->second.GetRxFrequency(); - return true; - } - else - { - *txfreq = YSF_DEFAULT_NODE_TX_FREQ; - *rxfreq = YSF_DEFAULT_NODE_RX_FREQ; - return false; - } + auto found = find(callsign); + if ( found != end() ) + { + *txfreq = found->second.GetTxFrequency(); + *rxfreq = found->second.GetRxFrequency(); + return true; + } + else + { + *txfreq = YSF_DEFAULT_NODE_TX_FREQ; + *rxfreq = YSF_DEFAULT_NODE_RX_FREQ; + return false; + } } diff --git a/src/cysfnodedir.h b/src/cysfnodedir.h index 23f9810..e10eee2 100644 --- a/src/cysfnodedir.h +++ b/src/cysfnodedir.h @@ -38,8 +38,8 @@ struct CYsfNodeDirCallsignCompare { - bool operator() (const CCallsign &cs1, const CCallsign &cs2) const - { return cs1.HasLowerCallsign(cs2);} + bool operator() (const CCallsign &cs1, const CCallsign &cs2) const + { return cs1.HasLowerCallsign(cs2);} }; //////////////////////////////////////////////////////////////////////////////////////// @@ -50,25 +50,25 @@ using CsNodeMap = std::map; class CYsfNodeDir { public: - // constructor - CYsfNodeDir(); - // destructor - virtual ~CYsfNodeDir(); + // constructor + CYsfNodeDir(); + // destructor + virtual ~CYsfNodeDir(); - // init & close - virtual bool Init(void); - virtual void Close(void); + // init & close + virtual bool Init(void); + virtual void Close(void); - // locks - void Lock(void) { m_Mutex.lock(); } - void Unlock(void) { m_Mutex.unlock(); } + // locks + void Lock(void) { m_Mutex.lock(); } + void Unlock(void) { m_Mutex.unlock(); } - // refresh - virtual bool LoadContent(CBuffer *) { return false; } - virtual bool RefreshContent(const CBuffer &) { return false; } + // refresh + virtual bool LoadContent(CBuffer *) { return false; } + virtual bool RefreshContent(const CBuffer &) { return false; } - // find - bool FindFrequencies(const CCallsign &, uint32 *, uint32 *); + // find + bool FindFrequencies(const CCallsign &, uint32 *, uint32 *); // pass-thru void clear() { m_map.clear(); } @@ -78,23 +78,23 @@ public: std::pair insert(const std::pair &pair) { return m_map.insert(pair); } protected: - // thread - static void Thread(CYsfNodeDir *); + // thread + static void Thread(CYsfNodeDir *); - // reload helpers - bool Reload(void); - virtual bool NeedReload(void) { return false; } - //bool IsValidDmrid(const char *); + // reload helpers + bool Reload(void); + virtual bool NeedReload(void) { return false; } + //bool IsValidDmrid(const char *); protected: - // Lock() - std::mutex m_Mutex; + // Lock() + std::mutex m_Mutex; - // thread - std::atomic keep_running; - std::thread *m_pThread; - CsNodeMap m_map; + // thread + std::atomic keep_running; + std::thread *m_pThread; + CsNodeMap m_map; }; diff --git a/src/cysfnodedirfile.cpp b/src/cysfnodedirfile.cpp index ac2cf2e..aa24b2f 100644 --- a/src/cysfnodedirfile.cpp +++ b/src/cysfnodedirfile.cpp @@ -38,7 +38,7 @@ CYsfNodeDirFile g_YsfNodeDir; CYsfNodeDirFile::CYsfNodeDirFile() { - ::memset(&m_LastModTime, 0, sizeof(time_t)); + ::memset(&m_LastModTime, 0, sizeof(time_t)); } //////////////////////////////////////////////////////////////////////////////////////// @@ -46,7 +46,7 @@ CYsfNodeDirFile::CYsfNodeDirFile() bool CYsfNodeDirFile::Init(void) { - return CYsfNodeDir::Init(); + return CYsfNodeDir::Init(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -54,114 +54,114 @@ bool CYsfNodeDirFile::Init(void) bool CYsfNodeDirFile::NeedReload(void) { - bool needReload = false; - - time_t time; - if ( GetLastModTime(&time) ) - { - needReload = time != m_LastModTime; - } - return needReload; + bool needReload = false; + + time_t time; + if ( GetLastModTime(&time) ) + { + needReload = time != m_LastModTime; + } + return needReload; } bool CYsfNodeDirFile::LoadContent(CBuffer *buffer) { - bool ok = false; - std::ifstream file; - std::streampos size; - - // open file - file.open(YSFNODEDB_PATH, std::ios::in | std::ios::binary | std::ios::ate); - if ( file.is_open() ) - { - // read file - size = file.tellg(); - if ( size > 0 ) - { - // read file into buffer - buffer->resize((int)size+1); - file.seekg (0, std::ios::beg); - file.read((char *)buffer->data(), (int)size); - - // close file - file.close(); - - // update time - GetLastModTime(&m_LastModTime); - - // done - ok = true; - } - } - - // done - return ok; + bool ok = false; + std::ifstream file; + std::streampos size; + + // open file + file.open(YSFNODEDB_PATH, std::ios::in | std::ios::binary | std::ios::ate); + if ( file.is_open() ) + { + // read file + size = file.tellg(); + if ( size > 0 ) + { + // read file into buffer + buffer->resize((int)size+1); + file.seekg (0, std::ios::beg); + file.read((char *)buffer->data(), (int)size); + + // close file + file.close(); + + // update time + GetLastModTime(&m_LastModTime); + + // done + ok = true; + } + } + + // done + return ok; } bool CYsfNodeDirFile::RefreshContent(const CBuffer &buffer) { - bool ok = false; - - // clear directory - clear(); - - // scan buffer - if ( buffer.size() > 0 ) - { - // crack it - char *ptr1 = (char *)buffer.data(); - char *ptr2; - - // get next line - while ( (ptr2 = ::strchr(ptr1, '\n')) != nullptr ) - { - *ptr2 = 0; - // get items - char *callsign; - char *txfreq; - char *rxfreq; - if ( ((callsign = ::strtok(ptr1, ";")) != nullptr) ) - { - if ( ((txfreq = ::strtok(nullptr, ";")) != nullptr) ) - { - if ( ((rxfreq = ::strtok(nullptr, ";")) != nullptr) ) - { - // new entry - CCallsign cs(callsign); - CYsfNode node(cs, atoi(txfreq), atoi(rxfreq)); - if ( cs.IsValid() && node.IsValid() ) - { - insert(std::pair(cs, node)); - } - } - } - } - // next line - ptr1 = ptr2+1; - } - - // done - ok = true; - } - - - // report - std::cout << "Read " << size() << " YSF nodes from file " << YSFNODEDB_PATH << std::endl; - - // done - return ok; + bool ok = false; + + // clear directory + clear(); + + // scan buffer + if ( buffer.size() > 0 ) + { + // crack it + char *ptr1 = (char *)buffer.data(); + char *ptr2; + + // get next line + while ( (ptr2 = ::strchr(ptr1, '\n')) != nullptr ) + { + *ptr2 = 0; + // get items + char *callsign; + char *txfreq; + char *rxfreq; + if ( ((callsign = ::strtok(ptr1, ";")) != nullptr) ) + { + if ( ((txfreq = ::strtok(nullptr, ";")) != nullptr) ) + { + if ( ((rxfreq = ::strtok(nullptr, ";")) != nullptr) ) + { + // new entry + CCallsign cs(callsign); + CYsfNode node(cs, atoi(txfreq), atoi(rxfreq)); + if ( cs.IsValid() && node.IsValid() ) + { + insert(std::pair(cs, node)); + } + } + } + } + // next line + ptr1 = ptr2+1; + } + + // done + ok = true; + } + + + // report + std::cout << "Read " << size() << " YSF nodes from file " << YSFNODEDB_PATH << std::endl; + + // done + return ok; } bool CYsfNodeDirFile::GetLastModTime(time_t *time) { - bool ok = false; - - struct stat fileStat; - if( ::stat(YSFNODEDB_PATH, &fileStat) != -1 ) - { - *time = fileStat.st_mtime; - ok = true; - } - return ok; + bool ok = false; + + struct stat fileStat; + if( ::stat(YSFNODEDB_PATH, &fileStat) != -1 ) + { + *time = fileStat.st_mtime; + ok = true; + } + return ok; } diff --git a/src/cysfnodedirfile.h b/src/cysfnodedirfile.h index 8106a7e..854ddb8 100644 --- a/src/cysfnodedirfile.h +++ b/src/cysfnodedirfile.h @@ -32,28 +32,28 @@ class CYsfNodeDirFile : public CYsfNodeDir { public: - // constructor - CYsfNodeDirFile(); - - // destructor - ~CYsfNodeDirFile() {} - - // init & close - bool Init(void); - - // refresh - bool LoadContent(CBuffer *); - bool RefreshContent(const CBuffer &); - + // constructor + CYsfNodeDirFile(); + + // destructor + ~CYsfNodeDirFile() {} + + // init & close + bool Init(void); + + // refresh + bool LoadContent(CBuffer *); + bool RefreshContent(const CBuffer &); + protected: - // reload helpers - bool NeedReload(void); - bool GetLastModTime(time_t *); - + // reload helpers + bool NeedReload(void); + bool GetLastModTime(time_t *); + protected: - // data - time_t m_LastModTime; - }; + // data + time_t m_LastModTime; +}; //////////////////////////////////////////////////////////////////////////////////////// #endif /* cysfnodedirfile_h */ diff --git a/src/cysfnodedirhttp.cpp b/src/cysfnodedirhttp.cpp index 8018976..9099df2 100644 --- a/src/cysfnodedirhttp.cpp +++ b/src/cysfnodedirhttp.cpp @@ -37,61 +37,61 @@ CYsfNodeDirHttp g_YsfNodeDir; bool CYsfNodeDirHttp::LoadContent(CBuffer *buffer) { - // get file from xlxapi server - return HttpGet("xlxapi.rlx.lu", "api/exportysfrepeaters.php", 80, buffer); + // get file from xlxapi server + return HttpGet("xlxapi.rlx.lu", "api/exportysfrepeaters.php", 80, buffer); } bool CYsfNodeDirHttp::RefreshContent(const CBuffer &buffer) { - bool ok = false; - - // clear directory - clear(); - - // scan buffer - if ( buffer.size() > 0 ) - { - // crack it - char *ptr1 = (char *)buffer.data(); - char *ptr2; - - // get next line - while ( (ptr2 = ::strchr(ptr1, '\n')) != nullptr ) - { - *ptr2 = 0; - // get items - char *callsign; - char *txfreq; - char *rxfreq; - if ( ((callsign = ::strtok(ptr1, ";")) != nullptr) ) - { - if ( ((txfreq = ::strtok(nullptr, ";")) != nullptr) ) - { - if ( ((rxfreq = ::strtok(nullptr, ";")) != nullptr) ) - { - // new entry - CCallsign cs(callsign); - CYsfNode node(cs, atoi(txfreq), atoi(rxfreq)); - if ( cs.IsValid() && node.IsValid() ) - { - insert(std::pair(cs, node)); - } - } - } - } - // next line - ptr1 = ptr2+1; - } - - // done - ok = true; - } - - // report - std::cout << "Read " << size() << " YSF nodes from xlxapi.rlx.lu database " << std::endl; - - // done - return ok; + bool ok = false; + + // clear directory + clear(); + + // scan buffer + if ( buffer.size() > 0 ) + { + // crack it + char *ptr1 = (char *)buffer.data(); + char *ptr2; + + // get next line + while ( (ptr2 = ::strchr(ptr1, '\n')) != nullptr ) + { + *ptr2 = 0; + // get items + char *callsign; + char *txfreq; + char *rxfreq; + if ( ((callsign = ::strtok(ptr1, ";")) != nullptr) ) + { + if ( ((txfreq = ::strtok(nullptr, ";")) != nullptr) ) + { + if ( ((rxfreq = ::strtok(nullptr, ";")) != nullptr) ) + { + // new entry + CCallsign cs(callsign); + CYsfNode node(cs, atoi(txfreq), atoi(rxfreq)); + if ( cs.IsValid() && node.IsValid() ) + { + insert(std::pair(cs, node)); + } + } + } + } + // next line + ptr1 = ptr2+1; + } + + // done + ok = true; + } + + // report + std::cout << "Read " << size() << " YSF nodes from xlxapi.rlx.lu database " << std::endl; + + // done + return ok; } @@ -102,83 +102,84 @@ bool CYsfNodeDirHttp::RefreshContent(const CBuffer &buffer) bool CYsfNodeDirHttp::HttpGet(const char *hostname, const char *filename, int port, CBuffer *buffer) { - bool ok = false; - int sock_id; - - // open socket - if ( (sock_id = ::socket(AF_INET, SOCK_STREAM, 0)) >= 0 ) - { - // get hostname address - struct sockaddr_in servaddr; - struct hostent *hp; - ::memset(&servaddr,0,sizeof(servaddr)); - if( (hp = gethostbyname(hostname)) != nullptr ) - { - // dns resolved - ::memcpy((char *)&servaddr.sin_addr.s_addr, (char *)hp->h_addr, hp->h_length); - servaddr.sin_port = htons(port); - servaddr.sin_family = AF_INET; - - // connect - if ( ::connect(sock_id, (struct sockaddr *)&servaddr, sizeof(servaddr)) == 0) - { - // send the GET request - char request[YSFNODE_HTTPGET_SIZEMAX]; - ::sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: xlxd\r\n\r\n", - filename, (const char *)g_Reflector.GetCallsign()); - ::write(sock_id, request, strlen(request)); - - // config receive timeouts - fd_set read_set; - struct timeval timeout; - timeout.tv_sec = 5; - timeout.tv_usec = 0; - FD_ZERO(&read_set); - FD_SET(sock_id, &read_set); - - // get the reply back - buffer->clear(); - bool done = false; - do - { - char buf[1440]; - ssize_t len = 0; - select(sock_id+1, &read_set, nullptr, nullptr, &timeout); - //if ( (ret > 0) || ((ret < 0) && (errno == EINPROGRESS)) ) - //if ( ret >= 0 ) - //{ - usleep(5000); - len = read(sock_id, buf, 1440); - if ( len > 0 ) - { - buffer->Append((uint8 *)buf, (int)len); - ok = true; - } - //} - done = (len <= 0); - - } while (!done); - buffer->Append((uint8)0); - - // and disconnect - close(sock_id); - } - else - { - std::cout << "Cannot establish connection with host " << hostname << std::endl; - } - } - else - { - std::cout << "Host " << hostname << " not found" << std::endl; - } - - } - else - { - std::cout << "Failed to open wget socket" << std::endl; - } - - // done - return ok; + bool ok = false; + int sock_id; + + // open socket + if ( (sock_id = ::socket(AF_INET, SOCK_STREAM, 0)) >= 0 ) + { + // get hostname address + struct sockaddr_in servaddr; + struct hostent *hp; + ::memset(&servaddr,0,sizeof(servaddr)); + if( (hp = gethostbyname(hostname)) != nullptr ) + { + // dns resolved + ::memcpy((char *)&servaddr.sin_addr.s_addr, (char *)hp->h_addr, hp->h_length); + servaddr.sin_port = htons(port); + servaddr.sin_family = AF_INET; + + // connect + if ( ::connect(sock_id, (struct sockaddr *)&servaddr, sizeof(servaddr)) == 0) + { + // send the GET request + char request[YSFNODE_HTTPGET_SIZEMAX]; + ::sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: xlxd\r\n\r\n", + filename, (const char *)g_Reflector.GetCallsign()); + ::write(sock_id, request, strlen(request)); + + // config receive timeouts + fd_set read_set; + struct timeval timeout; + timeout.tv_sec = 5; + timeout.tv_usec = 0; + FD_ZERO(&read_set); + FD_SET(sock_id, &read_set); + + // get the reply back + buffer->clear(); + bool done = false; + do + { + char buf[1440]; + ssize_t len = 0; + select(sock_id+1, &read_set, nullptr, nullptr, &timeout); + //if ( (ret > 0) || ((ret < 0) && (errno == EINPROGRESS)) ) + //if ( ret >= 0 ) + //{ + usleep(5000); + len = read(sock_id, buf, 1440); + if ( len > 0 ) + { + buffer->Append((uint8 *)buf, (int)len); + ok = true; + } + //} + done = (len <= 0); + + } + while (!done); + buffer->Append((uint8)0); + + // and disconnect + close(sock_id); + } + else + { + std::cout << "Cannot establish connection with host " << hostname << std::endl; + } + } + else + { + std::cout << "Host " << hostname << " not found" << std::endl; + } + + } + else + { + std::cout << "Failed to open wget socket" << std::endl; + } + + // done + return ok; } diff --git a/src/cysfnodedirhttp.h b/src/cysfnodedirhttp.h index 3997fcb..0f145a3 100644 --- a/src/cysfnodedirhttp.h +++ b/src/cysfnodedirhttp.h @@ -33,20 +33,20 @@ class CYsfNodeDirHttp : public CYsfNodeDir { public: - // constructor - CYsfNodeDirHttp() {} - - // destructor - ~CYsfNodeDirHttp() {} - - // refresh - bool LoadContent(CBuffer *); - bool RefreshContent(const CBuffer &); - + // constructor + CYsfNodeDirHttp() {} + + // destructor + ~CYsfNodeDirHttp() {} + + // refresh + bool LoadContent(CBuffer *); + bool RefreshContent(const CBuffer &); + protected: - // reload helpers - bool NeedReload(void) { return true; } - bool HttpGet(const char *, const char *, int, CBuffer *); + // reload helpers + bool NeedReload(void) { return true; } + bool HttpGet(const char *, const char *, int, CBuffer *); }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cysfpayload.cpp b/src/cysfpayload.cpp index a3ffaae..28e818a 100644 --- a/src/cysfpayload.cpp +++ b/src/cysfpayload.cpp @@ -24,53 +24,58 @@ #include #include -const unsigned int INTERLEAVE_TABLE_9_20[] = { - 0U, 40U, 80U, 120U, 160U, 200U, 240U, 280U, 320U, - 2U, 42U, 82U, 122U, 162U, 202U, 242U, 282U, 322U, - 4U, 44U, 84U, 124U, 164U, 204U, 244U, 284U, 324U, - 6U, 46U, 86U, 126U, 166U, 206U, 246U, 286U, 326U, - 8U, 48U, 88U, 128U, 168U, 208U, 248U, 288U, 328U, - 10U, 50U, 90U, 130U, 170U, 210U, 250U, 290U, 330U, - 12U, 52U, 92U, 132U, 172U, 212U, 252U, 292U, 332U, - 14U, 54U, 94U, 134U, 174U, 214U, 254U, 294U, 334U, - 16U, 56U, 96U, 136U, 176U, 216U, 256U, 296U, 336U, - 18U, 58U, 98U, 138U, 178U, 218U, 258U, 298U, 338U, - 20U, 60U, 100U, 140U, 180U, 220U, 260U, 300U, 340U, - 22U, 62U, 102U, 142U, 182U, 222U, 262U, 302U, 342U, - 24U, 64U, 104U, 144U, 184U, 224U, 264U, 304U, 344U, - 26U, 66U, 106U, 146U, 186U, 226U, 266U, 306U, 346U, - 28U, 68U, 108U, 148U, 188U, 228U, 268U, 308U, 348U, - 30U, 70U, 110U, 150U, 190U, 230U, 270U, 310U, 350U, - 32U, 72U, 112U, 152U, 192U, 232U, 272U, 312U, 352U, - 34U, 74U, 114U, 154U, 194U, 234U, 274U, 314U, 354U, - 36U, 76U, 116U, 156U, 196U, 236U, 276U, 316U, 356U, - 38U, 78U, 118U, 158U, 198U, 238U, 278U, 318U, 358U}; - -const unsigned int INTERLEAVE_TABLE_5_20[] = { - 0U, 40U, 80U, 120U, 160U, - 2U, 42U, 82U, 122U, 162U, - 4U, 44U, 84U, 124U, 164U, - 6U, 46U, 86U, 126U, 166U, - 8U, 48U, 88U, 128U, 168U, - 10U, 50U, 90U, 130U, 170U, - 12U, 52U, 92U, 132U, 172U, - 14U, 54U, 94U, 134U, 174U, - 16U, 56U, 96U, 136U, 176U, - 18U, 58U, 98U, 138U, 178U, - 20U, 60U, 100U, 140U, 180U, - 22U, 62U, 102U, 142U, 182U, - 24U, 64U, 104U, 144U, 184U, - 26U, 66U, 106U, 146U, 186U, - 28U, 68U, 108U, 148U, 188U, - 30U, 70U, 110U, 150U, 190U, - 32U, 72U, 112U, 152U, 192U, - 34U, 74U, 114U, 154U, 194U, - 36U, 76U, 116U, 156U, 196U, - 38U, 78U, 118U, 158U, 198U}; +const unsigned int INTERLEAVE_TABLE_9_20[] = +{ + 0U, 40U, 80U, 120U, 160U, 200U, 240U, 280U, 320U, + 2U, 42U, 82U, 122U, 162U, 202U, 242U, 282U, 322U, + 4U, 44U, 84U, 124U, 164U, 204U, 244U, 284U, 324U, + 6U, 46U, 86U, 126U, 166U, 206U, 246U, 286U, 326U, + 8U, 48U, 88U, 128U, 168U, 208U, 248U, 288U, 328U, + 10U, 50U, 90U, 130U, 170U, 210U, 250U, 290U, 330U, + 12U, 52U, 92U, 132U, 172U, 212U, 252U, 292U, 332U, + 14U, 54U, 94U, 134U, 174U, 214U, 254U, 294U, 334U, + 16U, 56U, 96U, 136U, 176U, 216U, 256U, 296U, 336U, + 18U, 58U, 98U, 138U, 178U, 218U, 258U, 298U, 338U, + 20U, 60U, 100U, 140U, 180U, 220U, 260U, 300U, 340U, + 22U, 62U, 102U, 142U, 182U, 222U, 262U, 302U, 342U, + 24U, 64U, 104U, 144U, 184U, 224U, 264U, 304U, 344U, + 26U, 66U, 106U, 146U, 186U, 226U, 266U, 306U, 346U, + 28U, 68U, 108U, 148U, 188U, 228U, 268U, 308U, 348U, + 30U, 70U, 110U, 150U, 190U, 230U, 270U, 310U, 350U, + 32U, 72U, 112U, 152U, 192U, 232U, 272U, 312U, 352U, + 34U, 74U, 114U, 154U, 194U, 234U, 274U, 314U, 354U, + 36U, 76U, 116U, 156U, 196U, 236U, 276U, 316U, 356U, + 38U, 78U, 118U, 158U, 198U, 238U, 278U, 318U, 358U +}; + +const unsigned int INTERLEAVE_TABLE_5_20[] = +{ + 0U, 40U, 80U, 120U, 160U, + 2U, 42U, 82U, 122U, 162U, + 4U, 44U, 84U, 124U, 164U, + 6U, 46U, 86U, 126U, 166U, + 8U, 48U, 88U, 128U, 168U, + 10U, 50U, 90U, 130U, 170U, + 12U, 52U, 92U, 132U, 172U, + 14U, 54U, 94U, 134U, 174U, + 16U, 56U, 96U, 136U, 176U, + 18U, 58U, 98U, 138U, 178U, + 20U, 60U, 100U, 140U, 180U, + 22U, 62U, 102U, 142U, 182U, + 24U, 64U, 104U, 144U, 184U, + 26U, 66U, 106U, 146U, 186U, + 28U, 68U, 108U, 148U, 188U, + 30U, 70U, 110U, 150U, 190U, + 32U, 72U, 112U, 152U, 192U, + 34U, 74U, 114U, 154U, 194U, + 36U, 76U, 116U, 156U, 196U, + 38U, 78U, 118U, 158U, 198U +}; // This one differs from the others in that it interleaves bits and not dibits const unsigned char WHITENING_DATA[] = {0x93U, 0xD7U, 0x51U, 0x21U, 0x9CU, 0x2FU, 0x6CU, 0xD0U, 0xEFU, 0x0FU, - 0xF8U, 0x3DU, 0xF1U, 0x73U, 0x20U, 0x94U, 0xEDU, 0x1EU, 0x7CU, 0xD8U}; + 0xF8U, 0x3DU, 0xF1U, 0x73U, 0x20U, 0x94U, 0xEDU, 0x1EU, 0x7CU, 0xD8U + }; const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; @@ -78,549 +83,590 @@ const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U #define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) CYSFPayload::CYSFPayload() : -m_uplink(nullptr), -m_downlink(nullptr), -m_source(nullptr), -m_dest(nullptr) + m_uplink(nullptr), + m_downlink(nullptr), + m_source(nullptr), + m_dest(nullptr) { } CYSFPayload::~CYSFPayload() { - delete[] m_uplink; - delete[] m_downlink; - delete[] m_source; - delete[] m_dest; + delete[] m_uplink; + delete[] m_downlink; + delete[] m_source; + delete[] m_dest; } bool CYSFPayload::processHeaderData(unsigned char* data) { - assert(data != nullptr); - - data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; - - unsigned char dch[45U]; - - unsigned char* p1 = data; - unsigned char* p2 = dch; - for (unsigned int i = 0U; i < 5U; i++) { - ::memcpy(p2, p1, 9U); - p1 += 18U; p2 += 9U; - } - - CYSFConvolution conv; - conv.start(); - - for (unsigned int i = 0U; i < 180U; i++) { - unsigned int n = INTERLEAVE_TABLE_9_20[i]; - uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U; - - n++; - uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U; - - conv.decode(s0, s1); - } - - unsigned char output[23U]; - conv.chainback(output, 176U); - - bool valid1 = CCRC::checkCCITT162(output, 22U); - if (valid1) { - for (unsigned int i = 0U; i < 20U; i++) - output[i] ^= WHITENING_DATA[i]; - - if (m_dest == nullptr) { - m_dest = new unsigned char[YSF_CALLSIGN_LENGTH]; - ::memcpy(m_dest, output + 0U, YSF_CALLSIGN_LENGTH); - } - - if (m_source == nullptr) { - m_source = new unsigned char[YSF_CALLSIGN_LENGTH]; - ::memcpy(m_source, output + YSF_CALLSIGN_LENGTH, YSF_CALLSIGN_LENGTH); - } - - for (unsigned int i = 0U; i < 20U; i++) - output[i] ^= WHITENING_DATA[i]; - - CCRC::addCCITT162(output, 22U); - output[22U] = 0x00U; - - unsigned char convolved[45U]; - conv.encode(output, convolved, 180U); - - unsigned char bytes[45U]; - unsigned int j = 0U; - for (unsigned int i = 0U; i < 180U; i++) { - unsigned int n = INTERLEAVE_TABLE_9_20[i]; - - bool s0 = READ_BIT1(convolved, j) != 0U; - j++; - - bool s1 = READ_BIT1(convolved, j) != 0U; - j++; - - WRITE_BIT1(bytes, n, s0); - - n++; - WRITE_BIT1(bytes, n, s1); - } - - p1 = data; - p2 = bytes; - for (unsigned int i = 0U; i < 5U; i++) { - ::memcpy(p1, p2, 9U); - p1 += 18U; p2 += 9U; - } - } - - p1 = data + 9U; - p2 = dch; - for (unsigned int i = 0U; i < 5U; i++) { - ::memcpy(p2, p1, 9U); - p1 += 18U; p2 += 9U; - } - - conv.start(); - - for (unsigned int i = 0U; i < 180U; i++) { - unsigned int n = INTERLEAVE_TABLE_9_20[i]; - uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U; - - n++; - uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U; - - conv.decode(s0, s1); - } - - conv.chainback(output, 176U); - - bool valid2 = CCRC::checkCCITT162(output, 22U); - if (valid2) { - for (unsigned int i = 0U; i < 20U; i++) - output[i] ^= WHITENING_DATA[i]; - - if (m_downlink != nullptr) - ::memcpy(output + 0U, m_downlink, YSF_CALLSIGN_LENGTH); + assert(data != nullptr); + + data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; + + unsigned char dch[45U]; + + unsigned char* p1 = data; + unsigned char* p2 = dch; + for (unsigned int i = 0U; i < 5U; i++) + { + ::memcpy(p2, p1, 9U); + p1 += 18U; + p2 += 9U; + } + + CYSFConvolution conv; + conv.start(); + + for (unsigned int i = 0U; i < 180U; i++) + { + unsigned int n = INTERLEAVE_TABLE_9_20[i]; + uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U; - if (m_uplink != nullptr) - ::memcpy(output + YSF_CALLSIGN_LENGTH, m_uplink, YSF_CALLSIGN_LENGTH); + n++; + uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U; - for (unsigned int i = 0U; i < 20U; i++) - output[i] ^= WHITENING_DATA[i]; + conv.decode(s0, s1); + } - CCRC::addCCITT162(output, 22U); - output[22U] = 0x00U; + unsigned char output[23U]; + conv.chainback(output, 176U); - unsigned char convolved[45U]; - conv.encode(output, convolved, 180U); + bool valid1 = CCRC::checkCCITT162(output, 22U); + if (valid1) + { + for (unsigned int i = 0U; i < 20U; i++) + output[i] ^= WHITENING_DATA[i]; - unsigned char bytes[45U]; - unsigned int j = 0U; - for (unsigned int i = 0U; i < 180U; i++) { - unsigned int n = INTERLEAVE_TABLE_9_20[i]; + if (m_dest == nullptr) + { + m_dest = new unsigned char[YSF_CALLSIGN_LENGTH]; + ::memcpy(m_dest, output + 0U, YSF_CALLSIGN_LENGTH); + } - bool s0 = READ_BIT1(convolved, j) != 0U; - j++; + if (m_source == nullptr) + { + m_source = new unsigned char[YSF_CALLSIGN_LENGTH]; + ::memcpy(m_source, output + YSF_CALLSIGN_LENGTH, YSF_CALLSIGN_LENGTH); + } - bool s1 = READ_BIT1(convolved, j) != 0U; - j++; + for (unsigned int i = 0U; i < 20U; i++) + output[i] ^= WHITENING_DATA[i]; - WRITE_BIT1(bytes, n, s0); + CCRC::addCCITT162(output, 22U); + output[22U] = 0x00U; + + unsigned char convolved[45U]; + conv.encode(output, convolved, 180U); + + unsigned char bytes[45U]; + unsigned int j = 0U; + for (unsigned int i = 0U; i < 180U; i++) + { + unsigned int n = INTERLEAVE_TABLE_9_20[i]; + + bool s0 = READ_BIT1(convolved, j) != 0U; + j++; + + bool s1 = READ_BIT1(convolved, j) != 0U; + j++; + + WRITE_BIT1(bytes, n, s0); + + n++; + WRITE_BIT1(bytes, n, s1); + } + + p1 = data; + p2 = bytes; + for (unsigned int i = 0U; i < 5U; i++) + { + ::memcpy(p1, p2, 9U); + p1 += 18U; + p2 += 9U; + } + } + + p1 = data + 9U; + p2 = dch; + for (unsigned int i = 0U; i < 5U; i++) + { + ::memcpy(p2, p1, 9U); + p1 += 18U; + p2 += 9U; + } + + conv.start(); + + for (unsigned int i = 0U; i < 180U; i++) + { + unsigned int n = INTERLEAVE_TABLE_9_20[i]; + uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U; + + n++; + uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U; + + conv.decode(s0, s1); + } + + conv.chainback(output, 176U); + + bool valid2 = CCRC::checkCCITT162(output, 22U); + if (valid2) + { + for (unsigned int i = 0U; i < 20U; i++) + output[i] ^= WHITENING_DATA[i]; + + if (m_downlink != nullptr) + ::memcpy(output + 0U, m_downlink, YSF_CALLSIGN_LENGTH); + + if (m_uplink != nullptr) + ::memcpy(output + YSF_CALLSIGN_LENGTH, m_uplink, YSF_CALLSIGN_LENGTH); - n++; - WRITE_BIT1(bytes, n, s1); - } + for (unsigned int i = 0U; i < 20U; i++) + output[i] ^= WHITENING_DATA[i]; + + CCRC::addCCITT162(output, 22U); + output[22U] = 0x00U; + + unsigned char convolved[45U]; + conv.encode(output, convolved, 180U); + + unsigned char bytes[45U]; + unsigned int j = 0U; + for (unsigned int i = 0U; i < 180U; i++) + { + unsigned int n = INTERLEAVE_TABLE_9_20[i]; + + bool s0 = READ_BIT1(convolved, j) != 0U; + j++; + + bool s1 = READ_BIT1(convolved, j) != 0U; + j++; - p1 = data + 9U; - p2 = bytes; - for (unsigned int i = 0U; i < 5U; i++) { - ::memcpy(p1, p2, 9U); - p1 += 18U; p2 += 9U; - } - } + WRITE_BIT1(bytes, n, s0); + + n++; + WRITE_BIT1(bytes, n, s1); + } - return valid1; + p1 = data + 9U; + p2 = bytes; + for (unsigned int i = 0U; i < 5U; i++) + { + ::memcpy(p1, p2, 9U); + p1 += 18U; + p2 += 9U; + } + } + + return valid1; } bool CYSFPayload::readDataFRModeData1(const unsigned char* data, unsigned char* dt) { - assert(data != nullptr); - assert(dt != nullptr); + assert(data != nullptr); + assert(dt != nullptr); - ::memset(dt, ' ', 20U); + ::memset(dt, ' ', 20U); - data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; + data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; - unsigned char dch[45U]; + unsigned char dch[45U]; - const unsigned char* p1 = data; - unsigned char* p2 = dch; - for (unsigned int i = 0U; i < 5U; i++) { - ::memcpy(p2, p1, 9U); - p1 += 18U; p2 += 9U; - } + const unsigned char* p1 = data; + unsigned char* p2 = dch; + for (unsigned int i = 0U; i < 5U; i++) + { + ::memcpy(p2, p1, 9U); + p1 += 18U; + p2 += 9U; + } - CYSFConvolution conv; - conv.start(); + CYSFConvolution conv; + conv.start(); - for (unsigned int i = 0U; i < 180U; i++) { - unsigned int n = INTERLEAVE_TABLE_9_20[i]; - uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U; + for (unsigned int i = 0U; i < 180U; i++) + { + unsigned int n = INTERLEAVE_TABLE_9_20[i]; + uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U; - n++; - uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U; + n++; + uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U; - conv.decode(s0, s1); - } + conv.decode(s0, s1); + } - unsigned char output[23U]; - conv.chainback(output, 176U); + unsigned char output[23U]; + conv.chainback(output, 176U); - bool ret = CCRC::checkCCITT162(output, 22U); - if (ret) { - for (unsigned int i = 0U; i < 20U; i++) - output[i] ^= WHITENING_DATA[i]; + bool ret = CCRC::checkCCITT162(output, 22U); + if (ret) + { + for (unsigned int i = 0U; i < 20U; i++) + output[i] ^= WHITENING_DATA[i]; - // CUtils::dump(1U, "FR Mode Data 1", output, 20U); + // CUtils::dump(1U, "FR Mode Data 1", output, 20U); - ::memcpy(dt, output, 20U); - } + ::memcpy(dt, output, 20U); + } - return ret; + return ret; } bool CYSFPayload::readDataFRModeData2(const unsigned char* data, unsigned char* dt) { - assert(data != nullptr); - assert(dt != nullptr); + assert(data != nullptr); + assert(dt != nullptr); - ::memset(dt, ' ', 20U); + ::memset(dt, ' ', 20U); - data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; + data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; - unsigned char dch[45U]; + unsigned char dch[45U]; - const unsigned char* p1 = data + 9U; - unsigned char* p2 = dch; - for (unsigned int i = 0U; i < 5U; i++) { - ::memcpy(p2, p1, 9U); - p1 += 18U; p2 += 9U; - } + const unsigned char* p1 = data + 9U; + unsigned char* p2 = dch; + for (unsigned int i = 0U; i < 5U; i++) + { + ::memcpy(p2, p1, 9U); + p1 += 18U; + p2 += 9U; + } - CYSFConvolution conv; - conv.start(); + CYSFConvolution conv; + conv.start(); - for (unsigned int i = 0U; i < 180U; i++) { - unsigned int n = INTERLEAVE_TABLE_9_20[i]; - uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U; + for (unsigned int i = 0U; i < 180U; i++) + { + unsigned int n = INTERLEAVE_TABLE_9_20[i]; + uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U; - n++; - uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U; + n++; + uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U; - conv.decode(s0, s1); - } + conv.decode(s0, s1); + } - unsigned char output[23U]; - conv.chainback(output, 176U); + unsigned char output[23U]; + conv.chainback(output, 176U); - bool ret = CCRC::checkCCITT162(output, 22U); - if (ret) { - for (unsigned int i = 0U; i < 20U; i++) - output[i] ^= WHITENING_DATA[i]; + bool ret = CCRC::checkCCITT162(output, 22U); + if (ret) + { + for (unsigned int i = 0U; i < 20U; i++) + output[i] ^= WHITENING_DATA[i]; - // CUtils::dump(1U, "FR Mode Data 2", output, 20U); + // CUtils::dump(1U, "FR Mode Data 2", output, 20U); - ::memcpy(dt, output, 20U); - } + ::memcpy(dt, output, 20U); + } - return ret; + return ret; } void CYSFPayload::writeVDMode2Data(unsigned char* data, const unsigned char* dt) { - data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; + data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; - unsigned char dt_tmp[13]; - ::memcpy(dt_tmp, dt, YSF_CALLSIGN_LENGTH); + unsigned char dt_tmp[13]; + ::memcpy(dt_tmp, dt, YSF_CALLSIGN_LENGTH); - for (unsigned int i = 0U; i < 10U; i++) - dt_tmp[i] ^= WHITENING_DATA[i]; + for (unsigned int i = 0U; i < 10U; i++) + dt_tmp[i] ^= WHITENING_DATA[i]; - CCRC::addCCITT162(dt_tmp, 12U); - dt_tmp[12U] = 0x00U; + CCRC::addCCITT162(dt_tmp, 12U); + dt_tmp[12U] = 0x00U; - unsigned char convolved[25U]; - CYSFConvolution conv; - conv.start(); - conv.encode(dt_tmp, convolved, 100U); + unsigned char convolved[25U]; + CYSFConvolution conv; + conv.start(); + conv.encode(dt_tmp, convolved, 100U); - unsigned char bytes[25U]; - unsigned int j = 0U; - for (unsigned int i = 0U; i < 100U; i++) { - unsigned int n = INTERLEAVE_TABLE_5_20[i]; + unsigned char bytes[25U]; + unsigned int j = 0U; + for (unsigned int i = 0U; i < 100U; i++) + { + unsigned int n = INTERLEAVE_TABLE_5_20[i]; - bool s0 = READ_BIT1(convolved, j) != 0U; - j++; + bool s0 = READ_BIT1(convolved, j) != 0U; + j++; - bool s1 = READ_BIT1(convolved, j) != 0U; - j++; + bool s1 = READ_BIT1(convolved, j) != 0U; + j++; - WRITE_BIT1(bytes, n, s0); + WRITE_BIT1(bytes, n, s0); - n++; - WRITE_BIT1(bytes, n, s1); - } + n++; + WRITE_BIT1(bytes, n, s1); + } - unsigned char* p1 = data; - unsigned char* p2 = bytes; - for (unsigned int i = 0U; i < 5U; i++) { - ::memcpy(p1, p2, 5U); - p1 += 18U; p2 += 5U; - } + unsigned char* p1 = data; + unsigned char* p2 = bytes; + for (unsigned int i = 0U; i < 5U; i++) + { + ::memcpy(p1, p2, 5U); + p1 += 18U; + p2 += 5U; + } } bool CYSFPayload::readVDMode1Data(const unsigned char* data, unsigned char* dt) { - assert(data != nullptr); - assert(dt != nullptr); + assert(data != nullptr); + assert(dt != nullptr); - data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; + data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; - unsigned char dch[45U]; + unsigned char dch[45U]; - const unsigned char* p1 = data; - unsigned char* p2 = dch; - for (unsigned int i = 0U; i < 5U; i++) { - ::memcpy(p2, p1, 9U); - p1 += 18U; p2 += 9U; - } + const unsigned char* p1 = data; + unsigned char* p2 = dch; + for (unsigned int i = 0U; i < 5U; i++) + { + ::memcpy(p2, p1, 9U); + p1 += 18U; + p2 += 9U; + } - CYSFConvolution conv; - conv.start(); + CYSFConvolution conv; + conv.start(); - for (unsigned int i = 0U; i < 180U; i++) { - unsigned int n = INTERLEAVE_TABLE_9_20[i]; - uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U; + for (unsigned int i = 0U; i < 180U; i++) + { + unsigned int n = INTERLEAVE_TABLE_9_20[i]; + uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U; - n++; - uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U; + n++; + uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U; - conv.decode(s0, s1); - } + conv.decode(s0, s1); + } - unsigned char output[23U]; - conv.chainback(output, 176U); + unsigned char output[23U]; + conv.chainback(output, 176U); - bool ret = CCRC::checkCCITT162(output, 22U); - if (ret) { - for (unsigned int i = 0U; i < 20U; i++) - output[i] ^= WHITENING_DATA[i]; + bool ret = CCRC::checkCCITT162(output, 22U); + if (ret) + { + for (unsigned int i = 0U; i < 20U; i++) + output[i] ^= WHITENING_DATA[i]; - // CUtils::dump(1U, "V/D Mode 1 Data", output, 20U); + // CUtils::dump(1U, "V/D Mode 1 Data", output, 20U); - ::memcpy(dt, output, 20U); - } + ::memcpy(dt, output, 20U); + } - return ret; + return ret; } bool CYSFPayload::readVDMode2Data(const unsigned char* data, unsigned char* dt) { - assert(data != nullptr); - assert(dt != nullptr); + assert(data != nullptr); + assert(dt != nullptr); - data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; + data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; - unsigned char dch[25U]; + unsigned char dch[25U]; - const unsigned char* p1 = data; - unsigned char* p2 = dch; - for (unsigned int i = 0U; i < 5U; i++) { - ::memcpy(p2, p1, 5U); - p1 += 18U; p2 += 5U; - } + const unsigned char* p1 = data; + unsigned char* p2 = dch; + for (unsigned int i = 0U; i < 5U; i++) + { + ::memcpy(p2, p1, 5U); + p1 += 18U; + p2 += 5U; + } - CYSFConvolution conv; - conv.start(); + CYSFConvolution conv; + conv.start(); - for (unsigned int i = 0U; i < 100U; i++) { - unsigned int n = INTERLEAVE_TABLE_5_20[i]; - uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U; + for (unsigned int i = 0U; i < 100U; i++) + { + unsigned int n = INTERLEAVE_TABLE_5_20[i]; + uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U; - n++; - uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U; + n++; + uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U; - conv.decode(s0, s1); - } + conv.decode(s0, s1); + } - unsigned char output[13U]; - conv.chainback(output, 96U); + unsigned char output[13U]; + conv.chainback(output, 96U); - bool ret = CCRC::checkCCITT162(output, 12U); - if (ret) { - for (unsigned int i = 0U; i < 10U; i++) - output[i] ^= WHITENING_DATA[i]; + bool ret = CCRC::checkCCITT162(output, 12U); + if (ret) + { + for (unsigned int i = 0U; i < 10U; i++) + output[i] ^= WHITENING_DATA[i]; - // CUtils::dump(1U, "V/D Mode 2 Data", output, YSF_CALLSIGN_LENGTH); + // CUtils::dump(1U, "V/D Mode 2 Data", output, YSF_CALLSIGN_LENGTH); - ::memcpy(dt, output, YSF_CALLSIGN_LENGTH); - } + ::memcpy(dt, output, YSF_CALLSIGN_LENGTH); + } - return ret; + return ret; } void CYSFPayload::writeHeader(unsigned char* data, const unsigned char* csd1, const unsigned char* csd2) { - assert(data != nullptr); - assert(csd1 != nullptr); - assert(csd2 != nullptr); + assert(data != nullptr); + assert(csd1 != nullptr); + assert(csd2 != nullptr); - writeDataFRModeData1(csd1, data); + writeDataFRModeData1(csd1, data); - writeDataFRModeData2(csd2, data); + writeDataFRModeData2(csd2, data); } void CYSFPayload::writeDataFRModeData1(const unsigned char* dt, unsigned char* data) { - assert(dt != nullptr); - assert(data != nullptr); + assert(dt != nullptr); + assert(data != nullptr); - data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; + data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; - unsigned char output[25U]; - for (unsigned int i = 0U; i < 20U; i++) - output[i] = dt[i] ^ WHITENING_DATA[i]; + unsigned char output[25U]; + for (unsigned int i = 0U; i < 20U; i++) + output[i] = dt[i] ^ WHITENING_DATA[i]; - CCRC::addCCITT162(output, 22U); - output[22U] = 0x00U; + CCRC::addCCITT162(output, 22U); + output[22U] = 0x00U; - unsigned char convolved[45U]; + unsigned char convolved[45U]; - CYSFConvolution conv; - conv.encode(output, convolved, 180U); + CYSFConvolution conv; + conv.encode(output, convolved, 180U); - unsigned char bytes[45U]; - unsigned int j = 0U; - for (unsigned int i = 0U; i < 180U; i++) { - unsigned int n = INTERLEAVE_TABLE_9_20[i]; + unsigned char bytes[45U]; + unsigned int j = 0U; + for (unsigned int i = 0U; i < 180U; i++) + { + unsigned int n = INTERLEAVE_TABLE_9_20[i]; - bool s0 = READ_BIT1(convolved, j) != 0U; - j++; + bool s0 = READ_BIT1(convolved, j) != 0U; + j++; - bool s1 = READ_BIT1(convolved, j) != 0U; - j++; + bool s1 = READ_BIT1(convolved, j) != 0U; + j++; - WRITE_BIT1(bytes, n, s0); + WRITE_BIT1(bytes, n, s0); - n++; - WRITE_BIT1(bytes, n, s1); - } + n++; + WRITE_BIT1(bytes, n, s1); + } - unsigned char* p1 = data; - unsigned char* p2 = bytes; - for (unsigned int i = 0U; i < 5U; i++) { - ::memcpy(p1, p2, 9U); - p1 += 18U; p2 += 9U; - } + unsigned char* p1 = data; + unsigned char* p2 = bytes; + for (unsigned int i = 0U; i < 5U; i++) + { + ::memcpy(p1, p2, 9U); + p1 += 18U; + p2 += 9U; + } } void CYSFPayload::writeDataFRModeData2(const unsigned char* dt, unsigned char* data) { - assert(dt != nullptr); - assert(data != nullptr); + assert(dt != nullptr); + assert(data != nullptr); - data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; + data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; - unsigned char output[25U]; - for (unsigned int i = 0U; i < 20U; i++) - output[i] = dt[i] ^ WHITENING_DATA[i]; + unsigned char output[25U]; + for (unsigned int i = 0U; i < 20U; i++) + output[i] = dt[i] ^ WHITENING_DATA[i]; - CCRC::addCCITT162(output, 22U); - output[22U] = 0x00U; + CCRC::addCCITT162(output, 22U); + output[22U] = 0x00U; - unsigned char convolved[45U]; + unsigned char convolved[45U]; - CYSFConvolution conv; - conv.encode(output, convolved, 180U); + CYSFConvolution conv; + conv.encode(output, convolved, 180U); - unsigned char bytes[45U]; - unsigned int j = 0U; - for (unsigned int i = 0U; i < 180U; i++) { - unsigned int n = INTERLEAVE_TABLE_9_20[i]; + unsigned char bytes[45U]; + unsigned int j = 0U; + for (unsigned int i = 0U; i < 180U; i++) + { + unsigned int n = INTERLEAVE_TABLE_9_20[i]; - bool s0 = READ_BIT1(convolved, j) != 0U; - j++; + bool s0 = READ_BIT1(convolved, j) != 0U; + j++; - bool s1 = READ_BIT1(convolved, j) != 0U; - j++; + bool s1 = READ_BIT1(convolved, j) != 0U; + j++; - WRITE_BIT1(bytes, n, s0); + WRITE_BIT1(bytes, n, s0); - n++; - WRITE_BIT1(bytes, n, s1); - } + n++; + WRITE_BIT1(bytes, n, s1); + } - unsigned char* p1 = data + 9U; - unsigned char* p2 = bytes; - for (unsigned int i = 0U; i < 5U; i++) { - ::memcpy(p1, p2, 9U); - p1 += 18U; p2 += 9U; - } + unsigned char* p1 = data + 9U; + unsigned char* p2 = bytes; + for (unsigned int i = 0U; i < 5U; i++) + { + ::memcpy(p1, p2, 9U); + p1 += 18U; + p2 += 9U; + } } void CYSFPayload::setUplink(const std::string& callsign) { - m_uplink = new unsigned char[YSF_CALLSIGN_LENGTH]; + m_uplink = new unsigned char[YSF_CALLSIGN_LENGTH]; - std::string uplink = callsign; - uplink.resize(YSF_CALLSIGN_LENGTH, ' '); + std::string uplink = callsign; + uplink.resize(YSF_CALLSIGN_LENGTH, ' '); - for (unsigned int i = 0U; i < YSF_CALLSIGN_LENGTH; i++) - m_uplink[i] = uplink.at(i); + for (unsigned int i = 0U; i < YSF_CALLSIGN_LENGTH; i++) + m_uplink[i] = uplink.at(i); } void CYSFPayload::setDownlink(const std::string& callsign) { - m_downlink = new unsigned char[YSF_CALLSIGN_LENGTH]; + m_downlink = new unsigned char[YSF_CALLSIGN_LENGTH]; - std::string downlink = callsign; - downlink.resize(YSF_CALLSIGN_LENGTH, ' '); + std::string downlink = callsign; + downlink.resize(YSF_CALLSIGN_LENGTH, ' '); - for (unsigned int i = 0U; i < YSF_CALLSIGN_LENGTH; i++) - m_downlink[i] = downlink.at(i); + for (unsigned int i = 0U; i < YSF_CALLSIGN_LENGTH; i++) + m_downlink[i] = downlink.at(i); } std::string CYSFPayload::getSource() { - std::string tmp; + std::string tmp; - if (m_dest) - tmp.assign((const char *)m_source, YSF_CALLSIGN_LENGTH); - else - tmp = ""; + if (m_dest) + tmp.assign((const char *)m_source, YSF_CALLSIGN_LENGTH); + else + tmp = ""; - return tmp; + return tmp; } std::string CYSFPayload::getDest() { - std::string tmp; + std::string tmp; - if (m_dest) - tmp.assign((const char *)m_dest, YSF_CALLSIGN_LENGTH); - else - tmp = ""; + if (m_dest) + tmp.assign((const char *)m_dest, YSF_CALLSIGN_LENGTH); + else + tmp = ""; - return tmp; + return tmp; } void CYSFPayload::reset() { - delete[] m_source; - delete[] m_dest; + delete[] m_source; + delete[] m_dest; - m_source = nullptr; - m_dest = nullptr; + m_source = nullptr; + m_dest = nullptr; } diff --git a/src/cysfpayload.h b/src/cysfpayload.h index b741037..1290381 100644 --- a/src/cysfpayload.h +++ b/src/cysfpayload.h @@ -21,37 +21,38 @@ #include -class CYSFPayload { +class CYSFPayload +{ public: - CYSFPayload(); - ~CYSFPayload(); - - bool processHeaderData(unsigned char* bytes); - - void writeVDMode2Data(unsigned char* data, const unsigned char* dt); - bool readVDMode1Data(const unsigned char* data, unsigned char* dt); - bool readVDMode2Data(const unsigned char* data, unsigned char* dt); - - void writeHeader(unsigned char* data, const unsigned char* csd1, const unsigned char* csd2); - - void writeDataFRModeData1(const unsigned char* dt, unsigned char* data); - void writeDataFRModeData2(const unsigned char* dt, unsigned char* data); - bool readDataFRModeData1(const unsigned char* data, unsigned char* dt); - bool readDataFRModeData2(const unsigned char* data, unsigned char* dt); - - std::string getSource(); - std::string getDest(); - - void setUplink(const std::string& callsign); - void setDownlink(const std::string& callsign); - - void reset(); - + CYSFPayload(); + ~CYSFPayload(); + + bool processHeaderData(unsigned char* bytes); + + void writeVDMode2Data(unsigned char* data, const unsigned char* dt); + bool readVDMode1Data(const unsigned char* data, unsigned char* dt); + bool readVDMode2Data(const unsigned char* data, unsigned char* dt); + + void writeHeader(unsigned char* data, const unsigned char* csd1, const unsigned char* csd2); + + void writeDataFRModeData1(const unsigned char* dt, unsigned char* data); + void writeDataFRModeData2(const unsigned char* dt, unsigned char* data); + bool readDataFRModeData1(const unsigned char* data, unsigned char* dt); + bool readDataFRModeData2(const unsigned char* data, unsigned char* dt); + + std::string getSource(); + std::string getDest(); + + void setUplink(const std::string& callsign); + void setDownlink(const std::string& callsign); + + void reset(); + private: - unsigned char* m_uplink; - unsigned char* m_downlink; - unsigned char* m_source; - unsigned char* m_dest; + unsigned char* m_uplink; + unsigned char* m_downlink; + unsigned char* m_source; + unsigned char* m_dest; }; #endif diff --git a/src/cysfprotocol.cpp b/src/cysfprotocol.cpp index a4770da..1d51b6e 100644 --- a/src/cysfprotocol.cpp +++ b/src/cysfprotocol.cpp @@ -39,7 +39,7 @@ // constructor CYsfProtocol::CYsfProtocol() { - m_seqNo = 0; + m_seqNo = 0; } //////////////////////////////////////////////////////////////////////////////////////// @@ -47,28 +47,28 @@ CYsfProtocol::CYsfProtocol() bool CYsfProtocol::Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6) { - // base class - if (! CProtocol::Initialize(type, port, has_ipv4, has_ipv6)) + // base class + if (! CProtocol::Initialize(type, port, has_ipv4, has_ipv6)) return false; - // init the wiresx cmd handler - if (! m_WiresxCmdHandler.Init()) + // init the wiresx cmd handler + if (! m_WiresxCmdHandler.Init()) return false; - // update time - m_LastKeepaliveTime.Now(); + // update time + m_LastKeepaliveTime.Now(); - // done - return true; + // done + return true; } void CYsfProtocol::Close(void) { - // base class - CProtocol::Close(); + // base class + CProtocol::Close(); - // and close wiresx handler - m_WiresxCmdHandler.Close(); + // and close wiresx handler + m_WiresxCmdHandler.Close(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -76,31 +76,31 @@ void CYsfProtocol::Close(void) void CYsfProtocol::Task(void) { - CBuffer Buffer; - CIp Ip; - CCallsign Callsign; - CYSFFICH Fich; - CDvHeaderPacket *Header; - CDvFramePacket *Frames[5]; - CWiresxCmd WiresxCmd; - - int iWiresxCmd; - int iWiresxArg; - - // handle outgoing packets - { - // any packet to go ? - CWiresxPacketQueue *queue = m_WiresxCmdHandler.GetPacketQueue(); - while ( !queue->empty() ) - { - CWiresxPacket packet = queue->front(); - queue->pop(); - Send(packet.GetBuffer(), packet.GetIp()); - } - m_WiresxCmdHandler.ReleasePacketQueue(); - } - - // handle incoming packets + CBuffer Buffer; + CIp Ip; + CCallsign Callsign; + CYSFFICH Fich; + CDvHeaderPacket *Header; + CDvFramePacket *Frames[5]; + CWiresxCmd WiresxCmd; + + int iWiresxCmd; + int iWiresxArg; + + // handle outgoing packets + { + // any packet to go ? + CWiresxPacketQueue *queue = m_WiresxCmdHandler.GetPacketQueue(); + while ( !queue->empty() ) + { + CWiresxPacket packet = queue->front(); + queue->pop(); + Send(packet.GetBuffer(), packet.GetIp()); + } + m_WiresxCmdHandler.ReleasePacketQueue(); + } + + // handle incoming packets #if YSF_IPV6==true #if YSF_IPV4==true if ( ReceiveDS(Buffer, Ip, 20) ) @@ -110,126 +110,126 @@ void CYsfProtocol::Task(void) #else if ( Receive4(Buffer, Ip, 20) ) #endif - { - // crack the packet - if ( IsValidDvPacket(Buffer, &Fich) ) - { - //std::cout << "FN = " << (int)Fich.getFN() << " FT = " << (int)Fich.getFT() << std::endl; - if ( IsValidDvFramePacket(Ip, Fich, Buffer, Frames) ) - { - //std::cout << "YSF DV frame" << std::endl; - - // handle it - OnDvFramePacketIn(Frames[0], &Ip); - OnDvFramePacketIn(Frames[1], &Ip); - OnDvFramePacketIn(Frames[2], &Ip); - OnDvFramePacketIn(Frames[3], &Ip); - OnDvFramePacketIn(Frames[4], &Ip); - } - else if ( IsValidDvHeaderPacket(Ip, Fich, Buffer, &Header, Frames) ) - { - //std::cout << "YSF DV header:" << std::endl << *Header << std::endl; - //std::cout << "YSF DV header:" << std::endl; - - // node linked and callsign muted? - if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_YSF, Header->GetRpt2Module()) ) - { - // handle it - OnDvHeaderPacketIn(Header, Ip); - //OnDvFramePacketIn(Frames[0], &Ip); - //OnDvFramePacketIn(Frames[1], &Ip); - } - else - { - delete Header; - } - } - else if ( IsValidDvLastFramePacket(Ip, Fich, Buffer, Frames) ) - { - //std::cout << "YSF last DV frame" << std::endl; - - // handle it - OnDvFramePacketIn(Frames[0], &Ip); - OnDvLastFramePacketIn((CDvLastFramePacket *)Frames[1], &Ip); - } - } - else if ( IsValidConnectPacket(Buffer, &Callsign) ) - { - //std::cout << "YSF keepalive/connect packet from " << Callsign << " at " << Ip << std::endl; - - // callsign authorized? - if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_YSF) ) - { - // acknowledge the request - EncodeConnectAckPacket(&Buffer); - Send(Buffer, Ip); - - // add client if needed - CClients *clients = g_Reflector.GetClients(); - std::shared_ptrclient = clients->FindClient(Callsign, Ip, PROTOCOL_YSF); - // client already connected ? - if ( client == nullptr ) - { - std::cout << "YSF connect packet from " << Callsign << " at " << Ip << std::endl; - - // create the client - auto newclient = std::make_shared(Callsign, Ip); - - // aautolink, if enabled - #if YSF_AUTOLINK_ENABLE - newclient->SetReflectorModule(YSF_AUTOLINK_MODULE); - #endif - - // and append - clients->AddClient(newclient); - } - else - { - client->Alive(); - } - // and done - g_Reflector.ReleaseClients(); - } - } - else if ( IsValidwirexPacket(Buffer, &Fich, &Callsign, &iWiresxCmd, &iWiresxArg) ) - { - //std::cout << "YSF Wires-x frame" << std::endl; - // prepare the cmd object - WiresxCmd = CWiresxCmd(Ip, Callsign, iWiresxCmd, iWiresxArg); - // and post it to hadler's queue - m_WiresxCmdHandler.GetCmdQueue()->push(WiresxCmd); - m_WiresxCmdHandler.ReleaseCmdQueue(); - } - else if ( IsValidServerStatusPacket(Buffer) ) - { - std::cout << "YSF server status enquiry from " << Ip << std::endl; - // reply - EncodeServerStatusPacket(&Buffer); - Send(Buffer, Ip); - } - else - { - // invalid packet - //std::cout << "YSF packet (" << Buffer.size() << ") from " << Callsign << " at " << Ip << std::endl; - //Buffer.DebugDump(g_Reflector.m_DebugFile); - } - } - - // handle end of streaming timeout - CheckStreamsTimeout(); - - // handle queue from reflector - HandleQueue(); - - // keep client alive - if ( m_LastKeepaliveTime.DurationSinceNow() > YSF_KEEPALIVE_PERIOD ) - { - // - HandleKeepalives(); - - // update time - m_LastKeepaliveTime.Now(); - } + { + // crack the packet + if ( IsValidDvPacket(Buffer, &Fich) ) + { + //std::cout << "FN = " << (int)Fich.getFN() << " FT = " << (int)Fich.getFT() << std::endl; + if ( IsValidDvFramePacket(Ip, Fich, Buffer, Frames) ) + { + //std::cout << "YSF DV frame" << std::endl; + + // handle it + OnDvFramePacketIn(Frames[0], &Ip); + OnDvFramePacketIn(Frames[1], &Ip); + OnDvFramePacketIn(Frames[2], &Ip); + OnDvFramePacketIn(Frames[3], &Ip); + OnDvFramePacketIn(Frames[4], &Ip); + } + else if ( IsValidDvHeaderPacket(Ip, Fich, Buffer, &Header, Frames) ) + { + //std::cout << "YSF DV header:" << std::endl << *Header << std::endl; + //std::cout << "YSF DV header:" << std::endl; + + // node linked and callsign muted? + if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_YSF, Header->GetRpt2Module()) ) + { + // handle it + OnDvHeaderPacketIn(Header, Ip); + //OnDvFramePacketIn(Frames[0], &Ip); + //OnDvFramePacketIn(Frames[1], &Ip); + } + else + { + delete Header; + } + } + else if ( IsValidDvLastFramePacket(Ip, Fich, Buffer, Frames) ) + { + //std::cout << "YSF last DV frame" << std::endl; + + // handle it + OnDvFramePacketIn(Frames[0], &Ip); + OnDvLastFramePacketIn((CDvLastFramePacket *)Frames[1], &Ip); + } + } + else if ( IsValidConnectPacket(Buffer, &Callsign) ) + { + //std::cout << "YSF keepalive/connect packet from " << Callsign << " at " << Ip << std::endl; + + // callsign authorized? + if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_YSF) ) + { + // acknowledge the request + EncodeConnectAckPacket(&Buffer); + Send(Buffer, Ip); + + // add client if needed + CClients *clients = g_Reflector.GetClients(); + std::shared_ptrclient = clients->FindClient(Callsign, Ip, PROTOCOL_YSF); + // client already connected ? + if ( client == nullptr ) + { + std::cout << "YSF connect packet from " << Callsign << " at " << Ip << std::endl; + + // create the client + auto newclient = std::make_shared(Callsign, Ip); + + // aautolink, if enabled +#if YSF_AUTOLINK_ENABLE + newclient->SetReflectorModule(YSF_AUTOLINK_MODULE); +#endif + + // and append + clients->AddClient(newclient); + } + else + { + client->Alive(); + } + // and done + g_Reflector.ReleaseClients(); + } + } + else if ( IsValidwirexPacket(Buffer, &Fich, &Callsign, &iWiresxCmd, &iWiresxArg) ) + { + //std::cout << "YSF Wires-x frame" << std::endl; + // prepare the cmd object + WiresxCmd = CWiresxCmd(Ip, Callsign, iWiresxCmd, iWiresxArg); + // and post it to hadler's queue + m_WiresxCmdHandler.GetCmdQueue()->push(WiresxCmd); + m_WiresxCmdHandler.ReleaseCmdQueue(); + } + else if ( IsValidServerStatusPacket(Buffer) ) + { + std::cout << "YSF server status enquiry from " << Ip << std::endl; + // reply + EncodeServerStatusPacket(&Buffer); + Send(Buffer, Ip); + } + else + { + // invalid packet + //std::cout << "YSF packet (" << Buffer.size() << ") from " << Callsign << " at " << Ip << std::endl; + //Buffer.DebugDump(g_Reflector.m_DebugFile); + } + } + + // handle end of streaming timeout + CheckStreamsTimeout(); + + // handle queue from reflector + HandleQueue(); + + // keep client alive + if ( m_LastKeepaliveTime.DurationSinceNow() > YSF_KEEPALIVE_PERIOD ) + { + // + HandleKeepalives(); + + // update time + m_LastKeepaliveTime.Now(); + } } //////////////////////////////////////////////////////////////////////////////////////// @@ -237,59 +237,59 @@ void CYsfProtocol::Task(void) bool CYsfProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip) { - bool newstream = false; - - // find the stream - CPacketStream *stream = GetStream(Header->GetStreamId()); - if ( stream == nullptr ) - { - // no stream open yet, open a new one - CCallsign via(Header->GetRpt1Callsign()); - - // find this client - std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_YSF); - if ( client != nullptr ) - { - // get client callsign - via = client->GetCallsign(); - // get module it's linked to - Header->SetRpt2Module(client->GetReflectorModule()); - - // and try to open the stream - if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) - { - // keep the handle - m_Streams.push_back(stream); - newstream = true; - } - } - // release - g_Reflector.ReleaseClients(); - - // update last heard - if ( g_Reflector.IsValidModule(Header->GetRpt2Module()) ) - { - g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), via, Header->GetRpt2Callsign()); - g_Reflector.ReleaseUsers(); - } - - // delete header if needed - if ( !newstream ) - { - delete Header; - } - } - else - { - // stream already open - // skip packet, but tickle the stream - stream->Tickle(); - // and delete packet - delete Header; - } - - // done - return newstream; + bool newstream = false; + + // find the stream + CPacketStream *stream = GetStream(Header->GetStreamId()); + if ( stream == nullptr ) + { + // no stream open yet, open a new one + CCallsign via(Header->GetRpt1Callsign()); + + // find this client + std::shared_ptrclient = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_YSF); + if ( client != nullptr ) + { + // get client callsign + via = client->GetCallsign(); + // get module it's linked to + Header->SetRpt2Module(client->GetReflectorModule()); + + // and try to open the stream + if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) + { + // keep the handle + m_Streams.push_back(stream); + newstream = true; + } + } + // release + g_Reflector.ReleaseClients(); + + // update last heard + if ( g_Reflector.IsValidModule(Header->GetRpt2Module()) ) + { + g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), via, Header->GetRpt2Callsign()); + g_Reflector.ReleaseUsers(); + } + + // delete header if needed + if ( !newstream ) + { + delete Header; + } + } + else + { + // stream already open + // skip packet, but tickle the stream + stream->Tickle(); + // and delete packet + delete Header; + } + + // done + return newstream; } //////////////////////////////////////////////////////////////////////////////////////// @@ -298,76 +298,76 @@ bool CYsfProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip) void CYsfProtocol::HandleQueue(void) { - m_Queue.Lock(); - while ( !m_Queue.empty() ) - { - // get the packet - CPacket *packet = m_Queue.front(); - m_Queue.pop(); - - // get our sender's id - int iModId = g_Reflector.GetModuleIndex(packet->GetModuleId()); - - // encode - CBuffer buffer; - - // check if it's header - if ( packet->IsDvHeader() ) - { - // update local stream cache - // this relies on queue feeder setting valid module id - m_StreamsCache[iModId].m_dvHeader = CDvHeaderPacket((const CDvHeaderPacket &)*packet); - - // encode it - EncodeDvHeaderPacket((const CDvHeaderPacket &)*packet, &buffer); - } - // check if it's a last frame - else if ( packet->IsLastPacket() ) - { - // encode it - EncodeDvLastPacket(m_StreamsCache[iModId].m_dvHeader, &buffer); - } - // otherwise, just a regular DV frame - else - { - // update local stream cache or send triplet when needed - uint8 sid = packet->GetYsfPacketSubId(); - if (sid <= 4) - { - //std::cout << (int)sid; - m_StreamsCache[iModId].m_dvFrames[sid] = CDvFramePacket((const CDvFramePacket &)*packet); - if ( sid == 4 ) - { - - EncodeDvPacket(m_StreamsCache[iModId].m_dvHeader, m_StreamsCache[iModId].m_dvFrames, &buffer); - } - } - } - - // send it - if ( buffer.size() > 0 ) - { - // and push it to all our clients linked to the module and who are not streaming in - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_YSF, it)) != nullptr ) - { - // is this client busy ? - if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) ) - { - // no, send the packet - Send(buffer, client->GetIp()); - - } - } - g_Reflector.ReleaseClients(); - } - - // done - delete packet; - } - m_Queue.Unlock(); + m_Queue.Lock(); + while ( !m_Queue.empty() ) + { + // get the packet + CPacket *packet = m_Queue.front(); + m_Queue.pop(); + + // get our sender's id + int iModId = g_Reflector.GetModuleIndex(packet->GetModuleId()); + + // encode + CBuffer buffer; + + // check if it's header + if ( packet->IsDvHeader() ) + { + // update local stream cache + // this relies on queue feeder setting valid module id + m_StreamsCache[iModId].m_dvHeader = CDvHeaderPacket((const CDvHeaderPacket &)*packet); + + // encode it + EncodeDvHeaderPacket((const CDvHeaderPacket &)*packet, &buffer); + } + // check if it's a last frame + else if ( packet->IsLastPacket() ) + { + // encode it + EncodeDvLastPacket(m_StreamsCache[iModId].m_dvHeader, &buffer); + } + // otherwise, just a regular DV frame + else + { + // update local stream cache or send triplet when needed + uint8 sid = packet->GetYsfPacketSubId(); + if (sid <= 4) + { + //std::cout << (int)sid; + m_StreamsCache[iModId].m_dvFrames[sid] = CDvFramePacket((const CDvFramePacket &)*packet); + if ( sid == 4 ) + { + + EncodeDvPacket(m_StreamsCache[iModId].m_dvHeader, m_StreamsCache[iModId].m_dvFrames, &buffer); + } + } + } + + // send it + if ( buffer.size() > 0 ) + { + // and push it to all our clients linked to the module and who are not streaming in + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_YSF, it)) != nullptr ) + { + // is this client busy ? + if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) ) + { + // no, send the packet + Send(buffer, client->GetIp()); + + } + } + g_Reflector.ReleaseClients(); + } + + // done + delete packet; + } + m_Queue.Unlock(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -375,32 +375,32 @@ void CYsfProtocol::HandleQueue(void) void CYsfProtocol::HandleKeepalives(void) { - // YSF protocol keepalive request is client tasks - // here, just check that all clients are still alive - // and disconnect them if not - - // iterate on clients - CClients *clients = g_Reflector.GetClients(); - auto it = clients->begin(); - std::shared_ptrclient = nullptr; - while ( (client = clients->FindNextClient(PROTOCOL_YSF, it)) != nullptr ) - { - // is this client busy ? - if ( client->IsAMaster() ) - { - // yes, just tickle it - client->Alive(); - } - // check it's still with us - else if ( !client->IsAlive() ) - { - // no, remove it - std::cout << "YSF client " << client->GetCallsign() << " keepalive timeout" << std::endl; - clients->RemoveClient(client); - } - - } - g_Reflector.ReleaseClients(); + // YSF protocol keepalive request is client tasks + // here, just check that all clients are still alive + // and disconnect them if not + + // iterate on clients + CClients *clients = g_Reflector.GetClients(); + auto it = clients->begin(); + std::shared_ptrclient = nullptr; + while ( (client = clients->FindNextClient(PROTOCOL_YSF, it)) != nullptr ) + { + // is this client busy ? + if ( client->IsAMaster() ) + { + // yes, just tickle it + client->Alive(); + } + // check it's still with us + else if ( !client->IsAlive() ) + { + // no, remove it + std::cout << "YSF client " << client->GetCallsign() << " keepalive timeout" << std::endl; + clients->RemoveClient(client); + } + + } + g_Reflector.ReleaseClients(); } //////////////////////////////////////////////////////////////////////////////////////// @@ -408,201 +408,201 @@ void CYsfProtocol::HandleKeepalives(void) bool CYsfProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsign) { - uint8 tag[] = { 'Y','S','F','P' }; - - bool valid = false; - if ( (Buffer.size() == 14) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - callsign->SetCallsign(Buffer.data()+4, 8); - callsign->SetModule(YSF_MODULE_ID); - valid = (callsign->IsValid()); - } - return valid; + uint8 tag[] = { 'Y','S','F','P' }; + + bool valid = false; + if ( (Buffer.size() == 14) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + callsign->SetCallsign(Buffer.data()+4, 8); + callsign->SetModule(YSF_MODULE_ID); + valid = (callsign->IsValid()); + } + return valid; } bool CYsfProtocol::IsValidDvPacket(const CBuffer &Buffer, CYSFFICH *Fich) { - uint8 tag[] = { 'Y','S','F','D' }; - - bool valid = false; - - if ( (Buffer.size() == 155) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - // decode YSH fich - if ( Fich->decode(&(Buffer.data()[40])) ) - { - valid = (Fich->getDT() == YSF_DT_VD_MODE2); - } - } - return valid; + uint8 tag[] = { 'Y','S','F','D' }; + + bool valid = false; + + if ( (Buffer.size() == 155) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + // decode YSH fich + if ( Fich->decode(&(Buffer.data()[40])) ) + { + valid = (Fich->getDT() == YSF_DT_VD_MODE2); + } + } + return valid; } bool CYsfProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CYSFFICH &Fich, const CBuffer &Buffer, CDvHeaderPacket **header, CDvFramePacket **frames) { - bool valid = false; - *header = nullptr; - frames[0] = nullptr; - frames[1] = nullptr; - - // DV header ? - if ( Fich.getFI() == YSF_FI_HEADER ) - { - // get stream id - uint32 uiStreamId = IpToStreamId(Ip); - - // get header data - CYSFPayload ysfPayload; - if ( ysfPayload.processHeaderData((unsigned char *)&(Buffer.data()[35])) ) - { - // build DVHeader - char sz[YSF_CALLSIGN_LENGTH+1]; - ::memcpy(sz, &(Buffer.data()[14]), YSF_CALLSIGN_LENGTH); - sz[YSF_CALLSIGN_LENGTH] = 0; - CCallsign csMY = CCallsign((const char *)sz); - ::memcpy(sz, &(Buffer.data()[4]), YSF_CALLSIGN_LENGTH); - sz[YSF_CALLSIGN_LENGTH] = 0; - CCallsign rpt1 = CCallsign((const char *)sz); - rpt1.SetModule(YSF_MODULE_ID); - CCallsign rpt2 = m_ReflectorCallsign; - // as YSF protocol does not provide a module-tranlatable - // destid, set module to none and rely on OnDvHeaderPacketIn() - // to later fill it with proper value - rpt2.SetModule(' '); - - // and packet - *header = new CDvHeaderPacket(csMY, CCallsign("CQCQCQ"), rpt1, rpt2, uiStreamId, Fich.getFN()); - } - // and 2 DV Frames - { - uint8 uiAmbe[AMBE_SIZE]; - ::memset(uiAmbe, 0x00, sizeof(uiAmbe)); - frames[0] = new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 0, 0); - frames[1] = new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 1, 0); - } - - // check validity of packets - if ( ((*header) == nullptr) || !(*header)->IsValid() || - (frames[0] == nullptr) || !(frames[0]->IsValid()) || - (frames[1] == nullptr) || !(frames[1]->IsValid()) ) - - { - delete *header; - *header = nullptr; - delete frames[0]; - delete frames[1]; - frames[0] = nullptr; - frames[1] = nullptr; - } - else - { - valid = true; - } - - } - - // done - return valid; + bool valid = false; + *header = nullptr; + frames[0] = nullptr; + frames[1] = nullptr; + + // DV header ? + if ( Fich.getFI() == YSF_FI_HEADER ) + { + // get stream id + uint32 uiStreamId = IpToStreamId(Ip); + + // get header data + CYSFPayload ysfPayload; + if ( ysfPayload.processHeaderData((unsigned char *)&(Buffer.data()[35])) ) + { + // build DVHeader + char sz[YSF_CALLSIGN_LENGTH+1]; + ::memcpy(sz, &(Buffer.data()[14]), YSF_CALLSIGN_LENGTH); + sz[YSF_CALLSIGN_LENGTH] = 0; + CCallsign csMY = CCallsign((const char *)sz); + ::memcpy(sz, &(Buffer.data()[4]), YSF_CALLSIGN_LENGTH); + sz[YSF_CALLSIGN_LENGTH] = 0; + CCallsign rpt1 = CCallsign((const char *)sz); + rpt1.SetModule(YSF_MODULE_ID); + CCallsign rpt2 = m_ReflectorCallsign; + // as YSF protocol does not provide a module-tranlatable + // destid, set module to none and rely on OnDvHeaderPacketIn() + // to later fill it with proper value + rpt2.SetModule(' '); + + // and packet + *header = new CDvHeaderPacket(csMY, CCallsign("CQCQCQ"), rpt1, rpt2, uiStreamId, Fich.getFN()); + } + // and 2 DV Frames + { + uint8 uiAmbe[AMBE_SIZE]; + ::memset(uiAmbe, 0x00, sizeof(uiAmbe)); + frames[0] = new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 0, 0); + frames[1] = new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 1, 0); + } + + // check validity of packets + if ( ((*header) == nullptr) || !(*header)->IsValid() || + (frames[0] == nullptr) || !(frames[0]->IsValid()) || + (frames[1] == nullptr) || !(frames[1]->IsValid()) ) + + { + delete *header; + *header = nullptr; + delete frames[0]; + delete frames[1]; + frames[0] = nullptr; + frames[1] = nullptr; + } + else + { + valid = true; + } + + } + + // done + return valid; } bool CYsfProtocol::IsValidDvFramePacket(const CIp &Ip, const CYSFFICH &Fich, const CBuffer &Buffer, CDvFramePacket **frames) { - bool valid = false; - frames[0] = nullptr; - frames[1] = nullptr; - frames[2] = nullptr; - frames[3] = nullptr; - frames[4] = nullptr; - - // is it DV frame ? - if ( Fich.getFI() == YSF_FI_COMMUNICATIONS ) - { - // get stream id - uint32 uiStreamId = IpToStreamId(Ip); - - // get DV frames - uint8 ambe0[AMBEPLUS_SIZE]; - uint8 ambe1[AMBEPLUS_SIZE]; - uint8 ambe2[AMBEPLUS_SIZE]; - uint8 ambe3[AMBEPLUS_SIZE]; - uint8 ambe4[AMBEPLUS_SIZE]; - uint8 *ambes[5] = { ambe0, ambe1, ambe2, ambe3, ambe4 }; - CYsfUtils::DecodeVD2Vchs((unsigned char *)&(Buffer.data()[35]), ambes); - - // get DV frames - uint8 fid = Buffer.data()[34]; - frames[0] = new CDvFramePacket(ambe0, uiStreamId, Fich.getFN(), 0, fid); - frames[1] = new CDvFramePacket(ambe1, uiStreamId, Fich.getFN(), 1, fid); - frames[2] = new CDvFramePacket(ambe2, uiStreamId, Fich.getFN(), 2, fid); - frames[3] = new CDvFramePacket(ambe3, uiStreamId, Fich.getFN(), 3, fid); - frames[4] = new CDvFramePacket(ambe4, uiStreamId, Fich.getFN(), 4, fid); - - // check validity of packets - if ( (frames[0] == nullptr) || !(frames[0]->IsValid()) || - (frames[1] == nullptr) || !(frames[1]->IsValid()) || - (frames[2] == nullptr) || !(frames[2]->IsValid()) || - (frames[3] == nullptr) || !(frames[3]->IsValid()) || - (frames[4] == nullptr) || !(frames[4]->IsValid()) ) - { - delete frames[0]; - delete frames[1]; - delete frames[2]; - delete frames[3]; - delete frames[4]; - frames[0] = nullptr; - frames[1] = nullptr; - frames[2] = nullptr; - frames[3] = nullptr; - frames[4] = nullptr; - } - else - { - valid = true; - } - } - - // done - return valid; + bool valid = false; + frames[0] = nullptr; + frames[1] = nullptr; + frames[2] = nullptr; + frames[3] = nullptr; + frames[4] = nullptr; + + // is it DV frame ? + if ( Fich.getFI() == YSF_FI_COMMUNICATIONS ) + { + // get stream id + uint32 uiStreamId = IpToStreamId(Ip); + + // get DV frames + uint8 ambe0[AMBEPLUS_SIZE]; + uint8 ambe1[AMBEPLUS_SIZE]; + uint8 ambe2[AMBEPLUS_SIZE]; + uint8 ambe3[AMBEPLUS_SIZE]; + uint8 ambe4[AMBEPLUS_SIZE]; + uint8 *ambes[5] = { ambe0, ambe1, ambe2, ambe3, ambe4 }; + CYsfUtils::DecodeVD2Vchs((unsigned char *)&(Buffer.data()[35]), ambes); + + // get DV frames + uint8 fid = Buffer.data()[34]; + frames[0] = new CDvFramePacket(ambe0, uiStreamId, Fich.getFN(), 0, fid); + frames[1] = new CDvFramePacket(ambe1, uiStreamId, Fich.getFN(), 1, fid); + frames[2] = new CDvFramePacket(ambe2, uiStreamId, Fich.getFN(), 2, fid); + frames[3] = new CDvFramePacket(ambe3, uiStreamId, Fich.getFN(), 3, fid); + frames[4] = new CDvFramePacket(ambe4, uiStreamId, Fich.getFN(), 4, fid); + + // check validity of packets + if ( (frames[0] == nullptr) || !(frames[0]->IsValid()) || + (frames[1] == nullptr) || !(frames[1]->IsValid()) || + (frames[2] == nullptr) || !(frames[2]->IsValid()) || + (frames[3] == nullptr) || !(frames[3]->IsValid()) || + (frames[4] == nullptr) || !(frames[4]->IsValid()) ) + { + delete frames[0]; + delete frames[1]; + delete frames[2]; + delete frames[3]; + delete frames[4]; + frames[0] = nullptr; + frames[1] = nullptr; + frames[2] = nullptr; + frames[3] = nullptr; + frames[4] = nullptr; + } + else + { + valid = true; + } + } + + // done + return valid; } bool CYsfProtocol::IsValidDvLastFramePacket(const CIp &Ip, const CYSFFICH &Fich, const CBuffer &Buffer, CDvFramePacket **frames) { - bool valid = false; - frames[0] = nullptr; - frames[1] = nullptr; - - // DV header ? - if ( Fich.getFI() == YSF_FI_TERMINATOR ) - { - // get stream id - uint32 uiStreamId = IpToStreamId(Ip); - - // get DV frames - { - uint8 uiAmbe[AMBE_SIZE]; - ::memset(uiAmbe, 0x00, sizeof(uiAmbe)); - frames[0] = new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 0, 0); - frames[1] = new CDvLastFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 1, 0); - } - - // check validity of packets - if ( (frames[0] == nullptr) || !(frames[0]->IsValid()) || - (frames[1] == nullptr) || !(frames[1]->IsValid()) ) - - { - delete frames[0]; - delete frames[1]; - frames[0] = nullptr; - frames[1] = nullptr; - } - else - { - valid = true; - } - } - - // done - return valid; + bool valid = false; + frames[0] = nullptr; + frames[1] = nullptr; + + // DV header ? + if ( Fich.getFI() == YSF_FI_TERMINATOR ) + { + // get stream id + uint32 uiStreamId = IpToStreamId(Ip); + + // get DV frames + { + uint8 uiAmbe[AMBE_SIZE]; + ::memset(uiAmbe, 0x00, sizeof(uiAmbe)); + frames[0] = new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 0, 0); + frames[1] = new CDvLastFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 1, 0); + } + + // check validity of packets + if ( (frames[0] == nullptr) || !(frames[0]->IsValid()) || + (frames[1] == nullptr) || !(frames[1]->IsValid()) ) + + { + delete frames[0]; + delete frames[1]; + frames[0] = nullptr; + frames[1] = nullptr; + } + else + { + valid = true; + } + } + + // done + return valid; } //////////////////////////////////////////////////////////////////////////////////////// @@ -610,211 +610,211 @@ bool CYsfProtocol::IsValidDvLastFramePacket(const CIp &Ip, const CYSFFICH &Fich, void CYsfProtocol::EncodeConnectAckPacket(CBuffer *Buffer) const { - uint8 tag[] = { 'Y','S','F','P','R','E','F','L','E','C','T','O','R',0x20 }; + uint8 tag[] = { 'Y','S','F','P','R','E','F','L','E','C','T','O','R',0x20 }; - Buffer->Set(tag, sizeof(tag)); + Buffer->Set(tag, sizeof(tag)); } bool CYsfProtocol::EncodeDvHeaderPacket(const CDvHeaderPacket &Header, CBuffer *Buffer) const { - uint8 tag[] = { 'Y','S','F','D' }; - uint8 dest[] = { 'A','L','L',' ',' ',' ',' ',' ',' ',' ' }; - char sz[YSF_CALLSIGN_LENGTH]; - uint8 fichd[YSF_FICH_LENGTH_BYTES]; - - // tag - Buffer->Set(tag, sizeof(tag)); - // rpt1 - ::memset(sz, ' ', sizeof(sz)); - Header.GetRpt1Callsign().GetCallsignString(sz); - sz[::strlen(sz)] = ' '; - Buffer->Append((uint8 *)sz, YSF_CALLSIGN_LENGTH); - // my - ::memset(sz, ' ', sizeof(sz)); - Header.GetMyCallsign().GetCallsignString(sz); - sz[::strlen(sz)] = ' '; - Buffer->Append((uint8 *)sz, YSF_CALLSIGN_LENGTH); - // dest - Buffer->Append(dest, 10); - // net frame counter - Buffer->Append((uint8)0x00); - // FS - Buffer->Append((uint8 *)YSF_SYNC_BYTES, YSF_SYNC_LENGTH_BYTES); - // FICH - CYSFFICH fich; - fich.setFI(YSF_FI_HEADER); - fich.setCS(2U); - //fich.setFN(Header.GetYsfPacketId()); - fich.setFN(0U); - fich.setFT(7U); - fich.setDev(0U); - fich.setMR(YSF_MR_BUSY); - fich.setDT(YSF_DT_VD_MODE2); - fich.setSQL(0U); - fich.setSQ(0U); - fich.encode(fichd); - Buffer->Append(fichd, YSF_FICH_LENGTH_BYTES); - // payload - unsigned char csd1[20U], csd2[20U]; - ::memset(csd1, '*', YSF_CALLSIGN_LENGTH); - ::memset(csd1 + YSF_CALLSIGN_LENGTH, ' ', YSF_CALLSIGN_LENGTH); - Header.GetMyCallsign().GetCallsignString(sz); - ::memcpy(csd1 + YSF_CALLSIGN_LENGTH, sz, ::strlen(sz)); - ::memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH); - CYSFPayload payload; - uint8 temp[120]; - payload.writeHeader(temp, csd1, csd2); - Buffer->Append(temp+30, 120-30); - - // done - return true; + uint8 tag[] = { 'Y','S','F','D' }; + uint8 dest[] = { 'A','L','L',' ',' ',' ',' ',' ',' ',' ' }; + char sz[YSF_CALLSIGN_LENGTH]; + uint8 fichd[YSF_FICH_LENGTH_BYTES]; + + // tag + Buffer->Set(tag, sizeof(tag)); + // rpt1 + ::memset(sz, ' ', sizeof(sz)); + Header.GetRpt1Callsign().GetCallsignString(sz); + sz[::strlen(sz)] = ' '; + Buffer->Append((uint8 *)sz, YSF_CALLSIGN_LENGTH); + // my + ::memset(sz, ' ', sizeof(sz)); + Header.GetMyCallsign().GetCallsignString(sz); + sz[::strlen(sz)] = ' '; + Buffer->Append((uint8 *)sz, YSF_CALLSIGN_LENGTH); + // dest + Buffer->Append(dest, 10); + // net frame counter + Buffer->Append((uint8)0x00); + // FS + Buffer->Append((uint8 *)YSF_SYNC_BYTES, YSF_SYNC_LENGTH_BYTES); + // FICH + CYSFFICH fich; + fich.setFI(YSF_FI_HEADER); + fich.setCS(2U); + //fich.setFN(Header.GetYsfPacketId()); + fich.setFN(0U); + fich.setFT(7U); + fich.setDev(0U); + fich.setMR(YSF_MR_BUSY); + fich.setDT(YSF_DT_VD_MODE2); + fich.setSQL(0U); + fich.setSQ(0U); + fich.encode(fichd); + Buffer->Append(fichd, YSF_FICH_LENGTH_BYTES); + // payload + unsigned char csd1[20U], csd2[20U]; + ::memset(csd1, '*', YSF_CALLSIGN_LENGTH); + ::memset(csd1 + YSF_CALLSIGN_LENGTH, ' ', YSF_CALLSIGN_LENGTH); + Header.GetMyCallsign().GetCallsignString(sz); + ::memcpy(csd1 + YSF_CALLSIGN_LENGTH, sz, ::strlen(sz)); + ::memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH); + CYSFPayload payload; + uint8 temp[120]; + payload.writeHeader(temp, csd1, csd2); + Buffer->Append(temp+30, 120-30); + + // done + return true; } bool CYsfProtocol::EncodeDvPacket(const CDvHeaderPacket &Header, const CDvFramePacket *DvFrames, CBuffer *Buffer) const { - uint8 tag[] = { 'Y','S','F','D' }; - uint8 dest[] = { 'A','L','L',' ',' ',' ',' ',' ',' ',' ' }; - uint8 gps[] = { 0x52,0x22,0x61,0x5F,0x27,0x03,0x5E,0x20,0x20,0x20 }; - char sz[YSF_CALLSIGN_LENGTH]; - uint8 fichd[YSF_FICH_LENGTH_BYTES]; - - // tag - Buffer->Set(tag, sizeof(tag)); - // rpt1 - ::memset(sz, ' ', sizeof(sz)); - Header.GetRpt1Callsign().GetCallsignString(sz); - sz[::strlen(sz)] = ' '; - Buffer->Append((uint8 *)sz, YSF_CALLSIGN_LENGTH); - // my - ::memset(sz, ' ', sizeof(sz)); - Header.GetMyCallsign().GetCallsignString(sz); - sz[::strlen(sz)] = ' '; - Buffer->Append((uint8 *)sz, YSF_CALLSIGN_LENGTH); - // dest - Buffer->Append(dest, 10); - // net frame counter - Buffer->Append(DvFrames[0].GetYsfPacketFrameId()); - // FS - Buffer->Append((uint8 *)YSF_SYNC_BYTES, YSF_SYNC_LENGTH_BYTES); - // FICH - CYSFFICH fich; - fich.setFI(YSF_FI_COMMUNICATIONS); - fich.setCS(2U); - fich.setFN(DvFrames[0].GetYsfPacketId()); - fich.setFT(6U); - fich.setDev(0U); - fich.setMR(YSF_MR_BUSY); - fich.setDT(YSF_DT_VD_MODE2); - fich.setSQL(0U); - fich.setSQ(0U); - fich.encode(fichd); - Buffer->Append(fichd, YSF_FICH_LENGTH_BYTES); - // payload - CYSFPayload payload; - uint8 temp[120]; - ::memset(temp, 0x00, sizeof(temp)); - // DV - for ( int i = 0; i < 5; i++ ) - { - CYsfUtils::EncodeVD2Vch((unsigned char *)DvFrames[i].GetAmbePlus(), temp+35+(18*i)); - } - // data - switch (DvFrames[0].GetYsfPacketId()) - { - case 0: - // Dest - payload.writeVDMode2Data(temp, (const unsigned char*)"**********"); - break; - case 1: - // Src - ::memset(sz, ' ', sizeof(sz)); - Header.GetMyCallsign().GetCallsignString(sz); - sz[::strlen(sz)] = ' '; - payload.writeVDMode2Data(temp, (const unsigned char*)sz); - break; - case 2: - // Down - ::memset(sz, ' ', sizeof(sz)); - Header.GetRpt1Callsign().GetCallsignString(sz); - sz[::strlen(sz)] = ' '; - payload.writeVDMode2Data(temp, (const unsigned char*)sz); - break; - case 5: - // Rem3+4 - // we need to provide a fake radioid for radios - // to display src callsign - payload.writeVDMode2Data(temp, (const unsigned char*)" G0gBJ"); - break; - case 6: - // DT1 - // we need to issue a fake gps string with proper terminator - // and crc for radios to display src callsign - payload.writeVDMode2Data(temp, gps); - break; - default: - payload.writeVDMode2Data(temp, (const unsigned char*)" "); - break; - - } - Buffer->Append(temp+30, 120-30); - - // done - return true; + uint8 tag[] = { 'Y','S','F','D' }; + uint8 dest[] = { 'A','L','L',' ',' ',' ',' ',' ',' ',' ' }; + uint8 gps[] = { 0x52,0x22,0x61,0x5F,0x27,0x03,0x5E,0x20,0x20,0x20 }; + char sz[YSF_CALLSIGN_LENGTH]; + uint8 fichd[YSF_FICH_LENGTH_BYTES]; + + // tag + Buffer->Set(tag, sizeof(tag)); + // rpt1 + ::memset(sz, ' ', sizeof(sz)); + Header.GetRpt1Callsign().GetCallsignString(sz); + sz[::strlen(sz)] = ' '; + Buffer->Append((uint8 *)sz, YSF_CALLSIGN_LENGTH); + // my + ::memset(sz, ' ', sizeof(sz)); + Header.GetMyCallsign().GetCallsignString(sz); + sz[::strlen(sz)] = ' '; + Buffer->Append((uint8 *)sz, YSF_CALLSIGN_LENGTH); + // dest + Buffer->Append(dest, 10); + // net frame counter + Buffer->Append(DvFrames[0].GetYsfPacketFrameId()); + // FS + Buffer->Append((uint8 *)YSF_SYNC_BYTES, YSF_SYNC_LENGTH_BYTES); + // FICH + CYSFFICH fich; + fich.setFI(YSF_FI_COMMUNICATIONS); + fich.setCS(2U); + fich.setFN(DvFrames[0].GetYsfPacketId()); + fich.setFT(6U); + fich.setDev(0U); + fich.setMR(YSF_MR_BUSY); + fich.setDT(YSF_DT_VD_MODE2); + fich.setSQL(0U); + fich.setSQ(0U); + fich.encode(fichd); + Buffer->Append(fichd, YSF_FICH_LENGTH_BYTES); + // payload + CYSFPayload payload; + uint8 temp[120]; + ::memset(temp, 0x00, sizeof(temp)); + // DV + for ( int i = 0; i < 5; i++ ) + { + CYsfUtils::EncodeVD2Vch((unsigned char *)DvFrames[i].GetAmbePlus(), temp+35+(18*i)); + } + // data + switch (DvFrames[0].GetYsfPacketId()) + { + case 0: + // Dest + payload.writeVDMode2Data(temp, (const unsigned char*)"**********"); + break; + case 1: + // Src + ::memset(sz, ' ', sizeof(sz)); + Header.GetMyCallsign().GetCallsignString(sz); + sz[::strlen(sz)] = ' '; + payload.writeVDMode2Data(temp, (const unsigned char*)sz); + break; + case 2: + // Down + ::memset(sz, ' ', sizeof(sz)); + Header.GetRpt1Callsign().GetCallsignString(sz); + sz[::strlen(sz)] = ' '; + payload.writeVDMode2Data(temp, (const unsigned char*)sz); + break; + case 5: + // Rem3+4 + // we need to provide a fake radioid for radios + // to display src callsign + payload.writeVDMode2Data(temp, (const unsigned char*)" G0gBJ"); + break; + case 6: + // DT1 + // we need to issue a fake gps string with proper terminator + // and crc for radios to display src callsign + payload.writeVDMode2Data(temp, gps); + break; + default: + payload.writeVDMode2Data(temp, (const unsigned char*)" "); + break; + + } + Buffer->Append(temp+30, 120-30); + + // done + return true; } bool CYsfProtocol::EncodeDvLastPacket(const CDvHeaderPacket &Header, CBuffer *Buffer) const { - uint8 tag[] = { 'Y','S','F','D' }; - uint8 dest[] = { 'A','L','L',' ',' ',' ',' ',' ',' ',' ' }; - char sz[YSF_CALLSIGN_LENGTH]; - uint8 fichd[YSF_FICH_LENGTH_BYTES]; - - // tag - Buffer->Set(tag, sizeof(tag)); - // rpt1 - ::memset(sz, ' ', sizeof(sz)); - Header.GetRpt1Callsign().GetCallsignString(sz); - sz[::strlen(sz)] = ' '; - Buffer->Append((uint8 *)sz, YSF_CALLSIGN_LENGTH); - // my - ::memset(sz, ' ', sizeof(sz)); - Header.GetMyCallsign().GetCallsignString(sz); - sz[::strlen(sz)] = ' '; - Buffer->Append((uint8 *)sz, YSF_CALLSIGN_LENGTH); - // dest - Buffer->Append(dest, 10); - // net frame counter - Buffer->Append((uint8)0x00); - // FS - Buffer->Append((uint8 *)YSF_SYNC_BYTES, YSF_SYNC_LENGTH_BYTES); - // FICH - CYSFFICH fich; - fich.setFI(YSF_FI_TERMINATOR); - fich.setCS(2U); - //fich.setFN(Header.GetYsfPacketId()); - fich.setFN(0U); - fich.setFT(7U); - fich.setDev(0U); - fich.setMR(YSF_MR_BUSY); - fich.setDT(YSF_DT_VD_MODE2); - fich.setSQL(0U); - fich.setSQ(0U); - fich.encode(fichd); - Buffer->Append(fichd, YSF_FICH_LENGTH_BYTES); - // payload - unsigned char csd1[20U], csd2[20U]; - ::memset(csd1, '*', YSF_CALLSIGN_LENGTH); - ::memset(csd1 + YSF_CALLSIGN_LENGTH, ' ', YSF_CALLSIGN_LENGTH); - Header.GetMyCallsign().GetCallsignString(sz); - ::memcpy(csd1 + YSF_CALLSIGN_LENGTH, sz, ::strlen(sz)); - ::memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH); - CYSFPayload payload; - uint8 temp[120]; - payload.writeHeader(temp, csd1, csd2); - Buffer->Append(temp+30, 120-30); - - // done - return true; + uint8 tag[] = { 'Y','S','F','D' }; + uint8 dest[] = { 'A','L','L',' ',' ',' ',' ',' ',' ',' ' }; + char sz[YSF_CALLSIGN_LENGTH]; + uint8 fichd[YSF_FICH_LENGTH_BYTES]; + + // tag + Buffer->Set(tag, sizeof(tag)); + // rpt1 + ::memset(sz, ' ', sizeof(sz)); + Header.GetRpt1Callsign().GetCallsignString(sz); + sz[::strlen(sz)] = ' '; + Buffer->Append((uint8 *)sz, YSF_CALLSIGN_LENGTH); + // my + ::memset(sz, ' ', sizeof(sz)); + Header.GetMyCallsign().GetCallsignString(sz); + sz[::strlen(sz)] = ' '; + Buffer->Append((uint8 *)sz, YSF_CALLSIGN_LENGTH); + // dest + Buffer->Append(dest, 10); + // net frame counter + Buffer->Append((uint8)0x00); + // FS + Buffer->Append((uint8 *)YSF_SYNC_BYTES, YSF_SYNC_LENGTH_BYTES); + // FICH + CYSFFICH fich; + fich.setFI(YSF_FI_TERMINATOR); + fich.setCS(2U); + //fich.setFN(Header.GetYsfPacketId()); + fich.setFN(0U); + fich.setFT(7U); + fich.setDev(0U); + fich.setMR(YSF_MR_BUSY); + fich.setDT(YSF_DT_VD_MODE2); + fich.setSQL(0U); + fich.setSQ(0U); + fich.encode(fichd); + Buffer->Append(fichd, YSF_FICH_LENGTH_BYTES); + // payload + unsigned char csd1[20U], csd2[20U]; + ::memset(csd1, '*', YSF_CALLSIGN_LENGTH); + ::memset(csd1 + YSF_CALLSIGN_LENGTH, ' ', YSF_CALLSIGN_LENGTH); + Header.GetMyCallsign().GetCallsignString(sz); + ::memcpy(csd1 + YSF_CALLSIGN_LENGTH, sz, ::strlen(sz)); + ::memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH); + CYSFPayload payload; + uint8 temp[120]; + payload.writeHeader(temp, csd1, csd2); + Buffer->Append(temp+30, 120-30); + + // done + return true; } //////////////////////////////////////////////////////////////////////////////////////// @@ -822,172 +822,172 @@ bool CYsfProtocol::EncodeDvLastPacket(const CDvHeaderPacket &Header, CBuffer *Bu bool CYsfProtocol::IsValidwirexPacket(const CBuffer &Buffer, CYSFFICH *Fich, CCallsign *Callsign, int *Cmd, int *Arg) { - uint8 tag[] = { 'Y','S','F','D' }; - uint8 DX_REQ[] = {0x5DU, 0x71U, 0x5FU}; - uint8 CONN_REQ[] = {0x5DU, 0x23U, 0x5FU}; - uint8 DISC_REQ[] = {0x5DU, 0x2AU, 0x5FU}; - uint8 ALL_REQ[] = {0x5DU, 0x66U, 0x5FU}; - uint8 command[300]; - CYSFPayload payload; - bool valid = false; - - if ( (Buffer.size() == 155) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - // decode YSH fich - if ( Fich->decode(&(Buffer.data()[40])) ) - { - //std::cout << (int)Fich->getDT() << "," - // << (int)Fich->getFI() << "," - // << (int)Fich->getFN() << "," - // << (int)Fich->getFT() - // << std::endl; - valid = (Fich->getDT() == YSF_DT_DATA_FR_MODE); - valid &= (Fich->getFI() == YSF_FI_COMMUNICATIONS); - if ( valid ) - { - // get callsign - Callsign->SetCallsign(&(Buffer.data()[4]), CALLSIGN_LEN, false); - Callsign->SetModule(YSF_MODULE_ID); - // decode payload - if ( Fich->getFN() == 0U ) - { - valid = false; - } - else if ( Fich->getFN() == 1U ) - { - valid &= payload.readDataFRModeData2(&(Buffer.data()[35]), command + 0U); - } - else - { - valid &= payload.readDataFRModeData1(&(Buffer.data()[35]), command + (Fich->getFN() - 1U) * 20U + 0U); - if ( valid ) - { - valid &= payload.readDataFRModeData2(&(Buffer.data()[35]), command + (Fich->getFN() - 1U) * 20U + 20U); - } - } - // check crc if end found - if ( Fich->getFN() == Fich->getFT() ) - { - valid = false; - // Find the end marker - for (unsigned int i = Fich->getFN() * 20U; i > 0U; i--) - { - if (command[i] == 0x03U) - { - unsigned char crc = CCRC::addCRC(command, i + 1U); - if (crc == command[i + 1U]) - valid = true; - break; - } - } - } - // and crack the command - if ( valid ) - { - // get argument - char buffer[4U]; - ::memcpy(buffer, command + 5U + 2U, 3U); - buffer[3U] = 0x00U; - *Arg = ::atoi(buffer); - // and decode command - if (::memcmp(command + 1U, DX_REQ, 3U) == 0) - { - *Cmd = WIRESX_CMD_DX_REQ; - *Arg = 0; - } - else if (::memcmp(command + 1U, ALL_REQ, 3U) == 0) - { - // argument is start index of list - if ( *Arg > 0 ) - (*Arg)--; - // check if all or search - if ( ::memcmp(command + 5U, "01", 2) == 0 ) - { - *Cmd = WIRESX_CMD_ALL_REQ; - } - else if ( ::memcmp(command + 5U, "11", 2) == 0 ) - { - *Cmd = WIRESX_CMD_SEARCH_REQ; - } - } - else if (::memcmp(command + 1U, CONN_REQ, 3U) == 0) - { - *Cmd = WIRESX_CMD_CONN_REQ; - } - else if (::memcmp(command + 1U, DISC_REQ, 3U) == 0) - { - *Cmd = WIRESX_CMD_DISC_REQ; - *Arg = 0; - } - else - { - std::cout << "Wires-X unknown command" << std::endl; - *Cmd = WIRESX_CMD_UNKNOWN; - *Arg = 0; - valid = false; - } - } - } - } - } - return valid; + uint8 tag[] = { 'Y','S','F','D' }; + uint8 DX_REQ[] = {0x5DU, 0x71U, 0x5FU}; + uint8 CONN_REQ[] = {0x5DU, 0x23U, 0x5FU}; + uint8 DISC_REQ[] = {0x5DU, 0x2AU, 0x5FU}; + uint8 ALL_REQ[] = {0x5DU, 0x66U, 0x5FU}; + uint8 command[300]; + CYSFPayload payload; + bool valid = false; + + if ( (Buffer.size() == 155) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + // decode YSH fich + if ( Fich->decode(&(Buffer.data()[40])) ) + { + //std::cout << (int)Fich->getDT() << "," + // << (int)Fich->getFI() << "," + // << (int)Fich->getFN() << "," + // << (int)Fich->getFT() + // << std::endl; + valid = (Fich->getDT() == YSF_DT_DATA_FR_MODE); + valid &= (Fich->getFI() == YSF_FI_COMMUNICATIONS); + if ( valid ) + { + // get callsign + Callsign->SetCallsign(&(Buffer.data()[4]), CALLSIGN_LEN, false); + Callsign->SetModule(YSF_MODULE_ID); + // decode payload + if ( Fich->getFN() == 0U ) + { + valid = false; + } + else if ( Fich->getFN() == 1U ) + { + valid &= payload.readDataFRModeData2(&(Buffer.data()[35]), command + 0U); + } + else + { + valid &= payload.readDataFRModeData1(&(Buffer.data()[35]), command + (Fich->getFN() - 1U) * 20U + 0U); + if ( valid ) + { + valid &= payload.readDataFRModeData2(&(Buffer.data()[35]), command + (Fich->getFN() - 1U) * 20U + 20U); + } + } + // check crc if end found + if ( Fich->getFN() == Fich->getFT() ) + { + valid = false; + // Find the end marker + for (unsigned int i = Fich->getFN() * 20U; i > 0U; i--) + { + if (command[i] == 0x03U) + { + unsigned char crc = CCRC::addCRC(command, i + 1U); + if (crc == command[i + 1U]) + valid = true; + break; + } + } + } + // and crack the command + if ( valid ) + { + // get argument + char buffer[4U]; + ::memcpy(buffer, command + 5U + 2U, 3U); + buffer[3U] = 0x00U; + *Arg = ::atoi(buffer); + // and decode command + if (::memcmp(command + 1U, DX_REQ, 3U) == 0) + { + *Cmd = WIRESX_CMD_DX_REQ; + *Arg = 0; + } + else if (::memcmp(command + 1U, ALL_REQ, 3U) == 0) + { + // argument is start index of list + if ( *Arg > 0 ) + (*Arg)--; + // check if all or search + if ( ::memcmp(command + 5U, "01", 2) == 0 ) + { + *Cmd = WIRESX_CMD_ALL_REQ; + } + else if ( ::memcmp(command + 5U, "11", 2) == 0 ) + { + *Cmd = WIRESX_CMD_SEARCH_REQ; + } + } + else if (::memcmp(command + 1U, CONN_REQ, 3U) == 0) + { + *Cmd = WIRESX_CMD_CONN_REQ; + } + else if (::memcmp(command + 1U, DISC_REQ, 3U) == 0) + { + *Cmd = WIRESX_CMD_DISC_REQ; + *Arg = 0; + } + else + { + std::cout << "Wires-X unknown command" << std::endl; + *Cmd = WIRESX_CMD_UNKNOWN; + *Arg = 0; + valid = false; + } + } + } + } + } + return valid; } // server status packet decoding helpers bool CYsfProtocol::IsValidServerStatusPacket(const CBuffer &Buffer) const { - uint8 tag[] = { 'Y','S','F','S' }; + uint8 tag[] = { 'Y','S','F','S' }; - return ( (Buffer.size() >= 4) && (Buffer.Compare(tag, sizeof(tag)) == 0) ); + return ( (Buffer.size() >= 4) && (Buffer.Compare(tag, sizeof(tag)) == 0) ); } // server status packet encoding helpers bool CYsfProtocol::EncodeServerStatusPacket(CBuffer *Buffer) const { - uint8 tag[] = { 'Y','S','F','S' }; - uint8 description[] = { 'X','L','X',' ','r','e','f','l','e','c','t','o','r',' ' }; - uint8 callsign[16]; - - // tag - Buffer->Set(tag, sizeof(tag)); - // hash - ::memset(callsign, ' ', sizeof(callsign)); - g_Reflector.GetCallsign().GetCallsign(callsign); - char sz[16]; - ::sprintf(sz, "%05u", CalcHash(callsign, 16) % 100000U); - Buffer->Append((uint8 *)sz, 5); - // name - Buffer->Append(callsign, 16); - // desscription - Buffer->Append(description, 14); - // connected clients - CClients *clients = g_Reflector.GetClients(); - int count = MIN(999, clients->GetSize()); - g_Reflector.ReleaseClients(); - ::sprintf(sz, "%03u", count); - Buffer->Append((uint8 *)sz, 3); - - // done - return true; + uint8 tag[] = { 'Y','S','F','S' }; + uint8 description[] = { 'X','L','X',' ','r','e','f','l','e','c','t','o','r',' ' }; + uint8 callsign[16]; + + // tag + Buffer->Set(tag, sizeof(tag)); + // hash + ::memset(callsign, ' ', sizeof(callsign)); + g_Reflector.GetCallsign().GetCallsign(callsign); + char sz[16]; + ::sprintf(sz, "%05u", CalcHash(callsign, 16) % 100000U); + Buffer->Append((uint8 *)sz, 5); + // name + Buffer->Append(callsign, 16); + // desscription + Buffer->Append(description, 14); + // connected clients + CClients *clients = g_Reflector.GetClients(); + int count = MIN(999, clients->GetSize()); + g_Reflector.ReleaseClients(); + ::sprintf(sz, "%03u", count); + Buffer->Append((uint8 *)sz, 3); + + // done + return true; } uint32 CYsfProtocol::CalcHash(const uint8 *buffer, int len) const { - uint32 hash = 0U; - - for ( int i = 0; i < len; i++) - { - hash += buffer[i]; - hash += (hash << 10); - hash ^= (hash >> 6); - } - hash += (hash << 3); - hash ^= (hash >> 11); - hash += (hash << 15); - - return hash; + uint32 hash = 0U; + + for ( int i = 0; i < len; i++) + { + hash += buffer[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + + return hash; } @@ -998,7 +998,7 @@ uint32 CYsfProtocol::CalcHash(const uint8 *buffer, int len) const // uiStreamId helpers uint32 CYsfProtocol::IpToStreamId(const CIp &ip) const { - return ip.GetAddr() ^ (uint32)(MAKEDWORD(ip.GetPort(), ip.GetPort())); + return ip.GetAddr() ^ (uint32)(MAKEDWORD(ip.GetPort(), ip.GetPort())); } //////////////////////////////////////////////////////////////////////////////////////// @@ -1007,124 +1007,124 @@ uint32 CYsfProtocol::IpToStreamId(const CIp &ip) const #ifdef DEBUG_DUMPFILE bool CYsfProtocol::DebugTestDecodePacket(const CBuffer &Buffer) { - uint8 tag[] = { 'Y','S','F','D' }; - static uint8 command[4098]; - static int len; - CYSFFICH Fich; - CYSFPayload payload; - CBuffer dump; - bool valid = false; - - if ( (Buffer.size() == 155) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) - { - // decode YSH fich - if ( Fich.decode(&(Buffer.data()[40])) ) - { - std::cout << (int)Fich.getDT() << "," - << (int)Fich.getFI() << "," - << (int)Fich.getBN() << "," - << (int)Fich.getBT() << "," - << (int)Fich.getFN() << "," - << (int)Fich.getFT() << " : "; - - switch ( Fich.getFI() ) - { - case YSF_FI_HEADER: - len = 0; - ::memset(command, 0x00, sizeof(command)); - std::cout << "Header" << std::endl; - break; - case YSF_FI_TERMINATOR: - std::cout << "Trailer" << std::endl; - std::cout << "length of payload : " << len << std::endl; - dump.Set(command, len); - dump.DebugDump(g_Reflector.m_DebugFile); - dump.DebugDumpAscii(g_Reflector.m_DebugFile); - break; - case YSF_FI_COMMUNICATIONS: - if ( Fich.getDT() == YSF_DT_DATA_FR_MODE ) - { - valid = payload.readDataFRModeData1(&(Buffer.data()[35]), command + len); - len += 20; - valid &= payload.readDataFRModeData2(&(Buffer.data()[35]), command + len); - len += 20; - std::cout << "decoded ok" << std::endl; - } - break; - } - } - else - { - std::cout << "invalid fich in packet" << std::endl; - } - } - else - { - std::cout << "invalid size packet" << std::endl; - } - return valid; + uint8 tag[] = { 'Y','S','F','D' }; + static uint8 command[4098]; + static int len; + CYSFFICH Fich; + CYSFPayload payload; + CBuffer dump; + bool valid = false; + + if ( (Buffer.size() == 155) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + // decode YSH fich + if ( Fich.decode(&(Buffer.data()[40])) ) + { + std::cout << (int)Fich.getDT() << "," + << (int)Fich.getFI() << "," + << (int)Fich.getBN() << "," + << (int)Fich.getBT() << "," + << (int)Fich.getFN() << "," + << (int)Fich.getFT() << " : "; + + switch ( Fich.getFI() ) + { + case YSF_FI_HEADER: + len = 0; + ::memset(command, 0x00, sizeof(command)); + std::cout << "Header" << std::endl; + break; + case YSF_FI_TERMINATOR: + std::cout << "Trailer" << std::endl; + std::cout << "length of payload : " << len << std::endl; + dump.Set(command, len); + dump.DebugDump(g_Reflector.m_DebugFile); + dump.DebugDumpAscii(g_Reflector.m_DebugFile); + break; + case YSF_FI_COMMUNICATIONS: + if ( Fich.getDT() == YSF_DT_DATA_FR_MODE ) + { + valid = payload.readDataFRModeData1(&(Buffer.data()[35]), command + len); + len += 20; + valid &= payload.readDataFRModeData2(&(Buffer.data()[35]), command + len); + len += 20; + std::cout << "decoded ok" << std::endl; + } + break; + } + } + else + { + std::cout << "invalid fich in packet" << std::endl; + } + } + else + { + std::cout << "invalid size packet" << std::endl; + } + return valid; } #endif bool CYsfProtocol::DebugDumpHeaderPacket(const CBuffer &Buffer) { - bool ok; - CYSFFICH fich; - CYSFPayload payload; - uint8 data[200]; + bool ok; + CYSFFICH fich; + CYSFPayload payload; + uint8 data[200]; - :: memset(data, 0, sizeof(data)); + :: memset(data, 0, sizeof(data)); - ok = IsValidDvPacket(Buffer, &fich); - if ( ok && (fich.getFI() == YSF_FI_HEADER) ) - { - ok &= payload.processHeaderData((unsigned char *)&(Buffer.data()[35])); - } + ok = IsValidDvPacket(Buffer, &fich); + if ( ok && (fich.getFI() == YSF_FI_HEADER) ) + { + ok &= payload.processHeaderData((unsigned char *)&(Buffer.data()[35])); + } - std::cout << "HD-" <<(ok ? "ok " : "xx ") << "src: " << payload.getSource() << "dest: " << payload.getDest() << std::endl; + std::cout << "HD-" <<(ok ? "ok " : "xx ") << "src: " << payload.getSource() << "dest: " << payload.getDest() << std::endl; - return ok; + return ok; } bool CYsfProtocol::DebugDumpDvPacket(const CBuffer &Buffer) { - bool ok; - CYSFFICH fich; - CYSFPayload payload; - uint8 data[200]; + bool ok; + CYSFFICH fich; + CYSFPayload payload; + uint8 data[200]; - :: memset(data, 0, sizeof(data)); + :: memset(data, 0, sizeof(data)); - ok = IsValidDvPacket(Buffer, &fich); - if ( ok && (fich.getFI() == YSF_FI_COMMUNICATIONS) ) - { - ok &= payload.readVDMode2Data(&(Buffer.data()[35]), data); - } + ok = IsValidDvPacket(Buffer, &fich); + if ( ok && (fich.getFI() == YSF_FI_COMMUNICATIONS) ) + { + ok &= payload.readVDMode2Data(&(Buffer.data()[35]), data); + } - std::cout << "DV-" <<(ok ? "ok " : "xx ") << "FN:" << (int)fich.getFN() << " payload: " << (char *)data << std::endl; + std::cout << "DV-" <<(ok ? "ok " : "xx ") << "FN:" << (int)fich.getFN() << " payload: " << (char *)data << std::endl; - return ok; + return ok; } bool CYsfProtocol::DebugDumpLastDvPacket(const CBuffer &Buffer) { - bool ok; - CYSFFICH fich; - CYSFPayload payload; - uint8 data[200]; + bool ok; + CYSFFICH fich; + CYSFPayload payload; + uint8 data[200]; - :: memset(data, 0, sizeof(data)); + :: memset(data, 0, sizeof(data)); - ok = IsValidDvPacket(Buffer, &fich); - if ( ok && (fich.getFI() == YSF_FI_TERMINATOR) ) - { - ok &= payload.processHeaderData((unsigned char *)&(Buffer.data()[35])); - } + ok = IsValidDvPacket(Buffer, &fich); + if ( ok && (fich.getFI() == YSF_FI_TERMINATOR) ) + { + ok &= payload.processHeaderData((unsigned char *)&(Buffer.data()[35])); + } - std::cout << "TC-" <<(ok ? "ok " : "xx ") << "src: " << payload.getSource() << "dest: " << payload.getDest() << std::endl; + std::cout << "TC-" <<(ok ? "ok " : "xx ") << "src: " << payload.getSource() << "dest: " << payload.getDest() << std::endl; - return ok; + return ok; } diff --git a/src/cysfprotocol.h b/src/cysfprotocol.h index ca2a4cf..459c060 100644 --- a/src/cysfprotocol.h +++ b/src/cysfprotocol.h @@ -58,86 +58,86 @@ class CYsfStreamCacheItem { public: - CYsfStreamCacheItem() {} - ~CYsfStreamCacheItem() {} + CYsfStreamCacheItem() {} + ~CYsfStreamCacheItem() {} - CDvHeaderPacket m_dvHeader; - CDvFramePacket m_dvFrames[5]; + CDvHeaderPacket m_dvHeader; + CDvFramePacket m_dvFrames[5]; - //uint8 m_uiSeqId; + //uint8 m_uiSeqId; }; class CYsfProtocol : public CProtocol { public: - // constructor - CYsfProtocol(); + // constructor + CYsfProtocol(); - // destructor - ~CYsfProtocol() {} + // destructor + ~CYsfProtocol() {} - // initialization - bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); - void Close(void); + // initialization + bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); + void Close(void); - // task - void Task(void); + // task + void Task(void); protected: - // queue helper - void HandleQueue(void); - - // keepalive helpers - void HandleKeepalives(void); - - // stream helpers - bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); - - // DV packet decoding helpers - bool IsValidConnectPacket(const CBuffer &, CCallsign *); - //bool IsValidDisconnectPacket(const CBuffer &, CCallsign *); - bool IsValidDvPacket(const CBuffer &, CYSFFICH *); - bool IsValidDvHeaderPacket(const CIp &, const CYSFFICH &, const CBuffer &, CDvHeaderPacket **, CDvFramePacket **); - bool IsValidDvFramePacket(const CIp &, const CYSFFICH &, const CBuffer &, CDvFramePacket **); - bool IsValidDvLastFramePacket(const CIp &, const CYSFFICH &, const CBuffer &, CDvFramePacket **); - - // DV packet encoding helpers - void EncodeConnectAckPacket(CBuffer *) const; - //void EncodeConnectNackPacket(const CCallsign &, char, CBuffer *); - //void EncodeDisconnectPacket(CBuffer *, std::shared_ptr); - bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; - bool EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket *, CBuffer *) const; - bool EncodeDvLastPacket(const CDvHeaderPacket &, CBuffer *) const; - - // Wires-X packet decoding helpers - bool IsValidwirexPacket(const CBuffer &, CYSFFICH *, CCallsign *, int *, int*); - - // server status packet decoding helpers - bool IsValidServerStatusPacket(const CBuffer &) const; - uint32 CalcHash(const uint8 *, int) const; - - // server status packet encoding helpers - bool EncodeServerStatusPacket(CBuffer *) const; - - // uiStreamId helpers - uint32 IpToStreamId(const CIp &) const; - - // debug - bool DebugTestDecodePacket(const CBuffer &); - bool DebugDumpHeaderPacket(const CBuffer &); - bool DebugDumpDvPacket(const CBuffer &); - bool DebugDumpLastDvPacket(const CBuffer &); + // queue helper + void HandleQueue(void); + + // keepalive helpers + void HandleKeepalives(void); + + // stream helpers + bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); + + // DV packet decoding helpers + bool IsValidConnectPacket(const CBuffer &, CCallsign *); + //bool IsValidDisconnectPacket(const CBuffer &, CCallsign *); + bool IsValidDvPacket(const CBuffer &, CYSFFICH *); + bool IsValidDvHeaderPacket(const CIp &, const CYSFFICH &, const CBuffer &, CDvHeaderPacket **, CDvFramePacket **); + bool IsValidDvFramePacket(const CIp &, const CYSFFICH &, const CBuffer &, CDvFramePacket **); + bool IsValidDvLastFramePacket(const CIp &, const CYSFFICH &, const CBuffer &, CDvFramePacket **); + + // DV packet encoding helpers + void EncodeConnectAckPacket(CBuffer *) const; + //void EncodeConnectNackPacket(const CCallsign &, char, CBuffer *); + //void EncodeDisconnectPacket(CBuffer *, std::shared_ptr); + bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; + bool EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket *, CBuffer *) const; + bool EncodeDvLastPacket(const CDvHeaderPacket &, CBuffer *) const; + + // Wires-X packet decoding helpers + bool IsValidwirexPacket(const CBuffer &, CYSFFICH *, CCallsign *, int *, int*); + + // server status packet decoding helpers + bool IsValidServerStatusPacket(const CBuffer &) const; + uint32 CalcHash(const uint8 *, int) const; + + // server status packet encoding helpers + bool EncodeServerStatusPacket(CBuffer *) const; + + // uiStreamId helpers + uint32 IpToStreamId(const CIp &) const; + + // debug + bool DebugTestDecodePacket(const CBuffer &); + bool DebugDumpHeaderPacket(const CBuffer &); + bool DebugDumpDvPacket(const CBuffer &); + bool DebugDumpLastDvPacket(const CBuffer &); protected: - // for keep alive - CTimePoint m_LastKeepaliveTime; + // for keep alive + CTimePoint m_LastKeepaliveTime; - // for queue header caches - std::array m_StreamsCache; + // for queue header caches + std::array m_StreamsCache; - // for wires-x - CWiresxCmdHandler m_WiresxCmdHandler; - unsigned char m_seqNo; + // for wires-x + CWiresxCmdHandler m_WiresxCmdHandler; + unsigned char m_seqNo; }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cysfutils.cpp b/src/cysfutils.cpp index 914f684..11686e9 100644 --- a/src/cysfutils.cpp +++ b/src/cysfutils.cpp @@ -34,436 +34,444 @@ //////////////////////////////////////////////////////////////////////////////////////// // constants & defines -const unsigned int PRNG_TABLE[] = { - 0x42CC47U, 0x19D6FEU, 0x304729U, 0x6B2CD0U, 0x60BF47U, 0x39650EU, 0x7354F1U, 0xEACF60U, 0x819C9FU, 0xDE25CEU, - 0xD7B745U, 0x8CC8B8U, 0x8D592BU, 0xF71257U, 0xBCA084U, 0xA5B329U, 0xEE6AFAU, 0xF7D9A7U, 0xBCC21CU, 0x4712D9U, - 0x4F2922U, 0x14FA37U, 0x5D43ECU, 0x564115U, 0x299A92U, 0x20A9EBU, 0x7B707DU, 0x3BE3A4U, 0x20D95BU, 0x6B085AU, - 0x5233A5U, 0x99A474U, 0xC0EDCBU, 0xCB5F12U, 0x918455U, 0xF897ECU, 0xE32E3BU, 0xAA7CC2U, 0xB1E7C9U, 0xFC561DU, - 0xA70DE6U, 0x8DBE73U, 0xD4F608U, 0x57658DU, 0x0E5E56U, 0x458DABU, 0x7E15B8U, 0x376645U, 0x2DFD86U, 0x64EC3BU, - 0x3F1F60U, 0x3481B4U, 0x4DA00FU, 0x067BCEU, 0x1B68B1U, 0xD19328U, 0xCA03FFU, 0xA31856U, 0xF8EB81U, 0xF9F2F8U, - 0xA26067U, 0xA91BB6U, 0xF19A59U, 0x9A6148U, 0x8372B6U, 0xC8E86FU, 0x9399DCU, 0x1A0291U, 0x619142U, 0x6DE9FFU, - 0x367A2CU, 0x7D2511U, 0x6484DAU, 0x2F1F0FU, 0x1E6DB4U, 0x55F6E1U, 0x0EA70AU, 0x061C96U, 0xDD0E45U, 0xB4D738U, - 0xAF64ABU, 0xE47F42U, 0xFDBE9DU, 0xB684ACU, 0xFE5773U, 0xC1E4A2U, 0x8AFD0DU, 0x932ED4U, 0xD814E3U, 0x81853AU, - 0x225EECU, 0x7A6945U, 0x31A112U, 0x2AB2EBU, 0x630974U, 0x785AB5U, 0x11E3CEU, 0x4A715BU, 0x402AA0U, 0x199B7DU, - 0x16C05EU, 0x6F5283U, 0xA4FB10U, 0xBFA8ECU, 0xF633B7U, 0xEC4012U, 0xADD8C9U, 0xD6EB1CU, 0xDD3027U, 0x84A1FAU, - 0xCF9E19U, 0xD64C80U, 0xBC4557U, 0xA7B62EU, 0x6E2DA1U, 0x311F50U, 0x38C68EU, 0x63D5BFU, 0x486E60U, 0x10BFE1U, - 0x5BAD1EU, 0x4A4647U, 0x0157F0U, 0x7ACC29U, 0x73BEEAU, 0x2825D7U, 0xA0940CU, 0xFBCFF9U, 0xB05C62U, 0x892426U, - 0xC6B3DDU, 0xDF3840U, 0x9449B3U, 0xCED3BEU, 0xE7804DU, 0xBC3B90U, 0xF5AA0BU, 0xE6D17EU, 0x2D43B5U, 0x345A04U, - 0x5EA9DBU, 0x07A202U, 0x0C7134U, 0x45C9FDU, 0x5EDA0AU, 0x310193U, 0x6830C4U, 0x62AA3DU, 0x3B59B2U, 0xB04043U, - 0xEB975CU, 0x82BCADU, 0x912E62U, 0xD8F7FBU, 0x82C489U, 0x895F54U, 0xF00FE7U, 0xFBBC2AU, 0xA2E771U, 0xE956C4U, - 0xF6CD1FU, 0x3F8FEAU, 0x0534E1U, 0x4C653CU, 0x17FE8FU, 0x1C4C52U, 0x4515A1U, 0x2E86A9U, 0x3FBD56U, 0x756C87U, - 0x6ED218U, 0x279179U, 0x7C0AA6U, 0xD53B17U, 0x8EE0C8U, 0x85F291U, 0xD94B36U, 0x9298EFU, 0xAB8318U, 0xE07301U, - 0xBB68DFU, 0xB2CB7CU, 0xE910A5U, 0xE101D2U, 0x92BB4BU, 0x59E8B4U, 0x407175U, 0x0B026AU, 0x12989BU, 0x792944U, - 0x2376EDU, 0x2EF5BAU, 0x758663U, 0x7C1ED5U, 0x078D0CU, 0x4EF6ABU, 0x5567F2U, 0x9F7C29U, 0xC68E9CU, 0xC51747U, - 0xBC6422U, 0xB7EFB9U, 0xECFD44U, 0xA50497U, 0xAF178AU, 0xD68C69U, 0xD97DB5U, 0x82670EU, 0xCBB45BU, 0x508D90U, - 0x190A25U, 0x63F0FEU, 0x68E3C7U, 0x317A10U, 0x3A09D9U, 0x6B926EU, 0x004237U, 0x1B79C8U, 0x53EA59U, 0x48B3B7U, - 0x811166U, 0xDE4A79U, 0xF5F988U, 0xAC6057U, 0xE733FEU, 0xFF89ADU, 0xB49830U, 0x8F4BC3U, 0xC6F00EU, 0x9DA135U, - 0x942FE0U, 0xC71C3BU, 0x4DC78FU, 0x3476C4U, 0x7F6C39U, 0x66BFAAU, 0x298657U, 0x725504U, 0x5B4E89U, 0x01FE72U, - 0x0835A3U, 0x53269CU, 0x189D4DU, 0x01CDC2U, 0xEA763BU, 0xF3A56DU, 0xB0BCD4U, 0xE80F13U, 0xE355CAU, 0x98C47DU, - 0x91AB24U, 0xCE38DBU, 0x87A35AU, 0x9CD3A5U, 0xD648F4U, 0xAF7B6FU, 0x24A292U, 0x7D3011U, 0x764B6DU, 0x2DDABEU, - 0x44D123U, 0x5E22D8U, 0x1FB09DU, 0x04A926U, 0x4F5AF3U, 0x064128U, 0x3DB105U, 0x70AAD6U, 0xAA392FU, 0xA1C4B8U, - 0xF8C7C0U, 0xD35D0FU, 0x8A2E9EU, 0xC1B761U, 0xDA44F0U, 0x925E8FU, 0x89CF4EU, 0xE8B4D1U, 0xB32728U, 0xB8FE7FU, - 0x61DCC6U, 0x2A4701U, 0x1614D8U, 0x5DADE2U, 0x46BE37U, 0x0F44DCU, 0x54D549U, 0x5D8E32U, 0x263DAFU, 0x2C237CU, - 0x75E291U, 0xBE5982U, 0xA74A7FU, 0xC493A4U, 0xDFA131U, 0x967A5AU, 0xCCCB8EU, 0xC1D835U, 0x9A02ECU, 0xF331BBU, - 0xE8B812U, 0xA3EBC5U, 0xBA507CU, 0x7080ABU, 0x099BC2U, 0x02285DU, 0x59718CU, 0x50C273U, 0x0B1862U, 0x4A1F8CU, - 0x70A655U, 0x3BF5C2U, 0x666FBBU, 0x6DDE68U, 0x3485C5U, 0x9F161EU, 0xC46F4BU, 0x8CFDF0U, 0x97C625U, 0xDE058EU, - 0xC59CD3U, 0xAEAE20U, 0xF775BCU, 0xFC647FU, 0xBD9F02U, 0xE70C91U, 0xCC1468U, 0x11E7B7U, 0x1AFC36U, 0x435B49U, - 0x080398U, 0x139027U, 0x7B63FEU, 0x607AF9U, 0x29E900U, 0x7293D6U, 0x79026FU, 0x00D930U, 0x0BEAF1U, 0xD3614EU, - 0x90119FU, 0x8B8AE4U, 0xC61969U, 0xBD609AU, 0xB4F247U, 0xEFA954U, 0xE518A9U, 0xBC0362U, 0xD7D0D6U, 0xCE7E8DU, - 0x856F18U, 0x1C94E3U, 0x578726U, 0x0D5F1DU, 0x24ECC0U, 0x7FF713U, 0x3E26AAU, 0x251D6DU, 0x6A8F14U, 0x53648BU, - 0x19757AU, 0x40AEB4U, 0xCB9CA5U, 0x90055AU, 0x9956C3U, 0xE2ED34U, 0xAB3C7DU, 0xB126EAU, 0xFA9513U, 0xA3D2C8U, - 0x886BFDU, 0xD9F836U, 0xD2A2E3U, 0x8D1359U, 0x454804U, 0x5EDBF7U, 0x37637AU, 0x2C3089U, 0x67ABD4U, 0x3E8847U, - 0x3551BAU, 0x4D6331U, 0x46B8C4U, 0x1D299FU, 0x54120EU, 0x5FC0E1U, 0x86D93BU, 0xE56A0EU, 0xFBB1D5U, 0xB2B600U, - 0xA94EABU, 0xE05DF6U, 0x9BE605U, 0x90B798U, 0xC92C6BU, 0xC3DE66U, 0x9AC7BDU, 0xD15448U, 0x6A3FD3U, 0x23ADA3U, - 0x78346CU, 0x7147F5U, 0x2BDC02U, 0x0EAD5BU, 0x553FFCU, 0x1EA425U, 0x07D5F2U, 0x4C4ECBU, 0x554C14U, 0x3EB3F5U, - 0xE4A26AU, 0xED799BU, 0xB6CA85U, 0xFFD25CU, 0xC421BFU, 0x8F3A22U, 0x96AB51U, 0xDC518CU, 0x895217U, 0x8289F2U, - 0xF9B8A9U, 0xF0231CU, 0x2BF1C7U, 0x62C80AU, 0x781B39U, 0x1320E5U, 0x4AB156U, 0x41EB8FU, 0x1848E0U, 0x13D771U, - 0x4886AEU, 0x203C5FU, 0x3B6F40U, 0x76F6A1U, 0xE5457EU, 0xAE1EE7U, 0xD7AC10U, 0xDCB549U, 0x8476EFU, 0x8FC536U, - 0xD49DE9U, 0x9D0ED8U, 0xA63513U, 0xEFE4A6U, 0xB4DF7DU, 0x3E0D00U, 0x779693U, 0x4CA75EU, 0x0568ADU, 0x527BB0U, - 0x59C34BU, 0x00109FU, 0x0A0B14U, 0x73FA61U, 0x38E0BAU, 0x23530FU, 0x6A88D4U, 0xB199DDU, 0x98322AU, 0xC260F3U, - 0xCBF944U, 0x908A0DU, 0xDB11F2U, 0xC28163U, 0xADFABDU, 0xBC694CU, 0xF65243U, 0xAD83BAU, 0xA40D6DU, 0x5F7EF4U, - 0x16E787U, 0x0DF44AU, 0x460EF1U, 0x5E1F24U, 0x15CC3FU, 0x6C77CAU, 0x676401U, 0x3C9CBDU, 0x359FEEU, 0x6A0413U, - 0x02F590U, 0x91EE4DU, 0xDA3C3EU, 0xC305A3U, 0x889658U, 0xF14D99U, 0xFA7F86U, 0xA1E677U, 0xE981E8U, 0xF21A10U, - 0xBB4BD7U, 0x80F1CEU, 0xCB6239U, 0x123BE0U, 0x1D885FU, 0x45921EU, 0x6641E1U, 0x3DE870U, 0x74BBAFU, 0x6F00C6U, - 0x261055U, 0x7DCBA8U, 0x57787AU, 0x0E2167U, 0x05B28CU, 0xCC8819U, 0x975BE2U, 0xBC52B7U, 0xE5E52CU, 0xEB37C9U, - 0xB20E12U, 0xF9DD2FU, 0xE8C6FCU, 0x837701U, 0xD8AD82U, 0xD1BE5AU, 0x0B0525U, 0x0244B4U, 0x79FE5BU, 0x322DCAU, - 0x2B3495U, 0x60876CU, 0x79DCFBU, 0x334C12U, 0x4C7745U, 0x45A4DCU, 0x1E3F23U, 0x175FF2U, 0xC4C0D8U, 0xAFF30DU, - 0xB72AF6U, 0xFCB96BU, 0xA5C338U, 0xAE5295U, 0xF54946U, 0xDCBABBU, 0x87A1A8U, 0xCF2165U, 0xD4DA9EU, 0x9FC90BU, - 0x223070U, 0x6922A4U, 0x30B92FU, 0x3348D6U, 0x695B01U, 0x20C038U, 0x1BB2EFU, 0x523B06U, 0x49EC99U, 0x02D7C8U, - 0x5B4777U, 0x713CA6U, 0xA8AF49U, 0xA3B650U, 0xF84586U, 0xB5DF7FU, 0xAE8CF8U, 0xC72581U, 0x9D3652U, 0x9EEDCFU, - 0xC75D34U, 0xCC0671U, 0xB5B5CAU, 0xFEAC1FU, 0x677EA4U, 0x2DC5F9U, 0x26D63AU, 0x7F1F86U, 0x142855U, 0x0DF2A8U, - 0x42E3B3U, 0x195872U, 0x108B8DU, 0x6AB31CU, 0x632063U, 0x307BAAU, 0xFBC83DU, 0xE201C4U, 0xA91393U, 0x90A82AU, - 0xDAF9E4U, 0x816A55U, 0x88D00AU, 0xD383DBU, 0xFA3A64U, 0xA569A5U, 0xEEE2DEU, 0x76D243U, 0x3D0D90U, 0x649E6DU, - 0x47E76EU, 0x1C7491U, 0x156E49U, 0x4E9DDEU, 0x0604B7U, 0x3D3720U, 0x76FDD9U, 0x6FEC06U, 0x2417B7U, 0xFD04F8U, - 0xF29D29U, 0x886F92U, 0xC1744FU, 0xDAC73CU, 0x939EB1U, 0x880C63U, 0xEBE79EU, 0xB2F285U, 0xB86970U, 0xE11ABBU, - 0xEA822EU, 0x311155U, 0x586AC0U, 0x43F92BU, 0x0A81F6U, 0x5412C5U, 0x5D111CU, 0x26E8CBU, 0x2D7B63U, 0x74213CU, - 0x3F90CDU, 0x2E8B52U, 0x645883U, 0xDFE36CU, 0x96F375U, 0xDD0882U, 0xC40B1BU, 0x8FD6CCU, 0xB464A5U, 0xFC7F3EU, - 0xA7AECBU, 0xAA9511U, 0xF10634U, 0xBA5CEFU, 0x83ED32U, 0x483681U, 0x5015DCU, 0x138D3FU, 0x48DEA2U, 0x616571U, - 0x3AF40CU, 0x33AF97U, 0x681D72U, 0x2246E9U, 0x3BD7B9U, 0x506C46U, 0x0D2FDFU, 0x869338U, 0xDDC061U, 0xD45BD6U, - 0xAF6A0FU, 0xE7B8C0U, 0xFC2371U, 0xBF102EU, 0xA6C9DFU, 0xEDDA40U, 0x943089U, 0x9FA1BFU, 0x459A66U, 0x0C4995U, - 0x175108U, 0x7AE243U, 0x6139B6U, 0x2A2A2DU, 0x73D3D8U, 0x79C183U, 0x204A26U, 0x0B3FFDU, 0x5AA420U, 0x111613U, - 0x8A4FDFU, 0xC3DC2CU, 0xF9A7B5U, 0xB034EAU, 0xEBAC5BU, 0xE0CF94U, 0xBD5465U, 0xF605FAU, 0xCFBEA3U, 0x85AC54U, - 0x9E55DDU, 0xD7C62AU, 0x0CDD73U, 0x252FCDU, 0x76361CU, 0x7DF5D3U, 0x3546E2U, 0x6E5B39U, 0x67A98CU, 0x1CB247U, - 0x57231AU, 0x4AD8A9U, 0x01CA74U, 0x191187U, 0xF2208AU, 0xA9AB50U, 0xA0F8A5U, 0xFB403EU, 0xF2D34BU, 0xA9A880U, - 0xCB393DU, 0xD262EEU, 0x99D0B7U, 0xC04B00U, 0xCB1AC9U, 0xB0B176U, 0x39E3A7U, 0x677EF8U, 0x2ECD58U, 0x359687U, - 0x7E277EU, 0x473D69U, 0x0CEEB0U, 0x55D557U, 0x5F04CEU, 0x0C8EBDU, 0x25BD60U, 0x7E64DBU, 0xB7771EU, 0xACCC05U, - 0xE51CF0U, 0xBF2F2AU, 0x90F497U, 0xC9E7D4U, 0xC25F09U, 0x9B9CBAU, 0xD08767U, 0xEB320CU, 0xA36999U, 0x38FB42U, - 0x7180B3U, 0x22112CU, 0x29AA45U, 0x50F9D2U, 0x1B610AU, 0x0202FDU, 0x4899E4U, 0x57080BU, 0x3E72DAU, 0x65E165U, - 0x6CFA34U, 0xB70BEBU, 0xBC104AU, 0xE4E295U, 0x8F7BECU, 0x96787FU, 0xD583B2U, 0x9E9740U, 0x870C5DU, 0xECFFA6U, - 0xF4E433U, 0xBF35F8U, 0xE00F8DU, 0x699C16U, 0x3265EBU, 0x1B6638U, 0x40F515U, 0x0A8DC6U, 0x131E1BU, 0x5845A0U, - 0x21F670U, 0x2A6E1FU, 0x791D8EU, 0x708651U, 0x2AD7E8U, 0xE37CAFU, 0xD8EE56U, 0x97B3C1U, 0x8E0018U, 0xC51B6FU, - 0x9CC9E6U, 0xB67019U, 0xEF23C8U, 0xE498F2U, 0xBF9927U, 0xF643ECU, 0xCD7051U, 0x04E902U, 0x563AFFU, 0x5D006CU, - 0x04D3A1U, 0x0FCA9AU, 0x72794FU, 0x39A2B4U, 0x228231U, 0x6A19EAU, 0x714E96U, 0x18F705U, 0x4324FCU, 0xC83E3BU, - 0x918D02U, 0xDADCD5U, 0xC2470CU, 0xA135B3U, 0xBABCF2U, 0xF30F4DU, 0xA8549EU, 0xA1C543U, 0xDEFF78U, 0xD42CBCU, - 0x0DB747U, 0x46C6D2U, 0x5F5C89U, 0x144F60U, 0x6FA6F7U, 0x66350EU, 0x2C0A59U, 0x35DAE0U, 0x7EC12FU, 0x0D32FEU, - 0x0429C1U, 0x5FB911U, 0xD642AEU, 0x895167U, 0xC3D8B0U, 0xFAAB89U, 0xB1315AU, 0xA8C0A7U, 0xE3DB24U, 0xB84879U, - 0x913382U, 0xCBA317U, 0x82F8FCU, 0x994BA9U, 0x50C213U, 0x4390CEU, 0x282F5DU, 0x713E30U, 0x7FCDE3U, 0x26565EU, - 0x2D0485U, 0x56BDD4U, 0x1FAE7BU, 0x0475AAU, 0x4DD555U, 0x17CE4CU, 0x9C1D9BU, 0xE52473U, 0xEEF7E4U, 0xB7CD1DU, - 0xF45E42U, 0xEF87E3U, 0x87B43CU, 0x986FADU, 0xD16FD2U, 0x8AD403U, 0x8103A8U, 0xD83A75U, 0x33A826U, 0x2BF39BU, - 0x604049U, 0x7B99A4U, 0x328ABFU, 0x49306AU, 0x407191U, 0x1BEA04U, 0x19D96FU, 0x4001F2U, 0x0FB201U, 0x36E9DCU, - 0xFD7ADFU, 0xE64326U, 0xAF91F9U, 0xF51249U, 0xDC2B16U, 0x87F8D7U, 0xCCE668U, 0xC517B1U, 0x9E8C46U, 0x97BF5FU, - 0xED6498U, 0xA67461U, 0x378FF6U, 0x788C8FU, 0x611514U, 0x0AE6F1U, 0x53FC2BU, 0x596F3EU, 0x0216C5U, 0x4B8508U, - 0x507FBBU, 0x396EE6U, 0x22F535U, 0xE99688U, 0xB10F43U, 0xBA1D36U, 0xC3E2ADU, 0xC07178U, 0x9B28C3U, 0xD69A8BU, - 0xCD817CU, 0x8570E5U, 0xFEEB12U, 0xF5E8CBU, 0xAC10C4U, 0x270335U, 0x7ED8EAU, 0x156B5BU, 0x0E7A14U, 0x46A0C5U, - 0x5D937AU, 0x144AA3U, 0x4F79D5U, 0x6CF35CU, 0x31228FU, 0x7A1932U, 0x628E69U, 0xA9D59CU, 0x926517U, 0xDBBEE2U, - 0x80ADB9U, 0x891424U, 0xD246D7U, 0xD8ED1AU, 0xA17C28U, 0xEA27F5U, 0xF3942EU, 0xB8CE8FU, 0xAB5FD0U, 0x466461U, - 0x1CB7BEU, 0x152F6FU, 0x4E1CC0U, 0x05D799U, 0x1CE66EU, 0x773DF7U, 0x7EAB00U, 0x249048U, 0x6D41D7U, 0x765A26U, - 0x1DA9F9U, 0x8431C8U, 0xCF0203U, 0x96C1DEU, 0x90D86DU, 0xCB6A30U, 0xA23193U, 0xB9A24EU, 0xF05B95U, 0xEB48A0U, - 0xA0D27AU, 0xD8A39FU, 0xD33804U, 0x0A9B79U, 0x01C3AAU, 0x5A5437U, 0x132FD4U, 0x28BC0DU, 0x60253AU, 0x3F57E3U, - 0x3CCC7CU, 0x65DD9DU, 0x4E26C2U, 0x172572U, 0xDCDDADU, 0xC64E64U, 0x8F5553U, 0x94A68AU, 0xFDBE7DU, 0xA66DE4U, - 0xADD68BU, 0xF4C75AU, 0xFE0CC1U, 0x873E34U, 0xC8A72FU, 0xDBD0C2U, 0x124B10U, 0x49998DU, 0x40A8FEU, 0x3A3323U, - 0x316088U, 0x68D95DU, 0x235B06U, 0x3A00B3U, 0x51B178U, 0x4AEA89U, 0x025816U, 0x59C36FU, 0xD092B8U, 0x8B2930U, - 0xE43AC7U, 0xF5E2DEU, 0xBEC121U, 0xA71AF0U, 0xED8B7FU, 0x94B40EU, 0x9F66D1U, 0xD45D68U, 0xCD8CBFU, 0x8617F6U, - 0x5F2545U, 0x75FC98U, 0x2EFF62U, 0x674467U, 0x7C959CU, 0x318F09U, 0x0A7CD2U, 0x4967AFU, 0x11D62CU, 0x1A8CD1U, - 0x431F02U, 0x48A69DU, 0xB3E5ECU, 0xFA7623U, 0xE10E9AU, 0xA99948U, 0xB20215U, 0xD971A6U, 0x80E86BU, 0x8BDA90U, - 0xD60185U, 0x9D907EU, 0x8FFBFBU, 0xE66920U, 0x7D705DU, 0x3483CEU, 0x6F9833U, 0x646BF1U, 0x1DF3E8U, 0x17E017U, - 0x4E1BC6U, 0x050A79U, 0x1E8038U, 0x5773E7U, 0x2C685EU, 0xA1BD89U, 0xFB86B0U, 0xF01477U, 0xA16D8EU, 0xCAFE19U, - 0xD365C1U, 0x9815AEU, 0x839E3FU, 0xCBCDC4U, 0x907611U, 0xB9E70AU, 0xE2BDE7U, 0x2B0E34U, 0x301789U, 0x7BE4DAU, - 0x477707U, 0x0C2FACU, 0x558C79U, 0x5E9743U, 0x0D4496U, 0x04786DU, 0x7FABE0U, 0x3730B3U, 0x3C014AU, 0xE7DADDU, - 0xEEE834U, 0x956163U, 0xDCB2FAU, 0xC78905U, 0x8D5BD4U, 0xD0427BU, 0xDBF12BU, 0xA22AB4U, 0xA93B4DU, 0xFA819AU, - 0xB3D2B3U, 0x287B64U, 0x40289DU, 0x5BB206U, 0x100153U, 0x495CB8U, 0x42CF2DU, 0x3BF4D6U, 0x70248BU, 0x6ABF19U, - 0x23CCF4U, 0x3C4527U, 0x75761AU, 0x8EACC1U, 0x853F44U, 0xD44EBFU, 0xDED5EEU, 0x87C751U, 0xEC3E80U, 0xF72D6FU, - 0xBEB676U, 0xE557A1U, 0xEC4D59U, 0xB6BECEU, 0x9DA527U, 0x443078U, 0x0BCAE9U, 0x12D916U, 0x594087U, 0x6033E8U, - 0x22A831U, 0x7948A2U, 0x70535FU, 0x2BC01CU, 0x62BBA1U, 0x592A7BU, 0x92308EU, 0x8AC395U, 0xC15A50U, 0x9809ABU, - 0xB3B336U, 0xECB245U, 0xE54998U, 0xBEDA1BU, 0xF681E6U, 0xED35F5U, 0x8E2E0CU, 0x87FDD3U, 0x5CC453U, 0x1556ACU, - 0x0E85FDU, 0x64AC42U, 0x3D7F8BU, 0x36447CU, 0x6FD665U, 0x640FB2U, 0x3B3C4BU, 0x52A7C4U, 0x48F7B5U, 0x014C2EU, - 0x9A9FFBU, 0xD19601U, 0xA0250CU, 0xAB7FFFU, 0xF2C822U, 0xB8D1B1U, 0xA302CCU, 0xEAB907U, 0xD1E9B2U, 0x987269U, - 0xC3411CU, 0xCC8897U, 0x141A42U, 0x3F61B8U, 0x66F2A1U, 0x2DCB56U, 0x3618DFU, 0x778208U, 0x2CB3F1U, 0x0468EEU, - 0x5F7B1FU, 0x5693D0U, 0x0D8041U, 0x461B3EU, 0xFFECE7U, 0xB4FD50U, 0xA94798U, 0xE314CFU, 0xB88D76U, 0xB17EADU, - 0xCA7508U, 0xC3E553U, 0x989EA6U, 0xDB0D3DU, 0xC396E8U, 0xA8E683U, 0x717D1EU, 0x7A0EEDU, 0x219730U, 0x288422U, - 0x736ECFU, 0x1BFF14U, 0x04A4A1U, 0x4F177AU, 0x56092BU, 0x1DD884U, 0x64635DU, 0xEF70EAU, 0xA589B3U, 0xF49B54U, - 0xFF50CDU, 0xA66312U, 0x8DFA62U, 0xD628FDU, 0x9F131CU, 0x8582C3U, 0xCCF9DAU, 0xF36A29U, 0xB8B2F4U, 0x618157U, - 0x6A020AU, 0x335999U, 0x79E864U, 0x4272BFU, 0x03259AU, 0x189C40U, 0x51CFB5U, 0x0A752EU, 0x216463U, 0x79BF90U, - 0x721C0DU, 0xAB47FEU, 0xE4D727U, 0xFDEC28U, 0x963FD9U, 0x8DA646U, 0xC594B7U, 0x9E4FE8U, 0x977E60U, 0xECA597U, - 0xAF264EU, 0xB61C79U, 0xFDCDA0U, 0x65D64FU, 0x2E61DCU, 0x553881U, 0x5CAA72U, 0x0351FBU, 0x0A400CU, 0x51FB55U, - 0x3BB9CAU, 0x22223AU, 0x6993B5U, 0x30C8C4U, 0x3B5B1BU, 0xE02B82U, 0xC1B075U, 0x9B23BCU, 0xD25A8BU, 0xC9C852U, - 0x82A3A9U, 0xBB303CU, 0xF42977U, 0xADDA82U, 0xA64418U, 0xFC55E5U, 0xB5AEE6U, 0x0EBD3BU, 0x4765C8U, 0x4CD655U, - 0x17DD2EU, 0x562EEBU, 0x6C3770U, 0x25A585U, 0x3E5EDEU, 0x754F6FU, 0x2C94A1U, 0x23A758U, 0x5A3F4FU, 0xD07C96U, - 0x8BC761U, 0xC254E8U, 0xD92C97U, 0xB0BF06U, 0xEBE0D9U, 0xE25138U, 0xB8CAA7U, 0xBB98DEU, 0xE22109U, 0x896291U, - 0x10F172U, 0x5BCB2FU, 0x401A94U, 0x0CA141U, 0x77B2BAU, 0x7E6BBFU, 0x255964U, 0x6E82D9U, 0x77130AU, 0x3C3877U, - 0x04EAF4U, 0x4FD129U, 0x9C40DBU, 0x959BC6U, 0xCEAC2DU, 0xE774FCU, 0xBC6763U, 0xF6DC12U, 0xEB8DCDU, 0xA00664U, - 0xF9F4B3U, 0xD2EF4AU, 0x895E5DU, 0x800584U, 0x5A972BU, 0x132EFBU, 0x287D84U, 0x63E615U, 0x7297CEU, 0x391D23U, - 0x608E30U, 0x6AF5CDU, 0x11641EU, 0x5C5E93U, 0x4789E0U, 0x0E903DU, 0x956386U, 0xFEF053U, 0xB6E879U, 0xAD0BACU, - 0xE41077U, 0xFF83CAU, 0xB47A99U, 0xCD6870U, 0xCE93E7U, 0x96823EU, 0x9D1941U, 0xC4EBD0U, 0x2BF23FU, 0x3031EEU, - 0x790A71U, 0x229909U, 0x2AC1CEU, 0x717677U, 0x5AEDA0U, 0x039C99U, 0x480646U, 0x515587U, 0x1AEC3CU, 0x296F69U, - 0xE13492U, 0xBA8607U, 0xB39FCCU, 0xEC4CB1U, 0xA77723U, 0x9EA7DEU, 0xD51C0DU, 0xCD0F00U, 0x86D4FBU, 0xDDF56EU, - 0xF46F95U, 0x2FBCD4U, 0x268D6BU, 0x7D52B2U, 0x374165U, 0x26F9DCU, 0x4D2A9BU, 0x141163U, 0x1FD2FCU, 0x40CA2DU, - 0x497952U, 0x3322D3U, 0x7AB32CU, 0xE108F5U, 0xAA5AE2U, 0xB3E31BU, 0xF8B098U, 0x812B65U, 0x8B8936U, 0xD0D08AU, - 0xD94341U, 0x8A7894U, 0xE3A9AFU, 0xF8377AU, 0xB74481U, 0x6FDD0CU, 0x64EE5FU, 0x3D35A2U, 0x163731U, 0x5F8ECCU, - 0x045DC7U, 0x0F4616U, 0x57B6E8U, 0x7CAD79U, 0x253E86U, 0x6EC7CFU, 0x7DD478U, 0xB426A1U, 0xCF2D76U, 0xC3BC5FU, - 0x984780U, 0x935571U, 0xCACCEEU, 0x81BBBFU, 0xB82054U, 0xF371C0U, 0xE9CB3BU, 0xA05826U, 0xFB33F5U, 0x52A218U, - 0x09B88BU, 0x424BF6U, 0x53D22DU, 0x198198U, 0x043A53U, 0x6F2A06U, 0x34F1BDU, 0x3DC260U, 0x664982U, 0x6FB81BU, - 0x15A24CU, 0xDE71F5U, 0xC7482AU, 0x8CDFCBU, 0x9505D4U, 0xDE3405U, 0xA5EFFAU, 0xA4FC63U, 0xFE5704U, 0xB387DDU, - 0xA8BC6AU, 0xC32FB2U, 0x5A7EE5U, 0x11C44CU, 0x489797U, 0x420E62U, 0x19BD79U, 0x30E6BCU, 0x6B6407U, 0x225DDAU, - 0x398EA9U, 0x703534U, 0x0A64F7U, 0x09FA0AU, 0xD4C910U, 0xDF10E5U, 0x86833EU, 0xCDB99BU, 0xE67A40U, 0xBE631BU, - 0xB590AEU, 0xEC8B75U, 0xA73BD0U, 0x9CE08BU, 0xD5F35EU, 0x8E0AE5U, 0x061828U, 0x5D835AU, 0x5660C7U, 0x277914U, - 0x68CAE9U, 0x7190E2U, 0x3A0113U, 0x20FECCU, 0x49ED7DU, 0x127522U, 0x1B06ABU, 0x40855CU, 0x8B9E85U, 0x926FB2U, - 0xF8F56AU, 0xE186A5U, 0xAA1F14U, 0xF10CCBU, 0xF0F7BAU, 0x8F6735U, 0x867CECU, 0xDC9F1FU, 0x978402U, 0x8E54F1U, - 0x45EF3CU, 0x7CFC8FU, 0x3705D2U, 0x6C1248U, 0x64C8BDU, 0x3FF976U, 0x566243U, 0x4DA198U, 0x069B45U, 0x1F0AF6U, - 0x5851BBU, 0x00E248U, 0xAB3BD1U, 0xF2090EU, 0xF9926FU, 0xA2C3F1U, 0xEB7800U, 0xD07B9FU, 0x98A1E6U, 0xC31021U, - 0xC84BB8U, 0x91D84FU, 0x9AEC96U, 0x6337A9U, 0x288468U, 0x369FB3U, 0x774E06U, 0x6C645DU, 0x05B7A9U, 0x4E2E22U, - 0x551DFFU, 0x1CC78CU, 0x47D611U, 0x4F2DF2U, 0x343E6FU, 0xBF8514U, 0xE655C1U, 0xAD5E5AU, 0xB4EDBFU, 0xDFB4E4U, - 0xC1265DU, 0x80DD8BU, 0xDBC852U, 0xD25375U, 0x8920ACU, 0xA2BA53U, 0xFB0BC2U, 0x31401DU, 0x28D33CU, 0x63AAE3U, - 0x18381AU, 0x11238DU, 0x4AD2E4U, 0x434933U, 0x195BABU, 0x56A058U, 0x6FB105U, 0x2C5AAEU, 0x35C97BU, 0xFED9A0U, - 0xA52295U, 0x8D314EU, 0xD6ECA3U, 0x9F5E30U, 0x84456DU, 0xCFB6DEU, 0xD6AF03U, 0xBD2CE9U, 0xE556FCU, 0xEEC707U, - 0xB71CD6U, 0x382F59U, 0x43B720U, 0x02E4F7U, 0x195F4EU, 0x51CC99U, 0x0AA550U, 0x013767U, 0x786CBEU, 0x73DD01U, - 0x2AC6D1U, 0x61159EU, 0x7BA92FU, 0x92BAF4U, 0x896109U, 0xC0521AU, 0x9F9AF7U, 0x942924U, 0xC532B9U, 0xEFE3C2U, - 0xA6D807U, 0xFD0ABCU, 0xF69369U, 0xAFA033U, 0x44738EU, 0x5D694DU, 0x17C8F0U, 0x0C93A3U, 0x45207AU, 0x1EF9C5U, - 0x37EB04U, 0x6850FBU, 0x6305EAU, 0x3B9E15U, 0x782DC4U, 0x41774BU, 0x8AF633U, 0xD18DE4U, 0xD81E5DU, 0x83A69AU, - 0x8AF583U, 0xF06E7CU, 0xBB5FADU, 0xA28416U, 0xE99653U, 0xF06D88U, 0x9FEC35U, 0xC4F7E6U, 0x4C059AU, 0x1F1C19U, - 0x56EFC4U, 0x4D743FU, 0x24612AU, 0x3F9BD1U, 0x748814U, 0x2C13AFU, 0x27F276U, 0x5EE861U, 0x553B88U, 0x0E0A5FU, - 0xC791E6U, 0xD8E2B0U, 0x907A69U, 0xABE9C6U, 0xE09217U, 0xB10168U, 0xBA48F9U, 0xE3FA26U, 0x8861CFU, 0x9230D8U, - 0xDB8B21U, 0xC099B2U, 0x09644FU, 0x52F704U, 0x79AC90U, 0x201F6BU, 0x2E17BEU, 0x77C495U, 0x3CFF48U, 0x172E9BU, - 0x4E9426U, 0x0D8775U, 0x145E98U, 0x5E6D03U, 0xC5F6D6U, 0xAC242DU, 0xF70D3CU, 0xFEDED2U, 0xA5C543U, 0xAE74BCU, - 0xD62EE5U, 0x9D9D72U, 0x80029BU, 0xCB534CU, 0x90E175U, 0x19BAAAU, 0x6A3B6BU, 0x6280D4U, 0x39D385U, 0x724B7AU, - 0x6B78E2U, 0x00A321U, 0x19101CU, 0x5248CFU, 0x0ADB30U, 0x01F0A9U, 0x5A21CEU, 0xB73A17U, 0xACC880U, 0xE55179U, - 0xFE42A6U, 0xB4B987U, 0xC5AF58U, 0xCE1688U, 0x97C533U, 0x9CCE76U, 0xC73F8DU, 0x8E2510U, 0xB4B6C3U, 0x7D4FFEU, - 0x665C3DU, 0x2DC7C0U, 0x70B55BU, 0x5B2C2EU, 0x025FF5U, 0x49D470U, 0x53448AU, 0x1A3FD7U, 0x09AC64U, 0x60BDBDU, - 0x3B467AU, 0xB0D043U, 0xE98B9CU, 0xE33A2DU, 0x9A21E2U, 0xD1C3B3U, 0xCA5A0CU, 0x8709DDU, 0xDCB222U, 0xF5A3AAU, - 0xBF79DDU, 0xA44A04U, 0xEDD193U, 0x3E006AU, 0x373B21U, 0x4CF994U, 0x47C04FU, 0x1F53DAU, 0x5488A1U, 0x4DB86CU, - 0x2623DFU, 0x7D7402U, 0x70CF50U, 0x2B9EFDU, 0x232426U, 0xF8A7D3U, 0x91FEC8U, 0x8A4D39U, 0xC117F6U, 0xD0866FU, - 0x9B3D18U, 0xE36EC1U, 0xE8F576U, 0xB3C5BFU, 0xBA1629U, 0xE1BD50U, 0xA8EC8FU, 0x17763EU, 0x5D45F1U, 0x049CA0U, - 0x0F8F1FU, 0x5630C6U, 0x7DE225U, 0x26FB38U, 0x6F08CBU, 0x7D0316U, 0x34B28DU, 0x2F68E9U, 0xC47B72U, 0x9DC287U, - 0x96915CU, 0xCF0B41U, 0x85F8A2U, 0xBAE17FU, 0xF372CCU, 0xE81991U, 0xA1894AU, 0xFAF2EBU, 0xF16134U, 0x89F845U, - 0x0A8ADBU, 0x53153AU, 0x1806E5U, 0x03FF7CU, 0x6A7C0BU, 0x312692U, 0x399775U, 0x628CACU, 0x6D7FB3U, 0x34EE42U, - 0x5FF49DU, 0x56073CU, 0x8D1C67U, 0x87CDBBU, 0xDEE708U, 0xB574D5U, 0xA4ADB6U, 0xEF9E2BU, 0xF605D0U, 0xBD7545U, - 0xE6EE0EU, 0xCE39FBU, 0x950260U, 0xD8929DU, 0x43D9CEU, 0x086A47U, 0x31B3B1U, 0x7AA068U, 0x221ADFU, 0x294B86U, - 0x72F049U, 0x73E3F8U, 0x083927U, 0x418856U, 0x5AC3C9U, 0x105020U, 0xC969B7U, 0xE2BBEEU, 0xBF2019U, 0xB41181U, - 0xEFCA6AU, 0xA6FD3FU, 0xBC27A4U, 0xD53651U, 0xCE9D9AU, 0x854EA7U, 0xDC5E74U, 0xDFE5A9U, 0x26B61AU, 0x6C0D57U, - 0x77DCECU, 0x3EC639U, 0x2575C3U, 0x682CD6U, 0x13AF1DU, 0x1855ECU, 0x404473U, 0x4BDF8AU, 0x12ACDDU, 0xF93754U, - 0xE207A3U, 0xABD87AU, 0xF04B45U, 0xF03284U, 0xABB05BU, 0x80ABEBU, 0xD95AB4U, 0x92C10DU, 0x8FD2CEU, 0xC42833U, - 0xEC3920U, 0x37C2FDU, 0x7C5106U, 0x654883U, 0x2EAAF8U, 0x37B12DU, 0x5C20B6U, 0x065B42U, 0x07C909U, 0x5C12B4U, - 0x152367U, 0x2EB4FAU, 0x65CF19U, 0xFC5F40U, 0xB294FFU, 0xEBA72EU, 0xE03ED1U, 0x9B6CD0U, 0x92D70FU, 0xC944F6U, - 0x801D60U, 0x9AAE19U, 0xF1F4DEU, 0xA85547U, 0xAB4EB8U, 0x729DE9U, 0x792456U, 0x223697U, 0x4BED0CU, 0x55DE71U, - 0x1C03A2U, 0x07910FU, 0x4CAADCU, 0x356BA0U, 0x3E5033U, 0x67C3EEU, 0x2D9B05U, 0xB62810U, 0xFFF3EBU, 0xC4E03EU, - 0x8558A5U, 0xDE0B48U, 0xD5905BU, 0x8D71A2U, 0xA26A75U, 0xFBD8ECU, 0xB08982U, 0xAB1253U, 0xE2A1ECU, 0x79FB3FU, - 0x116E52U, 0x4A15C9U, 0x43861CU, 0x188FE7U, 0x537DF2U, 0x62E619U, 0x29D7C0U, 0x310C57U, 0x7A1F2EU, 0x25E5B8U, - 0xAC7451U, 0xC76F86U, 0xDE9C9FU, 0x959460U, 0xCF27B1U, 0xC6FC1EU, 0xBDEDCFU, 0xF416B0U, 0xEF0429U, 0xA49FEEU, - 0xBDEA17U, 0xFF7104U, 0x06A3F8U, 0x0D8A63U, 0x5219A6U, 0x5B62DDU, 0x00F348U, 0x6969B3U, 0x731A6EU, 0x38816DU, - 0x61D090U, 0x6A6343U, 0x33F9FEU, 0x18B8A5U, 0xC30340U, 0x8B10DAU, 0x98E80BU, 0xD1FB74U, 0xEA20F5U, 0xA5930AU, - 0xFC8E93U, 0xF75CC4U, 0xAF673DU, 0xA4E6BAU, 0xDF3D43U, 0x960F9CU, 0x0DD68DU, 0x44E572U, 0x1F7EB2U, 0x35AD09U, - 0x6C9554U, 0x6746A7U, 0x365D3AU, 0x7DFCF9U, 0x64A6C4U, 0x0B351FU, 0x118CEAU, 0x58DF61U, 0x836434U, 0x8A36CFU, - 0xF1AB5BU, 0xBA18A0U, 0xA343EDU, 0xE8C27EU, 0xF0F887U, 0xBB2B50U, 0xC03A69U, 0xC9C1A6U, 0x9A5317U, 0x9368C8U, - 0x5CB919U, 0x26A226U, 0x2F01EFU, 0x74D919U, 0x3DCA80U, 0x2631D7U, 0x6D223EU, 0x54BAA1U, 0x1E4950U, 0x47520BU, - 0x4CA79EU, 0x97BC75U, 0xBE3EA8U, 0xED479BU, 0xA4D446U, 0xBA4FF5U, 0xF13C39U, 0xE8A46AU, 0x83D7D7U, 0xDA4C0CU, - 0xD1DDF9U, 0x8AA7F2U, 0xC22427U, 0x793DDCU, 0x30CE45U, 0x2B5522U, 0x6007FBU, 0x39BE6CU, 0x32AD95U, 0x42560BU, - 0x4D426AU, 0x16D1B5U, 0x5F3A04U, 0x442BDBU, 0x2DF082U, 0xF6C225U, 0xFE59FCU, 0xA5880FU, 0xAEB312U, 0xF761C9U, - 0x9C582CU, 0x85CBB7U, 0xCE00C3U, 0xD43118U, 0x9DAB9DU, 0xEAF866U, 0xE3437BU, 0x381288U, 0x738955U, 0x6A3BF6U, - 0x2066ABU, 0x19D570U, 0x52DEC1U, 0x090E1EU, 0x00B5FFU, 0x5BE6E1U, 0x727D38U, 0x284CCFU, 0x639656U, 0xFA8531U, - 0xBD3CA8U, 0xD4EF77U, 0xCFC586U, 0x841489U, 0x9C0F78U, 0xD7BCA7U, 0x8E671EU, 0xA5774DU, 0xFE8481U, 0xF79F32U, - 0xAC0AEFU, 0x65F09CU, 0x5FF301U, 0x144ACAU, 0x0D193FU, 0x468224U, 0x13F0D1U, 0x18694AU, 0x63FA87U, 0x2B81F4U, - 0x30106DU, 0x790A9BU, 0xE2E952U, 0x8970CDU, 0xD003BCU, 0xDB9963U, 0x838AD2U, 0x88731DU, 0xD1E064U, 0xBAFFF3U, - 0xA10F2AU, 0xEC049DU, 0xBFD7D4U, 0xB7EE2BU, 0x4C7CBBU, 0x478760U, 0x1E9415U, 0x554D9EU, 0x4C7E6BU, 0x07E4B0U, - 0x3D35ADU, 0x741E4EU, 0x2F8D93U, 0x26FC20U, 0x7D667DU, 0x16B586U, 0x8B8E02U, 0xC91FD9U, 0xD0456CU, 0x9BF237U, - 0xC0EBCEU, 0xE92849U, 0xB29390U, 0xBBC3E7U, 0xE1787EU, 0xAA6B81U, 0x93B040U, 0xD8005FU, 0x411BAEU, 0x0AC870U, - 0x51F1D1U, 0x5D328EU, 0x362837U, 0x6799E0U, 0x6C4239U, 0x37711AU, 0x3EABC7U, 0x45BA3CU, 0x0D01A9U, 0x16D6F2U, - 0xDDCF17U, 0xC46D8CU, 0x8F3670U, 0xF6A723U, 0xFD5CBCU, 0xA74F5DU, 0xEAF582U, 0xF1A43BU, 0x903768U, 0x8B0CC5U, - 0xC0DC16U, 0x9957CBU, 0x1324F0U, 0x4ABD25U, 0x61AECEU, 0x38545AU, 0x73C701U, 0x68FEF4U, 0x212D6FU, 0x5B3382U, - 0x52C2D1U, 0x09494CU, 0x065ABFU, 0xDFA126U, 0x9CB149U, 0xA56A98U, 0xEE5927U, 0xF4C0F6U, 0xBD33B8U, 0xE62901U, - 0xCFB8D6U, 0x94D32FU, 0x9F40B8U, 0xC69AF1U, 0x8CAB0EU, 0x15309FU, 0x7E6360U, 0x21DA31U, 0x2848BAU, 0x733747U, - 0x72A6D4U, 0x08EDA8U, 0x435F7BU, 0x5A4CD6U, 0x119505U, 0x082658U, 0x433DE3U, 0xB8ED26U, 0xB0D6DDU, 0xEB05C8U, - 0xA2BC13U, 0xA9BEEAU, 0xD6656DU, 0xDF5614U, 0x848F82U, 0xC41C5BU, 0xDF26A4U, 0x94F7A5U, 0xADCC5AU, 0x665B8BU, - 0x3F1234U, 0x34A0EDU, 0x6E7BAAU, 0x076813U, 0x1CD1C4U, 0x55833DU, 0x4E1836U, 0x03A9E2U, 0x58F219U, 0x72418CU, - 0x2B09F7U, 0xA89A72U, 0xF1A1A9U, 0xBA7254U, 0x81EA47U, 0xC899BAU, 0xD20279U, 0x9B13C4U, 0xC0E09FU, 0xCB7E4BU, - 0xB25FF0U, 0xF98431U, 0xE4974EU, 0x2E6CD7U, 0x35FC00U, 0x5CE7A9U, 0x07147EU, 0x060D07U, 0x5D9F98U, 0x56E449U, - 0x0E65A6U, 0x659EB7U, 0x7C8D49U, 0x371790U, 0x6C6623U, 0xE5FD6EU, 0x9E6EBDU, 0x921600U, 0xC985D3U, 0x82DAEEU, - 0x9B7B25U, 0xD0E0F0U, 0xE1924BU, 0xAA091EU, 0xF158F5U, 0xF9E369U, 0x22F1BAU, 0x4B28C7U, 0x509B54U, 0x1B80BDU, - 0x024162U, 0x497B53U, 0x01A88CU, 0x3E1B5DU, 0x7502F2U, 0x6CD12BU, 0x27EB1CU, 0x7E7AC5U, 0xDDA113U, 0x8596BAU, - 0xCE5EEDU, 0xD54D14U, 0x9CF68BU, 0x87A54AU, 0xEE1C31U, 0xB58EA4U, 0xBFD55FU, 0xE66482U, 0xE93FA1U, 0x90AD7CU, - 0x5B04EFU, 0x405713U, 0x09CC48U, 0x13BFEDU, 0x522736U, 0x2914E3U, 0x22CFD8U, 0x7B5E05U, 0x3061E6U, 0x29B37FU, - 0x43BAA8U, 0x5849D1U, 0x91D25EU, 0xCEE0AFU, 0xC73971U, 0x9C2A40U, 0xB7919FU, 0xEF401EU, 0xA452E1U, 0xB5B9B8U, - 0xFEA80FU, 0x8533D6U, 0x8C4115U, 0xD7DA28U, 0x5F6BF3U, 0x043006U, 0x4FA39DU, 0x76DBD9U, 0x394C22U, 0x20C7BFU, - 0x6BB64CU, 0x312C41U, 0x187FB2U, 0x43C46FU, 0x0A55F4U, 0x192E81U, 0xD2BC4AU, 0xCBA5FBU, 0xA15624U, 0xF85DFDU, - 0xF38ECBU, 0xBA3602U, 0xA125F5U, 0xCEFE6CU, 0x97CF3BU, 0x9D55C2U, 0xC4A64DU, 0x4FBFBCU, 0x1468A3U, 0x7D4352U, - 0x6ED19DU, 0x270804U, 0x7D3B76U, 0x76A0ABU, 0x0FF018U, 0x0443D5U, 0x5D188EU, 0x16A93BU, 0x0932E0U, 0xC07015U, - 0xFACB1EU, 0xB39AC3U, 0xE80170U, 0xE3B3ADU, 0xBAEA5EU, 0xD17956U, 0xC042A9U, 0x8A9378U, 0x912DE7U, 0xD86E86U, - 0x83F559U, 0x2AC4E8U, 0x711F37U, 0x7A0D6EU, 0x26B4C9U, 0x6D6710U, 0x547CE7U, 0x1F8CFEU, 0x449720U, 0x4D3483U, - 0x16EF5AU, 0x1EFE2DU, 0x6D44B4U, 0xA6174BU, 0xBF8E8AU, 0xF4FD95U, 0xED6764U, 0x86D6BBU, 0xDC8912U, 0xD10A45U, - 0x8A799CU, 0x83E12AU, 0xF872F3U, 0xB10954U, 0xAA980DU, 0x6083D6U, 0x397163U, 0x3AE8B8U, 0x439BDDU, 0x481046U, - 0x1302BBU, 0x5AFB68U, 0x50E875U, 0x297396U, 0x26824AU, 0x7D98F1U, 0x344BA4U, 0xAF726FU, 0xE6F5DAU, 0x9C0F01U, - 0x971C38U, 0xCE85EFU, 0xC5F626U, 0x946D91U, 0xFFBDC8U, 0xE48637U, 0xAC15A6U, 0xB74C48U, 0x7EEE99U, 0x21B586U, - 0x0A0677U, 0x539FA8U, 0x18CC01U, 0x007652U, 0x4B67CFU, 0x70B43CU, 0x390FF1U, 0x625ECAU, 0x6BD01FU, 0x38E3C4U, - 0xB23870U, 0xCB893BU, 0x8093C6U, 0x994055U, 0xD679A8U, 0x8DAAFBU, 0xA4B176U, 0xFE018DU, 0xF7CA5CU, 0xACD963U, - 0xE762B2U, 0xFE323DU, 0x1589C4U, 0x0C5A92U, 0x4F432BU, 0x17F0ECU, 0x1CAA35U, 0x673B82U, 0x6E54DBU, 0x31C724U, - 0x785CA5U, 0x632C5AU, 0x29B70BU, 0x508490U, 0xDB5D6DU, 0x82CFEEU, 0x89B492U, 0xD22541U, 0xBB2EDCU, 0xA1DD27U, - 0xE04F62U, 0xFB56D9U, 0xB0A50CU, 0xF9BED7U, 0xC24EFAU, 0x8F5529U, 0x55C6D0U, 0x5E3B47U, 0x07383FU, 0x2CA2F0U, - 0x75D161U, 0x3E489EU, 0x25BB0FU, 0x6DA170U, 0x7630B1U, 0x174B2EU, 0x4CD8D7U, 0x470180U, 0x9E2339U, 0xD5B8FEU, - 0xE9EB27U, 0xA2521DU, 0xB941C8U, 0xF0BB23U, 0xAB2AB6U, 0xA271CDU, 0xD9C250U, 0xD3DC83U, 0x8A1D6EU, 0x41A67DU, - 0x58B580U, 0x3B6C5BU, 0x205ECEU, 0x6985A5U, 0x333471U, 0x3E27CAU, 0x65FD13U, 0x0CCE44U, 0x1747EDU, 0x5C143AU, - 0x45AF83U, 0x8F7F54U, 0xF6643DU, 0xFDD7A2U, 0xA68E73U, 0xAF3D8CU, 0xF4E79DU, 0xB5E073U, 0x8F59AAU, 0xC40A3DU, - 0x999044U, 0x922197U, 0xCB7A3AU, 0x60E9E1U, 0x3B90B4U, 0x73020FU, 0x6839DAU, 0x21FA71U, 0x3A632CU, 0x5151DFU, - 0x088A43U, 0x039B80U, 0x4260FDU, 0x18F36EU, 0x33EB97U, 0xEE1848U, 0xE503C9U, 0xBCA4B6U, 0xF7FC67U, 0xEC6FD8U, - 0x849C01U, 0x9F8506U, 0xD616FFU, 0x8D6C29U, 0x86FD90U, 0xFF26CFU, 0xF4150EU, 0x2C9EB1U, 0x6FEE60U, 0x74751BU, - 0x39E696U, 0x429F65U, 0x4B0DB8U, 0x1056ABU, 0x1AE756U, 0x43FC9DU, 0x282F29U, 0x318172U, 0x7A90E7U, 0xE36B1CU, - 0xA878D9U, 0xF2A0E2U, 0xDB133FU, 0x8008ECU, 0xC1D955U, 0xDAE292U, 0x9570EBU, 0xAC9B74U, 0xE68A85U, 0xBF514BU, - 0x34635AU, 0x6FFAA5U, 0x66A93CU, 0x1D12CBU, 0x54C382U, 0x4ED915U, 0x056AECU, 0x5C2D37U, 0x779402U, 0x2607C9U, - 0x2D5D1CU, 0x72ECA6U, 0xBAB7FBU, 0xA12408U, 0xC89C85U, 0xD3CF76U, 0x98542BU, 0xC177B8U, 0xCAAE45U, 0xB29CCEU, - 0xB9473BU, 0xE2D660U, 0xABEDF1U, 0xA03F1EU, 0x7926C4U, 0x1A95F1U, 0x044E2AU, 0x4D49FFU, 0x56B154U, 0x1FA209U, - 0x6419FAU, 0x6F4867U, 0x36D394U, 0x3C2199U, 0x653842U, 0x2EABB7U, 0x95C02CU, 0xDC525CU, 0x87CB93U, 0x8EB80AU, - 0xD423FDU, 0xF152A4U, 0xAAC003U, 0xE15BDAU, 0xF82A0DU, 0xB3B134U, 0xAAB3EBU, 0xC14C0AU, 0x1B5D95U, 0x128664U, - 0x49357AU, 0x002DA3U, 0x3BDE40U, 0x70C5DDU, 0x6954AEU, 0x23AE73U, 0x76ADE8U, 0x7D760DU, 0x064756U, 0x0FDCE3U, - 0xD40E38U, 0x9D37F5U, 0x87E4C6U, 0xECDF1AU, 0xB54EA9U, 0xBE1470U, 0xE7B71FU, 0xEC288EU, 0xB77951U, 0xDFC3A0U, - 0xC490BFU, 0x89095EU, 0x1ABA81U, 0x51E118U, 0x2853EFU, 0x234AB6U, 0x7B8910U, 0x703AC9U, 0x2B6216U, 0x62F127U, - 0x59CAECU, 0x101B59U, 0x4B2082U, 0xC1F2FFU, 0x88696CU, 0xB358A1U, 0xFA9752U, 0xAD844FU, 0xA63CB4U, 0xFFEF60U, - 0xF5F4EBU, 0x8C059EU, 0xC71F45U, 0xDCACF0U, 0x95772BU, 0x4E6622U, 0x67CDD5U, 0x3D9F0CU, 0x3406BBU, 0x6F75F2U, - 0x24EE0DU, 0x3D7E9CU, 0x520542U, 0x4396B3U, 0x09ADBCU, 0x527C45U, 0x5BF292U, 0xA0810BU, 0xE91878U, 0xF20BB5U, - 0xB9F10EU, 0xA1E0DBU, 0xEA33C0U, 0x938835U, 0x989BFEU, 0xC36342U, 0xCA6011U, 0x95FBECU, 0xFD0A6FU, 0x6E11B2U, - 0x25C3C1U, 0x3CFA5CU, 0x7769A7U, 0x0EB266U, 0x058079U, 0x5E1988U, 0x167E17U, 0x0DE5EFU, 0x44B428U, 0x7F0E31U, - 0x349DC6U, 0xEDC41FU, 0xE277A0U, 0xBA6DE1U, 0x99BE1EU, 0xC2178FU, 0x8B4450U, 0x90FF39U, 0xD9EFAAU, 0x823457U, - 0xA88785U, 0xF1DE98U, 0xFA4D73U, 0x3377E6U, 0x68A41DU, 0x43AD48U, 0x1A1AD3U, 0x14C836U, 0x4DF1EDU, 0x0622D0U, - 0x173903U, 0x7C88FEU, 0x27527DU, 0x2E41A5U, 0xF4FADAU, 0xFDBB4BU, 0x8601A4U, 0xCDD235U, 0xD4CB6AU, 0x9F7893U, - 0x862304U, 0xCCB3EDU, 0xB388BAU, 0xBA5B23U, 0xE1C0DCU, 0xE8A00DU, 0x3B3F27U, 0x500CF2U, 0x48D509U, 0x034694U, - 0x5A3CC7U, 0x51AD6AU, 0x0AB6B9U, 0x234544U, 0x785E57U, 0x30DE9AU, 0x2B2561U, 0x6036F4U, 0xDDCF8FU, 0x96DD5BU, - 0xCF46D0U, 0xCCB729U, 0x96A4FEU, 0xDF3FC7U, 0xE44D10U, 0xADC4F9U, 0xB61366U, 0xFD2837U, 0xA4B888U, 0x8EC359U, - 0x5750B6U, 0x5C49AFU, 0x07BA79U, 0x4A2080U, 0x517307U, 0x38DA7EU, 0x62C9ADU, 0x611230U, 0x38A2CBU, 0x33F98EU, - 0x4A4A35U, 0x0153E0U, 0x98815BU, 0xD23A06U, 0xD929C5U, 0x80E079U, 0xEBD7AAU, 0xF20D57U, 0xBD1C4CU, 0xE6A78DU, - 0xEF7472U, 0x954CE3U, 0x9CDF9CU, 0xCF8455U, 0x0437C2U, 0x1DFE3BU, 0x56EC6CU, 0x6F57D5U, 0x25061BU, 0x7E95AAU, - 0x772FF5U, 0x2C7C24U, 0x05C59BU, 0x5A965AU, 0x111D21U, 0x892DBCU, 0xC2F26FU, 0x9B6192U, 0xB81891U, 0xE38B6EU, - 0xEA91B6U, 0xB16221U, 0xF9FB48U, 0xC2C8DFU, 0x890226U, 0x9013F9U, 0xDBE848U, 0x02FB07U, 0x0D62D6U, 0x77906DU, - 0x3E8BB0U, 0x2538C3U, 0x6C614EU, 0x77F39CU, 0x141861U, 0x4D0D7AU, 0x47968FU, 0x1EE544U, 0x157DD1U, 0xCEEEAAU, - 0xA7953FU, 0xBC06D4U, 0xF57E09U, 0xABED3AU, 0xA2EEE3U, 0xD91734U, 0xD2849CU, 0x8BDEC3U, 0xC06F32U, 0xD174ADU, - 0x9BA77CU, 0x201C93U, 0x690C8AU, 0x22F77DU, 0x3BF4E4U, 0x702933U, 0x4B9B5AU, 0x0380C1U, 0x585134U, 0x556AEEU, - 0x0EF9CBU, 0x45A310U, 0x7C12CDU, 0xB7C97EU, 0xAFEA23U, 0xEC72C0U, 0xB7215DU, 0x9E9A8EU, 0xC50BF3U, 0xCC5068U, - 0x97E28DU, 0xDDB916U, 0xC42846U, 0xAF93B9U, 0xF2D020U, 0x796CC7U, 0x223F9EU, 0x2BA429U, 0x5095F0U, 0x18473FU, - 0x03DC8EU, 0x40EFD1U, 0x593620U, 0x1225BFU, 0x6BCF76U, 0x605E40U, 0xBA6599U, 0xF3B66AU, 0xE8AEF7U, 0x851DBCU, - 0x9EC649U, 0xD5D5D2U, 0x8C2C27U, 0x863E7CU, 0xDFB5D9U, 0xF4C002U, 0xA55BDFU, 0xEEE9ECU, 0x75B020U, 0x3C23D3U, - 0x06584AU, 0x4FCB15U, 0x1453A4U, 0x1F306BU, 0x42AB9AU, 0x09FA05U, 0x30415CU, 0x7A53ABU, 0x61AA22U, 0x2839D5U, - 0xF3228CU, 0xDAD032U, 0x89C9E3U, 0x820A2CU, 0xCAB91DU, 0x91A4C6U, 0x985673U, 0xE34DB8U, 0xA8DCE5U, 0xB52756U, - 0xFE358BU, 0xE6EE78U, 0x0DDF75U, 0x5654AFU, 0x5F075AU, 0x04BFC1U, 0x0D2CB4U, 0x56577FU, 0x34C6C2U, 0x2D9D11U, - 0x662F48U, 0x3FB4FFU, 0x34E536U, 0x4F4E89U, 0xC61C58U, 0x988107U, 0xD132A7U, 0xCA6978U, 0x81D881U, 0xB8C296U, - 0xF3114FU, 0xAA2AA8U, 0xA0FB31U, 0xF37142U, 0xDA429FU, 0x819B24U, 0x4888E1U, 0x5333FAU, 0x1AE30FU, 0x40D0D5U, - 0x6F0B68U, 0x36182BU, 0x3DA0F6U, 0x646345U, 0x2F7898U, 0x14CDF3U, 0x5C9666U, 0xC704BDU, 0x8E7F4CU, 0xDDEED3U, - 0xD655BAU, 0xAF062DU, 0xE49EF5U, 0xFDFD02U, 0xB7661BU, 0xA8F7F4U, 0xC18D25U, 0x9A1E9AU, 0x9305CBU, 0x48F414U, - 0x43EFB5U, 0x1B1D6AU, 0x708413U, 0x698780U, 0x2A7C4DU, 0x6168BFU, 0x78F3A2U, 0x130059U, 0x0B1BCCU, 0x40CA07U, - 0x1FF072U, 0x9663E9U, 0xCD9A14U, 0xE499C7U, 0xBF0AEAU, 0xF57239U, 0xECE1E4U, 0xA7BA5FU, 0xDE098FU, 0xD591E0U, - 0x86E271U, 0x8F79AEU, 0xD52817U, 0x1C8350U, 0x2711A9U, 0x684C3EU, 0x71FFE7U, 0x3AE490U, 0x633619U, 0x498FE6U, - 0x10DC37U, 0x1B670DU, 0x4066D8U, 0x09BC13U, 0x328FAEU, 0xFB16FDU, 0xA9C500U, 0xA2FF93U, 0xFB2C5EU, 0xF03565U, - 0x8D86B0U, 0xC65D4BU, 0xDD7DCEU, 0x95E615U, 0x8EB169U, 0xE708FAU, 0xBCDB03U, 0x37C1C4U, 0x6E72FDU, 0x25232AU, - 0x3DB8F3U, 0x5ECA4CU, 0x45430DU, 0x0CF0B2U, 0x57AB61U, 0x5E3ABCU, 0x210087U, 0x2BD343U, 0xF248B8U, 0xB9392DU, - 0xA0A376U, 0xEBB09FU, 0x905908U, 0x99CAF1U, 0xD3F5A6U, 0xCA251FU, 0x813ED0U, 0xF2CD01U, 0xFBD63EU, 0xA046EEU, - 0x29BD51U, 0x76AE98U, 0x3C274FU, 0x055476U, 0x4ECEA5U, 0x573F58U, 0x1C24DBU, 0x47B786U, 0x6ECC7DU, 0x345CE8U, - 0x7D0703U, 0x66B456U, 0xAF3DECU, 0xBC6F31U, 0xD7D0A2U, 0x8EC1CFU, 0x80321CU, 0xD9A9A1U, 0xD2FB7AU, 0xA9422BU, - 0xE05184U, 0xFB8A55U, 0xB22AAAU, 0xE831B3U, 0x63E264U, 0x1ADB8CU, 0x11081BU, 0x4832E2U, 0x0BA1BDU, 0x10781CU, - 0x784BC3U, 0x679052U, 0x2E902DU, 0x752BFCU, 0x7EFC57U, 0x27C58AU, 0xCC57D9U, 0xD40C64U, 0x9FBFB6U, 0x84665BU, - 0xCD7540U, 0xB6CF95U, 0xBF8E6EU, 0xE415FBU, 0xE62690U, 0xBFFE0DU, 0xF04DFEU, 0xC91623U, 0x028520U, 0x19BCD9U, - 0x506E06U, 0x0AEDB6U, 0x23D4E9U, 0x780728U, 0x331997U, 0x3AE84EU, 0x6173B9U, 0x6840A0U, 0x129B67U, 0x598B9EU, - 0xC87009U, 0x877370U, 0x9EEAEBU, 0xF5190EU, 0xAC03D4U, 0xA690C1U, 0xFDE93AU, 0xB47AF7U, 0xAF8044U, 0xC69119U, - 0xDD0ACAU, 0x166977U, 0x4EF0BCU, 0x45E2C9U, 0x3C1D52U, 0x3F8E87U, 0x64D73CU, 0x296574U, 0x327E83U, 0x7A8F1AU, - 0x0114EDU, 0x0A1734U, 0x53EF3BU, 0xD8FCCAU, 0x812715U, 0xEA94A4U, 0xF185EBU, 0xB95F3AU, 0xA26C85U, 0xEBB55CU, - 0xB0862AU, 0x930CA3U, 0xCEDD70U, 0x85E6CDU, 0x9D7196U, 0x562A63U, 0x6D9AE8U, 0x24411DU, 0x7F5246U, 0x76EBDBU, - 0x2DB928U, 0x2712E5U, 0x5E83D7U, 0x15D80AU, 0x0C6BD1U, 0x473170U, 0x54A02FU, 0xB99B9EU, 0xE34841U, 0xEAD090U, - 0xB1E33FU, 0xFA2866U, 0xE31991U, 0x88C208U, 0x8154FFU, 0xDB6FB7U, 0x92BE28U, 0x89A5D9U, 0xE25606U, 0x7BCE37U, - 0x30FDFCU, 0x693E21U, 0x6F2792U, 0x3495CFU, 0x5DCE6CU, 0x465DB1U, 0x0FA46AU, 0x14B75FU, 0x5F2D85U, 0x275C60U, - 0x2CC7FBU, 0xF56486U, 0xFE3C55U, 0xA5ABC8U, 0xECD02BU, 0xD743F2U, 0x9FDAC5U, 0xC0A81CU, 0xC33383U, 0x9A2262U, - 0xB1D93DU, 0xE8DA8DU, 0x232252U, 0x39B19BU, 0x70AAACU, 0x6B5975U, 0x024182U, 0x59921BU, 0x522974U, 0x0B38A5U, - 0x01F33EU, 0x78C1CBU, 0x3758D0U, 0x242F3DU, 0xEDB4EFU, 0xB66672U, 0xBF5701U, 0xC5CCDCU, 0xCE9F77U, 0x9726A2U, - 0xDCA4F9U, 0xC5FF4CU, 0xAE4E87U, 0xB51576U, 0xFDA7E9U, 0xA63C90U, 0x2F6D47U, 0x74D6CFU, 0x1BC538U, 0x0A1D21U, - 0x413EDEU, 0x58E50FU, 0x127480U, 0x6B4BF1U, 0x60992EU, 0x2BA297U, 0x327340U, 0x79E809U, 0xA0DABAU, 0x8A0367U, - 0xD1009DU, 0x98BB98U, 0x836A63U, 0xCE70F6U, 0xF5832DU, 0xB69850U, 0xEE29D3U, 0xE5732EU, 0xBCE0FDU, 0xB75962U, - 0x4C1A13U, 0x0589DCU, 0x1EF165U, 0x5666B7U, 0x4DFDEAU, 0x268E59U, 0x7F1794U, 0x74256FU, 0x29FE7AU, 0x626F81U, - 0x700404U, 0x1996DFU, 0x828FA2U, 0xCB7C31U, 0x9067CCU, 0x9B940EU, 0xE20C17U, 0xE81FE8U, 0xB1E439U, 0xFAF586U, - 0xE17FC7U, 0xA88C18U, 0xD397A1U, 0x5E4276U, 0x04794FU, 0x0FEB88U, 0x5E9271U, 0x3501E6U, 0x2C9A3EU, 0x67EA51U, - 0x7C61C0U, 0x34323BU, 0x6F89EEU, 0x4618F5U, 0x1D4218U, 0xD4F1CBU, 0xCFE876U, 0x841B25U, 0xB888F8U, 0xF3D053U, - 0xAA7386U, 0xA168BCU, 0xF2BB69U, 0xFB8792U, 0x80541FU, 0xC8CF4CU, 0xC3FEB5U, 0x182522U, 0x1117CBU, 0x6A9E9CU, - 0x234D05U, 0x3876FAU, 0x72A42BU, 0x2FBD84U, 0x240ED4U, 0x5DD54BU, 0x56C4B2U, 0x057E65U, 0x4C2D4CU, 0xD7849BU, - 0xBFD762U, 0xA44DF9U, 0xEFFEACU, 0xB6A347U, 0xBD30D2U, 0xC40B29U, 0x8FDB74U, 0x9540E6U, 0xDC330BU, 0xC3BAD8U, - 0x8A89E5U, 0x71533EU, 0x7AC0BBU, 0x2BB140U, 0x212A11U, 0x7838AEU, 0x13C17FU, 0x08D290U, 0x414989U, 0x1AA85EU, - 0x13B2A6U, 0x494131U, 0x625AD8U, 0xBBCF87U, 0xF43516U, 0xED26E9U, 0xA6BF78U, 0x9FCC17U, 0xDD57CEU, 0x86B75DU, - 0x8FACA0U, 0xD43FE3U, 0x9D445EU, 0xA6D584U, 0x6DCF71U, 0x753C6AU, 0x3EA5AFU, 0x67F654U, 0x4C4CC9U, 0x134DBAU, - 0x1AB667U, 0x4125E4U, 0x097E19U, 0x12CA0AU, 0x71D1F3U, 0x78022CU, 0xA33BACU, 0xEAA953U, 0xF17A02U, 0x9B53BDU, - 0xC28074U, 0xC9BB83U, 0x90299AU, 0x9BF04DU, 0xC4C3B4U, 0xAD583BU, 0xB7084AU, 0xFEB3D1U, 0x656004U, 0x2E69FEU, - 0x5FDAF3U, 0x548000U, 0x0D37DDU, 0x472E4EU, 0x5CFD33U, 0x1546F8U, 0x2E164DU, 0x678D96U, 0x3CBEE3U, 0x337768U, - 0xEBE5BDU, 0xC09E47U, 0x990D5EU, 0xD234A9U, 0xC9E720U, 0x887DF7U, 0xD34C0EU, 0xFB9711U, 0xA084E0U, 0xA96C2FU, - 0xF27FBEU, 0xB9E4C1U, 0x001318U, 0x4B02AFU, 0x56B867U, 0x1CEB30U, 0x477289U, 0x4E8152U, 0x358AF7U, 0x3C1AACU, - 0x676159U, 0x24F2C2U, 0x3C6917U, 0x57197CU, 0x8E82E1U, 0x85F112U, 0xDE68CFU, 0xD77BDDU, 0x8C9130U, 0xE400EBU, - 0xFB5B5EU, 0xB0E885U, 0xA9F6D4U, 0xE2277BU, 0x9B9CA2U, 0x108F15U, 0x5A764CU, 0x0B64ABU, 0x00AF32U, 0x599CEDU, - 0x72059DU, 0x29D702U, 0x60ECE3U, 0x7A7D3CU, 0x330625U, 0x0C95D6U, 0x474D0BU, 0x9E7EA8U, 0x95FDF5U, 0xCCA666U, - 0x86179BU, 0xBD8D40U, 0xFCDA65U, 0xE763BFU, 0xAE304AU, 0xF58AD1U, 0xDE9B9CU, 0x86406FU, 0x8DE3F2U, 0x54B801U, - 0x1B28D8U, 0x0213D7U, 0x69C026U, 0x7259B9U, 0x3A6B48U, 0x61B017U, 0x68819FU, 0x135A68U, 0x50D9B1U, 0x49E386U, - 0x02325FU, 0x9A29B0U, 0xD19E23U, 0xAAC77EU, 0xA3558DU, 0xFCAE04U, 0xF5BFF3U, 0xAE04AAU, 0xC44635U, 0xDDDDC5U, - 0x966C4AU, 0xCF373BU, 0xC4A4E4U, 0x1FD47DU, 0x3E4F8AU, 0x64DC43U, 0x2DA574U, 0x3637ADU, 0x7D5C56U, 0x44CFC3U, - 0x0BD688U, 0x52257DU, 0x59BBE7U, 0x03AA1AU, 0x4A5119U, 0xF142C4U, 0xB89A37U, 0xB329AAU, 0xE822D1U, 0xA9D114U, - 0x93C88FU, 0xDA5A7AU, 0xC1A121U, 0x8AB090U, 0xD36B5EU, 0xDC58A7U, 0xA5C0B0U, 0x2F8369U, 0x74389EU, 0x3DAB17U, - 0x26D368U, 0x4F40F9U, 0x141F26U, 0x1DAEC7U, 0x473558U, 0x446721U, 0x1DDEF6U, 0x769D6EU, 0xEF0E8DU, 0xA434D0U, - 0xBFE56BU, 0xF35EBEU, 0x884D45U, 0x819440U, 0xDAA69BU, 0x917D26U, 0x88ECF5U, 0xC3C788U, 0xFB150BU, 0xB02ED6U, - 0x63BF24U, 0x6A6439U, 0x3153D2U, 0x188B03U, 0x43989CU, 0x0923EDU, 0x147232U, 0x5FF99BU, 0x060B4CU, 0x2D10B5U, - 0x76A1A2U, 0x7FFA7BU, 0xA568D4U, 0xECD104U, 0xD7827BU, 0x9C19EAU, 0x8D6831U, 0xC6E2DCU, 0x9F71CFU, 0x950A32U, - 0xEE9BE1U, 0xA3A16CU, 0xB8761FU, 0xF16FC2U, 0x6A9C79U, 0x010FACU, 0x491786U, 0x52F453U, 0x1BEF88U, 0x007C35U, - 0x4B8566U, 0x32978FU, 0x316C18U, 0x697DC1U, 0x62E6BEU, 0x3B142FU, 0xD40DC0U, 0xCFCE11U, 0x86F58EU, 0xDD66F6U, - 0xD53E31U, 0x8E8988U, 0xA5125FU, 0xFC6366U, 0xB7F9B9U, 0xAEAA78U, 0xE513C3U, 0xD69096U, 0x1ECB6DU, 0x4579F8U, - 0x4C6033U, 0x13B34EU, 0x5888DCU, 0x615821U, 0x2AE3F2U, 0x32F0FFU, 0x792B04U, 0x220A91U, 0x0B906AU, 0xD0432BU, - 0xD97294U, 0x82AD4DU, 0xC8BE9AU, 0xD90623U, 0xB2D564U, 0xEBEE9CU, 0xE02D03U, 0xBF35D2U, 0xB686ADU, 0xCCDD2CU, - 0x854CD3U, 0x1EF70AU, 0x55A51DU, 0x4C1CE4U, 0x074F67U, 0x7ED49AU, 0x7476C9U, 0x2F2F75U, 0x26BCBEU, 0x75876BU, - 0x1C5650U, 0x07C885U, 0x48BB7EU, 0x9022F3U, 0x9B11A0U, 0xC2CA5DU, 0xE9C8CEU, 0xA07133U, 0xFBA238U, 0xF0B9E9U, - 0xA84917U, 0x835286U, 0xDAC179U, 0x913830U, 0x822B87U, 0x4BD95EU, 0x30D289U, 0x3C43A0U, 0x67B87FU, 0x6CAA8EU, - 0x353311U, 0x7E4440U, 0x47DFABU, 0x0C8E3FU, 0x1634C4U, 0x5FA7D9U, 0x04CC0AU, 0xAD5DE7U, 0xF64774U, 0xBDB409U, - 0xAC2DD2U, 0xE67E67U, 0xFBC5ACU, 0x90D5F9U, 0xCB0E42U, 0xC23D9FU, 0x99B67DU, 0x9047E4U, 0xEA5DB3U, 0x218E0AU, - 0x38B7D5U, 0x732034U, 0x6AFA2BU, 0x21CBFAU, 0x5A1005U, 0x5B039CU, 0x01A8FBU, 0x4C7822U, 0x574395U, 0x3CD04DU, - 0xA5811AU, 0xEE3BB3U, 0xB76868U, 0xBDF19DU, 0xE64286U, 0xCF1943U, 0x949BF8U, 0xDDA225U, 0xC67156U, 0x8FCACBU, - 0xF59B08U, 0xF605F5U, 0x2B36EFU, 0x20EF1AU, 0x797CC1U, 0x324664U, 0x1985BFU, 0x419CE4U, 0x4A6F51U, 0x13748AU, - 0x58C42FU, 0x631F74U, 0x2A0CA1U, 0x71F51AU, 0xF9E7D7U, 0xA27CA5U, 0xA99F38U, 0xD886EBU, 0x973516U, 0x8E6F1DU, - 0xC5FEECU, 0xDF0133U, 0xB61282U, 0xED8ADDU, 0xE4F954U, 0xBF7AA3U, 0x74617AU, 0x6D904DU, 0x070A95U, 0x1E795AU, - 0x55E0EBU, 0x0EF334U, 0x0F0845U, 0x7098CAU, 0x798313U, 0x2360E0U, 0x687BFDU, 0x71AB0EU, 0xBA10C3U, 0x830370U, - 0xC8FA2DU, 0x93EDB7U, 0x9B3742U, 0xC00689U, 0xA99DBCU, 0xB25E67U, 0xF964BAU, 0xE0F509U, 0xA7AE44U, 0xFF1DB7U, - 0x54C42EU, 0x0DF6F1U, 0x066D90U, 0x5D3C0EU, 0x1487FFU, 0x2F8460U, 0x675E19U, 0x3CEFDEU, 0x37B447U, 0x6E27B0U, - 0x651369U, 0x9CC856U, 0xD77B97U, 0xC9604CU, 0x88B1F9U, 0x939BA2U, 0xFA4856U, 0xB1D1DDU, 0xAAE200U, 0xE33873U, - 0xB829EEU, 0xB0D20DU, 0xCBC190U, 0x407AEBU, 0x19AA3EU, 0x52A1A5U, 0x4B1240U, 0x204B1BU, 0x3ED9A2U, 0x7F2274U, - 0x2437ADU, 0x2DAC8AU, 0x76DF53U, 0x5D45ACU, 0x04F43DU, 0xCEBFE2U, 0xD72CC3U, 0x9C551CU, 0xE7C7E5U, 0xEEDC72U, - 0xB52D1BU, 0xBCB6CCU, 0xE6A454U, 0xA95FA7U, 0x904EFAU, 0xD3A551U, 0xCA3684U, 0x01265FU, 0x5ADD6AU, 0x72CEB1U, - 0x29135CU, 0x60A1CFU, 0x7BBA92U, 0x304921U, 0x2950FCU, 0x42D316U, 0x1AA903U, 0x1138F8U, 0x48E329U, 0xC7D0A6U, - 0xBC48DFU, 0xFD1B08U, 0xE6A0B1U, 0xAE3366U, 0xF55AAFU, 0xFEC898U, 0x879341U, 0x8C22FEU, 0xD5392EU, 0x9EEA61U, - 0x8456D0U, 0x6D450BU, 0x769EF6U, 0x3FADE5U, 0x606508U, 0x6BD6DBU, 0x3ACD46U, 0x101C3DU, 0x5927F8U, 0x02F543U, - 0x096C96U, 0x505FCCU, 0xBB8C71U, 0xA296B2U, 0xE8370FU, 0xF36C5CU, 0xBADF85U, 0xE1063AU, 0xC814FBU, 0x97AF04U, - 0x9CFA15U, 0xC461EAU, 0x87D23BU, 0xBE88B4U, 0x7509CCU, 0x2E721BU, 0x27E1A2U, 0x7C5965U, 0x750A7CU, 0x0F9183U, - 0x44A052U, 0x5D7BE9U, 0x1669ACU, 0x0F9277U, 0x6013CAU, 0x3B0819U, 0xB3FA65U, 0xE0E3E6U, 0xA9103BU, 0xB28BC0U, - 0xDB9ED5U, 0xC0642EU, 0x8B77EBU, 0xD3EC50U, 0xD80D89U, 0xA1179EU, 0xAAC477U, 0xF1F5A0U, 0x386E19U, 0x271D4FU, - 0x6F8596U, 0x541639U, 0x1F6DE8U, 0x4EFE97U, 0x45B706U, 0x1C05D9U, 0x779E30U, 0x6DCF27U, 0x2474DEU, 0x3F664DU, - 0xF69BB0U, 0xAD08FBU, 0x86536FU, 0xDFE094U, 0xD1E841U, 0x883B6AU, 0xC300B7U, 0xE8D164U, 0xB16BD9U, 0xF2788AU, - 0xEBA167U, 0xA192FCU, 0x3A0929U, 0x53DBD2U, 0x08F2C3U, 0x01212DU, 0x5A3ABCU, 0x518B43U, 0x29D11AU, 0x62628DU, - 0x7FFD64U, 0x34ACB3U, 0x6F1E8AU, 0xE64555U, 0x95C494U, 0x9D7F2BU, 0xC62C7AU, 0x8DB485U, 0x94871DU, 0xFF5CDEU, - 0xE6EFE3U, 0xADB730U, 0xF524CFU, 0xFE0F56U, 0xA5DE31U, 0x48C5E8U, 0x53377FU, 0x1AAE86U, 0x01BD59U, 0x4B4678U, - 0x3A50A7U, 0x31E977U, 0x683ACCU, 0x633189U, 0x38C072U, 0x71DAEFU, 0x4B493CU, 0x82B001U, 0x99A3C2U, 0xD2383FU, - 0x8F4AA4U, 0xA4D3D1U, 0xFDA00AU, 0xB62B8FU, 0xACBB75U, 0xE5C028U, 0xF6539BU, 0x9F4242U, 0xC4B985U, 0x4F2FBCU, - 0x167463U, 0x1CC5D2U, 0x65DE1DU, 0x2E3C4CU, 0x35A5F3U, 0x78F622U, 0x234DDDU, 0x0A5C55U, 0x408622U, 0x5BB5FBU, - 0x122E6CU, 0xC1FF95U, 0xC8C4DEU, 0xB3066BU, 0xB83FB0U, 0xE0AC25U, 0xAB775EU, 0xB24793U, 0xD9DC20U, 0x828BFDU, - 0x8F30AFU, 0xD46102U, 0xDCDBD9U, 0x07582CU, 0x6E0137U, 0x75B2C6U, 0x3EE809U, 0x2F7990U, 0x64C2E7U, 0x1C913EU, - 0x170A89U, 0x4C3A40U, 0x45E9D6U, 0x1E42AFU, 0x571370U, 0xE889C1U, 0xA2BA0EU, 0xFB635FU, 0xF070E0U, 0xA9CF39U, - 0x821DDAU, 0xD904C7U, 0x90F734U, 0x82FCE9U, 0xCB4D72U, 0xD09716U, 0x3B848DU, 0x623D78U, 0x696EA3U, 0x30F4BEU, - 0x7A075DU, 0x451E80U, 0x0C8D33U, 0x17E66EU, 0x5E76B5U, 0x050D14U, 0x0E9ECBU, 0x7607BAU, 0xF57524U, 0xACEAC5U, - 0xE7F91AU, 0xFC0083U, 0x9583F4U, 0xCED96DU, 0xC6688AU, 0x9D7353U, 0x92804CU, 0xCB11BDU, 0xA00B62U, 0xA9F8C3U, - 0x72E398U, 0x783244U, 0x2118F7U, 0x4A8B2AU, 0x5B5249U, 0x1061D4U, 0x09FA2FU, 0x428ABAU, 0x1911F1U, 0x31C604U, - 0x6AFD9FU, 0x276D62U, 0xBC2631U, 0xF795B8U, 0xCE4C4EU, 0x855F97U, 0xDDE520U, 0xD6B479U, 0x8D0FB6U, 0x8C1C07U, - 0xF7C6D8U, 0xBE77A9U, 0xA53C36U, 0xEFAFDFU, 0x369648U, 0x1D4411U, 0x40DFE6U, 0x4BEE7EU, 0x103595U, 0x5902C0U, - 0x43D85BU, 0x2AC9AEU, 0x316265U, 0x7AB158U, 0x23A18BU, 0x201A56U, 0xD949E5U, 0x93F2A8U, 0x882313U, 0xC139C6U, - 0xDA8A3CU, 0x97D329U, 0xEC50E2U, 0xE7AA13U, 0xBFBB8CU, 0xB42075U, 0xED5322U, 0x06C8ABU, 0x1DF85CU, 0x542785U, - 0x0FB4BAU, 0x0FCD7BU, 0x544FA4U, 0x7F5414U, 0x26A54BU, 0x6D3EF2U, 0x702D31U, 0x3BD7CCU, 0x13C6DFU, 0xC83D02U, - 0x83AEF9U, 0x9AB77CU, 0xD15507U, 0xC84ED2U, 0xA3DF49U, 0xF9A4BDU, 0xF836F6U, 0xA3ED4BU, 0xEADC98U, 0xD14B05U, - 0x9A30E6U, 0x03A0BFU, 0x4D6B00U, 0x1458D1U, 0x1FC12EU, 0x64932FU, 0x6D28F0U, 0x36BB09U, 0x7FE29FU, 0x6551E6U, - 0x0E0B21U, 0x57AAB8U, 0x54B147U, 0x8D6216U, 0x86DBA9U, 0xDDC968U, 0xB412F3U, 0xAA218EU, 0xE3FC5DU, 0xF86EF0U, - 0xB35523U, 0xCA945FU, 0xC1AFCCU, 0x983C11U, 0xD264FAU, 0x49D7EFU, 0x000C14U, 0x3B1FC1U, 0x7AA75AU, 0x21F4B7U, - 0x2A6FA4U, 0x728E5DU, 0x5D958AU, 0x042713U, 0x4F767DU, 0x54EDACU, 0x1D5E13U, 0x8604C0U, 0xEE91ADU, 0xB5EA36U, - 0xBC79E3U, 0xE77018U, 0xAC820DU, 0x9D19E6U, 0xD6283FU, 0xCEF3A8U, 0x85E0D1U, 0xDA1A47U, 0x538BAEU, 0x389079U, - 0x216360U, 0x6A6B9FU, 0x30D84EU, 0x3903E1U, 0x421230U, 0x0BE94FU, 0x10FBD6U, 0x5B6011U, 0x4215E8U, 0x008EFBU, - 0xF95C07U, 0xF2759CU, 0xADE659U, 0xA49D22U, 0xFF0CB7U, 0x96964CU, 0x8CE591U, 0xC77E92U, 0x9E2F6FU, 0x959CBCU, - 0xCC0601U, 0xE7475AU, 0x3CFCBFU, 0x74EF25U, 0x6717F4U, 0x2E048BU, 0x15DF0AU, 0x5A6CF5U, 0x03716CU, 0x08A33BU, - 0x5098C2U, 0x5B1945U, 0x20C2BCU, 0x69F063U, 0xF22972U, 0xBB1A8DU, 0xE0814DU, 0xCA52F6U, 0x936AABU, 0x98B958U, - 0xC9A2C5U, 0x820306U, 0x9B593BU, 0xF4CAE0U, 0xEE7315U, 0xA7209EU, 0x7C9BCBU, 0x75C930U, 0x0E54A4U, 0x45E75FU, - 0x5CBC12U, 0x173D81U, 0x0F0778U, 0x44D4AFU, 0x3FC596U, 0x363E59U, 0x65ACE8U, 0x6C9737U, 0xA346E6U, 0xD95DD9U, - 0xD0FE10U, 0x8B26E6U, 0xC2357FU, 0xD9CE28U, 0x92DDC1U, 0xAB455EU, 0xE1B6AFU, 0xB8ADF4U, 0xB35861U, 0x68438AU, - 0x41C157U, 0x12B864U, 0x5B2BB9U, 0x45B00AU, 0x0EC3C6U, 0x175B95U, 0x7C2828U, 0x25B3F3U, 0x2E2206U, 0x75580DU, - 0x3DDBD8U, 0x86C223U, 0xCF31BAU, 0xD4AADDU, 0x9FF804U, 0xC64193U, 0xCD526AU, 0xBDA9F4U, 0xB2BD95U, 0xE92E4AU, - 0xA0C5FBU, 0xBBD424U, 0xD20F7DU, 0x093DDAU, 0x01A603U, 0x5A77F0U, 0x514CEDU, 0x089E36U, 0x63A7D3U, 0x7A3448U, - 0x31FF3CU, 0x2BCEE7U, 0x625462U, 0x150799U, 0x1CBC84U, 0xC7ED77U, 0x8C76AAU, 0x95C409U, 0xDF9954U, 0xE62A8FU, - 0xAD213EU, 0xF6F1E1U, 0xFF4A00U, 0xA4191EU, 0x8D82C7U, 0xD7B330U, 0x9C69A9U, 0x057ACEU, 0x42C357U, 0x2B1088U, - 0x303A79U, 0x7BEB76U, 0x63F087U, 0x284358U, 0x7198E1U, 0x5A88B2U, 0x017B7EU, 0x0860CDU, 0x53F510U, 0x9A0F63U, - 0xA00CFEU, 0xEBB535U, 0xF2E6C0U, 0xB97DDBU, 0xEC0F2EU, 0xE796B5U, 0x9C0578U, 0xD47E0BU, 0xCFEF92U, 0x86F564U, - 0x1D16ADU, 0x768F32U, 0x2FFC43U, 0x24669CU, 0x7C752DU, 0x778CE2U, 0x2E1F9BU, 0x45000CU, 0x5EF0D5U, 0x13FB62U, - 0x40282BU, 0x4811D4U, 0xB38344U, 0xB8789FU, 0xE16BEAU, 0xAAB261U, 0xB38194U, 0xF81B4FU, 0xC2CA52U, 0x8BE1B1U, - 0xD0726CU, 0xD903DFU, 0x829982U, 0xE94A79U, 0x7471FDU, 0x36E026U, 0x2FBA93U, 0x640DC8U, 0x3F1431U, 0x16D7B6U, - 0x4D6C6FU, 0x443C18U, 0x1E8781U, 0x55947EU, 0x6C4FBFU, 0x27FFA0U, 0xBEE451U, 0xF5378FU, 0xAE0E2EU, 0xA2CD71U, - 0xC9D7C8U, 0x98661FU, 0x93BDC6U, 0xC88EE5U, 0xC15438U, 0xBA45C3U, 0xF2FE56U, 0xE9290DU, 0x2230E8U, 0x3B9273U, - 0x70C98FU, 0x0958DCU, 0x02A343U, 0x58B0A2U, 0x150A7DU, 0x0E5BC4U, 0x6FC897U, 0x74F33AU, 0x3F23E9U, 0x66A834U, - 0xECDB0FU, 0xB542DAU, 0x9E5131U, 0xC7ABA5U, 0x8C38FEU, 0x97010BU, 0xDED290U, 0xA4CC7DU, 0xAD3D2EU, 0xF6B6B3U, - 0xF9A540U, 0x205ED9U, 0x634EB6U, 0x5A9567U, 0x11A6D8U, 0x0B3F09U}; +const unsigned int PRNG_TABLE[] = +{ + 0x42CC47U, 0x19D6FEU, 0x304729U, 0x6B2CD0U, 0x60BF47U, 0x39650EU, 0x7354F1U, 0xEACF60U, 0x819C9FU, 0xDE25CEU, + 0xD7B745U, 0x8CC8B8U, 0x8D592BU, 0xF71257U, 0xBCA084U, 0xA5B329U, 0xEE6AFAU, 0xF7D9A7U, 0xBCC21CU, 0x4712D9U, + 0x4F2922U, 0x14FA37U, 0x5D43ECU, 0x564115U, 0x299A92U, 0x20A9EBU, 0x7B707DU, 0x3BE3A4U, 0x20D95BU, 0x6B085AU, + 0x5233A5U, 0x99A474U, 0xC0EDCBU, 0xCB5F12U, 0x918455U, 0xF897ECU, 0xE32E3BU, 0xAA7CC2U, 0xB1E7C9U, 0xFC561DU, + 0xA70DE6U, 0x8DBE73U, 0xD4F608U, 0x57658DU, 0x0E5E56U, 0x458DABU, 0x7E15B8U, 0x376645U, 0x2DFD86U, 0x64EC3BU, + 0x3F1F60U, 0x3481B4U, 0x4DA00FU, 0x067BCEU, 0x1B68B1U, 0xD19328U, 0xCA03FFU, 0xA31856U, 0xF8EB81U, 0xF9F2F8U, + 0xA26067U, 0xA91BB6U, 0xF19A59U, 0x9A6148U, 0x8372B6U, 0xC8E86FU, 0x9399DCU, 0x1A0291U, 0x619142U, 0x6DE9FFU, + 0x367A2CU, 0x7D2511U, 0x6484DAU, 0x2F1F0FU, 0x1E6DB4U, 0x55F6E1U, 0x0EA70AU, 0x061C96U, 0xDD0E45U, 0xB4D738U, + 0xAF64ABU, 0xE47F42U, 0xFDBE9DU, 0xB684ACU, 0xFE5773U, 0xC1E4A2U, 0x8AFD0DU, 0x932ED4U, 0xD814E3U, 0x81853AU, + 0x225EECU, 0x7A6945U, 0x31A112U, 0x2AB2EBU, 0x630974U, 0x785AB5U, 0x11E3CEU, 0x4A715BU, 0x402AA0U, 0x199B7DU, + 0x16C05EU, 0x6F5283U, 0xA4FB10U, 0xBFA8ECU, 0xF633B7U, 0xEC4012U, 0xADD8C9U, 0xD6EB1CU, 0xDD3027U, 0x84A1FAU, + 0xCF9E19U, 0xD64C80U, 0xBC4557U, 0xA7B62EU, 0x6E2DA1U, 0x311F50U, 0x38C68EU, 0x63D5BFU, 0x486E60U, 0x10BFE1U, + 0x5BAD1EU, 0x4A4647U, 0x0157F0U, 0x7ACC29U, 0x73BEEAU, 0x2825D7U, 0xA0940CU, 0xFBCFF9U, 0xB05C62U, 0x892426U, + 0xC6B3DDU, 0xDF3840U, 0x9449B3U, 0xCED3BEU, 0xE7804DU, 0xBC3B90U, 0xF5AA0BU, 0xE6D17EU, 0x2D43B5U, 0x345A04U, + 0x5EA9DBU, 0x07A202U, 0x0C7134U, 0x45C9FDU, 0x5EDA0AU, 0x310193U, 0x6830C4U, 0x62AA3DU, 0x3B59B2U, 0xB04043U, + 0xEB975CU, 0x82BCADU, 0x912E62U, 0xD8F7FBU, 0x82C489U, 0x895F54U, 0xF00FE7U, 0xFBBC2AU, 0xA2E771U, 0xE956C4U, + 0xF6CD1FU, 0x3F8FEAU, 0x0534E1U, 0x4C653CU, 0x17FE8FU, 0x1C4C52U, 0x4515A1U, 0x2E86A9U, 0x3FBD56U, 0x756C87U, + 0x6ED218U, 0x279179U, 0x7C0AA6U, 0xD53B17U, 0x8EE0C8U, 0x85F291U, 0xD94B36U, 0x9298EFU, 0xAB8318U, 0xE07301U, + 0xBB68DFU, 0xB2CB7CU, 0xE910A5U, 0xE101D2U, 0x92BB4BU, 0x59E8B4U, 0x407175U, 0x0B026AU, 0x12989BU, 0x792944U, + 0x2376EDU, 0x2EF5BAU, 0x758663U, 0x7C1ED5U, 0x078D0CU, 0x4EF6ABU, 0x5567F2U, 0x9F7C29U, 0xC68E9CU, 0xC51747U, + 0xBC6422U, 0xB7EFB9U, 0xECFD44U, 0xA50497U, 0xAF178AU, 0xD68C69U, 0xD97DB5U, 0x82670EU, 0xCBB45BU, 0x508D90U, + 0x190A25U, 0x63F0FEU, 0x68E3C7U, 0x317A10U, 0x3A09D9U, 0x6B926EU, 0x004237U, 0x1B79C8U, 0x53EA59U, 0x48B3B7U, + 0x811166U, 0xDE4A79U, 0xF5F988U, 0xAC6057U, 0xE733FEU, 0xFF89ADU, 0xB49830U, 0x8F4BC3U, 0xC6F00EU, 0x9DA135U, + 0x942FE0U, 0xC71C3BU, 0x4DC78FU, 0x3476C4U, 0x7F6C39U, 0x66BFAAU, 0x298657U, 0x725504U, 0x5B4E89U, 0x01FE72U, + 0x0835A3U, 0x53269CU, 0x189D4DU, 0x01CDC2U, 0xEA763BU, 0xF3A56DU, 0xB0BCD4U, 0xE80F13U, 0xE355CAU, 0x98C47DU, + 0x91AB24U, 0xCE38DBU, 0x87A35AU, 0x9CD3A5U, 0xD648F4U, 0xAF7B6FU, 0x24A292U, 0x7D3011U, 0x764B6DU, 0x2DDABEU, + 0x44D123U, 0x5E22D8U, 0x1FB09DU, 0x04A926U, 0x4F5AF3U, 0x064128U, 0x3DB105U, 0x70AAD6U, 0xAA392FU, 0xA1C4B8U, + 0xF8C7C0U, 0xD35D0FU, 0x8A2E9EU, 0xC1B761U, 0xDA44F0U, 0x925E8FU, 0x89CF4EU, 0xE8B4D1U, 0xB32728U, 0xB8FE7FU, + 0x61DCC6U, 0x2A4701U, 0x1614D8U, 0x5DADE2U, 0x46BE37U, 0x0F44DCU, 0x54D549U, 0x5D8E32U, 0x263DAFU, 0x2C237CU, + 0x75E291U, 0xBE5982U, 0xA74A7FU, 0xC493A4U, 0xDFA131U, 0x967A5AU, 0xCCCB8EU, 0xC1D835U, 0x9A02ECU, 0xF331BBU, + 0xE8B812U, 0xA3EBC5U, 0xBA507CU, 0x7080ABU, 0x099BC2U, 0x02285DU, 0x59718CU, 0x50C273U, 0x0B1862U, 0x4A1F8CU, + 0x70A655U, 0x3BF5C2U, 0x666FBBU, 0x6DDE68U, 0x3485C5U, 0x9F161EU, 0xC46F4BU, 0x8CFDF0U, 0x97C625U, 0xDE058EU, + 0xC59CD3U, 0xAEAE20U, 0xF775BCU, 0xFC647FU, 0xBD9F02U, 0xE70C91U, 0xCC1468U, 0x11E7B7U, 0x1AFC36U, 0x435B49U, + 0x080398U, 0x139027U, 0x7B63FEU, 0x607AF9U, 0x29E900U, 0x7293D6U, 0x79026FU, 0x00D930U, 0x0BEAF1U, 0xD3614EU, + 0x90119FU, 0x8B8AE4U, 0xC61969U, 0xBD609AU, 0xB4F247U, 0xEFA954U, 0xE518A9U, 0xBC0362U, 0xD7D0D6U, 0xCE7E8DU, + 0x856F18U, 0x1C94E3U, 0x578726U, 0x0D5F1DU, 0x24ECC0U, 0x7FF713U, 0x3E26AAU, 0x251D6DU, 0x6A8F14U, 0x53648BU, + 0x19757AU, 0x40AEB4U, 0xCB9CA5U, 0x90055AU, 0x9956C3U, 0xE2ED34U, 0xAB3C7DU, 0xB126EAU, 0xFA9513U, 0xA3D2C8U, + 0x886BFDU, 0xD9F836U, 0xD2A2E3U, 0x8D1359U, 0x454804U, 0x5EDBF7U, 0x37637AU, 0x2C3089U, 0x67ABD4U, 0x3E8847U, + 0x3551BAU, 0x4D6331U, 0x46B8C4U, 0x1D299FU, 0x54120EU, 0x5FC0E1U, 0x86D93BU, 0xE56A0EU, 0xFBB1D5U, 0xB2B600U, + 0xA94EABU, 0xE05DF6U, 0x9BE605U, 0x90B798U, 0xC92C6BU, 0xC3DE66U, 0x9AC7BDU, 0xD15448U, 0x6A3FD3U, 0x23ADA3U, + 0x78346CU, 0x7147F5U, 0x2BDC02U, 0x0EAD5BU, 0x553FFCU, 0x1EA425U, 0x07D5F2U, 0x4C4ECBU, 0x554C14U, 0x3EB3F5U, + 0xE4A26AU, 0xED799BU, 0xB6CA85U, 0xFFD25CU, 0xC421BFU, 0x8F3A22U, 0x96AB51U, 0xDC518CU, 0x895217U, 0x8289F2U, + 0xF9B8A9U, 0xF0231CU, 0x2BF1C7U, 0x62C80AU, 0x781B39U, 0x1320E5U, 0x4AB156U, 0x41EB8FU, 0x1848E0U, 0x13D771U, + 0x4886AEU, 0x203C5FU, 0x3B6F40U, 0x76F6A1U, 0xE5457EU, 0xAE1EE7U, 0xD7AC10U, 0xDCB549U, 0x8476EFU, 0x8FC536U, + 0xD49DE9U, 0x9D0ED8U, 0xA63513U, 0xEFE4A6U, 0xB4DF7DU, 0x3E0D00U, 0x779693U, 0x4CA75EU, 0x0568ADU, 0x527BB0U, + 0x59C34BU, 0x00109FU, 0x0A0B14U, 0x73FA61U, 0x38E0BAU, 0x23530FU, 0x6A88D4U, 0xB199DDU, 0x98322AU, 0xC260F3U, + 0xCBF944U, 0x908A0DU, 0xDB11F2U, 0xC28163U, 0xADFABDU, 0xBC694CU, 0xF65243U, 0xAD83BAU, 0xA40D6DU, 0x5F7EF4U, + 0x16E787U, 0x0DF44AU, 0x460EF1U, 0x5E1F24U, 0x15CC3FU, 0x6C77CAU, 0x676401U, 0x3C9CBDU, 0x359FEEU, 0x6A0413U, + 0x02F590U, 0x91EE4DU, 0xDA3C3EU, 0xC305A3U, 0x889658U, 0xF14D99U, 0xFA7F86U, 0xA1E677U, 0xE981E8U, 0xF21A10U, + 0xBB4BD7U, 0x80F1CEU, 0xCB6239U, 0x123BE0U, 0x1D885FU, 0x45921EU, 0x6641E1U, 0x3DE870U, 0x74BBAFU, 0x6F00C6U, + 0x261055U, 0x7DCBA8U, 0x57787AU, 0x0E2167U, 0x05B28CU, 0xCC8819U, 0x975BE2U, 0xBC52B7U, 0xE5E52CU, 0xEB37C9U, + 0xB20E12U, 0xF9DD2FU, 0xE8C6FCU, 0x837701U, 0xD8AD82U, 0xD1BE5AU, 0x0B0525U, 0x0244B4U, 0x79FE5BU, 0x322DCAU, + 0x2B3495U, 0x60876CU, 0x79DCFBU, 0x334C12U, 0x4C7745U, 0x45A4DCU, 0x1E3F23U, 0x175FF2U, 0xC4C0D8U, 0xAFF30DU, + 0xB72AF6U, 0xFCB96BU, 0xA5C338U, 0xAE5295U, 0xF54946U, 0xDCBABBU, 0x87A1A8U, 0xCF2165U, 0xD4DA9EU, 0x9FC90BU, + 0x223070U, 0x6922A4U, 0x30B92FU, 0x3348D6U, 0x695B01U, 0x20C038U, 0x1BB2EFU, 0x523B06U, 0x49EC99U, 0x02D7C8U, + 0x5B4777U, 0x713CA6U, 0xA8AF49U, 0xA3B650U, 0xF84586U, 0xB5DF7FU, 0xAE8CF8U, 0xC72581U, 0x9D3652U, 0x9EEDCFU, + 0xC75D34U, 0xCC0671U, 0xB5B5CAU, 0xFEAC1FU, 0x677EA4U, 0x2DC5F9U, 0x26D63AU, 0x7F1F86U, 0x142855U, 0x0DF2A8U, + 0x42E3B3U, 0x195872U, 0x108B8DU, 0x6AB31CU, 0x632063U, 0x307BAAU, 0xFBC83DU, 0xE201C4U, 0xA91393U, 0x90A82AU, + 0xDAF9E4U, 0x816A55U, 0x88D00AU, 0xD383DBU, 0xFA3A64U, 0xA569A5U, 0xEEE2DEU, 0x76D243U, 0x3D0D90U, 0x649E6DU, + 0x47E76EU, 0x1C7491U, 0x156E49U, 0x4E9DDEU, 0x0604B7U, 0x3D3720U, 0x76FDD9U, 0x6FEC06U, 0x2417B7U, 0xFD04F8U, + 0xF29D29U, 0x886F92U, 0xC1744FU, 0xDAC73CU, 0x939EB1U, 0x880C63U, 0xEBE79EU, 0xB2F285U, 0xB86970U, 0xE11ABBU, + 0xEA822EU, 0x311155U, 0x586AC0U, 0x43F92BU, 0x0A81F6U, 0x5412C5U, 0x5D111CU, 0x26E8CBU, 0x2D7B63U, 0x74213CU, + 0x3F90CDU, 0x2E8B52U, 0x645883U, 0xDFE36CU, 0x96F375U, 0xDD0882U, 0xC40B1BU, 0x8FD6CCU, 0xB464A5U, 0xFC7F3EU, + 0xA7AECBU, 0xAA9511U, 0xF10634U, 0xBA5CEFU, 0x83ED32U, 0x483681U, 0x5015DCU, 0x138D3FU, 0x48DEA2U, 0x616571U, + 0x3AF40CU, 0x33AF97U, 0x681D72U, 0x2246E9U, 0x3BD7B9U, 0x506C46U, 0x0D2FDFU, 0x869338U, 0xDDC061U, 0xD45BD6U, + 0xAF6A0FU, 0xE7B8C0U, 0xFC2371U, 0xBF102EU, 0xA6C9DFU, 0xEDDA40U, 0x943089U, 0x9FA1BFU, 0x459A66U, 0x0C4995U, + 0x175108U, 0x7AE243U, 0x6139B6U, 0x2A2A2DU, 0x73D3D8U, 0x79C183U, 0x204A26U, 0x0B3FFDU, 0x5AA420U, 0x111613U, + 0x8A4FDFU, 0xC3DC2CU, 0xF9A7B5U, 0xB034EAU, 0xEBAC5BU, 0xE0CF94U, 0xBD5465U, 0xF605FAU, 0xCFBEA3U, 0x85AC54U, + 0x9E55DDU, 0xD7C62AU, 0x0CDD73U, 0x252FCDU, 0x76361CU, 0x7DF5D3U, 0x3546E2U, 0x6E5B39U, 0x67A98CU, 0x1CB247U, + 0x57231AU, 0x4AD8A9U, 0x01CA74U, 0x191187U, 0xF2208AU, 0xA9AB50U, 0xA0F8A5U, 0xFB403EU, 0xF2D34BU, 0xA9A880U, + 0xCB393DU, 0xD262EEU, 0x99D0B7U, 0xC04B00U, 0xCB1AC9U, 0xB0B176U, 0x39E3A7U, 0x677EF8U, 0x2ECD58U, 0x359687U, + 0x7E277EU, 0x473D69U, 0x0CEEB0U, 0x55D557U, 0x5F04CEU, 0x0C8EBDU, 0x25BD60U, 0x7E64DBU, 0xB7771EU, 0xACCC05U, + 0xE51CF0U, 0xBF2F2AU, 0x90F497U, 0xC9E7D4U, 0xC25F09U, 0x9B9CBAU, 0xD08767U, 0xEB320CU, 0xA36999U, 0x38FB42U, + 0x7180B3U, 0x22112CU, 0x29AA45U, 0x50F9D2U, 0x1B610AU, 0x0202FDU, 0x4899E4U, 0x57080BU, 0x3E72DAU, 0x65E165U, + 0x6CFA34U, 0xB70BEBU, 0xBC104AU, 0xE4E295U, 0x8F7BECU, 0x96787FU, 0xD583B2U, 0x9E9740U, 0x870C5DU, 0xECFFA6U, + 0xF4E433U, 0xBF35F8U, 0xE00F8DU, 0x699C16U, 0x3265EBU, 0x1B6638U, 0x40F515U, 0x0A8DC6U, 0x131E1BU, 0x5845A0U, + 0x21F670U, 0x2A6E1FU, 0x791D8EU, 0x708651U, 0x2AD7E8U, 0xE37CAFU, 0xD8EE56U, 0x97B3C1U, 0x8E0018U, 0xC51B6FU, + 0x9CC9E6U, 0xB67019U, 0xEF23C8U, 0xE498F2U, 0xBF9927U, 0xF643ECU, 0xCD7051U, 0x04E902U, 0x563AFFU, 0x5D006CU, + 0x04D3A1U, 0x0FCA9AU, 0x72794FU, 0x39A2B4U, 0x228231U, 0x6A19EAU, 0x714E96U, 0x18F705U, 0x4324FCU, 0xC83E3BU, + 0x918D02U, 0xDADCD5U, 0xC2470CU, 0xA135B3U, 0xBABCF2U, 0xF30F4DU, 0xA8549EU, 0xA1C543U, 0xDEFF78U, 0xD42CBCU, + 0x0DB747U, 0x46C6D2U, 0x5F5C89U, 0x144F60U, 0x6FA6F7U, 0x66350EU, 0x2C0A59U, 0x35DAE0U, 0x7EC12FU, 0x0D32FEU, + 0x0429C1U, 0x5FB911U, 0xD642AEU, 0x895167U, 0xC3D8B0U, 0xFAAB89U, 0xB1315AU, 0xA8C0A7U, 0xE3DB24U, 0xB84879U, + 0x913382U, 0xCBA317U, 0x82F8FCU, 0x994BA9U, 0x50C213U, 0x4390CEU, 0x282F5DU, 0x713E30U, 0x7FCDE3U, 0x26565EU, + 0x2D0485U, 0x56BDD4U, 0x1FAE7BU, 0x0475AAU, 0x4DD555U, 0x17CE4CU, 0x9C1D9BU, 0xE52473U, 0xEEF7E4U, 0xB7CD1DU, + 0xF45E42U, 0xEF87E3U, 0x87B43CU, 0x986FADU, 0xD16FD2U, 0x8AD403U, 0x8103A8U, 0xD83A75U, 0x33A826U, 0x2BF39BU, + 0x604049U, 0x7B99A4U, 0x328ABFU, 0x49306AU, 0x407191U, 0x1BEA04U, 0x19D96FU, 0x4001F2U, 0x0FB201U, 0x36E9DCU, + 0xFD7ADFU, 0xE64326U, 0xAF91F9U, 0xF51249U, 0xDC2B16U, 0x87F8D7U, 0xCCE668U, 0xC517B1U, 0x9E8C46U, 0x97BF5FU, + 0xED6498U, 0xA67461U, 0x378FF6U, 0x788C8FU, 0x611514U, 0x0AE6F1U, 0x53FC2BU, 0x596F3EU, 0x0216C5U, 0x4B8508U, + 0x507FBBU, 0x396EE6U, 0x22F535U, 0xE99688U, 0xB10F43U, 0xBA1D36U, 0xC3E2ADU, 0xC07178U, 0x9B28C3U, 0xD69A8BU, + 0xCD817CU, 0x8570E5U, 0xFEEB12U, 0xF5E8CBU, 0xAC10C4U, 0x270335U, 0x7ED8EAU, 0x156B5BU, 0x0E7A14U, 0x46A0C5U, + 0x5D937AU, 0x144AA3U, 0x4F79D5U, 0x6CF35CU, 0x31228FU, 0x7A1932U, 0x628E69U, 0xA9D59CU, 0x926517U, 0xDBBEE2U, + 0x80ADB9U, 0x891424U, 0xD246D7U, 0xD8ED1AU, 0xA17C28U, 0xEA27F5U, 0xF3942EU, 0xB8CE8FU, 0xAB5FD0U, 0x466461U, + 0x1CB7BEU, 0x152F6FU, 0x4E1CC0U, 0x05D799U, 0x1CE66EU, 0x773DF7U, 0x7EAB00U, 0x249048U, 0x6D41D7U, 0x765A26U, + 0x1DA9F9U, 0x8431C8U, 0xCF0203U, 0x96C1DEU, 0x90D86DU, 0xCB6A30U, 0xA23193U, 0xB9A24EU, 0xF05B95U, 0xEB48A0U, + 0xA0D27AU, 0xD8A39FU, 0xD33804U, 0x0A9B79U, 0x01C3AAU, 0x5A5437U, 0x132FD4U, 0x28BC0DU, 0x60253AU, 0x3F57E3U, + 0x3CCC7CU, 0x65DD9DU, 0x4E26C2U, 0x172572U, 0xDCDDADU, 0xC64E64U, 0x8F5553U, 0x94A68AU, 0xFDBE7DU, 0xA66DE4U, + 0xADD68BU, 0xF4C75AU, 0xFE0CC1U, 0x873E34U, 0xC8A72FU, 0xDBD0C2U, 0x124B10U, 0x49998DU, 0x40A8FEU, 0x3A3323U, + 0x316088U, 0x68D95DU, 0x235B06U, 0x3A00B3U, 0x51B178U, 0x4AEA89U, 0x025816U, 0x59C36FU, 0xD092B8U, 0x8B2930U, + 0xE43AC7U, 0xF5E2DEU, 0xBEC121U, 0xA71AF0U, 0xED8B7FU, 0x94B40EU, 0x9F66D1U, 0xD45D68U, 0xCD8CBFU, 0x8617F6U, + 0x5F2545U, 0x75FC98U, 0x2EFF62U, 0x674467U, 0x7C959CU, 0x318F09U, 0x0A7CD2U, 0x4967AFU, 0x11D62CU, 0x1A8CD1U, + 0x431F02U, 0x48A69DU, 0xB3E5ECU, 0xFA7623U, 0xE10E9AU, 0xA99948U, 0xB20215U, 0xD971A6U, 0x80E86BU, 0x8BDA90U, + 0xD60185U, 0x9D907EU, 0x8FFBFBU, 0xE66920U, 0x7D705DU, 0x3483CEU, 0x6F9833U, 0x646BF1U, 0x1DF3E8U, 0x17E017U, + 0x4E1BC6U, 0x050A79U, 0x1E8038U, 0x5773E7U, 0x2C685EU, 0xA1BD89U, 0xFB86B0U, 0xF01477U, 0xA16D8EU, 0xCAFE19U, + 0xD365C1U, 0x9815AEU, 0x839E3FU, 0xCBCDC4U, 0x907611U, 0xB9E70AU, 0xE2BDE7U, 0x2B0E34U, 0x301789U, 0x7BE4DAU, + 0x477707U, 0x0C2FACU, 0x558C79U, 0x5E9743U, 0x0D4496U, 0x04786DU, 0x7FABE0U, 0x3730B3U, 0x3C014AU, 0xE7DADDU, + 0xEEE834U, 0x956163U, 0xDCB2FAU, 0xC78905U, 0x8D5BD4U, 0xD0427BU, 0xDBF12BU, 0xA22AB4U, 0xA93B4DU, 0xFA819AU, + 0xB3D2B3U, 0x287B64U, 0x40289DU, 0x5BB206U, 0x100153U, 0x495CB8U, 0x42CF2DU, 0x3BF4D6U, 0x70248BU, 0x6ABF19U, + 0x23CCF4U, 0x3C4527U, 0x75761AU, 0x8EACC1U, 0x853F44U, 0xD44EBFU, 0xDED5EEU, 0x87C751U, 0xEC3E80U, 0xF72D6FU, + 0xBEB676U, 0xE557A1U, 0xEC4D59U, 0xB6BECEU, 0x9DA527U, 0x443078U, 0x0BCAE9U, 0x12D916U, 0x594087U, 0x6033E8U, + 0x22A831U, 0x7948A2U, 0x70535FU, 0x2BC01CU, 0x62BBA1U, 0x592A7BU, 0x92308EU, 0x8AC395U, 0xC15A50U, 0x9809ABU, + 0xB3B336U, 0xECB245U, 0xE54998U, 0xBEDA1BU, 0xF681E6U, 0xED35F5U, 0x8E2E0CU, 0x87FDD3U, 0x5CC453U, 0x1556ACU, + 0x0E85FDU, 0x64AC42U, 0x3D7F8BU, 0x36447CU, 0x6FD665U, 0x640FB2U, 0x3B3C4BU, 0x52A7C4U, 0x48F7B5U, 0x014C2EU, + 0x9A9FFBU, 0xD19601U, 0xA0250CU, 0xAB7FFFU, 0xF2C822U, 0xB8D1B1U, 0xA302CCU, 0xEAB907U, 0xD1E9B2U, 0x987269U, + 0xC3411CU, 0xCC8897U, 0x141A42U, 0x3F61B8U, 0x66F2A1U, 0x2DCB56U, 0x3618DFU, 0x778208U, 0x2CB3F1U, 0x0468EEU, + 0x5F7B1FU, 0x5693D0U, 0x0D8041U, 0x461B3EU, 0xFFECE7U, 0xB4FD50U, 0xA94798U, 0xE314CFU, 0xB88D76U, 0xB17EADU, + 0xCA7508U, 0xC3E553U, 0x989EA6U, 0xDB0D3DU, 0xC396E8U, 0xA8E683U, 0x717D1EU, 0x7A0EEDU, 0x219730U, 0x288422U, + 0x736ECFU, 0x1BFF14U, 0x04A4A1U, 0x4F177AU, 0x56092BU, 0x1DD884U, 0x64635DU, 0xEF70EAU, 0xA589B3U, 0xF49B54U, + 0xFF50CDU, 0xA66312U, 0x8DFA62U, 0xD628FDU, 0x9F131CU, 0x8582C3U, 0xCCF9DAU, 0xF36A29U, 0xB8B2F4U, 0x618157U, + 0x6A020AU, 0x335999U, 0x79E864U, 0x4272BFU, 0x03259AU, 0x189C40U, 0x51CFB5U, 0x0A752EU, 0x216463U, 0x79BF90U, + 0x721C0DU, 0xAB47FEU, 0xE4D727U, 0xFDEC28U, 0x963FD9U, 0x8DA646U, 0xC594B7U, 0x9E4FE8U, 0x977E60U, 0xECA597U, + 0xAF264EU, 0xB61C79U, 0xFDCDA0U, 0x65D64FU, 0x2E61DCU, 0x553881U, 0x5CAA72U, 0x0351FBU, 0x0A400CU, 0x51FB55U, + 0x3BB9CAU, 0x22223AU, 0x6993B5U, 0x30C8C4U, 0x3B5B1BU, 0xE02B82U, 0xC1B075U, 0x9B23BCU, 0xD25A8BU, 0xC9C852U, + 0x82A3A9U, 0xBB303CU, 0xF42977U, 0xADDA82U, 0xA64418U, 0xFC55E5U, 0xB5AEE6U, 0x0EBD3BU, 0x4765C8U, 0x4CD655U, + 0x17DD2EU, 0x562EEBU, 0x6C3770U, 0x25A585U, 0x3E5EDEU, 0x754F6FU, 0x2C94A1U, 0x23A758U, 0x5A3F4FU, 0xD07C96U, + 0x8BC761U, 0xC254E8U, 0xD92C97U, 0xB0BF06U, 0xEBE0D9U, 0xE25138U, 0xB8CAA7U, 0xBB98DEU, 0xE22109U, 0x896291U, + 0x10F172U, 0x5BCB2FU, 0x401A94U, 0x0CA141U, 0x77B2BAU, 0x7E6BBFU, 0x255964U, 0x6E82D9U, 0x77130AU, 0x3C3877U, + 0x04EAF4U, 0x4FD129U, 0x9C40DBU, 0x959BC6U, 0xCEAC2DU, 0xE774FCU, 0xBC6763U, 0xF6DC12U, 0xEB8DCDU, 0xA00664U, + 0xF9F4B3U, 0xD2EF4AU, 0x895E5DU, 0x800584U, 0x5A972BU, 0x132EFBU, 0x287D84U, 0x63E615U, 0x7297CEU, 0x391D23U, + 0x608E30U, 0x6AF5CDU, 0x11641EU, 0x5C5E93U, 0x4789E0U, 0x0E903DU, 0x956386U, 0xFEF053U, 0xB6E879U, 0xAD0BACU, + 0xE41077U, 0xFF83CAU, 0xB47A99U, 0xCD6870U, 0xCE93E7U, 0x96823EU, 0x9D1941U, 0xC4EBD0U, 0x2BF23FU, 0x3031EEU, + 0x790A71U, 0x229909U, 0x2AC1CEU, 0x717677U, 0x5AEDA0U, 0x039C99U, 0x480646U, 0x515587U, 0x1AEC3CU, 0x296F69U, + 0xE13492U, 0xBA8607U, 0xB39FCCU, 0xEC4CB1U, 0xA77723U, 0x9EA7DEU, 0xD51C0DU, 0xCD0F00U, 0x86D4FBU, 0xDDF56EU, + 0xF46F95U, 0x2FBCD4U, 0x268D6BU, 0x7D52B2U, 0x374165U, 0x26F9DCU, 0x4D2A9BU, 0x141163U, 0x1FD2FCU, 0x40CA2DU, + 0x497952U, 0x3322D3U, 0x7AB32CU, 0xE108F5U, 0xAA5AE2U, 0xB3E31BU, 0xF8B098U, 0x812B65U, 0x8B8936U, 0xD0D08AU, + 0xD94341U, 0x8A7894U, 0xE3A9AFU, 0xF8377AU, 0xB74481U, 0x6FDD0CU, 0x64EE5FU, 0x3D35A2U, 0x163731U, 0x5F8ECCU, + 0x045DC7U, 0x0F4616U, 0x57B6E8U, 0x7CAD79U, 0x253E86U, 0x6EC7CFU, 0x7DD478U, 0xB426A1U, 0xCF2D76U, 0xC3BC5FU, + 0x984780U, 0x935571U, 0xCACCEEU, 0x81BBBFU, 0xB82054U, 0xF371C0U, 0xE9CB3BU, 0xA05826U, 0xFB33F5U, 0x52A218U, + 0x09B88BU, 0x424BF6U, 0x53D22DU, 0x198198U, 0x043A53U, 0x6F2A06U, 0x34F1BDU, 0x3DC260U, 0x664982U, 0x6FB81BU, + 0x15A24CU, 0xDE71F5U, 0xC7482AU, 0x8CDFCBU, 0x9505D4U, 0xDE3405U, 0xA5EFFAU, 0xA4FC63U, 0xFE5704U, 0xB387DDU, + 0xA8BC6AU, 0xC32FB2U, 0x5A7EE5U, 0x11C44CU, 0x489797U, 0x420E62U, 0x19BD79U, 0x30E6BCU, 0x6B6407U, 0x225DDAU, + 0x398EA9U, 0x703534U, 0x0A64F7U, 0x09FA0AU, 0xD4C910U, 0xDF10E5U, 0x86833EU, 0xCDB99BU, 0xE67A40U, 0xBE631BU, + 0xB590AEU, 0xEC8B75U, 0xA73BD0U, 0x9CE08BU, 0xD5F35EU, 0x8E0AE5U, 0x061828U, 0x5D835AU, 0x5660C7U, 0x277914U, + 0x68CAE9U, 0x7190E2U, 0x3A0113U, 0x20FECCU, 0x49ED7DU, 0x127522U, 0x1B06ABU, 0x40855CU, 0x8B9E85U, 0x926FB2U, + 0xF8F56AU, 0xE186A5U, 0xAA1F14U, 0xF10CCBU, 0xF0F7BAU, 0x8F6735U, 0x867CECU, 0xDC9F1FU, 0x978402U, 0x8E54F1U, + 0x45EF3CU, 0x7CFC8FU, 0x3705D2U, 0x6C1248U, 0x64C8BDU, 0x3FF976U, 0x566243U, 0x4DA198U, 0x069B45U, 0x1F0AF6U, + 0x5851BBU, 0x00E248U, 0xAB3BD1U, 0xF2090EU, 0xF9926FU, 0xA2C3F1U, 0xEB7800U, 0xD07B9FU, 0x98A1E6U, 0xC31021U, + 0xC84BB8U, 0x91D84FU, 0x9AEC96U, 0x6337A9U, 0x288468U, 0x369FB3U, 0x774E06U, 0x6C645DU, 0x05B7A9U, 0x4E2E22U, + 0x551DFFU, 0x1CC78CU, 0x47D611U, 0x4F2DF2U, 0x343E6FU, 0xBF8514U, 0xE655C1U, 0xAD5E5AU, 0xB4EDBFU, 0xDFB4E4U, + 0xC1265DU, 0x80DD8BU, 0xDBC852U, 0xD25375U, 0x8920ACU, 0xA2BA53U, 0xFB0BC2U, 0x31401DU, 0x28D33CU, 0x63AAE3U, + 0x18381AU, 0x11238DU, 0x4AD2E4U, 0x434933U, 0x195BABU, 0x56A058U, 0x6FB105U, 0x2C5AAEU, 0x35C97BU, 0xFED9A0U, + 0xA52295U, 0x8D314EU, 0xD6ECA3U, 0x9F5E30U, 0x84456DU, 0xCFB6DEU, 0xD6AF03U, 0xBD2CE9U, 0xE556FCU, 0xEEC707U, + 0xB71CD6U, 0x382F59U, 0x43B720U, 0x02E4F7U, 0x195F4EU, 0x51CC99U, 0x0AA550U, 0x013767U, 0x786CBEU, 0x73DD01U, + 0x2AC6D1U, 0x61159EU, 0x7BA92FU, 0x92BAF4U, 0x896109U, 0xC0521AU, 0x9F9AF7U, 0x942924U, 0xC532B9U, 0xEFE3C2U, + 0xA6D807U, 0xFD0ABCU, 0xF69369U, 0xAFA033U, 0x44738EU, 0x5D694DU, 0x17C8F0U, 0x0C93A3U, 0x45207AU, 0x1EF9C5U, + 0x37EB04U, 0x6850FBU, 0x6305EAU, 0x3B9E15U, 0x782DC4U, 0x41774BU, 0x8AF633U, 0xD18DE4U, 0xD81E5DU, 0x83A69AU, + 0x8AF583U, 0xF06E7CU, 0xBB5FADU, 0xA28416U, 0xE99653U, 0xF06D88U, 0x9FEC35U, 0xC4F7E6U, 0x4C059AU, 0x1F1C19U, + 0x56EFC4U, 0x4D743FU, 0x24612AU, 0x3F9BD1U, 0x748814U, 0x2C13AFU, 0x27F276U, 0x5EE861U, 0x553B88U, 0x0E0A5FU, + 0xC791E6U, 0xD8E2B0U, 0x907A69U, 0xABE9C6U, 0xE09217U, 0xB10168U, 0xBA48F9U, 0xE3FA26U, 0x8861CFU, 0x9230D8U, + 0xDB8B21U, 0xC099B2U, 0x09644FU, 0x52F704U, 0x79AC90U, 0x201F6BU, 0x2E17BEU, 0x77C495U, 0x3CFF48U, 0x172E9BU, + 0x4E9426U, 0x0D8775U, 0x145E98U, 0x5E6D03U, 0xC5F6D6U, 0xAC242DU, 0xF70D3CU, 0xFEDED2U, 0xA5C543U, 0xAE74BCU, + 0xD62EE5U, 0x9D9D72U, 0x80029BU, 0xCB534CU, 0x90E175U, 0x19BAAAU, 0x6A3B6BU, 0x6280D4U, 0x39D385U, 0x724B7AU, + 0x6B78E2U, 0x00A321U, 0x19101CU, 0x5248CFU, 0x0ADB30U, 0x01F0A9U, 0x5A21CEU, 0xB73A17U, 0xACC880U, 0xE55179U, + 0xFE42A6U, 0xB4B987U, 0xC5AF58U, 0xCE1688U, 0x97C533U, 0x9CCE76U, 0xC73F8DU, 0x8E2510U, 0xB4B6C3U, 0x7D4FFEU, + 0x665C3DU, 0x2DC7C0U, 0x70B55BU, 0x5B2C2EU, 0x025FF5U, 0x49D470U, 0x53448AU, 0x1A3FD7U, 0x09AC64U, 0x60BDBDU, + 0x3B467AU, 0xB0D043U, 0xE98B9CU, 0xE33A2DU, 0x9A21E2U, 0xD1C3B3U, 0xCA5A0CU, 0x8709DDU, 0xDCB222U, 0xF5A3AAU, + 0xBF79DDU, 0xA44A04U, 0xEDD193U, 0x3E006AU, 0x373B21U, 0x4CF994U, 0x47C04FU, 0x1F53DAU, 0x5488A1U, 0x4DB86CU, + 0x2623DFU, 0x7D7402U, 0x70CF50U, 0x2B9EFDU, 0x232426U, 0xF8A7D3U, 0x91FEC8U, 0x8A4D39U, 0xC117F6U, 0xD0866FU, + 0x9B3D18U, 0xE36EC1U, 0xE8F576U, 0xB3C5BFU, 0xBA1629U, 0xE1BD50U, 0xA8EC8FU, 0x17763EU, 0x5D45F1U, 0x049CA0U, + 0x0F8F1FU, 0x5630C6U, 0x7DE225U, 0x26FB38U, 0x6F08CBU, 0x7D0316U, 0x34B28DU, 0x2F68E9U, 0xC47B72U, 0x9DC287U, + 0x96915CU, 0xCF0B41U, 0x85F8A2U, 0xBAE17FU, 0xF372CCU, 0xE81991U, 0xA1894AU, 0xFAF2EBU, 0xF16134U, 0x89F845U, + 0x0A8ADBU, 0x53153AU, 0x1806E5U, 0x03FF7CU, 0x6A7C0BU, 0x312692U, 0x399775U, 0x628CACU, 0x6D7FB3U, 0x34EE42U, + 0x5FF49DU, 0x56073CU, 0x8D1C67U, 0x87CDBBU, 0xDEE708U, 0xB574D5U, 0xA4ADB6U, 0xEF9E2BU, 0xF605D0U, 0xBD7545U, + 0xE6EE0EU, 0xCE39FBU, 0x950260U, 0xD8929DU, 0x43D9CEU, 0x086A47U, 0x31B3B1U, 0x7AA068U, 0x221ADFU, 0x294B86U, + 0x72F049U, 0x73E3F8U, 0x083927U, 0x418856U, 0x5AC3C9U, 0x105020U, 0xC969B7U, 0xE2BBEEU, 0xBF2019U, 0xB41181U, + 0xEFCA6AU, 0xA6FD3FU, 0xBC27A4U, 0xD53651U, 0xCE9D9AU, 0x854EA7U, 0xDC5E74U, 0xDFE5A9U, 0x26B61AU, 0x6C0D57U, + 0x77DCECU, 0x3EC639U, 0x2575C3U, 0x682CD6U, 0x13AF1DU, 0x1855ECU, 0x404473U, 0x4BDF8AU, 0x12ACDDU, 0xF93754U, + 0xE207A3U, 0xABD87AU, 0xF04B45U, 0xF03284U, 0xABB05BU, 0x80ABEBU, 0xD95AB4U, 0x92C10DU, 0x8FD2CEU, 0xC42833U, + 0xEC3920U, 0x37C2FDU, 0x7C5106U, 0x654883U, 0x2EAAF8U, 0x37B12DU, 0x5C20B6U, 0x065B42U, 0x07C909U, 0x5C12B4U, + 0x152367U, 0x2EB4FAU, 0x65CF19U, 0xFC5F40U, 0xB294FFU, 0xEBA72EU, 0xE03ED1U, 0x9B6CD0U, 0x92D70FU, 0xC944F6U, + 0x801D60U, 0x9AAE19U, 0xF1F4DEU, 0xA85547U, 0xAB4EB8U, 0x729DE9U, 0x792456U, 0x223697U, 0x4BED0CU, 0x55DE71U, + 0x1C03A2U, 0x07910FU, 0x4CAADCU, 0x356BA0U, 0x3E5033U, 0x67C3EEU, 0x2D9B05U, 0xB62810U, 0xFFF3EBU, 0xC4E03EU, + 0x8558A5U, 0xDE0B48U, 0xD5905BU, 0x8D71A2U, 0xA26A75U, 0xFBD8ECU, 0xB08982U, 0xAB1253U, 0xE2A1ECU, 0x79FB3FU, + 0x116E52U, 0x4A15C9U, 0x43861CU, 0x188FE7U, 0x537DF2U, 0x62E619U, 0x29D7C0U, 0x310C57U, 0x7A1F2EU, 0x25E5B8U, + 0xAC7451U, 0xC76F86U, 0xDE9C9FU, 0x959460U, 0xCF27B1U, 0xC6FC1EU, 0xBDEDCFU, 0xF416B0U, 0xEF0429U, 0xA49FEEU, + 0xBDEA17U, 0xFF7104U, 0x06A3F8U, 0x0D8A63U, 0x5219A6U, 0x5B62DDU, 0x00F348U, 0x6969B3U, 0x731A6EU, 0x38816DU, + 0x61D090U, 0x6A6343U, 0x33F9FEU, 0x18B8A5U, 0xC30340U, 0x8B10DAU, 0x98E80BU, 0xD1FB74U, 0xEA20F5U, 0xA5930AU, + 0xFC8E93U, 0xF75CC4U, 0xAF673DU, 0xA4E6BAU, 0xDF3D43U, 0x960F9CU, 0x0DD68DU, 0x44E572U, 0x1F7EB2U, 0x35AD09U, + 0x6C9554U, 0x6746A7U, 0x365D3AU, 0x7DFCF9U, 0x64A6C4U, 0x0B351FU, 0x118CEAU, 0x58DF61U, 0x836434U, 0x8A36CFU, + 0xF1AB5BU, 0xBA18A0U, 0xA343EDU, 0xE8C27EU, 0xF0F887U, 0xBB2B50U, 0xC03A69U, 0xC9C1A6U, 0x9A5317U, 0x9368C8U, + 0x5CB919U, 0x26A226U, 0x2F01EFU, 0x74D919U, 0x3DCA80U, 0x2631D7U, 0x6D223EU, 0x54BAA1U, 0x1E4950U, 0x47520BU, + 0x4CA79EU, 0x97BC75U, 0xBE3EA8U, 0xED479BU, 0xA4D446U, 0xBA4FF5U, 0xF13C39U, 0xE8A46AU, 0x83D7D7U, 0xDA4C0CU, + 0xD1DDF9U, 0x8AA7F2U, 0xC22427U, 0x793DDCU, 0x30CE45U, 0x2B5522U, 0x6007FBU, 0x39BE6CU, 0x32AD95U, 0x42560BU, + 0x4D426AU, 0x16D1B5U, 0x5F3A04U, 0x442BDBU, 0x2DF082U, 0xF6C225U, 0xFE59FCU, 0xA5880FU, 0xAEB312U, 0xF761C9U, + 0x9C582CU, 0x85CBB7U, 0xCE00C3U, 0xD43118U, 0x9DAB9DU, 0xEAF866U, 0xE3437BU, 0x381288U, 0x738955U, 0x6A3BF6U, + 0x2066ABU, 0x19D570U, 0x52DEC1U, 0x090E1EU, 0x00B5FFU, 0x5BE6E1U, 0x727D38U, 0x284CCFU, 0x639656U, 0xFA8531U, + 0xBD3CA8U, 0xD4EF77U, 0xCFC586U, 0x841489U, 0x9C0F78U, 0xD7BCA7U, 0x8E671EU, 0xA5774DU, 0xFE8481U, 0xF79F32U, + 0xAC0AEFU, 0x65F09CU, 0x5FF301U, 0x144ACAU, 0x0D193FU, 0x468224U, 0x13F0D1U, 0x18694AU, 0x63FA87U, 0x2B81F4U, + 0x30106DU, 0x790A9BU, 0xE2E952U, 0x8970CDU, 0xD003BCU, 0xDB9963U, 0x838AD2U, 0x88731DU, 0xD1E064U, 0xBAFFF3U, + 0xA10F2AU, 0xEC049DU, 0xBFD7D4U, 0xB7EE2BU, 0x4C7CBBU, 0x478760U, 0x1E9415U, 0x554D9EU, 0x4C7E6BU, 0x07E4B0U, + 0x3D35ADU, 0x741E4EU, 0x2F8D93U, 0x26FC20U, 0x7D667DU, 0x16B586U, 0x8B8E02U, 0xC91FD9U, 0xD0456CU, 0x9BF237U, + 0xC0EBCEU, 0xE92849U, 0xB29390U, 0xBBC3E7U, 0xE1787EU, 0xAA6B81U, 0x93B040U, 0xD8005FU, 0x411BAEU, 0x0AC870U, + 0x51F1D1U, 0x5D328EU, 0x362837U, 0x6799E0U, 0x6C4239U, 0x37711AU, 0x3EABC7U, 0x45BA3CU, 0x0D01A9U, 0x16D6F2U, + 0xDDCF17U, 0xC46D8CU, 0x8F3670U, 0xF6A723U, 0xFD5CBCU, 0xA74F5DU, 0xEAF582U, 0xF1A43BU, 0x903768U, 0x8B0CC5U, + 0xC0DC16U, 0x9957CBU, 0x1324F0U, 0x4ABD25U, 0x61AECEU, 0x38545AU, 0x73C701U, 0x68FEF4U, 0x212D6FU, 0x5B3382U, + 0x52C2D1U, 0x09494CU, 0x065ABFU, 0xDFA126U, 0x9CB149U, 0xA56A98U, 0xEE5927U, 0xF4C0F6U, 0xBD33B8U, 0xE62901U, + 0xCFB8D6U, 0x94D32FU, 0x9F40B8U, 0xC69AF1U, 0x8CAB0EU, 0x15309FU, 0x7E6360U, 0x21DA31U, 0x2848BAU, 0x733747U, + 0x72A6D4U, 0x08EDA8U, 0x435F7BU, 0x5A4CD6U, 0x119505U, 0x082658U, 0x433DE3U, 0xB8ED26U, 0xB0D6DDU, 0xEB05C8U, + 0xA2BC13U, 0xA9BEEAU, 0xD6656DU, 0xDF5614U, 0x848F82U, 0xC41C5BU, 0xDF26A4U, 0x94F7A5U, 0xADCC5AU, 0x665B8BU, + 0x3F1234U, 0x34A0EDU, 0x6E7BAAU, 0x076813U, 0x1CD1C4U, 0x55833DU, 0x4E1836U, 0x03A9E2U, 0x58F219U, 0x72418CU, + 0x2B09F7U, 0xA89A72U, 0xF1A1A9U, 0xBA7254U, 0x81EA47U, 0xC899BAU, 0xD20279U, 0x9B13C4U, 0xC0E09FU, 0xCB7E4BU, + 0xB25FF0U, 0xF98431U, 0xE4974EU, 0x2E6CD7U, 0x35FC00U, 0x5CE7A9U, 0x07147EU, 0x060D07U, 0x5D9F98U, 0x56E449U, + 0x0E65A6U, 0x659EB7U, 0x7C8D49U, 0x371790U, 0x6C6623U, 0xE5FD6EU, 0x9E6EBDU, 0x921600U, 0xC985D3U, 0x82DAEEU, + 0x9B7B25U, 0xD0E0F0U, 0xE1924BU, 0xAA091EU, 0xF158F5U, 0xF9E369U, 0x22F1BAU, 0x4B28C7U, 0x509B54U, 0x1B80BDU, + 0x024162U, 0x497B53U, 0x01A88CU, 0x3E1B5DU, 0x7502F2U, 0x6CD12BU, 0x27EB1CU, 0x7E7AC5U, 0xDDA113U, 0x8596BAU, + 0xCE5EEDU, 0xD54D14U, 0x9CF68BU, 0x87A54AU, 0xEE1C31U, 0xB58EA4U, 0xBFD55FU, 0xE66482U, 0xE93FA1U, 0x90AD7CU, + 0x5B04EFU, 0x405713U, 0x09CC48U, 0x13BFEDU, 0x522736U, 0x2914E3U, 0x22CFD8U, 0x7B5E05U, 0x3061E6U, 0x29B37FU, + 0x43BAA8U, 0x5849D1U, 0x91D25EU, 0xCEE0AFU, 0xC73971U, 0x9C2A40U, 0xB7919FU, 0xEF401EU, 0xA452E1U, 0xB5B9B8U, + 0xFEA80FU, 0x8533D6U, 0x8C4115U, 0xD7DA28U, 0x5F6BF3U, 0x043006U, 0x4FA39DU, 0x76DBD9U, 0x394C22U, 0x20C7BFU, + 0x6BB64CU, 0x312C41U, 0x187FB2U, 0x43C46FU, 0x0A55F4U, 0x192E81U, 0xD2BC4AU, 0xCBA5FBU, 0xA15624U, 0xF85DFDU, + 0xF38ECBU, 0xBA3602U, 0xA125F5U, 0xCEFE6CU, 0x97CF3BU, 0x9D55C2U, 0xC4A64DU, 0x4FBFBCU, 0x1468A3U, 0x7D4352U, + 0x6ED19DU, 0x270804U, 0x7D3B76U, 0x76A0ABU, 0x0FF018U, 0x0443D5U, 0x5D188EU, 0x16A93BU, 0x0932E0U, 0xC07015U, + 0xFACB1EU, 0xB39AC3U, 0xE80170U, 0xE3B3ADU, 0xBAEA5EU, 0xD17956U, 0xC042A9U, 0x8A9378U, 0x912DE7U, 0xD86E86U, + 0x83F559U, 0x2AC4E8U, 0x711F37U, 0x7A0D6EU, 0x26B4C9U, 0x6D6710U, 0x547CE7U, 0x1F8CFEU, 0x449720U, 0x4D3483U, + 0x16EF5AU, 0x1EFE2DU, 0x6D44B4U, 0xA6174BU, 0xBF8E8AU, 0xF4FD95U, 0xED6764U, 0x86D6BBU, 0xDC8912U, 0xD10A45U, + 0x8A799CU, 0x83E12AU, 0xF872F3U, 0xB10954U, 0xAA980DU, 0x6083D6U, 0x397163U, 0x3AE8B8U, 0x439BDDU, 0x481046U, + 0x1302BBU, 0x5AFB68U, 0x50E875U, 0x297396U, 0x26824AU, 0x7D98F1U, 0x344BA4U, 0xAF726FU, 0xE6F5DAU, 0x9C0F01U, + 0x971C38U, 0xCE85EFU, 0xC5F626U, 0x946D91U, 0xFFBDC8U, 0xE48637U, 0xAC15A6U, 0xB74C48U, 0x7EEE99U, 0x21B586U, + 0x0A0677U, 0x539FA8U, 0x18CC01U, 0x007652U, 0x4B67CFU, 0x70B43CU, 0x390FF1U, 0x625ECAU, 0x6BD01FU, 0x38E3C4U, + 0xB23870U, 0xCB893BU, 0x8093C6U, 0x994055U, 0xD679A8U, 0x8DAAFBU, 0xA4B176U, 0xFE018DU, 0xF7CA5CU, 0xACD963U, + 0xE762B2U, 0xFE323DU, 0x1589C4U, 0x0C5A92U, 0x4F432BU, 0x17F0ECU, 0x1CAA35U, 0x673B82U, 0x6E54DBU, 0x31C724U, + 0x785CA5U, 0x632C5AU, 0x29B70BU, 0x508490U, 0xDB5D6DU, 0x82CFEEU, 0x89B492U, 0xD22541U, 0xBB2EDCU, 0xA1DD27U, + 0xE04F62U, 0xFB56D9U, 0xB0A50CU, 0xF9BED7U, 0xC24EFAU, 0x8F5529U, 0x55C6D0U, 0x5E3B47U, 0x07383FU, 0x2CA2F0U, + 0x75D161U, 0x3E489EU, 0x25BB0FU, 0x6DA170U, 0x7630B1U, 0x174B2EU, 0x4CD8D7U, 0x470180U, 0x9E2339U, 0xD5B8FEU, + 0xE9EB27U, 0xA2521DU, 0xB941C8U, 0xF0BB23U, 0xAB2AB6U, 0xA271CDU, 0xD9C250U, 0xD3DC83U, 0x8A1D6EU, 0x41A67DU, + 0x58B580U, 0x3B6C5BU, 0x205ECEU, 0x6985A5U, 0x333471U, 0x3E27CAU, 0x65FD13U, 0x0CCE44U, 0x1747EDU, 0x5C143AU, + 0x45AF83U, 0x8F7F54U, 0xF6643DU, 0xFDD7A2U, 0xA68E73U, 0xAF3D8CU, 0xF4E79DU, 0xB5E073U, 0x8F59AAU, 0xC40A3DU, + 0x999044U, 0x922197U, 0xCB7A3AU, 0x60E9E1U, 0x3B90B4U, 0x73020FU, 0x6839DAU, 0x21FA71U, 0x3A632CU, 0x5151DFU, + 0x088A43U, 0x039B80U, 0x4260FDU, 0x18F36EU, 0x33EB97U, 0xEE1848U, 0xE503C9U, 0xBCA4B6U, 0xF7FC67U, 0xEC6FD8U, + 0x849C01U, 0x9F8506U, 0xD616FFU, 0x8D6C29U, 0x86FD90U, 0xFF26CFU, 0xF4150EU, 0x2C9EB1U, 0x6FEE60U, 0x74751BU, + 0x39E696U, 0x429F65U, 0x4B0DB8U, 0x1056ABU, 0x1AE756U, 0x43FC9DU, 0x282F29U, 0x318172U, 0x7A90E7U, 0xE36B1CU, + 0xA878D9U, 0xF2A0E2U, 0xDB133FU, 0x8008ECU, 0xC1D955U, 0xDAE292U, 0x9570EBU, 0xAC9B74U, 0xE68A85U, 0xBF514BU, + 0x34635AU, 0x6FFAA5U, 0x66A93CU, 0x1D12CBU, 0x54C382U, 0x4ED915U, 0x056AECU, 0x5C2D37U, 0x779402U, 0x2607C9U, + 0x2D5D1CU, 0x72ECA6U, 0xBAB7FBU, 0xA12408U, 0xC89C85U, 0xD3CF76U, 0x98542BU, 0xC177B8U, 0xCAAE45U, 0xB29CCEU, + 0xB9473BU, 0xE2D660U, 0xABEDF1U, 0xA03F1EU, 0x7926C4U, 0x1A95F1U, 0x044E2AU, 0x4D49FFU, 0x56B154U, 0x1FA209U, + 0x6419FAU, 0x6F4867U, 0x36D394U, 0x3C2199U, 0x653842U, 0x2EABB7U, 0x95C02CU, 0xDC525CU, 0x87CB93U, 0x8EB80AU, + 0xD423FDU, 0xF152A4U, 0xAAC003U, 0xE15BDAU, 0xF82A0DU, 0xB3B134U, 0xAAB3EBU, 0xC14C0AU, 0x1B5D95U, 0x128664U, + 0x49357AU, 0x002DA3U, 0x3BDE40U, 0x70C5DDU, 0x6954AEU, 0x23AE73U, 0x76ADE8U, 0x7D760DU, 0x064756U, 0x0FDCE3U, + 0xD40E38U, 0x9D37F5U, 0x87E4C6U, 0xECDF1AU, 0xB54EA9U, 0xBE1470U, 0xE7B71FU, 0xEC288EU, 0xB77951U, 0xDFC3A0U, + 0xC490BFU, 0x89095EU, 0x1ABA81U, 0x51E118U, 0x2853EFU, 0x234AB6U, 0x7B8910U, 0x703AC9U, 0x2B6216U, 0x62F127U, + 0x59CAECU, 0x101B59U, 0x4B2082U, 0xC1F2FFU, 0x88696CU, 0xB358A1U, 0xFA9752U, 0xAD844FU, 0xA63CB4U, 0xFFEF60U, + 0xF5F4EBU, 0x8C059EU, 0xC71F45U, 0xDCACF0U, 0x95772BU, 0x4E6622U, 0x67CDD5U, 0x3D9F0CU, 0x3406BBU, 0x6F75F2U, + 0x24EE0DU, 0x3D7E9CU, 0x520542U, 0x4396B3U, 0x09ADBCU, 0x527C45U, 0x5BF292U, 0xA0810BU, 0xE91878U, 0xF20BB5U, + 0xB9F10EU, 0xA1E0DBU, 0xEA33C0U, 0x938835U, 0x989BFEU, 0xC36342U, 0xCA6011U, 0x95FBECU, 0xFD0A6FU, 0x6E11B2U, + 0x25C3C1U, 0x3CFA5CU, 0x7769A7U, 0x0EB266U, 0x058079U, 0x5E1988U, 0x167E17U, 0x0DE5EFU, 0x44B428U, 0x7F0E31U, + 0x349DC6U, 0xEDC41FU, 0xE277A0U, 0xBA6DE1U, 0x99BE1EU, 0xC2178FU, 0x8B4450U, 0x90FF39U, 0xD9EFAAU, 0x823457U, + 0xA88785U, 0xF1DE98U, 0xFA4D73U, 0x3377E6U, 0x68A41DU, 0x43AD48U, 0x1A1AD3U, 0x14C836U, 0x4DF1EDU, 0x0622D0U, + 0x173903U, 0x7C88FEU, 0x27527DU, 0x2E41A5U, 0xF4FADAU, 0xFDBB4BU, 0x8601A4U, 0xCDD235U, 0xD4CB6AU, 0x9F7893U, + 0x862304U, 0xCCB3EDU, 0xB388BAU, 0xBA5B23U, 0xE1C0DCU, 0xE8A00DU, 0x3B3F27U, 0x500CF2U, 0x48D509U, 0x034694U, + 0x5A3CC7U, 0x51AD6AU, 0x0AB6B9U, 0x234544U, 0x785E57U, 0x30DE9AU, 0x2B2561U, 0x6036F4U, 0xDDCF8FU, 0x96DD5BU, + 0xCF46D0U, 0xCCB729U, 0x96A4FEU, 0xDF3FC7U, 0xE44D10U, 0xADC4F9U, 0xB61366U, 0xFD2837U, 0xA4B888U, 0x8EC359U, + 0x5750B6U, 0x5C49AFU, 0x07BA79U, 0x4A2080U, 0x517307U, 0x38DA7EU, 0x62C9ADU, 0x611230U, 0x38A2CBU, 0x33F98EU, + 0x4A4A35U, 0x0153E0U, 0x98815BU, 0xD23A06U, 0xD929C5U, 0x80E079U, 0xEBD7AAU, 0xF20D57U, 0xBD1C4CU, 0xE6A78DU, + 0xEF7472U, 0x954CE3U, 0x9CDF9CU, 0xCF8455U, 0x0437C2U, 0x1DFE3BU, 0x56EC6CU, 0x6F57D5U, 0x25061BU, 0x7E95AAU, + 0x772FF5U, 0x2C7C24U, 0x05C59BU, 0x5A965AU, 0x111D21U, 0x892DBCU, 0xC2F26FU, 0x9B6192U, 0xB81891U, 0xE38B6EU, + 0xEA91B6U, 0xB16221U, 0xF9FB48U, 0xC2C8DFU, 0x890226U, 0x9013F9U, 0xDBE848U, 0x02FB07U, 0x0D62D6U, 0x77906DU, + 0x3E8BB0U, 0x2538C3U, 0x6C614EU, 0x77F39CU, 0x141861U, 0x4D0D7AU, 0x47968FU, 0x1EE544U, 0x157DD1U, 0xCEEEAAU, + 0xA7953FU, 0xBC06D4U, 0xF57E09U, 0xABED3AU, 0xA2EEE3U, 0xD91734U, 0xD2849CU, 0x8BDEC3U, 0xC06F32U, 0xD174ADU, + 0x9BA77CU, 0x201C93U, 0x690C8AU, 0x22F77DU, 0x3BF4E4U, 0x702933U, 0x4B9B5AU, 0x0380C1U, 0x585134U, 0x556AEEU, + 0x0EF9CBU, 0x45A310U, 0x7C12CDU, 0xB7C97EU, 0xAFEA23U, 0xEC72C0U, 0xB7215DU, 0x9E9A8EU, 0xC50BF3U, 0xCC5068U, + 0x97E28DU, 0xDDB916U, 0xC42846U, 0xAF93B9U, 0xF2D020U, 0x796CC7U, 0x223F9EU, 0x2BA429U, 0x5095F0U, 0x18473FU, + 0x03DC8EU, 0x40EFD1U, 0x593620U, 0x1225BFU, 0x6BCF76U, 0x605E40U, 0xBA6599U, 0xF3B66AU, 0xE8AEF7U, 0x851DBCU, + 0x9EC649U, 0xD5D5D2U, 0x8C2C27U, 0x863E7CU, 0xDFB5D9U, 0xF4C002U, 0xA55BDFU, 0xEEE9ECU, 0x75B020U, 0x3C23D3U, + 0x06584AU, 0x4FCB15U, 0x1453A4U, 0x1F306BU, 0x42AB9AU, 0x09FA05U, 0x30415CU, 0x7A53ABU, 0x61AA22U, 0x2839D5U, + 0xF3228CU, 0xDAD032U, 0x89C9E3U, 0x820A2CU, 0xCAB91DU, 0x91A4C6U, 0x985673U, 0xE34DB8U, 0xA8DCE5U, 0xB52756U, + 0xFE358BU, 0xE6EE78U, 0x0DDF75U, 0x5654AFU, 0x5F075AU, 0x04BFC1U, 0x0D2CB4U, 0x56577FU, 0x34C6C2U, 0x2D9D11U, + 0x662F48U, 0x3FB4FFU, 0x34E536U, 0x4F4E89U, 0xC61C58U, 0x988107U, 0xD132A7U, 0xCA6978U, 0x81D881U, 0xB8C296U, + 0xF3114FU, 0xAA2AA8U, 0xA0FB31U, 0xF37142U, 0xDA429FU, 0x819B24U, 0x4888E1U, 0x5333FAU, 0x1AE30FU, 0x40D0D5U, + 0x6F0B68U, 0x36182BU, 0x3DA0F6U, 0x646345U, 0x2F7898U, 0x14CDF3U, 0x5C9666U, 0xC704BDU, 0x8E7F4CU, 0xDDEED3U, + 0xD655BAU, 0xAF062DU, 0xE49EF5U, 0xFDFD02U, 0xB7661BU, 0xA8F7F4U, 0xC18D25U, 0x9A1E9AU, 0x9305CBU, 0x48F414U, + 0x43EFB5U, 0x1B1D6AU, 0x708413U, 0x698780U, 0x2A7C4DU, 0x6168BFU, 0x78F3A2U, 0x130059U, 0x0B1BCCU, 0x40CA07U, + 0x1FF072U, 0x9663E9U, 0xCD9A14U, 0xE499C7U, 0xBF0AEAU, 0xF57239U, 0xECE1E4U, 0xA7BA5FU, 0xDE098FU, 0xD591E0U, + 0x86E271U, 0x8F79AEU, 0xD52817U, 0x1C8350U, 0x2711A9U, 0x684C3EU, 0x71FFE7U, 0x3AE490U, 0x633619U, 0x498FE6U, + 0x10DC37U, 0x1B670DU, 0x4066D8U, 0x09BC13U, 0x328FAEU, 0xFB16FDU, 0xA9C500U, 0xA2FF93U, 0xFB2C5EU, 0xF03565U, + 0x8D86B0U, 0xC65D4BU, 0xDD7DCEU, 0x95E615U, 0x8EB169U, 0xE708FAU, 0xBCDB03U, 0x37C1C4U, 0x6E72FDU, 0x25232AU, + 0x3DB8F3U, 0x5ECA4CU, 0x45430DU, 0x0CF0B2U, 0x57AB61U, 0x5E3ABCU, 0x210087U, 0x2BD343U, 0xF248B8U, 0xB9392DU, + 0xA0A376U, 0xEBB09FU, 0x905908U, 0x99CAF1U, 0xD3F5A6U, 0xCA251FU, 0x813ED0U, 0xF2CD01U, 0xFBD63EU, 0xA046EEU, + 0x29BD51U, 0x76AE98U, 0x3C274FU, 0x055476U, 0x4ECEA5U, 0x573F58U, 0x1C24DBU, 0x47B786U, 0x6ECC7DU, 0x345CE8U, + 0x7D0703U, 0x66B456U, 0xAF3DECU, 0xBC6F31U, 0xD7D0A2U, 0x8EC1CFU, 0x80321CU, 0xD9A9A1U, 0xD2FB7AU, 0xA9422BU, + 0xE05184U, 0xFB8A55U, 0xB22AAAU, 0xE831B3U, 0x63E264U, 0x1ADB8CU, 0x11081BU, 0x4832E2U, 0x0BA1BDU, 0x10781CU, + 0x784BC3U, 0x679052U, 0x2E902DU, 0x752BFCU, 0x7EFC57U, 0x27C58AU, 0xCC57D9U, 0xD40C64U, 0x9FBFB6U, 0x84665BU, + 0xCD7540U, 0xB6CF95U, 0xBF8E6EU, 0xE415FBU, 0xE62690U, 0xBFFE0DU, 0xF04DFEU, 0xC91623U, 0x028520U, 0x19BCD9U, + 0x506E06U, 0x0AEDB6U, 0x23D4E9U, 0x780728U, 0x331997U, 0x3AE84EU, 0x6173B9U, 0x6840A0U, 0x129B67U, 0x598B9EU, + 0xC87009U, 0x877370U, 0x9EEAEBU, 0xF5190EU, 0xAC03D4U, 0xA690C1U, 0xFDE93AU, 0xB47AF7U, 0xAF8044U, 0xC69119U, + 0xDD0ACAU, 0x166977U, 0x4EF0BCU, 0x45E2C9U, 0x3C1D52U, 0x3F8E87U, 0x64D73CU, 0x296574U, 0x327E83U, 0x7A8F1AU, + 0x0114EDU, 0x0A1734U, 0x53EF3BU, 0xD8FCCAU, 0x812715U, 0xEA94A4U, 0xF185EBU, 0xB95F3AU, 0xA26C85U, 0xEBB55CU, + 0xB0862AU, 0x930CA3U, 0xCEDD70U, 0x85E6CDU, 0x9D7196U, 0x562A63U, 0x6D9AE8U, 0x24411DU, 0x7F5246U, 0x76EBDBU, + 0x2DB928U, 0x2712E5U, 0x5E83D7U, 0x15D80AU, 0x0C6BD1U, 0x473170U, 0x54A02FU, 0xB99B9EU, 0xE34841U, 0xEAD090U, + 0xB1E33FU, 0xFA2866U, 0xE31991U, 0x88C208U, 0x8154FFU, 0xDB6FB7U, 0x92BE28U, 0x89A5D9U, 0xE25606U, 0x7BCE37U, + 0x30FDFCU, 0x693E21U, 0x6F2792U, 0x3495CFU, 0x5DCE6CU, 0x465DB1U, 0x0FA46AU, 0x14B75FU, 0x5F2D85U, 0x275C60U, + 0x2CC7FBU, 0xF56486U, 0xFE3C55U, 0xA5ABC8U, 0xECD02BU, 0xD743F2U, 0x9FDAC5U, 0xC0A81CU, 0xC33383U, 0x9A2262U, + 0xB1D93DU, 0xE8DA8DU, 0x232252U, 0x39B19BU, 0x70AAACU, 0x6B5975U, 0x024182U, 0x59921BU, 0x522974U, 0x0B38A5U, + 0x01F33EU, 0x78C1CBU, 0x3758D0U, 0x242F3DU, 0xEDB4EFU, 0xB66672U, 0xBF5701U, 0xC5CCDCU, 0xCE9F77U, 0x9726A2U, + 0xDCA4F9U, 0xC5FF4CU, 0xAE4E87U, 0xB51576U, 0xFDA7E9U, 0xA63C90U, 0x2F6D47U, 0x74D6CFU, 0x1BC538U, 0x0A1D21U, + 0x413EDEU, 0x58E50FU, 0x127480U, 0x6B4BF1U, 0x60992EU, 0x2BA297U, 0x327340U, 0x79E809U, 0xA0DABAU, 0x8A0367U, + 0xD1009DU, 0x98BB98U, 0x836A63U, 0xCE70F6U, 0xF5832DU, 0xB69850U, 0xEE29D3U, 0xE5732EU, 0xBCE0FDU, 0xB75962U, + 0x4C1A13U, 0x0589DCU, 0x1EF165U, 0x5666B7U, 0x4DFDEAU, 0x268E59U, 0x7F1794U, 0x74256FU, 0x29FE7AU, 0x626F81U, + 0x700404U, 0x1996DFU, 0x828FA2U, 0xCB7C31U, 0x9067CCU, 0x9B940EU, 0xE20C17U, 0xE81FE8U, 0xB1E439U, 0xFAF586U, + 0xE17FC7U, 0xA88C18U, 0xD397A1U, 0x5E4276U, 0x04794FU, 0x0FEB88U, 0x5E9271U, 0x3501E6U, 0x2C9A3EU, 0x67EA51U, + 0x7C61C0U, 0x34323BU, 0x6F89EEU, 0x4618F5U, 0x1D4218U, 0xD4F1CBU, 0xCFE876U, 0x841B25U, 0xB888F8U, 0xF3D053U, + 0xAA7386U, 0xA168BCU, 0xF2BB69U, 0xFB8792U, 0x80541FU, 0xC8CF4CU, 0xC3FEB5U, 0x182522U, 0x1117CBU, 0x6A9E9CU, + 0x234D05U, 0x3876FAU, 0x72A42BU, 0x2FBD84U, 0x240ED4U, 0x5DD54BU, 0x56C4B2U, 0x057E65U, 0x4C2D4CU, 0xD7849BU, + 0xBFD762U, 0xA44DF9U, 0xEFFEACU, 0xB6A347U, 0xBD30D2U, 0xC40B29U, 0x8FDB74U, 0x9540E6U, 0xDC330BU, 0xC3BAD8U, + 0x8A89E5U, 0x71533EU, 0x7AC0BBU, 0x2BB140U, 0x212A11U, 0x7838AEU, 0x13C17FU, 0x08D290U, 0x414989U, 0x1AA85EU, + 0x13B2A6U, 0x494131U, 0x625AD8U, 0xBBCF87U, 0xF43516U, 0xED26E9U, 0xA6BF78U, 0x9FCC17U, 0xDD57CEU, 0x86B75DU, + 0x8FACA0U, 0xD43FE3U, 0x9D445EU, 0xA6D584U, 0x6DCF71U, 0x753C6AU, 0x3EA5AFU, 0x67F654U, 0x4C4CC9U, 0x134DBAU, + 0x1AB667U, 0x4125E4U, 0x097E19U, 0x12CA0AU, 0x71D1F3U, 0x78022CU, 0xA33BACU, 0xEAA953U, 0xF17A02U, 0x9B53BDU, + 0xC28074U, 0xC9BB83U, 0x90299AU, 0x9BF04DU, 0xC4C3B4U, 0xAD583BU, 0xB7084AU, 0xFEB3D1U, 0x656004U, 0x2E69FEU, + 0x5FDAF3U, 0x548000U, 0x0D37DDU, 0x472E4EU, 0x5CFD33U, 0x1546F8U, 0x2E164DU, 0x678D96U, 0x3CBEE3U, 0x337768U, + 0xEBE5BDU, 0xC09E47U, 0x990D5EU, 0xD234A9U, 0xC9E720U, 0x887DF7U, 0xD34C0EU, 0xFB9711U, 0xA084E0U, 0xA96C2FU, + 0xF27FBEU, 0xB9E4C1U, 0x001318U, 0x4B02AFU, 0x56B867U, 0x1CEB30U, 0x477289U, 0x4E8152U, 0x358AF7U, 0x3C1AACU, + 0x676159U, 0x24F2C2U, 0x3C6917U, 0x57197CU, 0x8E82E1U, 0x85F112U, 0xDE68CFU, 0xD77BDDU, 0x8C9130U, 0xE400EBU, + 0xFB5B5EU, 0xB0E885U, 0xA9F6D4U, 0xE2277BU, 0x9B9CA2U, 0x108F15U, 0x5A764CU, 0x0B64ABU, 0x00AF32U, 0x599CEDU, + 0x72059DU, 0x29D702U, 0x60ECE3U, 0x7A7D3CU, 0x330625U, 0x0C95D6U, 0x474D0BU, 0x9E7EA8U, 0x95FDF5U, 0xCCA666U, + 0x86179BU, 0xBD8D40U, 0xFCDA65U, 0xE763BFU, 0xAE304AU, 0xF58AD1U, 0xDE9B9CU, 0x86406FU, 0x8DE3F2U, 0x54B801U, + 0x1B28D8U, 0x0213D7U, 0x69C026U, 0x7259B9U, 0x3A6B48U, 0x61B017U, 0x68819FU, 0x135A68U, 0x50D9B1U, 0x49E386U, + 0x02325FU, 0x9A29B0U, 0xD19E23U, 0xAAC77EU, 0xA3558DU, 0xFCAE04U, 0xF5BFF3U, 0xAE04AAU, 0xC44635U, 0xDDDDC5U, + 0x966C4AU, 0xCF373BU, 0xC4A4E4U, 0x1FD47DU, 0x3E4F8AU, 0x64DC43U, 0x2DA574U, 0x3637ADU, 0x7D5C56U, 0x44CFC3U, + 0x0BD688U, 0x52257DU, 0x59BBE7U, 0x03AA1AU, 0x4A5119U, 0xF142C4U, 0xB89A37U, 0xB329AAU, 0xE822D1U, 0xA9D114U, + 0x93C88FU, 0xDA5A7AU, 0xC1A121U, 0x8AB090U, 0xD36B5EU, 0xDC58A7U, 0xA5C0B0U, 0x2F8369U, 0x74389EU, 0x3DAB17U, + 0x26D368U, 0x4F40F9U, 0x141F26U, 0x1DAEC7U, 0x473558U, 0x446721U, 0x1DDEF6U, 0x769D6EU, 0xEF0E8DU, 0xA434D0U, + 0xBFE56BU, 0xF35EBEU, 0x884D45U, 0x819440U, 0xDAA69BU, 0x917D26U, 0x88ECF5U, 0xC3C788U, 0xFB150BU, 0xB02ED6U, + 0x63BF24U, 0x6A6439U, 0x3153D2U, 0x188B03U, 0x43989CU, 0x0923EDU, 0x147232U, 0x5FF99BU, 0x060B4CU, 0x2D10B5U, + 0x76A1A2U, 0x7FFA7BU, 0xA568D4U, 0xECD104U, 0xD7827BU, 0x9C19EAU, 0x8D6831U, 0xC6E2DCU, 0x9F71CFU, 0x950A32U, + 0xEE9BE1U, 0xA3A16CU, 0xB8761FU, 0xF16FC2U, 0x6A9C79U, 0x010FACU, 0x491786U, 0x52F453U, 0x1BEF88U, 0x007C35U, + 0x4B8566U, 0x32978FU, 0x316C18U, 0x697DC1U, 0x62E6BEU, 0x3B142FU, 0xD40DC0U, 0xCFCE11U, 0x86F58EU, 0xDD66F6U, + 0xD53E31U, 0x8E8988U, 0xA5125FU, 0xFC6366U, 0xB7F9B9U, 0xAEAA78U, 0xE513C3U, 0xD69096U, 0x1ECB6DU, 0x4579F8U, + 0x4C6033U, 0x13B34EU, 0x5888DCU, 0x615821U, 0x2AE3F2U, 0x32F0FFU, 0x792B04U, 0x220A91U, 0x0B906AU, 0xD0432BU, + 0xD97294U, 0x82AD4DU, 0xC8BE9AU, 0xD90623U, 0xB2D564U, 0xEBEE9CU, 0xE02D03U, 0xBF35D2U, 0xB686ADU, 0xCCDD2CU, + 0x854CD3U, 0x1EF70AU, 0x55A51DU, 0x4C1CE4U, 0x074F67U, 0x7ED49AU, 0x7476C9U, 0x2F2F75U, 0x26BCBEU, 0x75876BU, + 0x1C5650U, 0x07C885U, 0x48BB7EU, 0x9022F3U, 0x9B11A0U, 0xC2CA5DU, 0xE9C8CEU, 0xA07133U, 0xFBA238U, 0xF0B9E9U, + 0xA84917U, 0x835286U, 0xDAC179U, 0x913830U, 0x822B87U, 0x4BD95EU, 0x30D289U, 0x3C43A0U, 0x67B87FU, 0x6CAA8EU, + 0x353311U, 0x7E4440U, 0x47DFABU, 0x0C8E3FU, 0x1634C4U, 0x5FA7D9U, 0x04CC0AU, 0xAD5DE7U, 0xF64774U, 0xBDB409U, + 0xAC2DD2U, 0xE67E67U, 0xFBC5ACU, 0x90D5F9U, 0xCB0E42U, 0xC23D9FU, 0x99B67DU, 0x9047E4U, 0xEA5DB3U, 0x218E0AU, + 0x38B7D5U, 0x732034U, 0x6AFA2BU, 0x21CBFAU, 0x5A1005U, 0x5B039CU, 0x01A8FBU, 0x4C7822U, 0x574395U, 0x3CD04DU, + 0xA5811AU, 0xEE3BB3U, 0xB76868U, 0xBDF19DU, 0xE64286U, 0xCF1943U, 0x949BF8U, 0xDDA225U, 0xC67156U, 0x8FCACBU, + 0xF59B08U, 0xF605F5U, 0x2B36EFU, 0x20EF1AU, 0x797CC1U, 0x324664U, 0x1985BFU, 0x419CE4U, 0x4A6F51U, 0x13748AU, + 0x58C42FU, 0x631F74U, 0x2A0CA1U, 0x71F51AU, 0xF9E7D7U, 0xA27CA5U, 0xA99F38U, 0xD886EBU, 0x973516U, 0x8E6F1DU, + 0xC5FEECU, 0xDF0133U, 0xB61282U, 0xED8ADDU, 0xE4F954U, 0xBF7AA3U, 0x74617AU, 0x6D904DU, 0x070A95U, 0x1E795AU, + 0x55E0EBU, 0x0EF334U, 0x0F0845U, 0x7098CAU, 0x798313U, 0x2360E0U, 0x687BFDU, 0x71AB0EU, 0xBA10C3U, 0x830370U, + 0xC8FA2DU, 0x93EDB7U, 0x9B3742U, 0xC00689U, 0xA99DBCU, 0xB25E67U, 0xF964BAU, 0xE0F509U, 0xA7AE44U, 0xFF1DB7U, + 0x54C42EU, 0x0DF6F1U, 0x066D90U, 0x5D3C0EU, 0x1487FFU, 0x2F8460U, 0x675E19U, 0x3CEFDEU, 0x37B447U, 0x6E27B0U, + 0x651369U, 0x9CC856U, 0xD77B97U, 0xC9604CU, 0x88B1F9U, 0x939BA2U, 0xFA4856U, 0xB1D1DDU, 0xAAE200U, 0xE33873U, + 0xB829EEU, 0xB0D20DU, 0xCBC190U, 0x407AEBU, 0x19AA3EU, 0x52A1A5U, 0x4B1240U, 0x204B1BU, 0x3ED9A2U, 0x7F2274U, + 0x2437ADU, 0x2DAC8AU, 0x76DF53U, 0x5D45ACU, 0x04F43DU, 0xCEBFE2U, 0xD72CC3U, 0x9C551CU, 0xE7C7E5U, 0xEEDC72U, + 0xB52D1BU, 0xBCB6CCU, 0xE6A454U, 0xA95FA7U, 0x904EFAU, 0xD3A551U, 0xCA3684U, 0x01265FU, 0x5ADD6AU, 0x72CEB1U, + 0x29135CU, 0x60A1CFU, 0x7BBA92U, 0x304921U, 0x2950FCU, 0x42D316U, 0x1AA903U, 0x1138F8U, 0x48E329U, 0xC7D0A6U, + 0xBC48DFU, 0xFD1B08U, 0xE6A0B1U, 0xAE3366U, 0xF55AAFU, 0xFEC898U, 0x879341U, 0x8C22FEU, 0xD5392EU, 0x9EEA61U, + 0x8456D0U, 0x6D450BU, 0x769EF6U, 0x3FADE5U, 0x606508U, 0x6BD6DBU, 0x3ACD46U, 0x101C3DU, 0x5927F8U, 0x02F543U, + 0x096C96U, 0x505FCCU, 0xBB8C71U, 0xA296B2U, 0xE8370FU, 0xF36C5CU, 0xBADF85U, 0xE1063AU, 0xC814FBU, 0x97AF04U, + 0x9CFA15U, 0xC461EAU, 0x87D23BU, 0xBE88B4U, 0x7509CCU, 0x2E721BU, 0x27E1A2U, 0x7C5965U, 0x750A7CU, 0x0F9183U, + 0x44A052U, 0x5D7BE9U, 0x1669ACU, 0x0F9277U, 0x6013CAU, 0x3B0819U, 0xB3FA65U, 0xE0E3E6U, 0xA9103BU, 0xB28BC0U, + 0xDB9ED5U, 0xC0642EU, 0x8B77EBU, 0xD3EC50U, 0xD80D89U, 0xA1179EU, 0xAAC477U, 0xF1F5A0U, 0x386E19U, 0x271D4FU, + 0x6F8596U, 0x541639U, 0x1F6DE8U, 0x4EFE97U, 0x45B706U, 0x1C05D9U, 0x779E30U, 0x6DCF27U, 0x2474DEU, 0x3F664DU, + 0xF69BB0U, 0xAD08FBU, 0x86536FU, 0xDFE094U, 0xD1E841U, 0x883B6AU, 0xC300B7U, 0xE8D164U, 0xB16BD9U, 0xF2788AU, + 0xEBA167U, 0xA192FCU, 0x3A0929U, 0x53DBD2U, 0x08F2C3U, 0x01212DU, 0x5A3ABCU, 0x518B43U, 0x29D11AU, 0x62628DU, + 0x7FFD64U, 0x34ACB3U, 0x6F1E8AU, 0xE64555U, 0x95C494U, 0x9D7F2BU, 0xC62C7AU, 0x8DB485U, 0x94871DU, 0xFF5CDEU, + 0xE6EFE3U, 0xADB730U, 0xF524CFU, 0xFE0F56U, 0xA5DE31U, 0x48C5E8U, 0x53377FU, 0x1AAE86U, 0x01BD59U, 0x4B4678U, + 0x3A50A7U, 0x31E977U, 0x683ACCU, 0x633189U, 0x38C072U, 0x71DAEFU, 0x4B493CU, 0x82B001U, 0x99A3C2U, 0xD2383FU, + 0x8F4AA4U, 0xA4D3D1U, 0xFDA00AU, 0xB62B8FU, 0xACBB75U, 0xE5C028U, 0xF6539BU, 0x9F4242U, 0xC4B985U, 0x4F2FBCU, + 0x167463U, 0x1CC5D2U, 0x65DE1DU, 0x2E3C4CU, 0x35A5F3U, 0x78F622U, 0x234DDDU, 0x0A5C55U, 0x408622U, 0x5BB5FBU, + 0x122E6CU, 0xC1FF95U, 0xC8C4DEU, 0xB3066BU, 0xB83FB0U, 0xE0AC25U, 0xAB775EU, 0xB24793U, 0xD9DC20U, 0x828BFDU, + 0x8F30AFU, 0xD46102U, 0xDCDBD9U, 0x07582CU, 0x6E0137U, 0x75B2C6U, 0x3EE809U, 0x2F7990U, 0x64C2E7U, 0x1C913EU, + 0x170A89U, 0x4C3A40U, 0x45E9D6U, 0x1E42AFU, 0x571370U, 0xE889C1U, 0xA2BA0EU, 0xFB635FU, 0xF070E0U, 0xA9CF39U, + 0x821DDAU, 0xD904C7U, 0x90F734U, 0x82FCE9U, 0xCB4D72U, 0xD09716U, 0x3B848DU, 0x623D78U, 0x696EA3U, 0x30F4BEU, + 0x7A075DU, 0x451E80U, 0x0C8D33U, 0x17E66EU, 0x5E76B5U, 0x050D14U, 0x0E9ECBU, 0x7607BAU, 0xF57524U, 0xACEAC5U, + 0xE7F91AU, 0xFC0083U, 0x9583F4U, 0xCED96DU, 0xC6688AU, 0x9D7353U, 0x92804CU, 0xCB11BDU, 0xA00B62U, 0xA9F8C3U, + 0x72E398U, 0x783244U, 0x2118F7U, 0x4A8B2AU, 0x5B5249U, 0x1061D4U, 0x09FA2FU, 0x428ABAU, 0x1911F1U, 0x31C604U, + 0x6AFD9FU, 0x276D62U, 0xBC2631U, 0xF795B8U, 0xCE4C4EU, 0x855F97U, 0xDDE520U, 0xD6B479U, 0x8D0FB6U, 0x8C1C07U, + 0xF7C6D8U, 0xBE77A9U, 0xA53C36U, 0xEFAFDFU, 0x369648U, 0x1D4411U, 0x40DFE6U, 0x4BEE7EU, 0x103595U, 0x5902C0U, + 0x43D85BU, 0x2AC9AEU, 0x316265U, 0x7AB158U, 0x23A18BU, 0x201A56U, 0xD949E5U, 0x93F2A8U, 0x882313U, 0xC139C6U, + 0xDA8A3CU, 0x97D329U, 0xEC50E2U, 0xE7AA13U, 0xBFBB8CU, 0xB42075U, 0xED5322U, 0x06C8ABU, 0x1DF85CU, 0x542785U, + 0x0FB4BAU, 0x0FCD7BU, 0x544FA4U, 0x7F5414U, 0x26A54BU, 0x6D3EF2U, 0x702D31U, 0x3BD7CCU, 0x13C6DFU, 0xC83D02U, + 0x83AEF9U, 0x9AB77CU, 0xD15507U, 0xC84ED2U, 0xA3DF49U, 0xF9A4BDU, 0xF836F6U, 0xA3ED4BU, 0xEADC98U, 0xD14B05U, + 0x9A30E6U, 0x03A0BFU, 0x4D6B00U, 0x1458D1U, 0x1FC12EU, 0x64932FU, 0x6D28F0U, 0x36BB09U, 0x7FE29FU, 0x6551E6U, + 0x0E0B21U, 0x57AAB8U, 0x54B147U, 0x8D6216U, 0x86DBA9U, 0xDDC968U, 0xB412F3U, 0xAA218EU, 0xE3FC5DU, 0xF86EF0U, + 0xB35523U, 0xCA945FU, 0xC1AFCCU, 0x983C11U, 0xD264FAU, 0x49D7EFU, 0x000C14U, 0x3B1FC1U, 0x7AA75AU, 0x21F4B7U, + 0x2A6FA4U, 0x728E5DU, 0x5D958AU, 0x042713U, 0x4F767DU, 0x54EDACU, 0x1D5E13U, 0x8604C0U, 0xEE91ADU, 0xB5EA36U, + 0xBC79E3U, 0xE77018U, 0xAC820DU, 0x9D19E6U, 0xD6283FU, 0xCEF3A8U, 0x85E0D1U, 0xDA1A47U, 0x538BAEU, 0x389079U, + 0x216360U, 0x6A6B9FU, 0x30D84EU, 0x3903E1U, 0x421230U, 0x0BE94FU, 0x10FBD6U, 0x5B6011U, 0x4215E8U, 0x008EFBU, + 0xF95C07U, 0xF2759CU, 0xADE659U, 0xA49D22U, 0xFF0CB7U, 0x96964CU, 0x8CE591U, 0xC77E92U, 0x9E2F6FU, 0x959CBCU, + 0xCC0601U, 0xE7475AU, 0x3CFCBFU, 0x74EF25U, 0x6717F4U, 0x2E048BU, 0x15DF0AU, 0x5A6CF5U, 0x03716CU, 0x08A33BU, + 0x5098C2U, 0x5B1945U, 0x20C2BCU, 0x69F063U, 0xF22972U, 0xBB1A8DU, 0xE0814DU, 0xCA52F6U, 0x936AABU, 0x98B958U, + 0xC9A2C5U, 0x820306U, 0x9B593BU, 0xF4CAE0U, 0xEE7315U, 0xA7209EU, 0x7C9BCBU, 0x75C930U, 0x0E54A4U, 0x45E75FU, + 0x5CBC12U, 0x173D81U, 0x0F0778U, 0x44D4AFU, 0x3FC596U, 0x363E59U, 0x65ACE8U, 0x6C9737U, 0xA346E6U, 0xD95DD9U, + 0xD0FE10U, 0x8B26E6U, 0xC2357FU, 0xD9CE28U, 0x92DDC1U, 0xAB455EU, 0xE1B6AFU, 0xB8ADF4U, 0xB35861U, 0x68438AU, + 0x41C157U, 0x12B864U, 0x5B2BB9U, 0x45B00AU, 0x0EC3C6U, 0x175B95U, 0x7C2828U, 0x25B3F3U, 0x2E2206U, 0x75580DU, + 0x3DDBD8U, 0x86C223U, 0xCF31BAU, 0xD4AADDU, 0x9FF804U, 0xC64193U, 0xCD526AU, 0xBDA9F4U, 0xB2BD95U, 0xE92E4AU, + 0xA0C5FBU, 0xBBD424U, 0xD20F7DU, 0x093DDAU, 0x01A603U, 0x5A77F0U, 0x514CEDU, 0x089E36U, 0x63A7D3U, 0x7A3448U, + 0x31FF3CU, 0x2BCEE7U, 0x625462U, 0x150799U, 0x1CBC84U, 0xC7ED77U, 0x8C76AAU, 0x95C409U, 0xDF9954U, 0xE62A8FU, + 0xAD213EU, 0xF6F1E1U, 0xFF4A00U, 0xA4191EU, 0x8D82C7U, 0xD7B330U, 0x9C69A9U, 0x057ACEU, 0x42C357U, 0x2B1088U, + 0x303A79U, 0x7BEB76U, 0x63F087U, 0x284358U, 0x7198E1U, 0x5A88B2U, 0x017B7EU, 0x0860CDU, 0x53F510U, 0x9A0F63U, + 0xA00CFEU, 0xEBB535U, 0xF2E6C0U, 0xB97DDBU, 0xEC0F2EU, 0xE796B5U, 0x9C0578U, 0xD47E0BU, 0xCFEF92U, 0x86F564U, + 0x1D16ADU, 0x768F32U, 0x2FFC43U, 0x24669CU, 0x7C752DU, 0x778CE2U, 0x2E1F9BU, 0x45000CU, 0x5EF0D5U, 0x13FB62U, + 0x40282BU, 0x4811D4U, 0xB38344U, 0xB8789FU, 0xE16BEAU, 0xAAB261U, 0xB38194U, 0xF81B4FU, 0xC2CA52U, 0x8BE1B1U, + 0xD0726CU, 0xD903DFU, 0x829982U, 0xE94A79U, 0x7471FDU, 0x36E026U, 0x2FBA93U, 0x640DC8U, 0x3F1431U, 0x16D7B6U, + 0x4D6C6FU, 0x443C18U, 0x1E8781U, 0x55947EU, 0x6C4FBFU, 0x27FFA0U, 0xBEE451U, 0xF5378FU, 0xAE0E2EU, 0xA2CD71U, + 0xC9D7C8U, 0x98661FU, 0x93BDC6U, 0xC88EE5U, 0xC15438U, 0xBA45C3U, 0xF2FE56U, 0xE9290DU, 0x2230E8U, 0x3B9273U, + 0x70C98FU, 0x0958DCU, 0x02A343U, 0x58B0A2U, 0x150A7DU, 0x0E5BC4U, 0x6FC897U, 0x74F33AU, 0x3F23E9U, 0x66A834U, + 0xECDB0FU, 0xB542DAU, 0x9E5131U, 0xC7ABA5U, 0x8C38FEU, 0x97010BU, 0xDED290U, 0xA4CC7DU, 0xAD3D2EU, 0xF6B6B3U, + 0xF9A540U, 0x205ED9U, 0x634EB6U, 0x5A9567U, 0x11A6D8U, 0x0B3F09U +}; const unsigned int DMR_A_TABLE[] = {0U, 4U, 8U, 12U, 16U, 20U, 24U, 28U, 32U, 36U, 40U, 44U, - 48U, 52U, 56U, 60U, 64U, 68U, 1U, 5U, 9U, 13U, 17U, 21U}; + 48U, 52U, 56U, 60U, 64U, 68U, 1U, 5U, 9U, 13U, 17U, 21U + }; const unsigned int DMR_B_TABLE[] = {25U, 29U, 33U, 37U, 41U, 45U, 49U, 53U, 57U, 61U, 65U, 69U, - 2U, 6U, 10U, 14U, 18U, 22U, 26U, 30U, 34U, 38U, 42U}; + 2U, 6U, 10U, 14U, 18U, 22U, 26U, 30U, 34U, 38U, 42U + }; const unsigned int DMR_C_TABLE[] = {46U, 50U, 54U, 58U, 62U, 66U, 70U, 3U, 7U, 11U, 15U, 19U, 23U, - 27U, 31U, 35U, 39U, 43U, 47U, 51U, 55U, 59U, 63U, 67U, 71U}; + 27U, 31U, 35U, 39U, 43U, 47U, 51U, 55U, 59U, 63U, 67U, 71U + }; const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U}; -const unsigned int INTERLEAVE_TABLE_26_4[] = { - 0U, 4U, 8U, 12U, 16U, 20U, 24U, 28U, 32U, 36U, 40U, 44U, 48U, 52U, 56U, 60U, 64U, 68U, 72U, 76U, 80U, 84U, 88U, 92U, 96U, 100U, - 1U, 5U, 9U, 13U, 17U, 21U, 25U, 29U, 33U, 37U, 41U, 45U, 49U, 53U, 57U, 61U, 65U, 69U, 73U, 77U, 81U, 85U, 89U, 93U, 97U, 101U, - 2U, 6U, 10U, 14U, 18U, 22U, 26U, 30U, 34U, 38U, 42U, 46U, 50U, 54U, 58U, 62U, 66U, 70U, 74U, 78U, 82U, 86U, 90U, 94U, 98U, 102U, - 3U, 7U, 11U, 15U, 19U, 23U, 27U, 31U, 35U, 39U, 43U, 47U, 51U, 55U, 59U, 63U, 67U, 71U, 75U, 79U, 83U, 87U, 91U, 95U, 99U, 103U}; +const unsigned int INTERLEAVE_TABLE_26_4[] = +{ + 0U, 4U, 8U, 12U, 16U, 20U, 24U, 28U, 32U, 36U, 40U, 44U, 48U, 52U, 56U, 60U, 64U, 68U, 72U, 76U, 80U, 84U, 88U, 92U, 96U, 100U, + 1U, 5U, 9U, 13U, 17U, 21U, 25U, 29U, 33U, 37U, 41U, 45U, 49U, 53U, 57U, 61U, 65U, 69U, 73U, 77U, 81U, 85U, 89U, 93U, 97U, 101U, + 2U, 6U, 10U, 14U, 18U, 22U, 26U, 30U, 34U, 38U, 42U, 46U, 50U, 54U, 58U, 62U, 66U, 70U, 74U, 78U, 82U, 86U, 90U, 94U, 98U, 102U, + 3U, 7U, 11U, 15U, 19U, 23U, 27U, 31U, 35U, 39U, 43U, 47U, 51U, 55U, 59U, 63U, 67U, 71U, 75U, 79U, 83U, 87U, 91U, 95U, 99U, 103U +}; const unsigned char WHITENING_DATA[] = {0x93U, 0xD7U, 0x51U, 0x21U, 0x9CU, 0x2FU, 0x6CU, 0xD0U, 0xEFU, 0x0FU, - 0xF8U, 0x3DU, 0xF1U, 0x73U, 0x20U, 0x94U, 0xEDU, 0x1EU, 0x7CU, 0xD8U}; + 0xF8U, 0x3DU, 0xF1U, 0x73U, 0x20U, 0x94U, 0xEDU, 0x1EU, 0x7CU, 0xD8U + }; //////////////////////////////////////////////////////////////////////////////////////// // macros @@ -476,166 +484,183 @@ const unsigned char WHITENING_DATA[] = {0x93U, 0xD7U, 0x51U, 0x21U, 0x9CU, 0x2FU void CYsfUtils::DecodeVD2Vchs(uint8 *data, uint8 **ambe) { - int frame = 0; - - data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; - - unsigned int offset = 40U; // DCH(0) - - // We have a total of 5 VCH sections, iterate through each - for (unsigned int j = 0U; j < 5U; j++, offset += 144U) { - - unsigned char vch[13U]; - unsigned int dat_a = 0U; - unsigned int dat_b = 0U; - unsigned int dat_c = 0U; - - // Deinterleave - for (unsigned int i = 0U; i < 104U; i++) { - unsigned int n = INTERLEAVE_TABLE_26_4[i]; - bool s = READ_BIT(data, offset + n); - WRITE_BIT(vch, i, s); - } - - // "Un-whiten" (descramble) - for (unsigned int i = 0U; i < 13U; i++) - vch[i] ^= WHITENING_DATA[i]; - - for (unsigned int i = 0U; i < 12U; i++) { - dat_a <<= 1U; - if (READ_BIT(vch, 3U*i + 1U)) - dat_a |= 0x01U;; - } - - for (unsigned int i = 0U; i < 12U; i++) { - dat_b <<= 1U; - if (READ_BIT(vch, 3U*(i + 12U) + 1U)) - dat_b |= 0x01U;; - } - - for (unsigned int i = 0U; i < 3U; i++) { - dat_c <<= 1U; - if (READ_BIT(vch, 3U*(i + 24U) + 1U)) - dat_c |= 0x01U;; - } - - for (unsigned int i = 0U; i < 22U; i++) { - dat_c <<= 1U; - if (READ_BIT(vch, i + 81U)) - dat_c |= 0x01U;; - } - - // convert to ambe2plus - unsigned char v_dmr[9U]; - - unsigned int a = CGolay24128::encode24128(dat_a); - unsigned int p = PRNG_TABLE[dat_a] >> 1; - unsigned int b = CGolay24128::encode23127(dat_b) >> 1; - b ^= p; - - unsigned int MASK = 0x800000U; - for (unsigned int i = 0U; i < 24U; i++, MASK >>= 1) { - unsigned int aPos = DMR_A_TABLE[i]; - WRITE_BIT(v_dmr, aPos, a & MASK); - } - - MASK = 0x400000U; - for (unsigned int i = 0U; i < 23U; i++, MASK >>= 1) { - unsigned int bPos = DMR_B_TABLE[i]; - WRITE_BIT(v_dmr, bPos, b & MASK); - } - - MASK = 0x1000000U; - for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) { - unsigned int cPos = DMR_C_TABLE[i]; - WRITE_BIT(v_dmr, cPos, dat_c & MASK); - } - - ::memcpy(ambe[frame++], v_dmr, 9); - } + int frame = 0; + + data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; + + unsigned int offset = 40U; // DCH(0) + + // We have a total of 5 VCH sections, iterate through each + for (unsigned int j = 0U; j < 5U; j++, offset += 144U) + { + + unsigned char vch[13U]; + unsigned int dat_a = 0U; + unsigned int dat_b = 0U; + unsigned int dat_c = 0U; + + // Deinterleave + for (unsigned int i = 0U; i < 104U; i++) + { + unsigned int n = INTERLEAVE_TABLE_26_4[i]; + bool s = READ_BIT(data, offset + n); + WRITE_BIT(vch, i, s); + } + + // "Un-whiten" (descramble) + for (unsigned int i = 0U; i < 13U; i++) + vch[i] ^= WHITENING_DATA[i]; + + for (unsigned int i = 0U; i < 12U; i++) + { + dat_a <<= 1U; + if (READ_BIT(vch, 3U*i + 1U)) + dat_a |= 0x01U; + } + + for (unsigned int i = 0U; i < 12U; i++) + { + dat_b <<= 1U; + if (READ_BIT(vch, 3U*(i + 12U) + 1U)) + dat_b |= 0x01U; + } + + for (unsigned int i = 0U; i < 3U; i++) + { + dat_c <<= 1U; + if (READ_BIT(vch, 3U*(i + 24U) + 1U)) + dat_c |= 0x01U; + } + + for (unsigned int i = 0U; i < 22U; i++) + { + dat_c <<= 1U; + if (READ_BIT(vch, i + 81U)) + dat_c |= 0x01U; + } + + // convert to ambe2plus + unsigned char v_dmr[9U]; + + unsigned int a = CGolay24128::encode24128(dat_a); + unsigned int p = PRNG_TABLE[dat_a] >> 1; + unsigned int b = CGolay24128::encode23127(dat_b) >> 1; + b ^= p; + + unsigned int MASK = 0x800000U; + for (unsigned int i = 0U; i < 24U; i++, MASK >>= 1) + { + unsigned int aPos = DMR_A_TABLE[i]; + WRITE_BIT(v_dmr, aPos, a & MASK); + } + + MASK = 0x400000U; + for (unsigned int i = 0U; i < 23U; i++, MASK >>= 1) + { + unsigned int bPos = DMR_B_TABLE[i]; + WRITE_BIT(v_dmr, bPos, b & MASK); + } + + MASK = 0x1000000U; + for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) + { + unsigned int cPos = DMR_C_TABLE[i]; + WRITE_BIT(v_dmr, cPos, dat_c & MASK); + } + + ::memcpy(ambe[frame++], v_dmr, 9); + } } void CYsfUtils::EncodeVD2Vch(uint8 *ambe, uint8 *data) { - // convert from ambe2plus - unsigned int a = 0U; - unsigned int MASK = 0x800000U; - for (unsigned int i = 0U; i < 24U; i++, MASK >>= 1) { - unsigned int aPos = DMR_A_TABLE[i]; - - if (READ_BIT(ambe, aPos)) - a |= MASK; - } - - unsigned int b = 0U; - MASK = 0x400000U; - for (unsigned int i = 0U; i < 23U; i++, MASK >>= 1) { - unsigned int bPos = DMR_B_TABLE[i]; - - if (READ_BIT(ambe, bPos)) - b |= MASK; - } - - unsigned int dat_c = 0U; - MASK = 0x1000000U; - for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) { - unsigned int cPos = DMR_C_TABLE[i]; - - if (READ_BIT(ambe, cPos)) - dat_c |= MASK; - } - - // and to vch - unsigned char vch[13U]; - unsigned char ysfFrame[13U]; - ::memset(vch, 0U, 13U); - ::memset(ysfFrame, 0, 13U); - - unsigned int dat_a = a >> 12; - - // The PRNG - b ^= (PRNG_TABLE[dat_a] >> 1); - - unsigned int dat_b = b >> 11; - - for (unsigned int i = 0U; i < 12U; i++) { - bool s = (dat_a << (20U + i)) & 0x80000000U; - WRITE_BIT(vch, 3*i + 0U, s); - WRITE_BIT(vch, 3*i + 1U, s); - WRITE_BIT(vch, 3*i + 2U, s); - } - - for (unsigned int i = 0U; i < 12U; i++) { - bool s = (dat_b << (20U + i)) & 0x80000000U; - WRITE_BIT(vch, 3*(i + 12U) + 0U, s); - WRITE_BIT(vch, 3*(i + 12U) + 1U, s); - WRITE_BIT(vch, 3*(i + 12U) + 2U, s); - } - - for (unsigned int i = 0U; i < 3U; i++) { - bool s = (dat_c << (7U + i)) & 0x80000000U; - WRITE_BIT(vch, 3*(i + 24U) + 0U, s); - WRITE_BIT(vch, 3*(i + 24U) + 1U, s); - WRITE_BIT(vch, 3*(i + 24U) + 2U, s); - } - - for (unsigned int i = 0U; i < 22U; i++) { - bool s = (dat_c << (10U + i)) & 0x80000000U; - WRITE_BIT(vch, i + 81U, s); - } - - WRITE_BIT(vch, 103U, 0U); - - // Scramble - for (unsigned int i = 0U; i < 13U; i++) - vch[i] ^= WHITENING_DATA[i]; - - // Interleave - for (unsigned int i = 0U; i < 104U; i++) { - unsigned int n = INTERLEAVE_TABLE_26_4[i]; - bool s = READ_BIT(vch, i); - WRITE_BIT(ysfFrame, n, s); - } - - ::memcpy(data, ysfFrame, 13U); - } + // convert from ambe2plus + unsigned int a = 0U; + unsigned int MASK = 0x800000U; + for (unsigned int i = 0U; i < 24U; i++, MASK >>= 1) + { + unsigned int aPos = DMR_A_TABLE[i]; + + if (READ_BIT(ambe, aPos)) + a |= MASK; + } + + unsigned int b = 0U; + MASK = 0x400000U; + for (unsigned int i = 0U; i < 23U; i++, MASK >>= 1) + { + unsigned int bPos = DMR_B_TABLE[i]; + + if (READ_BIT(ambe, bPos)) + b |= MASK; + } + + unsigned int dat_c = 0U; + MASK = 0x1000000U; + for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) + { + unsigned int cPos = DMR_C_TABLE[i]; + + if (READ_BIT(ambe, cPos)) + dat_c |= MASK; + } + + // and to vch + unsigned char vch[13U]; + unsigned char ysfFrame[13U]; + ::memset(vch, 0U, 13U); + ::memset(ysfFrame, 0, 13U); + + unsigned int dat_a = a >> 12; + + // The PRNG + b ^= (PRNG_TABLE[dat_a] >> 1); + + unsigned int dat_b = b >> 11; + + for (unsigned int i = 0U; i < 12U; i++) + { + bool s = (dat_a << (20U + i)) & 0x80000000U; + WRITE_BIT(vch, 3*i + 0U, s); + WRITE_BIT(vch, 3*i + 1U, s); + WRITE_BIT(vch, 3*i + 2U, s); + } + + for (unsigned int i = 0U; i < 12U; i++) + { + bool s = (dat_b << (20U + i)) & 0x80000000U; + WRITE_BIT(vch, 3*(i + 12U) + 0U, s); + WRITE_BIT(vch, 3*(i + 12U) + 1U, s); + WRITE_BIT(vch, 3*(i + 12U) + 2U, s); + } + + for (unsigned int i = 0U; i < 3U; i++) + { + bool s = (dat_c << (7U + i)) & 0x80000000U; + WRITE_BIT(vch, 3*(i + 24U) + 0U, s); + WRITE_BIT(vch, 3*(i + 24U) + 1U, s); + WRITE_BIT(vch, 3*(i + 24U) + 2U, s); + } + + for (unsigned int i = 0U; i < 22U; i++) + { + bool s = (dat_c << (10U + i)) & 0x80000000U; + WRITE_BIT(vch, i + 81U, s); + } + + WRITE_BIT(vch, 103U, 0U); + + // Scramble + for (unsigned int i = 0U; i < 13U; i++) + vch[i] ^= WHITENING_DATA[i]; + + // Interleave + for (unsigned int i = 0U; i < 104U; i++) + { + unsigned int n = INTERLEAVE_TABLE_26_4[i]; + bool s = READ_BIT(vch, i); + WRITE_BIT(ysfFrame, n, s); + } + + ::memcpy(data, ysfFrame, 13U); +} diff --git a/src/cysfutils.h b/src/cysfutils.h index fe65394..f16bf07 100644 --- a/src/cysfutils.h +++ b/src/cysfutils.h @@ -34,9 +34,9 @@ class CYsfUtils { public: - // operation - static void DecodeVD2Vchs(uint8 *, uint8 **); - static void EncodeVD2Vch(uint8 *, uint8 *); + // operation + static void DecodeVD2Vchs(uint8 *, uint8 **); + static void EncodeVD2Vch(uint8 *, uint8 *); }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/main.cpp b/src/main.cpp index 01d143a..df764b5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -50,33 +50,33 @@ int main() // remove pidfile remove(PIDFILE_PATH); - // splash - std::cout << "Starting " << cs << " " << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_REVISION << std::endl << std::endl; + // splash + std::cout << "Starting " << cs << " " << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_REVISION << std::endl << std::endl; - // initialize reflector - g_Reflector.SetCallsign(cs.c_str()); + // initialize reflector + g_Reflector.SetCallsign(cs.c_str()); #ifdef LISTEN_IPV4 - g_Reflector.SetListenIPv4(LISTEN_IPV4, INET_ADDRSTRLEN); + g_Reflector.SetListenIPv4(LISTEN_IPV4, INET_ADDRSTRLEN); #endif #ifdef LISTEN_IPV6 - g_Reflector.SetListenIPv6(LISTEN_IPV6, INET6_ADDRSTRLEN); + g_Reflector.SetListenIPv6(LISTEN_IPV6, INET6_ADDRSTRLEN); #endif #ifdef TRANSCODER_IP - g_Reflector.SetTranscoderIp(TRANSCODER_IP, INET6_ADDRSTRLEN); + g_Reflector.SetTranscoderIp(TRANSCODER_IP, INET6_ADDRSTRLEN); #endif - // and let it run - if ( !g_Reflector.Start() ) - { - std::cout << "Error starting reflector" << std::endl; - return EXIT_FAILURE; - } + // and let it run + if ( !g_Reflector.Start() ) + { + std::cout << "Error starting reflector" << std::endl; + return EXIT_FAILURE; + } - std::cout << "Reflector " << g_Reflector.GetCallsign() << "started and listening on "; + std::cout << "Reflector " << g_Reflector.GetCallsign() << "started and listening on "; #if defined LISTEN_IPV4 std::cout << g_Reflector.GetListenIPv4() << " for IPv4"; #ifdef LISTEN_IPV6 @@ -96,9 +96,9 @@ int main() pause(); // wait for any signal - g_Reflector.Stop(); - std::cout << "Reflector stopped" << std::endl; + g_Reflector.Stop(); + std::cout << "Reflector stopped" << std::endl; - // done - return EXIT_SUCCESS; + // done + return EXIT_SUCCESS; } diff --git a/src/main.h b/src/main.h index 8baf9ec..9e2cf5e 100644 --- a/src/main.h +++ b/src/main.h @@ -243,19 +243,19 @@ extern CGateKeeper g_GateKeeper; #ifndef NO_XLX #if (DMRIDDB_USE_RLX_SERVER == 1) - class CDmridDirHttp; - extern CDmridDirHttp g_DmridDir; +class CDmridDirHttp; +extern CDmridDirHttp g_DmridDir; #else - class CDmridDirFile; - extern CDmridDirFile g_DmridDir; +class CDmridDirFile; +extern CDmridDirFile g_DmridDir; #endif #if (YSFNODEDB_USE_RLX_SERVER == 1) - class CYsfNodeDirHttp; - extern CYsfNodeDirHttp g_YsfNodeDir; +class CYsfNodeDirHttp; +extern CYsfNodeDirHttp g_YsfNodeDir; #else - class CYsfNodeDirFile; - extern CYsfNodeDirFile g_YsfNodeDir; +class CYsfNodeDirFile; +extern CYsfNodeDirFile g_YsfNodeDir; #endif class CTranscoder;