astyle -A1 -T -O

pull/1/head
Tom Early 6 years ago
parent 2af8c7225a
commit a0e615c459

@ -36,24 +36,28 @@ typedef void VOID;
typedef USHORT *PUSHORT; typedef USHORT *PUSHORT;
typedef unsigned long long int ULONGLONG; typedef unsigned long long int ULONGLONG;
typedef struct _OVERLAPPED { typedef struct _OVERLAPPED
DWORD Internal; {
DWORD InternalHigh; DWORD Internal;
union { DWORD InternalHigh;
struct{ union
DWORD Offset; {
DWORD OffsetHigh; struct
}; {
PVOID Pointer; DWORD Offset;
}; DWORD OffsetHigh;
HANDLE hEvent; };
PVOID Pointer;
};
HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED; } OVERLAPPED, *LPOVERLAPPED;
typedef struct _SECURITY_ATTRIBUTES { typedef struct _SECURITY_ATTRIBUTES
DWORD nLength; {
LPVOID lpSecurityDescriptor; DWORD nLength;
BOOL bInheritHandle; LPVOID lpSecurityDescriptor;
} SECURITY_ATTRIBUTES , *LPSECURITY_ATTRIBUTES; BOOL bInheritHandle;
} SECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
#include <pthread.h> #include <pthread.h>
// Substitute for HANDLE returned by Windows CreateEvent API. // Substitute for HANDLE returned by Windows CreateEvent API.
@ -61,9 +65,9 @@ typedef struct _SECURITY_ATTRIBUTES {
// of one of these structures. // of one of these structures.
typedef struct _EVENT_HANDLE typedef struct _EVENT_HANDLE
{ {
pthread_cond_t eCondVar; pthread_cond_t eCondVar;
pthread_mutex_t eMutex; pthread_mutex_t eMutex;
int iVar; int iVar;
} EVENT_HANDLE; } EVENT_HANDLE;
typedef struct timeval SYSTEMTIME; typedef struct timeval SYSTEMTIME;

@ -34,21 +34,21 @@
CAGC::CAGC(float initialLeveldB) CAGC::CAGC(float initialLeveldB)
{ {
// set internal gain appropriately // set internal gain appropriately
m_Gain = pow(10.0f, initialLeveldB/20.0f); m_Gain = pow(10.0f, initialLeveldB/20.0f);
//+- 10dB Margin, TODO Move margin to constant //+- 10dB Margin, TODO Move margin to constant
m_GainMax = pow(10.0f, (initialLeveldB + AGC_CLAMPING)/20.0f); m_GainMax = pow(10.0f, (initialLeveldB + AGC_CLAMPING)/20.0f);
m_GainMin = pow(10.0f, (initialLeveldB - AGC_CLAMPING)/20.0f); m_GainMin = pow(10.0f, (initialLeveldB - AGC_CLAMPING)/20.0f);
m_EnergyPrime = 1.0f;
// We do not target full scale to avoid stauration m_EnergyPrime = 1.0f;
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... // We do not target full scale to avoid stauration
m_Bandwidth = 1e-2f;//TODO : Move to parameter ? m_targetEnergy = 32767.0f * pow(10.0f, (initialLeveldB - 25.0)/20.0f);//25 dB below saturation as stated in docs
m_Alpha = m_Bandwidth; //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() float CAGC::GetGain()
{ {
return 20.0f*log10(m_Gain); return 20.0f*log10(m_Gain);
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// process // 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) for(int i = 0; i < length; i += 2)
{ {
float input = (float)(short)MAKEWORD(voice[i+1], voice[i]); float input = (float)(short)MAKEWORD(voice[i+1], voice[i]);
//apply AGC //apply AGC
// apply gain to input sample // apply gain to input sample
float output = input * m_Gain; float output = input * m_Gain;
// compute output signal energy, scaled to 0 to 1 // compute output signal energy, scaled to 0 to 1
float instantEnergy = abs(output) / m_targetEnergy; float instantEnergy = abs(output) / m_targetEnergy;
// smooth energy estimate using single-pole low-pass filter // smooth energy estimate using single-pole low-pass filter
m_EnergyPrime = (1.0f - m_Alpha) * m_EnergyPrime + m_Alpha * instantEnergy; m_EnergyPrime = (1.0f - m_Alpha) * m_EnergyPrime + m_Alpha * instantEnergy;
// update gain according to output energy // update gain according to output energy
if (m_EnergyPrime > 1e-6f) if (m_EnergyPrime > 1e-6f)
m_Gain *= exp( -0.5f * m_Alpha * log(m_EnergyPrime) ); m_Gain *= exp( -0.5f * m_Alpha * log(m_EnergyPrime) );
// clamp gain // clamp gain
if (m_Gain > m_GainMax) if (m_Gain > m_GainMax)
m_Gain = m_GainMax; m_Gain = m_GainMax;
else if(m_Gain < m_GainMin) else if(m_Gain < m_GainMin)
m_Gain = m_GainMin; m_Gain = m_GainMin;
//write processed sample back //write processed sample back
voice[i] = HIBYTE((short)output); voice[i] = HIBYTE((short)output);
voice[i+1] = LOBYTE((short)output); voice[i+1] = LOBYTE((short)output);
} }
} }

@ -23,7 +23,7 @@
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Geoffrey Merck F4FXL / KC3FRA AGC code largely inspired by Liquid DSP // 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 // 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 #ifndef cagc_h
#define cagc_h #define cagc_h
@ -33,24 +33,24 @@
class CAGC : CSampleBlockProcessor class CAGC : CSampleBlockProcessor
{ {
public: public:
//Constructor //Constructor
CAGC(float initialLeveldB); 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: private:
float m_Gain; // current gain value float m_Gain; // current gain value
float m_GainMax, m_GainMin; //gain clamping float m_GainMax, m_GainMin; //gain clamping
float m_targetEnergy; // scale value for target energy float m_targetEnergy; // scale value for target energy
// gain control loop filter parameters // gain control loop filter parameters
float m_Bandwidth; // bandwidth-time constant float m_Bandwidth; // bandwidth-time constant
float m_Alpha; // feed-back gain float m_Alpha; // feed-back gain
// signal level estimate // signal level estimate
float m_EnergyPrime; // filtered output signal energy estimate float m_EnergyPrime; // filtered output signal energy estimate
}; };
#endif /* cgc_h */ #endif /* cgc_h */

@ -35,22 +35,22 @@
CAmbePacket::CAmbePacket() CAmbePacket::CAmbePacket()
{ {
m_uiCodec = CODEC_NONE; m_uiCodec = CODEC_NONE;
::memset(m_uiAmbe, 0, AMBE_SIZE); ::memset(m_uiAmbe, 0, AMBE_SIZE);
} }
CAmbePacket::CAmbePacket(uint8 uiPid, uint8 uiCodec, const uint8 *Ambe) CAmbePacket::CAmbePacket(uint8 uiPid, uint8 uiCodec, const uint8 *Ambe)
: CPacket(uiPid) : CPacket(uiPid)
{ {
m_uiCodec = uiCodec; m_uiCodec = uiCodec;
::memcpy(m_uiAmbe, Ambe, AMBE_SIZE); ::memcpy(m_uiAmbe, Ambe, AMBE_SIZE);
} }
CAmbePacket::CAmbePacket(const CAmbePacket &packet) CAmbePacket::CAmbePacket(const CAmbePacket &packet)
: CPacket(packet) : CPacket(packet)
{ {
m_uiCodec = packet.m_uiCodec; m_uiCodec = packet.m_uiCodec;
::memcpy(m_uiAmbe, packet.m_uiAmbe, sizeof(m_uiAmbe)); ::memcpy(m_uiAmbe, packet.m_uiAmbe, sizeof(m_uiAmbe));
} }
@ -66,6 +66,6 @@ CAmbePacket::~CAmbePacket()
void CAmbePacket::SetAmbe(const uint8 *p) void CAmbePacket::SetAmbe(const uint8 *p)
{ {
::memcpy(m_uiAmbe, p, AMBE_SIZE); ::memcpy(m_uiAmbe, p, AMBE_SIZE);
} }

@ -40,30 +40,30 @@
class CAmbePacket : public CPacket class CAmbePacket : public CPacket
{ {
public: public:
// constructors // constructors
CAmbePacket(); CAmbePacket();
CAmbePacket(uint8, uint8, const uint8 *); CAmbePacket(uint8, uint8, const uint8 *);
CAmbePacket(const CAmbePacket &); CAmbePacket(const CAmbePacket &);
// destructor // destructor
virtual ~CAmbePacket(); virtual ~CAmbePacket();
// identity // identity
bool IsAmbe(void) const { return true; } bool IsAmbe(void) const { return true; }
// get // get
uint8 GetCodec(void) const { return m_uiCodec; } uint8 GetCodec(void) const { return m_uiCodec; }
uint8 *GetAmbe(void) { return m_uiAmbe; } uint8 *GetAmbe(void) { return m_uiAmbe; }
int GetAmbeSize(void) const { return AMBE_SIZE; } int GetAmbeSize(void) const { return AMBE_SIZE; }
// set // set
void SetCodec(uint8 c) { m_uiCodec = c; } void SetCodec(uint8 c) { m_uiCodec = c; }
void SetAmbe(const uint8 *); void SetAmbe(const uint8 *);
protected: protected:
// data // data
uint8 m_uiCodec; uint8 m_uiCodec;
uint8 m_uiAmbe[AMBE_SIZE]; uint8 m_uiAmbe[AMBE_SIZE];
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -40,20 +40,20 @@ CAmbeServer g_AmbeServer;
bool CAmbeServer::Start(void) bool CAmbeServer::Start(void)
{ {
// init interfaces & controller // init interfaces & controller
std::cout << "Initializing vocodecs:" << std::endl; std::cout << "Initializing vocodecs:" << std::endl;
if (! g_Vocodecs.Init()) if (! g_Vocodecs.Init())
return false; return false;
std::cout << "Initializing controller" << std::endl; std::cout << "Initializing controller" << std::endl;
if (! m_Controller.Init()) if (! m_Controller.Init())
return false; return false;
return true; return true;
} }
void CAmbeServer::Stop(void) void CAmbeServer::Stop(void)
{ {
// stop controller // stop controller
m_Controller.Close(); m_Controller.Close();
} }

@ -35,27 +35,27 @@ class CAmbeServer
{ {
public: public:
// operation // operation
bool Start(void); bool Start(void);
void Stop(void); void Stop(void);
// task // task
static void Thread(CAmbeServer *); static void Thread(CAmbeServer *);
void Task(void); void Task(void);
// get // get
const char *GetListenIp(void) const { return m_Controller.GetListenIp(); } const char *GetListenIp(void) const { return m_Controller.GetListenIp(); }
// set // set
void SetListenIp(const char *ip) { m_Controller.SetListenIp(ip); } void SetListenIp(const char *ip) { m_Controller.SetListenIp(ip); }
protected: protected:
// objects // objects
CController m_Controller; CController m_Controller;
public: public:
#ifdef DEBUG_DUMPFILE #ifdef DEBUG_DUMPFILE
std::ofstream m_DebugFile; std::ofstream m_DebugFile;
#endif #endif
}; };

@ -32,14 +32,14 @@
CCallsign::CCallsign() CCallsign::CCallsign()
{ {
// blank all // blank all
::memset(m_Callsign, ' ', sizeof(m_Callsign)); ::memset(m_Callsign, ' ', sizeof(m_Callsign));
} }
CCallsign::CCallsign(const char *sz) CCallsign::CCallsign(const char *sz)
{ {
::memset(m_Callsign, ' ', sizeof(m_Callsign)); ::memset(m_Callsign, ' ', sizeof(m_Callsign));
::memcpy(m_Callsign, sz, MIN(strlen(sz), 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 CCallsign::IsValid(void) const
{ {
bool valid = true; bool valid = true;
int i; int i;
// callsign // callsign
// first 3 chars are letter or number but cannot be all number // first 3 chars are letter or number but cannot be all number
int iNum = 0; int iNum = 0;
for ( i = 0; i < 3; i++ ) for ( i = 0; i < 3; i++ )
{ {
valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]); valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]);
if ( IsNumber(m_Callsign[i]) ) if ( IsNumber(m_Callsign[i]) )
{ {
iNum++; iNum++;
} }
} }
valid &= (iNum < 3); valid &= (iNum < 3);
// all remaining char are letter, number or space // all remaining char are letter, number or space
for ( ; i < CALLSIGN_LEN; i++) for ( ; i < CALLSIGN_LEN; i++)
{ {
valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]) || IsSpace(m_Callsign[i]); valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]) || IsSpace(m_Callsign[i]);
} }
// done // done
return valid; return valid;
} }
@ -78,23 +78,23 @@ bool CCallsign::IsValid(void) const
void CCallsign::SetCallsign(const char *sz) void CCallsign::SetCallsign(const char *sz)
{ {
// set callsign // set callsign
::memset(m_Callsign, ' ', sizeof(m_Callsign)); ::memset(m_Callsign, ' ', sizeof(m_Callsign));
::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign))); ::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign)));
} }
void CCallsign::SetCallsign(const uint8 *buffer, int len) void CCallsign::SetCallsign(const uint8 *buffer, int len)
{ {
// set callsign // set callsign
::memset(m_Callsign, ' ', sizeof(m_Callsign)); ::memset(m_Callsign, ' ', sizeof(m_Callsign));
::memcpy(m_Callsign, buffer, MIN(len, sizeof(m_Callsign))); ::memcpy(m_Callsign, buffer, MIN(len, sizeof(m_Callsign)));
for ( unsigned i = 0; i < sizeof(m_Callsign); i++ ) for ( unsigned i = 0; i < sizeof(m_Callsign); i++ )
{ {
if ( m_Callsign[i] == 0 ) if ( m_Callsign[i] == 0 )
{ {
m_Callsign[i] = ' '; 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) void CCallsign::PatchCallsign(int off, const uint8 *patch, int len)
{ {
if ( off < int(sizeof(m_Callsign)) ) if ( off < int(sizeof(m_Callsign)) )
{ {
::memcpy(m_Callsign, patch, MIN(len, sizeof(m_Callsign) - off)); ::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 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 void CCallsign::GetCallsignString(char *sz) const
{ {
unsigned i; unsigned i;
for ( i = 0; (i < sizeof(m_Callsign)) && (m_Callsign[i] != ' '); i++ ) for ( i = 0; (i < sizeof(m_Callsign)) && (m_Callsign[i] != ' '); i++ )
{ {
sz[i] = m_Callsign[i]; sz[i] = m_Callsign[i];
} }
sz[i] = 0; sz[i] = 0;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -133,22 +133,22 @@ void CCallsign::GetCallsignString(char *sz) const
bool CCallsign::HasSameCallsign(const CCallsign &Callsign) 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 CCallsign::HasSameCallsignWithWildcard(const CCallsign &callsign) const
{ {
bool same = true; bool same = true;
bool done = false; bool done = false;
for ( unsigned i = 0; (i < sizeof(m_Callsign)) && same && !done; i++ ) for ( unsigned i = 0; (i < sizeof(m_Callsign)) && same && !done; i++ )
{ {
if ( !(done = ((m_Callsign[i] == '*') || (callsign[i] == '*'))) ) if ( !(done = ((m_Callsign[i] == '*') || (callsign[i] == '*'))) )
{ {
same &= (m_Callsign[i] == callsign[i]); same &= (m_Callsign[i] == callsign[i]);
} }
} }
return same; return same;
} }
@ -157,7 +157,7 @@ bool CCallsign::HasSameCallsignWithWildcard(const CCallsign &callsign) const
bool CCallsign::operator ==(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 CCallsign::operator const char *() const
@ -166,12 +166,12 @@ CCallsign::operator const char *() const
// empty // empty
::memset(sz, 0, sizeof(m_sz)); ::memset(sz, 0, sizeof(m_sz));
// callsign // callsign
sz[CALLSIGN_LEN] = 0; sz[CALLSIGN_LEN] = 0;
::memcpy(sz, m_Callsign, sizeof(m_Callsign)); ::memcpy(sz, m_Callsign, sizeof(m_Callsign));
// done // done
return m_sz; return m_sz;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -179,15 +179,15 @@ CCallsign::operator const char *() const
bool CCallsign::IsNumber(char c) const bool CCallsign::IsNumber(char c) const
{ {
return ((c >= '0') && (c <= '9')); return ((c >= '0') && (c <= '9'));
} }
bool CCallsign::IsLetter(char c) const bool CCallsign::IsLetter(char c) const
{ {
return ((c >= 'A') && (c <= 'Z')); return ((c >= 'A') && (c <= 'Z'));
} }
bool CCallsign::IsSpace(char c) const bool CCallsign::IsSpace(char c) const
{ {
return (c == ' '); return (c == ' ');
} }

@ -37,42 +37,42 @@
class CCallsign class CCallsign
{ {
public: public:
// contructors // contructors
CCallsign(); CCallsign();
CCallsign(const char *); CCallsign(const char *);
// status // status
bool IsValid(void) const; bool IsValid(void) const;
// set // set
void SetCallsign(const char *); void SetCallsign(const char *);
void SetCallsign(const uint8 *, int); void SetCallsign(const uint8 *, int);
// modify // modify
void PatchCallsign(int, const uint8 *, int); void PatchCallsign(int, const uint8 *, int);
// get // get
void GetCallsign(uint8 *) const; void GetCallsign(uint8 *) const;
void GetCallsignString(char *) const; void GetCallsignString(char *) const;
// compare // compare
bool HasSameCallsign(const CCallsign &) const; bool HasSameCallsign(const CCallsign &) const;
bool HasSameCallsignWithWildcard(const CCallsign &) const; bool HasSameCallsignWithWildcard(const CCallsign &) const;
// operators // operators
bool operator ==(const CCallsign &) const; bool operator ==(const CCallsign &) const;
operator const char *() const; operator const char *() const;
protected: protected:
// helper // helper
bool IsNumber(char) const; bool IsNumber(char) const;
bool IsLetter(char) const; bool IsLetter(char) const;
bool IsSpace(char) const; bool IsSpace(char) const;
protected: protected:
// data // data
char m_Callsign[CALLSIGN_LEN]; char m_Callsign[CALLSIGN_LEN];
char m_sz[CALLSIGN_LEN+1]; char m_sz[CALLSIGN_LEN+1];
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -34,9 +34,9 @@
CController::CController() CController::CController()
{ {
m_bStopThread = false; m_bStopThread = false;
m_pThread = NULL; m_pThread = NULL;
m_uiLastStreamId = 0; m_uiLastStreamId = 0;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -44,27 +44,27 @@ CController::CController()
CController::~CController() CController::~CController()
{ {
// close socket // close socket
m_Socket.Close(); m_Socket.Close();
// close all streams // close all streams
m_Mutex.lock(); m_Mutex.lock();
{ {
for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ ) for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ )
{ {
delete *it; delete *it;
} }
m_Streams.clear(); m_Streams.clear();
} }
m_Mutex.unlock(); m_Mutex.unlock();
m_bStopThread = true; m_bStopThread = true;
if ( m_pThread != NULL ) if ( m_pThread != NULL )
{ {
m_pThread->join(); m_pThread->join();
delete m_pThread; delete m_pThread;
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -72,35 +72,36 @@ CController::~CController()
bool CController::Init(void) bool CController::Init(void)
{ {
// reset stop flag // reset stop flag
m_bStopThread = false; m_bStopThread = false;
// create our socket // create our socket
CIp ip(strchr(m_addr, ':') ? AF_INET6 : AF_INET, TRANSCODER_PORT, m_addr); 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; std::cerr << "IP initialization failed for " << m_addr << std::endl;
return false; return false;
} }
if (! m_Socket.Open(ip)) if (! m_Socket.Open(ip))
{ {
std::cout << "Error opening socket on port UDP" << TRANSCODER_PORT << " on ip " << ip.GetAddress() << std::endl; std::cout << "Error opening socket on port UDP" << TRANSCODER_PORT << " on ip " << ip.GetAddress() << std::endl;
return false; return false;
} }
// start thread; // start thread;
m_pThread = new std::thread(CController::Thread, this); m_pThread = new std::thread(CController::Thread, this);
return true; return true;
} }
void CController::Close(void) void CController::Close(void)
{ {
m_bStopThread = true; m_bStopThread = true;
if ( m_pThread != NULL ) if ( m_pThread != NULL )
{ {
m_pThread->join(); m_pThread->join();
delete m_pThread; delete m_pThread;
m_pThread = NULL; m_pThread = NULL;
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -108,10 +109,10 @@ void CController::Close(void)
void CController::Thread(CController *This) void CController::Thread(CController *This)
{ {
while ( !This->m_bStopThread ) while ( !This->m_bStopThread )
{ {
This->Task(); This->Task();
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -119,51 +120,51 @@ void CController::Thread(CController *This)
void CController::Task(void) void CController::Task(void)
{ {
CBuffer Buffer; CBuffer Buffer;
CIp Ip; CIp Ip;
CCallsign Callsign; CCallsign Callsign;
uint8 CodecIn; uint8 CodecIn;
uint8 CodecOut; uint8 CodecOut;
uint16 StreamId; uint16 StreamId;
CStream *Stream; CStream *Stream;
// anything coming in from codec client ? // anything coming in from codec client ?
if ( m_Socket.Receive(Buffer, Ip, 20) ) if ( m_Socket.Receive(Buffer, Ip, 20) )
{ {
// crack packet // crack packet
if ( IsValidOpenstreamPacket(Buffer, &Callsign, &CodecIn, &CodecOut) ) if ( IsValidOpenstreamPacket(Buffer, &Callsign, &CodecIn, &CodecOut) )
{ {
std::cout << "Stream Open from " << Callsign << std::endl; std::cout << "Stream Open from " << Callsign << std::endl;
// try create the stream // try create the stream
Stream = OpenStream(Callsign, Ip, CodecIn, CodecOut); Stream = OpenStream(Callsign, Ip, CodecIn, CodecOut);
// send back details // send back details
if ( Stream != NULL ) if ( Stream != NULL )
{ {
EncodeStreamDescrPacket(&Buffer, *Stream); EncodeStreamDescrPacket(&Buffer, *Stream);
} }
else else
{ {
EncodeNoStreamAvailablePacket(&Buffer); EncodeNoStreamAvailablePacket(&Buffer);
} }
m_Socket.Send(Buffer, Ip); m_Socket.Send(Buffer, Ip);
} }
else if ( IsValidClosestreamPacket(Buffer, &StreamId) ) else if ( IsValidClosestreamPacket(Buffer, &StreamId) )
{ {
// close the stream // close the stream
CloseStream(StreamId); CloseStream(StreamId);
std::cout << "Stream " << (int)StreamId << " closed" << std::endl; std::cout << "Stream " << (int)StreamId << " closed" << std::endl;
} }
else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) else if ( IsValidKeepAlivePacket(Buffer, &Callsign) )
{ {
//std::cout << "ping - " << Callsign << std::endl; //std::cout << "ping - " << Callsign << std::endl;
// pong back // pong back
EncodeKeepAlivePacket(&Buffer); EncodeKeepAlivePacket(&Buffer);
m_Socket.Send(Buffer, Ip); m_Socket.Send(Buffer, Ip);
} }
} }
// any inactive streams? // any inactive streams?
Lock(); Lock();
@ -189,34 +190,34 @@ void CController::Task(void)
CStream *CController::OpenStream(const CCallsign &Callsign, const CIp &Ip, uint8 CodecIn, uint8 CodecOut) CStream *CController::OpenStream(const CCallsign &Callsign, const CIp &Ip, uint8 CodecIn, uint8 CodecOut)
{ {
CStream *stream = NULL; CStream *stream = NULL;
// create a new stream // create a new stream
m_uiLastStreamId = (m_uiLastStreamId + 1); m_uiLastStreamId = (m_uiLastStreamId + 1);
m_uiLastStreamId = (m_uiLastStreamId == NB_MAX_STREAMS+1) ? 1 : m_uiLastStreamId; m_uiLastStreamId = (m_uiLastStreamId == NB_MAX_STREAMS+1) ? 1 : m_uiLastStreamId;
stream = new CStream(m_uiLastStreamId, Callsign, Ip, CodecIn, CodecOut); stream = new CStream(m_uiLastStreamId, Callsign, Ip, CodecIn, CodecOut);
if ( stream->Init(TRANSCODER_PORT+m_uiLastStreamId) ) if ( stream->Init(TRANSCODER_PORT+m_uiLastStreamId) )
{ {
std::cout << "Opened stream " << m_uiLastStreamId << std::endl; std::cout << "Opened stream " << m_uiLastStreamId << std::endl;
// and store it // and store it
Lock(); Lock();
m_Streams.push_back(stream); m_Streams.push_back(stream);
Unlock(); Unlock();
} }
else else
{ {
delete stream; delete stream;
stream = NULL; stream = NULL;
} }
// done // done
return stream; return stream;
} }
void CController::CloseStream(uint16 StreamId) void CController::CloseStream(uint16 StreamId)
{ {
Lock(); Lock();
// look for the stream // look for the stream
for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ ) for ( auto it=m_Streams.begin(); it!=m_Streams.end(); it++ )
{ {
// compare object pointers // compare object pointers
@ -231,7 +232,7 @@ void CController::CloseStream(uint16 StreamId)
break; break;
} }
} }
Unlock(); Unlock();
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -239,48 +240,48 @@ void CController::CloseStream(uint16 StreamId)
bool CController::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *Callsign) bool CController::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *Callsign)
{ {
uint8 tag[] = { 'A','M','B','E','D','P','I','N','G' }; uint8 tag[] = { 'A','M','B','E','D','P','I','N','G' };
bool valid = false; bool valid = false;
if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) )
{ {
// get callsign here // get callsign here
Callsign->SetCallsign(&(Buffer.data()[9]), 8); Callsign->SetCallsign(&(Buffer.data()[9]), 8);
valid = Callsign->IsValid(); valid = Callsign->IsValid();
} }
return valid; return valid;
} }
bool CController::IsValidOpenstreamPacket(const CBuffer &Buffer, CCallsign *Callsign, uint8 *CodecIn, uint8 *CodecOut) bool CController::IsValidOpenstreamPacket(const CBuffer &Buffer, CCallsign *Callsign, uint8 *CodecIn, uint8 *CodecOut)
{ {
uint8 tag[] = { 'A','M','B','E','D','O','S' }; uint8 tag[] = { 'A','M','B','E','D','O','S' };
bool valid = false; bool valid = false;
if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) )
{ {
// get callsign here // get callsign here
Callsign->SetCallsign(&(Buffer.data()[7]), 8); Callsign->SetCallsign(&(Buffer.data()[7]), 8);
*CodecIn = Buffer.data()[15]; *CodecIn = Buffer.data()[15];
*CodecOut = Buffer.data()[16]; *CodecOut = Buffer.data()[16];
// valid ? // valid ?
valid = Callsign->IsValid() && IsValidCodecIn(*CodecIn) && IsValidCodecOut(*CodecOut); valid = Callsign->IsValid() && IsValidCodecIn(*CodecIn) && IsValidCodecOut(*CodecOut);
} }
return valid; return valid;
} }
bool CController::IsValidClosestreamPacket(const CBuffer &Buffer, uint16 *StreamId) bool CController::IsValidClosestreamPacket(const CBuffer &Buffer, uint16 *StreamId)
{ {
uint8 tag[] = { 'A','M','B','E','D','C','S' }; uint8 tag[] = { 'A','M','B','E','D','C','S' };
bool valid = false; bool valid = false;
if ( /*(Buffer.size() == 16) &&*/ (Buffer.Compare(tag, sizeof(tag)) == 0) ) if ( /*(Buffer.size() == 16) &&*/ (Buffer.Compare(tag, sizeof(tag)) == 0) )
{ {
// get stream id // get stream id
*StreamId = *(uint16 *)(&Buffer.data()[7]); *StreamId = *(uint16 *)(&Buffer.data()[7]);
valid = true; valid = true;
} }
return valid; return valid;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -288,31 +289,31 @@ bool CController::IsValidClosestreamPacket(const CBuffer &Buffer, uint16 *Stream
void CController::EncodeKeepAlivePacket(CBuffer *Buffer) 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) void CController::EncodeStreamDescrPacket(CBuffer *Buffer, const CStream &Stream)
{ {
uint8 tag[] = { 'A','M','B','E','D','S','T','D' }; uint8 tag[] = { 'A','M','B','E','D','S','T','D' };
Buffer->Set(tag, sizeof(tag)); Buffer->Set(tag, sizeof(tag));
// id // id
Buffer->Append((uint16)Stream.GetId()); Buffer->Append((uint16)Stream.GetId());
// port // port
Buffer->Append((uint16)Stream.GetPort()); Buffer->Append((uint16)Stream.GetPort());
// codecin // codecin
Buffer->Append((uint8)Stream.GetCodecIn()); Buffer->Append((uint8)Stream.GetCodecIn());
// codecout // codecout
Buffer->Append((uint8)Stream.GetCodecOut()); Buffer->Append((uint8)Stream.GetCodecOut());
} }
void CController::EncodeNoStreamAvailablePacket(CBuffer *Buffer) 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) bool CController::IsValidCodecIn(uint8 codec)
{ {
return ((codec == CODEC_AMBEPLUS) || (codec == CODEC_AMBE2PLUS) ); return ((codec == CODEC_AMBEPLUS) || (codec == CODEC_AMBE2PLUS) );
} }
bool CController::IsValidCodecOut(uint8 codec) bool CController::IsValidCodecOut(uint8 codec)
{ {
return ((codec == CODEC_AMBEPLUS) || (codec == CODEC_AMBE2PLUS) ); return ((codec == CODEC_AMBEPLUS) || (codec == CODEC_AMBE2PLUS) );
} }

@ -35,61 +35,61 @@
class CController class CController
{ {
public: public:
// constructors // constructors
CController(); CController();
// destructor // destructor
virtual ~CController(); virtual ~CController();
// initialization // initialization
bool Init(void); bool Init(void);
void Close(void); void Close(void);
// locks // locks
void Lock(void) { m_Mutex.lock(); } void Lock(void) { m_Mutex.lock(); }
void Unlock(void) { m_Mutex.unlock(); } void Unlock(void) { m_Mutex.unlock(); }
// get // get
const char *GetListenIp(void) const { return m_addr; } const char *GetListenIp(void) const { return m_addr; }
// set // set
void SetListenIp(const char *str) { memset(m_addr, 0, INET6_ADDRSTRLEN); strncpy(m_addr, str, INET6_ADDRSTRLEN-1); } void SetListenIp(const char *str) { memset(m_addr, 0, INET6_ADDRSTRLEN); strncpy(m_addr, str, INET6_ADDRSTRLEN-1); }
// task // task
static void Thread(CController *); static void Thread(CController *);
void Task(void); void Task(void);
protected: protected:
// streams management // streams management
CStream *OpenStream(const CCallsign &, const CIp &, uint8, uint8); CStream *OpenStream(const CCallsign &, const CIp &, uint8, uint8);
void CloseStream(uint16); void CloseStream(uint16);
// packet decoding helpers // packet decoding helpers
bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *);
bool IsValidOpenstreamPacket(const CBuffer &, CCallsign *, uint8 *, uint8 *); bool IsValidOpenstreamPacket(const CBuffer &, CCallsign *, uint8 *, uint8 *);
bool IsValidClosestreamPacket(const CBuffer &, uint16 *); bool IsValidClosestreamPacket(const CBuffer &, uint16 *);
// packet encoding helpers // packet encoding helpers
void EncodeKeepAlivePacket(CBuffer *); void EncodeKeepAlivePacket(CBuffer *);
void EncodeStreamDescrPacket(CBuffer *, const CStream &); void EncodeStreamDescrPacket(CBuffer *, const CStream &);
void EncodeNoStreamAvailablePacket(CBuffer *); void EncodeNoStreamAvailablePacket(CBuffer *);
// codec helpers // codec helpers
bool IsValidCodecIn(uint8); bool IsValidCodecIn(uint8);
bool IsValidCodecOut(uint8); bool IsValidCodecOut(uint8);
// control socket // control socket
char m_addr[INET6_ADDRSTRLEN]; char m_addr[INET6_ADDRSTRLEN];
CUdpSocket m_Socket; CUdpSocket m_Socket;
// streams // streams
uint16 m_uiLastStreamId; uint16 m_uiLastStreamId;
std::mutex m_Mutex; std::mutex m_Mutex;
std::list<CStream *> m_Streams; std::list<CStream *> m_Streams;
// thread // thread
bool m_bStopThread; bool m_bStopThread;
std::thread *m_pThread; std::thread *m_pThread;
}; };

@ -28,48 +28,48 @@
CFIRFilter::CFIRFilter(const float* taps, int tapsLength) CFIRFilter::CFIRFilter(const float* taps, int tapsLength)
{ {
m_taps = new float[tapsLength]; m_taps = new float[tapsLength];
m_buffer = new float[tapsLength]; m_buffer = new float[tapsLength];
m_tapsLength = tapsLength; m_tapsLength = tapsLength;
::memcpy(m_taps, taps, tapsLength * sizeof(float)); ::memcpy(m_taps, taps, tapsLength * sizeof(float));
::memset(m_buffer, 0, tapsLength * sizeof(float)); ::memset(m_buffer, 0, tapsLength * sizeof(float));
m_currentBufferPosition = 0; m_currentBufferPosition = 0;
} }
CFIRFilter::~CFIRFilter() CFIRFilter::~CFIRFilter()
{ {
delete[] m_taps; delete[] m_taps;
delete[] m_buffer; delete[] m_buffer;
} }
inline void CFIRFilter::ProcessSampleBlock(uint8* voice, int length) inline void CFIRFilter::ProcessSampleBlock(uint8* voice, int length)
{ {
for(int i = 0; i < length; i += 2) for(int i = 0; i < length; i += 2)
{ {
float input = (float)(short)MAKEWORD(voice[i+1], voice[i]); float input = (float)(short)MAKEWORD(voice[i+1], voice[i]);
float output = 0.0f; float output = 0.0f;
int iTaps = 0; int iTaps = 0;
// Buffer latest sample into delay line // Buffer latest sample into delay line
m_buffer[m_currentBufferPosition] = input; m_buffer[m_currentBufferPosition] = input;
for(int i = m_currentBufferPosition; i >= 0; i--) for(int i = m_currentBufferPosition; i >= 0; i--)
{ {
output += m_taps[iTaps++] * m_buffer[i]; output += m_taps[iTaps++] * m_buffer[i];
} }
for(int i = m_tapsLength - 1; i > m_currentBufferPosition; i--) for(int i = m_tapsLength - 1; i > m_currentBufferPosition; i--)
{ {
output += m_taps[iTaps++] * m_buffer[i]; output += m_taps[iTaps++] * m_buffer[i];
} }
m_currentBufferPosition = (m_currentBufferPosition + 1) % m_tapsLength;
//write processed sample back m_currentBufferPosition = (m_currentBufferPosition + 1) % m_tapsLength;
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);
}
} }

@ -31,20 +31,20 @@
class CFIRFilter : CSampleBlockProcessor class CFIRFilter : CSampleBlockProcessor
{ {
public : public :
//Constructor //Constructor
CFIRFilter(const float* taps, int tapsLength); CFIRFilter(const float* taps, int tapsLength);
// Destructor // Destructor
~CFIRFilter(); ~CFIRFilter();
// Processing // Processing
void ProcessSampleBlock(uint8* voice, int length); void ProcessSampleBlock(uint8* voice, int length);
private: private:
float* m_taps; float* m_taps;
int m_tapsLength; int m_tapsLength;
float* m_buffer; float* m_buffer;
int m_currentBufferPosition; int m_currentBufferPosition;
}; };
#endif //cfirfilter_h #endif //cfirfilter_h

@ -31,23 +31,23 @@
CFixedGain::CFixedGain(float gaindB) CFixedGain::CFixedGain(float gaindB)
{ {
m_gaindB = gaindB; m_gaindB = gaindB;
m_gainLinear = pow(10.0f, m_gaindB/20.0f); m_gainLinear = pow(10.0f, m_gaindB/20.0f);
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// processing // processing
inline void CFixedGain::ProcessSampleBlock(uint8* voice, int length) inline void CFixedGain::ProcessSampleBlock(uint8* voice, int length)
{ {
for(int i = 0; i < length; i += 2) for(int i = 0; i < length; i += 2)
{ {
float input = (float)(short)MAKEWORD(voice[i+1], voice[i]); float input = (float)(short)MAKEWORD(voice[i+1], voice[i]);
//apply gain //apply gain
float output = input * m_gainLinear; float output = input * m_gainLinear;
//write processed sample back //write processed sample back
voice[i] = HIBYTE((short)output); voice[i] = HIBYTE((short)output);
voice[i+1] = LOBYTE((short)output); voice[i+1] = LOBYTE((short)output);
} }
} }

@ -31,15 +31,15 @@
class CFixedGain : CSampleBlockProcessor class CFixedGain : CSampleBlockProcessor
{ {
public: public:
//Constructor //Constructor
CFixedGain(float gaindB); CFixedGain(float gaindB);
//processing //processing
void ProcessSampleBlock(uint8* voice, int length); void ProcessSampleBlock(uint8* voice, int length);
private: private:
float m_gaindB; //gain in dB float m_gaindB; //gain in dB
float m_gainLinear; //linearized gain float m_gainLinear; //linearized gain
}; };
#endif /* cfixedgain_h */ #endif /* cfixedgain_h */

@ -36,29 +36,29 @@
CFtdiDeviceDescr::CFtdiDeviceDescr(void) CFtdiDeviceDescr::CFtdiDeviceDescr(void)
{ {
m_bUsed = false; m_bUsed = false;
m_uiVid = 0; m_uiVid = 0;
m_uiPid = 0; m_uiPid = 0;
::memset(m_szDescription, 0, sizeof(m_szDescription)); ::memset(m_szDescription, 0, sizeof(m_szDescription));
::memset(m_szSerial, 0, sizeof(m_szSerial)); ::memset(m_szSerial, 0, sizeof(m_szSerial));
} }
CFtdiDeviceDescr::CFtdiDeviceDescr(uint32 uiVid, uint32 uiPid, const char *szDescription, const char *szSerial) CFtdiDeviceDescr::CFtdiDeviceDescr(uint32 uiVid, uint32 uiPid, const char *szDescription, const char *szSerial)
{ {
m_bUsed = false; m_bUsed = false;
m_uiVid = uiVid; m_uiVid = uiVid;
m_uiPid = uiPid; m_uiPid = uiPid;
::strcpy(m_szDescription, szDescription); ::strcpy(m_szDescription, szDescription);
::strcpy(m_szSerial, szSerial); ::strcpy(m_szSerial, szSerial);
} }
CFtdiDeviceDescr::CFtdiDeviceDescr(const CFtdiDeviceDescr &descr) CFtdiDeviceDescr::CFtdiDeviceDescr(const CFtdiDeviceDescr &descr)
{ {
m_bUsed = descr.m_bUsed; m_bUsed = descr.m_bUsed;
m_uiVid = descr.m_uiVid; m_uiVid = descr.m_uiVid;
m_uiPid = descr.m_uiPid; m_uiPid = descr.m_uiPid;
::memcpy(m_szDescription, descr.m_szDescription, sizeof(m_szDescription)); ::memcpy(m_szDescription, descr.m_szDescription, sizeof(m_szDescription));
::memcpy(m_szSerial, descr.m_szSerial, sizeof(m_szSerial)); ::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<CVocodecChannel *>*channels) int CFtdiDeviceDescr::CreateInterface(CFtdiDeviceDescr *descr, std::vector<CVocodecChannel *>*channels)
{ {
int iNbChs = 0; int iNbChs = 0;
// single channel devices cannot be created alone // single channel devices cannot be created alone
// three channels devices // three channels devices
if ( (::strcmp(descr->GetDescription(), "USB-3003") == 0) || // DVSI's USB-3003 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(), "DF2ET-3003") == 0) || // DF2ET's USB-3003 opensource device
(::strcmp(descr->GetDescription(), "DVstick-33") == 0) || // DVMEGA USB-3003 device (::strcmp(descr->GetDescription(), "DVstick-33") == 0) || // DVMEGA USB-3003 device
(::strcmp(descr->GetDescription(), "ThumbDV-3") == 0) ) // ThumbDV-3 (::strcmp(descr->GetDescription(), "ThumbDV-3") == 0) ) // ThumbDV-3
{ {
iNbChs = CreateUsb3003(descr, channels); iNbChs = CreateUsb3003(descr, channels);
} }
// six channels devices // six channels devices
else if ( (::strcmp(descr->GetDescription(), "USB-3006 A") == 0) ) // LX3JL's USB-3006 opensource device else if ( (::strcmp(descr->GetDescription(), "USB-3006 A") == 0) ) // LX3JL's USB-3006 opensource device
{ {
iNbChs = CreateUsb3006(descr, channels); iNbChs = CreateUsb3006(descr, channels);
} }
// twelves channels devices // twelves channels devices
else if ( (::strcmp(descr->GetDescription(), "USB-3012 A") == 0) ) // DVSI's USB-3012 else if ( (::strcmp(descr->GetDescription(), "USB-3012 A") == 0) ) // DVSI's USB-3012
{ {
iNbChs = CreateUsb3012(descr, channels); iNbChs = CreateUsb3012(descr, channels);
} }
// done // done
return iNbChs; return iNbChs;
} }
int CFtdiDeviceDescr::CreateInterfacePair(CFtdiDeviceDescr *descr1, CFtdiDeviceDescr *descr2, std::vector<CVocodecChannel *>*channels) int CFtdiDeviceDescr::CreateInterfacePair(CFtdiDeviceDescr *descr1, CFtdiDeviceDescr *descr2, std::vector<CVocodecChannel *>*channels)
{ {
int iNbChs = 0; int iNbChs = 0;
// create interface objects // create interface objects
if ( (descr1->GetNbChannels() == 1) && (descr2->GetNbChannels() == 1) ) if ( (descr1->GetNbChannels() == 1) && (descr2->GetNbChannels() == 1) )
{ {
// create 3000-3000 pair // create 3000-3000 pair
CUsb3000Interface *Usb3000A = InstantiateUsb3000(descr1); CUsb3000Interface *Usb3000A = InstantiateUsb3000(descr1);
CUsb3000Interface *Usb3000B = InstantiateUsb3000(descr2); CUsb3000Interface *Usb3000B = InstantiateUsb3000(descr2);
iNbChs = CreatePair(Usb3000A, Usb3000B, channels); iNbChs = CreatePair(Usb3000A, Usb3000B, channels);
} }
else if ( (descr1->GetNbChannels() == 3) && (descr2->GetNbChannels() == 1) ) else if ( (descr1->GetNbChannels() == 3) && (descr2->GetNbChannels() == 1) )
{ {
// create 3003-3000 pair // create 3003-3000 pair
CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr1); CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr1);
CUsb3000Interface *Usb3000 = InstantiateUsb3000(descr2); CUsb3000Interface *Usb3000 = InstantiateUsb3000(descr2);
iNbChs = CreatePair(Usb3003, Usb3000, channels); iNbChs = CreatePair(Usb3003, Usb3000, channels);
} }
else if ( (descr1->GetNbChannels() == 1) && (descr2->GetNbChannels() == 3) ) else if ( (descr1->GetNbChannels() == 1) && (descr2->GetNbChannels() == 3) )
{ {
// create 3000-3003 pair // create 3000-3003 pair
CUsb3000Interface *Usb3000 = InstantiateUsb3000(descr1); CUsb3000Interface *Usb3000 = InstantiateUsb3000(descr1);
CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr2); CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr2);
iNbChs = CreatePair(Usb3003, Usb3000, channels); iNbChs = CreatePair(Usb3003, Usb3000, channels);
} }
else if ( (descr1->GetNbChannels() == 3) && (descr2->GetNbChannels() == 3) ) else if ( (descr1->GetNbChannels() == 3) && (descr2->GetNbChannels() == 3) )
{ {
// create 3003-3003 pair // create 3003-3003 pair
CUsb3003Interface *Usb3003A = InstantiateUsb3003(descr1); CUsb3003Interface *Usb3003A = InstantiateUsb3003(descr1);
CUsb3003Interface *Usb3003B = InstantiateUsb3003(descr2); CUsb3003Interface *Usb3003B = InstantiateUsb3003(descr2);
iNbChs = CreatePair(Usb3003A, Usb3003B, channels); iNbChs = CreatePair(Usb3003A, Usb3003B, channels);
} }
// done // done
return iNbChs; return iNbChs;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -134,63 +134,63 @@ int CFtdiDeviceDescr::CreateInterfacePair(CFtdiDeviceDescr *descr1, CFtdiDeviceD
const char * CFtdiDeviceDescr::GetChannelDescription(int ch) const const char * CFtdiDeviceDescr::GetChannelDescription(int ch) const
{ {
static char descr[FTDI_MAX_STRINGLENGTH]; static char descr[FTDI_MAX_STRINGLENGTH];
char tag[3] = "_X"; char tag[3] = "_X";
::strcpy(descr, GetDescription()); ::strcpy(descr, GetDescription());
if ( ::strlen(descr) >= 2 ) if ( ::strlen(descr) >= 2 )
{ {
descr[::strlen(descr)-2] = 0x00; descr[::strlen(descr)-2] = 0x00;
tag[1] = (char)ch + 'A'; tag[1] = (char)ch + 'A';
::strcat(descr, tag); ::strcat(descr, tag);
} }
return descr; return descr;
} }
const char * CFtdiDeviceDescr::GetChannelSerialNumber(int ch) const const char * CFtdiDeviceDescr::GetChannelSerialNumber(int ch) const
{ {
static char serial[FTDI_MAX_STRINGLENGTH]; static char serial[FTDI_MAX_STRINGLENGTH];
::strcpy(serial, GetSerialNumber()); ::strcpy(serial, GetSerialNumber());
if ( ::strlen(serial) >= 1 ) if ( ::strlen(serial) >= 1 )
{ {
serial[::strlen(serial)-1] = (char)ch + 'A'; serial[::strlen(serial)-1] = (char)ch + 'A';
} }
return serial; return serial;
} }
int CFtdiDeviceDescr::GetNbChannels(void) const int CFtdiDeviceDescr::GetNbChannels(void) const
{ {
int iNbChs = 0; int iNbChs = 0;
// single channel devices // single channel devices
if ( (::strcmp(m_szDescription, "USB-3000") == 0) || // DVSI's USB-3000 if ( (::strcmp(m_szDescription, "USB-3000") == 0) || // DVSI's USB-3000
(::strcmp(m_szDescription, "DVstick-30") == 0) || // DVMEGA AMBE3000 device (::strcmp(m_szDescription, "DVstick-30") == 0) || // DVMEGA AMBE3000 device
(::strcmp(m_szDescription, "ThumbDV") == 0) ) // ThumbDV (::strcmp(m_szDescription, "ThumbDV") == 0) ) // ThumbDV
{ {
iNbChs = 1; iNbChs = 1;
} }
// three channels devices // three channels devices
else if ( (::strcmp(m_szDescription, "USB-3003") == 0) || // DVSI's USB-3003 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, "DF2ET-3003") == 0) || // DF2ET's USB-3003 opensource device
(::strcmp(m_szDescription, "DVstick-33") == 0) || // DVMEGA AMBE 3003 device (::strcmp(m_szDescription, "DVstick-33") == 0) || // DVMEGA AMBE 3003 device
(::strcmp(m_szDescription, "ThumbDV-3") == 0) ) // ThumbDV-3 (::strcmp(m_szDescription, "ThumbDV-3") == 0) ) // ThumbDV-3
{ {
iNbChs = 3; iNbChs = 3;
} }
// six channels devices // six channels devices
else if ( (::strcmp(m_szDescription, "USB-3006 A") == 0) ) // LX3JL's USB-3006 opensource device else if ( (::strcmp(m_szDescription, "USB-3006 A") == 0) ) // LX3JL's USB-3006 opensource device
{ {
iNbChs = 6; iNbChs = 6;
} }
// twelves channels devices // twelves channels devices
else if ( (::strcmp(m_szDescription, "USB-3012 A") == 0) ) // DVSI's USB-3012 else if ( (::strcmp(m_szDescription, "USB-3012 A") == 0) ) // DVSI's USB-3012
{ {
iNbChs = 12; iNbChs = 12;
} }
// done // done
return iNbChs; return iNbChs;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -203,92 +203,92 @@ int CFtdiDeviceDescr::GetNbChannels(void) const
int CFtdiDeviceDescr::CreateUsb3012(CFtdiDeviceDescr *descr, std::vector<CVocodecChannel *>*channels) int CFtdiDeviceDescr::CreateUsb3012(CFtdiDeviceDescr *descr, std::vector<CVocodecChannel *>*channels)
{ {
int nStreams = 0; int nStreams = 0;
// create the interfaces for the four 3003 chips // create the interfaces for the four 3003 chips
CUsb3003HRInterface *Usb3003A = CUsb3003HRInterface *Usb3003A =
new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(0), descr->GetChannelSerialNumber(0)); new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(0), descr->GetChannelSerialNumber(0));
CUsb3003HRInterface *Usb3003B = CUsb3003HRInterface *Usb3003B =
new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(1), descr->GetChannelSerialNumber(1)); new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(1), descr->GetChannelSerialNumber(1));
CUsb3003HRInterface *Usb3003C = CUsb3003HRInterface *Usb3003C =
new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(2), descr->GetChannelSerialNumber(2)); new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(2), descr->GetChannelSerialNumber(2));
CUsb3003HRInterface *Usb3003D = CUsb3003HRInterface *Usb3003D =
new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(3), descr->GetChannelSerialNumber(3)); new CUsb3003HRInterface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(3), descr->GetChannelSerialNumber(3));
// init the interfaces // init the interfaces
if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) && if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) &&
Usb3003C->Init(CODEC_AMBEPLUS) && Usb3003D->Init(CODEC_AMBE2PLUS) ) Usb3003C->Init(CODEC_AMBEPLUS) && Usb3003D->Init(CODEC_AMBE2PLUS) )
{ {
CVocodecChannel *Channel; CVocodecChannel *Channel;
// create all channels // create all channels
{ {
// ch1 // ch1
Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS); Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003A->AddChannel(Channel); Usb3003A->AddChannel(Channel);
// ch2 // ch2
Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS); Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003A->AddChannel(Channel); Usb3003A->AddChannel(Channel);
// ch3 // ch3
Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS); Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003B->AddChannel(Channel); Usb3003B->AddChannel(Channel);
// ch4 // ch4
Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS); Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003B->AddChannel(Channel); Usb3003B->AddChannel(Channel);
// ch5 // ch5
Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS); Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003A->AddChannel(Channel); Usb3003A->AddChannel(Channel);
Usb3003B->AddChannel(Channel); Usb3003B->AddChannel(Channel);
// ch6 // ch6
Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS); Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003A->AddChannel(Channel); Usb3003A->AddChannel(Channel);
Usb3003B->AddChannel(Channel); Usb3003B->AddChannel(Channel);
// ch7 // ch7
Channel = new CVocodecChannel(Usb3003C, 0, Usb3003C, 1, CODECGAIN_AMBEPLUS); Channel = new CVocodecChannel(Usb3003C, 0, Usb3003C, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003C->AddChannel(Channel); Usb3003C->AddChannel(Channel);
// ch8 // ch8
Channel = new CVocodecChannel(Usb3003C, 1, Usb3003C, 0, CODECGAIN_AMBE2PLUS); Channel = new CVocodecChannel(Usb3003C, 1, Usb3003C, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003C->AddChannel(Channel); Usb3003C->AddChannel(Channel);
// ch9 // ch9
Channel = new CVocodecChannel(Usb3003D, 0, Usb3003D, 1, CODECGAIN_AMBEPLUS); Channel = new CVocodecChannel(Usb3003D, 0, Usb3003D, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003D->AddChannel(Channel); Usb3003D->AddChannel(Channel);
// ch10 // ch10
Channel = new CVocodecChannel(Usb3003D, 1, Usb3003D, 0, CODECGAIN_AMBE2PLUS); Channel = new CVocodecChannel(Usb3003D, 1, Usb3003D, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003D->AddChannel(Channel); Usb3003D->AddChannel(Channel);
// ch11 // ch11
Channel = new CVocodecChannel(Usb3003C, 2, Usb3003D, 2, CODECGAIN_AMBEPLUS); Channel = new CVocodecChannel(Usb3003C, 2, Usb3003D, 2, CODECGAIN_AMBEPLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003C->AddChannel(Channel); Usb3003C->AddChannel(Channel);
Usb3003D->AddChannel(Channel); Usb3003D->AddChannel(Channel);
// ch12 // ch12
Channel = new CVocodecChannel(Usb3003D, 2, Usb3003C, 2, CODECGAIN_AMBE2PLUS); Channel = new CVocodecChannel(Usb3003D, 2, Usb3003C, 2, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003C->AddChannel(Channel); Usb3003C->AddChannel(Channel);
Usb3003D->AddChannel(Channel); Usb3003D->AddChannel(Channel);
//done //done
nStreams = 12; nStreams = 12;
} }
} }
else else
{ {
// cleanup // cleanup
delete Usb3003A; delete Usb3003A;
delete Usb3003B; delete Usb3003B;
delete Usb3003C; delete Usb3003C;
delete Usb3003D; delete Usb3003D;
} }
// done // done
return nStreams; return nStreams;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -300,59 +300,59 @@ int CFtdiDeviceDescr::CreateUsb3012(CFtdiDeviceDescr *descr, std::vector<CVocode
// //
int CFtdiDeviceDescr::CreateUsb3006(CFtdiDeviceDescr *descr, std::vector<CVocodecChannel *>*channels) int CFtdiDeviceDescr::CreateUsb3006(CFtdiDeviceDescr *descr, std::vector<CVocodecChannel *>*channels)
{ {
int nStreams = 0; int nStreams = 0;
// create the interfaces for the two 3003 chips // create the interfaces for the two 3003 chips
CUsb3003Interface *Usb3003A = CUsb3003Interface *Usb3003A =
new CUsb3003Interface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(0), descr->GetChannelSerialNumber(0)); new CUsb3003Interface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(0), descr->GetChannelSerialNumber(0));
CUsb3003Interface *Usb3003B = CUsb3003Interface *Usb3003B =
new CUsb3003Interface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(1), descr->GetChannelSerialNumber(1)); new CUsb3003Interface(descr->GetVid(), descr->GetPid(), descr->GetChannelDescription(1), descr->GetChannelSerialNumber(1));
// init the interfaces // init the interfaces
if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) ) if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) )
{ {
CVocodecChannel *Channel; CVocodecChannel *Channel;
// create all channels // create all channels
{ {
// ch1 // ch1
Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS); Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003A->AddChannel(Channel); Usb3003A->AddChannel(Channel);
// ch2 // ch2
Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS); Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003A->AddChannel(Channel); Usb3003A->AddChannel(Channel);
// ch3 // ch3
Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS); Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003B->AddChannel(Channel); Usb3003B->AddChannel(Channel);
// ch4 // ch4
Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS); Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003B->AddChannel(Channel); Usb3003B->AddChannel(Channel);
// ch5 // ch5
Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS); Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003A->AddChannel(Channel); Usb3003A->AddChannel(Channel);
Usb3003B->AddChannel(Channel); Usb3003B->AddChannel(Channel);
// ch6 // ch6
Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS); Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003A->AddChannel(Channel); Usb3003A->AddChannel(Channel);
Usb3003B->AddChannel(Channel); Usb3003B->AddChannel(Channel);
//done //done
nStreams = 6; nStreams = 6;
} }
} }
else else
{ {
// cleanup // cleanup
delete Usb3003A; delete Usb3003A;
delete Usb3003B; delete Usb3003B;
} }
// done // done
return nStreams; return nStreams;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -368,37 +368,37 @@ int CFtdiDeviceDescr::CreateUsb3006(CFtdiDeviceDescr *descr, std::vector<CVocode
// //
int CFtdiDeviceDescr::CreateUsb3003(CFtdiDeviceDescr *descr, std::vector<CVocodecChannel *>*channels) int CFtdiDeviceDescr::CreateUsb3003(CFtdiDeviceDescr *descr, std::vector<CVocodecChannel *>*channels)
{ {
int nStreams = 0; int nStreams = 0;
// create the interfaces for the 3003 chip // create the interfaces for the 3003 chip
CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr); CUsb3003Interface *Usb3003 = InstantiateUsb3003(descr);
// init the interface // init the interface
if ( (Usb3003 != NULL) && Usb3003->Init(CODEC_NONE) ) if ( (Usb3003 != NULL) && Usb3003->Init(CODEC_NONE) )
{ {
CVocodecChannel *Channel; CVocodecChannel *Channel;
// create all channels // create all channels
{ {
// ch1 // ch1
Channel = new CVocodecChannel(Usb3003, 0, Usb3003, 1, CODECGAIN_AMBEPLUS); Channel = new CVocodecChannel(Usb3003, 0, Usb3003, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003->AddChannel(Channel); Usb3003->AddChannel(Channel);
// ch2 // ch2
Channel = new CVocodecChannel(Usb3003, 1, Usb3003, 0, CODECGAIN_AMBE2PLUS); Channel = new CVocodecChannel(Usb3003, 1, Usb3003, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003->AddChannel(Channel); Usb3003->AddChannel(Channel);
// done // done
nStreams = 2; nStreams = 2;
} }
} }
else else
{ {
// cleanup // cleanup
delete Usb3003; delete Usb3003;
} }
// done // done
return nStreams; return nStreams;
} }
@ -407,38 +407,38 @@ int CFtdiDeviceDescr::CreateUsb3003(CFtdiDeviceDescr *descr, std::vector<CVocode
int CFtdiDeviceDescr::CreatePair(CUsb3000Interface *Usb3000A, CUsb3000Interface *Usb3000B, std::vector<CVocodecChannel *>*channels) int CFtdiDeviceDescr::CreatePair(CUsb3000Interface *Usb3000A, CUsb3000Interface *Usb3000B, std::vector<CVocodecChannel *>*channels)
{ {
int nStreams = 0; int nStreams = 0;
// init the interfaces // init the interfaces
if ( Usb3000A->Init(CODEC_AMBEPLUS) && Usb3000B->Init(CODEC_AMBE2PLUS) ) if ( Usb3000A->Init(CODEC_AMBEPLUS) && Usb3000B->Init(CODEC_AMBE2PLUS) )
{ {
CVocodecChannel *Channel; CVocodecChannel *Channel;
// create all channels // create all channels
{ {
// ch1 // ch1
Channel = new CVocodecChannel(Usb3000A, 0, Usb3000B, 0, CODECGAIN_AMBEPLUS); Channel = new CVocodecChannel(Usb3000A, 0, Usb3000B, 0, CODECGAIN_AMBEPLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3000A->AddChannel(Channel); Usb3000A->AddChannel(Channel);
Usb3000B->AddChannel(Channel); Usb3000B->AddChannel(Channel);
// ch2 // ch2
Channel = new CVocodecChannel(Usb3000B, 0, Usb3000A, 0, CODECGAIN_AMBE2PLUS); Channel = new CVocodecChannel(Usb3000B, 0, Usb3000A, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3000A->AddChannel(Channel); Usb3000A->AddChannel(Channel);
Usb3000B->AddChannel(Channel); Usb3000B->AddChannel(Channel);
// done // done
nStreams = 2; nStreams = 2;
} }
} }
else else
{ {
// cleanup // cleanup
delete Usb3000A; delete Usb3000A;
delete Usb3000B; delete Usb3000B;
} }
// done // done
return nStreams; return nStreams;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -446,53 +446,53 @@ int CFtdiDeviceDescr::CreatePair(CUsb3000Interface *Usb3000A, CUsb3000Interface
int CFtdiDeviceDescr::CreatePair(CUsb3003Interface *Usb3003A, CUsb3003Interface *Usb3003B, std::vector<CVocodecChannel *>*channels) int CFtdiDeviceDescr::CreatePair(CUsb3003Interface *Usb3003A, CUsb3003Interface *Usb3003B, std::vector<CVocodecChannel *>*channels)
{ {
int nStreams = 0; int nStreams = 0;
// init the interfaces // init the interfaces
if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) ) if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) )
{ {
CVocodecChannel *Channel; CVocodecChannel *Channel;
// create all channels // create all channels
{ {
// ch1 // ch1
Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS); Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003A->AddChannel(Channel); Usb3003A->AddChannel(Channel);
// ch2 // ch2
Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS); Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003A->AddChannel(Channel); Usb3003A->AddChannel(Channel);
// ch3 // ch3
Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS); Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003B->AddChannel(Channel); Usb3003B->AddChannel(Channel);
// ch4 // ch4
Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS); Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003B->AddChannel(Channel); Usb3003B->AddChannel(Channel);
// ch5 // ch5
Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS); Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003A->AddChannel(Channel); Usb3003A->AddChannel(Channel);
Usb3003B->AddChannel(Channel); Usb3003B->AddChannel(Channel);
// ch6 // ch6
Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS); Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003A->AddChannel(Channel); Usb3003A->AddChannel(Channel);
Usb3003B->AddChannel(Channel); Usb3003B->AddChannel(Channel);
// done // done
nStreams = 6; nStreams = 6;
} }
} }
else else
{ {
// cleanup // cleanup
delete Usb3003A; delete Usb3003A;
delete Usb3003B; delete Usb3003B;
} }
// done // done
return nStreams; return nStreams;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -500,45 +500,45 @@ int CFtdiDeviceDescr::CreatePair(CUsb3003Interface *Usb3003A, CUsb3003Interface
int CFtdiDeviceDescr::CreatePair(CUsb3003Interface *Usb3003A, CUsb3000Interface *Usb3000B, std::vector<CVocodecChannel *>*channels) int CFtdiDeviceDescr::CreatePair(CUsb3003Interface *Usb3003A, CUsb3000Interface *Usb3000B, std::vector<CVocodecChannel *>*channels)
{ {
int nStreams = 0; int nStreams = 0;
// init the interfaces // init the interfaces
if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3000B->Init(CODEC_AMBE2PLUS) ) if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3000B->Init(CODEC_AMBE2PLUS) )
{ {
CVocodecChannel *Channel; CVocodecChannel *Channel;
// create all channels // create all channels
{ {
// ch1 // ch1
Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS); Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003A->AddChannel(Channel); Usb3003A->AddChannel(Channel);
// ch2 // ch2
Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS); Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003A->AddChannel(Channel); Usb3003A->AddChannel(Channel);
// ch3 // ch3
Channel = new CVocodecChannel(Usb3003A, 2, Usb3000B, 0, CODECGAIN_AMBEPLUS); Channel = new CVocodecChannel(Usb3003A, 2, Usb3000B, 0, CODECGAIN_AMBEPLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003A->AddChannel(Channel); Usb3003A->AddChannel(Channel);
Usb3000B->AddChannel(Channel); Usb3000B->AddChannel(Channel);
// ch4 // ch4
Channel = new CVocodecChannel(Usb3000B, 0, Usb3003A, 2, CODECGAIN_AMBE2PLUS); Channel = new CVocodecChannel(Usb3000B, 0, Usb3003A, 2, CODECGAIN_AMBE2PLUS);
channels->push_back(Channel); channels->push_back(Channel);
Usb3003A->AddChannel(Channel); Usb3003A->AddChannel(Channel);
Usb3000B->AddChannel(Channel); Usb3000B->AddChannel(Channel);
// done // done
nStreams = 4; nStreams = 4;
} }
} }
else else
{ {
// cleanup // cleanup
delete Usb3003A; delete Usb3003A;
delete Usb3000B; delete Usb3000B;
} }
// done // done
return nStreams; return nStreams;
} }
@ -547,50 +547,50 @@ int CFtdiDeviceDescr::CreatePair(CUsb3003Interface *Usb3003A, CUsb3000Interface
CUsb3003Interface *CFtdiDeviceDescr::InstantiateUsb3003(CFtdiDeviceDescr *descr) CUsb3003Interface *CFtdiDeviceDescr::InstantiateUsb3003(CFtdiDeviceDescr *descr)
{ {
CUsb3003Interface *Usb3003 = NULL; CUsb3003Interface *Usb3003 = NULL;
// intstantiate the proper version of USB-3003 // intstantiate the proper version of USB-3003
if ( (::strcmp(descr->GetDescription(), "USB-3003") == 0) ) // DVSI's USB-3003 if ( (::strcmp(descr->GetDescription(), "USB-3003") == 0) ) // DVSI's USB-3003
{ {
// hardware reset, 921600 bps // hardware reset, 921600 bps
Usb3003 = new CUsb3003HRInterface Usb3003 = new CUsb3003HRInterface
(descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber()); (descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber());
} }
else if ( (::strcmp(descr->GetDescription(), "DF2ET-3003") == 0) ) // DF2ET's USB-3003 opensource device else if ( (::strcmp(descr->GetDescription(), "DF2ET-3003") == 0) ) // DF2ET's USB-3003 opensource device
{ {
// specific hardware reset, 921600 bps // specific hardware reset, 921600 bps
Usb3003 = new CUsb3003DF2ETInterface Usb3003 = new CUsb3003DF2ETInterface
(descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber()); (descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber());
} }
else if ( (::strcmp(descr->GetDescription(), "ThumbDV-3") == 0) ) // ThumbDV-3 else if ( (::strcmp(descr->GetDescription(), "ThumbDV-3") == 0) ) // ThumbDV-3
{ {
// software reset, 921600 bps // software reset, 921600 bps
Usb3003 = new CUsb3003Interface Usb3003 = new CUsb3003Interface
(descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber()); (descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber());
} }
else if ( (::strcmp(descr->GetDescription(), "DVstick-33") == 0) ) // DVMEGA AMBE3003 device else if ( (::strcmp(descr->GetDescription(), "DVstick-33") == 0) ) // DVMEGA AMBE3003 device
{ {
// specific fardware reset, 921600 bps // specific fardware reset, 921600 bps
Usb3003 = new CUsb3003DF2ETInterface Usb3003 = new CUsb3003DF2ETInterface
(descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber()); (descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber());
} }
// done // done
return Usb3003; return Usb3003;
} }
CUsb3000Interface *CFtdiDeviceDescr::InstantiateUsb3000(CFtdiDeviceDescr *descr) CUsb3000Interface *CFtdiDeviceDescr::InstantiateUsb3000(CFtdiDeviceDescr *descr)
{ {
CUsb3000Interface *Usb3000 = NULL; CUsb3000Interface *Usb3000 = NULL;
// intstantiate the proper version of USB-3000 // intstantiate the proper version of USB-3000
if ( (::strcmp(descr->GetDescription(), "USB-3000") == 0) || // DVSI's 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(), "DVstick-30")== 0) || // DVMEGA AMBE3000 device
(::strcmp(descr->GetDescription(), "ThumbDV") == 0) ) // ThumbDV (::strcmp(descr->GetDescription(), "ThumbDV") == 0) ) // ThumbDV
{ {
Usb3000 = new CUsb3000Interface Usb3000 = new CUsb3000Interface
(descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber()); (descr->GetVid(), descr->GetPid(), descr->GetDescription(), descr->GetSerialNumber());
} }
// done // done
return Usb3000; return Usb3000;
} }

@ -45,52 +45,52 @@ class CUsb3003Interface;
class CFtdiDeviceDescr class CFtdiDeviceDescr
{ {
public: public:
// constructors // constructors
CFtdiDeviceDescr(void); CFtdiDeviceDescr(void);
CFtdiDeviceDescr(uint32, uint32, const char *, const char *); CFtdiDeviceDescr(uint32, uint32, const char *, const char *);
CFtdiDeviceDescr(const CFtdiDeviceDescr &); CFtdiDeviceDescr(const CFtdiDeviceDescr &);
// destructor // destructor
virtual ~CFtdiDeviceDescr() {} virtual ~CFtdiDeviceDescr() {}
// interface factory // interface factory
static int CreateInterface(CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*); static int CreateInterface(CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*);
static int CreateInterfacePair(CFtdiDeviceDescr *, CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*); static int CreateInterfacePair(CFtdiDeviceDescr *, CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*);
// get // get
bool IsUsed(void) const { return m_bUsed; } bool IsUsed(void) const { return m_bUsed; }
int GetNbChannels(void) const; int GetNbChannels(void) const;
uint32 GetVid(void) const { return m_uiVid; } uint32 GetVid(void) const { return m_uiVid; }
uint32 GetPid(void) const { return m_uiPid; } uint32 GetPid(void) const { return m_uiPid; }
const char *GetDescription(void) const { return m_szDescription; } const char *GetDescription(void) const { return m_szDescription; }
const char *GetSerialNumber(void) const { return m_szSerial; } const char *GetSerialNumber(void) const { return m_szSerial; }
const char * GetChannelDescription(int) const; const char * GetChannelDescription(int) const;
const char * GetChannelSerialNumber(int) const; const char * GetChannelSerialNumber(int) const;
// set // set
void SetUsed(bool used) { m_bUsed = used; } void SetUsed(bool used) { m_bUsed = used; }
protected: protected:
// factory helper // factory helper
static int CreateUsb3012(CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*); static int CreateUsb3012(CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*);
static int CreateUsb3006(CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*); static int CreateUsb3006(CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*);
static int CreateUsb3003(CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*); static int CreateUsb3003(CFtdiDeviceDescr *, std::vector<CVocodecChannel *>*);
static int CreatePair(CUsb3003Interface *, CUsb3003Interface *, std::vector<CVocodecChannel *>*); static int CreatePair(CUsb3003Interface *, CUsb3003Interface *, std::vector<CVocodecChannel *>*);
static int CreatePair(CUsb3003Interface *, CUsb3000Interface *, std::vector<CVocodecChannel *>*); static int CreatePair(CUsb3003Interface *, CUsb3000Interface *, std::vector<CVocodecChannel *>*);
static int CreatePair(CUsb3000Interface *, CUsb3000Interface *, std::vector<CVocodecChannel *>*); static int CreatePair(CUsb3000Interface *, CUsb3000Interface *, std::vector<CVocodecChannel *>*);
static CUsb3003Interface *InstantiateUsb3003(CFtdiDeviceDescr *); static CUsb3003Interface *InstantiateUsb3003(CFtdiDeviceDescr *);
static CUsb3000Interface *InstantiateUsb3000(CFtdiDeviceDescr *); static CUsb3000Interface *InstantiateUsb3000(CFtdiDeviceDescr *);
protected: protected:
// status // status
bool m_bUsed; bool m_bUsed;
// data // data
uint32 m_uiVid; uint32 m_uiVid;
uint32 m_uiPid; uint32 m_uiPid;
char m_szDescription[FTDI_MAX_STRINGLENGTH]; char m_szDescription[FTDI_MAX_STRINGLENGTH];
char m_szSerial[FTDI_MAX_STRINGLENGTH]; char m_szSerial[FTDI_MAX_STRINGLENGTH];
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -31,19 +31,19 @@
CPacket::CPacket() CPacket::CPacket()
{ {
m_iCh = 0; m_iCh = 0;
m_uiPid = 0; m_uiPid = 0;
}; };
CPacket::CPacket(uint8 uiPid) CPacket::CPacket(uint8 uiPid)
{ {
m_iCh = 0; m_iCh = 0;
m_uiPid = uiPid; m_uiPid = uiPid;
} }
CPacket::CPacket(const CPacket &packet) CPacket::CPacket(const CPacket &packet)
{ {
m_iCh = packet.m_iCh; m_iCh = packet.m_iCh;
m_uiPid = packet.m_uiPid; m_uiPid = packet.m_uiPid;
}; };

@ -32,30 +32,30 @@
class CPacket class CPacket
{ {
public: public:
// constructors // constructors
CPacket(); CPacket();
CPacket(uint8); CPacket(uint8);
CPacket(const CPacket &); CPacket(const CPacket &);
// destructor // destructor
virtual ~CPacket() {}; virtual ~CPacket() {};
// identity // identity
virtual bool IsVoice(void) const { return false; } virtual bool IsVoice(void) const { return false; }
virtual bool IsAmbe(void) const { return false; } virtual bool IsAmbe(void) const { return false; }
// get // get
int GetChannel(void) const { return m_iCh; } int GetChannel(void) const { return m_iCh; }
uint8 GetPid(void) const { return m_uiPid; } uint8 GetPid(void) const { return m_uiPid; }
// set // set
void SetChannel(int i) { m_iCh = i; } void SetChannel(int i) { m_iCh = i; }
void SetPid(uint8 ui) { m_uiPid = ui; } void SetPid(uint8 ui) { m_uiPid = ui; }
protected: protected:
// data // data
int m_iCh; int m_iCh;
uint8 m_uiPid; uint8 m_uiPid;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -38,12 +38,12 @@ CPacketQueue::CPacketQueue()
CPacketQueue::~CPacketQueue() CPacketQueue::~CPacketQueue()
{ {
// empty codec queue // empty codec queue
while ( !empty() ) while ( !empty() )
{ {
delete front(); delete front();
pop(); pop();
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -51,10 +51,10 @@ CPacketQueue::~CPacketQueue()
void CPacketQueue::Purge(void) void CPacketQueue::Purge(void)
{ {
// this assume queue is already locked // this assume queue is already locked
while ( !empty() ) while ( !empty() )
{ {
delete front(); delete front();
pop(); pop();
} }
} }

@ -33,22 +33,22 @@
class CPacketQueue : public std::queue<CPacket *> class CPacketQueue : public std::queue<CPacket *>
{ {
public: public:
// constructor // constructor
CPacketQueue(); CPacketQueue();
// destructor // destructor
~CPacketQueue(); ~CPacketQueue();
// lock // lock
void Lock() { m_Mutex.lock(); } void Lock() { m_Mutex.lock(); }
void Unlock() { m_Mutex.unlock(); } void Unlock() { m_Mutex.unlock(); }
// purge // purge
void Purge(void); void Purge(void);
protected: protected:
// status // status
std::mutex m_Mutex; std::mutex m_Mutex;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -32,8 +32,8 @@ class CSampleBlockProcessor
{ {
public: public:
virtual ~CSampleBlockProcessor() {} virtual ~CSampleBlockProcessor() {}
//processing //processing
virtual void ProcessSampleBlock(uint8* voice, int length) = 0; virtual void ProcessSampleBlock(uint8* voice, int length) = 0;
}; };
#endif /* csampleprocessor_h */ #endif /* csampleprocessor_h */

@ -43,12 +43,12 @@
CSignalProcessor::CSignalProcessor(float gaindB) CSignalProcessor::CSignalProcessor(float gaindB)
{ {
#if USE_BANDPASSFILTER #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 #endif
#if USE_AGC == 1 #if USE_AGC == 1
m_sampleProcessors.push_back((CSampleBlockProcessor*)new CAGC(gaindB)); m_sampleProcessors.push_back((CSampleBlockProcessor*)new CAGC(gaindB));
#else #else
m_sampleProcessors.push_back((CSampleBlockProcessor*)new CFixedGain(gaindB)); m_sampleProcessors.push_back((CSampleBlockProcessor*)new CFixedGain(gaindB));
#endif #endif
} }
@ -57,10 +57,10 @@ CSignalProcessor::CSignalProcessor(float gaindB)
CSignalProcessor::~CSignalProcessor() CSignalProcessor::~CSignalProcessor()
{ {
for(auto it=m_sampleProcessors.begin(); it!=m_sampleProcessors.end(); it++) for(auto it=m_sampleProcessors.begin(); it!=m_sampleProcessors.end(); it++)
{ {
delete *it; delete *it;
} }
m_sampleProcessors.clear(); m_sampleProcessors.clear();
} }
@ -69,26 +69,26 @@ CSignalProcessor::~CSignalProcessor()
void CSignalProcessor::Process(uint8* voice, int length) void CSignalProcessor::Process(uint8* voice, int length)
{ {
/*float sample; /*float sample;
int j;*/ int j;*/
for(auto it=m_sampleProcessors.begin(); it!=m_sampleProcessors.end(); it++) for(auto it=m_sampleProcessors.begin(); it!=m_sampleProcessors.end(); it++)
{ {
(*it)->ProcessSampleBlock(voice, length); (*it)->ProcessSampleBlock(voice, length);
} }
/*for(int i = 0; i < length; i += 2) /*for(int i = 0; i < length; i += 2)
{ {
//Get the sample //Get the sample
sample = (float)(short)MAKEWORD(voice[i+1], voice[i]); sample = (float)(short)MAKEWORD(voice[i+1], voice[i]);
for(j = 0; j < processorsSize; j++) for(j = 0; j < processorsSize; j++)
{ {
sample = m_sampleProcessors[j]->ProcessSample(sample); sample = m_sampleProcessors[j]->ProcessSample(sample);
} }
//write processed sample back //write processed sample back
voice[i] = HIBYTE((short)sample); voice[i] = HIBYTE((short)sample);
voice[i+1] = LOBYTE((short)sample); voice[i+1] = LOBYTE((short)sample);
}*/ }*/
} }

@ -32,17 +32,17 @@
class CSignalProcessor class CSignalProcessor
{ {
public: public:
//Constructor //Constructor
CSignalProcessor(float gaindB); CSignalProcessor(float gaindB);
//Destructor //Destructor
~CSignalProcessor(); ~CSignalProcessor();
//Processing //Processing
void Process(uint8* voice, int length); void Process(uint8* voice, int length);
private: private:
std::list<CSampleBlockProcessor *> m_sampleProcessors; std::list<CSampleBlockProcessor *> m_sampleProcessors;
}; };
#endif /* csignalprocessor_h */ #endif /* csignalprocessor_h */

@ -41,30 +41,30 @@
CStream::CStream() CStream::CStream()
{ {
m_uiId = 0; m_uiId = 0;
m_uiPort = 0; m_uiPort = 0;
m_bStopThread = false; m_bStopThread = false;
m_pThread = NULL; m_pThread = NULL;
m_VocodecChannel = NULL; m_VocodecChannel = NULL;
m_LastActivity.Now(); m_LastActivity.Now();
m_iTotalPackets = 0; m_iTotalPackets = 0;
m_iLostPackets = 0; m_iLostPackets = 0;
} }
CStream::CStream(uint16 uiId, const CCallsign &Callsign, const CIp &Ip, uint8 uiCodecIn, uint8 uiCodecOut) CStream::CStream(uint16 uiId, const CCallsign &Callsign, const CIp &Ip, uint8 uiCodecIn, uint8 uiCodecOut)
{ {
m_uiId = uiId; m_uiId = uiId;
m_Callsign = Callsign; m_Callsign = Callsign;
m_Ip = Ip; m_Ip = Ip;
m_uiPort = 0; m_uiPort = 0;
m_uiCodecIn = uiCodecIn; m_uiCodecIn = uiCodecIn;
m_uiCodecOut = uiCodecOut; m_uiCodecOut = uiCodecOut;
m_bStopThread = false; m_bStopThread = false;
m_pThread = NULL; m_pThread = NULL;
m_VocodecChannel = NULL; m_VocodecChannel = NULL;
m_LastActivity.Now(); m_LastActivity.Now();
m_iTotalPackets = 0; m_iTotalPackets = 0;
m_iLostPackets = 0; m_iLostPackets = 0;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -72,21 +72,21 @@ CStream::CStream(uint16 uiId, const CCallsign &Callsign, const CIp &Ip, uint8 ui
CStream::~CStream() CStream::~CStream()
{ {
// stop thread first // stop thread first
m_bStopThread = true; m_bStopThread = true;
if ( m_pThread != NULL ) if ( m_pThread != NULL )
{ {
m_pThread->join(); m_pThread->join();
delete m_pThread; delete m_pThread;
m_pThread = NULL; m_pThread = NULL;
} }
// then close everything // then close everything
m_Socket.Close(); m_Socket.Close();
if ( m_VocodecChannel != NULL ) if ( m_VocodecChannel != NULL )
{ {
m_VocodecChannel->Close(); m_VocodecChannel->Close();
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -94,10 +94,10 @@ CStream::~CStream()
bool CStream::Init(uint16 uiPort) bool CStream::Init(uint16 uiPort)
{ {
// reset stop flag // reset stop flag
m_bStopThread = false; m_bStopThread = false;
// create our socket // create our socket
auto s = g_AmbeServer.GetListenIp(); auto s = g_AmbeServer.GetListenIp();
CIp ip(strchr(s, ':') ? AF_INET6 : AF_INET, uiPort, s); CIp ip(strchr(s, ':') ? AF_INET6 : AF_INET, uiPort, s);
if (! ip.IsSet()) if (! ip.IsSet())
@ -106,7 +106,7 @@ bool CStream::Init(uint16 uiPort)
return false; return false;
} }
if (! m_Socket.Open(ip)) if (! m_Socket.Open(ip))
{ {
std::cout << "Error opening stream stream socket on " << ip << std::endl; std::cout << "Error opening stream stream socket on " << ip << std::endl;
return false; return false;
@ -133,32 +133,32 @@ bool CStream::Init(uint16 uiPort)
m_iLostPackets = 0; m_iLostPackets = 0;
// done // done
return true; return true;
} }
void CStream::Close(void) void CStream::Close(void)
{ {
// stop thread first // stop thread first
m_bStopThread = true; m_bStopThread = true;
if ( m_pThread != NULL ) if ( m_pThread != NULL )
{ {
m_pThread->join(); m_pThread->join();
delete m_pThread; delete m_pThread;
m_pThread = NULL; m_pThread = NULL;
} }
// then close everything // then close everything
m_Socket.Close(); m_Socket.Close();
if ( m_VocodecChannel != NULL ) if ( m_VocodecChannel != NULL )
{ {
m_VocodecChannel->Close(); m_VocodecChannel->Close();
} }
// report // report
std::cout << m_iLostPackets << " of " << m_iTotalPackets << " packets lost" << std::endl; std::cout << m_iLostPackets << " of " << m_iTotalPackets << " packets lost" << std::endl;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -166,10 +166,10 @@ void CStream::Close(void)
void CStream::Thread(CStream *This) void CStream::Thread(CStream *This)
{ {
while ( !This->m_bStopThread ) while ( !This->m_bStopThread )
{ {
This->Task(); This->Task();
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -177,45 +177,45 @@ void CStream::Thread(CStream *This)
void CStream::Task(void) void CStream::Task(void)
{ {
CBuffer Buffer; CBuffer Buffer;
static CIp Ip; static CIp Ip;
uint8 uiPid; uint8 uiPid;
uint8 Ambe[AMBE_FRAME_SIZE]; uint8 Ambe[AMBE_FRAME_SIZE];
CAmbePacket *packet; CAmbePacket *packet;
CPacketQueue *queue; CPacketQueue *queue;
// anything coming in from codec client ? // anything coming in from codec client ?
if ( m_Socket.Receive(Buffer, Ip, 1) ) if ( m_Socket.Receive(Buffer, Ip, 1) )
{ {
// crack packet // crack packet
if ( IsValidDvFramePacket(Buffer, &uiPid, Ambe) ) if ( IsValidDvFramePacket(Buffer, &uiPid, Ambe) )
{ {
// transcode AMBE here // transcode AMBE here
m_LastActivity.Now(); m_LastActivity.Now();
m_iTotalPackets++; m_iTotalPackets++;
// post packet to VocoderChannel // post packet to VocoderChannel
packet = new CAmbePacket(uiPid, m_uiCodecIn, Ambe); packet = new CAmbePacket(uiPid, m_uiCodecIn, Ambe);
queue = m_VocodecChannel->GetPacketQueueIn(); queue = m_VocodecChannel->GetPacketQueueIn();
queue->push(packet); queue->push(packet);
m_VocodecChannel->ReleasePacketQueueIn(); m_VocodecChannel->ReleasePacketQueueIn();
} }
} }
// anything in our queue ? // anything in our queue ?
queue = m_VocodecChannel->GetPacketQueueOut(); queue = m_VocodecChannel->GetPacketQueueOut();
while ( !queue->empty() ) while ( !queue->empty() )
{ {
// get the packet // get the packet
packet = (CAmbePacket *)queue->front(); packet = (CAmbePacket *)queue->front();
queue->pop(); queue->pop();
// send it to client // send it to client
EncodeDvFramePacket(&Buffer, packet->GetPid(), packet->GetAmbe()); EncodeDvFramePacket(&Buffer, packet->GetPid(), packet->GetAmbe());
m_Socket.Send(Buffer, Ip, m_uiPort); m_Socket.Send(Buffer, Ip, m_uiPort);
// and done // and done
delete packet; delete packet;
} }
m_VocodecChannel->ReleasePacketQueueOut(); m_VocodecChannel->ReleasePacketQueueOut();
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -223,17 +223,17 @@ void CStream::Task(void)
bool CStream::IsValidDvFramePacket(const CBuffer &Buffer, uint8 *pid, uint8 *ambe) bool CStream::IsValidDvFramePacket(const CBuffer &Buffer, uint8 *pid, uint8 *ambe)
{ {
bool valid = false; bool valid = false;
if ( Buffer.size() == 11 ) if ( Buffer.size() == 11 )
{ {
uint8 codec = Buffer.data()[0]; uint8 codec = Buffer.data()[0];
*pid = Buffer.data()[1]; *pid = Buffer.data()[1];
::memcpy(ambe, &(Buffer.data()[2]), 9); ::memcpy(ambe, &(Buffer.data()[2]), 9);
valid = (codec == GetCodecIn()); 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) void CStream::EncodeDvFramePacket(CBuffer *Buffer, uint8 Pid, uint8 *Ambe)
{ {
Buffer->clear(); Buffer->clear();
Buffer->Append((uint8)GetCodecOut()); Buffer->Append((uint8)GetCodecOut());
Buffer->Append((uint8)Pid); Buffer->Append((uint8)Pid);
Buffer->Append(Ambe, 9); Buffer->Append(Ambe, 9);
} }

@ -35,61 +35,61 @@
class CStream class CStream
{ {
public: public:
// constructors // constructors
CStream(); CStream();
CStream(uint16, const CCallsign &, const CIp &, uint8, uint8); CStream(uint16, const CCallsign &, const CIp &, uint8, uint8);
// destructor // destructor
virtual ~CStream(); virtual ~CStream();
// initialization // initialization
bool Init(uint16); bool Init(uint16);
void Close(void); void Close(void);
// get // get
uint16 GetId(void) const { return m_uiId; } uint16 GetId(void) const { return m_uiId; }
uint16 GetPort(void) const { return m_uiPort; } uint16 GetPort(void) const { return m_uiPort; }
uint8 GetCodecIn(void) const { return m_uiCodecIn; } uint8 GetCodecIn(void) const { return m_uiCodecIn; }
uint8 GetCodecOut(void) const { return m_uiCodecOut; } uint8 GetCodecOut(void) const { return m_uiCodecOut; }
// activity timer // activity timer
bool IsActive(void) const { return m_LastActivity.DurationSinceNow() <= STREAM_ACTIVITY_TIMEOUT; } bool IsActive(void) const { return m_LastActivity.DurationSinceNow() <= STREAM_ACTIVITY_TIMEOUT; }
// task // task
static void Thread(CStream *); static void Thread(CStream *);
void Task(void); void Task(void);
protected: protected:
// packet decoding helpers // packet decoding helpers
bool IsValidDvFramePacket(const CBuffer &, uint8 *, uint8 *); bool IsValidDvFramePacket(const CBuffer &, uint8 *, uint8 *);
// packet encodeing helpers // packet encodeing helpers
void EncodeDvFramePacket(CBuffer *, uint8, uint8 *); void EncodeDvFramePacket(CBuffer *, uint8, uint8 *);
protected: protected:
// data // data
uint16 m_uiId; uint16 m_uiId;
CUdpSocket m_Socket; CUdpSocket m_Socket;
uint16 m_uiPort; uint16 m_uiPort;
uint8 m_uiCodecIn; uint8 m_uiCodecIn;
uint8 m_uiCodecOut; uint8 m_uiCodecOut;
CVocodecChannel *m_VocodecChannel; CVocodecChannel *m_VocodecChannel;
// client details // client details
CCallsign m_Callsign; CCallsign m_Callsign;
CIp m_Ip; CIp m_Ip;
// counters // counters
int m_iTotalPackets; int m_iTotalPackets;
int m_iLostPackets; int m_iLostPackets;
// activity timer // activity timer
CTimePoint m_LastActivity; CTimePoint m_LastActivity;
// thread // thread
bool m_bStopThread; bool m_bStopThread;
std::thread *m_pThread; std::thread *m_pThread;
}; };

@ -19,7 +19,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#include "main.h" #include "main.h"
@ -30,7 +30,7 @@
CTimePoint::CTimePoint() 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 double CTimePoint::DurationSinceNow(void) const
{ {
std::chrono::steady_clock::time_point Now = std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point Now = std::chrono::steady_clock::now();
std::chrono::steady_clock::duration time_span = (Now - m_TimePoint); 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; 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) void CTimePoint::TaskSleepFor(uint ms)
{ {
std::chrono::milliseconds timespan(ms); std::chrono::milliseconds timespan(ms);
std::this_thread::sleep_for(timespan); std::this_thread::sleep_for(timespan);
} }

@ -19,7 +19,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#ifndef ctimepoint_h #ifndef ctimepoint_h
@ -32,22 +32,22 @@
class CTimePoint : public std::chrono::steady_clock::time_point class CTimePoint : public std::chrono::steady_clock::time_point
{ {
public: public:
// constructor // constructor
CTimePoint(); CTimePoint();
// destructor // destructor
virtual ~CTimePoint() {} virtual ~CTimePoint() {}
// operation // operation
void Now(void) { m_TimePoint = std::chrono::steady_clock::now(); } void Now(void) { m_TimePoint = std::chrono::steady_clock::now(); }
double DurationSinceNow(void) const; double DurationSinceNow(void) const;
// task // task
static void TaskSleepFor(uint); static void TaskSleepFor(uint);
protected: protected:
// data // data
std::chrono::steady_clock::time_point m_TimePoint; std::chrono::steady_clock::time_point m_TimePoint;
}; };

@ -38,9 +38,9 @@
// constructor // constructor
CUsb3000Interface::CUsb3000Interface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial) 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 CUsb3000Interface::Init(uint8 uiOddCodec)
{ {
bool ok = true; bool ok = true;
// init the odd channel // init the odd channel
m_uiChCodec = uiOddCodec; m_uiChCodec = uiOddCodec;
// base class // base class
ok &= CUsb3xxxInterface::Init(); ok &= CUsb3xxxInterface::Init();
// do not create our channels now // do not create our channels now
// this is delegated to caller (CVocodecs) as our channel // this is delegated to caller (CVocodecs) as our channel
// may be hybrids between 2 interfaces in case of odd n' of channel device) // may be hybrids between 2 interfaces in case of odd n' of channel device)
// done // done
return ok; return ok;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -69,7 +69,7 @@ bool CUsb3000Interface::Init(uint8 uiOddCodec)
uint8 CUsb3000Interface::GetChannelCodec(int iCh) const 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 *CUsb3000Interface::GetChannelWithChannelIn(int iCh)
{ {
CVocodecChannel *Channel = NULL; CVocodecChannel *Channel = NULL;
bool done = false; bool done = false;
for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ ) for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ )
{ {
if ( iCh == 0 ) if ( iCh == 0 )
{ {
if ( (m_Channels[i]->GetChannelIn() == iCh) && !(m_Channels[i]->IsInterfaceOut(this)) ) if ( (m_Channels[i]->GetChannelIn() == iCh) && !(m_Channels[i]->IsInterfaceOut(this)) )
{ {
Channel = m_Channels[i]; Channel = m_Channels[i];
done = true; done = true;
} }
} }
} }
return Channel; return Channel;
} }
CVocodecChannel *CUsb3000Interface::GetChannelWithChannelOut(int iCh) CVocodecChannel *CUsb3000Interface::GetChannelWithChannelOut(int iCh)
{ {
CVocodecChannel *Channel = NULL; CVocodecChannel *Channel = NULL;
bool done = false; bool done = false;
for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ ) for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ )
{ {
if ( (m_Channels[i]->GetChannelOut() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) ) if ( (m_Channels[i]->GetChannelOut() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) )
{ {
Channel = m_Channels[i]; Channel = m_Channels[i];
done = true; done = true;
} }
} }
return Channel; return Channel;
} }
@ -114,34 +114,34 @@ CVocodecChannel *CUsb3000Interface::GetChannelWithChannelOut(int iCh)
bool CUsb3000Interface::IsValidChannelPacket(const CBuffer &buffer, int *ch, CAmbePacket *packet) bool CUsb3000Interface::IsValidChannelPacket(const CBuffer &buffer, int *ch, CAmbePacket *packet)
{ {
bool valid = false; bool valid = false;
uint8 tag[] = { PKT_HEADER,0x00,0x0B,PKT_CHANNEL }; uint8 tag[] = { PKT_HEADER,0x00,0x0B,PKT_CHANNEL };
if ( (buffer.size() == 15) && (buffer.Compare(tag, sizeof(tag)) == 0)) if ( (buffer.size() == 15) && (buffer.Compare(tag, sizeof(tag)) == 0))
{ {
*ch = 0; *ch = 0;
packet->SetCodec(m_uiChCodec); packet->SetCodec(m_uiChCodec);
packet->SetAmbe(&(buffer.data()[6])); packet->SetAmbe(&(buffer.data()[6]));
valid = (*ch < GetNbChannels()); valid = (*ch < GetNbChannels());
//std::cout << "CHAN " << *ch << " " << buffer.size() << " " << (int)buffer[6] << std::endl; //std::cout << "CHAN " << *ch << " " << buffer.size() << " " << (int)buffer[6] << std::endl;
} }
return valid; return valid;
} }
bool CUsb3000Interface::IsValidSpeechPacket(const CBuffer &buffer, int *ch, CVoicePacket *packet) bool CUsb3000Interface::IsValidSpeechPacket(const CBuffer &buffer, int *ch, CVoicePacket *packet)
{ {
bool valid = false; bool valid = false;
if ( (buffer.size() > 6) && if ( (buffer.size() > 6) &&
(buffer.data()[0] == PKT_HEADER) && (buffer.data()[3] == PKT_SPEECH) && (buffer.data()[0] == PKT_HEADER) && (buffer.data()[3] == PKT_SPEECH) &&
(buffer.data()[4] == PKT_SPEECHD) ) (buffer.data()[4] == PKT_SPEECHD) )
{ {
*ch = 0; *ch = 0;
packet->SetVoice(&(buffer.data()[6]), buffer.data()[5] * 2); packet->SetVoice(&(buffer.data()[6]), buffer.data()[5] * 2);
valid = (*ch < GetNbChannels()); valid = (*ch < GetNbChannels());
//std::cout << "SPCH " << *ch << " " << buffer.size() << std::endl; //std::cout << "SPCH " << *ch << " " << buffer.size() << std::endl;
} }
return valid; return valid;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -149,28 +149,28 @@ bool CUsb3000Interface::IsValidSpeechPacket(const CBuffer &buffer, int *ch, CVoi
void CUsb3000Interface::EncodeChannelPacket(CBuffer *buffer, int ch, CAmbePacket *packet) void CUsb3000Interface::EncodeChannelPacket(CBuffer *buffer, int ch, CAmbePacket *packet)
{ {
uint size = (uint16)packet->GetAmbeSize() + 2; uint size = (uint16)packet->GetAmbeSize() + 2;
buffer->clear(); buffer->clear();
buffer->Append((uint8)PKT_HEADER); buffer->Append((uint8)PKT_HEADER);
buffer->Append((uint8)HIBYTE(size)); buffer->Append((uint8)HIBYTE(size));
buffer->Append((uint8)LOBYTE(size)); buffer->Append((uint8)LOBYTE(size));
buffer->Append((uint8)PKT_CHANNEL); buffer->Append((uint8)PKT_CHANNEL);
buffer->Append((uint8)(PKT_CHAND)); buffer->Append((uint8)(PKT_CHAND));
buffer->Append((uint8)(packet->GetAmbeSize()*8)); buffer->Append((uint8)(packet->GetAmbeSize()*8));
buffer->Append(packet->GetAmbe(), packet->GetAmbeSize()); buffer->Append(packet->GetAmbe(), packet->GetAmbeSize());
} }
void CUsb3000Interface::EncodeSpeechPacket(CBuffer *buffer, int ch, CVoicePacket *packet) void CUsb3000Interface::EncodeSpeechPacket(CBuffer *buffer, int ch, CVoicePacket *packet)
{ {
uint16 size = (uint16)packet->GetVoiceSize() + 2; uint16 size = (uint16)packet->GetVoiceSize() + 2;
buffer->clear(); buffer->clear();
buffer->Append((uint8)PKT_HEADER); buffer->Append((uint8)PKT_HEADER);
buffer->Append((uint8)HIBYTE(size)); buffer->Append((uint8)HIBYTE(size));
buffer->Append((uint8)LOBYTE(size)); buffer->Append((uint8)LOBYTE(size));
buffer->Append((uint8)PKT_SPEECH); buffer->Append((uint8)PKT_SPEECH);
buffer->Append((uint8)PKT_SPEECHD); buffer->Append((uint8)PKT_SPEECHD);
buffer->Append((uint8)(packet->GetVoiceSize()/2)); buffer->Append((uint8)(packet->GetVoiceSize()/2));
buffer->Append(packet->GetVoice(), packet->GetVoiceSize()); buffer->Append(packet->GetVoice(), packet->GetVoiceSize());
} }
@ -179,119 +179,119 @@ void CUsb3000Interface::EncodeSpeechPacket(CBuffer *buffer, int ch, CVoicePacket
bool CUsb3000Interface::OpenDevice(void) bool CUsb3000Interface::OpenDevice(void)
{ {
FT_STATUS ftStatus; FT_STATUS ftStatus;
int baudrate = 460800; int baudrate = 460800;
//sets serial VID/PID for a Standard Device NOTE: This is for legacy purposes only. This can be ommitted. //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); ftStatus = FT_SetVIDPID(m_uiVid, m_uiPid);
if (ftStatus != FT_OK) {FTDI_Error((char *)"FT_SetVIDPID", ftStatus ); return false; } 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); 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; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_OpenEx", ftStatus ); return false; }
CTimePoint::TaskSleepFor(50); CTimePoint::TaskSleepFor(50);
FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX ); FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX );
CTimePoint::TaskSleepFor(50); CTimePoint::TaskSleepFor(50);
ftStatus = FT_SetDataCharacteristics(m_FtdiHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE); 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; } if ( ftStatus != FT_OK ) { FTDI_Error((char *)"FT_SetDataCharacteristics", ftStatus ); return false; }
ftStatus = FT_SetFlowControl(m_FtdiHandle, FT_FLOW_RTS_CTS, 0x11, 0x13); ftStatus = FT_SetFlowControl(m_FtdiHandle, FT_FLOW_RTS_CTS, 0x11, 0x13);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetFlowControl", ftStatus ); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetFlowControl", ftStatus ); return false; }
ftStatus = FT_SetRts (m_FtdiHandle); ftStatus = FT_SetRts (m_FtdiHandle);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetRts", ftStatus ); return false; } 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 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 //for other devices noting is connected to DTR so it is a dont care
ftStatus = FT_ClrDtr(m_FtdiHandle); ftStatus = FT_ClrDtr(m_FtdiHandle);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_ClrDtr", ftStatus); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_ClrDtr", ftStatus); return false; }
ftStatus = FT_SetBaudRate(m_FtdiHandle, baudrate ); ftStatus = FT_SetBaudRate(m_FtdiHandle, baudrate );
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetBaudRate", ftStatus ); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetBaudRate", ftStatus ); return false; }
ftStatus = FT_SetLatencyTimer(m_FtdiHandle, 4); ftStatus = FT_SetLatencyTimer(m_FtdiHandle, 4);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetLatencyTimer", ftStatus ); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetLatencyTimer", ftStatus ); return false; }
ftStatus = FT_SetUSBParameters(m_FtdiHandle, USB3XXX_MAXPACKETSIZE, 0); ftStatus = FT_SetUSBParameters(m_FtdiHandle, USB3XXX_MAXPACKETSIZE, 0);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetUSBParameters", ftStatus ); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetUSBParameters", ftStatus ); return false; }
ftStatus = FT_SetTimeouts(m_FtdiHandle, 200, 200 ); ftStatus = FT_SetTimeouts(m_FtdiHandle, 200, 200 );
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetTimeouts", ftStatus ); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetTimeouts", ftStatus ); return false; }
// done // done
return true; return true;
} }
bool CUsb3000Interface::ResetDevice(void) bool CUsb3000Interface::ResetDevice(void)
{ {
bool ok = false; bool ok = false;
int len; int len;
char rxpacket[100]; char rxpacket[100];
char zeropacket[10] = char zeropacket[10] =
{ {
0,0,0,0,0,0,0,0,0,0 0,0,0,0,0,0,0,0,0,0
}; };
char txpacket[7] = char txpacket[7] =
{ {
PKT_HEADER, PKT_HEADER,
0, 0,
3, 3,
0, 0,
PKT_RESET, PKT_RESET,
PKT_PARITYBYTE, PKT_PARITYBYTE,
3 ^ 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. //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 //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 //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 //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. //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++ ) for ( int i = 0; i < 35 ; i++ )
{ {
FTDI_write_packet(m_FtdiHandle, zeropacket, sizeof(zeropacket)); FTDI_write_packet(m_FtdiHandle, zeropacket, sizeof(zeropacket));
} }
// write soft-reset packet // write soft-reset packet
if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) )
{ {
// read reply // read reply
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ); len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) );
ok = ((len == 5) && (rxpacket[4] == PKT_READY)); ok = ((len == 5) && (rxpacket[4] == PKT_READY));
if ( !ok ) if ( !ok )
{ {
std::cout << "USB-3000 soft reset failed" << std::endl; std::cout << "USB-3000 soft reset failed" << std::endl;
} }
} }
// done // done
return ok; return ok;
} }
bool CUsb3000Interface::ConfigureDevice(void) bool CUsb3000Interface::ConfigureDevice(void)
{ {
bool ok = true; bool ok = true;
uint8 pkt_ratep_ambeplus[] = { 0x01,0x30,0x07,0x63,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x48 }; 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 }; uint8 pkt_ratep_ambe2plus[] = { 0x04,0x31,0x07,0x54,0x24,0x00,0x00,0x00,0x00,0x00,0x6F,0x48 };
// configure the channel for desired codec // configure the channel for desired codec
switch ( m_uiChCodec ) switch ( m_uiChCodec )
{ {
case CODEC_AMBEPLUS: case CODEC_AMBEPLUS:
ok &= ConfigureChannel(PKT_CHANNEL0, pkt_ratep_ambeplus, 0, 0); ok &= ConfigureChannel(PKT_CHANNEL0, pkt_ratep_ambeplus, 0, 0);
break; break;
case CODEC_AMBE2PLUS: case CODEC_AMBE2PLUS:
ok &= ConfigureChannel(PKT_CHANNEL0, pkt_ratep_ambe2plus, 0, 0); ok &= ConfigureChannel(PKT_CHANNEL0, pkt_ratep_ambe2plus, 0, 0);
break; break;
case CODEC_NONE: case CODEC_NONE:
default: default:
break; break;
} }
// done // done
return ok; return ok;
} }

@ -41,39 +41,39 @@
class CUsb3000Interface : public CUsb3xxxInterface class CUsb3000Interface : public CUsb3xxxInterface
{ {
public: public:
// constructors // constructors
CUsb3000Interface(uint32, uint32, const char *, const char *); CUsb3000Interface(uint32, uint32, const char *, const char *);
// destructor // destructor
virtual ~CUsb3000Interface() {} virtual ~CUsb3000Interface() {}
// initialization // initialization
bool Init(uint8); bool Init(uint8);
// manage channels // manage channels
int GetNbChannels(void) const { return USB3000_NB_CH; } int GetNbChannels(void) const { return USB3000_NB_CH; }
uint8 GetChannelCodec(int) const; uint8 GetChannelCodec(int) const;
// manage vocodec channels // manage vocodec channels
CVocodecChannel *GetChannelWithChannelIn(int); CVocodecChannel *GetChannelWithChannelIn(int);
CVocodecChannel *GetChannelWithChannelOut(int); CVocodecChannel *GetChannelWithChannelOut(int);
protected: protected:
// decoder helper // decoder helper
bool IsValidChannelPacket(const CBuffer &, int *, CAmbePacket *); bool IsValidChannelPacket(const CBuffer &, int *, CAmbePacket *);
bool IsValidSpeechPacket(const CBuffer &, int *, CVoicePacket *); bool IsValidSpeechPacket(const CBuffer &, int *, CVoicePacket *);
// encoder helpers // encoder helpers
void EncodeChannelPacket(CBuffer *, int, CAmbePacket *); void EncodeChannelPacket(CBuffer *, int, CAmbePacket *);
void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *); void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *);
// low level // low level
bool OpenDevice(void); bool OpenDevice(void);
bool ResetDevice(void); bool ResetDevice(void);
bool ConfigureDevice(void); bool ConfigureDevice(void);
// data // data
uint8 m_uiChCodec; uint8 m_uiChCodec;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -35,7 +35,7 @@
// constructor // constructor
CUsb3003DF2ETInterface::CUsb3003DF2ETInterface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial) 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) bool CUsb3003DF2ETInterface::OpenDevice(void)
{ {
FT_STATUS ftStatus; FT_STATUS ftStatus;
int baudrate = 921600; int baudrate = 921600;
//sets serial VID/PID for a Standard Device NOTE: This is for legacy purposes only. This can be ommitted. //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); ftStatus = FT_SetVIDPID(m_uiVid, m_uiPid);
if (ftStatus != FT_OK) {FTDI_Error((char *)"FT_SetVIDPID", ftStatus ); return false; } 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); 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; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_OpenEx", ftStatus ); return false; }
CTimePoint::TaskSleepFor(50); CTimePoint::TaskSleepFor(50);
FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX ); FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX );
CTimePoint::TaskSleepFor(50); CTimePoint::TaskSleepFor(50);
ftStatus = FT_SetDataCharacteristics(m_FtdiHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE); 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; } if ( ftStatus != FT_OK ) { FTDI_Error((char *)"FT_SetDataCharacteristics", ftStatus ); return false; }
ftStatus = FT_SetFlowControl(m_FtdiHandle, FT_FLOW_RTS_CTS, 0x11, 0x13); ftStatus = FT_SetFlowControl(m_FtdiHandle, FT_FLOW_RTS_CTS, 0x11, 0x13);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetFlowControl", ftStatus ); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetFlowControl", ftStatus ); return false; }
ftStatus = FT_SetRts (m_FtdiHandle); ftStatus = FT_SetRts (m_FtdiHandle);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetRts", ftStatus ); return false; } 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. // for DF2ET-3003 interface pull DTR low to take AMBE3003 out of reset.
ftStatus = FT_SetDtr( m_FtdiHandle ); ftStatus = FT_SetDtr( m_FtdiHandle );
CTimePoint::TaskSleepFor(50); CTimePoint::TaskSleepFor(50);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetDtr", ftStatus); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetDtr", ftStatus); return false; }
ftStatus = FT_SetBaudRate(m_FtdiHandle, baudrate ); ftStatus = FT_SetBaudRate(m_FtdiHandle, baudrate );
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetBaudRate", ftStatus ); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetBaudRate", ftStatus ); return false; }
ftStatus = FT_SetLatencyTimer(m_FtdiHandle, 4); ftStatus = FT_SetLatencyTimer(m_FtdiHandle, 4);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetLatencyTimer", ftStatus ); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetLatencyTimer", ftStatus ); return false; }
ftStatus = FT_SetUSBParameters(m_FtdiHandle, USB3XXX_MAXPACKETSIZE, 0); ftStatus = FT_SetUSBParameters(m_FtdiHandle, USB3XXX_MAXPACKETSIZE, 0);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetUSBParameters", ftStatus ); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetUSBParameters", ftStatus ); return false; }
ftStatus = FT_SetTimeouts(m_FtdiHandle, 200, 200 ); ftStatus = FT_SetTimeouts(m_FtdiHandle, 200, 200 );
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetTimeouts", ftStatus ); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetTimeouts", ftStatus ); return false; }
// done // done
return true; return true;
} }
bool CUsb3003DF2ETInterface::ResetDevice(void) bool CUsb3003DF2ETInterface::ResetDevice(void)
{ {
bool ok = false; bool ok = false;
FT_STATUS ftStatus; FT_STATUS ftStatus;
int len, i; int len, i;
char rxpacket[100]; char rxpacket[100];
std::cout << "Trying DF2ET-3003 soft reset" << std::endl; std::cout << "Trying DF2ET-3003 soft reset" << std::endl;
DWORD n, b; DWORD n, b;
char txpacket[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 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 reset_packet[7] = { PKT_HEADER, 0, 3, 0, PKT_RESET, PKT_PARITYBYTE, 3 ^ PKT_RESET ^ PKT_PARITYBYTE };
char *p; char *p;
for (i = 0; i < 35; i++) for (i = 0; i < 35; i++)
{ {
p = &txpacket[0]; p = &txpacket[0];
n = 10; n = 10;
do do
{ {
ftStatus = FT_Write( m_FtdiHandle, p, n, &b); ftStatus = FT_Write( m_FtdiHandle, p, n, &b);
if (FT_OK != ftStatus) if (FT_OK != ftStatus)
{ {
return 1; return 1;
} }
n -= b; n -= b;
p += b; p += b;
} while (n > 0); }
} while (n > 0);
}
p = &reset_packet[0];
n = 7; p = &reset_packet[0];
do n = 7;
{ do
ftStatus = FT_Write( m_FtdiHandle, p, n, &b); {
if (FT_OK != ftStatus) ftStatus = FT_Write( m_FtdiHandle, p, n, &b);
{ if (FT_OK != ftStatus)
return 1; {
} return 1;
n -= b; }
p += b; n -= b;
} while (n > 0); p += b;
}
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ); while (n > 0);
ok = ((len == 7) && (rxpacket[4] == PKT_READY));
if ( ok ) len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) );
{ ok = ((len == 7) && (rxpacket[4] == PKT_READY));
std::cout << "DF2ET-3003 soft reset succeeded" << std::endl; if ( ok )
} {
else std::cout << "DF2ET-3003 soft reset succeeded" << std::endl;
{ }
std::cout << "DF2ET-3003 soft reset failed" << std::endl; else
{
std::cout << "Trying DF2ET-3003 hard reset" << std::endl; std::cout << "DF2ET-3003 soft reset failed" << std::endl;
ftStatus = FT_ClrDtr( m_FtdiHandle ); std::cout << "Trying DF2ET-3003 hard reset" << std::endl;
CTimePoint::TaskSleepFor(10);
ftStatus = FT_SetDtr( m_FtdiHandle ); ftStatus = FT_ClrDtr( m_FtdiHandle );
CTimePoint::TaskSleepFor(10); CTimePoint::TaskSleepFor(10);
ftStatus = FT_SetDtr( m_FtdiHandle );
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ); CTimePoint::TaskSleepFor(10);
ok = ((len == 7) && (rxpacket[4] == PKT_READY));
if ( ok ) len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) );
{ ok = ((len == 7) && (rxpacket[4] == PKT_READY));
std::cout << "DF2ET-3003 hard reset succeeded" << std::endl; if ( ok )
} {
else std::cout << "DF2ET-3003 hard reset succeeded" << std::endl;
{ }
std::cout << "DF2ET-3003 hard reset failed" << std::endl; else
} {
} std::cout << "DF2ET-3003 hard reset failed" << std::endl;
return ok; }
}
return ok;
} }

@ -41,16 +41,16 @@
class CUsb3003DF2ETInterface : public CUsb3003Interface class CUsb3003DF2ETInterface : public CUsb3003Interface
{ {
public: public:
// constructors // constructors
CUsb3003DF2ETInterface(uint32, uint32, const char *, const char *); CUsb3003DF2ETInterface(uint32, uint32, const char *, const char *);
// destructor // destructor
virtual ~CUsb3003DF2ETInterface() {} virtual ~CUsb3003DF2ETInterface() {}
protected: protected:
// low level // low level
bool OpenDevice(void); bool OpenDevice(void);
bool ResetDevice(void); bool ResetDevice(void);
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -32,7 +32,7 @@
// constructor // constructor
CUsb3003HRInterface::CUsb3003HRInterface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial) 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 CUsb3003HRInterface::ResetDevice(void)
{ {
bool ok = false; bool ok = false;
int len; int len;
char rxpacket[100]; char rxpacket[100];
//if the device is a USB-3003, it supports reset via UART break signal //if the device is a USB-3003, it supports reset via UART break signal
//printf("reset via uart break...\n"); //printf("reset via uart break...\n");
FT_SetBreakOn( m_FtdiHandle ); FT_SetBreakOn( m_FtdiHandle );
CTimePoint::TaskSleepFor(10); CTimePoint::TaskSleepFor(10);
FT_SetBreakOff( m_FtdiHandle ); FT_SetBreakOff( m_FtdiHandle );
//CTimePoint::TaskSleepFor(10); //CTimePoint::TaskSleepFor(10);
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ); len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) );
ok = ((len == 7) && (rxpacket[4] == PKT_READY)); ok = ((len == 7) && (rxpacket[4] == PKT_READY));
if ( !ok ) if ( !ok )
{ {
std::cout << "USB-3003 hard reset failed" << std::endl; std::cout << "USB-3003 hard reset failed" << std::endl;
} }
// done // done
return ok; return ok;
} }

@ -40,15 +40,15 @@
class CUsb3003HRInterface : public CUsb3003Interface class CUsb3003HRInterface : public CUsb3003Interface
{ {
public: public:
// constructors // constructors
CUsb3003HRInterface(uint32, uint32, const char *, const char *); CUsb3003HRInterface(uint32, uint32, const char *, const char *);
// destructor // destructor
virtual ~CUsb3003HRInterface() {} virtual ~CUsb3003HRInterface() {}
protected: protected:
// low level // low level
bool ResetDevice(void); bool ResetDevice(void);
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -40,11 +40,11 @@
// constructor // constructor
CUsb3003Interface::CUsb3003Interface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial) 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[0]= CODEC_AMBEPLUS;
m_uiChCodecs[1]= CODEC_AMBE2PLUS; m_uiChCodecs[1]= CODEC_AMBE2PLUS;
m_uiChCodecs[2]= CODEC_NONE; m_uiChCodecs[2]= CODEC_NONE;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -52,20 +52,20 @@ CUsb3003Interface::CUsb3003Interface(uint32 uiVid, uint32 uiPid, const char *szD
bool CUsb3003Interface::Init(uint8 uiOddCodec) bool CUsb3003Interface::Init(uint8 uiOddCodec)
{ {
bool ok = true; bool ok = true;
// init the odd channel // init the odd channel
m_uiChCodecs[2] = uiOddCodec; m_uiChCodecs[2] = uiOddCodec;
// base class // base class
ok &= CUsb3xxxInterface::Init(); ok &= CUsb3xxxInterface::Init();
// do not create our channels now // do not create our channels now
// this is delegated to caller (CVocodecs) as our channel // this is delegated to caller (CVocodecs) as our channel
// may be hybrids between 2 interfaces in case of odd n' of channel device) // may be hybrids between 2 interfaces in case of odd n' of channel device)
// done // done
return ok; return ok;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -73,12 +73,12 @@ bool CUsb3003Interface::Init(uint8 uiOddCodec)
uint8 CUsb3003Interface::GetChannelCodec(int iCh) const uint8 CUsb3003Interface::GetChannelCodec(int iCh) const
{ {
uint8 uiCodec = CODEC_NONE; uint8 uiCodec = CODEC_NONE;
if ( (iCh >= 0) && (iCh <= USB3003_NB_CH) ) if ( (iCh >= 0) && (iCh <= USB3003_NB_CH) )
{ {
uiCodec = m_uiChCodecs[iCh]; uiCodec = m_uiChCodecs[iCh];
} }
return uiCodec; return uiCodec;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -86,43 +86,43 @@ uint8 CUsb3003Interface::GetChannelCodec(int iCh) const
CVocodecChannel *CUsb3003Interface::GetChannelWithChannelIn(int iCh) CVocodecChannel *CUsb3003Interface::GetChannelWithChannelIn(int iCh)
{ {
CVocodecChannel *Channel = NULL; CVocodecChannel *Channel = NULL;
bool done = false; bool done = false;
for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ ) for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ )
{ {
if ( iCh == 2 ) if ( iCh == 2 )
{ {
if ( (m_Channels[i]->GetChannelIn() == iCh) && !(m_Channels[i]->IsInterfaceOut(this)) ) if ( (m_Channels[i]->GetChannelIn() == iCh) && !(m_Channels[i]->IsInterfaceOut(this)) )
{ {
Channel = m_Channels[i]; Channel = m_Channels[i];
done = true; done = true;
} }
} }
else else
{ {
if ( (m_Channels[i]->GetChannelIn() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) ) if ( (m_Channels[i]->GetChannelIn() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) )
{ {
Channel = m_Channels[i]; Channel = m_Channels[i];
done = true; done = true;
} }
} }
} }
return Channel; return Channel;
} }
CVocodecChannel *CUsb3003Interface::GetChannelWithChannelOut(int iCh) CVocodecChannel *CUsb3003Interface::GetChannelWithChannelOut(int iCh)
{ {
CVocodecChannel *Channel = NULL; CVocodecChannel *Channel = NULL;
bool done = false; bool done = false;
for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ ) for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ )
{ {
if ( (m_Channels[i]->GetChannelOut() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) ) if ( (m_Channels[i]->GetChannelOut() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) )
{ {
Channel = m_Channels[i]; Channel = m_Channels[i];
done = true; done = true;
} }
} }
return Channel; return Channel;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -130,39 +130,39 @@ CVocodecChannel *CUsb3003Interface::GetChannelWithChannelOut(int iCh)
bool CUsb3003Interface::IsValidChannelPacket(const CBuffer &buffer, int *ch, CAmbePacket *packet) bool CUsb3003Interface::IsValidChannelPacket(const CBuffer &buffer, int *ch, CAmbePacket *packet)
{ {
bool valid = false; bool valid = false;
uint8 tag[] = { PKT_HEADER,0x00,0x0C,PKT_CHANNEL }; uint8 tag[] = { PKT_HEADER,0x00,0x0C,PKT_CHANNEL };
if ( (buffer.size() == 16) && (buffer.Compare(tag, sizeof(tag)) == 0)) if ( (buffer.size() == 16) && (buffer.Compare(tag, sizeof(tag)) == 0))
{ {
*ch = buffer.data()[4] - PKT_CHANNEL0; *ch = buffer.data()[4] - PKT_CHANNEL0;
if ( *ch == 0 ) if ( *ch == 0 )
packet->SetCodec(CODEC_AMBEPLUS); packet->SetCodec(CODEC_AMBEPLUS);
else if ( *ch == 1 ) else if ( *ch == 1 )
packet->SetCodec(CODEC_AMBE2PLUS); packet->SetCodec(CODEC_AMBE2PLUS);
else else
packet->SetCodec(CODEC_NONE); packet->SetCodec(CODEC_NONE);
packet->SetAmbe(&(buffer.data()[7])); packet->SetAmbe(&(buffer.data()[7]));
valid = (*ch < GetNbChannels()); valid = (*ch < GetNbChannels());
//std::cout << "CHAN " << *ch << " " << buffer.size() << " " << (int)buffer[6] << std::endl; //std::cout << "CHAN " << *ch << " " << buffer.size() << " " << (int)buffer[6] << std::endl;
} }
return valid; return valid;
} }
bool CUsb3003Interface::IsValidSpeechPacket(const CBuffer &buffer, int *ch, CVoicePacket *packet) bool CUsb3003Interface::IsValidSpeechPacket(const CBuffer &buffer, int *ch, CVoicePacket *packet)
{ {
bool valid = false; bool valid = false;
if ( (buffer.size() > 6) && if ( (buffer.size() > 6) &&
(buffer.data()[0] == PKT_HEADER) && (buffer.data()[3] == PKT_SPEECH) && (buffer.data()[0] == PKT_HEADER) && (buffer.data()[3] == PKT_SPEECH) &&
(buffer.data()[5] == PKT_SPEECHD) ) (buffer.data()[5] == PKT_SPEECHD) )
{ {
*ch = buffer.data()[4] - PKT_CHANNEL0; *ch = buffer.data()[4] - PKT_CHANNEL0;
packet->SetVoice(&(buffer.data()[7]), buffer.data()[6] * 2); packet->SetVoice(&(buffer.data()[7]), buffer.data()[6] * 2);
valid = (*ch < GetNbChannels()); valid = (*ch < GetNbChannels());
//std::cout << "SPCH " << *ch << " " << buffer.size() << std::endl; //std::cout << "SPCH " << *ch << " " << buffer.size() << std::endl;
} }
return valid; return valid;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -170,30 +170,30 @@ bool CUsb3003Interface::IsValidSpeechPacket(const CBuffer &buffer, int *ch, CVoi
void CUsb3003Interface::EncodeChannelPacket(CBuffer *buffer, int ch, CAmbePacket *packet) void CUsb3003Interface::EncodeChannelPacket(CBuffer *buffer, int ch, CAmbePacket *packet)
{ {
uint size = (uint16)packet->GetAmbeSize() + 3; uint size = (uint16)packet->GetAmbeSize() + 3;
buffer->clear(); buffer->clear();
buffer->Append((uint8)PKT_HEADER); buffer->Append((uint8)PKT_HEADER);
buffer->Append((uint8)HIBYTE(size)); buffer->Append((uint8)HIBYTE(size));
buffer->Append((uint8)LOBYTE(size)); buffer->Append((uint8)LOBYTE(size));
buffer->Append((uint8)PKT_CHANNEL); buffer->Append((uint8)PKT_CHANNEL);
buffer->Append((uint8)(PKT_CHANNEL0+ch)); buffer->Append((uint8)(PKT_CHANNEL0+ch));
buffer->Append((uint8)(PKT_CHAND)); buffer->Append((uint8)(PKT_CHAND));
buffer->Append((uint8)(packet->GetAmbeSize()*8)); buffer->Append((uint8)(packet->GetAmbeSize()*8));
buffer->Append(packet->GetAmbe(), packet->GetAmbeSize()); buffer->Append(packet->GetAmbe(), packet->GetAmbeSize());
} }
void CUsb3003Interface::EncodeSpeechPacket(CBuffer *buffer, int ch, CVoicePacket *packet) void CUsb3003Interface::EncodeSpeechPacket(CBuffer *buffer, int ch, CVoicePacket *packet)
{ {
uint16 size = (uint16)packet->GetVoiceSize() + 3; uint16 size = (uint16)packet->GetVoiceSize() + 3;
buffer->clear(); buffer->clear();
buffer->Append((uint8)PKT_HEADER); buffer->Append((uint8)PKT_HEADER);
buffer->Append((uint8)HIBYTE(size)); buffer->Append((uint8)HIBYTE(size));
buffer->Append((uint8)LOBYTE(size)); buffer->Append((uint8)LOBYTE(size));
buffer->Append((uint8)PKT_SPEECH); buffer->Append((uint8)PKT_SPEECH);
buffer->Append((uint8)(PKT_CHANNEL0+ch)); buffer->Append((uint8)(PKT_CHANNEL0+ch));
buffer->Append((uint8)PKT_SPEECHD); buffer->Append((uint8)PKT_SPEECHD);
buffer->Append((uint8)(packet->GetVoiceSize()/2)); buffer->Append((uint8)(packet->GetVoiceSize()/2));
buffer->Append(packet->GetVoice(), packet->GetVoiceSize()); buffer->Append(packet->GetVoice(), packet->GetVoiceSize());
} }
@ -202,122 +202,122 @@ void CUsb3003Interface::EncodeSpeechPacket(CBuffer *buffer, int ch, CVoicePacket
bool CUsb3003Interface::OpenDevice(void) bool CUsb3003Interface::OpenDevice(void)
{ {
FT_STATUS ftStatus; FT_STATUS ftStatus;
int baudrate = 921600; int baudrate = 921600;
//sets serial VID/PID for a Standard Device NOTE: This is for legacy purposes only. This can be ommitted. //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); ftStatus = FT_SetVIDPID(m_uiVid, m_uiPid);
if (ftStatus != FT_OK) {FTDI_Error((char *)"FT_SetVIDPID", ftStatus ); return false; } 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); 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; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_OpenEx", ftStatus ); return false; }
CTimePoint::TaskSleepFor(50); CTimePoint::TaskSleepFor(50);
FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX ); FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX );
CTimePoint::TaskSleepFor(50); CTimePoint::TaskSleepFor(50);
ftStatus = FT_SetDataCharacteristics(m_FtdiHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE); 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; } if ( ftStatus != FT_OK ) { FTDI_Error((char *)"FT_SetDataCharacteristics", ftStatus ); return false; }
ftStatus = FT_SetFlowControl(m_FtdiHandle, FT_FLOW_RTS_CTS, 0x11, 0x13); ftStatus = FT_SetFlowControl(m_FtdiHandle, FT_FLOW_RTS_CTS, 0x11, 0x13);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetFlowControl", ftStatus ); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetFlowControl", ftStatus ); return false; }
ftStatus = FT_SetRts (m_FtdiHandle); ftStatus = FT_SetRts (m_FtdiHandle);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetRts", ftStatus ); return false; } 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 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 //for other devices noting is connected to DTR so it is a dont care
ftStatus = FT_ClrDtr(m_FtdiHandle); ftStatus = FT_ClrDtr(m_FtdiHandle);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_ClrDtr", ftStatus); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_ClrDtr", ftStatus); return false; }
ftStatus = FT_SetBaudRate(m_FtdiHandle, baudrate ); ftStatus = FT_SetBaudRate(m_FtdiHandle, baudrate );
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetBaudRate", ftStatus ); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetBaudRate", ftStatus ); return false; }
ftStatus = FT_SetLatencyTimer(m_FtdiHandle, 4); ftStatus = FT_SetLatencyTimer(m_FtdiHandle, 4);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetLatencyTimer", ftStatus ); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetLatencyTimer", ftStatus ); return false; }
ftStatus = FT_SetUSBParameters(m_FtdiHandle, USB3XXX_MAXPACKETSIZE, 0); ftStatus = FT_SetUSBParameters(m_FtdiHandle, USB3XXX_MAXPACKETSIZE, 0);
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetUSBParameters", ftStatus ); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetUSBParameters", ftStatus ); return false; }
ftStatus = FT_SetTimeouts(m_FtdiHandle, 200, 200 ); ftStatus = FT_SetTimeouts(m_FtdiHandle, 200, 200 );
if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetTimeouts", ftStatus ); return false; } if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetTimeouts", ftStatus ); return false; }
// done // done
return true; return true;
} }
bool CUsb3003Interface::ResetDevice(void) bool CUsb3003Interface::ResetDevice(void)
{ {
bool ok = false; bool ok = false;
int len; int len;
char rxpacket[100]; char rxpacket[100];
char zeropacket[10] = char zeropacket[10] =
{ {
0,0,0,0,0,0,0,0,0,0 0,0,0,0,0,0,0,0,0,0
}; };
char txpacket[7] = char txpacket[7] =
{ {
PKT_HEADER, PKT_HEADER,
0, 0,
3, 3,
0, 0,
PKT_RESET, PKT_RESET,
PKT_PARITYBYTE, PKT_PARITYBYTE,
3 ^ 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. //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 //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 //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 //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. //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++ ) for ( int i = 0; i < 35 ; i++ )
{ {
FTDI_write_packet(m_FtdiHandle, zeropacket, sizeof(zeropacket)); FTDI_write_packet(m_FtdiHandle, zeropacket, sizeof(zeropacket));
} }
// write soft-reset packet // write soft-reset packet
if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) )
{ {
// read reply // read reply
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ); len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) );
ok = ((len == 7) && (rxpacket[4] == PKT_READY)); ok = ((len == 7) && (rxpacket[4] == PKT_READY));
if ( !ok ) if ( !ok )
{ {
std::cout << "USB-3003 soft reset failed" << std::endl; std::cout << "USB-3003 soft reset failed" << std::endl;
} }
} }
// done // done
return ok; return ok;
} }
bool CUsb3003Interface::ConfigureDevice(void) bool CUsb3003Interface::ConfigureDevice(void)
{ {
bool ok = true; bool ok = true;
uint8 pkt_ratep_ambeplus[] = { 0x01,0x30,0x07,0x63,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x48 }; 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 }; uint8 pkt_ratep_ambe2plus[] = { 0x04,0x31,0x07,0x54,0x24,0x00,0x00,0x00,0x00,0x00,0x6F,0x48 };
// configure each channels for desired codec // configure each channels for desired codec
for ( int i = 0; i < USB3003_NB_CH; i++ ) for ( int i = 0; i < USB3003_NB_CH; i++ )
{ {
switch ( m_uiChCodecs[i] ) switch ( m_uiChCodecs[i] )
{ {
case CODEC_AMBEPLUS: case CODEC_AMBEPLUS:
ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambeplus, 0, 0); ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambeplus, 0, 0);
break; break;
case CODEC_AMBE2PLUS: case CODEC_AMBE2PLUS:
ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambe2plus, 0, 0); ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambe2plus, 0, 0);
break; break;
case CODEC_NONE: case CODEC_NONE:
default: default:
break; break;
} }
} }
// done // done
return ok; return ok;
} }

@ -40,40 +40,40 @@
class CUsb3003Interface : public CUsb3xxxInterface class CUsb3003Interface : public CUsb3xxxInterface
{ {
public: public:
// constructors // constructors
CUsb3003Interface(uint32, uint32, const char *, const char *); CUsb3003Interface(uint32, uint32, const char *, const char *);
// destructor // destructor
virtual ~CUsb3003Interface() {} virtual ~CUsb3003Interface() {}
// initialization // initialization
bool Init(uint8); bool Init(uint8);
// manage channels // manage channels
int GetNbChannels(void) const { return USB3003_NB_CH; } int GetNbChannels(void) const { return USB3003_NB_CH; }
uint8 GetChannelCodec(int) const; uint8 GetChannelCodec(int) const;
// manage vocodec channels // manage vocodec channels
CVocodecChannel *GetChannelWithChannelIn(int); CVocodecChannel *GetChannelWithChannelIn(int);
CVocodecChannel *GetChannelWithChannelOut(int); CVocodecChannel *GetChannelWithChannelOut(int);
protected: protected:
// decoder helper // decoder helper
bool IsValidChannelPacket(const CBuffer &, int *, CAmbePacket *); bool IsValidChannelPacket(const CBuffer &, int *, CAmbePacket *);
bool IsValidSpeechPacket(const CBuffer &, int *, CVoicePacket *); bool IsValidSpeechPacket(const CBuffer &, int *, CVoicePacket *);
// encoder helpers // encoder helpers
void EncodeChannelPacket(CBuffer *, int, CAmbePacket *); void EncodeChannelPacket(CBuffer *, int, CAmbePacket *);
void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *); void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *);
// low level // low level
bool OpenDevice(void); bool OpenDevice(void);
bool ResetDevice(void); bool ResetDevice(void);
bool ConfigureDevice(void); bool ConfigureDevice(void);
int GetDeviceFifoSize(void) const { return 2; } int GetDeviceFifoSize(void) const { return 2; }
// data // data
uint8 m_uiChCodecs[USB3003_NB_CH]; uint8 m_uiChCodecs[USB3003_NB_CH];
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -38,13 +38,13 @@
CUsb3xxxInterface::CUsb3xxxInterface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial) CUsb3xxxInterface::CUsb3xxxInterface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial)
{ {
m_FtdiHandle = NULL; m_FtdiHandle = NULL;
m_uiVid = uiVid; m_uiVid = uiVid;
m_uiPid = uiPid; m_uiPid = uiPid;
::strcpy(m_szDeviceName, szDeviceName); ::strcpy(m_szDeviceName, szDeviceName);
::strcpy(m_szDeviceSerial, szDeviceSerial); ::strcpy(m_szDeviceSerial, szDeviceSerial);
m_iSpeechFifolLevel = 0; m_iSpeechFifolLevel = 0;
m_iChannelFifolLevel = 0; m_iChannelFifolLevel = 0;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -52,19 +52,19 @@ CUsb3xxxInterface::CUsb3xxxInterface(uint32 uiVid, uint32 uiPid, const char *szD
CUsb3xxxInterface::~CUsb3xxxInterface() CUsb3xxxInterface::~CUsb3xxxInterface()
{ {
// delete m_SpeechQueues // delete m_SpeechQueues
for ( unsigned i = 0; i < m_SpeechQueues.size(); i++ ) for ( unsigned i = 0; i < m_SpeechQueues.size(); i++ )
{ {
delete m_SpeechQueues[i]; delete m_SpeechQueues[i];
} }
m_SpeechQueues.clear(); m_SpeechQueues.clear();
// delete m_ChannelQueues // delete m_ChannelQueues
for ( unsigned i = 0; i < m_ChannelQueues.size(); i++ ) for ( unsigned i = 0; i < m_ChannelQueues.size(); i++ )
{ {
delete m_ChannelQueues[i]; delete m_ChannelQueues[i];
} }
m_ChannelQueues.clear(); m_ChannelQueues.clear();
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -72,44 +72,44 @@ CUsb3xxxInterface::~CUsb3xxxInterface()
bool CUsb3xxxInterface::Init(void) bool CUsb3xxxInterface::Init(void)
{ {
bool ok = true; bool ok = true;
// open USB device // open USB device
std::cout << "Opening " << m_szDeviceName << ":" << m_szDeviceSerial << " device" << std::endl; std::cout << "Opening " << m_szDeviceName << ":" << m_szDeviceSerial << " device" << std::endl;
if ( ok &= OpenDevice() ) if ( ok &= OpenDevice() )
{ {
// reset // reset
//std::cout << "Reseting " << m_szDeviceName << "device" << std::endl; //std::cout << "Reseting " << m_szDeviceName << "device" << std::endl;
if ( ok &= ResetDevice() ) if ( ok &= ResetDevice() )
{ {
// read version // read version
//std::cout << "Reading " << m_szDeviceName << " device version" << std::endl; //std::cout << "Reading " << m_szDeviceName << " device version" << std::endl;
if ( ok &= ReadDeviceVersion() ) if ( ok &= ReadDeviceVersion() )
{ {
// send configuration packet(s) // send configuration packet(s)
//std::cout << "Configuring " << m_szDeviceName << " device" << std::endl; //std::cout << "Configuring " << m_szDeviceName << " device" << std::endl;
ok &= DisableParity(); ok &= DisableParity();
ok &= ConfigureDevice(); ok &= ConfigureDevice();
} }
} }
} }
std::cout << std::endl; std::cout << std::endl;
// create our queues // create our queues
for ( int i = 0; i < GetNbChannels(); i++ ) for ( int i = 0; i < GetNbChannels(); i++ )
{ {
m_SpeechQueues.push_back(new CPacketQueue); m_SpeechQueues.push_back(new CPacketQueue);
m_ChannelQueues.push_back(new CPacketQueue); m_ChannelQueues.push_back(new CPacketQueue);
} }
// base class // base class
if ( ok ) if ( ok )
{ {
ok &= CVocodecInterface::Init(); ok &= CVocodecInterface::Init();
} }
// done // done
return ok; return ok;
} }
@ -118,212 +118,217 @@ bool CUsb3xxxInterface::Init(void)
void CUsb3xxxInterface::Task(void) void CUsb3xxxInterface::Task(void)
{ {
CBuffer Buffer; CBuffer Buffer;
int iCh; int iCh;
CPacketQueue *Queue; CPacketQueue *Queue;
CVocodecChannel *Channel; CVocodecChannel *Channel;
CAmbePacket AmbePacket; CAmbePacket AmbePacket;
CVoicePacket VoicePacket; CVoicePacket VoicePacket;
bool done; bool done;
// TODO : // TODO :
// preserve packets PIDs, so the transcoded CAmbePacket returned // preserve packets PIDs, so the transcoded CAmbePacket returned
// to CStream client is garantied to have the same PID // to CStream client is garantied to have the same PID
// than the corresponding incoming packet // than the corresponding incoming packet
// process the device incoming packet // process the device incoming packet
// get all packets from device and push them // get all packets from device and push them
// to the relevant clients queues // to the relevant clients queues
if ( ReadBuffer(&Buffer) ) if ( ReadBuffer(&Buffer) )
{ {
if ( IsValidSpeechPacket(Buffer, &iCh, &VoicePacket) ) if ( IsValidSpeechPacket(Buffer, &iCh, &VoicePacket) )
{ {
// update fifo level // update fifo level
// as we get a speech packet, it means that the device // as we get a speech packet, it means that the device
// channel fifo input decreased by 1 // channel fifo input decreased by 1
m_iChannelFifolLevel = MAX(0, m_iChannelFifolLevel-1); m_iChannelFifolLevel = MAX(0, m_iChannelFifolLevel-1);
// push back to relevant channel voice queue // push back to relevant channel voice queue
// our incoming channel packet has now been through the decoder // our incoming channel packet has now been through the decoder
// find the coupled channel encoder and push to it's queue // find the coupled channel encoder and push to it's queue
// this is were the DVSI enc-dec channel crossover take place // this is were the DVSI enc-dec channel crossover take place
Channel = GetChannelWithChannelIn(iCh); Channel = GetChannelWithChannelIn(iCh);
if ( Channel != NULL ) if ( Channel != NULL )
{ {
Queue = Channel->GetVoiceQueue(); Queue = Channel->GetVoiceQueue();
CVoicePacket *clone = new CVoicePacket(VoicePacket); CVoicePacket *clone = new CVoicePacket(VoicePacket);
Channel->ProcessSignal(*clone); Channel->ProcessSignal(*clone);
Queue->push(clone); Queue->push(clone);
Channel->ReleaseVoiceQueue(); Channel->ReleaseVoiceQueue();
} }
} }
else if ( IsValidChannelPacket(Buffer, &iCh, &AmbePacket) ) else if ( IsValidChannelPacket(Buffer, &iCh, &AmbePacket) )
{ {
// update fifo level // update fifo level
// as we get a channel packet, it means that the device // as we get a channel packet, it means that the device
// speech fifo input decreased by 1 // speech fifo input decreased by 1
m_iSpeechFifolLevel = MAX(0, m_iSpeechFifolLevel-1); m_iSpeechFifolLevel = MAX(0, m_iSpeechFifolLevel-1);
// push back to relevant channel outcoming queue // push back to relevant channel outcoming queue
// we are done with this packet transcoding // we are done with this packet transcoding
// it's final step // it's final step
Channel = GetChannelWithChannelOut(iCh); Channel = GetChannelWithChannelOut(iCh);
if ( Channel != NULL ) if ( Channel != NULL )
{ {
Queue = Channel->GetPacketQueueOut(); Queue = Channel->GetPacketQueueOut();
CAmbePacket *clone = new CAmbePacket(AmbePacket); CAmbePacket *clone = new CAmbePacket(AmbePacket);
Queue->push(clone); Queue->push(clone);
Channel->ReleasePacketQueueOut(); Channel->ReleasePacketQueueOut();
} }
} }
} }
// process the streams (channels) incoming queue // process the streams (channels) incoming queue
// make sure that packets from different channels // make sure that packets from different channels
// are interlaced so to keep the device fifo busy // are interlaced so to keep the device fifo busy
do do
{ {
done = true; done = true;
for ( unsigned i = 0; i < m_Channels.size(); i++) for ( unsigned i = 0; i < m_Channels.size(); i++)
{ {
// get channel // get channel
Channel = m_Channels[i]; Channel = m_Channels[i];
// any packet in voice queue ? // any packet in voice queue ?
if ( Channel->IsInterfaceOut(this) ) if ( Channel->IsInterfaceOut(this) )
{ {
Queue = Channel->GetVoiceQueue(); Queue = Channel->GetVoiceQueue();
if ( !Queue->empty() ) if ( !Queue->empty() )
{ {
// get packet // get packet
CVoicePacket *Packet = (CVoicePacket *)Queue->front(); CVoicePacket *Packet = (CVoicePacket *)Queue->front();
Queue->pop(); Queue->pop();
// this is second step of transcoding // this is second step of transcoding
// we just received from hardware a decoded speech packet // we just received from hardware a decoded speech packet
// post it to relevant channel encoder // post it to relevant channel encoder
int i = Channel->GetChannelOut(); int i = Channel->GetChannelOut();
Packet->SetChannel(i); Packet->SetChannel(i);
m_SpeechQueues[i]->push(Packet); m_SpeechQueues[i]->push(Packet);
// done // done
done = false; done = false;
} }
Channel->ReleaseVoiceQueue(); Channel->ReleaseVoiceQueue();
} }
// any packet in ambe queue for us ? // any packet in ambe queue for us ?
if ( Channel->IsInterfaceIn(this) ) if ( Channel->IsInterfaceIn(this) )
{ {
Queue = Channel->GetPacketQueueIn(); Queue = Channel->GetPacketQueueIn();
if ( !Queue->empty() ) if ( !Queue->empty() )
{ {
// get packet // get packet
CAmbePacket *Packet = (CAmbePacket *)Queue->front(); CAmbePacket *Packet = (CAmbePacket *)Queue->front();
Queue->pop(); Queue->pop();
// this is first step of transcoding // this is first step of transcoding
// a fresh new packet to be transcoded is showing up // a fresh new packet to be transcoded is showing up
// post it to relevant channel decoder // post it to relevant channel decoder
int i = Channel->GetChannelIn(); int i = Channel->GetChannelIn();
Packet->SetChannel(i); Packet->SetChannel(i);
m_ChannelQueues[i]->push(Packet); m_ChannelQueues[i]->push(Packet);
// done // done
done = false; done = false;
} }
Channel->ReleasePacketQueueIn(); Channel->ReleasePacketQueueIn();
} }
} }
} while (!done); }
while (!done);
// process device incoming queues (aka to device)
// interlace speech and channels packets // process device incoming queues (aka to device)
// and post to final device queue // interlace speech and channels packets
do // and post to final device queue
{ do
done = true; {
// loop on all channels done = true;
for ( int i = 0; i < GetNbChannels(); i++ ) // loop on all channels
{ for ( int i = 0; i < GetNbChannels(); i++ )
// speech {
if ( !m_SpeechQueues[i]->empty() ) // speech
{ if ( !m_SpeechQueues[i]->empty() )
// get packet {
CPacket *Packet = m_SpeechQueues[i]->front(); // get packet
m_SpeechQueues[i]->pop(); CPacket *Packet = m_SpeechQueues[i]->front();
// and push to device queue m_SpeechQueues[i]->pop();
m_DeviceQueue.push(Packet); // and push to device queue
// next m_DeviceQueue.push(Packet);
done = false; // next
} done = false;
// ambe }
if ( !m_ChannelQueues[i]->empty() ) // ambe
{ if ( !m_ChannelQueues[i]->empty() )
// get packet {
CPacket *Packet = m_ChannelQueues[i]->front(); // get packet
m_ChannelQueues[i]->pop(); CPacket *Packet = m_ChannelQueues[i]->front();
// and push to device queue m_ChannelQueues[i]->pop();
m_DeviceQueue.push(Packet); // and push to device queue
// done = false; m_DeviceQueue.push(Packet);
} // done = false;
} }
}
} while (!done);
}
// process device queue to feed hardware while (!done);
// make sure that device fifo is fed all the time
int fifoSize = GetDeviceFifoSize(); // process device queue to feed hardware
do // make sure that device fifo is fed all the time
{ int fifoSize = GetDeviceFifoSize();
done = true; do
// if device fifo level is zero (device idle) {
// wait that at least 3 packets are in incoming done = true;
// queue before restarting // if device fifo level is zero (device idle)
if ( ((m_iSpeechFifolLevel+m_iChannelFifolLevel) > 0) || (m_DeviceQueue.size() >= unsigned(fifoSize+1)) ) // wait that at least 3 packets are in incoming
{ // queue before restarting
// any packet to send ? if ( ((m_iSpeechFifolLevel+m_iChannelFifolLevel) > 0) || (m_DeviceQueue.size() >= unsigned(fifoSize+1)) )
if ( m_DeviceQueue.size() > 0 ) {
{ // any packet to send ?
// yes, get it if ( m_DeviceQueue.size() > 0 )
CPacket *Packet = m_DeviceQueue.front(); {
if ( Packet->IsVoice() && (m_iSpeechFifolLevel < fifoSize) ) // yes, get it
{ CPacket *Packet = m_DeviceQueue.front();
// encode & post if ( Packet->IsVoice() && (m_iSpeechFifolLevel < fifoSize) )
EncodeSpeechPacket(&Buffer, Packet->GetChannel(), (CVoicePacket *)Packet); {
WriteBuffer(Buffer); // encode & post
// remove from queue EncodeSpeechPacket(&Buffer, Packet->GetChannel(), (CVoicePacket *)Packet);
m_DeviceQueue.pop(); WriteBuffer(Buffer);
// and delete it // remove from queue
delete Packet; m_DeviceQueue.pop();
// update fifo level // and delete it
m_iSpeechFifolLevel++; delete Packet;
// next // update fifo level
done = false; m_iSpeechFifolLevel++;
// next
done = false;
#ifdef DEBUG_DUMPFILE #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 #endif
} }
else if ( Packet->IsAmbe() && (m_iChannelFifolLevel < fifoSize) ) else if ( Packet->IsAmbe() && (m_iChannelFifolLevel < fifoSize) )
{ {
// encode & post // encode & post
EncodeChannelPacket(&Buffer, Packet->GetChannel(), (CAmbePacket *)Packet); EncodeChannelPacket(&Buffer, Packet->GetChannel(), (CAmbePacket *)Packet);
WriteBuffer(Buffer); WriteBuffer(Buffer);
// remove from queue // remove from queue
m_DeviceQueue.pop(); m_DeviceQueue.pop();
// and delete it // and delete it
delete Packet; delete Packet;
// update fifo level // update fifo level
m_iChannelFifolLevel++; m_iChannelFifolLevel++;
// next // next
done = false; done = false;
#ifdef DEBUG_DUMPFILE #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 #endif
} }
} }
} }
} while (!done); }
while (!done);
// and wait a bit // and wait a bit
CTimePoint::TaskSleepFor(2); CTimePoint::TaskSleepFor(2);
} }
@ -332,100 +337,100 @@ void CUsb3xxxInterface::Task(void)
bool CUsb3xxxInterface::ReadDeviceVersion(void) bool CUsb3xxxInterface::ReadDeviceVersion(void)
{ {
bool ok = false; bool ok = false;
int i, len; int i, len;
char rxpacket[128]; char rxpacket[128];
char txpacket[8] = char txpacket[8] =
{ {
PKT_HEADER, PKT_HEADER,
0, 0,
4, 4,
PKT_CONTROL, PKT_CONTROL,
PKT_PRODID, PKT_PRODID,
PKT_VERSTRING, PKT_VERSTRING,
PKT_PARITYBYTE, PKT_PARITYBYTE,
4 ^ PKT_CONTROL ^ PKT_PRODID ^ PKT_VERSTRING ^ PKT_PARITYBYTE 4 ^ PKT_CONTROL ^ PKT_PRODID ^ PKT_VERSTRING ^ PKT_PARITYBYTE
}; };
// write packet // write packet
if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) )
{ {
// read reply // read reply
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4; len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4;
ok = (len != 0); ok = (len != 0);
//we succeed in reading a packet, print it out //we succeed in reading a packet, print it out
std::cout << "ReadDeviceVersion : "; std::cout << "ReadDeviceVersion : ";
for ( i = 4; i < len+4 ; i++ ) for ( i = 4; i < len+4 ; i++ )
{ {
std::cout << (char)(rxpacket[i] & 0x00ff); std::cout << (char)(rxpacket[i] & 0x00ff);
} }
std::cout << std::endl; std::cout << std::endl;
} }
return ok; return ok;
} }
bool CUsb3xxxInterface::DisableParity(void) bool CUsb3xxxInterface::DisableParity(void)
{ {
bool ok = false; bool ok = false;
int len; int len;
char rxpacket[16]; char rxpacket[16];
char txpacket[8] = char txpacket[8] =
{ {
PKT_HEADER, PKT_HEADER,
0, 0,
4, 4,
PKT_CONTROL, PKT_CONTROL,
PKT_PARITYMODE,0x00, PKT_PARITYMODE,0x00,
PKT_PARITYBYTE, PKT_PARITYBYTE,
4 ^ PKT_CONTROL ^ PKT_PARITYMODE ^ 0x00 ^ PKT_PARITYBYTE 4 ^ PKT_CONTROL ^ PKT_PARITYMODE ^ 0x00 ^ PKT_PARITYBYTE
}; };
// write packet // write packet
if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) )
{ {
// read reply // read reply
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4; len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4;
ok = ((len == 2) && (rxpacket[4] == PKT_PARITYMODE) &&(rxpacket[5] == 0x00) ); ok = ((len == 2) && (rxpacket[4] == PKT_PARITYMODE) &&(rxpacket[5] == 0x00) );
} }
return ok; return ok;
} }
bool CUsb3xxxInterface::ConfigureChannel(uint8 pkt_ch, const uint8 *pkt_ratep, int in_gain, int out_gain) bool CUsb3xxxInterface::ConfigureChannel(uint8 pkt_ch, const uint8 *pkt_ratep, int in_gain, int out_gain)
{ {
bool ok = false; bool ok = false;
int len; int len;
char rxpacket[64]; char rxpacket[64];
char txpacket[] = char txpacket[] =
{ {
PKT_HEADER, PKT_HEADER,
0, 0,
33, 33,
PKT_CONTROL, PKT_CONTROL,
0x00, 0x00,
PKT_ECMODE, 0x00,0x00, PKT_ECMODE, 0x00,0x00,
PKT_DCMODE, 0x00,0x00, PKT_DCMODE, 0x00,0x00,
PKT_COMPAND,0x00, PKT_COMPAND,0x00,
PKT_RATEP, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, PKT_RATEP, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
PKT_CHANFMT,0x00,0x00, PKT_CHANFMT,0x00,0x00,
PKT_SPCHFMT,0x00,0x00, PKT_SPCHFMT,0x00,0x00,
PKT_GAIN, 0x00,0x00, PKT_GAIN, 0x00,0x00,
PKT_INIT, 0x03 PKT_INIT, 0x03
}; };
// update packet content // update packet content
txpacket[4] = pkt_ch; txpacket[4] = pkt_ch;
:: memcpy(&(txpacket[14]), pkt_ratep, 12); :: memcpy(&(txpacket[14]), pkt_ratep, 12);
txpacket[33] = (uint8)(signed char)in_gain; txpacket[33] = (uint8)(signed char)in_gain;
txpacket[34] = (uint8)(signed char)out_gain; txpacket[34] = (uint8)(signed char)out_gain;
// write packet // write packet
if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) )
{ {
// read reply // read reply
len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4; len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4;
ok = ((len == 18) && (rxpacket[20] == PKT_INIT) &&(rxpacket[21] == 0x00) ); ok = ((len == 18) && (rxpacket[20] == PKT_INIT) &&(rxpacket[21] == 0x00) );
} }
return ok; return ok;
} }
@ -435,89 +440,89 @@ bool CUsb3xxxInterface::ConfigureChannel(uint8 pkt_ch, const uint8 *pkt_ratep, i
bool CUsb3xxxInterface::ReadBuffer(CBuffer *buffer) bool CUsb3xxxInterface::ReadBuffer(CBuffer *buffer)
{ {
bool ok = false; bool ok = false;
int n; int n;
// any byte in tx queue ? // any byte in tx queue ?
if ( FT_GetQueueStatus(m_FtdiHandle, (LPDWORD)&n) == FT_OK ) if ( FT_GetQueueStatus(m_FtdiHandle, (LPDWORD)&n) == FT_OK )
{ {
//if ( (FT_GetQueueStatus(m_FtdiHandle, (LPDWORD)&n) == FT_OK) && (n != 0) ) //if ( (FT_GetQueueStatus(m_FtdiHandle, (LPDWORD)&n) == FT_OK) && (n != 0) )
if ( n != 0 ) if ( n != 0 )
{ {
buffer->clear(); buffer->clear();
buffer->resize(USB3XXX_MAXPACKETSIZE); buffer->resize(USB3XXX_MAXPACKETSIZE);
n = FTDI_read_packet(m_FtdiHandle, (char *)buffer->data(), USB3XXX_MAXPACKETSIZE); n = FTDI_read_packet(m_FtdiHandle, (char *)buffer->data(), USB3XXX_MAXPACKETSIZE);
buffer->resize(n); buffer->resize(n);
ok = (n != 0); ok = (n != 0);
} }
} }
return ok; return ok;
} }
bool CUsb3xxxInterface::WriteBuffer(const CBuffer &buffer) 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 CUsb3xxxInterface::FTDI_read_packet(FT_HANDLE ftHandle, char *pkt, int maxlen)
{ {
int plen; int plen;
// first read 4 bytes header // first read 4 bytes header
if ( FTDI_read_bytes(ftHandle, pkt, 4) ) if ( FTDI_read_bytes(ftHandle, pkt, 4) )
{ {
// get payload length // get payload length
plen = (pkt[1] & 0x00ff); plen = (pkt[1] & 0x00ff);
plen <<= 8; plen <<= 8;
plen += (pkt[2] & 0x00ff); plen += (pkt[2] & 0x00ff);
// check buffer length // check buffer length
if (plen+4 > maxlen) if (plen+4 > maxlen)
{ {
std::cout << "FTDI_read_packet supplied buffer is not large enough for packet" << std::endl; std::cout << "FTDI_read_packet supplied buffer is not large enough for packet" << std::endl;
FT_Purge(ftHandle, FT_PURGE_RX); FT_Purge(ftHandle, FT_PURGE_RX);
return 0; return 0;
} }
// and get payload // and get payload
if ( FTDI_read_bytes(ftHandle, &pkt[4], plen) ) if ( FTDI_read_bytes(ftHandle, &pkt[4], plen) )
{ {
return plen+4; return plen+4;
} }
} }
return 0; return 0;
} }
bool CUsb3xxxInterface::FTDI_read_bytes(FT_HANDLE ftHandle, char *buffer, int len) bool CUsb3xxxInterface::FTDI_read_bytes(FT_HANDLE ftHandle, char *buffer, int len)
{ {
// this relies on FT_SetTimouts() mechanism // this relies on FT_SetTimouts() mechanism
int n; int n;
bool ok = false; bool ok = false;
ok = (FT_Read(ftHandle, (LPVOID)buffer, len, (LPDWORD)&n) == FT_OK) && (n == len); ok = (FT_Read(ftHandle, (LPVOID)buffer, len, (LPDWORD)&n) == FT_OK) && (n == len);
if ( !ok ) if ( !ok )
{ {
//FT_Purge(ftHandle, FT_PURGE_RX); //FT_Purge(ftHandle, FT_PURGE_RX);
std::cout << "FTDI_read_bytes(" << len << ") failed : " << n << std::endl; std::cout << "FTDI_read_bytes(" << len << ") failed : " << n << std::endl;
} }
return ok; return ok;
} }
bool CUsb3xxxInterface::FTDI_write_packet(FT_HANDLE ft_handle, const char *pkt, int len) bool CUsb3xxxInterface::FTDI_write_packet(FT_HANDLE ft_handle, const char *pkt, int len)
{ {
FT_STATUS ftStatus; FT_STATUS ftStatus;
bool ok = true; bool ok = true;
int nwritten; int nwritten;
if ( len > 0 ) if ( len > 0 )
{ {
ftStatus = FT_Write(m_FtdiHandle, (LPVOID *)pkt, (DWORD)len, (LPDWORD)&nwritten); ftStatus = FT_Write(m_FtdiHandle, (LPVOID *)pkt, (DWORD)len, (LPDWORD)&nwritten);
ok = (ftStatus == FT_OK) && (len == nwritten); ok = (ftStatus == FT_OK) && (len == nwritten);
if ( !ok ) if ( !ok )
{ {
FTDI_Error((char *)"FT_Write", ftStatus); FTDI_Error((char *)"FT_Write", ftStatus);
} }
} }
return ok; 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) 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;
} }

@ -72,64 +72,64 @@
class CUsb3xxxInterface : public CVocodecInterface class CUsb3xxxInterface : public CVocodecInterface
{ {
public: public:
// constructors // constructors
CUsb3xxxInterface(uint32, uint32, const char *, const char *); CUsb3xxxInterface(uint32, uint32, const char *, const char *);
// destructor // destructor
virtual ~CUsb3xxxInterface(); virtual ~CUsb3xxxInterface();
// initialization // initialization
bool Init(void); bool Init(void);
// get // get
const char *GetName(void) const { return m_szDeviceName; } const char *GetName(void) const { return m_szDeviceName; }
const char *GetSerial(void) const { return m_szDeviceSerial; } const char *GetSerial(void) const { return m_szDeviceSerial; }
// task // task
void Task(void); void Task(void);
protected: protected:
// decoder helper // decoder helper
virtual bool IsValidChannelPacket(const CBuffer &, int *, CAmbePacket *) { return false; } virtual bool IsValidChannelPacket(const CBuffer &, int *, CAmbePacket *) { return false; }
virtual bool IsValidSpeechPacket(const CBuffer &, int *, CVoicePacket *) { return false; } virtual bool IsValidSpeechPacket(const CBuffer &, int *, CVoicePacket *) { return false; }
// encoder helpers // encoder helpers
virtual void EncodeChannelPacket(CBuffer *, int, CAmbePacket *) {} virtual void EncodeChannelPacket(CBuffer *, int, CAmbePacket *) {}
virtual void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *) {} virtual void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *) {}
// low level // low level
virtual bool OpenDevice(void) { return false; } virtual bool OpenDevice(void) { return false; }
virtual bool ResetDevice(void) { return false; } virtual bool ResetDevice(void) { return false; }
bool ReadDeviceVersion(void); bool ReadDeviceVersion(void);
bool DisableParity(void); bool DisableParity(void);
virtual bool ConfigureDevice(void) { return false; } virtual bool ConfigureDevice(void) { return false; }
bool ConfigureChannel(uint8, const uint8 *, int, int); bool ConfigureChannel(uint8, const uint8 *, int, int);
virtual int GetDeviceFifoSize(void) const { return 1; } virtual int GetDeviceFifoSize(void) const { return 1; }
// io level // io level
bool ReadBuffer(CBuffer *); bool ReadBuffer(CBuffer *);
bool WriteBuffer(const CBuffer &); bool WriteBuffer(const CBuffer &);
int FTDI_read_packet(FT_HANDLE, char *, int); int FTDI_read_packet(FT_HANDLE, char *, int);
bool FTDI_read_bytes(FT_HANDLE, char *, int); bool FTDI_read_bytes(FT_HANDLE, char *, int);
bool FTDI_write_packet(FT_HANDLE, const char *, int); bool FTDI_write_packet(FT_HANDLE, const char *, int);
// error reporting // error reporting
void FTDI_Error(char *, FT_STATUS); void FTDI_Error(char *, FT_STATUS);
protected: protected:
// data // data
uint32 m_uiVid; uint32 m_uiVid;
uint32 m_uiPid; uint32 m_uiPid;
char m_szDeviceName[FTDI_MAX_STRINGLENGTH]; char m_szDeviceName[FTDI_MAX_STRINGLENGTH];
char m_szDeviceSerial[FTDI_MAX_STRINGLENGTH]; char m_szDeviceSerial[FTDI_MAX_STRINGLENGTH];
FT_HANDLE m_FtdiHandle; FT_HANDLE m_FtdiHandle;
// queue // queue
std::vector<CPacketQueue*> m_SpeechQueues; std::vector<CPacketQueue*> m_SpeechQueues;
std::vector<CPacketQueue*> m_ChannelQueues; std::vector<CPacketQueue*> m_ChannelQueues;
CPacketQueue m_DeviceQueue; CPacketQueue m_DeviceQueue;
int m_iSpeechFifolLevel; int m_iSpeechFifolLevel;
int m_iChannelFifolLevel; int m_iChannelFifolLevel;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -32,13 +32,13 @@
CVocodecChannel::CVocodecChannel(CVocodecInterface *InterfaceIn, int iChIn, CVocodecInterface *InterfaceOut, int iChOut, int iSpeechGain) CVocodecChannel::CVocodecChannel(CVocodecInterface *InterfaceIn, int iChIn, CVocodecInterface *InterfaceOut, int iChOut, int iSpeechGain)
{ {
m_bOpen = false; m_bOpen = false;
m_InterfaceIn = InterfaceIn; m_InterfaceIn = InterfaceIn;
m_iChannelIn = iChIn; m_iChannelIn = iChIn;
m_InterfaceOut = InterfaceOut; m_InterfaceOut = InterfaceOut;
m_iChannelOut = iChOut; m_iChannelOut = iChOut;
m_iSpeechGain = iSpeechGain; m_iSpeechGain = iSpeechGain;
m_signalProcessor = new CSignalProcessor((float)m_iSpeechGain); m_signalProcessor = new CSignalProcessor((float)m_iSpeechGain);
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -46,8 +46,8 @@ CVocodecChannel::CVocodecChannel(CVocodecInterface *InterfaceIn, int iChIn, CVoc
CVocodecChannel::~CVocodecChannel() CVocodecChannel::~CVocodecChannel()
{ {
PurgeAllQueues(); PurgeAllQueues();
delete m_signalProcessor; delete m_signalProcessor;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -55,29 +55,29 @@ CVocodecChannel::~CVocodecChannel()
bool CVocodecChannel::Open(void) bool CVocodecChannel::Open(void)
{ {
bool ok = false; bool ok = false;
if ( !m_bOpen ) if ( !m_bOpen )
{ {
m_bOpen = true; m_bOpen = true;
ok = true; ok = true;
PurgeAllQueues(); PurgeAllQueues();
std::cout << "Vocodec channel " << std::cout << "Vocodec channel " <<
m_InterfaceIn->GetName() << ":" << (int)m_iChannelIn << " -> " << m_InterfaceIn->GetName() << ":" << (int)m_iChannelIn << " -> " <<
m_InterfaceOut->GetName() << ":" << (int)m_iChannelOut << " open" << std::endl; m_InterfaceOut->GetName() << ":" << (int)m_iChannelOut << " open" << std::endl;
} }
return ok; return ok;
} }
void CVocodecChannel::Close(void) void CVocodecChannel::Close(void)
{ {
if ( m_bOpen ) if ( m_bOpen )
{ {
m_bOpen = false; m_bOpen = false;
PurgeAllQueues(); PurgeAllQueues();
std::cout << "Vocodec channel " << std::cout << "Vocodec channel " <<
m_InterfaceIn->GetName() << ":" << (int)m_iChannelIn << " -> " << m_InterfaceIn->GetName() << ":" << (int)m_iChannelIn << " -> " <<
m_InterfaceOut->GetName() << ":" << (int)m_iChannelOut << " closed" << std::endl; m_InterfaceOut->GetName() << ":" << (int)m_iChannelOut << " closed" << std::endl;
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -85,12 +85,12 @@ void CVocodecChannel::Close(void)
uint8 CVocodecChannel::GetCodecIn(void) const uint8 CVocodecChannel::GetCodecIn(void) const
{ {
return m_InterfaceIn->GetChannelCodec(m_iChannelIn); return m_InterfaceIn->GetChannelCodec(m_iChannelIn);
} }
uint8 CVocodecChannel::GetCodecOut(void) const 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) 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) void CVocodecChannel::PurgeAllQueues(void)
{ {
GetPacketQueueIn()->Purge(); GetPacketQueueIn()->Purge();
ReleasePacketQueueIn(); ReleasePacketQueueIn();
GetPacketQueueOut()->Purge(); GetPacketQueueOut()->Purge();
ReleasePacketQueueOut(); ReleasePacketQueueOut();
GetVoiceQueue()->Purge(); GetVoiceQueue()->Purge();
ReleaseVoiceQueue(); ReleaseVoiceQueue();
} }

@ -38,67 +38,67 @@ class CVocodecInterface;
class CVocodecChannel class CVocodecChannel
{ {
public: public:
// constructors // constructors
CVocodecChannel(CVocodecInterface *, int, CVocodecInterface *, int, int); CVocodecChannel(CVocodecInterface *, int, CVocodecInterface *, int, int);
// destructor // destructor
virtual ~CVocodecChannel(); virtual ~CVocodecChannel();
// open & close // open & close
bool Open(void); bool Open(void);
bool IsOpen(void) const { return m_bOpen; } bool IsOpen(void) const { return m_bOpen; }
void Close(void); void Close(void);
// get // get
uint8 GetCodecIn(void) const; uint8 GetCodecIn(void) const;
uint8 GetCodecOut(void) const; uint8 GetCodecOut(void) const;
int GetChannelIn(void) const { return m_iChannelIn; } int GetChannelIn(void) const { return m_iChannelIn; }
int GetChannelOut(void) const { return m_iChannelOut; } int GetChannelOut(void) const { return m_iChannelOut; }
int GetSpeechGain(void) const { return m_iSpeechGain; } int GetSpeechGain(void) const { return m_iSpeechGain; }
//Processing //Processing
void ProcessSignal(CVoicePacket& voicePacket); void ProcessSignal(CVoicePacket& voicePacket);
// interfaces // interfaces
bool IsInterfaceIn(const CVocodecInterface *interface) { return (interface == m_InterfaceIn); } bool IsInterfaceIn(const CVocodecInterface *interface) { return (interface == m_InterfaceIn); }
bool IsInterfaceOut(const CVocodecInterface *interface) { return (interface == m_InterfaceOut); } bool IsInterfaceOut(const CVocodecInterface *interface) { return (interface == m_InterfaceOut); }
// queues // queues
CPacketQueue *GetPacketQueueIn(void) { m_QueuePacketIn.Lock(); return &m_QueuePacketIn; } CPacketQueue *GetPacketQueueIn(void) { m_QueuePacketIn.Lock(); return &m_QueuePacketIn; }
void ReleasePacketQueueIn(void) { m_QueuePacketIn.Unlock(); } void ReleasePacketQueueIn(void) { m_QueuePacketIn.Unlock(); }
CPacketQueue *GetPacketQueueOut(void) { m_QueuePacketOut.Lock(); return &m_QueuePacketOut; } CPacketQueue *GetPacketQueueOut(void) { m_QueuePacketOut.Lock(); return &m_QueuePacketOut; }
void ReleasePacketQueueOut(void) { m_QueuePacketOut.Unlock(); } void ReleasePacketQueueOut(void) { m_QueuePacketOut.Unlock(); }
CPacketQueue *GetVoiceQueue(void) { m_QueueVoice.Lock(); return &m_QueueVoice; } CPacketQueue *GetVoiceQueue(void) { m_QueueVoice.Lock(); return &m_QueueVoice; }
void ReleaseVoiceQueue(void) { m_QueueVoice.Unlock(); } void ReleaseVoiceQueue(void) { m_QueueVoice.Unlock(); }
// operators // operators
//virtual bool operator ==(const CVocodecChannel &) const { return false; } //virtual bool operator ==(const CVocodecChannel &) const { return false; }
protected: protected:
// queues helpers // queues helpers
void PurgeAllQueues(void); void PurgeAllQueues(void);
protected: protected:
// status // status
bool m_bOpen; bool m_bOpen;
// connected interfaces // connected interfaces
CVocodecInterface *m_InterfaceIn; CVocodecInterface *m_InterfaceIn;
int m_iChannelIn; int m_iChannelIn;
CVocodecInterface *m_InterfaceOut; CVocodecInterface *m_InterfaceOut;
int m_iChannelOut; int m_iChannelOut;
// ambe queues // ambe queues
CPacketQueue m_QueuePacketIn; CPacketQueue m_QueuePacketIn;
CPacketQueue m_QueuePacketOut; CPacketQueue m_QueuePacketOut;
// voice queue // voice queue
CPacketQueue m_QueueVoice; CPacketQueue m_QueueVoice;
// settings // settings
int m_iSpeechGain; int m_iSpeechGain;
private: private:
CSignalProcessor* m_signalProcessor; CSignalProcessor* m_signalProcessor;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -33,9 +33,9 @@
CVocodecInterface::CVocodecInterface() CVocodecInterface::CVocodecInterface()
{ {
m_Channels.reserve(5); m_Channels.reserve(5);
m_bStopThread = false; m_bStopThread = false;
m_pThread = NULL; m_pThread = NULL;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -43,17 +43,17 @@ CVocodecInterface::CVocodecInterface()
CVocodecInterface::~CVocodecInterface() CVocodecInterface::~CVocodecInterface()
{ {
// empty channel array // empty channel array
// chennels are deleted by their owner (CVocodecs) // chennels are deleted by their owner (CVocodecs)
m_Channels.clear(); m_Channels.clear();
// stop thread // stop thread
m_bStopThread = true; m_bStopThread = true;
if ( m_pThread != NULL ) if ( m_pThread != NULL )
{ {
m_pThread->join(); m_pThread->join();
delete m_pThread; delete m_pThread;
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -61,14 +61,14 @@ CVocodecInterface::~CVocodecInterface()
bool CVocodecInterface::Init(void) bool CVocodecInterface::Init(void)
{ {
// reset stop flag // reset stop flag
m_bStopThread = false; m_bStopThread = false;
// start thread; // start thread;
m_pThread = new std::thread(CVocodecInterface::Thread, this); m_pThread = new std::thread(CVocodecInterface::Thread, this);
// done // done
return true; return true;
} }
@ -77,10 +77,10 @@ bool CVocodecInterface::Init(void)
void CVocodecInterface::Thread(CVocodecInterface *This) void CVocodecInterface::Thread(CVocodecInterface *This)
{ {
while ( !This->m_bStopThread ) while ( !This->m_bStopThread )
{ {
This->Task(); This->Task();
} }
} }
@ -89,7 +89,7 @@ void CVocodecInterface::Thread(CVocodecInterface *This)
void CVocodecInterface::AddChannel(CVocodecChannel *Channel) void CVocodecInterface::AddChannel(CVocodecChannel *Channel)
{ {
m_Channels.push_back(Channel); m_Channels.push_back(Channel);
} }

@ -35,40 +35,40 @@ class CVocodecs;
class CVocodecInterface class CVocodecInterface
{ {
public: public:
// constructors // constructors
CVocodecInterface(); CVocodecInterface();
// destructor // destructor
virtual ~CVocodecInterface(); virtual ~CVocodecInterface();
// initialization // initialization
virtual bool Init(void); virtual bool Init(void);
// get // get
virtual const char *GetName(void) const { return ""; } virtual const char *GetName(void) const { return ""; }
// manage channels // manage channels
virtual int GetNbChannels(void) const { return 0; } virtual int GetNbChannels(void) const { return 0; }
virtual uint8 GetChannelCodec(int) const { return CODEC_NONE; } virtual uint8 GetChannelCodec(int) const { return CODEC_NONE; }
void AddChannel(CVocodecChannel *); void AddChannel(CVocodecChannel *);
virtual CVocodecChannel *GetChannelWithChannelIn(int) { return NULL; } virtual CVocodecChannel *GetChannelWithChannelIn(int) { return NULL; }
virtual CVocodecChannel *GetChannelWithChannelOut(int) { return NULL; } virtual CVocodecChannel *GetChannelWithChannelOut(int) { return NULL; }
// task // task
static void Thread(CVocodecInterface *); static void Thread(CVocodecInterface *);
virtual void Task(void) {}; virtual void Task(void) {};
// operators
virtual bool operator ==(const CVocodecInterface &) const { return false; }
// operators
virtual bool operator ==(const CVocodecInterface &) const { return false; }
protected: protected:
// array of channels // array of channels
std::vector<CVocodecChannel *> m_Channels; std::vector<CVocodecChannel *> m_Channels;
// thread // thread
bool m_bStopThread; bool m_bStopThread;
std::thread *m_pThread; std::thread *m_pThread;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -36,9 +36,9 @@ CVocodecs g_Vocodecs;
CVocodecs::CVocodecs() CVocodecs::CVocodecs()
{ {
m_Interfaces.reserve(5); m_Interfaces.reserve(5);
m_Channels.reserve(20); m_Channels.reserve(20);
m_FtdiDeviceDescrs.reserve(10); m_FtdiDeviceDescrs.reserve(10);
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -46,33 +46,33 @@ CVocodecs::CVocodecs()
CVocodecs::~CVocodecs() CVocodecs::~CVocodecs()
{ {
// delete channels // delete channels
m_MutexChannels.lock(); m_MutexChannels.lock();
{ {
for ( unsigned i = 0; i < m_Channels.size(); i++ ) for ( unsigned i = 0; i < m_Channels.size(); i++ )
{ {
delete m_Channels[i]; delete m_Channels[i];
} }
m_Channels.clear(); m_Channels.clear();
} }
m_MutexChannels.unlock(); m_MutexChannels.unlock();
// delete interfaces // delete interfaces
m_MutexInterfaces.lock(); m_MutexInterfaces.lock();
{ {
for ( unsigned i = 0; i < m_Interfaces.size(); i++ ) for ( unsigned i = 0; i < m_Interfaces.size(); i++ )
{ {
delete m_Interfaces[i]; delete m_Interfaces[i];
} }
m_Interfaces.clear(); m_Interfaces.clear();
} }
m_MutexInterfaces.unlock(); m_MutexInterfaces.unlock();
// delete ftdi device descriptors // delete ftdi device descriptors
for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
{ {
delete m_FtdiDeviceDescrs[i]; delete m_FtdiDeviceDescrs[i];
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -80,176 +80,176 @@ CVocodecs::~CVocodecs()
bool CVocodecs::Init(void) bool CVocodecs::Init(void)
{ {
bool ok = true; bool ok = true;
int iNbCh = 0; int iNbCh = 0;
// discover and add vocodecs interfaces // discover and add vocodecs interfaces
DiscoverFtdiDevices(); DiscoverFtdiDevices();
// and create interfaces for the discovered devices // and create interfaces for the discovered devices
// first handle all even number of channels devices // first handle all even number of channels devices
std::vector<CVocodecChannel *> Multi3003DevicesChs; std::vector<CVocodecChannel *> Multi3003DevicesChs;
for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
{ {
CFtdiDeviceDescr *descr = m_FtdiDeviceDescrs[i]; CFtdiDeviceDescr *descr = m_FtdiDeviceDescrs[i];
if ( !descr->IsUsed() && IsEven(descr->GetNbChannels()) ) if ( !descr->IsUsed() && IsEven(descr->GetNbChannels()) )
{ {
// create the object // create the object
iNbCh += CFtdiDeviceDescr::CreateInterface(descr, &Multi3003DevicesChs); iNbCh += CFtdiDeviceDescr::CreateInterface(descr, &Multi3003DevicesChs);
// and flag as used // and flag as used
descr->SetUsed(true); descr->SetUsed(true);
} }
} }
// next handle all single channel devices. // next handle all single channel devices.
// they must be handeled in pair, or in pair with another // they must be handeled in pair, or in pair with another
// even number of channels device. // even number of channels device.
std::vector<CVocodecChannel *> PairsOf3000DevicesChs; std::vector<CVocodecChannel *> PairsOf3000DevicesChs;
for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
{ {
CFtdiDeviceDescr *descr1 = m_FtdiDeviceDescrs[i]; CFtdiDeviceDescr *descr1 = m_FtdiDeviceDescrs[i];
CFtdiDeviceDescr *descr2 = NULL; CFtdiDeviceDescr *descr2 = NULL;
if ( !descr1->IsUsed() && (descr1->GetNbChannels() == 1) ) if ( !descr1->IsUsed() && (descr1->GetNbChannels() == 1) )
{ {
// any other single channel device to pair with ? // any other single channel device to pair with ?
bool found = false; bool found = false;
unsigned j = i+1; unsigned j = i+1;
while ( !found && (j < m_FtdiDeviceDescrs.size()) ) while ( !found && (j < m_FtdiDeviceDescrs.size()) )
{ {
descr2 = m_FtdiDeviceDescrs[j]; descr2 = m_FtdiDeviceDescrs[j];
found = (!descr2->IsUsed() && (descr2->GetNbChannels() == 1)); found = (!descr2->IsUsed() && (descr2->GetNbChannels() == 1));
j++; j++;
} }
// found one ? // found one ?
if ( found ) if ( found )
{ {
// yes, create and pair both interfaces // yes, create and pair both interfaces
iNbCh += CFtdiDeviceDescr::CreateInterfacePair(descr1, descr2, &PairsOf3000DevicesChs); iNbCh += CFtdiDeviceDescr::CreateInterfacePair(descr1, descr2, &PairsOf3000DevicesChs);
// and flag as used // and flag as used
descr1->SetUsed(true); descr1->SetUsed(true);
descr2->SetUsed(true); descr2->SetUsed(true);
} }
} }
} }
// now we should have only remaining the 3 channels device(s) // now we should have only remaining the 3 channels device(s)
// and possibly an unique single channel device // and possibly an unique single channel device
std::vector<CVocodecChannel *> Single3003DeviceChannels; std::vector<CVocodecChannel *> Single3003DeviceChannels;
for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
{ {
CFtdiDeviceDescr *descr1 = m_FtdiDeviceDescrs[i]; CFtdiDeviceDescr *descr1 = m_FtdiDeviceDescrs[i];
CFtdiDeviceDescr *descr2 = NULL; CFtdiDeviceDescr *descr2 = NULL;
if ( !descr1->IsUsed() && (descr1->GetNbChannels() == 3) ) if ( !descr1->IsUsed() && (descr1->GetNbChannels() == 3) )
{ {
// any other 3 channel device to pair with ? // any other 3 channel device to pair with ?
bool found = false; bool found = false;
unsigned j = i+1; unsigned j = i+1;
while ( !found && (j < m_FtdiDeviceDescrs.size()) ) while ( !found && (j < m_FtdiDeviceDescrs.size()) )
{ {
descr2 = m_FtdiDeviceDescrs[j]; descr2 = m_FtdiDeviceDescrs[j];
found = (!descr2->IsUsed() && (descr2->GetNbChannels() == 3)); found = (!descr2->IsUsed() && (descr2->GetNbChannels() == 3));
j++; j++;
} }
// found one ? // found one ?
if ( found ) if ( found )
{ {
// yes, create and pair both interfaces // yes, create and pair both interfaces
iNbCh += CFtdiDeviceDescr::CreateInterfacePair(descr1, descr2, &Multi3003DevicesChs); iNbCh += CFtdiDeviceDescr::CreateInterfacePair(descr1, descr2, &Multi3003DevicesChs);
// and flag as used // and flag as used
descr1->SetUsed(true); descr1->SetUsed(true);
descr2->SetUsed(true); descr2->SetUsed(true);
} }
} }
} }
// at this point we should have only remaining an unique 3 channels // at this point we should have only remaining an unique 3 channels
// and or a unique single channel // and or a unique single channel
std::vector<CVocodecChannel *> Combined3003And3000DeviceChannels; std::vector<CVocodecChannel *> Combined3003And3000DeviceChannels;
for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
{ {
CFtdiDeviceDescr *descr1 = m_FtdiDeviceDescrs[i]; CFtdiDeviceDescr *descr1 = m_FtdiDeviceDescrs[i];
CFtdiDeviceDescr *descr2 = NULL; CFtdiDeviceDescr *descr2 = NULL;
// Any 3003 ? // Any 3003 ?
if ( !descr1->IsUsed() && (descr1->GetNbChannels() == 3) ) if ( !descr1->IsUsed() && (descr1->GetNbChannels() == 3) )
{ {
// any single channel device to pair with ? // any single channel device to pair with ?
bool found = false; bool found = false;
unsigned j = 0; unsigned j = 0;
while ( !found && (j < m_FtdiDeviceDescrs.size()) ) while ( !found && (j < m_FtdiDeviceDescrs.size()) )
{ {
descr2 = m_FtdiDeviceDescrs[j]; descr2 = m_FtdiDeviceDescrs[j];
found = ((descr1 != descr2) && !descr2->IsUsed() && (descr2->GetNbChannels() == 1)); found = ((descr1 != descr2) && !descr2->IsUsed() && (descr2->GetNbChannels() == 1));
j++; j++;
} }
// found one ? // found one ?
if ( found ) if ( found )
{ {
// yes, create and pair both interfaces // yes, create and pair both interfaces
iNbCh += CFtdiDeviceDescr::CreateInterfacePair(descr1, descr2, &Combined3003And3000DeviceChannels); iNbCh += CFtdiDeviceDescr::CreateInterfacePair(descr1, descr2, &Combined3003And3000DeviceChannels);
// and flag as used // and flag as used
descr1->SetUsed(true); descr1->SetUsed(true);
descr2->SetUsed(true); descr2->SetUsed(true);
} }
else else
{ {
// no, just create a standalone 3003 interface // no, just create a standalone 3003 interface
iNbCh += CFtdiDeviceDescr::CreateInterface(descr1, &Single3003DeviceChannels); iNbCh += CFtdiDeviceDescr::CreateInterface(descr1, &Single3003DeviceChannels);
// and flag as used // and flag as used
descr1->SetUsed(true); descr1->SetUsed(true);
} }
} }
} }
// at this point we should possible only have unique 3003 remaining // at this point we should possible only have unique 3003 remaining
// now agregate channels by order of priority // now agregate channels by order of priority
// for proper load sharing // for proper load sharing
// pairs of 3000 devices first // pairs of 3000 devices first
{ {
for ( unsigned i = 0; i < PairsOf3000DevicesChs.size(); i++ ) for ( unsigned i = 0; i < PairsOf3000DevicesChs.size(); i++ )
{ {
m_Channels.push_back(PairsOf3000DevicesChs.at(i)); m_Channels.push_back(PairsOf3000DevicesChs.at(i));
} }
PairsOf3000DevicesChs.clear(); PairsOf3000DevicesChs.clear();
} }
// next the left-over single 3003 device // next the left-over single 3003 device
{ {
for ( unsigned i = 0; i < Single3003DeviceChannels.size(); i++ ) for ( unsigned i = 0; i < Single3003DeviceChannels.size(); i++ )
{ {
m_Channels.push_back(Single3003DeviceChannels.at(i)); m_Channels.push_back(Single3003DeviceChannels.at(i));
} }
Single3003DeviceChannels.clear(); Single3003DeviceChannels.clear();
} }
// finally interlace multi-3003 and pairs of 3003 devices which always // finally interlace multi-3003 and pairs of 3003 devices which always
// results to 6 channels per pair of 3003 // results to 6 channels per pair of 3003
{ {
unsigned n = (int)Multi3003DevicesChs.size() / 6; unsigned n = (int)Multi3003DevicesChs.size() / 6;
for ( unsigned i = 0; (i < 6) && (n != 0); i++ ) for ( unsigned i = 0; (i < 6) && (n != 0); i++ )
{ {
for ( unsigned j = 0; j < n; j++ ) for ( unsigned j = 0; j < n; j++ )
{ {
m_Channels.push_back(Multi3003DevicesChs.at((j*6) + i)); m_Channels.push_back(Multi3003DevicesChs.at((j*6) + i));
} }
} }
Multi3003DevicesChs.clear(); Multi3003DevicesChs.clear();
} }
// and finaly the hybrid combination of 3003 / 3000 // and finaly the hybrid combination of 3003 / 3000
{ {
for ( unsigned i = 0; i < Combined3003And3000DeviceChannels.size(); i++ ) for ( unsigned i = 0; i < Combined3003And3000DeviceChannels.size(); i++ )
{ {
m_Channels.push_back(Combined3003And3000DeviceChannels.at(i)); m_Channels.push_back(Combined3003And3000DeviceChannels.at(i));
} }
Combined3003And3000DeviceChannels.clear(); Combined3003And3000DeviceChannels.clear();
} }
// done // done
if ( ok ) if ( ok )
{ {
std::cout << "Codec interfaces initialized successfully : " << iNbCh << " channels available" << std::endl; std::cout << "Codec interfaces initialized successfully : " << iNbCh << " channels available" << std::endl;
} }
else else
{ {
std::cout << "At least one codec interfaces failed to initialize : " << iNbCh << " channels availables" << std::endl; std::cout << "At least one codec interfaces failed to initialize : " << iNbCh << " channels availables" << std::endl;
} }
// done // done
return ok; return ok;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -257,51 +257,51 @@ bool CVocodecs::Init(void)
bool CVocodecs::DiscoverFtdiDevices(void) bool CVocodecs::DiscoverFtdiDevices(void)
{ {
bool ok = false; bool ok = false;
int iNbDevices = 0; int iNbDevices = 0;
FT_DEVICE_LIST_INFO_NODE *list; FT_DEVICE_LIST_INFO_NODE *list;
// clear vector // clear vector
for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) for ( unsigned i = 0; i < m_FtdiDeviceDescrs.size(); i++ )
{ {
delete m_FtdiDeviceDescrs[i]; delete m_FtdiDeviceDescrs[i];
} }
// and discover // and discover
if ( FT_CreateDeviceInfoList((LPDWORD)&iNbDevices) == FT_OK ) if ( FT_CreateDeviceInfoList((LPDWORD)&iNbDevices) == FT_OK )
{ {
std::cout << "Detected " << iNbDevices << " USB-FTDI devices" << std::endl << std::endl; std::cout << "Detected " << iNbDevices << " USB-FTDI devices" << std::endl << std::endl;
ok = true; ok = true;
if ( iNbDevices > 0 ) if ( iNbDevices > 0 )
{ {
// allocate the list // allocate the list
list = new FT_DEVICE_LIST_INFO_NODE[iNbDevices]; list = new FT_DEVICE_LIST_INFO_NODE[iNbDevices];
// fill // fill
if ( FT_GetDeviceInfoList(list, (LPDWORD)&iNbDevices) == FT_OK ) if ( FT_GetDeviceInfoList(list, (LPDWORD)&iNbDevices) == FT_OK )
{ {
// process // process
for ( int i = 0; i < iNbDevices; i++ ) for ( int i = 0; i < iNbDevices; i++ )
{ {
std::cout << "Description : " << list[i].Description << "\t Serial : " << list[i].SerialNumber << std::endl; std::cout << "Description : " << list[i].Description << "\t Serial : " << list[i].SerialNumber << std::endl;
CFtdiDeviceDescr *descr = new CFtdiDeviceDescr( CFtdiDeviceDescr *descr = new CFtdiDeviceDescr(
LOWORD(list[i].ID), HIWORD(list[i].ID), LOWORD(list[i].ID), HIWORD(list[i].ID),
list[i].Description, list[i].SerialNumber); list[i].Description, list[i].SerialNumber);
m_FtdiDeviceDescrs.push_back(descr); m_FtdiDeviceDescrs.push_back(descr);
} }
} }
else else
{ {
ok = false; ok = false;
} }
// and delete // and delete
delete list; delete list;
} }
} }
// done // done
return ok; return ok;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -309,31 +309,31 @@ bool CVocodecs::DiscoverFtdiDevices(void)
CVocodecChannel *CVocodecs::OpenChannel(uint8 uiCodecIn, uint8 uiCodecOut) CVocodecChannel *CVocodecs::OpenChannel(uint8 uiCodecIn, uint8 uiCodecOut)
{ {
CVocodecChannel *Channel = NULL; CVocodecChannel *Channel = NULL;
bool done = false; bool done = false;
// loop on all interface until suitable & available channel found // loop on all interface until suitable & available channel found
m_MutexChannels.lock(); m_MutexChannels.lock();
for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ ) for ( unsigned i = 0; (i < m_Channels.size()) && !done; i++ )
{ {
if ( !m_Channels[i]->IsOpen() && if ( !m_Channels[i]->IsOpen() &&
(m_Channels[i]->GetCodecIn() == uiCodecIn) && (m_Channels[i]->GetCodecIn() == uiCodecIn) &&
(m_Channels[i]->GetCodecOut() == uiCodecOut) ) (m_Channels[i]->GetCodecOut() == uiCodecOut) )
{ {
if ( m_Channels[i]->Open() ) if ( m_Channels[i]->Open() )
{ {
Channel = m_Channels[i]; Channel = m_Channels[i];
done = true; done = true;
} }
} }
} }
m_MutexChannels.unlock(); m_MutexChannels.unlock();
// done // done
return Channel; return Channel;
} }
void CVocodecs::CloseChannel(CVocodecChannel *Channel) void CVocodecs::CloseChannel(CVocodecChannel *Channel)
{ {
Channel->Close(); Channel->Close();
} }

@ -35,43 +35,43 @@
class CVocodecs class CVocodecs
{ {
public: public:
// constructors // constructors
CVocodecs(); CVocodecs();
// destructor // destructor
virtual ~CVocodecs(); virtual ~CVocodecs();
// initialization // initialization
bool Init(void); bool Init(void);
// manage interfaces // manage interfaces
int GetNbInterfaces(void) const { return (int)m_Interfaces.size(); } int GetNbInterfaces(void) const { return (int)m_Interfaces.size(); }
CVocodecInterface *GetInterface(int); CVocodecInterface *GetInterface(int);
// manage channels // manage channels
CVocodecChannel *OpenChannel(uint8, uint8); CVocodecChannel *OpenChannel(uint8, uint8);
void AddChannel(CVocodecChannel *ch) { m_Channels.push_back(ch); } void AddChannel(CVocodecChannel *ch) { m_Channels.push_back(ch); }
void CloseChannel(CVocodecChannel *); void CloseChannel(CVocodecChannel *);
protected: protected:
// initialisation helpers // initialisation helpers
bool DiscoverFtdiDevices(void); bool DiscoverFtdiDevices(void);
// helpers // helpers
bool IsEven(int i) const { return ((i % 2) == 0); } bool IsEven(int i) const { return ((i % 2) == 0); }
bool IsOdd(int i) const { return !IsEven(i); } bool IsOdd(int i) const { return !IsEven(i); }
protected: protected:
// array of interfaces // array of interfaces
std::mutex m_MutexInterfaces; std::mutex m_MutexInterfaces;
std::vector<CVocodecInterface *> m_Interfaces; std::vector<CVocodecInterface *> m_Interfaces;
// array of channels // array of channels
std::mutex m_MutexChannels; std::mutex m_MutexChannels;
std::vector<CVocodecChannel *> m_Channels; std::vector<CVocodecChannel *> m_Channels;
// array of FTDI desciptors // array of FTDI desciptors
std::vector<CFtdiDeviceDescr *> m_FtdiDeviceDescrs; std::vector<CFtdiDeviceDescr *> m_FtdiDeviceDescrs;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -33,22 +33,22 @@
CVoicePacket::CVoicePacket() CVoicePacket::CVoicePacket()
{ {
m_iSize = 0; m_iSize = 0;
::memset(m_uiVoice, 0, sizeof(m_uiVoice)); ::memset(m_uiVoice, 0, sizeof(m_uiVoice));
} }
CVoicePacket::CVoicePacket(const uint8 *voice, int size) CVoicePacket::CVoicePacket(const uint8 *voice, int size)
{ {
m_iSize = MIN(size, sizeof(m_uiVoice)); m_iSize = MIN(size, sizeof(m_uiVoice));
::memset(m_uiVoice, 0, sizeof(m_uiVoice)); ::memset(m_uiVoice, 0, sizeof(m_uiVoice));
::memcpy(m_uiVoice, voice, m_iSize); ::memcpy(m_uiVoice, voice, m_iSize);
} }
CVoicePacket::CVoicePacket(const CVoicePacket &packet) CVoicePacket::CVoicePacket(const CVoicePacket &packet)
: CPacket(packet) : CPacket(packet)
{ {
m_iSize = packet.m_iSize; m_iSize = packet.m_iSize;
::memcpy(m_uiVoice, packet.m_uiVoice, sizeof(m_uiVoice)); ::memcpy(m_uiVoice, packet.m_uiVoice, sizeof(m_uiVoice));
} }
@ -64,8 +64,8 @@ CVoicePacket::~CVoicePacket()
void CVoicePacket::SetVoice(const uint8 *voice, int size) void CVoicePacket::SetVoice(const uint8 *voice, int size)
{ {
m_iSize = MIN(size, sizeof(m_uiVoice)); m_iSize = MIN(size, sizeof(m_uiVoice));
::memset(m_uiVoice, 0, sizeof(m_uiVoice)); ::memset(m_uiVoice, 0, sizeof(m_uiVoice));
::memcpy(m_uiVoice, voice, m_iSize); ::memcpy(m_uiVoice, voice, m_iSize);
} }

@ -40,28 +40,28 @@
class CVoicePacket : public CPacket class CVoicePacket : public CPacket
{ {
public: public:
// constructors // constructors
CVoicePacket(); CVoicePacket();
CVoicePacket(const uint8 *, int); CVoicePacket(const uint8 *, int);
CVoicePacket(const CVoicePacket &); CVoicePacket(const CVoicePacket &);
// destructor
virtual ~CVoicePacket();
// identity // destructor
bool IsVoice(void) const { return true; } 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: protected:
// data // data
int m_iSize; int m_iSize;
uint8 m_uiVoice[VOICE_SIZEMAX]; uint8 m_uiVoice[VOICE_SIZEMAX];
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

@ -35,24 +35,24 @@
int main() int main()
{ {
// initialize ambeserver // initialize ambeserver
g_AmbeServer.SetListenIp(TRANSCODER_IP); g_AmbeServer.SetListenIp(TRANSCODER_IP);
// and let it run // and let it run
std::cout << "Starting AMBEd " << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_REVISION << std::endl << std::endl; std::cout << "Starting AMBEd " << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_REVISION << std::endl << std::endl;
if ( ! g_AmbeServer.Start() ) if ( ! g_AmbeServer.Start() )
{ {
std::cout << "Error starting AMBEd" << std::endl; std::cout << "Error starting AMBEd" << std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
std::cout << "AMBEd started and listening on " << g_AmbeServer.GetListenIp() << std::endl; std::cout << "AMBEd started and listening on " << g_AmbeServer.GetListenIp() << std::endl;
pause(); // wait for any signal pause(); // wait for any signal
// and wait for end // and wait for end
g_AmbeServer.Stop(); g_AmbeServer.Stop();
std::cout << "AMBEd stopped" << std::endl; std::cout << "AMBEd stopped" << std::endl;
// done // done
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

@ -127,10 +127,12 @@ grid
#if USE_BANDPASSFILTER == 1 #if USE_BANDPASSFILTER == 1
const float FILTER_TAPS[] { 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.05063341f, -0.00060337f, -0.08892498f, -0.02026701f, -0.05940750f, -0.10977641f, 0.03244024f, -0.22304499f,
-0.08892498f, -0.00060337f, -0.05063341f }; 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 #define FILTER_TAPS_LENGTH 19
#endif #endif

@ -35,12 +35,12 @@ CBmClient::CBmClient()
} }
CBmClient::CBmClient(const CCallsign &callsign, const CIp &ip, char reflectorModule) CBmClient::CBmClient(const CCallsign &callsign, const CIp &ip, char reflectorModule)
: CClient(callsign, ip, reflectorModule) : CClient(callsign, ip, reflectorModule)
{ {
} }
CBmClient::CBmClient(const CBmClient &client) CBmClient::CBmClient(const CBmClient &client)
: CClient(client) : CClient(client)
{ {
} }
@ -49,6 +49,6 @@ CBmClient::CBmClient(const CBmClient &client)
bool CBmClient::IsAlive(void) const bool CBmClient::IsAlive(void) const
{ {
return (m_LastKeepaliveTime.DurationSinceNow() < XLX_KEEPALIVE_TIMEOUT); return (m_LastKeepaliveTime.DurationSinceNow() < XLX_KEEPALIVE_TIMEOUT);
} }

@ -39,26 +39,26 @@
class CBmClient : public CClient class CBmClient : public CClient
{ {
public: public:
// constructors // constructors
CBmClient(); CBmClient();
CBmClient(const CCallsign &, const CIp &, char = ' '); CBmClient(const CCallsign &, const CIp &, char = ' ');
CBmClient(const CBmClient &); CBmClient(const CBmClient &);
// destructor // destructor
virtual ~CBmClient() {}; virtual ~CBmClient() {};
// identity // identity
int GetProtocol(void) const { return PROTOCOL_XLX; } int GetProtocol(void) const { return PROTOCOL_XLX; }
int GetProtocolRevision(void) const { return XLX_PROTOCOL_REVISION_2; } int GetProtocolRevision(void) const { return XLX_PROTOCOL_REVISION_2; }
const char *GetProtocolName(void) const { return "XLX"; } const char *GetProtocolName(void) const { return "XLX"; }
int GetCodec(void) const { return CODEC_AMBE2PLUS; } int GetCodec(void) const { return CODEC_AMBE2PLUS; }
bool IsPeer(void) const { return true; } bool IsPeer(void) const { return true; }
// status // status
bool IsAlive(void) const; bool IsAlive(void) const;
// reporting // reporting
void WriteXml(std::ofstream &) {} void WriteXml(std::ofstream &) {}
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -38,16 +38,16 @@ CBmPeer::CBmPeer()
} }
CBmPeer::CBmPeer(const CCallsign &callsign, const CIp &ip, const char *modules, const CVersion &version) 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 // and construct all xlx clients
for ( unsigned i = 0; i < ::strlen(modules); i++ ) for ( unsigned i = 0; i < ::strlen(modules); i++ )
{ {
// create and append to vector // create and append to vector
m_Clients.push_back(std::make_shared<CBmClient>(callsign, ip, modules[i])); m_Clients.push_back(std::make_shared<CBmClient>(callsign, ip, modules[i]));
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -55,7 +55,7 @@ CBmPeer::CBmPeer(const CCallsign &callsign, const CIp &ip, const char *modules,
bool CBmPeer::IsAlive(void) const 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) int CBmPeer::GetProtocolRevision(const CVersion &version)
{ {
return XLX_PROTOCOL_REVISION_2; return XLX_PROTOCOL_REVISION_2;
} }

@ -39,20 +39,20 @@
class CBmPeer : public CPeer class CBmPeer : public CPeer
{ {
public: public:
// constructors // constructors
CBmPeer(); CBmPeer();
CBmPeer(const CCallsign &, const CIp &, const char *, const CVersion &); CBmPeer(const CCallsign &, const CIp &, const char *, const CVersion &);
CBmPeer(const CBmPeer &) = delete; CBmPeer(const CBmPeer &) = delete;
// status // status
bool IsAlive(void) const; bool IsAlive(void) const;
// identity // identity
int GetProtocol(void) const { return PROTOCOL_XLX; } int GetProtocol(void) const { return PROTOCOL_XLX; }
const char *GetProtocolName(void) const { return "XLX"; } const char *GetProtocolName(void) const { return "XLX"; }
// revision helper // revision helper
static int GetProtocolRevision(const CVersion &); static int GetProtocolRevision(const CVersion &);
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -37,305 +37,318 @@ CBPTC19696::~CBPTC19696()
// The main decode function // The main decode function
void CBPTC19696::decode(const unsigned char* in, unsigned char* out) void CBPTC19696::decode(const unsigned char* in, unsigned char* out)
{ {
assert(in != nullptr); assert(in != nullptr);
assert(out != nullptr); assert(out != nullptr);
// Get the raw binary // Get the raw binary
decodeExtractBinary(in); decodeExtractBinary(in);
// Deinterleave // Deinterleave
decodeDeInterleave(); decodeDeInterleave();
// Error check // Error check
decodeErrorCheck(); decodeErrorCheck();
// Extract Data // Extract Data
decodeExtractData(out); decodeExtractData(out);
} }
// The main encode function // The main encode function
void CBPTC19696::encode(const unsigned char* in, unsigned char* out) void CBPTC19696::encode(const unsigned char* in, unsigned char* out)
{ {
assert(in != nullptr); assert(in != nullptr);
assert(out != nullptr); assert(out != nullptr);
// Extract Data // Extract Data
encodeExtractData(in); encodeExtractData(in);
// Error check // Error check
encodeErrorCheck(); encodeErrorCheck();
// Deinterleave // Deinterleave
encodeInterleave(); encodeInterleave();
// Get the raw binary // Get the raw binary
encodeExtractBinary(out); encodeExtractBinary(out);
} }
void CBPTC19696::decodeExtractBinary(const unsigned char* in) void CBPTC19696::decodeExtractBinary(const unsigned char* in)
{ {
// First block // First block
CUtils::byteToBitsBE(in[0U], m_rawData + 0U); CUtils::byteToBitsBE(in[0U], m_rawData + 0U);
CUtils::byteToBitsBE(in[1U], m_rawData + 8U); CUtils::byteToBitsBE(in[1U], m_rawData + 8U);
CUtils::byteToBitsBE(in[2U], m_rawData + 16U); CUtils::byteToBitsBE(in[2U], m_rawData + 16U);
CUtils::byteToBitsBE(in[3U], m_rawData + 24U); CUtils::byteToBitsBE(in[3U], m_rawData + 24U);
CUtils::byteToBitsBE(in[4U], m_rawData + 32U); CUtils::byteToBitsBE(in[4U], m_rawData + 32U);
CUtils::byteToBitsBE(in[5U], m_rawData + 40U); CUtils::byteToBitsBE(in[5U], m_rawData + 40U);
CUtils::byteToBitsBE(in[6U], m_rawData + 48U); CUtils::byteToBitsBE(in[6U], m_rawData + 48U);
CUtils::byteToBitsBE(in[7U], m_rawData + 56U); CUtils::byteToBitsBE(in[7U], m_rawData + 56U);
CUtils::byteToBitsBE(in[8U], m_rawData + 64U); CUtils::byteToBitsBE(in[8U], m_rawData + 64U);
CUtils::byteToBitsBE(in[9U], m_rawData + 72U); CUtils::byteToBitsBE(in[9U], m_rawData + 72U);
CUtils::byteToBitsBE(in[10U], m_rawData + 80U); CUtils::byteToBitsBE(in[10U], m_rawData + 80U);
CUtils::byteToBitsBE(in[11U], m_rawData + 88U); CUtils::byteToBitsBE(in[11U], m_rawData + 88U);
CUtils::byteToBitsBE(in[12U], m_rawData + 96U); CUtils::byteToBitsBE(in[12U], m_rawData + 96U);
// Handle the two bits // Handle the two bits
bool bits[8U]; bool bits[8U];
CUtils::byteToBitsBE(in[20U], bits); CUtils::byteToBitsBE(in[20U], bits);
m_rawData[98U] = bits[6U]; m_rawData[98U] = bits[6U];
m_rawData[99U] = bits[7U]; m_rawData[99U] = bits[7U];
// Second block // Second block
CUtils::byteToBitsBE(in[21U], m_rawData + 100U); CUtils::byteToBitsBE(in[21U], m_rawData + 100U);
CUtils::byteToBitsBE(in[22U], m_rawData + 108U); CUtils::byteToBitsBE(in[22U], m_rawData + 108U);
CUtils::byteToBitsBE(in[23U], m_rawData + 116U); CUtils::byteToBitsBE(in[23U], m_rawData + 116U);
CUtils::byteToBitsBE(in[24U], m_rawData + 124U); CUtils::byteToBitsBE(in[24U], m_rawData + 124U);
CUtils::byteToBitsBE(in[25U], m_rawData + 132U); CUtils::byteToBitsBE(in[25U], m_rawData + 132U);
CUtils::byteToBitsBE(in[26U], m_rawData + 140U); CUtils::byteToBitsBE(in[26U], m_rawData + 140U);
CUtils::byteToBitsBE(in[27U], m_rawData + 148U); CUtils::byteToBitsBE(in[27U], m_rawData + 148U);
CUtils::byteToBitsBE(in[28U], m_rawData + 156U); CUtils::byteToBitsBE(in[28U], m_rawData + 156U);
CUtils::byteToBitsBE(in[29U], m_rawData + 164U); CUtils::byteToBitsBE(in[29U], m_rawData + 164U);
CUtils::byteToBitsBE(in[30U], m_rawData + 172U); CUtils::byteToBitsBE(in[30U], m_rawData + 172U);
CUtils::byteToBitsBE(in[31U], m_rawData + 180U); CUtils::byteToBitsBE(in[31U], m_rawData + 180U);
CUtils::byteToBitsBE(in[32U], m_rawData + 188U); CUtils::byteToBitsBE(in[32U], m_rawData + 188U);
} }
// Deinterleave the raw data // Deinterleave the raw data
void CBPTC19696::decodeDeInterleave() void CBPTC19696::decodeDeInterleave()
{ {
for (unsigned int i = 0U; i < 196U; i++) for (unsigned int i = 0U; i < 196U; i++)
m_deInterData[i] = false; m_deInterData[i] = false;
// The first bit is R(3) which is not used so can be ignored // The first bit is R(3) which is not used so can be ignored
for (unsigned int a = 0U; a < 196U; a++) { for (unsigned int a = 0U; a < 196U; a++)
// Calculate the interleave sequence {
unsigned int interleaveSequence = (a * 181U) % 196U; // Calculate the interleave sequence
// Shuffle the data unsigned int interleaveSequence = (a * 181U) % 196U;
m_deInterData[a] = m_rawData[interleaveSequence]; // 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 // Check each row with a Hamming (15,11,3) code and each column with a Hamming (13,9,3) code
void CBPTC19696::decodeErrorCheck() void CBPTC19696::decodeErrorCheck()
{ {
bool fixing; bool fixing;
unsigned int count = 0U; unsigned int count = 0U;
do { do
fixing = false; {
fixing = false;
// Run through each of the 15 columns
bool col[13U]; // Run through each of the 15 columns
for (unsigned int c = 0U; c < 15U; c++) { bool col[13U];
unsigned int pos = c + 1U; for (unsigned int c = 0U; c < 15U; c++)
for (unsigned int a = 0U; a < 13U; a++) { {
col[a] = m_deInterData[pos]; unsigned int pos = c + 1U;
pos = pos + 15U; for (unsigned int a = 0U; a < 13U; a++)
} {
col[a] = m_deInterData[pos];
if (CHamming::decode1393(col)) { pos = pos + 15U;
unsigned int pos = c + 1U; }
for (unsigned int a = 0U; a < 13U; a++) {
m_deInterData[pos] = col[a]; if (CHamming::decode1393(col))
pos = pos + 15U; {
} unsigned int pos = c + 1U;
for (unsigned int a = 0U; a < 13U; a++)
fixing = true; {
} 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++) { fixing = true;
unsigned int pos = (r * 15U) + 1U; }
if (CHamming::decode15113_2(m_deInterData + pos)) }
fixing = true;
} // Run through each of the 9 rows containing data
for (unsigned int r = 0U; r < 9U; r++)
count++; {
} while (fixing && count < 5U); 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 // Extract the 96 bits of payload
void CBPTC19696::decodeExtractData(unsigned char* data) const void CBPTC19696::decodeExtractData(unsigned char* data) const
{ {
bool bData[96U]; bool bData[96U];
unsigned int pos = 0U; unsigned int pos = 0U;
for (unsigned int a = 4U; a <= 11U; a++, pos++) for (unsigned int a = 4U; a <= 11U; a++, pos++)
bData[pos] = m_deInterData[a]; bData[pos] = m_deInterData[a];
for (unsigned int a = 16U; a <= 26U; a++, pos++) for (unsigned int a = 16U; a <= 26U; a++, pos++)
bData[pos] = m_deInterData[a]; bData[pos] = m_deInterData[a];
for (unsigned int a = 31U; a <= 41U; a++, pos++) for (unsigned int a = 31U; a <= 41U; a++, pos++)
bData[pos] = m_deInterData[a]; bData[pos] = m_deInterData[a];
for (unsigned int a = 46U; a <= 56U; a++, pos++) for (unsigned int a = 46U; a <= 56U; a++, pos++)
bData[pos] = m_deInterData[a]; bData[pos] = m_deInterData[a];
for (unsigned int a = 61U; a <= 71U; a++, pos++) for (unsigned int a = 61U; a <= 71U; a++, pos++)
bData[pos] = m_deInterData[a]; bData[pos] = m_deInterData[a];
for (unsigned int a = 76U; a <= 86U; a++, pos++) for (unsigned int a = 76U; a <= 86U; a++, pos++)
bData[pos] = m_deInterData[a]; bData[pos] = m_deInterData[a];
for (unsigned int a = 91U; a <= 101U; a++, pos++) for (unsigned int a = 91U; a <= 101U; a++, pos++)
bData[pos] = m_deInterData[a]; bData[pos] = m_deInterData[a];
for (unsigned int a = 106U; a <= 116U; a++, pos++) for (unsigned int a = 106U; a <= 116U; a++, pos++)
bData[pos] = m_deInterData[a]; bData[pos] = m_deInterData[a];
for (unsigned int a = 121U; a <= 131U; a++, pos++) for (unsigned int a = 121U; a <= 131U; a++, pos++)
bData[pos] = m_deInterData[a]; bData[pos] = m_deInterData[a];
CUtils::bitsToByteBE(bData + 0U, data[0U]); CUtils::bitsToByteBE(bData + 0U, data[0U]);
CUtils::bitsToByteBE(bData + 8U, data[1U]); CUtils::bitsToByteBE(bData + 8U, data[1U]);
CUtils::bitsToByteBE(bData + 16U, data[2U]); CUtils::bitsToByteBE(bData + 16U, data[2U]);
CUtils::bitsToByteBE(bData + 24U, data[3U]); CUtils::bitsToByteBE(bData + 24U, data[3U]);
CUtils::bitsToByteBE(bData + 32U, data[4U]); CUtils::bitsToByteBE(bData + 32U, data[4U]);
CUtils::bitsToByteBE(bData + 40U, data[5U]); CUtils::bitsToByteBE(bData + 40U, data[5U]);
CUtils::bitsToByteBE(bData + 48U, data[6U]); CUtils::bitsToByteBE(bData + 48U, data[6U]);
CUtils::bitsToByteBE(bData + 56U, data[7U]); CUtils::bitsToByteBE(bData + 56U, data[7U]);
CUtils::bitsToByteBE(bData + 64U, data[8U]); CUtils::bitsToByteBE(bData + 64U, data[8U]);
CUtils::bitsToByteBE(bData + 72U, data[9U]); CUtils::bitsToByteBE(bData + 72U, data[9U]);
CUtils::bitsToByteBE(bData + 80U, data[10U]); CUtils::bitsToByteBE(bData + 80U, data[10U]);
CUtils::bitsToByteBE(bData + 88U, data[11U]); CUtils::bitsToByteBE(bData + 88U, data[11U]);
} }
// Extract the 96 bits of payload // Extract the 96 bits of payload
void CBPTC19696::encodeExtractData(const unsigned char* in) void CBPTC19696::encodeExtractData(const unsigned char* in)
{ {
bool bData[96U]; bool bData[96U];
CUtils::byteToBitsBE(in[0U], bData + 0U); CUtils::byteToBitsBE(in[0U], bData + 0U);
CUtils::byteToBitsBE(in[1U], bData + 8U); CUtils::byteToBitsBE(in[1U], bData + 8U);
CUtils::byteToBitsBE(in[2U], bData + 16U); CUtils::byteToBitsBE(in[2U], bData + 16U);
CUtils::byteToBitsBE(in[3U], bData + 24U); CUtils::byteToBitsBE(in[3U], bData + 24U);
CUtils::byteToBitsBE(in[4U], bData + 32U); CUtils::byteToBitsBE(in[4U], bData + 32U);
CUtils::byteToBitsBE(in[5U], bData + 40U); CUtils::byteToBitsBE(in[5U], bData + 40U);
CUtils::byteToBitsBE(in[6U], bData + 48U); CUtils::byteToBitsBE(in[6U], bData + 48U);
CUtils::byteToBitsBE(in[7U], bData + 56U); CUtils::byteToBitsBE(in[7U], bData + 56U);
CUtils::byteToBitsBE(in[8U], bData + 64U); CUtils::byteToBitsBE(in[8U], bData + 64U);
CUtils::byteToBitsBE(in[9U], bData + 72U); CUtils::byteToBitsBE(in[9U], bData + 72U);
CUtils::byteToBitsBE(in[10U], bData + 80U); CUtils::byteToBitsBE(in[10U], bData + 80U);
CUtils::byteToBitsBE(in[11U], bData + 88U); CUtils::byteToBitsBE(in[11U], bData + 88U);
for (unsigned int i = 0U; i < 196U; i++) for (unsigned int i = 0U; i < 196U; i++)
m_deInterData[i] = false; m_deInterData[i] = false;
unsigned int pos = 0U; unsigned int pos = 0U;
for (unsigned int a = 4U; a <= 11U; a++, pos++) for (unsigned int a = 4U; a <= 11U; a++, pos++)
m_deInterData[a] = bData[pos]; m_deInterData[a] = bData[pos];
for (unsigned int a = 16U; a <= 26U; a++, pos++) for (unsigned int a = 16U; a <= 26U; a++, pos++)
m_deInterData[a] = bData[pos]; m_deInterData[a] = bData[pos];
for (unsigned int a = 31U; a <= 41U; a++, pos++) for (unsigned int a = 31U; a <= 41U; a++, pos++)
m_deInterData[a] = bData[pos]; m_deInterData[a] = bData[pos];
for (unsigned int a = 46U; a <= 56U; a++, pos++) for (unsigned int a = 46U; a <= 56U; a++, pos++)
m_deInterData[a] = bData[pos]; m_deInterData[a] = bData[pos];
for (unsigned int a = 61U; a <= 71U; a++, pos++) for (unsigned int a = 61U; a <= 71U; a++, pos++)
m_deInterData[a] = bData[pos]; m_deInterData[a] = bData[pos];
for (unsigned int a = 76U; a <= 86U; a++, pos++) for (unsigned int a = 76U; a <= 86U; a++, pos++)
m_deInterData[a] = bData[pos]; m_deInterData[a] = bData[pos];
for (unsigned int a = 91U; a <= 101U; a++, pos++) for (unsigned int a = 91U; a <= 101U; a++, pos++)
m_deInterData[a] = bData[pos]; m_deInterData[a] = bData[pos];
for (unsigned int a = 106U; a <= 116U; a++, pos++) for (unsigned int a = 106U; a <= 116U; a++, pos++)
m_deInterData[a] = bData[pos]; m_deInterData[a] = bData[pos];
for (unsigned int a = 121U; a <= 131U; a++, pos++) for (unsigned int a = 121U; a <= 131U; a++, pos++)
m_deInterData[a] = bData[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 // Check each row with a Hamming (15,11,3) code and each column with a Hamming (13,9,3) code
void CBPTC19696::encodeErrorCheck() void CBPTC19696::encodeErrorCheck()
{ {
// Run through each of the 9 rows containing data // Run through each of the 9 rows containing data
for (unsigned int r = 0U; r < 9U; r++) { for (unsigned int r = 0U; r < 9U; r++)
unsigned int pos = (r * 15U) + 1U; {
CHamming::encode15113_2(m_deInterData + pos); unsigned int pos = (r * 15U) + 1U;
} CHamming::encode15113_2(m_deInterData + pos);
}
// Run through each of the 15 columns
bool col[13U]; // Run through each of the 15 columns
for (unsigned int c = 0U; c < 15U; c++) { bool col[13U];
unsigned int pos = c + 1U; for (unsigned int c = 0U; c < 15U; c++)
for (unsigned int a = 0U; a < 13U; a++) { {
col[a] = m_deInterData[pos]; unsigned int pos = c + 1U;
pos = pos + 15U; for (unsigned int a = 0U; a < 13U; a++)
} {
col[a] = m_deInterData[pos];
CHamming::encode1393(col); pos = pos + 15U;
}
pos = c + 1U;
for (unsigned int a = 0U; a < 13U; a++) { CHamming::encode1393(col);
m_deInterData[pos] = col[a];
pos = pos + 15U; pos = c + 1U;
} for (unsigned int a = 0U; a < 13U; a++)
} {
m_deInterData[pos] = col[a];
pos = pos + 15U;
}
}
} }
// Interleave the raw data // Interleave the raw data
void CBPTC19696::encodeInterleave() void CBPTC19696::encodeInterleave()
{ {
for (unsigned int i = 0U; i < 196U; i++) for (unsigned int i = 0U; i < 196U; i++)
m_rawData[i] = false; m_rawData[i] = false;
// The first bit is R(3) which is not used so can be ignored // The first bit is R(3) which is not used so can be ignored
for (unsigned int a = 0U; a < 196U; a++) { for (unsigned int a = 0U; a < 196U; a++)
// Calculate the interleave sequence {
unsigned int interleaveSequence = (a * 181U) % 196U; // Calculate the interleave sequence
// Unshuffle the data unsigned int interleaveSequence = (a * 181U) % 196U;
m_rawData[interleaveSequence] = m_deInterData[a]; // Unshuffle the data
} m_rawData[interleaveSequence] = m_deInterData[a];
}
} }
void CBPTC19696::encodeExtractBinary(unsigned char* data) void CBPTC19696::encodeExtractBinary(unsigned char* data)
{ {
// First block // First block
CUtils::bitsToByteBE(m_rawData + 0U, data[0U]); CUtils::bitsToByteBE(m_rawData + 0U, data[0U]);
CUtils::bitsToByteBE(m_rawData + 8U, data[1U]); CUtils::bitsToByteBE(m_rawData + 8U, data[1U]);
CUtils::bitsToByteBE(m_rawData + 16U, data[2U]); CUtils::bitsToByteBE(m_rawData + 16U, data[2U]);
CUtils::bitsToByteBE(m_rawData + 24U, data[3U]); CUtils::bitsToByteBE(m_rawData + 24U, data[3U]);
CUtils::bitsToByteBE(m_rawData + 32U, data[4U]); CUtils::bitsToByteBE(m_rawData + 32U, data[4U]);
CUtils::bitsToByteBE(m_rawData + 40U, data[5U]); CUtils::bitsToByteBE(m_rawData + 40U, data[5U]);
CUtils::bitsToByteBE(m_rawData + 48U, data[6U]); CUtils::bitsToByteBE(m_rawData + 48U, data[6U]);
CUtils::bitsToByteBE(m_rawData + 56U, data[7U]); CUtils::bitsToByteBE(m_rawData + 56U, data[7U]);
CUtils::bitsToByteBE(m_rawData + 64U, data[8U]); CUtils::bitsToByteBE(m_rawData + 64U, data[8U]);
CUtils::bitsToByteBE(m_rawData + 72U, data[9U]); CUtils::bitsToByteBE(m_rawData + 72U, data[9U]);
CUtils::bitsToByteBE(m_rawData + 80U, data[10U]); CUtils::bitsToByteBE(m_rawData + 80U, data[10U]);
CUtils::bitsToByteBE(m_rawData + 88U, data[11U]); CUtils::bitsToByteBE(m_rawData + 88U, data[11U]);
// Handle the two bits // Handle the two bits
unsigned char byte; unsigned char byte;
CUtils::bitsToByteBE(m_rawData + 96U, byte); CUtils::bitsToByteBE(m_rawData + 96U, byte);
data[12U] = (data[12U] & 0x3FU) | ((byte >> 0) & 0xC0U); data[12U] = (data[12U] & 0x3FU) | ((byte >> 0) & 0xC0U);
data[20U] = (data[20U] & 0xFCU) | ((byte >> 4) & 0x03U); data[20U] = (data[20U] & 0xFCU) | ((byte >> 4) & 0x03U);
// Second block // Second block
CUtils::bitsToByteBE(m_rawData + 100U, data[21U]); CUtils::bitsToByteBE(m_rawData + 100U, data[21U]);
CUtils::bitsToByteBE(m_rawData + 108U, data[22U]); CUtils::bitsToByteBE(m_rawData + 108U, data[22U]);
CUtils::bitsToByteBE(m_rawData + 116U, data[23U]); CUtils::bitsToByteBE(m_rawData + 116U, data[23U]);
CUtils::bitsToByteBE(m_rawData + 124U, data[24U]); CUtils::bitsToByteBE(m_rawData + 124U, data[24U]);
CUtils::bitsToByteBE(m_rawData + 132U, data[25U]); CUtils::bitsToByteBE(m_rawData + 132U, data[25U]);
CUtils::bitsToByteBE(m_rawData + 140U, data[26U]); CUtils::bitsToByteBE(m_rawData + 140U, data[26U]);
CUtils::bitsToByteBE(m_rawData + 148U, data[27U]); CUtils::bitsToByteBE(m_rawData + 148U, data[27U]);
CUtils::bitsToByteBE(m_rawData + 156U, data[28U]); CUtils::bitsToByteBE(m_rawData + 156U, data[28U]);
CUtils::bitsToByteBE(m_rawData + 164U, data[29U]); CUtils::bitsToByteBE(m_rawData + 164U, data[29U]);
CUtils::bitsToByteBE(m_rawData + 172U, data[30U]); CUtils::bitsToByteBE(m_rawData + 172U, data[30U]);
CUtils::bitsToByteBE(m_rawData + 180U, data[31U]); CUtils::bitsToByteBE(m_rawData + 180U, data[31U]);
CUtils::bitsToByteBE(m_rawData + 188U, data[32U]); CUtils::bitsToByteBE(m_rawData + 188U, data[32U]);
} }

@ -22,26 +22,26 @@
class CBPTC19696 class CBPTC19696
{ {
public: public:
CBPTC19696(); CBPTC19696();
~CBPTC19696(); ~CBPTC19696();
void decode(const unsigned char* in, unsigned char* out); void decode(const unsigned char* in, unsigned char* out);
void encode(const unsigned char* in, unsigned char* out); void encode(const unsigned char* in, unsigned char* out);
private: private:
bool m_rawData[196]; bool m_rawData[196];
bool m_deInterData[196]; bool m_deInterData[196];
void decodeExtractBinary(const unsigned char* in); void decodeExtractBinary(const unsigned char* in);
void decodeErrorCheck(); void decodeErrorCheck();
void decodeDeInterleave(); void decodeDeInterleave();
void decodeExtractData(unsigned char* data) const; void decodeExtractData(unsigned char* data) const;
void encodeExtractData(const unsigned char* in); void encodeExtractData(const unsigned char* in);
void encodeInterleave(); void encodeInterleave();
void encodeErrorCheck(); void encodeErrorCheck();
void encodeExtractBinary(unsigned char* data); void encodeExtractBinary(unsigned char* data);
}; };
#endif #endif

@ -92,7 +92,8 @@ void CBuffer::Append(const char *sz)
void CBuffer::ReplaceAt(int i, uint8_t ui) 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)); m_data.resize(i+sizeof(uint8_t));
} }
*(uint8_t *)(&(m_data.data()[i])) = ui; *(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) 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)); m_data.resize(i+sizeof(uint16_t));
} }
*(uint16_t *)(&(m_data.data()[i])) = ui; *(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) 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)); m_data.resize(i+sizeof(uint32_t));
} }
*(uint32_t *)(&(m_data.data()[i])) = ui; *(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) 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); m_data.resize(i+len);
} }
::memcpy(&(m_data.data()[i]), ptr, 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 CBuffer::Compare(uint8_t *buffer, int len) const
{ {
int result = -1; int result = -1;
if ( m_data.size() >= unsigned(len) ) { if ( m_data.size() >= unsigned(len) )
{
result = ::memcmp(m_data.data(), buffer, len); result = ::memcmp(m_data.data(), buffer, len);
} }
return result; 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 CBuffer::Compare(uint8_t *buffer, int off, int len) const
{ {
int result = -1; 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); result = ::memcmp(&(m_data.data()[off]), buffer, len);
} }
return result; return result;
@ -149,7 +155,8 @@ int CBuffer::Compare(uint8_t *buffer, int off, int len) const
bool CBuffer::operator ==(const CBuffer &Buffer) 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 (::memcmp((const char *)m_data.data(), (const char *)Buffer.m_data.data(), m_data.size()) == 0);
} }
return false; return false;
@ -157,7 +164,8 @@ bool CBuffer::operator ==(const CBuffer &Buffer) const
bool CBuffer::operator ==(const char *sz) 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 (::memcmp((const char *)m_data.data(), sz, m_data.size()) == 0);
} }
return false; return false;
@ -174,14 +182,18 @@ CBuffer::operator const char *() const
void CBuffer::DebugDump(std::ofstream &debugout) const void CBuffer::DebugDump(std::ofstream &debugout) const
{ {
// dump an hex line // 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]; char sz[16];
//sprintf(sz, "%02X", m_data.data()[i]); //sprintf(sz, "%02X", m_data.data()[i]);
sprintf(sz, "0x%02X", m_data.data()[i]); sprintf(sz, "0x%02X", m_data.data()[i]);
debugout << sz; debugout << sz;
if ( i == m_data.size()-1 ) { if ( i == m_data.size()-1 )
{
debugout << std::endl; debugout << std::endl;
} else { }
else
{
debugout << ','; debugout << ',';
} }
} }
@ -190,14 +202,19 @@ void CBuffer::DebugDump(std::ofstream &debugout) const
void CBuffer::DebugDumpAscii(std::ofstream &debugout) const void CBuffer::DebugDumpAscii(std::ofstream &debugout) const
{ {
// dump an ascii line // 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]; char c = m_data.data()[i];
if ( isascii(c) ) { if ( isascii(c) )
{
debugout << c; debugout << c;
} else { }
else
{
debugout << '.'; debugout << '.';
} }
if ( i == m_data.size()-1 ) { if ( i == m_data.size()-1 )
{
debugout << std::endl; debugout << std::endl;
} }
} }

@ -34,49 +34,49 @@
CCallsign::CCallsign() CCallsign::CCallsign()
{ {
// blank all // blank all
::memset(m_Callsign, ' ', sizeof(m_Callsign)); ::memset(m_Callsign, ' ', sizeof(m_Callsign));
::memset(m_Suffix, ' ', sizeof(m_Suffix)); ::memset(m_Suffix, ' ', sizeof(m_Suffix));
m_Module = ' '; m_Module = ' ';
#ifndef NO_XLX #ifndef NO_XLX
m_uiDmrid = 0; m_uiDmrid = 0;
#endif #endif
} }
CCallsign::CCallsign(const char *sz, uint32 dmrid) CCallsign::CCallsign(const char *sz, uint32 dmrid)
{ {
// blank all // blank all
::memset(m_Callsign, ' ', sizeof(m_Callsign)); ::memset(m_Callsign, ' ', sizeof(m_Callsign));
::memset(m_Suffix, ' ', sizeof(m_Suffix)); ::memset(m_Suffix, ' ', sizeof(m_Suffix));
m_Module = ' '; m_Module = ' ';
#ifndef NO_XLX #ifndef NO_XLX
m_uiDmrid = dmrid; m_uiDmrid = dmrid;
#endif #endif
// and populate // and populate
if ( ::strlen(sz) > 0 ) if ( ::strlen(sz) > 0 )
{ {
// callsign valid // callsign valid
::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign)-1)); ::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign)-1));
if ( strlen(sz) >= sizeof(m_Callsign) ) if ( strlen(sz) >= sizeof(m_Callsign) )
{ {
m_Module = sz[sizeof(m_Callsign)-1]; m_Module = sz[sizeof(m_Callsign)-1];
} }
#ifndef NO_XLX #ifndef NO_XLX
// dmrid ok ? // dmrid ok ?
if ( m_uiDmrid == 0 ) if ( m_uiDmrid == 0 )
{ {
g_DmridDir.Lock(); g_DmridDir.Lock();
{ {
m_uiDmrid = g_DmridDir.FindDmrid(*this); m_uiDmrid = g_DmridDir.FindDmrid(*this);
} }
g_DmridDir.Unlock(); g_DmridDir.Unlock();
} }
} }
else if ( m_uiDmrid != 0 ) else if ( m_uiDmrid != 0 )
{ {
g_DmridDir.Lock(); g_DmridDir.Lock();
{ {
const CCallsign *callsign = g_DmridDir.FindCallsign(m_uiDmrid); const CCallsign *callsign = g_DmridDir.FindCallsign(m_uiDmrid);
if ( callsign != nullptr ) if ( callsign != nullptr )
{ {
@ -85,7 +85,7 @@ CCallsign::CCallsign(const char *sz, uint32 dmrid)
} }
g_DmridDir.Unlock(); g_DmridDir.Unlock();
#endif #endif
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -93,53 +93,53 @@ CCallsign::CCallsign(const char *sz, uint32 dmrid)
bool CCallsign::IsValid(void) const bool CCallsign::IsValid(void) const
{ {
bool valid = true; bool valid = true;
int i; int i;
// callsign // callsign
// first 3 chars are letter or number but cannot be all number // first 3 chars are letter or number but cannot be all number
int iNum = 0; int iNum = 0;
for ( i = 0; i < 3; i++ ) for ( i = 0; i < 3; i++ )
{ {
valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]); valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]);
if ( IsNumber(m_Callsign[i]) ) if ( IsNumber(m_Callsign[i]) )
{ {
iNum++; iNum++;
} }
} }
valid &= (iNum < 3); valid &= (iNum < 3);
// all remaining char are letter, number or space // all remaining char are letter, number or space
for ( ; i < CALLSIGN_LEN; i++) for ( ; i < CALLSIGN_LEN; i++)
{ {
valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]) || IsSpace(m_Callsign[i]); valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]) || IsSpace(m_Callsign[i]);
} }
// prefix // prefix
// all chars are number, uppercase or space // all chars are number, uppercase or space
for ( i = 0; i < CALLSUFFIX_LEN; i++ ) for ( i = 0; i < CALLSUFFIX_LEN; i++ )
{ {
valid &= IsLetter(m_Suffix[i]) || IsNumber(m_Suffix[i]) || IsSpace(m_Suffix[i]); valid &= IsLetter(m_Suffix[i]) || IsNumber(m_Suffix[i]) || IsSpace(m_Suffix[i]);
} }
// module // module
// is an letter or space // is an letter or space
valid &= IsLetter(m_Module) || IsSpace(m_Module); valid &= IsLetter(m_Module) || IsSpace(m_Module);
// dmrid is not tested, as it can be nullptr // dmrid is not tested, as it can be nullptr
// if station does is not dmr registered // if station does is not dmr registered
// done // done
return valid; return valid;
} }
bool CCallsign::HasSuffix(void) const bool CCallsign::HasSuffix(void) const
{ {
bool has = false; bool has = false;
for ( int i = 0; i < CALLSUFFIX_LEN; i++ ) for ( int i = 0; i < CALLSUFFIX_LEN; i++ )
{ {
has |= (m_Suffix[i] != ' '); has |= (m_Suffix[i] != ' ');
} }
return has; return has;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -147,64 +147,64 @@ bool CCallsign::HasSuffix(void) const
void CCallsign::SetCallsign(const char *sz, bool UpdateDmrid) void CCallsign::SetCallsign(const char *sz, bool UpdateDmrid)
{ {
// set callsign // set callsign
::memset(m_Callsign, ' ', sizeof(m_Callsign)); ::memset(m_Callsign, ' ', sizeof(m_Callsign));
m_Module = ' '; m_Module = ' ';
::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign)-1)); ::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign)-1));
if ( strlen(sz) >= sizeof(m_Callsign) ) if ( strlen(sz) >= sizeof(m_Callsign) )
{ {
m_Module = sz[sizeof(m_Callsign)-1]; m_Module = sz[sizeof(m_Callsign)-1];
} }
#ifndef NO_XLX #ifndef NO_XLX
// and update dmrid // and update dmrid
if ( UpdateDmrid ) if ( UpdateDmrid )
{ {
g_DmridDir.Lock(); g_DmridDir.Lock();
{ {
m_uiDmrid = g_DmridDir.FindDmrid(*this); m_uiDmrid = g_DmridDir.FindDmrid(*this);
} }
g_DmridDir.Unlock(); g_DmridDir.Unlock();
} }
#endif #endif
} }
void CCallsign::SetCallsign(const uint8 *buffer, int len, bool UpdateDmrid) void CCallsign::SetCallsign(const uint8 *buffer, int len, bool UpdateDmrid)
{ {
// set callsign // set callsign
::memset(m_Callsign, ' ', sizeof(m_Callsign)); ::memset(m_Callsign, ' ', sizeof(m_Callsign));
m_Module = ' '; m_Module = ' ';
::memcpy(m_Callsign, buffer, MIN(len, sizeof(m_Callsign)-1)); ::memcpy(m_Callsign, buffer, MIN(len, sizeof(m_Callsign)-1));
for ( unsigned i = 0; i < sizeof(m_Callsign); i++ ) for ( unsigned i = 0; i < sizeof(m_Callsign); i++ )
{ {
if ( m_Callsign[i] == 0 ) if ( m_Callsign[i] == 0 )
{ {
m_Callsign[i] = ' '; m_Callsign[i] = ' ';
} }
} }
if ( (len >= (int)sizeof(m_Callsign)) && ((char)buffer[sizeof(m_Callsign)-1] != 0) ) if ( (len >= (int)sizeof(m_Callsign)) && ((char)buffer[sizeof(m_Callsign)-1] != 0) )
{ {
m_Module = (char)buffer[sizeof(m_Callsign)-1]; m_Module = (char)buffer[sizeof(m_Callsign)-1];
} }
#ifndef NO_XLX #ifndef NO_XLX
if ( UpdateDmrid ) if ( UpdateDmrid )
{ {
g_DmridDir.Lock(); g_DmridDir.Lock();
{ {
m_uiDmrid = g_DmridDir.FindDmrid(*this); m_uiDmrid = g_DmridDir.FindDmrid(*this);
} }
g_DmridDir.Unlock(); g_DmridDir.Unlock();
} }
#endif #endif
} }
#ifndef NO_XLX #ifndef NO_XLX
void CCallsign::SetDmrid(uint32 dmrid, bool UpdateCallsign) void CCallsign::SetDmrid(uint32 dmrid, bool UpdateCallsign)
{ {
m_uiDmrid = dmrid; m_uiDmrid = dmrid;
if ( UpdateCallsign ) if ( UpdateCallsign )
{ {
g_DmridDir.Lock(); g_DmridDir.Lock();
{ {
const CCallsign *callsign = g_DmridDir.FindCallsign(dmrid); const CCallsign *callsign = g_DmridDir.FindCallsign(dmrid);
if ( callsign != nullptr ) if ( callsign != nullptr )
{ {
@ -212,35 +212,35 @@ void CCallsign::SetDmrid(uint32 dmrid, bool UpdateCallsign)
} }
} }
g_DmridDir.Unlock(); g_DmridDir.Unlock();
} }
} }
void CCallsign::SetDmrid(const uint8 *buffer, bool UpdateCallsign) void CCallsign::SetDmrid(const uint8 *buffer, bool UpdateCallsign)
{ {
char sz[9]; char sz[9];
::memcpy(sz, buffer, 8); ::memcpy(sz, buffer, 8);
sz[8] = 0; sz[8] = 0;
SetDmrid((uint32)::strtol(sz, nullptr, 16), UpdateCallsign); SetDmrid((uint32)::strtol(sz, nullptr, 16), UpdateCallsign);
} }
#endif #endif
void CCallsign::SetModule(char c) void CCallsign::SetModule(char c)
{ {
m_Module = c; m_Module = c;
} }
void CCallsign::SetSuffix(const char *sz) void CCallsign::SetSuffix(const char *sz)
{ {
::memset(m_Suffix, ' ', sizeof(m_Suffix)); ::memset(m_Suffix, ' ', sizeof(m_Suffix));
::memcpy(m_Suffix, sz, MIN(strlen(sz), sizeof(m_Suffix))); ::memcpy(m_Suffix, sz, MIN(strlen(sz), sizeof(m_Suffix)));
} }
void CCallsign::SetSuffix(const uint8 *buffer, int len) void CCallsign::SetSuffix(const uint8 *buffer, int len)
{ {
len = MIN(len, sizeof(m_Suffix)); len = MIN(len, sizeof(m_Suffix));
::memset(m_Suffix, ' ', sizeof(m_Suffix)); ::memset(m_Suffix, ' ', sizeof(m_Suffix));
::memcpy(m_Suffix, buffer, len); ::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) void CCallsign::PatchCallsign(int off, const uint8 *patch, int len)
{ {
if ( off < CALLSIGN_LEN ) if ( off < CALLSIGN_LEN )
{ {
::memcpy(m_Callsign, patch, MIN(len, sizeof(m_Callsign) - off)); ::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 void CCallsign::GetCallsign(uint8 *buffer) const
{ {
::memcpy(buffer, m_Callsign, sizeof(m_Callsign)); ::memcpy(buffer, m_Callsign, sizeof(m_Callsign));
if ( HasModule() ) if ( HasModule() )
{ {
buffer[sizeof(m_Callsign)-1] = m_Module; buffer[sizeof(m_Callsign)-1] = m_Module;
} }
} }
void CCallsign::GetCallsignString(char *sz) const void CCallsign::GetCallsignString(char *sz) const
{ {
unsigned i; unsigned i;
for ( i = 0; (i < sizeof(m_Callsign)) && (m_Callsign[i] != ' '); i++ ) for ( i = 0; (i < sizeof(m_Callsign)) && (m_Callsign[i] != ' '); i++ )
{ {
sz[i] = m_Callsign[i]; sz[i] = m_Callsign[i];
} }
sz[i] = 0; sz[i] = 0;
} }
void CCallsign::GetSuffix(uint8 *buffer) const 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 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 CCallsign::HasSameCallsignWithWildcard(const CCallsign &callsign) const
{ {
bool same = true; bool same = true;
bool done = false; bool done = false;
for ( unsigned i = 0; (i < sizeof(m_Callsign)) && same && !done; i++ ) for ( unsigned i = 0; (i < sizeof(m_Callsign)) && same && !done; i++ )
{ {
if ( !(done = ((m_Callsign[i] == '*') || (callsign[i] == '*'))) ) if ( !(done = ((m_Callsign[i] == '*') || (callsign[i] == '*'))) )
{ {
same &= (m_Callsign[i] == callsign[i]); same &= (m_Callsign[i] == callsign[i]);
} }
} }
return same; return same;
} }
bool CCallsign::HasLowerCallsign(const CCallsign &Callsign) const 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 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 bool CCallsign::operator ==(const CCallsign &callsign) const
{ {
return ((::memcmp(callsign.m_Callsign, m_Callsign, sizeof(m_Callsign)) == 0) && (m_Module == callsign.m_Module) 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) && (::memcmp(callsign.m_Suffix, m_Suffix, sizeof(m_Suffix)) == 0)
#ifndef NO_XLX #ifndef NO_XLX
&& (m_uiDmrid == callsign.m_uiDmrid) && (m_uiDmrid == callsign.m_uiDmrid)
#endif #endif
); );
} }
CCallsign::operator const char *() const CCallsign::operator const char *() const
@ -335,23 +335,23 @@ CCallsign::operator const char *() const
// empty // empty
::memset(sz, 0, sizeof(m_sz)); ::memset(sz, 0, sizeof(m_sz));
// callsign // callsign
sz[CALLSIGN_LEN] = 0; sz[CALLSIGN_LEN] = 0;
::memcpy(sz, m_Callsign, sizeof(m_Callsign)); ::memcpy(sz, m_Callsign, sizeof(m_Callsign));
// module // module
if ( HasModule() ) if ( HasModule() )
{ {
sz[sizeof(m_Callsign)] = m_Module; sz[sizeof(m_Callsign)] = m_Module;
} }
// suffix // suffix
if ( HasSuffix() ) if ( HasSuffix() )
{ {
::strcat(sz, " / "); ::strcat(sz, " / ");
::strncat(sz, m_Suffix, sizeof(m_Suffix)); ::strncat(sz, m_Suffix, sizeof(m_Suffix));
} }
// done // done
return m_sz; return m_sz;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -359,15 +359,15 @@ CCallsign::operator const char *() const
bool CCallsign::IsNumber(char c) const bool CCallsign::IsNumber(char c) const
{ {
return ((c >= '0') && (c <= '9')); return ((c >= '0') && (c <= '9'));
} }
bool CCallsign::IsLetter(char c) const bool CCallsign::IsLetter(char c) const
{ {
return ((c >= 'A') && (c <= 'Z')); return ((c >= 'A') && (c <= 'Z'));
} }
bool CCallsign::IsSpace(char c) const bool CCallsign::IsSpace(char c) const
{ {
return (c == ' '); return (c == ' ');
} }

@ -38,62 +38,62 @@
class CCallsign class CCallsign
{ {
public: public:
// contructors // contructors
CCallsign(); CCallsign();
CCallsign(const char *, uint32 = 0); CCallsign(const char *, uint32 = 0);
// status // status
bool IsValid(void) const; bool IsValid(void) const;
bool HasSuffix(void) const; bool HasSuffix(void) const;
bool HasModule(void) const { return m_Module != ' '; } bool HasModule(void) const { return m_Module != ' '; }
// set // set
void SetCallsign(const char *, bool = true); void SetCallsign(const char *, bool = true);
void SetCallsign(const uint8 *, int, bool = true); void SetCallsign(const uint8 *, int, bool = true);
#ifndef NO_XLX #ifndef NO_XLX
void SetDmrid(uint32, bool = true); void SetDmrid(uint32, bool = true);
void SetDmrid(const uint8 *, bool = true); void SetDmrid(const uint8 *, bool = true);
#endif #endif
void SetModule(char); void SetModule(char);
void SetSuffix(const char *); void SetSuffix(const char *);
void SetSuffix(const uint8 *, int); void SetSuffix(const uint8 *, int);
// modify // modify
void PatchCallsign(int, const uint8 *, int); void PatchCallsign(int, const uint8 *, int);
// get // get
void GetCallsign(uint8 *) const; void GetCallsign(uint8 *) const;
void GetCallsignString(char *) const; void GetCallsignString(char *) const;
#ifndef NO_XLX #ifndef NO_XLX
uint32 GetDmrid(void) const { return m_uiDmrid; } uint32 GetDmrid(void) const { return m_uiDmrid; }
#endif #endif
void GetSuffix(uint8 *) const; void GetSuffix(uint8 *) const;
char GetModule(void) const { return m_Module; } char GetModule(void) const { return m_Module; }
// compare // compare
bool HasSameCallsign(const CCallsign &) const; bool HasSameCallsign(const CCallsign &) const;
bool HasSameCallsignWithWildcard(const CCallsign &) const; bool HasSameCallsignWithWildcard(const CCallsign &) const;
bool HasLowerCallsign(const CCallsign &) const; bool HasLowerCallsign(const CCallsign &) const;
bool HasSameModule(const CCallsign &) const; bool HasSameModule(const CCallsign &) const;
// operators // operators
bool operator ==(const CCallsign &) const; bool operator ==(const CCallsign &) const;
operator const char *() const; operator const char *() const;
protected: protected:
// helper // helper
bool IsNumber(char) const; bool IsNumber(char) const;
bool IsLetter(char) const; bool IsLetter(char) const;
bool IsSpace(char) const; bool IsSpace(char) const;
protected: protected:
// data // data
char m_Callsign[CALLSIGN_LEN]; char m_Callsign[CALLSIGN_LEN];
char m_Suffix[CALLSUFFIX_LEN]; char m_Suffix[CALLSUFFIX_LEN];
char m_Module; char m_Module;
char m_sz[CALLSIGN_LEN+CALLSUFFIX_LEN+5]; char m_sz[CALLSIGN_LEN+CALLSUFFIX_LEN+5];
#ifndef NO_XLX #ifndef NO_XLX
uint32 m_uiDmrid; uint32 m_uiDmrid;
#endif #endif
}; };

@ -34,8 +34,8 @@
CCallsignList::CCallsignList() CCallsignList::CCallsignList()
{ {
m_Filename = nullptr; m_Filename = nullptr;
::memset(&m_LastModTime, 0, sizeof(time_t)); ::memset(&m_LastModTime, 0, sizeof(time_t));
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -43,86 +43,86 @@ CCallsignList::CCallsignList()
bool CCallsignList::LoadFromFile(const char *filename) bool CCallsignList::LoadFromFile(const char *filename)
{ {
bool ok = false; bool ok = false;
char sz[256]; char sz[256];
char szStar[2] = "*"; char szStar[2] = "*";
// and load // and load
std::ifstream file (filename); std::ifstream file (filename);
if ( file.is_open() ) if ( file.is_open() )
{ {
Lock(); Lock();
// empty list // empty list
m_Callsigns.clear(); m_Callsigns.clear();
// fill with file content // fill with file content
while ( file.getline(sz, sizeof(sz)).good() ) while ( file.getline(sz, sizeof(sz)).good() )
{ {
// remove leading & trailing spaces // remove leading & trailing spaces
char *szt = TrimWhiteSpaces(sz); char *szt = TrimWhiteSpaces(sz);
// crack it // crack it
if ( (::strlen(szt) > 0) && (szt[0] != '#') ) if ( (::strlen(szt) > 0) && (szt[0] != '#') )
{ {
// 1st token is callsign // 1st token is callsign
if ( (szt = ::strtok(szt, " ,\t")) != nullptr ) if ( (szt = ::strtok(szt, " ,\t")) != nullptr )
{ {
CCallsign callsign(szt); CCallsign callsign(szt);
// 2nd token is modules list // 2nd token is modules list
szt = ::strtok(nullptr, " ,\t"); szt = ::strtok(nullptr, " ,\t");
// if token absent, use wildcard // if token absent, use wildcard
if ( szt == nullptr ) if ( szt == nullptr )
{ {
szt = szStar; szt = szStar;
} }
// and add to list // and add to list
m_Callsigns.push_back(CCallsignListItem(callsign, CIp(), szt)); m_Callsigns.push_back(CCallsignListItem(callsign, CIp(), szt));
} }
} }
} }
// close file // close file
file.close(); file.close();
// keep file path // keep file path
m_Filename = filename; m_Filename = filename;
// update time // update time
GetLastModTime(&m_LastModTime); GetLastModTime(&m_LastModTime);
// and done // and done
Unlock(); Unlock();
ok = true; ok = true;
std::cout << "Gatekeeper loaded " << m_Callsigns.size() << " lines from " << filename << std::endl; std::cout << "Gatekeeper loaded " << m_Callsigns.size() << " lines from " << filename << std::endl;
} }
else else
{ {
std::cout << "Gatekeeper cannot find " << filename << std::endl; std::cout << "Gatekeeper cannot find " << filename << std::endl;
} }
return ok; return ok;
} }
bool CCallsignList::ReloadFromFile(void) bool CCallsignList::ReloadFromFile(void)
{ {
bool ok = false; bool ok = false;
if ( m_Filename != nullptr ) if ( m_Filename != nullptr )
{ {
ok = LoadFromFile(m_Filename); ok = LoadFromFile(m_Filename);
} }
return ok; return ok;
} }
bool CCallsignList::NeedReload(void) bool CCallsignList::NeedReload(void)
{ {
bool needReload = false; bool needReload = false;
time_t time; time_t time;
if ( GetLastModTime(&time) ) if ( GetLastModTime(&time) )
{ {
needReload = time != m_LastModTime; needReload = time != m_LastModTime;
} }
return needReload; return needReload;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -130,46 +130,46 @@ bool CCallsignList::NeedReload(void)
bool CCallsignList::IsCallsignListedWithWildcard(const CCallsign &callsign) const bool CCallsignList::IsCallsignListedWithWildcard(const CCallsign &callsign) const
{ {
for ( const auto &item : m_Callsigns ) for ( const auto &item : m_Callsigns )
{ {
if (item.HasSameCallsignWithWildcard(callsign)) if (item.HasSameCallsignWithWildcard(callsign))
return true; return true;
} }
return false; return false;
} }
bool CCallsignList::IsCallsignListedWithWildcard(const CCallsign &callsign, char module) const bool CCallsignList::IsCallsignListedWithWildcard(const CCallsign &callsign, char module) const
{ {
for ( const auto &item : m_Callsigns ) for ( const auto &item : m_Callsigns )
{ {
if (item.HasSameCallsignWithWildcard(callsign) && ((module == ' ') || item.HasModuleListed(module)) ) if (item.HasSameCallsignWithWildcard(callsign) && ((module == ' ') || item.HasModuleListed(module)) )
return true; return true;
} }
return false; return false;
} }
bool CCallsignList::IsCallsignListed(const CCallsign &callsign, char module) const bool CCallsignList::IsCallsignListed(const CCallsign &callsign, char module) const
{ {
for ( const auto &item : m_Callsigns ) for ( const auto &item : m_Callsigns )
{ {
if (item.HasSameCallsign(callsign) && item.HasModuleListed(module)) if (item.HasSameCallsign(callsign) && item.HasModuleListed(module))
return true; return true;
} }
return false; return false;
} }
bool CCallsignList::IsCallsignListed(const CCallsign &callsign, char *modules) const bool CCallsignList::IsCallsignListed(const CCallsign &callsign, char *modules) const
{ {
for ( const auto &item : m_Callsigns ) for ( const auto &item : m_Callsigns )
{ {
if (item.HasSameCallsign(callsign) && item.CheckListedModules(modules)) if (item.HasSameCallsign(callsign) && item.CheckListedModules(modules))
return true; 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) CCallsignListItem *CCallsignList::FindListItem(const CCallsign &Callsign)
{ {
for ( auto &item : m_Callsigns ) for ( auto &item : m_Callsigns )
{ {
if ( item.GetCallsign().HasSameCallsign(Callsign) ) if ( item.GetCallsign().HasSameCallsign(Callsign) )
{ {
return &item; return &item;
} }
} }
return nullptr; return nullptr;
} }
@ -194,37 +194,37 @@ CCallsignListItem *CCallsignList::FindListItem(const CCallsign &Callsign)
char *CCallsignList::TrimWhiteSpaces(char *str) char *CCallsignList::TrimWhiteSpaces(char *str)
{ {
char *end; char *end;
// Trim leading space & tabs // Trim leading space & tabs
while((*str == ' ') || (*str == '\t')) str++; while((*str == ' ') || (*str == '\t')) str++;
// All spaces? // All spaces?
if(*str == 0) if(*str == 0)
return str; return str;
// Trim trailing space, tab or lf // Trim trailing space, tab or lf
end = str + ::strlen(str) - 1; end = str + ::strlen(str) - 1;
while((end > str) && ((*end == ' ') || (*end == '\t') || (*end == '\r'))) end--; while((end > str) && ((*end == ' ') || (*end == '\t') || (*end == '\r'))) end--;
// Write new null terminator // Write new null terminator
*(end+1) = 0; *(end+1) = 0;
return str; return str;
} }
bool CCallsignList::GetLastModTime(time_t *time) bool CCallsignList::GetLastModTime(time_t *time)
{ {
bool ok = false; bool ok = false;
if ( m_Filename != nullptr ) if ( m_Filename != nullptr )
{ {
struct stat fileStat; struct stat fileStat;
if( ::stat(m_Filename, &fileStat) != -1 ) if( ::stat(m_Filename, &fileStat) != -1 )
{ {
*time = fileStat.st_mtime; *time = fileStat.st_mtime;
ok = true; ok = true;
} }
} }
return ok; return ok;
} }

@ -36,43 +36,43 @@
class CCallsignList class CCallsignList
{ {
public: public:
// constructor // constructor
CCallsignList(); CCallsignList();
// destructor // destructor
virtual ~CCallsignList() {} virtual ~CCallsignList() {}
// locks // locks
void Lock(void) { m_Mutex.lock(); } void Lock(void) { m_Mutex.lock(); }
void Unlock(void) { m_Mutex.unlock(); } void Unlock(void) { m_Mutex.unlock(); }
// file io // file io
virtual bool LoadFromFile(const char *); virtual bool LoadFromFile(const char *);
bool ReloadFromFile(void); bool ReloadFromFile(void);
bool NeedReload(void); bool NeedReload(void);
// compare // compare
bool IsCallsignListedWithWildcard(const CCallsign &) const; bool IsCallsignListedWithWildcard(const CCallsign &) const;
bool IsCallsignListedWithWildcard(const CCallsign &, char) const; bool IsCallsignListedWithWildcard(const CCallsign &, char) const;
bool IsCallsignListed(const CCallsign &, char) const; bool IsCallsignListed(const CCallsign &, char) const;
bool IsCallsignListed(const CCallsign &, char*) const; bool IsCallsignListed(const CCallsign &, char*) const;
// pass-thru // pass-thru
bool empty() const { return m_Callsigns.empty(); } bool empty() const { return m_Callsigns.empty(); }
std::list<CCallsignListItem>::iterator begin() { return m_Callsigns.begin(); } std::list<CCallsignListItem>::iterator begin() { return m_Callsigns.begin(); }
std::list<CCallsignListItem>::iterator end() { return m_Callsigns.end(); } std::list<CCallsignListItem>::iterator end() { return m_Callsigns.end(); }
// find // find
CCallsignListItem *FindListItem(const CCallsign &); CCallsignListItem *FindListItem(const CCallsign &);
protected: protected:
bool GetLastModTime(time_t *); bool GetLastModTime(time_t *);
char *TrimWhiteSpaces(char *); char *TrimWhiteSpaces(char *);
// data // data
std::mutex m_Mutex; std::mutex m_Mutex;
const char * m_Filename; const char * m_Filename;
time_t m_LastModTime; time_t m_LastModTime;
std::list<CCallsignListItem> m_Callsigns; std::list<CCallsignListItem> m_Callsigns;
}; };

@ -31,76 +31,76 @@
CCallsignListItem::CCallsignListItem() CCallsignListItem::CCallsignListItem()
{ {
::memset(m_Modules, 0, sizeof(m_Modules)); ::memset(m_Modules, 0, sizeof(m_Modules));
::memset(m_szUrl, 0, sizeof(m_szUrl)); ::memset(m_szUrl, 0, sizeof(m_szUrl));
} }
CCallsignListItem::CCallsignListItem(const CCallsign &callsign, const CIp &ip, const char *modules) CCallsignListItem::CCallsignListItem(const CCallsign &callsign, const CIp &ip, const char *modules)
{ {
m_Callsign = callsign; m_Callsign = callsign;
::memset(m_szUrl, 0, sizeof(m_szUrl)); ::memset(m_szUrl, 0, sizeof(m_szUrl));
m_Ip = ip; m_Ip = ip;
if ( modules != nullptr ) if ( modules != nullptr )
{ {
::memset(m_Modules, 0, sizeof(m_Modules)); ::memset(m_Modules, 0, sizeof(m_Modules));
if ( modules[0] == '*' ) if ( modules[0] == '*' )
{ {
for ( char i = 0; i < NB_OF_MODULES; i++ ) for ( char i = 0; i < NB_OF_MODULES; i++ )
{ {
m_Modules[i] = 'A' + i; m_Modules[i] = 'A' + i;
} }
} }
else else
{ {
int n = MIN((int)::strlen(modules), sizeof(m_Modules)-1); int n = MIN((int)::strlen(modules), sizeof(m_Modules)-1);
int j = 0; int j = 0;
for ( int i = 0; i < n; i++ ) for ( int i = 0; i < n; i++ )
{ {
if ( (modules[i] - 'A') < NB_OF_MODULES ) if ( (modules[i] - 'A') < NB_OF_MODULES )
{ {
m_Modules[j++] = modules[i]; m_Modules[j++] = modules[i];
} }
} }
} }
} }
} }
CCallsignListItem::CCallsignListItem(const CCallsign &callsign, const char *url, const char *modules) CCallsignListItem::CCallsignListItem(const CCallsign &callsign, const char *url, const char *modules)
{ {
m_Callsign = callsign; m_Callsign = callsign;
::strncpy(m_szUrl, url, URL_MAXLEN); ::strncpy(m_szUrl, url, URL_MAXLEN);
m_Ip = CIp(m_szUrl); m_Ip = CIp(m_szUrl);
if ( modules != nullptr ) if ( modules != nullptr )
{ {
::memset(m_Modules, 0, sizeof(m_Modules)); ::memset(m_Modules, 0, sizeof(m_Modules));
if ( modules[0] == '*' ) if ( modules[0] == '*' )
{ {
for ( char i = 0; i < NB_OF_MODULES; i++ ) for ( char i = 0; i < NB_OF_MODULES; i++ )
{ {
m_Modules[i] = 'A' + i; m_Modules[i] = 'A' + i;
} }
} }
else else
{ {
int n = MIN((int)::strlen(modules), sizeof(m_Modules)-1); int n = MIN((int)::strlen(modules), sizeof(m_Modules)-1);
int j = 0; int j = 0;
for ( int i = 0; i < n; i++ ) for ( int i = 0; i < n; i++ )
{ {
if ( (modules[i] - 'A') < NB_OF_MODULES ) if ( (modules[i] - 'A') < NB_OF_MODULES )
{ {
m_Modules[j++] = modules[i]; m_Modules[j++] = modules[i];
} }
} }
} }
} }
} }
CCallsignListItem::CCallsignListItem(const CCallsignListItem &item) CCallsignListItem::CCallsignListItem(const CCallsignListItem &item)
{ {
m_Callsign = item.m_Callsign; m_Callsign = item.m_Callsign;
::memcpy(m_szUrl, item.m_szUrl, sizeof(m_szUrl)); ::memcpy(m_szUrl, item.m_szUrl, sizeof(m_szUrl));
m_Ip = item.m_Ip; m_Ip = item.m_Ip;
::memcpy(m_Modules, item.m_Modules, sizeof(m_Modules)); ::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 bool CCallsignListItem::HasSameCallsign(const CCallsign &callsign) const
{ {
return m_Callsign.HasSameCallsign(callsign); return m_Callsign.HasSameCallsign(callsign);
} }
bool CCallsignListItem::HasSameCallsignWithWildcard(const CCallsign &callsign) const bool CCallsignListItem::HasSameCallsignWithWildcard(const CCallsign &callsign) const
{ {
return m_Callsign.HasSameCallsignWithWildcard(callsign); return m_Callsign.HasSameCallsignWithWildcard(callsign);
} }
bool CCallsignListItem::HasModuleListed(char module) const 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 CCallsignListItem::CheckListedModules(char *Modules) const
{ {
bool listed = false; bool listed = false;
if ( Modules != nullptr ) if ( Modules != nullptr )
{ {
// build a list of common modules // build a list of common modules
char list[27]; char list[27];
list[0] = 0; list[0] = 0;
// //
for ( unsigned i = 0; i < ::strlen(Modules); i++ ) for ( unsigned i = 0; i < ::strlen(Modules); i++ )
{ {
if ( HasModuleListed(Modules[i]) ) if ( HasModuleListed(Modules[i]) )
{ {
::strncat(list, &(Modules[i]), 1); ::strncat(list, &(Modules[i]), 1);
listed = true; listed = true;
} }
} }
::strcpy(Modules, list); ::strcpy(Modules, list);
} }
return listed; return listed;
} }

@ -40,35 +40,35 @@
class CCallsignListItem class CCallsignListItem
{ {
public: public:
// constructor // constructor
CCallsignListItem(); CCallsignListItem();
CCallsignListItem(const CCallsign &, const CIp &, const char *); CCallsignListItem(const CCallsign &, const CIp &, const char *);
CCallsignListItem(const CCallsign &, const char *, const char *); CCallsignListItem(const CCallsign &, const char *, const char *);
CCallsignListItem(const CCallsignListItem &); CCallsignListItem(const CCallsignListItem &);
// destructor // destructor
virtual ~CCallsignListItem() {} virtual ~CCallsignListItem() {}
// compare // compare
bool HasSameCallsign(const CCallsign &) const; bool HasSameCallsign(const CCallsign &) const;
bool HasSameCallsignWithWildcard(const CCallsign &) const; bool HasSameCallsignWithWildcard(const CCallsign &) const;
bool HasModuleListed(char) const; bool HasModuleListed(char) const;
bool CheckListedModules(char*) const; bool CheckListedModules(char*) const;
// get // get
const CCallsign &GetCallsign(void) const { return m_Callsign; } const CCallsign &GetCallsign(void) const { return m_Callsign; }
const CIp &GetIp(void) const { return m_Ip; } const CIp &GetIp(void) const { return m_Ip; }
const char *GetModules(void) { return m_Modules; } const char *GetModules(void) { return m_Modules; }
// update // update
void ResolveIp(void) { m_Ip = CIp(m_szUrl); } void ResolveIp(void) { m_Ip = CIp(m_szUrl); }
protected: protected:
// data // data
CCallsign m_Callsign; CCallsign m_Callsign;
char m_szUrl[URL_MAXLEN+1]; char m_szUrl[URL_MAXLEN+1];
CIp m_Ip; CIp m_Ip;
char m_Modules[27]; char m_Modules[27];
}; };

@ -32,33 +32,33 @@
CClient::CClient() CClient::CClient()
{ {
m_ReflectorModule = ' '; m_ReflectorModule = ' ';
m_ModuleMastered = ' '; m_ModuleMastered = ' ';
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
m_ConnectTime = std::time(nullptr); m_ConnectTime = std::time(nullptr);
m_LastHeardTime = std::time(nullptr); m_LastHeardTime = std::time(nullptr);
} }
CClient::CClient(const CCallsign &callsign, const CIp &ip, char reflectorModule) CClient::CClient(const CCallsign &callsign, const CIp &ip, char reflectorModule)
{ {
m_ReflectorModule = reflectorModule; m_ReflectorModule = reflectorModule;
m_Callsign = callsign; m_Callsign = callsign;
m_Ip = ip; m_Ip = ip;
m_ModuleMastered = ' '; m_ModuleMastered = ' ';
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
m_ConnectTime = std::time(nullptr); m_ConnectTime = std::time(nullptr);
m_LastHeardTime = std::time(nullptr); m_LastHeardTime = std::time(nullptr);
} }
CClient::CClient(const CClient &client) CClient::CClient(const CClient &client)
{ {
m_Callsign = client.m_Callsign; m_Callsign = client.m_Callsign;
m_Ip = client.m_Ip; m_Ip = client.m_Ip;
m_ReflectorModule = client.m_ReflectorModule; m_ReflectorModule = client.m_ReflectorModule;
m_ModuleMastered = client.m_ModuleMastered; m_ModuleMastered = client.m_ModuleMastered;
m_LastKeepaliveTime = client.m_LastKeepaliveTime; m_LastKeepaliveTime = client.m_LastKeepaliveTime;
m_ConnectTime = client.m_ConnectTime; m_ConnectTime = client.m_ConnectTime;
m_LastHeardTime = client.m_LastHeardTime; m_LastHeardTime = client.m_LastHeardTime;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -66,7 +66,7 @@ CClient::CClient(const CClient &client)
void CClient::Alive(void) 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 bool CClient::operator ==(const CClient &client) const
{ {
return ((client.m_Callsign == m_Callsign) && return ((client.m_Callsign == m_Callsign) &&
(client.m_Ip == m_Ip) && (client.m_Ip == m_Ip) &&
(client.m_ReflectorModule == m_ReflectorModule)); (client.m_ReflectorModule == m_ReflectorModule));
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -85,38 +85,38 @@ bool CClient::operator ==(const CClient &client) const
void CClient::WriteXml(std::ofstream &xmlFile) void CClient::WriteXml(std::ofstream &xmlFile)
{ {
xmlFile << "<NODE>" << std::endl; xmlFile << "<NODE>" << std::endl;
xmlFile << "\t<Callsign>" << m_Callsign << "</Callsign>" << std::endl; xmlFile << "\t<Callsign>" << m_Callsign << "</Callsign>" << std::endl;
xmlFile << "\t<IP>" << m_Ip.GetAddress() << "</IP>" << std::endl; xmlFile << "\t<IP>" << m_Ip.GetAddress() << "</IP>" << std::endl;
xmlFile << "\t<LinkedModule>" << m_ReflectorModule << "</LinkedModule>" << std::endl; xmlFile << "\t<LinkedModule>" << m_ReflectorModule << "</LinkedModule>" << std::endl;
xmlFile << "\t<Protocol>" << GetProtocolName() << "</Protocol>" << std::endl; xmlFile << "\t<Protocol>" << GetProtocolName() << "</Protocol>" << std::endl;
char mbstr[100]; char mbstr[100];
if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_ConnectTime))) if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_ConnectTime)))
{ {
xmlFile << "\t<ConnectTime>" << mbstr << "</ConnectTime>" << std::endl; xmlFile << "\t<ConnectTime>" << mbstr << "</ConnectTime>" << std::endl;
} }
if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime))) if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime)))
{ {
xmlFile << "\t<LastHeardTime>" << mbstr << "</LastHeardTime>" << std::endl; xmlFile << "\t<LastHeardTime>" << mbstr << "</LastHeardTime>" << std::endl;
} }
xmlFile << "</NODE>" << std::endl; xmlFile << "</NODE>" << std::endl;
} }
void CClient::GetJsonObject(char *Buffer) void CClient::GetJsonObject(char *Buffer)
{ {
char sz[512]; char sz[512];
char mbstr[100]; char mbstr[100];
char cs[16]; char cs[16];
if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime))) if (std::strftime(mbstr, sizeof(mbstr), "%A %c", std::localtime(&m_LastHeardTime)))
{ {
m_Callsign.GetCallsignString(cs); m_Callsign.GetCallsignString(cs);
::sprintf(sz, "{\"callsign\":\"%s\",\"module\":\"%c\",\"linkedto\":\"%c\",\"time\":\"%s\"}", ::sprintf(sz, "{\"callsign\":\"%s\",\"module\":\"%c\",\"linkedto\":\"%c\",\"time\":\"%s\"}",
cs, cs,
m_Callsign.GetModule(), m_Callsign.GetModule(),
m_ReflectorModule, m_ReflectorModule,
mbstr); mbstr);
::strcat(Buffer, sz); ::strcat(Buffer, sz);
} }
} }

@ -39,64 +39,64 @@
class CClient class CClient
{ {
public: public:
// constructors // constructors
CClient(); CClient();
CClient(const CCallsign &, const CIp &, char = ' '); CClient(const CCallsign &, const CIp &, char = ' ');
CClient(const CClient &); CClient(const CClient &);
// destructor // destructor
virtual ~CClient() {}; virtual ~CClient() {};
// operators // operators
bool operator ==(const CClient &) const; bool operator ==(const CClient &) const;
// get // get
const CCallsign &GetCallsign(void) const { return m_Callsign; } const CCallsign &GetCallsign(void) const { return m_Callsign; }
const CIp &GetIp(void) const { return m_Ip; } const CIp &GetIp(void) const { return m_Ip; }
bool HasModule(void) const { return m_Callsign.HasModule(); } bool HasModule(void) const { return m_Callsign.HasModule(); }
char GetModule(void) const { return m_Callsign.GetModule(); } char GetModule(void) const { return m_Callsign.GetModule(); }
bool HasReflectorModule(void) const { return m_ReflectorModule != ' '; } bool HasReflectorModule(void) const { return m_ReflectorModule != ' '; }
char GetReflectorModule(void) const { return m_ReflectorModule; } char GetReflectorModule(void) const { return m_ReflectorModule; }
// set // set
void SetModule(char c) { m_Callsign.SetModule(c); } void SetModule(char c) { m_Callsign.SetModule(c); }
void SetReflectorModule(char c) { m_ReflectorModule = c; } void SetReflectorModule(char c) { m_ReflectorModule = c; }
// identity // identity
virtual int GetProtocol(void) const { return PROTOCOL_NONE; } virtual int GetProtocol(void) const { return PROTOCOL_NONE; }
virtual int GetProtocolRevision(void) const { return 0; } virtual int GetProtocolRevision(void) const { return 0; }
virtual int GetCodec(void) const { return CODEC_NONE; } virtual int GetCodec(void) const { return CODEC_NONE; }
virtual const char *GetProtocolName(void) const { return "none"; } virtual const char *GetProtocolName(void) const { return "none"; }
virtual bool IsNode(void) const { return false; } virtual bool IsNode(void) const { return false; }
virtual bool IsPeer(void) const { return false; } virtual bool IsPeer(void) const { return false; }
virtual bool IsDextraDongle(void) const { return false; } virtual bool IsDextraDongle(void) const { return false; }
virtual void SetDextraDongle(void) { } virtual void SetDextraDongle(void) { }
// status // status
virtual void Alive(void); virtual void Alive(void);
virtual bool IsAlive(void) const { return false; } virtual bool IsAlive(void) const { return false; }
virtual bool IsAMaster(void) const { return (m_ModuleMastered != ' '); } virtual bool IsAMaster(void) const { return (m_ModuleMastered != ' '); }
virtual void SetMasterOfModule(char c) { m_ModuleMastered = c; } virtual void SetMasterOfModule(char c) { m_ModuleMastered = c; }
virtual void NotAMaster(void) { m_ModuleMastered = ' '; } virtual void NotAMaster(void) { m_ModuleMastered = ' '; }
virtual void Heard(void) { m_LastHeardTime = std::time(nullptr); } virtual void Heard(void) { m_LastHeardTime = std::time(nullptr); }
// reporting // reporting
virtual void WriteXml(std::ofstream &); virtual void WriteXml(std::ofstream &);
virtual void GetJsonObject(char *); virtual void GetJsonObject(char *);
protected: protected:
// data // data
CCallsign m_Callsign; CCallsign m_Callsign;
CIp m_Ip; CIp m_Ip;
// linked to // linked to
char m_ReflectorModule; char m_ReflectorModule;
// status // status
char m_ModuleMastered; char m_ModuleMastered;
CTimePoint m_LastKeepaliveTime; CTimePoint m_LastKeepaliveTime;
std::time_t m_ConnectTime; std::time_t m_ConnectTime;
std::time_t m_LastHeardTime; std::time_t m_LastHeardTime;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -41,9 +41,9 @@ CClients::CClients()
CClients::~CClients() CClients::~CClients()
{ {
m_Mutex.lock(); m_Mutex.lock();
m_Clients.clear(); m_Clients.clear();
m_Mutex.unlock(); m_Mutex.unlock();
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -51,23 +51,22 @@ CClients::~CClients()
void CClients::AddClient(std::shared_ptr<CClient> client) void CClients::AddClient(std::shared_ptr<CClient> client)
{ {
// first check if client already exists // first check if client already exists
for ( auto it=begin(); it!=end(); it++ ) for ( auto it=begin(); it!=end(); it++ )
{ {
if (*client == *(*it)) if (*client == *(*it))
// if found, just do nothing // if found, just do nothing
// so *client keep pointing on a valid object // so *client keep pointing on a valid object
// on function return // on function return
{ {
// delete new one // delete new one
return; return;
} }
} }
// and append // and append
m_Clients.push_back(client); m_Clients.push_back(client);
std::cout << "New client " << client->GetCallsign() << " at " << client->GetIp() std::cout << "New client " << client->GetCallsign() << " at " << client->GetIp() << " added with protocol " << client->GetProtocolName();
<< " added with protocol " << client->GetProtocolName();
if ( client->GetReflectorModule() != ' ' ) if ( client->GetReflectorModule() != ' ' )
{ {
std::cout << " on module " << client->GetReflectorModule(); std::cout << " on module " << client->GetReflectorModule();
@ -79,40 +78,40 @@ void CClients::AddClient(std::shared_ptr<CClient> client)
void CClients::RemoveClient(std::shared_ptr<CClient> client) void CClients::RemoveClient(std::shared_ptr<CClient> client)
{ {
// look for the client // look for the client
bool found = false; bool found = false;
for ( auto it=begin(); it!=end(); it++ ) for ( auto it=begin(); it!=end(); it++ )
{ {
// compare objetc pointers // compare objetc pointers
if ( *it == client ) if ( *it == client )
{ {
// found it ! // found it !
if ( !(*it)->IsAMaster() ) if ( !(*it)->IsAMaster() )
{ {
// remove it // remove it
std::cout << "Client " << (*it)->GetCallsign() << " at " << (*it)->GetIp() << " removed with protocol " << (*it)->GetProtocolName(); std::cout << "Client " << (*it)->GetCallsign() << " at " << (*it)->GetIp() << " removed with protocol " << (*it)->GetProtocolName();
if ( (*it)->GetReflectorModule() != ' ' ) if ( (*it)->GetReflectorModule() != ' ' )
{ {
std::cout << " on module " << (*it)->GetReflectorModule(); std::cout << " on module " << (*it)->GetReflectorModule();
} }
std::cout << std::endl; std::cout << std::endl;
m_Clients.erase(it); m_Clients.erase(it);
// notify // notify
g_Reflector.OnClientsChanged(); g_Reflector.OnClientsChanged();
break; break;
} }
} }
} }
} }
bool CClients::IsClient(std::shared_ptr<CClient> client) const bool CClients::IsClient(std::shared_ptr<CClient> client) const
{ {
for ( auto it=cbegin(); it!=cend(); it++ ) for ( auto it=cbegin(); it!=cend(); it++ )
{ {
if (*it == client) if (*it == client)
return true; return true;
} }
return false; return false;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -120,97 +119,89 @@ bool CClients::IsClient(std::shared_ptr<CClient> client) const
std::shared_ptr<CClient> CClients::FindClient(const CIp &Ip) std::shared_ptr<CClient> CClients::FindClient(const CIp &Ip)
{ {
// find client // find client
for ( auto it=begin(); it!=end(); it++ ) for ( auto it=begin(); it!=end(); it++ )
{ {
if ( (*it)->GetIp() == Ip ) if ( (*it)->GetIp() == Ip )
{ {
return *it; return *it;
} }
} }
// done // done
return nullptr; return nullptr;
} }
std::shared_ptr<CClient> CClients::FindClient(const CIp &Ip, int Protocol) std::shared_ptr<CClient> CClients::FindClient(const CIp &Ip, int Protocol)
{ {
// find client // find client
for ( auto it=begin(); it!=end(); it++ ) for ( auto it=begin(); it!=end(); it++ )
{ {
if ( ((*it)->GetIp() == Ip) && ((*it)->GetProtocol() == Protocol)) if ( ((*it)->GetIp() == Ip) && ((*it)->GetProtocol() == Protocol))
{ {
return *it; return *it;
} }
} }
// done // done
return nullptr; return nullptr;
} }
std::shared_ptr<CClient> CClients::FindClient(const CIp &Ip, int Protocol, char ReflectorModule) std::shared_ptr<CClient> CClients::FindClient(const CIp &Ip, int Protocol, char ReflectorModule)
{ {
// find client // find client
for ( auto it=begin(); it!=end(); it++ ) for ( auto it=begin(); it!=end(); it++ )
{ {
if ( ((*it)->GetIp() == Ip) && if ( ((*it)->GetIp() == Ip) && ((*it)->GetReflectorModule() == ReflectorModule) && ((*it)->GetProtocol() == Protocol) )
((*it)->GetReflectorModule() == ReflectorModule) && {
((*it)->GetProtocol() == Protocol) ) return *it;
{ }
return *it; }
}
}
// done // done
return nullptr; return nullptr;
} }
std::shared_ptr<CClient> CClients::FindClient(const CCallsign &Callsign, const CIp &Ip, int Protocol) std::shared_ptr<CClient> CClients::FindClient(const CCallsign &Callsign, const CIp &Ip, int Protocol)
{ {
// find client // find client
for ( auto it=begin(); it!=end(); it++ ) for ( auto it=begin(); it!=end(); it++ )
{ {
if ( (*it)->GetCallsign().HasSameCallsign(Callsign) && if ( (*it)->GetCallsign().HasSameCallsign(Callsign) && ((*it)->GetIp() == Ip) && ((*it)->GetProtocol() == Protocol) )
((*it)->GetIp() == Ip) && {
((*it)->GetProtocol() == Protocol) ) return *it;
{ }
return *it; }
}
}
return nullptr; return nullptr;
} }
std::shared_ptr<CClient> CClients::FindClient(const CCallsign &Callsign, char module, const CIp &Ip, int Protocol) std::shared_ptr<CClient> CClients::FindClient(const CCallsign &Callsign, char module, const CIp &Ip, int Protocol)
{ {
// find client // find client
for ( auto it=begin(); it!=end(); it++ ) for ( auto it=begin(); it!=end(); it++ )
{ {
if ( (*it)->GetCallsign().HasSameCallsign(Callsign) && if ( (*it)->GetCallsign().HasSameCallsign(Callsign) && ((*it)->GetModule() == module) && ((*it)->GetIp() == Ip) && ((*it)->GetProtocol() == Protocol) )
((*it)->GetModule() == module) && {
((*it)->GetIp() == Ip) && return *it;
((*it)->GetProtocol() == Protocol) ) }
{ }
return *it;
}
}
return nullptr; return nullptr;
} }
std::shared_ptr<CClient> CClients::FindClient(const CCallsign &Callsign, int Protocol) std::shared_ptr<CClient> CClients::FindClient(const CCallsign &Callsign, int Protocol)
{ {
// find client // find client
for ( auto it=begin(); it!=end(); it++ ) for ( auto it=begin(); it!=end(); it++ )
{ {
if ( ((*it)->GetProtocol() == Protocol) && if ( ((*it)->GetProtocol() == Protocol) && (*it)->GetCallsign().HasSameCallsign(Callsign) )
(*it)->GetCallsign().HasSameCallsign(Callsign) ) {
{ return *it;
return *it; }
} }
}
return nullptr; return nullptr;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -218,42 +209,39 @@ std::shared_ptr<CClient> CClients::FindClient(const CCallsign &Callsign, int Pro
std::shared_ptr<CClient> CClients::FindNextClient(int Protocol, std::list<std::shared_ptr<CClient>>::iterator &it) std::shared_ptr<CClient> CClients::FindNextClient(int Protocol, std::list<std::shared_ptr<CClient>>::iterator &it)
{ {
while ( it != end() ) while ( it != end() )
{ {
if ( (*it)->GetProtocol() == Protocol ) if ( (*it)->GetProtocol() == Protocol )
{ {
return *it++; return *it++;
} }
it++; it++;
} }
return nullptr; return nullptr;
} }
std::shared_ptr<CClient> CClients::FindNextClient(const CIp &Ip, int Protocol, std::list<std::shared_ptr<CClient>>::iterator &it) std::shared_ptr<CClient> CClients::FindNextClient(const CIp &Ip, int Protocol, std::list<std::shared_ptr<CClient>>::iterator &it)
{ {
while ( it != end() ) while ( it != end() )
{ {
if ( ((*it)->GetProtocol() == Protocol) && if ( ((*it)->GetProtocol() == Protocol) && ((*it)->GetIp() == Ip) )
((*it)->GetIp() == Ip) ) {
{ return *it++;
return *it++; }
}
it++; it++;
} }
return nullptr; return nullptr;
} }
std::shared_ptr<CClient> CClients::FindNextClient(const CCallsign &Callsign, const CIp &Ip, int Protocol, std::list<std::shared_ptr<CClient>>::iterator &it) std::shared_ptr<CClient> CClients::FindNextClient(const CCallsign &Callsign, const CIp &Ip, int Protocol, std::list<std::shared_ptr<CClient>>::iterator &it)
{ {
while ( it != end() ) while ( it != end() )
{ {
if ( ((*it)->GetProtocol() == Protocol) && if ( ((*it)->GetProtocol() == Protocol) && ((*it)->GetIp() == Ip) && (*it)->GetCallsign().HasSameCallsign(Callsign) )
((*it)->GetIp() == Ip) && {
(*it)->GetCallsign().HasSameCallsign(Callsign) ) return *it++;
{ }
return *it++;
}
it++; it++;
} }
return nullptr; return nullptr;
} }

@ -39,21 +39,21 @@
class CClients class CClients
{ {
public: public:
// constructors // constructors
CClients(); CClients();
// destructors // destructors
virtual ~CClients(); virtual ~CClients();
// locks // locks
void Lock(void) { m_Mutex.lock(); } void Lock(void) { m_Mutex.lock(); }
void Unlock(void) { m_Mutex.unlock(); } void Unlock(void) { m_Mutex.unlock(); }
// manage Clients // manage Clients
int GetSize(void) const { return (int)m_Clients.size(); } int GetSize(void) const { return (int)m_Clients.size(); }
void AddClient(std::shared_ptr<CClient>); void AddClient(std::shared_ptr<CClient>);
void RemoveClient(std::shared_ptr<CClient>); void RemoveClient(std::shared_ptr<CClient>);
bool IsClient(std::shared_ptr<CClient>) const; bool IsClient(std::shared_ptr<CClient>) const;
// pass-thru // pass-thru
std::list<std::shared_ptr<CClient>>::iterator begin() { return m_Clients.begin(); } std::list<std::shared_ptr<CClient>>::iterator begin() { return m_Clients.begin(); }
@ -61,23 +61,23 @@ public:
std::list<std::shared_ptr<CClient>>::const_iterator cbegin() const { return m_Clients.cbegin(); } std::list<std::shared_ptr<CClient>>::const_iterator cbegin() const { return m_Clients.cbegin(); }
std::list<std::shared_ptr<CClient>>::const_iterator cend() const { return m_Clients.cend(); } std::list<std::shared_ptr<CClient>>::const_iterator cend() const { return m_Clients.cend(); }
// find clients // find clients
std::shared_ptr<CClient> FindClient(const CIp &); std::shared_ptr<CClient> FindClient(const CIp &);
std::shared_ptr<CClient> FindClient(const CIp &, int); std::shared_ptr<CClient> FindClient(const CIp &, int);
std::shared_ptr<CClient> FindClient(const CIp &, int, char); std::shared_ptr<CClient> FindClient(const CIp &, int, char);
std::shared_ptr<CClient> FindClient(const CCallsign &, const CIp &, int); std::shared_ptr<CClient> FindClient(const CCallsign &, const CIp &, int);
std::shared_ptr<CClient> FindClient(const CCallsign &, char, const CIp &, int); std::shared_ptr<CClient> FindClient(const CCallsign &, char, const CIp &, int);
std::shared_ptr<CClient> FindClient(const CCallsign &, int); std::shared_ptr<CClient> FindClient(const CCallsign &, int);
// iterate on clients // iterate on clients
std::shared_ptr<CClient> FindNextClient(int, std::list<std::shared_ptr<CClient>>::iterator &); std::shared_ptr<CClient> FindNextClient(int, std::list<std::shared_ptr<CClient>>::iterator &);
std::shared_ptr<CClient> FindNextClient(const CIp &, int, std::list<std::shared_ptr<CClient>>::iterator &); std::shared_ptr<CClient> FindNextClient(const CIp &, int, std::list<std::shared_ptr<CClient>>::iterator &);
std::shared_ptr<CClient> FindNextClient(const CCallsign &, const CIp &, int, std::list<std::shared_ptr<CClient>>::iterator &); std::shared_ptr<CClient> FindNextClient(const CCallsign &, const CIp &, int, std::list<std::shared_ptr<CClient>>::iterator &);
protected: protected:
// data // data
std::mutex m_Mutex; std::mutex m_Mutex;
std::list<std::shared_ptr<CClient>> m_Clients; std::list<std::shared_ptr<CClient>> m_Clients;
}; };

@ -38,20 +38,20 @@
CCodecStream::CCodecStream(CPacketStream *PacketStream, uint16 uiId, uint8 uiCodecIn, uint8 uiCodecOut) CCodecStream::CCodecStream(CPacketStream *PacketStream, uint16 uiId, uint8 uiCodecIn, uint8 uiCodecOut)
{ {
keep_running = true; keep_running = true;
m_pThread = nullptr; m_pThread = nullptr;
m_uiStreamId = uiId; m_uiStreamId = uiId;
m_uiPid = 0; m_uiPid = 0;
m_uiCodecIn = uiCodecIn; m_uiCodecIn = uiCodecIn;
m_uiCodecOut = uiCodecOut; m_uiCodecOut = uiCodecOut;
m_bConnected = false; m_bConnected = false;
m_fPingMin = -1; m_fPingMin = -1;
m_fPingMax = -1; m_fPingMax = -1;
m_fPingSum = 0; m_fPingSum = 0;
m_fPingCount = 0; m_fPingCount = 0;
m_uiTotalPackets = 0; m_uiTotalPackets = 0;
m_uiTimeoutPackets = 0; m_uiTimeoutPackets = 0;
m_PacketStream = PacketStream; m_PacketStream = PacketStream;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -59,30 +59,30 @@ CCodecStream::CCodecStream(CPacketStream *PacketStream, uint16 uiId, uint8 uiCod
CCodecStream::~CCodecStream() CCodecStream::~CCodecStream()
{ {
// close socket // close socket
m_Socket.Close(); m_Socket.Close();
// kill threads // kill threads
keep_running = false; keep_running = false;
if ( m_pThread != nullptr ) if ( m_pThread != nullptr )
{ {
m_pThread->join(); m_pThread->join();
delete m_pThread; delete m_pThread;
m_pThread = nullptr; m_pThread = nullptr;
} }
// empty local queue // empty local queue
while ( !m_LocalQueue.empty() ) while ( !m_LocalQueue.empty() )
{ {
delete m_LocalQueue.front(); delete m_LocalQueue.front();
m_LocalQueue.pop(); m_LocalQueue.pop();
} }
// empty ourselves // empty ourselves
while ( !empty() ) while ( !empty() )
{ {
delete front(); delete front();
pop(); pop();
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -92,8 +92,8 @@ bool CCodecStream::Init(uint16 uiPort)
{ {
m_bConnected = keep_running = false; // prepare for the worst m_bConnected = keep_running = false; // prepare for the worst
// create the send to address // create the send to address
m_uiPort = uiPort; m_uiPort = uiPort;
auto s = g_Reflector.GetTranscoderIp(); auto s = g_Reflector.GetTranscoderIp();
m_Ip.Initialize(strchr(s, ':') ? AF_INET6 : AF_INET, m_uiPort, s); m_Ip.Initialize(strchr(s, ':') ? AF_INET6 : AF_INET, m_uiPort, s);
@ -114,10 +114,11 @@ bool CCodecStream::Init(uint16 uiPort)
#endif #endif
CIp ip(m_Ip.GetFamily(), m_uiPort, s); CIp ip(m_Ip.GetFamily(), m_uiPort, s);
// create our socket // create our socket
if (ip.IsSet()) 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; std::cerr << "Error opening socket on IP address " << m_Ip << std::endl;
return false; return false;
} }
@ -131,22 +132,22 @@ bool CCodecStream::Init(uint16 uiPort)
keep_running = m_bConnected = true; keep_running = m_bConnected = true;
m_pThread = new std::thread(CCodecStream::Thread, this); m_pThread = new std::thread(CCodecStream::Thread, this);
return true; return true;
} }
void CCodecStream::Close(void) void CCodecStream::Close(void)
{ {
// close socket // close socket
keep_running = m_bConnected = false; keep_running = m_bConnected = false;
m_Socket.Close(); m_Socket.Close();
// kill threads // kill threads
if ( m_pThread != nullptr ) if ( m_pThread != nullptr )
{ {
m_pThread->join(); m_pThread->join();
delete m_pThread; delete m_pThread;
m_pThread = nullptr; m_pThread = nullptr;
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -154,7 +155,7 @@ void CCodecStream::Close(void)
bool CCodecStream::IsEmpty(void) const 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) void CCodecStream::Thread(CCodecStream *This)
{ {
while (This->keep_running) while (This->keep_running)
{ {
This->Task(); This->Task();
} }
} }
void CCodecStream::Task(void) void CCodecStream::Task(void)
{ {
CBuffer Buffer; CBuffer Buffer;
CIp Ip; CIp Ip;
uint8 Ambe[AMBE_SIZE]; uint8 Ambe[AMBE_SIZE];
uint8 DStarSync[] = { 0x55,0x2D,0x16 }; uint8 DStarSync[] = { 0x55,0x2D,0x16 };
// any packet from transcoder // any packet from transcoder
if ( m_Socket.Receive(Buffer, Ip, 5) ) if ( m_Socket.Receive(Buffer, Ip, 5) )
{ {
// crack // crack
if ( IsValidAmbePacket(Buffer, Ambe) ) if ( IsValidAmbePacket(Buffer, Ambe) )
{ {
// tickle // tickle
m_TimeoutTimer.Now(); m_TimeoutTimer.Now();
// update statistics // update statistics
double ping = m_StatsTimer.DurationSinceNow(); double ping = m_StatsTimer.DurationSinceNow();
if ( m_fPingMin == -1 ) if ( m_fPingMin == -1 )
{ {
m_fPingMin = ping; m_fPingMin = ping;
m_fPingMax = ping; m_fPingMax = ping;
} }
else else
{ {
m_fPingMin = MIN(m_fPingMin, ping); m_fPingMin = MIN(m_fPingMin, ping);
m_fPingMax = MAX(m_fPingMax, ping); m_fPingMax = MAX(m_fPingMax, ping);
} }
m_fPingSum += ping; m_fPingSum += ping;
m_fPingCount += 1; m_fPingCount += 1;
// pop the original packet // pop the original packet
if ( !m_LocalQueue.empty() ) if ( !m_LocalQueue.empty() )
{ {
CDvFramePacket *Packet = (CDvFramePacket *)m_LocalQueue.front(); CDvFramePacket *Packet = (CDvFramePacket *)m_LocalQueue.front();
m_LocalQueue.pop(); m_LocalQueue.pop();
// todo: check the PID // todo: check the PID
// update content with transcoded ambe // update content with transcoded ambe
Packet->SetAmbe(m_uiCodecOut, Ambe); Packet->SetAmbe(m_uiCodecOut, Ambe);
// tag syncs in DvData // tag syncs in DvData
if ( (m_uiCodecOut == CODEC_AMBEPLUS) && (Packet->GetPacketId() % 21) == 0 ) if ( (m_uiCodecOut == CODEC_AMBEPLUS) && (Packet->GetPacketId() % 21) == 0 )
{ {
Packet->SetDvData(DStarSync); Packet->SetDvData(DStarSync);
} }
// and push it back to client // and push it back to client
m_PacketStream->Lock(); m_PacketStream->Lock();
m_PacketStream->push(Packet); m_PacketStream->push(Packet);
m_PacketStream->Unlock(); m_PacketStream->Unlock();
} }
else else
{ {
std::cout << "Unexpected transcoded packet received from ambed" << std::endl; std::cout << "Unexpected transcoded packet received from ambed" << std::endl;
} }
} }
} }
// anything in our queue // anything in our queue
while ( !empty() ) while ( !empty() )
{ {
// yes, pop it from queue // yes, pop it from queue
CPacket *Packet = front(); CPacket *Packet = front();
pop(); pop();
// yes, send to ambed // yes, send to ambed
// this assume that thread pushing the Packet // this assume that thread pushing the Packet
// have verified that the CodecStream is connected // have verified that the CodecStream is connected
// and that the packet needs transcoding // and that the packet needs transcoding
m_StatsTimer.Now(); m_StatsTimer.Now();
m_uiTotalPackets++; m_uiTotalPackets++;
EncodeAmbePacket(&Buffer, ((CDvFramePacket *)Packet)->GetAmbe(m_uiCodecIn)); EncodeAmbePacket(&Buffer, ((CDvFramePacket *)Packet)->GetAmbe(m_uiCodecIn));
m_Socket.Send(Buffer, m_Ip, m_uiPort); m_Socket.Send(Buffer, m_Ip, m_uiPort);
// and push to our local queue // and push to our local queue
m_LocalQueue.push(Packet); m_LocalQueue.push(Packet);
} }
// handle timeout // handle timeout
if ( !m_LocalQueue.empty() && (m_TimeoutTimer.DurationSinceNow() >= (TRANSCODER_AMBEPACKET_TIMEOUT/1000.0f)) ) if ( !m_LocalQueue.empty() && (m_TimeoutTimer.DurationSinceNow() >= (TRANSCODER_AMBEPACKET_TIMEOUT/1000.0f)) )
{ {
//std::cout << "ambed packet timeout" << std::endl; //std::cout << "ambed packet timeout" << std::endl;
m_uiTimeoutPackets++; m_uiTimeoutPackets++;
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -259,14 +260,14 @@ void CCodecStream::Task(void)
bool CCodecStream::IsValidAmbePacket(const CBuffer &Buffer, uint8 *Ambe) bool CCodecStream::IsValidAmbePacket(const CBuffer &Buffer, uint8 *Ambe)
{ {
bool valid = false; bool valid = false;
if ( (Buffer.size() == 11) && (Buffer.data()[0] == m_uiCodecOut) ) if ( (Buffer.size() == 11) && (Buffer.data()[0] == m_uiCodecOut) )
{ {
::memcpy(Ambe, &(Buffer.data()[2]), 9); ::memcpy(Ambe, &(Buffer.data()[2]), 9);
valid = true; valid = true;
} }
return valid; return valid;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -274,8 +275,8 @@ bool CCodecStream::IsValidAmbePacket(const CBuffer &Buffer, uint8 *Ambe)
void CCodecStream::EncodeAmbePacket(CBuffer *Buffer, const uint8 *Ambe) void CCodecStream::EncodeAmbePacket(CBuffer *Buffer, const uint8 *Ambe)
{ {
Buffer->clear(); Buffer->clear();
Buffer->Append(m_uiCodecIn); Buffer->Append(m_uiCodecIn);
Buffer->Append(m_uiPid); Buffer->Append(m_uiPid);
Buffer->Append((uint8 *)Ambe, 9); Buffer->Append((uint8 *)Ambe, 9);
} }

@ -46,69 +46,69 @@ class CPacketStream;
class CCodecStream : public CPacketQueue class CCodecStream : public CPacketQueue
{ {
public: public:
// constructor // constructor
CCodecStream(CPacketStream *, uint16, uint8, uint8); CCodecStream(CPacketStream *, uint16, uint8, uint8);
// destructor // destructor
virtual ~CCodecStream(); virtual ~CCodecStream();
// initialization // initialization
bool Init(uint16); bool Init(uint16);
void Close(void); void Close(void);
// get // get
bool IsConnected(void) const { return m_bConnected; } bool IsConnected(void) const { return m_bConnected; }
uint16 GetStreamId(void) const { return m_uiStreamId; } uint16 GetStreamId(void) const { return m_uiStreamId; }
double GetPingMin(void) const { return m_fPingMin; } double GetPingMin(void) const { return m_fPingMin; }
double GetPingMax(void) const { return m_fPingMax; } double GetPingMax(void) const { return m_fPingMax; }
double GetPingAve(void) const { return (m_fPingCount != 0) ? m_fPingSum/m_fPingCount : 0; } double GetPingAve(void) const { return (m_fPingCount != 0) ? m_fPingSum/m_fPingCount : 0; }
uint32 GetTotalPackets(void) const { return m_uiTotalPackets; } uint32 GetTotalPackets(void) const { return m_uiTotalPackets; }
uint32 GetTimeoutPackets(void) const { return m_uiTimeoutPackets; } uint32 GetTimeoutPackets(void) const { return m_uiTimeoutPackets; }
bool IsEmpty(void) const; bool IsEmpty(void) const;
// task // task
static void Thread(CCodecStream *); static void Thread(CCodecStream *);
void Task(void); void Task(void);
protected: protected:
// packet decoding helpers // packet decoding helpers
bool IsValidAmbePacket(const CBuffer &, uint8 *); bool IsValidAmbePacket(const CBuffer &, uint8 *);
// packet encoding helpers // packet encoding helpers
void EncodeAmbePacket(CBuffer *, const uint8 *); void EncodeAmbePacket(CBuffer *, const uint8 *);
protected: protected:
// data // data
uint16 m_uiStreamId; uint16 m_uiStreamId;
uint16 m_uiPort; uint16 m_uiPort;
uint8 m_uiPid; uint8 m_uiPid;
uint8 m_uiCodecIn; uint8 m_uiCodecIn;
uint8 m_uiCodecOut; uint8 m_uiCodecOut;
// socket // socket
CIp m_Ip; CIp m_Ip;
CUdpSocket m_Socket; CUdpSocket m_Socket;
bool m_bConnected; bool m_bConnected;
// associated packet stream // associated packet stream
CPacketStream *m_PacketStream; CPacketStream *m_PacketStream;
CPacketQueue m_LocalQueue; CPacketQueue m_LocalQueue;
// thread // thread
std::atomic<bool> keep_running; std::atomic<bool> keep_running;
std::thread *m_pThread; std::thread *m_pThread;
CTimePoint m_TimeoutTimer; CTimePoint m_TimeoutTimer;
CTimePoint m_StatsTimer; CTimePoint m_StatsTimer;
// statistics // statistics
double m_fPingMin; double m_fPingMin;
double m_fPingMax; double m_fPingMax;
double m_fPingSum; double m_fPingSum;
double m_fPingCount; double m_fPingCount;
uint32 m_uiTotalPackets; uint32 m_uiTotalPackets;
uint32 m_uiTimeoutPackets; uint32 m_uiTimeoutPackets;
}; };

@ -25,227 +25,238 @@
#include <cassert> #include <cassert>
#include <cmath> #include <cmath>
const uint8_t CRC8_TABLE[] = { 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, 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31,
0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, 0xE0, 0xE7, 0xEE, 0xE9, 0x24, 0x23, 0x2A, 0x2D, 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, 0xE0, 0xE7, 0xEE, 0xE9,
0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1, 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
0xB4, 0xB3, 0xBA, 0xBD, 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1,
0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, 0xB7, 0xB0, 0xB9, 0xBE, 0xB4, 0xB3, 0xBA, 0xBD, 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, 0xB7, 0xB0, 0xB9, 0xBE,
0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
0x03, 0x04, 0x0D, 0x0A, 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16,
0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, 0x89, 0x8E, 0x87, 0x80, 0x03, 0x04, 0x0D, 0x0A, 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, 0x89, 0x8E, 0x87, 0x80,
0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, 0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
0xDD, 0xDA, 0xD3, 0xD4, 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8,
0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, 0x19, 0x1E, 0x17, 0x10, 0xDD, 0xDA, 0xD3, 0xD4, 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, 0x19, 0x1E, 0x17, 0x10,
0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
0x6A, 0x6D, 0x64, 0x63, 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F,
0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, 0xAE, 0xA9, 0xA0, 0xA7, 0x6A, 0x6D, 0x64, 0x63, 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, 0xAE, 0xA9, 0xA0, 0xA7,
0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
0xFA, 0xFD, 0xF4, 0xF3, 0x01 }; 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, const uint16_t CCITT16_TABLE1[] =
0x1081U, 0x0108U, 0x3393U, 0x221aU, 0x56a5U, 0x472cU, 0x75b7U, 0x643eU, {
0x9cc9U, 0x8d40U, 0xbfdbU, 0xae52U, 0xdaedU, 0xcb64U, 0xf9ffU, 0xe876U, 0x0000U, 0x1189U, 0x2312U, 0x329bU, 0x4624U, 0x57adU, 0x6536U, 0x74bfU,
0x2102U, 0x308bU, 0x0210U, 0x1399U, 0x6726U, 0x76afU, 0x4434U, 0x55bdU, 0x8c48U, 0x9dc1U, 0xaf5aU, 0xbed3U, 0xca6cU, 0xdbe5U, 0xe97eU, 0xf8f7U,
0xad4aU, 0xbcc3U, 0x8e58U, 0x9fd1U, 0xeb6eU, 0xfae7U, 0xc87cU, 0xd9f5U, 0x1081U, 0x0108U, 0x3393U, 0x221aU, 0x56a5U, 0x472cU, 0x75b7U, 0x643eU,
0x3183U, 0x200aU, 0x1291U, 0x0318U, 0x77a7U, 0x662eU, 0x54b5U, 0x453cU, 0x9cc9U, 0x8d40U, 0xbfdbU, 0xae52U, 0xdaedU, 0xcb64U, 0xf9ffU, 0xe876U,
0xbdcbU, 0xac42U, 0x9ed9U, 0x8f50U, 0xfbefU, 0xea66U, 0xd8fdU, 0xc974U, 0x2102U, 0x308bU, 0x0210U, 0x1399U, 0x6726U, 0x76afU, 0x4434U, 0x55bdU,
0x4204U, 0x538dU, 0x6116U, 0x709fU, 0x0420U, 0x15a9U, 0x2732U, 0x36bbU, 0xad4aU, 0xbcc3U, 0x8e58U, 0x9fd1U, 0xeb6eU, 0xfae7U, 0xc87cU, 0xd9f5U,
0xce4cU, 0xdfc5U, 0xed5eU, 0xfcd7U, 0x8868U, 0x99e1U, 0xab7aU, 0xbaf3U, 0x3183U, 0x200aU, 0x1291U, 0x0318U, 0x77a7U, 0x662eU, 0x54b5U, 0x453cU,
0x5285U, 0x430cU, 0x7197U, 0x601eU, 0x14a1U, 0x0528U, 0x37b3U, 0x263aU, 0xbdcbU, 0xac42U, 0x9ed9U, 0x8f50U, 0xfbefU, 0xea66U, 0xd8fdU, 0xc974U,
0xdecdU, 0xcf44U, 0xfddfU, 0xec56U, 0x98e9U, 0x8960U, 0xbbfbU, 0xaa72U, 0x4204U, 0x538dU, 0x6116U, 0x709fU, 0x0420U, 0x15a9U, 0x2732U, 0x36bbU,
0x6306U, 0x728fU, 0x4014U, 0x519dU, 0x2522U, 0x34abU, 0x0630U, 0x17b9U, 0xce4cU, 0xdfc5U, 0xed5eU, 0xfcd7U, 0x8868U, 0x99e1U, 0xab7aU, 0xbaf3U,
0xef4eU, 0xfec7U, 0xcc5cU, 0xddd5U, 0xa96aU, 0xb8e3U, 0x8a78U, 0x9bf1U, 0x5285U, 0x430cU, 0x7197U, 0x601eU, 0x14a1U, 0x0528U, 0x37b3U, 0x263aU,
0x7387U, 0x620eU, 0x5095U, 0x411cU, 0x35a3U, 0x242aU, 0x16b1U, 0x0738U, 0xdecdU, 0xcf44U, 0xfddfU, 0xec56U, 0x98e9U, 0x8960U, 0xbbfbU, 0xaa72U,
0xffcfU, 0xee46U, 0xdcddU, 0xcd54U, 0xb9ebU, 0xa862U, 0x9af9U, 0x8b70U, 0x6306U, 0x728fU, 0x4014U, 0x519dU, 0x2522U, 0x34abU, 0x0630U, 0x17b9U,
0x8408U, 0x9581U, 0xa71aU, 0xb693U, 0xc22cU, 0xd3a5U, 0xe13eU, 0xf0b7U, 0xef4eU, 0xfec7U, 0xcc5cU, 0xddd5U, 0xa96aU, 0xb8e3U, 0x8a78U, 0x9bf1U,
0x0840U, 0x19c9U, 0x2b52U, 0x3adbU, 0x4e64U, 0x5fedU, 0x6d76U, 0x7cffU, 0x7387U, 0x620eU, 0x5095U, 0x411cU, 0x35a3U, 0x242aU, 0x16b1U, 0x0738U,
0x9489U, 0x8500U, 0xb79bU, 0xa612U, 0xd2adU, 0xc324U, 0xf1bfU, 0xe036U, 0xffcfU, 0xee46U, 0xdcddU, 0xcd54U, 0xb9ebU, 0xa862U, 0x9af9U, 0x8b70U,
0x18c1U, 0x0948U, 0x3bd3U, 0x2a5aU, 0x5ee5U, 0x4f6cU, 0x7df7U, 0x6c7eU, 0x8408U, 0x9581U, 0xa71aU, 0xb693U, 0xc22cU, 0xd3a5U, 0xe13eU, 0xf0b7U,
0xa50aU, 0xb483U, 0x8618U, 0x9791U, 0xe32eU, 0xf2a7U, 0xc03cU, 0xd1b5U, 0x0840U, 0x19c9U, 0x2b52U, 0x3adbU, 0x4e64U, 0x5fedU, 0x6d76U, 0x7cffU,
0x2942U, 0x38cbU, 0x0a50U, 0x1bd9U, 0x6f66U, 0x7eefU, 0x4c74U, 0x5dfdU, 0x9489U, 0x8500U, 0xb79bU, 0xa612U, 0xd2adU, 0xc324U, 0xf1bfU, 0xe036U,
0xb58bU, 0xa402U, 0x9699U, 0x8710U, 0xf3afU, 0xe226U, 0xd0bdU, 0xc134U, 0x18c1U, 0x0948U, 0x3bd3U, 0x2a5aU, 0x5ee5U, 0x4f6cU, 0x7df7U, 0x6c7eU,
0x39c3U, 0x284aU, 0x1ad1U, 0x0b58U, 0x7fe7U, 0x6e6eU, 0x5cf5U, 0x4d7cU, 0xa50aU, 0xb483U, 0x8618U, 0x9791U, 0xe32eU, 0xf2a7U, 0xc03cU, 0xd1b5U,
0xc60cU, 0xd785U, 0xe51eU, 0xf497U, 0x8028U, 0x91a1U, 0xa33aU, 0xb2b3U, 0x2942U, 0x38cbU, 0x0a50U, 0x1bd9U, 0x6f66U, 0x7eefU, 0x4c74U, 0x5dfdU,
0x4a44U, 0x5bcdU, 0x6956U, 0x78dfU, 0x0c60U, 0x1de9U, 0x2f72U, 0x3efbU, 0xb58bU, 0xa402U, 0x9699U, 0x8710U, 0xf3afU, 0xe226U, 0xd0bdU, 0xc134U,
0xd68dU, 0xc704U, 0xf59fU, 0xe416U, 0x90a9U, 0x8120U, 0xb3bbU, 0xa232U, 0x39c3U, 0x284aU, 0x1ad1U, 0x0b58U, 0x7fe7U, 0x6e6eU, 0x5cf5U, 0x4d7cU,
0x5ac5U, 0x4b4cU, 0x79d7U, 0x685eU, 0x1ce1U, 0x0d68U, 0x3ff3U, 0x2e7aU, 0xc60cU, 0xd785U, 0xe51eU, 0xf497U, 0x8028U, 0x91a1U, 0xa33aU, 0xb2b3U,
0xe70eU, 0xf687U, 0xc41cU, 0xd595U, 0xa12aU, 0xb0a3U, 0x8238U, 0x93b1U, 0x4a44U, 0x5bcdU, 0x6956U, 0x78dfU, 0x0c60U, 0x1de9U, 0x2f72U, 0x3efbU,
0x6b46U, 0x7acfU, 0x4854U, 0x59ddU, 0x2d62U, 0x3cebU, 0x0e70U, 0x1ff9U, 0xd68dU, 0xc704U, 0xf59fU, 0xe416U, 0x90a9U, 0x8120U, 0xb3bbU, 0xa232U,
0xf78fU, 0xe606U, 0xd49dU, 0xc514U, 0xb1abU, 0xa022U, 0x92b9U, 0x8330U, 0x5ac5U, 0x4b4cU, 0x79d7U, 0x685eU, 0x1ce1U, 0x0d68U, 0x3ff3U, 0x2e7aU,
0x7bc7U, 0x6a4eU, 0x58d5U, 0x495cU, 0x3de3U, 0x2c6aU, 0x1ef1U, 0x0f78U }; 0xe70eU, 0xf687U, 0xc41cU, 0xd595U, 0xa12aU, 0xb0a3U, 0x8238U, 0x93b1U,
0x6b46U, 0x7acfU, 0x4854U, 0x59ddU, 0x2d62U, 0x3cebU, 0x0e70U, 0x1ff9U,
const uint16_t CCITT16_TABLE2[] = { 0xf78fU, 0xe606U, 0xd49dU, 0xc514U, 0xb1abU, 0xa022U, 0x92b9U, 0x8330U,
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x7bc7U, 0x6a4eU, 0x58d5U, 0x495cU, 0x3de3U, 0x2c6aU, 0x1ef1U, 0x0f78U
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, };
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, const uint16_t CCITT16_TABLE2[] =
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, {
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 }; 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) bool CCRC::checkFiveBit(bool* in, unsigned int tcrc)
{ {
assert(in != nullptr); assert(in != nullptr);
unsigned int crc; unsigned int crc;
encodeFiveBit(in, crc); encodeFiveBit(in, crc);
return crc == tcrc; return crc == tcrc;
} }
void CCRC::encodeFiveBit(const bool* in, unsigned int& tcrc) void CCRC::encodeFiveBit(const bool* in, unsigned int& tcrc)
{ {
assert(in != nullptr); assert(in != nullptr);
unsigned short total = 0U; unsigned short total = 0U;
for (unsigned int i = 0U; i < 72U; i += 8U) { for (unsigned int i = 0U; i < 72U; i += 8U)
unsigned char c; {
CUtils::bitsToByteBE(in + i, c); unsigned char c;
total += 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) void CCRC::addCCITT162(unsigned char *in, unsigned int length)
{ {
assert(in != nullptr); assert(in != nullptr);
assert(length > 2U); assert(length > 2U);
union { union
uint16_t crc16; {
uint8_t crc8[2U]; uint16_t crc16;
}; uint8_t crc8[2U];
};
crc16 = 0U; crc16 = 0U;
for (unsigned i = 0U; i < (length - 2U); i++) for (unsigned i = 0U; i < (length - 2U); i++)
crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ in[i]]; crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ in[i]];
crc16 = ~crc16; crc16 = ~crc16;
in[length - 1U] = crc8[0U]; in[length - 1U] = crc8[0U];
in[length - 2U] = crc8[1U]; in[length - 2U] = crc8[1U];
} }
bool CCRC::checkCCITT162(const unsigned char *in, unsigned int length) bool CCRC::checkCCITT162(const unsigned char *in, unsigned int length)
{ {
assert(in != nullptr); assert(in != nullptr);
assert(length > 2U); assert(length > 2U);
union { union
uint16_t crc16; {
uint8_t crc8[2U]; uint16_t crc16;
}; uint8_t crc8[2U];
};
crc16 = 0U; crc16 = 0U;
for (unsigned i = 0U; i < (length - 2U); i++) for (unsigned i = 0U; i < (length - 2U); i++)
crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ in[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) void CCRC::addCCITT161(unsigned char *in, unsigned int length)
{ {
assert(in != nullptr); assert(in != nullptr);
assert(length > 2U); assert(length > 2U);
union { union
uint16_t crc16; {
uint8_t crc8[2U]; uint16_t crc16;
}; uint8_t crc8[2U];
};
crc16 = 0xFFFFU; crc16 = 0xFFFFU;
for (unsigned int i = 0U; i < (length - 2U); i++) for (unsigned int i = 0U; i < (length - 2U); i++)
crc16 = uint16_t(crc8[1U]) ^ CCITT16_TABLE1[crc8[0U] ^ in[i]]; crc16 = uint16_t(crc8[1U]) ^ CCITT16_TABLE1[crc8[0U] ^ in[i]];
crc16 = ~crc16; crc16 = ~crc16;
in[length - 2U] = crc8[0U]; in[length - 2U] = crc8[0U];
in[length - 1U] = crc8[1U]; in[length - 1U] = crc8[1U];
} }
bool CCRC::checkCCITT161(const unsigned char *in, unsigned int length) bool CCRC::checkCCITT161(const unsigned char *in, unsigned int length)
{ {
assert(in != nullptr); assert(in != nullptr);
assert(length > 2U); assert(length > 2U);
union { union
uint16_t crc16; {
uint8_t crc8[2U]; uint16_t crc16;
}; uint8_t crc8[2U];
};
crc16 = 0xFFFFU; crc16 = 0xFFFFU;
for (unsigned int i = 0U; i < (length - 2U); i++) for (unsigned int i = 0U; i < (length - 2U); i++)
crc16 = uint16_t(crc8[1U]) ^ CCITT16_TABLE1[crc8[0U] ^ in[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) 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++) for (unsigned int i = 0U; i < length; i++)
crc = CRC8_TABLE[crc ^ in[i]]; crc = CRC8_TABLE[crc ^ in[i]];
return crc; return crc;
} }
unsigned char CCRC::addCRC(const unsigned char* in, unsigned int length) 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++) for (unsigned int i = 0U; i < length; i++)
crc += in[i]; crc += in[i];
return crc; return crc;
} }

@ -22,18 +22,18 @@
class CCRC class CCRC
{ {
public: public:
static bool checkFiveBit(bool* in, unsigned int tcrc); static bool checkFiveBit(bool* in, unsigned int tcrc);
static void encodeFiveBit(const 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 addCCITT161(unsigned char* in, unsigned int length);
static void addCCITT162(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 checkCCITT161(const unsigned char* in, unsigned int length);
static bool checkCCITT162(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 crc8(const unsigned char* in, unsigned int length);
static unsigned char addCRC(const unsigned char* in, unsigned int length); static unsigned char addCRC(const unsigned char* in, unsigned int length);
}; };
#endif #endif

@ -19,7 +19,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#include "main.h" #include "main.h"
@ -34,12 +34,12 @@ CDcsClient::CDcsClient()
} }
CDcsClient::CDcsClient(const CCallsign &callsign, const CIp &ip, char reflectorModule) CDcsClient::CDcsClient(const CCallsign &callsign, const CIp &ip, char reflectorModule)
: CClient(callsign, ip, reflectorModule) : CClient(callsign, ip, reflectorModule)
{ {
} }
CDcsClient::CDcsClient(const CDcsClient &client) CDcsClient::CDcsClient(const CDcsClient &client)
: CClient(client) : CClient(client)
{ {
} }
@ -48,5 +48,5 @@ CDcsClient::CDcsClient(const CDcsClient &client)
bool CDcsClient::IsAlive(void) const bool CDcsClient::IsAlive(void) const
{ {
return (m_LastKeepaliveTime.DurationSinceNow() < DCS_KEEPALIVE_TIMEOUT); return (m_LastKeepaliveTime.DurationSinceNow() < DCS_KEEPALIVE_TIMEOUT);
} }

@ -19,7 +19,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#ifndef cdcsclient_h #ifndef cdcsclient_h
@ -37,22 +37,22 @@
class CDcsClient : public CClient class CDcsClient : public CClient
{ {
public: public:
// constructors // constructors
CDcsClient(); CDcsClient();
CDcsClient(const CCallsign &, const CIp &, char = ' '); CDcsClient(const CCallsign &, const CIp &, char = ' ');
CDcsClient(const CDcsClient &); CDcsClient(const CDcsClient &);
// destructor // destructor
virtual ~CDcsClient() {}; virtual ~CDcsClient() {};
// identity // identity
int GetProtocol(void) const { return PROTOCOL_DCS; } int GetProtocol(void) const { return PROTOCOL_DCS; }
const char *GetProtocolName(void) const { return "DCS"; } const char *GetProtocolName(void) const { return "DCS"; }
int GetCodec(void) const { return CODEC_AMBEPLUS; } int GetCodec(void) const { return CODEC_AMBEPLUS; }
bool IsNode(void) const { return true; } bool IsNode(void) const { return true; }
// status // status
bool IsAlive(void) const; bool IsAlive(void) const;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -35,15 +35,15 @@
bool CDcsProtocol::Init(void) bool CDcsProtocol::Init(void)
{ {
// base class // base class
if (! CProtocol::Initialize("DCS", DCS_PORT, DSTAR_IPV4, DSTAR_IPV6)) if (! CProtocol::Initialize("DCS", DCS_PORT, DSTAR_IPV4, DSTAR_IPV6))
return false; return false;
// update time // update time
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
// done // done
return true; return true;
} }
@ -53,14 +53,14 @@ bool CDcsProtocol::Init(void)
void CDcsProtocol::Task(void) void CDcsProtocol::Task(void)
{ {
CBuffer Buffer; CBuffer Buffer;
CIp Ip; CIp Ip;
CCallsign Callsign; CCallsign Callsign;
char ToLinkModule; char ToLinkModule;
CDvHeaderPacket *Header; CDvHeaderPacket *Header;
CDvFramePacket *Frame; CDvFramePacket *Frame;
// handle incoming packets // handle incoming packets
#if DSTAR_IPV6==true #if DSTAR_IPV6==true
#if DSTAR_IPV4==true #if DSTAR_IPV4==true
if ( ReceiveDS(Buffer, Ip, 20) ) if ( ReceiveDS(Buffer, Ip, 20) )
@ -70,128 +70,128 @@ void CDcsProtocol::Task(void)
#else #else
if ( Receive4(Buffer, Ip, 20) ) if ( Receive4(Buffer, Ip, 20) )
#endif #endif
{ {
// crack the packet // crack the packet
if ( IsValidDvPacket(Buffer, &Header, &Frame) ) if ( IsValidDvPacket(Buffer, &Header, &Frame) )
{ {
//std::cout << "DCS DV packet" << std::endl; //std::cout << "DCS DV packet" << std::endl;
// callsign muted? // callsign muted?
if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_DCS, Header->GetRpt2Module()) ) if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_DCS, Header->GetRpt2Module()) )
{ {
// handle it // handle it
OnDvHeaderPacketIn(Header, Ip); OnDvHeaderPacketIn(Header, Ip);
if ( !Frame->IsLastPacket() ) if ( !Frame->IsLastPacket() )
{ {
//std::cout << "DCS DV frame" << std::endl; //std::cout << "DCS DV frame" << std::endl;
OnDvFramePacketIn(Frame, &Ip); OnDvFramePacketIn(Frame, &Ip);
} }
else else
{ {
//std::cout << "DCS DV last frame" << std::endl; //std::cout << "DCS DV last frame" << std::endl;
OnDvLastFramePacketIn((CDvLastFramePacket *)Frame, &Ip); OnDvLastFramePacketIn((CDvLastFramePacket *)Frame, &Ip);
} }
} }
else else
{ {
delete Header; delete Header;
delete Frame; delete Frame;
} }
} }
else if ( IsValidConnectPacket(Buffer, &Callsign, &ToLinkModule) ) else if ( IsValidConnectPacket(Buffer, &Callsign, &ToLinkModule) )
{ {
std::cout << "DCS connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl; std::cout << "DCS connect packet for module " << ToLinkModule << " from " << Callsign << " at " << Ip << std::endl;
// callsign authorized? // callsign authorized?
if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_DCS) && g_Reflector.IsValidModule(ToLinkModule) ) if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_DCS) && g_Reflector.IsValidModule(ToLinkModule) )
{ {
// valid module ? // valid module ?
if ( g_Reflector.IsValidModule(ToLinkModule) ) if ( g_Reflector.IsValidModule(ToLinkModule) )
{ {
// acknowledge the request // acknowledge the request
EncodeConnectAckPacket(Callsign, ToLinkModule, &Buffer); EncodeConnectAckPacket(Callsign, ToLinkModule, &Buffer);
Send(Buffer, Ip); Send(Buffer, Ip);
// create the client and append // create the client and append
g_Reflector.GetClients()->AddClient(std::make_shared<CDcsClient>(Callsign, Ip, ToLinkModule)); g_Reflector.GetClients()->AddClient(std::make_shared<CDcsClient>(Callsign, Ip, ToLinkModule));
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
} }
else else
{ {
std::cout << "DCS node " << Callsign << " connect attempt on non-existing module" << std::endl; std::cout << "DCS node " << Callsign << " connect attempt on non-existing module" << std::endl;
// deny the request // deny the request
EncodeConnectNackPacket(Callsign, ToLinkModule, &Buffer); EncodeConnectNackPacket(Callsign, ToLinkModule, &Buffer);
Send(Buffer, Ip); Send(Buffer, Ip);
} }
} }
else else
{ {
// deny the request // deny the request
EncodeConnectNackPacket(Callsign, ToLinkModule, &Buffer); EncodeConnectNackPacket(Callsign, ToLinkModule, &Buffer);
Send(Buffer, Ip); Send(Buffer, Ip);
} }
} }
else if ( IsValidDisconnectPacket(Buffer, &Callsign) ) else if ( IsValidDisconnectPacket(Buffer, &Callsign) )
{ {
std::cout << "DCS disconnect packet from " << Callsign << " at " << Ip << std::endl; std::cout << "DCS disconnect packet from " << Callsign << " at " << Ip << std::endl;
// find client // find client
CClients *clients = g_Reflector.GetClients(); CClients *clients = g_Reflector.GetClients();
std::shared_ptr<CClient>client = clients->FindClient(Ip, PROTOCOL_DCS); std::shared_ptr<CClient>client = clients->FindClient(Ip, PROTOCOL_DCS);
if ( client != nullptr ) if ( client != nullptr )
{ {
// remove it // remove it
clients->RemoveClient(client); clients->RemoveClient(client);
// and acknowledge the disconnect // and acknowledge the disconnect
EncodeConnectNackPacket(Callsign, ' ', &Buffer); EncodeConnectNackPacket(Callsign, ' ', &Buffer);
Send(Buffer, Ip); Send(Buffer, Ip);
} }
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
} }
else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) else if ( IsValidKeepAlivePacket(Buffer, &Callsign) )
{ {
//std::cout << "DCS keepalive packet from " << Callsign << " at " << Ip << std::endl; //std::cout << "DCS keepalive packet from " << Callsign << " at " << Ip << std::endl;
// find all clients with that callsign & ip and keep them alive // find all clients with that callsign & ip and keep them alive
CClients *clients = g_Reflector.GetClients(); CClients *clients = g_Reflector.GetClients();
auto it = clients->begin(); auto it = clients->begin();
std::shared_ptr<CClient>client = nullptr; std::shared_ptr<CClient>client = nullptr;
while ( (client = clients->FindNextClient(Callsign, Ip, PROTOCOL_DCS, it)) != nullptr ) while ( (client = clients->FindNextClient(Callsign, Ip, PROTOCOL_DCS, it)) != nullptr )
{ {
client->Alive(); client->Alive();
} }
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
} }
else if ( IsIgnorePacket(Buffer) ) else if ( IsIgnorePacket(Buffer) )
{ {
// valid but ignore packet // valid but ignore packet
//std::cout << "DCS ignored packet from " << Ip << std::endl; //std::cout << "DCS ignored packet from " << Ip << std::endl;
} }
else else
{ {
// invalid packet // invalid packet
std::cout << "DCS packet (" << Buffer.size() << ") from " << Ip << std::endl; std::cout << "DCS packet (" << Buffer.size() << ") from " << Ip << std::endl;
} }
} }
// handle end of streaming timeout // handle end of streaming timeout
CheckStreamsTimeout(); CheckStreamsTimeout();
// handle queue from reflector // handle queue from reflector
HandleQueue(); HandleQueue();
// keep client alive // keep client alive
if ( m_LastKeepaliveTime.DurationSinceNow() > DCS_KEEPALIVE_PERIOD ) if ( m_LastKeepaliveTime.DurationSinceNow() > DCS_KEEPALIVE_PERIOD )
{ {
// //
HandleKeepalives(); HandleKeepalives();
// update time // update time
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -199,53 +199,53 @@ void CDcsProtocol::Task(void)
bool CDcsProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip) bool CDcsProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip)
{ {
bool newstream = false; bool newstream = false;
// find the stream // find the stream
CPacketStream *stream = GetStream(Header->GetStreamId()); CPacketStream *stream = GetStream(Header->GetStreamId());
if ( stream == nullptr ) if ( stream == nullptr )
{ {
// no stream open yet, open a new one // no stream open yet, open a new one
CCallsign via(Header->GetRpt1Callsign()); CCallsign via(Header->GetRpt1Callsign());
// find this client // find this client
std::shared_ptr<CClient>client = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_DCS); std::shared_ptr<CClient>client = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_DCS);
if ( client != nullptr ) if ( client != nullptr )
{ {
// get client callsign // get client callsign
via = client->GetCallsign(); via = client->GetCallsign();
// and try to open the stream // and try to open the stream
if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr )
{ {
// keep the handle // keep the handle
m_Streams.push_back(stream); m_Streams.push_back(stream);
newstream = true; newstream = true;
} }
} }
// release // release
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
// update last heard // update last heard
g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), via, Header->GetRpt2Callsign()); g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), via, Header->GetRpt2Callsign());
g_Reflector.ReleaseUsers(); g_Reflector.ReleaseUsers();
// delete header if needed // delete header if needed
if ( !newstream ) if ( !newstream )
{ {
delete Header; delete Header;
} }
} }
else else
{ {
// stream already open // stream already open
// skip packet, but tickle the stream // skip packet, but tickle the stream
stream->Tickle(); stream->Tickle();
// and delete packet // and delete packet
delete Header; delete Header;
} }
// done // done
return newstream; return newstream;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -253,69 +253,69 @@ bool CDcsProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip)
void CDcsProtocol::HandleQueue(void) void CDcsProtocol::HandleQueue(void)
{ {
m_Queue.Lock(); m_Queue.Lock();
while ( !m_Queue.empty() ) while ( !m_Queue.empty() )
{ {
// get the packet // get the packet
CPacket *packet = m_Queue.front(); CPacket *packet = m_Queue.front();
m_Queue.pop(); m_Queue.pop();
// get our sender's id // get our sender's id
int iModId = g_Reflector.GetModuleIndex(packet->GetModuleId()); int iModId = g_Reflector.GetModuleIndex(packet->GetModuleId());
// check if it's header and update cache // check if it's header and update cache
if ( packet->IsDvHeader() ) if ( packet->IsDvHeader() )
{ {
// this relies on queue feeder setting valid module id // this relies on queue feeder setting valid module id
m_StreamsCache[iModId].m_dvHeader = CDvHeaderPacket((const CDvHeaderPacket &)*packet); m_StreamsCache[iModId].m_dvHeader = CDvHeaderPacket((const CDvHeaderPacket &)*packet);
m_StreamsCache[iModId].m_iSeqCounter = 0; m_StreamsCache[iModId].m_iSeqCounter = 0;
} }
else else
{ {
// encode it // encode it
CBuffer buffer; CBuffer buffer;
if ( packet->IsLastPacket() ) if ( packet->IsLastPacket() )
{ {
EncodeDvLastPacket( EncodeDvLastPacket(
m_StreamsCache[iModId].m_dvHeader, m_StreamsCache[iModId].m_dvHeader,
(const CDvFramePacket &)*packet, (const CDvFramePacket &)*packet,
m_StreamsCache[iModId].m_iSeqCounter++, m_StreamsCache[iModId].m_iSeqCounter++,
&buffer); &buffer);
} }
else if ( packet->IsDvFrame() ) else if ( packet->IsDvFrame() )
{ {
EncodeDvPacket( EncodeDvPacket(
m_StreamsCache[iModId].m_dvHeader, m_StreamsCache[iModId].m_dvHeader,
(const CDvFramePacket &)*packet, (const CDvFramePacket &)*packet,
m_StreamsCache[iModId].m_iSeqCounter++, m_StreamsCache[iModId].m_iSeqCounter++,
&buffer); &buffer);
} }
// send it // send it
if ( buffer.size() > 0 ) if ( buffer.size() > 0 )
{ {
// and push it to all our clients linked to the module and who are not streaming in // and push it to all our clients linked to the module and who are not streaming in
CClients *clients = g_Reflector.GetClients(); CClients *clients = g_Reflector.GetClients();
auto it = clients->begin(); auto it = clients->begin();
std::shared_ptr<CClient>client = nullptr; std::shared_ptr<CClient>client = nullptr;
while ( (client = clients->FindNextClient(PROTOCOL_DCS, it)) != nullptr ) while ( (client = clients->FindNextClient(PROTOCOL_DCS, it)) != nullptr )
{ {
// is this client busy ? // is this client busy ?
if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) ) if ( !client->IsAMaster() && (client->GetReflectorModule() == packet->GetModuleId()) )
{ {
// no, send the packet // no, send the packet
Send(buffer, client->GetIp()); Send(buffer, client->GetIp());
} }
} }
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
} }
} }
// done // done
delete packet; delete packet;
} }
m_Queue.Unlock(); m_Queue.Unlock();
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -323,47 +323,47 @@ void CDcsProtocol::HandleQueue(void)
void CDcsProtocol::HandleKeepalives(void) void CDcsProtocol::HandleKeepalives(void)
{ {
// DCS protocol sends and monitors keepalives packets // DCS protocol sends and monitors keepalives packets
// event if the client is currently streaming // event if the client is currently streaming
// so, send keepalives to all // so, send keepalives to all
CBuffer keepalive1; CBuffer keepalive1;
EncodeKeepAlivePacket(&keepalive1); EncodeKeepAlivePacket(&keepalive1);
// iterate on clients // iterate on clients
CClients *clients = g_Reflector.GetClients(); CClients *clients = g_Reflector.GetClients();
auto it = clients->begin(); auto it = clients->begin();
std::shared_ptr<CClient>client = nullptr; std::shared_ptr<CClient>client = nullptr;
while ( (client = clients->FindNextClient(PROTOCOL_DCS, it)) != nullptr ) while ( (client = clients->FindNextClient(PROTOCOL_DCS, it)) != nullptr )
{ {
// encode client's specific keepalive packet // encode client's specific keepalive packet
CBuffer keepalive2; CBuffer keepalive2;
EncodeKeepAlivePacket(&keepalive2, client); EncodeKeepAlivePacket(&keepalive2, client);
// send keepalive // send keepalive
Send(keepalive1, client->GetIp()); Send(keepalive1, client->GetIp());
Send(keepalive2, client->GetIp()); Send(keepalive2, client->GetIp());
// is this client busy ? // is this client busy ?
if ( client->IsAMaster() ) if ( client->IsAMaster() )
{ {
// yes, just tickle it // yes, just tickle it
client->Alive(); client->Alive();
} }
// check it's still with us // check it's still with us
else if ( !client->IsAlive() ) else if ( !client->IsAlive() )
{ {
// no, disconnect // no, disconnect
CBuffer disconnect; CBuffer disconnect;
EncodeDisconnectPacket(&disconnect, client); EncodeDisconnectPacket(&disconnect, client);
Send(disconnect, client->GetIp()); Send(disconnect, client->GetIp());
// remove it // remove it
std::cout << "DCS client " << client->GetCallsign() << " keepalive timeout" << std::endl; std::cout << "DCS client " << client->GetCallsign() << " keepalive timeout" << std::endl;
clients->RemoveClient(client); clients->RemoveClient(client);
} }
} }
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -371,98 +371,98 @@ void CDcsProtocol::HandleKeepalives(void)
bool CDcsProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsign, char *reflectormodule) bool CDcsProtocol::IsValidConnectPacket(const CBuffer &Buffer, CCallsign *callsign, char *reflectormodule)
{ {
bool valid = false; bool valid = false;
if ( Buffer.size() == 519 ) if ( Buffer.size() == 519 )
{ {
callsign->SetCallsign(Buffer.data(), 8); callsign->SetCallsign(Buffer.data(), 8);
callsign->SetModule(Buffer.data()[8]); callsign->SetModule(Buffer.data()[8]);
*reflectormodule = Buffer.data()[9]; *reflectormodule = Buffer.data()[9];
valid = (callsign->IsValid() && IsLetter(*reflectormodule)); valid = (callsign->IsValid() && IsLetter(*reflectormodule));
} }
return valid; return valid;
} }
bool CDcsProtocol::IsValidDisconnectPacket(const CBuffer &Buffer, CCallsign *callsign) bool CDcsProtocol::IsValidDisconnectPacket(const CBuffer &Buffer, CCallsign *callsign)
{ {
bool valid = false; bool valid = false;
if ((Buffer.size() == 11) && (Buffer.data()[9] == ' ')) if ((Buffer.size() == 11) && (Buffer.data()[9] == ' '))
{ {
callsign->SetCallsign(Buffer.data(), 8); callsign->SetCallsign(Buffer.data(), 8);
callsign->SetModule(Buffer.data()[8]); callsign->SetModule(Buffer.data()[8]);
valid = callsign->IsValid(); valid = callsign->IsValid();
} }
else if ((Buffer.size() == 19) && (Buffer.data()[9] == ' ') && (Buffer.data()[10] == 0x00)) else if ((Buffer.size() == 19) && (Buffer.data()[9] == ' ') && (Buffer.data()[10] == 0x00))
{ {
callsign->SetCallsign(Buffer.data(), 8); callsign->SetCallsign(Buffer.data(), 8);
callsign->SetModule(Buffer.data()[8]); callsign->SetModule(Buffer.data()[8]);
valid = callsign->IsValid(); valid = callsign->IsValid();
} }
return valid; return valid;
} }
bool CDcsProtocol::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *callsign) bool CDcsProtocol::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *callsign)
{ {
bool valid = false; bool valid = false;
if ( (Buffer.size() == 17) || (Buffer.size() == 15) || (Buffer.size() == 22) ) if ( (Buffer.size() == 17) || (Buffer.size() == 15) || (Buffer.size() == 22) )
{ {
callsign->SetCallsign(Buffer.data(), 8); callsign->SetCallsign(Buffer.data(), 8);
valid = callsign->IsValid(); valid = callsign->IsValid();
} }
return valid; return valid;
} }
bool CDcsProtocol::IsValidDvPacket(const CBuffer &Buffer, CDvHeaderPacket **header, CDvFramePacket **frame) bool CDcsProtocol::IsValidDvPacket(const CBuffer &Buffer, CDvHeaderPacket **header, CDvFramePacket **frame)
{ {
uint8 tag[] = { '0','0','0','1' }; uint8 tag[] = { '0','0','0','1' };
bool valid = false; bool valid = false;
*header = nullptr; *header = nullptr;
*frame = nullptr; *frame = nullptr;
if ( (Buffer.size() >= 100) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) if ( (Buffer.size() >= 100) && (Buffer.Compare(tag, sizeof(tag)) == 0) )
{ {
// get the header // get the header
*header = new CDvHeaderPacket((struct dstar_header *)&(Buffer.data()[4]), *((uint16 *)&(Buffer.data()[43])), 0x80); *header = new CDvHeaderPacket((struct dstar_header *)&(Buffer.data()[4]), *((uint16 *)&(Buffer.data()[43])), 0x80);
// get the frame // get the frame
if ( ((Buffer.data()[45]) & 0x40) != 0 ) if ( ((Buffer.data()[45]) & 0x40) != 0 )
{ {
// it's the last frame // it's the last frame
*frame = new CDvLastFramePacket((struct dstar_dvframe *)&(Buffer.data()[46]), *((uint16 *)&(Buffer.data()[43])), Buffer.data()[45]); *frame = new CDvLastFramePacket((struct dstar_dvframe *)&(Buffer.data()[46]), *((uint16 *)&(Buffer.data()[43])), Buffer.data()[45]);
} }
else else
{ {
// it's a regular DV frame // it's a regular DV frame
*frame = new CDvFramePacket((struct dstar_dvframe *)&(Buffer.data()[46]), *((uint16 *)&(Buffer.data()[43])), Buffer.data()[45]); *frame = new CDvFramePacket((struct dstar_dvframe *)&(Buffer.data()[46]), *((uint16 *)&(Buffer.data()[43])), Buffer.data()[45]);
} }
// check validity of packets // check validity of packets
if ( !((*header)->IsValid() && (*frame)->IsValid()) ) if ( !((*header)->IsValid() && (*frame)->IsValid()) )
{ {
delete *header; delete *header;
delete *frame; delete *frame;
*header = nullptr; *header = nullptr;
*frame = nullptr; *frame = nullptr;
} }
else else
{ {
valid = true; valid = true;
} }
} }
// done // done
return valid; return valid;
} }
bool CDcsProtocol::IsIgnorePacket(const CBuffer &Buffer) bool CDcsProtocol::IsIgnorePacket(const CBuffer &Buffer)
{ {
bool valid = false; bool valid = false;
uint8 tag[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; uint8 tag[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, };
if ( Buffer.size() == 15 ) if ( Buffer.size() == 15 )
{ {
valid = (Buffer.Compare(tag, sizeof(tag)) == 0); valid = (Buffer.Compare(tag, sizeof(tag)) == 0);
} }
return valid; return valid;
} }
@ -471,81 +471,81 @@ bool CDcsProtocol::IsIgnorePacket(const CBuffer &Buffer)
void CDcsProtocol::EncodeKeepAlivePacket(CBuffer *Buffer) void CDcsProtocol::EncodeKeepAlivePacket(CBuffer *Buffer)
{ {
Buffer->Set(GetReflectorCallsign()); Buffer->Set(GetReflectorCallsign());
} }
void CDcsProtocol::EncodeKeepAlivePacket(CBuffer *Buffer, std::shared_ptr<CClient>Client) void CDcsProtocol::EncodeKeepAlivePacket(CBuffer *Buffer, std::shared_ptr<CClient>Client)
{ {
uint8 tag[] = { 0x0A,0x00,0x20,0x20 }; uint8 tag[] = { 0x0A,0x00,0x20,0x20 };
Buffer->Set((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN-1); Buffer->Set((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN-1);
Buffer->Append((uint8)Client->GetReflectorModule()); Buffer->Append((uint8)Client->GetReflectorModule());
Buffer->Append((uint8)' '); Buffer->Append((uint8)' ');
Buffer->Append((uint8 *)(const char *)Client->GetCallsign(), CALLSIGN_LEN-1); Buffer->Append((uint8 *)(const char *)Client->GetCallsign(), CALLSIGN_LEN-1);
Buffer->Append((uint8)Client->GetModule()); Buffer->Append((uint8)Client->GetModule());
Buffer->Append((uint8)Client->GetModule()); Buffer->Append((uint8)Client->GetModule());
Buffer->Append(tag, sizeof(tag)); Buffer->Append(tag, sizeof(tag));
} }
void CDcsProtocol::EncodeConnectAckPacket(const CCallsign &Callsign, char ReflectorModule, CBuffer *Buffer) void CDcsProtocol::EncodeConnectAckPacket(const CCallsign &Callsign, char ReflectorModule, CBuffer *Buffer)
{ {
uint8 tag[] = { 'A','C','K',0x00 }; uint8 tag[] = { 'A','C','K',0x00 };
uint8 cs[CALLSIGN_LEN]; uint8 cs[CALLSIGN_LEN];
Callsign.GetCallsign(cs); Callsign.GetCallsign(cs);
Buffer->Set(cs, CALLSIGN_LEN-1); Buffer->Set(cs, CALLSIGN_LEN-1);
Buffer->Append((uint8)' '); Buffer->Append((uint8)' ');
Buffer->Append((uint8)Callsign.GetModule()); Buffer->Append((uint8)Callsign.GetModule());
Buffer->Append((uint8)ReflectorModule); Buffer->Append((uint8)ReflectorModule);
Buffer->Append(tag, sizeof(tag)); Buffer->Append(tag, sizeof(tag));
} }
void CDcsProtocol::EncodeConnectNackPacket(const CCallsign &Callsign, char ReflectorModule, CBuffer *Buffer) void CDcsProtocol::EncodeConnectNackPacket(const CCallsign &Callsign, char ReflectorModule, CBuffer *Buffer)
{ {
uint8 tag[] = { 'N','A','K',0x00 }; uint8 tag[] = { 'N','A','K',0x00 };
uint8 cs[CALLSIGN_LEN]; uint8 cs[CALLSIGN_LEN];
Callsign.GetCallsign(cs); Callsign.GetCallsign(cs);
Buffer->Set(cs, CALLSIGN_LEN-1); Buffer->Set(cs, CALLSIGN_LEN-1);
Buffer->Append((uint8)' '); Buffer->Append((uint8)' ');
Buffer->Append((uint8)Callsign.GetModule()); Buffer->Append((uint8)Callsign.GetModule());
Buffer->Append((uint8)ReflectorModule); Buffer->Append((uint8)ReflectorModule);
Buffer->Append(tag, sizeof(tag)); Buffer->Append(tag, sizeof(tag));
} }
void CDcsProtocol::EncodeDisconnectPacket(CBuffer *Buffer, std::shared_ptr<CClient>Client) void CDcsProtocol::EncodeDisconnectPacket(CBuffer *Buffer, std::shared_ptr<CClient>Client)
{ {
Buffer->Set((uint8 *)(const char *)Client->GetCallsign(), CALLSIGN_LEN-1); Buffer->Set((uint8 *)(const char *)Client->GetCallsign(), CALLSIGN_LEN-1);
Buffer->Append((uint8)' '); Buffer->Append((uint8)' ');
Buffer->Append((uint8)Client->GetModule()); Buffer->Append((uint8)Client->GetModule());
Buffer->Append((uint8)0x00); Buffer->Append((uint8)0x00);
Buffer->Append((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN-1); Buffer->Append((uint8 *)(const char *)GetReflectorCallsign(), CALLSIGN_LEN-1);
Buffer->Append((uint8)' '); Buffer->Append((uint8)' ');
Buffer->Append((uint8)0x00); Buffer->Append((uint8)0x00);
} }
void CDcsProtocol::EncodeDvPacket(const CDvHeaderPacket &Header, const CDvFramePacket &DvFrame, uint32 iSeq, CBuffer *Buffer) const void CDcsProtocol::EncodeDvPacket(const CDvHeaderPacket &Header, const CDvFramePacket &DvFrame, uint32 iSeq, CBuffer *Buffer) const
{ {
uint8 tag[] = { '0','0','0','1' }; uint8 tag[] = { '0','0','0','1' };
struct dstar_header DstarHeader; struct dstar_header DstarHeader;
Header.ConvertToDstarStruct(&DstarHeader); Header.ConvertToDstarStruct(&DstarHeader);
Buffer->Set(tag, sizeof(tag)); Buffer->Set(tag, sizeof(tag));
Buffer->Append((uint8 *)&DstarHeader, sizeof(struct dstar_header) - sizeof(uint16)); Buffer->Append((uint8 *)&DstarHeader, sizeof(struct dstar_header) - sizeof(uint16));
Buffer->Append(DvFrame.GetStreamId()); Buffer->Append(DvFrame.GetStreamId());
Buffer->Append((uint8)(DvFrame.GetPacketId() % 21)); Buffer->Append((uint8)(DvFrame.GetPacketId() % 21));
Buffer->Append((uint8 *)DvFrame.GetAmbe(), AMBE_SIZE); Buffer->Append((uint8 *)DvFrame.GetAmbe(), AMBE_SIZE);
Buffer->Append((uint8 *)DvFrame.GetDvData(), DVDATA_SIZE); Buffer->Append((uint8 *)DvFrame.GetDvData(), DVDATA_SIZE);
Buffer->Append((uint8)((iSeq >> 0) & 0xFF)); Buffer->Append((uint8)((iSeq >> 0) & 0xFF));
Buffer->Append((uint8)((iSeq >> 8) & 0xFF)); Buffer->Append((uint8)((iSeq >> 8) & 0xFF));
Buffer->Append((uint8)((iSeq >> 16) & 0xFF)); Buffer->Append((uint8)((iSeq >> 16) & 0xFF));
Buffer->Append((uint8)0x01); Buffer->Append((uint8)0x01);
Buffer->Append((uint8)0x00, 38); Buffer->Append((uint8)0x00, 38);
} }
void CDcsProtocol::EncodeDvLastPacket(const CDvHeaderPacket &Header, const CDvFramePacket &DvFrame, uint32 iSeq, CBuffer *Buffer) const void CDcsProtocol::EncodeDvLastPacket(const CDvHeaderPacket &Header, const CDvFramePacket &DvFrame, uint32 iSeq, CBuffer *Buffer) const
{ {
EncodeDvPacket(Header, DvFrame, iSeq, Buffer); EncodeDvPacket(Header, DvFrame, iSeq, Buffer);
(Buffer->data())[45] |= 0x40; (Buffer->data())[45] |= 0x40;
} }

@ -40,54 +40,54 @@
class CDcsStreamCacheItem class CDcsStreamCacheItem
{ {
public: public:
CDcsStreamCacheItem() { m_iSeqCounter = 0; } CDcsStreamCacheItem() { m_iSeqCounter = 0; }
~CDcsStreamCacheItem() {} ~CDcsStreamCacheItem() {}
CDvHeaderPacket m_dvHeader; CDvHeaderPacket m_dvHeader;
uint32 m_iSeqCounter; uint32 m_iSeqCounter;
}; };
class CDcsProtocol : public CProtocol class CDcsProtocol : public CProtocol
{ {
public: public:
// initialization // initialization
bool Init(void); bool Init(void);
// task // task
void Task(void); void Task(void);
protected: protected:
// queue helper // queue helper
void HandleQueue(void); void HandleQueue(void);
// keepalive helpers // keepalive helpers
void HandleKeepalives(void); void HandleKeepalives(void);
// stream helpers // stream helpers
bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &);
// packet decoding helpers // packet decoding helpers
bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *); bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *);
bool IsValidDisconnectPacket(const CBuffer &, CCallsign *); bool IsValidDisconnectPacket(const CBuffer &, CCallsign *);
bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *);
bool IsValidDvPacket(const CBuffer &, CDvHeaderPacket **, CDvFramePacket **); bool IsValidDvPacket(const CBuffer &, CDvHeaderPacket **, CDvFramePacket **);
bool IsIgnorePacket(const CBuffer &); bool IsIgnorePacket(const CBuffer &);
// packet encoding helpers // packet encoding helpers
void EncodeKeepAlivePacket(CBuffer *); void EncodeKeepAlivePacket(CBuffer *);
void EncodeKeepAlivePacket(CBuffer *, std::shared_ptr<CClient>); void EncodeKeepAlivePacket(CBuffer *, std::shared_ptr<CClient>);
void EncodeConnectAckPacket(const CCallsign &, char, CBuffer *); void EncodeConnectAckPacket(const CCallsign &, char, CBuffer *);
void EncodeConnectNackPacket(const CCallsign &, char, CBuffer *); void EncodeConnectNackPacket(const CCallsign &, char, CBuffer *);
void EncodeDisconnectPacket(CBuffer *, std::shared_ptr<CClient>); void EncodeDisconnectPacket(CBuffer *, std::shared_ptr<CClient>);
void EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket &, uint32, CBuffer *) const; void EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket &, uint32, CBuffer *) const;
void EncodeDvLastPacket(const CDvHeaderPacket &, const CDvFramePacket &, uint32, CBuffer *) const; void EncodeDvLastPacket(const CDvHeaderPacket &, const CDvFramePacket &, uint32, CBuffer *) const;
protected: protected:
// for keep alive // for keep alive
CTimePoint m_LastKeepaliveTime; CTimePoint m_LastKeepaliveTime;
// for queue header caches // for queue header caches
std::array<CDcsStreamCacheItem, NB_OF_MODULES> m_StreamsCache; std::array<CDcsStreamCacheItem, NB_OF_MODULES> m_StreamsCache;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -19,7 +19,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#include "main.h" #include "main.h"
@ -31,19 +31,19 @@
CDextraClient::CDextraClient() CDextraClient::CDextraClient()
{ {
m_ProtRev = 0; m_ProtRev = 0;
} }
CDextraClient::CDextraClient(const CCallsign &callsign, const CIp &ip, char reflectorModule, int protRev) 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) 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 bool CDextraClient::IsAlive(void) const
{ {
return (m_LastKeepaliveTime.DurationSinceNow() < DEXTRA_KEEPALIVE_TIMEOUT); return (m_LastKeepaliveTime.DurationSinceNow() < DEXTRA_KEEPALIVE_TIMEOUT);
} }

@ -19,7 +19,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#ifndef cdextraclient_h #ifndef cdextraclient_h
@ -37,27 +37,27 @@
class CDextraClient : public CClient class CDextraClient : public CClient
{ {
public: public:
// constructors // constructors
CDextraClient(); CDextraClient();
CDextraClient(const CCallsign &, const CIp &, char = ' ', int = 0); CDextraClient(const CCallsign &, const CIp &, char = ' ', int = 0);
CDextraClient(const CDextraClient &); CDextraClient(const CDextraClient &);
// destructor // destructor
virtual ~CDextraClient() {}; virtual ~CDextraClient() {};
// identity // identity
int GetProtocol(void) const { return PROTOCOL_DEXTRA; } int GetProtocol(void) const { return PROTOCOL_DEXTRA; }
int GetProtocolRevision(void) const { return m_ProtRev; } int GetProtocolRevision(void) const { return m_ProtRev; }
const char *GetProtocolName(void) const { return "DExtra"; } const char *GetProtocolName(void) const { return "DExtra"; }
int GetCodec(void) const { return CODEC_AMBEPLUS; } int GetCodec(void) const { return CODEC_AMBEPLUS; }
bool IsNode(void) const { return true; } bool IsNode(void) const { return true; }
// status // status
bool IsAlive(void) const; bool IsAlive(void) const;
protected: protected:
// data // data
int m_ProtRev; int m_ProtRev;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -39,16 +39,16 @@ CDextraPeer::CDextraPeer()
} }
CDextraPeer::CDextraPeer(const CCallsign &callsign, const CIp &ip, const char *modules, const CVersion &version) 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 // and construct the DExtra clients
for ( unsigned i = 0; i < ::strlen(modules); i++ ) for ( unsigned i = 0; i < ::strlen(modules); i++ )
{ {
// create and append to vector // create and append to vector
m_Clients.push_back(std::make_shared<CDextraClient>(callsign, ip, modules[i], version.GetMajor())); m_Clients.push_back(std::make_shared<CDextraClient>(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 bool CDextraPeer::IsAlive(void) const
{ {
for ( auto it=cbegin(); it!=cend(); it++ ) for ( auto it=cbegin(); it!=cend(); it++ )
{ {
if (! (*it)->IsAlive()) if (! (*it)->IsAlive())
return false; return false;
} }
return true; return true;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -69,5 +69,5 @@ bool CDextraPeer::IsAlive(void) const
int CDextraPeer::GetProtocolRevision(const CVersion &version) int CDextraPeer::GetProtocolRevision(const CVersion &version)
{ {
return version.GetMajor(); return version.GetMajor();
} }

@ -38,20 +38,20 @@
class CDextraPeer : public CPeer class CDextraPeer : public CPeer
{ {
public: public:
// constructors // constructors
CDextraPeer(); CDextraPeer();
CDextraPeer(const CCallsign &, const CIp &, const char *, const CVersion &); CDextraPeer(const CCallsign &, const CIp &, const char *, const CVersion &);
CDextraPeer(const CDextraPeer &) = delete; CDextraPeer(const CDextraPeer &) = delete;
// status // status
bool IsAlive(void) const; bool IsAlive(void) const;
// identity // identity
int GetProtocol(void) const { return PROTOCOL_DEXTRA; } int GetProtocol(void) const { return PROTOCOL_DEXTRA; }
const char *GetProtocolName(void) const { return "DExtra"; } const char *GetProtocolName(void) const { return "DExtra"; }
// revision helper // revision helper
static int GetProtocolRevision(const CVersion &); static int GetProtocolRevision(const CVersion &);
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

@ -58,46 +58,46 @@
class CDextraProtocol : public CProtocol class CDextraProtocol : public CProtocol
{ {
public: public:
// initialization // initialization
bool Initialize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); bool Initialize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6);
// task // task
void Task(void); void Task(void);
protected: protected:
// queue helper // queue helper
void HandleQueue(void); void HandleQueue(void);
// keepalive helpers // keepalive helpers
void HandlePeerLinks(void); void HandlePeerLinks(void);
void HandleKeepalives(void); void HandleKeepalives(void);
// stream helpers // stream helpers
bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &);
// packet decoding helpers // packet decoding helpers
bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, int *); bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, int *);
bool IsValidDisconnectPacket(const CBuffer &, CCallsign *); bool IsValidDisconnectPacket(const CBuffer &, CCallsign *);
bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *);
CDvHeaderPacket *IsValidDvHeaderPacket(const CBuffer &); CDvHeaderPacket *IsValidDvHeaderPacket(const CBuffer &);
CDvFramePacket *IsValidDvFramePacket(const CBuffer &); CDvFramePacket *IsValidDvFramePacket(const CBuffer &);
CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &); CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &);
// packet encoding helpers // packet encoding helpers
void EncodeKeepAlivePacket(CBuffer *); void EncodeKeepAlivePacket(CBuffer *);
void EncodeConnectPacket(CBuffer *, const char *); void EncodeConnectPacket(CBuffer *, const char *);
void EncodeConnectAckPacket(CBuffer *, int); void EncodeConnectAckPacket(CBuffer *, int);
void EncodeConnectNackPacket(CBuffer *); void EncodeConnectNackPacket(CBuffer *);
void EncodeDisconnectPacket(CBuffer *, char); void EncodeDisconnectPacket(CBuffer *, char);
void EncodeDisconnectedPacket(CBuffer *); void EncodeDisconnectedPacket(CBuffer *);
bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const;
bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const;
bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const;
protected: protected:
// time // time
CTimePoint m_LastKeepaliveTime; CTimePoint m_LastKeepaliveTime;
CTimePoint m_LastPeersLinkTime; CTimePoint m_LastPeersLinkTime;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -34,20 +34,20 @@
CDmridDir::CDmridDir() CDmridDir::CDmridDir()
{ {
keep_running = true; keep_running = true;
m_pThread = nullptr; m_pThread = nullptr;
} }
CDmridDir::~CDmridDir() CDmridDir::~CDmridDir()
{ {
// kill threads // kill threads
keep_running = false; keep_running = false;
if ( m_pThread != nullptr ) if ( m_pThread != nullptr )
{ {
m_pThread->join(); m_pThread->join();
delete m_pThread; delete m_pThread;
m_pThread = nullptr; m_pThread = nullptr;
} }
} }
@ -59,24 +59,24 @@ bool CDmridDir::Init(void)
// load content // load content
Reload(); Reload();
// reset run flag // reset run flag
keep_running = true; keep_running = true;
// start thread; // start thread;
m_pThread = new std::thread(CDmridDir::Thread, this); m_pThread = new std::thread(CDmridDir::Thread, this);
return true; return true;
} }
void CDmridDir::Close(void) void CDmridDir::Close(void)
{ {
keep_running = false; keep_running = false;
if ( m_pThread != nullptr ) if ( m_pThread != nullptr )
{ {
m_pThread->join(); m_pThread->join();
delete m_pThread; delete m_pThread;
m_pThread = nullptr; m_pThread = nullptr;
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -84,18 +84,18 @@ void CDmridDir::Close(void)
void CDmridDir::Thread(CDmridDir *This) void CDmridDir::Thread(CDmridDir *This)
{ {
while (This->keep_running) while (This->keep_running)
{ {
// Wait DMRIDDB_REFRESH_RATE minutes // Wait DMRIDDB_REFRESH_RATE minutes
for (int i=0; i<30*DMRIDDB_REFRESH_RATE && This->keep_running; i++) for (int i=0; i<30*DMRIDDB_REFRESH_RATE && This->keep_running; i++)
CTimePoint::TaskSleepFor(2000); CTimePoint::TaskSleepFor(2000);
// have lists files changed ? // have lists files changed ?
if ( This->NeedReload() ) if ( This->NeedReload() )
{ {
This->Reload(); This->Reload();
} }
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -103,18 +103,18 @@ void CDmridDir::Thread(CDmridDir *This)
bool CDmridDir::Reload(void) bool CDmridDir::Reload(void)
{ {
CBuffer buffer; CBuffer buffer;
bool ok = false; bool ok = false;
if ( LoadContent(&buffer) ) if ( LoadContent(&buffer) )
{ {
Lock(); Lock();
{ {
ok = RefreshContent(buffer); ok = RefreshContent(buffer);
} }
Unlock(); Unlock();
} }
return ok; return ok;
} }
@ -123,22 +123,22 @@ bool CDmridDir::Reload(void)
const CCallsign *CDmridDir::FindCallsign(uint32 dmrid) const CCallsign *CDmridDir::FindCallsign(uint32 dmrid)
{ {
auto found = m_CallsignMap.find(dmrid); auto found = m_CallsignMap.find(dmrid);
if ( found != m_CallsignMap.end() ) if ( found != m_CallsignMap.end() )
{ {
return &(found->second); return &(found->second);
} }
return nullptr; return nullptr;
} }
uint32 CDmridDir::FindDmrid(const CCallsign &callsign) uint32 CDmridDir::FindDmrid(const CCallsign &callsign)
{ {
auto found = m_DmridMap.find(callsign); auto found = m_DmridMap.find(callsign);
if ( found != m_DmridMap.end() ) if ( found != m_DmridMap.end() )
{ {
return (found->second); return (found->second);
} }
return 0; return 0;
} }
@ -147,15 +147,15 @@ uint32 CDmridDir::FindDmrid(const CCallsign &callsign)
bool CDmridDir::IsValidDmrid(const char *sz) bool CDmridDir::IsValidDmrid(const char *sz)
{ {
bool ok = false; bool ok = false;
size_t n = ::strlen(sz); size_t n = ::strlen(sz);
if ( (n > 0) && (n <= 8) ) if ( (n > 0) && (n <= 8) )
{ {
ok = true; ok = true;
for ( size_t i = 0; (i < n) && ok; i++ ) for ( size_t i = 0; (i < n) && ok; i++ )
{ {
ok &= ::isdigit(sz[i]); ok &= ::isdigit(sz[i]);
} }
} }
return ok; return ok;
} }

@ -36,8 +36,8 @@
struct CDmridDirCallsignCompare struct CDmridDirCallsignCompare
{ {
bool operator() (const CCallsign &cs1, const CCallsign &cs2) const bool operator() (const CCallsign &cs1, const CCallsign &cs2) const
{ return cs1.HasLowerCallsign(cs2);} { return cs1.HasLowerCallsign(cs2);}
}; };
@ -46,48 +46,48 @@ struct CDmridDirCallsignCompare
class CDmridDir class CDmridDir
{ {
public: public:
// constructor // constructor
CDmridDir(); CDmridDir();
// destructor // destructor
~CDmridDir(); ~CDmridDir();
// init & close // init & close
virtual bool Init(void); virtual bool Init(void);
virtual void Close(void); virtual void Close(void);
// locks // locks
void Lock(void) { m_Mutex.lock(); } void Lock(void) { m_Mutex.lock(); }
void Unlock(void) { m_Mutex.unlock(); } void Unlock(void) { m_Mutex.unlock(); }
// refresh // refresh
virtual bool LoadContent(CBuffer *) { return false; } virtual bool LoadContent(CBuffer *) { return false; }
virtual bool RefreshContent(const CBuffer &) { return false; } virtual bool RefreshContent(const CBuffer &) { return false; }
// find // find
const CCallsign *FindCallsign(uint32); const CCallsign *FindCallsign(uint32);
uint32 FindDmrid(const CCallsign &); uint32 FindDmrid(const CCallsign &);
protected: protected:
// thread // thread
static void Thread(CDmridDir *); static void Thread(CDmridDir *);
// reload helpers // reload helpers
bool Reload(void); bool Reload(void);
virtual bool NeedReload(void) { return false; } virtual bool NeedReload(void) { return false; }
bool IsValidDmrid(const char *); bool IsValidDmrid(const char *);
protected: protected:
// data // data
std::map <uint32, CCallsign> m_CallsignMap; std::map <uint32, CCallsign> m_CallsignMap;
std::map <CCallsign, uint32, CDmridDirCallsignCompare> m_DmridMap; std::map <CCallsign, uint32, CDmridDirCallsignCompare> m_DmridMap;
// Lock() // Lock()
std::mutex m_Mutex; std::mutex m_Mutex;
// thread // thread
std::atomic<bool> keep_running; std::atomic<bool> keep_running;
std::thread *m_pThread; std::thread *m_pThread;
}; };

@ -38,7 +38,7 @@ CDmridDirFile g_DmridDir;
CDmridDirFile::CDmridDirFile() 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) bool CDmridDirFile::Init(void)
{ {
return CDmridDir::Init(); return CDmridDir::Init();
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -55,111 +55,111 @@ bool CDmridDirFile::Init(void)
bool CDmridDirFile::NeedReload(void) bool CDmridDirFile::NeedReload(void)
{ {
bool needReload = false; bool needReload = false;
time_t time; time_t time;
if ( GetLastModTime(&time) ) if ( GetLastModTime(&time) )
{ {
needReload = time != m_LastModTime; needReload = time != m_LastModTime;
} }
return needReload; return needReload;
} }
bool CDmridDirFile::LoadContent(CBuffer *buffer) bool CDmridDirFile::LoadContent(CBuffer *buffer)
{ {
bool ok = false; bool ok = false;
std::ifstream file; std::ifstream file;
std::streampos size; std::streampos size;
// open file // open file
file.open(DMRIDDB_PATH, std::ios::in | std::ios::binary | std::ios::ate); file.open(DMRIDDB_PATH, std::ios::in | std::ios::binary | std::ios::ate);
if ( file.is_open() ) if ( file.is_open() )
{ {
// read file // read file
size = file.tellg(); size = file.tellg();
if ( size > 0 ) if ( size > 0 )
{ {
// read file into buffer // read file into buffer
buffer->resize((int)size+1); buffer->resize((int)size+1);
file.seekg (0, std::ios::beg); file.seekg (0, std::ios::beg);
file.read((char *)buffer->data(), (int)size); file.read((char *)buffer->data(), (int)size);
// close file // close file
file.close(); file.close();
// update time // update time
GetLastModTime(&m_LastModTime); GetLastModTime(&m_LastModTime);
// done // done
ok = true; ok = true;
} }
} }
// done // done
return ok; return ok;
} }
bool CDmridDirFile::RefreshContent(const CBuffer &buffer) bool CDmridDirFile::RefreshContent(const CBuffer &buffer)
{ {
bool ok = false; bool ok = false;
// clear directory // clear directory
m_CallsignMap.clear(); m_CallsignMap.clear();
m_DmridMap.clear(); m_DmridMap.clear();
// scan buffer // scan buffer
if ( buffer.size() > 0 ) if ( buffer.size() > 0 )
{ {
// crack it // crack it
char *ptr1 = (char *)buffer.data(); char *ptr1 = (char *)buffer.data();
char *ptr2; char *ptr2;
// get next line // get next line
while ( (ptr2 = ::strchr(ptr1, '\n')) != nullptr ) while ( (ptr2 = ::strchr(ptr1, '\n')) != nullptr )
{ {
*ptr2 = 0; *ptr2 = 0;
// get items // get items
char *dmrid; char *dmrid;
char *callsign; char *callsign;
if ( ((dmrid = ::strtok(ptr1, ";")) != nullptr) && IsValidDmrid(dmrid) ) if ( ((dmrid = ::strtok(ptr1, ";")) != nullptr) && IsValidDmrid(dmrid) )
{ {
if ( ((callsign = ::strtok(nullptr, ";")) != nullptr) ) if ( ((callsign = ::strtok(nullptr, ";")) != nullptr) )
{ {
// new entry // new entry
uint32 ui = atoi(dmrid); uint32 ui = atoi(dmrid);
CCallsign cs(callsign, ui); CCallsign cs(callsign, ui);
if ( cs.IsValid() ) if ( cs.IsValid() )
{ {
m_CallsignMap.insert(std::pair<uint32,CCallsign>(ui, cs)); m_CallsignMap.insert(std::pair<uint32,CCallsign>(ui, cs));
m_DmridMap.insert(std::pair<CCallsign,uint32>(cs,ui)); m_DmridMap.insert(std::pair<CCallsign,uint32>(cs,ui));
} }
} }
} }
// next line // next line
ptr1 = ptr2+1; ptr1 = ptr2+1;
} }
// done // done
ok = true; ok = true;
} }
// report // report
std::cout << "Read " << m_DmridMap.size() << " DMR ids from file " << DMRIDDB_PATH << std::endl; std::cout << "Read " << m_DmridMap.size() << " DMR ids from file " << DMRIDDB_PATH << std::endl;
// done // done
return ok; return ok;
} }
bool CDmridDirFile::GetLastModTime(time_t *time) bool CDmridDirFile::GetLastModTime(time_t *time)
{ {
bool ok = false; bool ok = false;
struct stat fileStat; struct stat fileStat;
if( ::stat(DMRIDDB_PATH, &fileStat) != -1 ) if( ::stat(DMRIDDB_PATH, &fileStat) != -1 )
{ {
*time = fileStat.st_mtime; *time = fileStat.st_mtime;
ok = true; ok = true;
} }
return ok; return ok;
} }

@ -32,28 +32,28 @@
class CDmridDirFile : public CDmridDir class CDmridDirFile : public CDmridDir
{ {
public: public:
// constructor // constructor
CDmridDirFile(); CDmridDirFile();
// destructor // destructor
~CDmridDirFile() {} ~CDmridDirFile() {}
// init & close // init & close
bool Init(void); bool Init(void);
// refresh // refresh
bool LoadContent(CBuffer *); bool LoadContent(CBuffer *);
bool RefreshContent(const CBuffer &); bool RefreshContent(const CBuffer &);
protected: protected:
// reload helpers // reload helpers
bool NeedReload(void); bool NeedReload(void);
bool GetLastModTime(time_t *); bool GetLastModTime(time_t *);
protected: protected:
// data // data
time_t m_LastModTime; time_t m_LastModTime;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
#endif /* cdmrididirfile_h */ #endif /* cdmrididirfile_h */

@ -39,56 +39,56 @@ CDmridDirHttp g_DmridDir;
bool CDmridDirHttp::LoadContent(CBuffer *buffer) bool CDmridDirHttp::LoadContent(CBuffer *buffer)
{ {
// get file from xlxapi server // get file from xlxapi server
return HttpGet("xlxapi.rlx.lu", "api/exportdmr.php", 80, buffer); return HttpGet("xlxapi.rlx.lu", "api/exportdmr.php", 80, buffer);
} }
bool CDmridDirHttp::RefreshContent(const CBuffer &buffer) bool CDmridDirHttp::RefreshContent(const CBuffer &buffer)
{ {
bool ok = false; bool ok = false;
// clear directory // clear directory
m_CallsignMap.clear(); m_CallsignMap.clear();
m_DmridMap.clear(); m_DmridMap.clear();
// scan file // scan file
if ( buffer.size() > 0 ) if ( buffer.size() > 0 )
{ {
char *ptr1 = (char *)buffer.data(); char *ptr1 = (char *)buffer.data();
char *ptr2; char *ptr2;
// get next line // get next line
while ( (ptr2 = ::strchr(ptr1, '\n')) != nullptr ) while ( (ptr2 = ::strchr(ptr1, '\n')) != nullptr )
{ {
*ptr2 = 0; *ptr2 = 0;
// get items // get items
char *dmrid; char *dmrid;
char *callsign; char *callsign;
if ( ((dmrid = ::strtok(ptr1, ";")) != nullptr) && IsValidDmrid(dmrid) ) if ( ((dmrid = ::strtok(ptr1, ";")) != nullptr) && IsValidDmrid(dmrid) )
{ {
if ( ((callsign = ::strtok(nullptr, ";")) != nullptr) ) if ( ((callsign = ::strtok(nullptr, ";")) != nullptr) )
{ {
// new entry // new entry
uint32 ui = atoi(dmrid); uint32 ui = atoi(dmrid);
CCallsign cs(callsign, ui); CCallsign cs(callsign, ui);
if ( cs.IsValid() ) if ( cs.IsValid() )
{ {
m_CallsignMap.insert(std::pair<uint32,CCallsign>(ui, cs)); m_CallsignMap.insert(std::pair<uint32,CCallsign>(ui, cs));
m_DmridMap.insert(std::pair<CCallsign,uint32>(cs,ui)); m_DmridMap.insert(std::pair<CCallsign,uint32>(cs,ui));
} }
} }
} }
// next line // next line
ptr1 = ptr2+1; ptr1 = ptr2+1;
} }
// done // done
ok = true; ok = true;
} }
// report // report
std::cout << "Read " << m_DmridMap.size() << " DMR ids from xlxapi.rlx.lu database " << std::endl; std::cout << "Read " << m_DmridMap.size() << " DMR ids from xlxapi.rlx.lu database " << std::endl;
// done // done
return ok; 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 CDmridDirHttp::HttpGet(const char *hostname, const char *filename, int port, CBuffer *buffer)
{ {
bool ok = false; bool ok = false;
int sock_id; int sock_id;
// open socket // open socket
if ( (sock_id = ::socket(AF_INET, SOCK_STREAM, 0)) >= 0 ) if ( (sock_id = ::socket(AF_INET, SOCK_STREAM, 0)) >= 0 )
{ {
// get hostname address // get hostname address
struct sockaddr_in servaddr; struct sockaddr_in servaddr;
struct hostent *hp; struct hostent *hp;
::memset(&servaddr,0,sizeof(servaddr)); ::memset(&servaddr,0,sizeof(servaddr));
if( (hp = gethostbyname(hostname)) != nullptr ) if( (hp = gethostbyname(hostname)) != nullptr )
{ {
// dns resolved // dns resolved
::memcpy((char *)&servaddr.sin_addr.s_addr, (char *)hp->h_addr, hp->h_length); ::memcpy((char *)&servaddr.sin_addr.s_addr, (char *)hp->h_addr, hp->h_length);
servaddr.sin_port = htons(port); servaddr.sin_port = htons(port);
servaddr.sin_family = AF_INET; servaddr.sin_family = AF_INET;
// connect // connect
if ( ::connect(sock_id, (struct sockaddr *)&servaddr, sizeof(servaddr)) == 0) if ( ::connect(sock_id, (struct sockaddr *)&servaddr, sizeof(servaddr)) == 0)
{ {
// send the GET request // send the GET request
char request[DMRID_HTTPGET_SIZEMAX]; char request[DMRID_HTTPGET_SIZEMAX];
::sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: xlxd\r\n\r\n", ::sprintf(request, "GET /%s HTTP/1.0\r\nFrom: %s\r\nUser-Agent: xlxd\r\n\r\n",
filename, (const char *)g_Reflector.GetCallsign()); filename, (const char *)g_Reflector.GetCallsign());
::write(sock_id, request, strlen(request)); ::write(sock_id, request, strlen(request));
// config receive timeouts // config receive timeouts
fd_set read_set; fd_set read_set;
struct timeval timeout; struct timeval timeout;
timeout.tv_sec = 5; timeout.tv_sec = 5;
timeout.tv_usec = 0; timeout.tv_usec = 0;
FD_ZERO(&read_set); FD_ZERO(&read_set);
FD_SET(sock_id, &read_set); FD_SET(sock_id, &read_set);
// get the reply back // get the reply back
buffer->clear(); buffer->clear();
bool done = false; bool done = false;
do do
{ {
char buf[1440]; char buf[1440];
ssize_t len = 0; ssize_t len = 0;
select(sock_id+1, &read_set, nullptr, nullptr, &timeout); select(sock_id+1, &read_set, nullptr, nullptr, &timeout);
//if ( (ret > 0) || ((ret < 0) && (errno == EINPROGRESS)) ) //if ( (ret > 0) || ((ret < 0) && (errno == EINPROGRESS)) )
//if ( ret >= 0 ) //if ( ret >= 0 )
//{ //{
usleep(5000); usleep(5000);
len = read(sock_id, buf, 1440); len = read(sock_id, buf, 1440);
if ( len > 0 ) if ( len > 0 )
{ {
buffer->Append((uint8 *)buf, (int)len); buffer->Append((uint8 *)buf, (int)len);
ok = true; ok = true;
} }
//} //}
done = (len <= 0); done = (len <= 0);
} while (!done); }
buffer->Append((uint8)0); while (!done);
buffer->Append((uint8)0);
// and disconnect
close(sock_id); // and disconnect
} close(sock_id);
else }
{ else
std::cout << "Cannot establish connection with host " << hostname << std::endl; {
} std::cout << "Cannot establish connection with host " << hostname << std::endl;
} }
else }
{ else
std::cout << "Host " << hostname << " not found" << std::endl; {
} std::cout << "Host " << hostname << " not found" << std::endl;
}
}
else }
{ else
std::cout << "Failed to open wget socket" << std::endl; {
} std::cout << "Failed to open wget socket" << std::endl;
}
// done
return ok; // done
return ok;
} }

@ -32,20 +32,20 @@
class CDmridDirHttp : public CDmridDir class CDmridDirHttp : public CDmridDir
{ {
public: public:
// constructor // constructor
CDmridDirHttp() {} CDmridDirHttp() {}
// destructor // destructor
~CDmridDirHttp() {} ~CDmridDirHttp() {}
// refresh // refresh
bool LoadContent(CBuffer *); bool LoadContent(CBuffer *);
bool RefreshContent(const CBuffer &); bool RefreshContent(const CBuffer &);
protected: protected:
// reload helpers // reload helpers
bool NeedReload(void) { return true; } bool NeedReload(void) { return true; }
bool HttpGet(const char *, const char *, int, CBuffer *); bool HttpGet(const char *, const char *, int, CBuffer *);
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -34,12 +34,12 @@ CDmrmmdvmClient::CDmrmmdvmClient()
} }
CDmrmmdvmClient::CDmrmmdvmClient(const CCallsign &callsign, const CIp &ip, char reflectorModule) CDmrmmdvmClient::CDmrmmdvmClient(const CCallsign &callsign, const CIp &ip, char reflectorModule)
: CClient(callsign, ip, reflectorModule) : CClient(callsign, ip, reflectorModule)
{ {
} }
CDmrmmdvmClient::CDmrmmdvmClient(const CDmrmmdvmClient &client) CDmrmmdvmClient::CDmrmmdvmClient(const CDmrmmdvmClient &client)
: CClient(client) : CClient(client)
{ {
} }
@ -48,5 +48,5 @@ CDmrmmdvmClient::CDmrmmdvmClient(const CDmrmmdvmClient &client)
bool CDmrmmdvmClient::IsAlive(void) const bool CDmrmmdvmClient::IsAlive(void) const
{ {
return (m_LastKeepaliveTime.DurationSinceNow() < DMRMMDVM_KEEPALIVE_TIMEOUT); return (m_LastKeepaliveTime.DurationSinceNow() < DMRMMDVM_KEEPALIVE_TIMEOUT);
} }

@ -37,22 +37,22 @@
class CDmrmmdvmClient : public CClient class CDmrmmdvmClient : public CClient
{ {
public: public:
// constructors // constructors
CDmrmmdvmClient(); CDmrmmdvmClient();
CDmrmmdvmClient(const CCallsign &, const CIp &, char = ' '); CDmrmmdvmClient(const CCallsign &, const CIp &, char = ' ');
CDmrmmdvmClient(const CDmrmmdvmClient &); CDmrmmdvmClient(const CDmrmmdvmClient &);
// destructor // destructor
virtual ~CDmrmmdvmClient() {}; virtual ~CDmrmmdvmClient() {};
// identity // identity
int GetProtocol(void) const { return PROTOCOL_DMRMMDVM; } int GetProtocol(void) const { return PROTOCOL_DMRMMDVM; }
const char *GetProtocolName(void) const { return "DMRMmdvm"; } const char *GetProtocolName(void) const { return "DMRMmdvm"; }
int GetCodec(void) const { return CODEC_AMBE2PLUS; } int GetCodec(void) const { return CODEC_AMBE2PLUS; }
bool IsNode(void) const { return true; } bool IsNode(void) const { return true; }
// status // status
bool IsAlive(void) const; bool IsAlive(void) const;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

@ -52,82 +52,82 @@
class CDmrmmdvmStreamCacheItem class CDmrmmdvmStreamCacheItem
{ {
public: public:
CDmrmmdvmStreamCacheItem() {} CDmrmmdvmStreamCacheItem() {}
~CDmrmmdvmStreamCacheItem() {} ~CDmrmmdvmStreamCacheItem() {}
CDvHeaderPacket m_dvHeader; CDvHeaderPacket m_dvHeader;
CDvFramePacket m_dvFrame0; CDvFramePacket m_dvFrame0;
CDvFramePacket m_dvFrame1; CDvFramePacket m_dvFrame1;
uint8 m_uiSeqId; uint8 m_uiSeqId;
}; };
class CDmrmmdvmProtocol : public CProtocol class CDmrmmdvmProtocol : public CProtocol
{ {
public: public:
// initialization // initialization
bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6);
// task // task
void Task(void); void Task(void);
protected: protected:
// queue helper // queue helper
void HandleQueue(void); void HandleQueue(void);
// keepalive helpers // keepalive helpers
void HandleKeepalives(void); void HandleKeepalives(void);
// stream helpers // stream helpers
bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &, uint8, uint8); bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &, uint8, uint8);
// packet decoding helpers // packet decoding helpers
bool IsValidConnectPacket(const CBuffer &, CCallsign *, const CIp &); bool IsValidConnectPacket(const CBuffer &, CCallsign *, const CIp &);
bool IsValidAuthenticationPacket(const CBuffer &, CCallsign *, const CIp &); bool IsValidAuthenticationPacket(const CBuffer &, CCallsign *, const CIp &);
bool IsValidDisconnectPacket(const CBuffer &, CCallsign *); bool IsValidDisconnectPacket(const CBuffer &, CCallsign *);
bool IsValidConfigPacket(const CBuffer &, CCallsign *, const CIp &); bool IsValidConfigPacket(const CBuffer &, CCallsign *, const CIp &);
bool IsValidOptionPacket(const CBuffer &, CCallsign *); bool IsValidOptionPacket(const CBuffer &, CCallsign *);
bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *);
bool IsValidRssiPacket(const CBuffer &, CCallsign *, int *); bool IsValidRssiPacket(const CBuffer &, CCallsign *, int *);
bool IsValidDvHeaderPacket(const CBuffer &, CDvHeaderPacket **, uint8 *, uint8 *); bool IsValidDvHeaderPacket(const CBuffer &, CDvHeaderPacket **, uint8 *, uint8 *);
bool IsValidDvFramePacket(const CBuffer &, CDvFramePacket **); bool IsValidDvFramePacket(const CBuffer &, CDvFramePacket **);
bool IsValidDvLastFramePacket(const CBuffer &, CDvLastFramePacket **); bool IsValidDvLastFramePacket(const CBuffer &, CDvLastFramePacket **);
// packet encoding helpers // packet encoding helpers
void EncodeKeepAlivePacket(CBuffer *, std::shared_ptr<CClient>); void EncodeKeepAlivePacket(CBuffer *, std::shared_ptr<CClient>);
void EncodeAckPacket(CBuffer *, const CCallsign &); void EncodeAckPacket(CBuffer *, const CCallsign &);
void EncodeConnectAckPacket(CBuffer *, const CCallsign &, uint32); void EncodeConnectAckPacket(CBuffer *, const CCallsign &, uint32);
void EncodeNackPacket(CBuffer *, const CCallsign &); void EncodeNackPacket(CBuffer *, const CCallsign &);
void EncodeClosePacket(CBuffer *, std::shared_ptr<CClient>); void EncodeClosePacket(CBuffer *, std::shared_ptr<CClient>);
bool EncodeDvHeaderPacket(const CDvHeaderPacket &, uint8, CBuffer *) const; bool EncodeDvHeaderPacket(const CDvHeaderPacket &, uint8, CBuffer *) const;
void EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket &, const CDvFramePacket &, const CDvFramePacket &, uint8, CBuffer *) const; void EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket &, const CDvFramePacket &, const CDvFramePacket &, uint8, CBuffer *) const;
void EncodeDvLastPacket(const CDvHeaderPacket &, uint8, CBuffer *) const; void EncodeDvLastPacket(const CDvHeaderPacket &, uint8, CBuffer *) const;
// dmr DstId to Module helper // dmr DstId to Module helper
char DmrDstIdToModule(uint32) const; char DmrDstIdToModule(uint32) const;
uint32 ModuleToDmrDestId(char) const; uint32 ModuleToDmrDestId(char) const;
// Buffer & LC helpers // Buffer & LC helpers
void AppendVoiceLCToBuffer(CBuffer *, uint32) const; void AppendVoiceLCToBuffer(CBuffer *, uint32) const;
void AppendTerminatorLCToBuffer(CBuffer *, uint32) const; void AppendTerminatorLCToBuffer(CBuffer *, uint32) const;
void ReplaceEMBInBuffer(CBuffer *, uint8) const; void ReplaceEMBInBuffer(CBuffer *, uint8) const;
void AppendDmrIdToBuffer(CBuffer *, uint32) const; void AppendDmrIdToBuffer(CBuffer *, uint32) const;
void AppendDmrRptrIdToBuffer(CBuffer *, uint32) const; void AppendDmrRptrIdToBuffer(CBuffer *, uint32) const;
protected: protected:
// for keep alive // for keep alive
CTimePoint m_LastKeepaliveTime; CTimePoint m_LastKeepaliveTime;
// for stream id // for stream id
uint16 m_uiStreamId; uint16 m_uiStreamId;
// for queue header caches // for queue header caches
std::array<CDmrmmdvmStreamCacheItem, NB_OF_MODULES> m_StreamsCache; std::array<CDmrmmdvmStreamCacheItem, NB_OF_MODULES> m_StreamsCache;
// for authentication // for authentication
uint32 m_uiAuthSeed; uint32 m_uiAuthSeed;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -34,12 +34,12 @@ CDmrplusClient::CDmrplusClient()
} }
CDmrplusClient::CDmrplusClient(const CCallsign &callsign, const CIp &ip, char reflectorModule) CDmrplusClient::CDmrplusClient(const CCallsign &callsign, const CIp &ip, char reflectorModule)
: CClient(callsign, ip, reflectorModule) : CClient(callsign, ip, reflectorModule)
{ {
} }
CDmrplusClient::CDmrplusClient(const CDmrplusClient &client) CDmrplusClient::CDmrplusClient(const CDmrplusClient &client)
: CClient(client) : CClient(client)
{ {
} }
@ -48,5 +48,5 @@ CDmrplusClient::CDmrplusClient(const CDmrplusClient &client)
bool CDmrplusClient::IsAlive(void) const bool CDmrplusClient::IsAlive(void) const
{ {
return (m_LastKeepaliveTime.DurationSinceNow() < DMRPLUS_KEEPALIVE_TIMEOUT); return (m_LastKeepaliveTime.DurationSinceNow() < DMRPLUS_KEEPALIVE_TIMEOUT);
} }

@ -37,22 +37,22 @@
class CDmrplusClient : public CClient class CDmrplusClient : public CClient
{ {
public: public:
// constructors // constructors
CDmrplusClient(); CDmrplusClient();
CDmrplusClient(const CCallsign &, const CIp &, char = ' '); CDmrplusClient(const CCallsign &, const CIp &, char = ' ');
CDmrplusClient(const CDmrplusClient &); CDmrplusClient(const CDmrplusClient &);
// destructor // destructor
virtual ~CDmrplusClient() {}; virtual ~CDmrplusClient() {};
// identity // identity
int GetProtocol(void) const { return PROTOCOL_DMRPLUS; } int GetProtocol(void) const { return PROTOCOL_DMRPLUS; }
const char *GetProtocolName(void) const { return "DMRplus"; } const char *GetProtocolName(void) const { return "DMRplus"; }
int GetCodec(void) const { return CODEC_AMBE2PLUS; } int GetCodec(void) const { return CODEC_AMBE2PLUS; }
bool IsNode(void) const { return true; } bool IsNode(void) const { return true; }
// status // status
bool IsAlive(void) const; bool IsAlive(void) const;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

@ -43,72 +43,72 @@
class CDmrplusStreamCacheItem class CDmrplusStreamCacheItem
{ {
public: public:
CDmrplusStreamCacheItem() { m_uiSeqId = 0x77; } CDmrplusStreamCacheItem() { m_uiSeqId = 0x77; }
CDvHeaderPacket m_dvHeader; CDvHeaderPacket m_dvHeader;
CDvFramePacket m_dvFrame0; CDvFramePacket m_dvFrame0;
CDvFramePacket m_dvFrame1; CDvFramePacket m_dvFrame1;
uint8 m_uiSeqId; uint8 m_uiSeqId;
}; };
class CDmrplusProtocol : public CProtocol class CDmrplusProtocol : public CProtocol
{ {
public: public:
// initialization // initialization
bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6);
// task // task
void Task(void); void Task(void);
protected: protected:
// queue helper // queue helper
void HandleQueue(void); void HandleQueue(void);
void SendBufferToClients(const CBuffer &, uint8); void SendBufferToClients(const CBuffer &, uint8);
// keepalive helpers // keepalive helpers
void HandleKeepalives(void); void HandleKeepalives(void);
// stream helpers // stream helpers
bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &);
// packet decoding helpers // packet decoding helpers
bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, const CIp &); bool IsValidConnectPacket(const CBuffer &, CCallsign *, char *, const CIp &);
bool IsValidDisconnectPacket(const CBuffer &, CCallsign *, char *); bool IsValidDisconnectPacket(const CBuffer &, CCallsign *, char *);
bool IsValidDvHeaderPacket(const CIp &, const CBuffer &, CDvHeaderPacket **); bool IsValidDvHeaderPacket(const CIp &, const CBuffer &, CDvHeaderPacket **);
bool IsValidDvFramePacket(const CIp &, const CBuffer &, CDvFramePacket **); bool IsValidDvFramePacket(const CIp &, const CBuffer &, CDvFramePacket **);
// packet encoding helpers // packet encoding helpers
void EncodeConnectAckPacket(CBuffer *); void EncodeConnectAckPacket(CBuffer *);
void EncodeConnectNackPacket(CBuffer *); void EncodeConnectNackPacket(CBuffer *);
bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const;
void EncodeDvPacket(const CDvHeaderPacket &, const CDvFramePacket &, const CDvFramePacket &, const CDvFramePacket &, uint8, 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 EncodeDvLastPacket(const CDvHeaderPacket &, const CDvFramePacket &, const CDvFramePacket &, const CDvFramePacket &, uint8, CBuffer *) const;
void SwapEndianess(uint8 *, int) const; void SwapEndianess(uint8 *, int) const;
// dmr SeqId helper // dmr SeqId helper
uint8 GetNextSeqId(uint8) const; uint8 GetNextSeqId(uint8) const;
// dmr DstId to Module helper // dmr DstId to Module helper
char DmrDstIdToModule(uint32) const; char DmrDstIdToModule(uint32) const;
uint32 ModuleToDmrDestId(char) const; uint32 ModuleToDmrDestId(char) const;
// uiStreamId helpers // uiStreamId helpers
uint32 IpToStreamId(const CIp &) const; uint32 IpToStreamId(const CIp &) const;
// Buffer & LC helpers // Buffer & LC helpers
void AppendVoiceLCToBuffer(CBuffer *, uint32) const; void AppendVoiceLCToBuffer(CBuffer *, uint32) const;
void AppendTerminatorLCToBuffer(CBuffer *, uint32) const; void AppendTerminatorLCToBuffer(CBuffer *, uint32) const;
void ReplaceEMBInBuffer(CBuffer *, uint8) const; void ReplaceEMBInBuffer(CBuffer *, uint8) const;
protected: protected:
// for keep alive // for keep alive
CTimePoint m_LastKeepaliveTime; CTimePoint m_LastKeepaliveTime;
// for queue header caches // for queue header caches
std::array<CDmrplusStreamCacheItem, NB_OF_MODULES> m_StreamsCache; std::array<CDmrplusStreamCacheItem, NB_OF_MODULES> m_StreamsCache;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -19,7 +19,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#include "main.h" #include "main.h"
@ -31,19 +31,19 @@
CDplusClient::CDplusClient() CDplusClient::CDplusClient()
{ {
m_bDextraDongle = false; m_bDextraDongle = false;
} }
CDplusClient::CDplusClient(const CCallsign &callsign, const CIp &ip, char reflectorModule) 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) 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 bool CDplusClient::IsAlive(void) const
{ {
return (m_LastKeepaliveTime.DurationSinceNow() < DPLUS_KEEPALIVE_TIMEOUT); return (m_LastKeepaliveTime.DurationSinceNow() < DPLUS_KEEPALIVE_TIMEOUT);
} }
void CDplusClient::SetMasterOfModule(char c) void CDplusClient::SetMasterOfModule(char c)
{ {
CClient::SetMasterOfModule(c); CClient::SetMasterOfModule(c);
SetReflectorModule(c); SetReflectorModule(c);
} }

@ -19,7 +19,7 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Foobar. If not, see <http://www.gnu.org/licenses/>. // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#ifndef cdplusclient_h #ifndef cdplusclient_h
@ -37,29 +37,29 @@
class CDplusClient : public CClient class CDplusClient : public CClient
{ {
public: public:
// constructors // constructors
CDplusClient(); CDplusClient();
CDplusClient(const CCallsign &, const CIp &, char = ' '); CDplusClient(const CCallsign &, const CIp &, char = ' ');
CDplusClient(const CDplusClient &); CDplusClient(const CDplusClient &);
// destructor // destructor
virtual ~CDplusClient() {}; virtual ~CDplusClient() {};
// identity // identity
int GetProtocol(void) const { return PROTOCOL_DPLUS; } int GetProtocol(void) const { return PROTOCOL_DPLUS; }
const char *GetProtocolName(void) const { return "DPlus"; } const char *GetProtocolName(void) const { return "DPlus"; }
int GetCodec(void) const { return CODEC_AMBEPLUS; } int GetCodec(void) const { return CODEC_AMBEPLUS; }
bool IsNode(void) const { return true; } bool IsNode(void) const { return true; }
bool IsDextraDongle(void) const { return m_bDextraDongle; } bool IsDextraDongle(void) const { return m_bDextraDongle; }
void SetDextraDongle(void) { m_bDextraDongle = true; } void SetDextraDongle(void) { m_bDextraDongle = true; }
// status // status
bool IsAlive(void) const; bool IsAlive(void) const;
void SetMasterOfModule(char); void SetMasterOfModule(char);
protected: protected:
// data // data
bool m_bDextraDongle; bool m_bDextraDongle;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -36,15 +36,15 @@
bool CDplusProtocol::Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6) bool CDplusProtocol::Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6)
{ {
// base class // base class
if (! CProtocol::Initialize(type, port, has_ipv4, has_ipv6)) if (! CProtocol::Initialize(type, port, has_ipv4, has_ipv6))
return false; return false;
// update time // update time
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
// done // done
return true; return true;
} }
@ -54,14 +54,14 @@ bool CDplusProtocol::Initalize(const char *type, const uint16 port, const bool h
void CDplusProtocol::Task(void) void CDplusProtocol::Task(void)
{ {
CBuffer Buffer; CBuffer Buffer;
CIp Ip; CIp Ip;
CCallsign Callsign; CCallsign Callsign;
CDvHeaderPacket *Header; CDvHeaderPacket *Header;
CDvFramePacket *Frame; CDvFramePacket *Frame;
CDvLastFramePacket *LastFrame; CDvLastFramePacket *LastFrame;
// handle incoming packets // handle incoming packets
#if DSTAR_IPV6==true #if DSTAR_IPV6==true
#if DSTAR_IPV4==true #if DSTAR_IPV4==true
if ( ReceiveDS(Buffer, Ip, 20) ) if ( ReceiveDS(Buffer, Ip, 20) )
@ -71,191 +71,191 @@ void CDplusProtocol::Task(void)
#else #else
if ( Receive4(Buffer, Ip, 20) ) if ( Receive4(Buffer, Ip, 20) )
#endif #endif
{ {
// crack the packet // crack the packet
if ( (Frame = IsValidDvFramePacket(Buffer)) != nullptr ) if ( (Frame = IsValidDvFramePacket(Buffer)) != nullptr )
{ {
//std::cout << "DPlus DV frame" << std::endl; //std::cout << "DPlus DV frame" << std::endl;
// handle it // handle it
OnDvFramePacketIn(Frame, &Ip); OnDvFramePacketIn(Frame, &Ip);
} }
else if ( (Header = IsValidDvHeaderPacket(Buffer)) != nullptr ) else if ( (Header = IsValidDvHeaderPacket(Buffer)) != nullptr )
{ {
//std::cout << "DPlus DV header:" << std::endl << *Header << std::endl; //std::cout << "DPlus DV header:" << std::endl << *Header << std::endl;
// callsign muted? // callsign muted?
if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_DPLUS, Header->GetRpt2Module()) ) if ( g_GateKeeper.MayTransmit(Header->GetMyCallsign(), Ip, PROTOCOL_DPLUS, Header->GetRpt2Module()) )
{ {
// handle it // handle it
OnDvHeaderPacketIn(Header, Ip); OnDvHeaderPacketIn(Header, Ip);
} }
else else
{ {
delete Header; delete Header;
} }
} }
else if ( (LastFrame = IsValidDvLastFramePacket(Buffer)) != nullptr ) else if ( (LastFrame = IsValidDvLastFramePacket(Buffer)) != nullptr )
{ {
//std::cout << "DPlus DV last frame" << std::endl; //std::cout << "DPlus DV last frame" << std::endl;
// handle it // handle it
OnDvLastFramePacketIn(LastFrame, &Ip); OnDvLastFramePacketIn(LastFrame, &Ip);
} }
else if ( IsValidConnectPacket(Buffer) ) else if ( IsValidConnectPacket(Buffer) )
{ {
std::cout << "DPlus connect request packet from " << Ip << std::endl; std::cout << "DPlus connect request packet from " << Ip << std::endl;
// acknowledge the request // acknowledge the request
Send(Buffer, Ip); Send(Buffer, Ip);
} }
else if ( IsValidLoginPacket(Buffer, &Callsign) ) else if ( IsValidLoginPacket(Buffer, &Callsign) )
{ {
std::cout << "DPlus login packet from " << Callsign << " at " << Ip << std::endl; std::cout << "DPlus login packet from " << Callsign << " at " << Ip << std::endl;
// callsign authorized? // callsign authorized?
if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_DPLUS) ) if ( g_GateKeeper.MayLink(Callsign, Ip, PROTOCOL_DPLUS) )
{ {
// acknowledge the request // acknowledge the request
EncodeLoginAckPacket(&Buffer); EncodeLoginAckPacket(&Buffer);
Send(Buffer, Ip); Send(Buffer, Ip);
// create the client and append // create the client and append
g_Reflector.GetClients()->AddClient(std::make_shared<CDplusClient>(Callsign, Ip)); g_Reflector.GetClients()->AddClient(std::make_shared<CDplusClient>(Callsign, Ip));
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
} }
else else
{ {
// deny the request // deny the request
EncodeLoginNackPacket(&Buffer); EncodeLoginNackPacket(&Buffer);
Send(Buffer, Ip); Send(Buffer, Ip);
} }
} }
else if ( IsValidDisconnectPacket(Buffer) ) else if ( IsValidDisconnectPacket(Buffer) )
{ {
std::cout << "DPlus disconnect packet from " << Ip << std::endl; std::cout << "DPlus disconnect packet from " << Ip << std::endl;
// find client // find client
CClients *clients = g_Reflector.GetClients(); CClients *clients = g_Reflector.GetClients();
std::shared_ptr<CClient>client = clients->FindClient(Ip, PROTOCOL_DPLUS); std::shared_ptr<CClient>client = clients->FindClient(Ip, PROTOCOL_DPLUS);
if ( client != nullptr ) if ( client != nullptr )
{ {
// remove it // remove it
clients->RemoveClient(client); clients->RemoveClient(client);
// and acknowledge the disconnect // and acknowledge the disconnect
EncodeDisconnectPacket(&Buffer); EncodeDisconnectPacket(&Buffer);
Send(Buffer, Ip); Send(Buffer, Ip);
} }
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
} }
else if ( IsValidKeepAlivePacket(Buffer) ) else if ( IsValidKeepAlivePacket(Buffer) )
{ {
//std::cout << "DPlus keepalive packet from " << Ip << std::endl; //std::cout << "DPlus keepalive packet from " << Ip << std::endl;
// find all clients with that callsign & ip and keep them alive // find all clients with that callsign & ip and keep them alive
CClients *clients = g_Reflector.GetClients(); CClients *clients = g_Reflector.GetClients();
auto it = clients->begin(); auto it = clients->begin();
std::shared_ptr<CClient>client = nullptr; std::shared_ptr<CClient>client = nullptr;
while ( (client = clients->FindNextClient(Ip, PROTOCOL_DPLUS, it)) != nullptr ) while ( (client = clients->FindNextClient(Ip, PROTOCOL_DPLUS, it)) != nullptr )
{ {
client->Alive(); client->Alive();
} }
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
} }
else else
{ {
std::cout << "DPlus packet (" << Buffer.size() << ")" << std::endl; std::cout << "DPlus packet (" << Buffer.size() << ")" << std::endl;
} }
} }
// handle end of streaming timeout // handle end of streaming timeout
CheckStreamsTimeout(); CheckStreamsTimeout();
// handle queue from reflector // handle queue from reflector
HandleQueue(); HandleQueue();
// keep client alive // keep client alive
if ( m_LastKeepaliveTime.DurationSinceNow() > DPLUS_KEEPALIVE_PERIOD ) if ( m_LastKeepaliveTime.DurationSinceNow() > DPLUS_KEEPALIVE_PERIOD )
{ {
// //
HandleKeepalives(); HandleKeepalives();
// update time // update time
m_LastKeepaliveTime.Now(); m_LastKeepaliveTime.Now();
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
// streams helpers // streams helpers
bool CDplusProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip) bool CDplusProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip)
{ {
bool newstream = false; bool newstream = false;
// find the stream // find the stream
CPacketStream *stream = GetStream(Header->GetStreamId()); CPacketStream *stream = GetStream(Header->GetStreamId());
if ( stream == nullptr ) if ( stream == nullptr )
{ {
// no stream open yet, open a new one // no stream open yet, open a new one
CCallsign via(Header->GetRpt1Callsign()); CCallsign via(Header->GetRpt1Callsign());
// first, check module is valid // first, check module is valid
if ( g_Reflector.IsValidModule(Header->GetRpt1Module()) ) if ( g_Reflector.IsValidModule(Header->GetRpt1Module()) )
{ {
// find this client // find this client
std::shared_ptr<CClient>client = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_DPLUS); std::shared_ptr<CClient>client = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_DPLUS);
if ( client != nullptr ) if ( client != nullptr )
{ {
// now we know if it's a dextra dongle or a genuine dplus node // now we know if it's a dextra dongle or a genuine dplus node
if ( Header->GetRpt2Callsign().HasSameCallsignWithWildcard(CCallsign("XRF*")) ) if ( Header->GetRpt2Callsign().HasSameCallsignWithWildcard(CCallsign("XRF*")) )
{ {
client->SetDextraDongle(); client->SetDextraDongle();
} }
// now we know its module, let's update it // now we know its module, let's update it
if ( !client->HasModule() ) if ( !client->HasModule() )
{ {
client->SetModule(Header->GetRpt1Module()); client->SetModule(Header->GetRpt1Module());
} }
// get client callsign // get client callsign
via = client->GetCallsign(); via = client->GetCallsign();
// and try to open the stream // and try to open the stream
if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr ) if ( (stream = g_Reflector.OpenStream(Header, client)) != nullptr )
{ {
// keep the handle // keep the handle
m_Streams.push_back(stream); m_Streams.push_back(stream);
newstream = true; newstream = true;
} }
} }
// release // release
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
// update last heard // update last heard
g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), via, Header->GetRpt2Callsign()); g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), via, Header->GetRpt2Callsign());
g_Reflector.ReleaseUsers(); g_Reflector.ReleaseUsers();
// delete header if needed // delete header if needed
if ( !newstream ) if ( !newstream )
{ {
delete Header; delete Header;
} }
} }
else else
{ {
std::cout << "DPlus node " << via << " link attempt on non-existing module" << std::endl; std::cout << "DPlus node " << via << " link attempt on non-existing module" << std::endl;
} }
} }
else else
{ {
// stream already open // stream already open
// skip packet, but tickle the stream // skip packet, but tickle the stream
stream->Tickle(); stream->Tickle();
// and delete packet // and delete packet
delete Header; delete Header;
} }
// done // done
return newstream; return newstream;
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -263,113 +263,113 @@ bool CDplusProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip)
void CDplusProtocol::HandleQueue(void) void CDplusProtocol::HandleQueue(void)
{ {
m_Queue.Lock(); m_Queue.Lock();
while ( !m_Queue.empty() ) while ( !m_Queue.empty() )
{ {
// get the packet // get the packet
CPacket *packet = m_Queue.front(); CPacket *packet = m_Queue.front();
m_Queue.pop(); m_Queue.pop();
// get our sender's id // get our sender's id
int iModId = g_Reflector.GetModuleIndex(packet->GetModuleId()); int iModId = g_Reflector.GetModuleIndex(packet->GetModuleId());
// check if it's header and update cache // check if it's header and update cache
if ( packet->IsDvHeader() ) if ( packet->IsDvHeader() )
{ {
// this relies on queue feeder setting valid module id // this relies on queue feeder setting valid module id
m_StreamsCache[iModId].m_dvHeader = CDvHeaderPacket((const CDvHeaderPacket &)*packet); m_StreamsCache[iModId].m_dvHeader = CDvHeaderPacket((const CDvHeaderPacket &)*packet);
m_StreamsCache[iModId].m_iSeqCounter = 0; m_StreamsCache[iModId].m_iSeqCounter = 0;
} }
// encode it // encode it
CBuffer buffer; CBuffer buffer;
if ( EncodeDvPacket(*packet, &buffer) ) if ( EncodeDvPacket(*packet, &buffer) )
{ {
// and push it to all our clients who are not streaming in // 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 // 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 // it's client who decide which stream he's interrrested in
CClients *clients = g_Reflector.GetClients(); CClients *clients = g_Reflector.GetClients();
auto it = clients->begin(); auto it = clients->begin();
std::shared_ptr<CClient>client = nullptr; std::shared_ptr<CClient>client = nullptr;
while ( (client = clients->FindNextClient(PROTOCOL_DPLUS, it)) != nullptr ) while ( (client = clients->FindNextClient(PROTOCOL_DPLUS, it)) != nullptr )
{ {
// is this client busy ? // is this client busy ?
if ( !client->IsAMaster() ) if ( !client->IsAMaster() )
{ {
// check if client is a dextra dongle // check if client is a dextra dongle
// then replace RPT2 with XRF instead of REF // then replace RPT2 with XRF instead of REF
// if the client type is not yet known, send bothheaders // if the client type is not yet known, send bothheaders
if ( packet->IsDvHeader() ) if ( packet->IsDvHeader() )
{ {
// sending header in Dplus is client specific // sending header in Dplus is client specific
SendDvHeader((CDvHeaderPacket *)packet, (CDplusClient *)client.get()); SendDvHeader((CDvHeaderPacket *)packet, (CDplusClient *)client.get());
} }
else if ( packet->IsDvFrame() ) else if ( packet->IsDvFrame() )
{ {
// and send the DV frame // and send the DV frame
Send(buffer, client->GetIp()); Send(buffer, client->GetIp());
// is it time to insert a DVheader copy ? // is it time to insert a DVheader copy ?
if ( (m_StreamsCache[iModId].m_iSeqCounter++ % 21) == 20 ) if ( (m_StreamsCache[iModId].m_iSeqCounter++ % 21) == 20 )
{ {
// yes, clone it // yes, clone it
CDvHeaderPacket packet2(m_StreamsCache[iModId].m_dvHeader); CDvHeaderPacket packet2(m_StreamsCache[iModId].m_dvHeader);
// and send it // and send it
SendDvHeader(&packet2, (CDplusClient *)client.get()); SendDvHeader(&packet2, (CDplusClient *)client.get());
} }
} }
else else
{ {
// otherwise, send the original packet // otherwise, send the original packet
Send(buffer, client->GetIp()); Send(buffer, client->GetIp());
} }
} }
} }
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
} }
// done // done
delete packet; delete packet;
} }
m_Queue.Unlock(); m_Queue.Unlock();
} }
void CDplusProtocol::SendDvHeader(CDvHeaderPacket *packet, CDplusClient *client) void CDplusProtocol::SendDvHeader(CDvHeaderPacket *packet, CDplusClient *client)
{ {
// encode it // encode it
CBuffer buffer; CBuffer buffer;
if ( EncodeDvPacket(*packet, &buffer) ) if ( EncodeDvPacket(*packet, &buffer) )
{ {
if ( (client->IsDextraDongle() || !client->HasModule()) ) if ( (client->IsDextraDongle() || !client->HasModule()) )
{ {
// clone the packet and patch it // clone the packet and patch it
CDvHeaderPacket packet2(*((CDvHeaderPacket *)packet)); CDvHeaderPacket packet2(*((CDvHeaderPacket *)packet));
CCallsign rpt2 = packet2.GetRpt2Callsign(); CCallsign rpt2 = packet2.GetRpt2Callsign();
rpt2.PatchCallsign(0, (const uint8 *)"XRF", 3); rpt2.PatchCallsign(0, (const uint8 *)"XRF", 3);
packet2.SetRpt2Callsign(rpt2); packet2.SetRpt2Callsign(rpt2);
// encode it // encode it
CBuffer buffer2; CBuffer buffer2;
if ( EncodeDvPacket(packet2, &buffer2) ) if ( EncodeDvPacket(packet2, &buffer2) )
{ {
// and send it // and send it
Send(buffer2, client->GetIp()); Send(buffer2, client->GetIp());
} }
// client type known ? // client type known ?
if ( !client->HasModule() ) if ( !client->HasModule() )
{ {
// no, send also the genuine packet // no, send also the genuine packet
Send(buffer, client->GetIp()); Send(buffer, client->GetIp());
} }
} }
else else
{ {
// otherwise, send the original packet // otherwise, send the original packet
Send(buffer, client->GetIp()); Send(buffer, client->GetIp());
} }
} }
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -377,40 +377,40 @@ void CDplusProtocol::SendDvHeader(CDvHeaderPacket *packet, CDplusClient *client)
void CDplusProtocol::HandleKeepalives(void) void CDplusProtocol::HandleKeepalives(void)
{ {
// send keepalives // send keepalives
CBuffer keepalive; CBuffer keepalive;
EncodeKeepAlivePacket(&keepalive); EncodeKeepAlivePacket(&keepalive);
// iterate on clients // iterate on clients
CClients *clients = g_Reflector.GetClients(); CClients *clients = g_Reflector.GetClients();
auto it = clients->begin(); auto it = clients->begin();
std::shared_ptr<CClient>client = nullptr; std::shared_ptr<CClient>client = nullptr;
while ( (client = clients->FindNextClient(PROTOCOL_DPLUS, it)) != nullptr ) while ( (client = clients->FindNextClient(PROTOCOL_DPLUS, it)) != nullptr )
{ {
// send keepalive // send keepalive
//std::cout << "Sending DPlus packet @ " << client->GetIp() << std::endl; //std::cout << "Sending DPlus packet @ " << client->GetIp() << std::endl;
Send(keepalive, client->GetIp()); Send(keepalive, client->GetIp());
// is this client busy ? // is this client busy ?
if ( client->IsAMaster() ) if ( client->IsAMaster() )
{ {
// yes, just tickle it // yes, just tickle it
client->Alive(); client->Alive();
} }
// check it's still with us // check it's still with us
else if ( !client->IsAlive() ) else if ( !client->IsAlive() )
{ {
// no, disconnect // no, disconnect
CBuffer disconnect; CBuffer disconnect;
EncodeDisconnectPacket(&disconnect); EncodeDisconnectPacket(&disconnect);
Send(disconnect, client->GetIp()); Send(disconnect, client->GetIp());
// and remove it // and remove it
std::cout << "DPlus client " << client->GetCallsign() << " keepalive timeout" << std::endl; std::cout << "DPlus client " << client->GetCallsign() << " keepalive timeout" << std::endl;
clients->RemoveClient(client); clients->RemoveClient(client);
} }
} }
g_Reflector.ReleaseClients(); g_Reflector.ReleaseClients();
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -418,99 +418,99 @@ void CDplusProtocol::HandleKeepalives(void)
bool CDplusProtocol::IsValidConnectPacket(const CBuffer &Buffer) bool CDplusProtocol::IsValidConnectPacket(const CBuffer &Buffer)
{ {
uint8 tag[] = { 0x05,0x00,0x18,0x00,0x01 }; uint8 tag[] = { 0x05,0x00,0x18,0x00,0x01 };
return (Buffer == CBuffer(tag, sizeof(tag))); return (Buffer == CBuffer(tag, sizeof(tag)));
} }
bool CDplusProtocol::IsValidLoginPacket(const CBuffer &Buffer, CCallsign *Callsign) bool CDplusProtocol::IsValidLoginPacket(const CBuffer &Buffer, CCallsign *Callsign)
{ {
uint8 Tag[] = { 0x1C,0xC0,0x04,0x00 }; uint8 Tag[] = { 0x1C,0xC0,0x04,0x00 };
bool valid = false; bool valid = false;
if ( (Buffer.size() == 28) &&(::memcmp(Buffer.data(), Tag, sizeof(Tag)) == 0) ) if ( (Buffer.size() == 28) &&(::memcmp(Buffer.data(), Tag, sizeof(Tag)) == 0) )
{ {
Callsign->SetCallsign(&(Buffer.data()[4]), 8); Callsign->SetCallsign(&(Buffer.data()[4]), 8);
valid = Callsign->IsValid(); valid = Callsign->IsValid();
} }
return valid; return valid;
} }
bool CDplusProtocol::IsValidDisconnectPacket(const CBuffer &Buffer) bool CDplusProtocol::IsValidDisconnectPacket(const CBuffer &Buffer)
{ {
uint8 tag[] = { 0x05,0x00,0x18,0x00,0x00 }; uint8 tag[] = { 0x05,0x00,0x18,0x00,0x00 };
return (Buffer == CBuffer(tag, sizeof(tag))); return (Buffer == CBuffer(tag, sizeof(tag)));
} }
bool CDplusProtocol::IsValidKeepAlivePacket(const CBuffer &Buffer) bool CDplusProtocol::IsValidKeepAlivePacket(const CBuffer &Buffer)
{ {
uint8 tag[] = { 0x03,0x60,0x00 }; uint8 tag[] = { 0x03,0x60,0x00 };
return (Buffer == CBuffer(tag, sizeof(tag))); return (Buffer == CBuffer(tag, sizeof(tag)));
} }
CDvHeaderPacket *CDplusProtocol::IsValidDvHeaderPacket(const CBuffer &Buffer) CDvHeaderPacket *CDplusProtocol::IsValidDvHeaderPacket(const CBuffer &Buffer)
{ {
CDvHeaderPacket *header = nullptr; CDvHeaderPacket *header = nullptr;
if ( (Buffer.size() == 58) && if ( (Buffer.size() == 58) &&
(Buffer.data()[0] == 0x3A) && (Buffer.data()[1] == 0x80) && (Buffer.data()[0] == 0x3A) && (Buffer.data()[1] == 0x80) &&
(Buffer.Compare((uint8 *)"DSVT", 2, 4) == 0) && (Buffer.Compare((uint8 *)"DSVT", 2, 4) == 0) &&
(Buffer.data()[6] == 0x10) && (Buffer.data()[10] == 0x20) ) (Buffer.data()[6] == 0x10) && (Buffer.data()[10] == 0x20) )
{ {
// create packet // create packet
header = new CDvHeaderPacket((struct dstar_header *)&(Buffer.data()[17]), header = new CDvHeaderPacket((struct dstar_header *)&(Buffer.data()[17]),
*((uint16 *)&(Buffer.data()[14])), 0x80); *((uint16 *)&(Buffer.data()[14])), 0x80);
// check validity of packet // check validity of packet
if ( !header->IsValid() ) if ( !header->IsValid() )
{ {
delete header; delete header;
header = nullptr; header = nullptr;
} }
} }
return header; return header;
} }
CDvFramePacket *CDplusProtocol::IsValidDvFramePacket(const CBuffer &Buffer) CDvFramePacket *CDplusProtocol::IsValidDvFramePacket(const CBuffer &Buffer)
{ {
CDvFramePacket *dvframe = nullptr; CDvFramePacket *dvframe = nullptr;
if ( (Buffer.size() == 29) && if ( (Buffer.size() == 29) &&
(Buffer.data()[0] == 0x1D) && (Buffer.data()[1] == 0x80) && (Buffer.data()[0] == 0x1D) && (Buffer.data()[1] == 0x80) &&
(Buffer.Compare((uint8 *)"DSVT", 2, 4) == 0) && (Buffer.Compare((uint8 *)"DSVT", 2, 4) == 0) &&
(Buffer.data()[6] == 0x20) && (Buffer.data()[10] == 0x20) ) (Buffer.data()[6] == 0x20) && (Buffer.data()[10] == 0x20) )
{ {
// create packet // create packet
dvframe = new CDvFramePacket((struct dstar_dvframe *)&(Buffer.data()[17]), dvframe = new CDvFramePacket((struct dstar_dvframe *)&(Buffer.data()[17]),
*((uint16 *)&(Buffer.data()[14])), Buffer.data()[16]); *((uint16 *)&(Buffer.data()[14])), Buffer.data()[16]);
// check validity of packet // check validity of packet
if ( !dvframe->IsValid() ) if ( !dvframe->IsValid() )
{ {
delete dvframe; delete dvframe;
dvframe = nullptr; dvframe = nullptr;
} }
} }
return dvframe; return dvframe;
} }
CDvLastFramePacket *CDplusProtocol::IsValidDvLastFramePacket(const CBuffer &Buffer) CDvLastFramePacket *CDplusProtocol::IsValidDvLastFramePacket(const CBuffer &Buffer)
{ {
CDvLastFramePacket *dvframe = nullptr; CDvLastFramePacket *dvframe = nullptr;
if ( (Buffer.size() == 32) && if ( (Buffer.size() == 32) &&
(Buffer.Compare((uint8 *)"DSVT", 2, 4) == 0) && (Buffer.Compare((uint8 *)"DSVT", 2, 4) == 0) &&
(Buffer.data()[0] == 0x20) && (Buffer.data()[1] == 0x80) && (Buffer.data()[0] == 0x20) && (Buffer.data()[1] == 0x80) &&
(Buffer.data()[6] == 0x20) && (Buffer.data()[10] == 0x20) ) (Buffer.data()[6] == 0x20) && (Buffer.data()[10] == 0x20) )
{ {
// create packet // create packet
dvframe = new CDvLastFramePacket((struct dstar_dvframe *)&(Buffer.data()[17]), dvframe = new CDvLastFramePacket((struct dstar_dvframe *)&(Buffer.data()[17]),
*((uint16 *)&(Buffer.data()[14])), Buffer.data()[16]); *((uint16 *)&(Buffer.data()[14])), Buffer.data()[16]);
// check validity of packet // check validity of packet
if ( !dvframe->IsValid() ) if ( !dvframe->IsValid() )
{ {
delete dvframe; delete dvframe;
dvframe = nullptr; dvframe = nullptr;
} }
} }
return dvframe; return dvframe;
} }
@ -519,67 +519,67 @@ CDvLastFramePacket *CDplusProtocol::IsValidDvLastFramePacket(const CBuffer &Buff
void CDplusProtocol::EncodeKeepAlivePacket(CBuffer *Buffer) void CDplusProtocol::EncodeKeepAlivePacket(CBuffer *Buffer)
{ {
uint8 tag[] = { 0x03,0x60,0x00 }; uint8 tag[] = { 0x03,0x60,0x00 };
Buffer->Set(tag, sizeof(tag)); Buffer->Set(tag, sizeof(tag));
} }
void CDplusProtocol::EncodeLoginAckPacket(CBuffer *Buffer) void CDplusProtocol::EncodeLoginAckPacket(CBuffer *Buffer)
{ {
uint8 tag[] = { 0x08,0xC0,0x04,0x00,'O','K','R','W' }; uint8 tag[] = { 0x08,0xC0,0x04,0x00,'O','K','R','W' };
Buffer->Set(tag, sizeof(tag)); Buffer->Set(tag, sizeof(tag));
} }
void CDplusProtocol::EncodeLoginNackPacket(CBuffer *Buffer) void CDplusProtocol::EncodeLoginNackPacket(CBuffer *Buffer)
{ {
uint8 tag[] = { 0x08,0xC0,0x04,0x00,'B','U','S','Y' }; uint8 tag[] = { 0x08,0xC0,0x04,0x00,'B','U','S','Y' };
Buffer->Set(tag, sizeof(tag)); Buffer->Set(tag, sizeof(tag));
} }
void CDplusProtocol::EncodeDisconnectPacket(CBuffer *Buffer) void CDplusProtocol::EncodeDisconnectPacket(CBuffer *Buffer)
{ {
uint8 tag[] = { 0x05,0x00,0x18,0x00,0x00 }; uint8 tag[] = { 0x05,0x00,0x18,0x00,0x00 };
Buffer->Set(tag, sizeof(tag)); Buffer->Set(tag, sizeof(tag));
} }
bool CDplusProtocol::EncodeDvHeaderPacket(const CDvHeaderPacket &Packet, CBuffer *Buffer) const 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 }; uint8 tag[] = { 0x3A,0x80,0x44,0x53,0x56,0x54,0x10,0x00,0x00,0x00,0x20,0x00,0x01,0x02 };
struct dstar_header DstarHeader; struct dstar_header DstarHeader;
Packet.ConvertToDstarStruct(&DstarHeader); Packet.ConvertToDstarStruct(&DstarHeader);
Buffer->Set(tag, sizeof(tag)); Buffer->Set(tag, sizeof(tag));
Buffer->Append(Packet.GetStreamId()); Buffer->Append(Packet.GetStreamId());
Buffer->Append((uint8)0x80); Buffer->Append((uint8)0x80);
Buffer->Append((uint8 *)&DstarHeader, sizeof(struct dstar_header)); Buffer->Append((uint8 *)&DstarHeader, sizeof(struct dstar_header));
return true; return true;
} }
bool CDplusProtocol::EncodeDvFramePacket(const CDvFramePacket &Packet, CBuffer *Buffer) const 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->Set(tag, sizeof(tag));
Buffer->Append(Packet.GetStreamId()); Buffer->Append(Packet.GetStreamId());
Buffer->Append((uint8)(Packet.GetPacketId() % 21)); Buffer->Append((uint8)(Packet.GetPacketId() % 21));
Buffer->Append((uint8 *)Packet.GetAmbe(), AMBE_SIZE); Buffer->Append((uint8 *)Packet.GetAmbe(), AMBE_SIZE);
Buffer->Append((uint8 *)Packet.GetDvData(), DVDATA_SIZE); Buffer->Append((uint8 *)Packet.GetDvData(), DVDATA_SIZE);
return true; return true;
} }
bool CDplusProtocol::EncodeDvLastFramePacket(const CDvLastFramePacket &Packet, CBuffer *Buffer) const 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 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 tag2[] = { 0x55,0xC8,0x7A,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x25,0x1A,0xC6 };
Buffer->Set(tag1, sizeof(tag1)); Buffer->Set(tag1, sizeof(tag1));
Buffer->Append(Packet.GetStreamId()); Buffer->Append(Packet.GetStreamId());
Buffer->Append((uint8)((Packet.GetPacketId() % 21) | 0x40)); Buffer->Append((uint8)((Packet.GetPacketId() % 21) | 0x40));
Buffer->Append(tag2, sizeof(tag2)); Buffer->Append(tag2, sizeof(tag2));
return true; return true;
} }

@ -42,57 +42,57 @@ class CDplusClient;
class CDPlusStreamCacheItem class CDPlusStreamCacheItem
{ {
public: public:
CDPlusStreamCacheItem() { m_iSeqCounter = 0; } CDPlusStreamCacheItem() { m_iSeqCounter = 0; }
CDvHeaderPacket m_dvHeader; CDvHeaderPacket m_dvHeader;
uint8 m_iSeqCounter; uint8 m_iSeqCounter;
}; };
class CDplusProtocol : public CProtocol class CDplusProtocol : public CProtocol
{ {
public: public:
// initialization // initialization
bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6); bool Initalize(const char *type, const uint16 port, const bool has_ipv4, const bool has_ipv6);
// task // task
void Task(void); void Task(void);
protected: protected:
// queue helper // queue helper
void HandleQueue(void); void HandleQueue(void);
void SendDvHeader(CDvHeaderPacket *, CDplusClient *); void SendDvHeader(CDvHeaderPacket *, CDplusClient *);
// keepalive helpers // keepalive helpers
void HandleKeepalives(void); void HandleKeepalives(void);
// stream helpers // stream helpers
bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &); bool OnDvHeaderPacketIn(CDvHeaderPacket *, const CIp &);
// packet decoding helpers // packet decoding helpers
bool IsValidConnectPacket(const CBuffer &); bool IsValidConnectPacket(const CBuffer &);
bool IsValidLoginPacket(const CBuffer &, CCallsign *); bool IsValidLoginPacket(const CBuffer &, CCallsign *);
bool IsValidDisconnectPacket(const CBuffer &); bool IsValidDisconnectPacket(const CBuffer &);
bool IsValidKeepAlivePacket(const CBuffer &); bool IsValidKeepAlivePacket(const CBuffer &);
CDvHeaderPacket *IsValidDvHeaderPacket(const CBuffer &); CDvHeaderPacket *IsValidDvHeaderPacket(const CBuffer &);
CDvFramePacket *IsValidDvFramePacket(const CBuffer &); CDvFramePacket *IsValidDvFramePacket(const CBuffer &);
CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &); CDvLastFramePacket *IsValidDvLastFramePacket(const CBuffer &);
// packet encoding helpers // packet encoding helpers
void EncodeKeepAlivePacket(CBuffer *); void EncodeKeepAlivePacket(CBuffer *);
void EncodeLoginAckPacket(CBuffer *); void EncodeLoginAckPacket(CBuffer *);
void EncodeLoginNackPacket(CBuffer *); void EncodeLoginNackPacket(CBuffer *);
void EncodeDisconnectPacket(CBuffer *); void EncodeDisconnectPacket(CBuffer *);
bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const; bool EncodeDvHeaderPacket(const CDvHeaderPacket &, CBuffer *) const;
bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const; bool EncodeDvFramePacket(const CDvFramePacket &, CBuffer *) const;
bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const; bool EncodeDvLastFramePacket(const CDvLastFramePacket &, CBuffer *) const;
protected: protected:
// for keep alive // for keep alive
CTimePoint m_LastKeepaliveTime; CTimePoint m_LastKeepaliveTime;
// for queue header caches // for queue header caches
std::array<CDPlusStreamCacheItem, NB_OF_MODULES> m_StreamsCache; std::array<CDPlusStreamCacheItem, NB_OF_MODULES> m_StreamsCache;
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////

@ -33,24 +33,24 @@
CDvFramePacket::CDvFramePacket() CDvFramePacket::CDvFramePacket()
{ {
::memset(m_uiAmbe, 0, sizeof(m_uiAmbe)); ::memset(m_uiAmbe, 0, sizeof(m_uiAmbe));
::memset(m_uiDvData, 0, sizeof(m_uiDvData)); ::memset(m_uiDvData, 0, sizeof(m_uiDvData));
#ifndef NO_XLX #ifndef NO_XLX
::memset(m_uiAmbePlus, 0, sizeof(m_uiAmbePlus)); ::memset(m_uiAmbePlus, 0, sizeof(m_uiAmbePlus));
::memset(m_uiDvSync, 0, sizeof(m_uiDvSync)); ::memset(m_uiDvSync, 0, sizeof(m_uiDvSync));
#endif #endif
}; };
// dstar constructor // dstar constructor
CDvFramePacket::CDvFramePacket(const struct dstar_dvframe *dvframe, uint16 sid, uint8 pid) 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_uiAmbe, dvframe->AMBE, sizeof(m_uiAmbe));
::memcpy(m_uiDvData, dvframe->DVDATA, sizeof(m_uiDvData)); ::memcpy(m_uiDvData, dvframe->DVDATA, sizeof(m_uiDvData));
#ifndef NO_XLX #ifndef NO_XLX
::memset(m_uiAmbePlus, 0, sizeof(m_uiAmbePlus)); ::memset(m_uiAmbePlus, 0, sizeof(m_uiAmbePlus));
::memset(m_uiDvSync, 0, sizeof(m_uiDvSync)); ::memset(m_uiDvSync, 0, sizeof(m_uiDvSync));
#endif #endif
} }
@ -58,37 +58,37 @@ CDvFramePacket::CDvFramePacket(const struct dstar_dvframe *dvframe, uint16 sid,
// dmr constructor // dmr constructor
CDvFramePacket::CDvFramePacket(const uint8 *ambe, const uint8 *sync, uint16 sid, uint8 pid, uint8 spid) 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_uiAmbePlus, ambe, sizeof(m_uiAmbePlus));
::memcpy(m_uiDvSync, sync, sizeof(m_uiDvSync)); ::memcpy(m_uiDvSync, sync, sizeof(m_uiDvSync));
::memset(m_uiAmbe, 0, sizeof(m_uiAmbe)); ::memset(m_uiAmbe, 0, sizeof(m_uiAmbe));
::memset(m_uiDvData, 0, sizeof(m_uiDvData)); ::memset(m_uiDvData, 0, sizeof(m_uiDvData));
} }
// ysf constructor // ysf constructor
CDvFramePacket::CDvFramePacket(const uint8 *ambe, uint16 sid, uint8 pid, uint8 spid, uint8 fid) 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)); ::memcpy(m_uiAmbePlus, ambe, sizeof(m_uiAmbePlus));
::memset(m_uiDvSync, 0, sizeof(m_uiDvSync)); ::memset(m_uiDvSync, 0, sizeof(m_uiDvSync));
::memset(m_uiAmbe, 0, sizeof(m_uiAmbe)); ::memset(m_uiAmbe, 0, sizeof(m_uiAmbe));
::memset(m_uiDvData, 0, sizeof(m_uiDvData)); ::memset(m_uiDvData, 0, sizeof(m_uiDvData));
} }
// xlx constructor // xlx constructor
CDvFramePacket::CDvFramePacket CDvFramePacket::CDvFramePacket
(uint16 sid, (uint16 sid,
uint8 dstarpid, const uint8 *dstarambe, const uint8 *dstardvdata, uint8 dstarpid, const uint8 *dstarambe, const uint8 *dstardvdata,
uint8 dmrpid, uint8 dprspid, const uint8 *dmrambe, const uint8 *dmrsync) uint8 dmrpid, uint8 dprspid, const uint8 *dmrambe, const uint8 *dmrsync)
: CPacket(sid, dstarpid, dmrpid, dprspid, 0xFF, 0xFF, 0xFF) : CPacket(sid, dstarpid, dmrpid, dprspid, 0xFF, 0xFF, 0xFF)
{ {
::memcpy(m_uiAmbe, dstarambe, sizeof(m_uiAmbe)); ::memcpy(m_uiAmbe, dstarambe, sizeof(m_uiAmbe));
::memcpy(m_uiDvData, dstardvdata, sizeof(m_uiDvData)); ::memcpy(m_uiDvData, dstardvdata, sizeof(m_uiDvData));
::memcpy(m_uiAmbePlus, dmrambe, sizeof(m_uiAmbePlus)); ::memcpy(m_uiAmbePlus, dmrambe, sizeof(m_uiAmbePlus));
::memcpy(m_uiDvSync, dmrsync, sizeof(m_uiDvSync)); ::memcpy(m_uiDvSync, dmrsync, sizeof(m_uiDvSync));
} }
#endif #endif
@ -97,7 +97,7 @@ CDvFramePacket::CDvFramePacket
CPacket *CDvFramePacket::Duplicate(void) const 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 const uint8 *CDvFramePacket::GetAmbe(uint8 uiCodec) const
{ {
switch (uiCodec) switch (uiCodec)
{ {
case CODEC_AMBEPLUS: return m_uiAmbe; case CODEC_AMBEPLUS:
return m_uiAmbe;
#ifndef NO_XLX #ifndef NO_XLX
case CODEC_AMBE2PLUS: return m_uiAmbePlus; case CODEC_AMBE2PLUS:
return m_uiAmbePlus;
#endif #endif
default: return nullptr; default:
} return nullptr;
}
} }
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -120,22 +123,22 @@ const uint8 *CDvFramePacket::GetAmbe(uint8 uiCodec) const
void CDvFramePacket::SetDvData(uint8 *DvData) 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) void CDvFramePacket::SetAmbe(uint8 uiCodec, uint8 *Ambe)
{ {
switch (uiCodec) switch (uiCodec)
{ {
case CODEC_AMBEPLUS: case CODEC_AMBEPLUS:
::memcpy(m_uiAmbe, Ambe, sizeof(m_uiAmbe)); ::memcpy(m_uiAmbe, Ambe, sizeof(m_uiAmbe));
break; break;
#ifndef NO_XLX #ifndef NO_XLX
case CODEC_AMBE2PLUS: case CODEC_AMBE2PLUS:
::memcpy(m_uiAmbePlus, Ambe, sizeof(m_uiAmbe)); ::memcpy(m_uiAmbePlus, Ambe, sizeof(m_uiAmbe));
break; break;
#endif #endif
} }
} }
@ -144,11 +147,11 @@ void CDvFramePacket::SetAmbe(uint8 uiCodec, uint8 *Ambe)
bool CDvFramePacket::operator ==(const CDvFramePacket &DvFrame) const bool CDvFramePacket::operator ==(const CDvFramePacket &DvFrame) const
{ {
return ( (::memcmp(m_uiAmbe, DvFrame.m_uiAmbe, sizeof(m_uiAmbe)) == 0) return ( (::memcmp(m_uiAmbe, DvFrame.m_uiAmbe, sizeof(m_uiAmbe)) == 0)
&& (::memcmp(m_uiDvData, DvFrame.m_uiDvData, sizeof(m_uiDvData)) == 0) && (::memcmp(m_uiDvData, DvFrame.m_uiDvData, sizeof(m_uiDvData)) == 0)
#ifndef NO_XLX #ifndef NO_XLX
&& (::memcmp(m_uiAmbePlus, DvFrame.m_uiAmbePlus, sizeof(m_uiAmbePlus)) == 0) && (::memcmp(m_uiAmbePlus, DvFrame.m_uiAmbePlus, sizeof(m_uiAmbePlus)) == 0)
&& (::memcmp(m_uiDvSync, DvFrame.m_uiDvSync, sizeof(m_uiDvSync)) == 0) && (::memcmp(m_uiDvSync, DvFrame.m_uiDvSync, sizeof(m_uiDvSync)) == 0)
#endif #endif
); );
} }

@ -40,8 +40,8 @@
struct __attribute__ ((__packed__))dstar_dvframe struct __attribute__ ((__packed__))dstar_dvframe
{ {
uint8 AMBE[AMBE_SIZE]; uint8 AMBE[AMBE_SIZE];
uint8 DVDATA[DVDATA_SIZE]; uint8 DVDATA[DVDATA_SIZE];
}; };
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
@ -49,57 +49,57 @@ struct __attribute__ ((__packed__))dstar_dvframe
class CDvFramePacket : public CPacket class CDvFramePacket : public CPacket
{ {
friend class CCodecStream; friend class CCodecStream;
public: public:
// constructor // constructor
CDvFramePacket(); CDvFramePacket();
CDvFramePacket(const struct dstar_dvframe *, uint16, uint8); CDvFramePacket(const struct dstar_dvframe *, uint16, uint8);
#ifndef NO_XLX #ifndef NO_XLX
CDvFramePacket(const uint8 *, const uint8 *, uint16, uint8, uint8); CDvFramePacket(const uint8 *, const uint8 *, uint16, uint8, uint8);
CDvFramePacket(const uint8 *, uint16, uint8, uint8, uint8); CDvFramePacket(const uint8 *, uint16, uint8, uint8, uint8);
CDvFramePacket(uint16, uint8, const uint8 *, const uint8 *, uint8, uint8, const uint8 *, const uint8 *); CDvFramePacket(uint16, uint8, const uint8 *, const uint8 *, uint8, uint8, const uint8 *, const uint8 *);
#endif #endif
// virtual duplication // virtual duplication
CPacket *Duplicate(void) const; CPacket *Duplicate(void) const;
// identity // identity
bool IsDvFrame(void) const { return true; } bool IsDvFrame(void) const { return true; }
#ifndef NO_XLX #ifndef NO_XLX
bool HaveTranscodableAmbe(void) const { return true; } bool HaveTranscodableAmbe(void) const { return true; }
#endif #endif
// get // get
const uint8 *GetAmbe(uint8) const; const uint8 *GetAmbe(uint8) const;
const uint8 *GetAmbe(void) const { return m_uiAmbe; } const uint8 *GetAmbe(void) const { return m_uiAmbe; }
#ifndef NO_XLX #ifndef NO_XLX
const uint8 *GetAmbePlus(void) const { return m_uiAmbePlus; } const uint8 *GetAmbePlus(void) const { return m_uiAmbePlus; }
const uint8 *GetDvSync(void) const { return m_uiDvSync; } const uint8 *GetDvSync(void) const { return m_uiDvSync; }
#endif #endif
const uint8 *GetDvData(void) const { return m_uiDvData; } const uint8 *GetDvData(void) const { return m_uiDvData; }
// set // set
void SetDvData(uint8 *); void SetDvData(uint8 *);
void SetAmbe(uint8, uint8 *); void SetAmbe(uint8, uint8 *);
// operators // operators
bool operator ==(const CDvFramePacket &) const; bool operator ==(const CDvFramePacket &) const;
protected: protected:
// get // get
uint8 *GetAmbeData(void) { return m_uiAmbe; } uint8 *GetAmbeData(void) { return m_uiAmbe; }
#ifndef NO_XLX #ifndef NO_XLX
uint8 *GetAmbePlusData(void) { return m_uiAmbePlus; } uint8 *GetAmbePlusData(void) { return m_uiAmbePlus; }
#endif #endif
protected: protected:
// data (dstar) // data (dstar)
uint8 m_uiAmbe[AMBE_SIZE]; uint8 m_uiAmbe[AMBE_SIZE];
uint8 m_uiDvData[DVDATA_SIZE]; uint8 m_uiDvData[DVDATA_SIZE];
#ifndef NO_XLX #ifndef NO_XLX
// data (dmr) // data (dmr)
uint8 m_uiAmbePlus[AMBEPLUS_SIZE]; uint8 m_uiAmbePlus[AMBEPLUS_SIZE];
uint8 m_uiDvSync[DVSYNC_SIZE]; uint8 m_uiDvSync[DVSYNC_SIZE];
#endif #endif
}; };

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save

Powered by TurnKey Linux.