From cd8f730e5ee8b46ba9f1395ad62671657da0c155 Mon Sep 17 00:00:00 2001 From: Doug McLain Date: Fri, 3 Sep 2021 11:51:43 -0400 Subject: [PATCH] Attempt to extract callsign from 10 char YSF frames. When YSF headers are missed (late entries), extract callsign from one of the VD2 frames. If no DMR ID can be found after all of these attempts, use an optional default DMR ID, defined in main.h. Also append a main.h defined module char on RPTR1 when no char exists in REF mode. This is the case for OpenSpot 1 users that can not assign a module char to their RPTR1 when in REF mode. DPlus reflectors allow RPTR1 callsings with no module char, but stock xlxd does not. --- src/ccallsign.cpp | 15 +++++++++++-- src/ccallsign.h | 2 ++ src/cdmrmmdvmprotocol.cpp | 16 +++++++++++++ src/cdvframepacket.cpp | 8 ++++++- src/cdvframepacket.h | 5 ++++- src/cdvheaderpacket.cpp | 12 +++++++++- src/cdvlastframepacket.cpp | 4 ++-- src/cdvlastframepacket.h | 2 +- src/cysfprotocol.cpp | 46 +++++++++++++++++++++++++++++--------- src/main.h | 2 ++ 10 files changed, 93 insertions(+), 19 deletions(-) diff --git a/src/ccallsign.cpp b/src/ccallsign.cpp index 23cdb3e..d098228 100644 --- a/src/ccallsign.cpp +++ b/src/ccallsign.cpp @@ -117,10 +117,10 @@ bool CCallsign::IsValid(void) const } // prefix - // all chars are number, uppercase or space + // all chars are number, letter, special char, or space 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]) || IsLetterLC(m_Suffix[i]) || IsSpecialChar(m_Suffix[i]); } // module @@ -365,3 +365,14 @@ bool CCallsign::IsSpace(char c) const { return (c == ' '); } + +bool CCallsign::IsLetterLC(char c) const +{ + return ((c >= 'a') && (c <= 'z')); +} + +bool CCallsign::IsSpecialChar(char c) const +{ + return ((c >= '!') && (c <= '/')); +} + diff --git a/src/ccallsign.h b/src/ccallsign.h index bd5f118..d2593a0 100644 --- a/src/ccallsign.h +++ b/src/ccallsign.h @@ -85,6 +85,8 @@ protected: bool IsNumber(char) const; bool IsLetter(char) const; bool IsSpace(char) const; + bool IsLetterLC(char) const; + bool IsSpecialChar(char) const; protected: // data diff --git a/src/cdmrmmdvmprotocol.cpp b/src/cdmrmmdvmprotocol.cpp index 1d964f5..41754a0 100644 --- a/src/cdmrmmdvmprotocol.cpp +++ b/src/cdmrmmdvmprotocol.cpp @@ -919,12 +919,28 @@ void CDmrmmdvmProtocol::EncodeDvPacket( { uint8 tag[] = { 'D','M','R','D' }; Buffer->Set(tag, sizeof(tag)); + uint8_t cs[12]; // DMR header // uiSeqId Buffer->Append((uint8)seqid); // uiSrcId uint32 uiSrcId = Header.GetMyCallsign().GetDmrid(); + DvFrame0.GetMyCallsign().GetCallsign(cs); + + if(uiSrcId == 0){ + uiSrcId = DvFrame0.GetMyCallsign().GetDmrid(); + } + if(uiSrcId == 0){ + uiSrcId = DvFrame1.GetMyCallsign().GetDmrid(); + } + if(uiSrcId == 0){ + uiSrcId = DvFrame2.GetMyCallsign().GetDmrid(); + } + if(uiSrcId == 0){ + uiSrcId = DMRMMDVM_DEFAULTID; + } + AppendDmrIdToBuffer(Buffer, uiSrcId); // uiDstId = TG9 uint32 uiDstId = 9; // ModuleToDmrDestId(Header.GetRpt2Module()); diff --git a/src/cdvframepacket.cpp b/src/cdvframepacket.cpp index 8c2e02b..31e571c 100644 --- a/src/cdvframepacket.cpp +++ b/src/cdvframepacket.cpp @@ -63,13 +63,16 @@ CDvFramePacket::CDvFramePacket(const uint8 *ambe, const uint8 *sync, uint16 sid, // 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, CCallsign cs) : CPacket(sid, pid, spid, fid) { ::memcpy(m_uiAmbePlus, ambe, sizeof(m_uiAmbePlus)); ::memset(m_uiDvSync, 0, sizeof(m_uiDvSync)); ::memset(m_uiAmbe, 0, sizeof(m_uiAmbe)); ::memset(m_uiDvData, 0, sizeof(m_uiDvData)); + uint8_t c[12]; + cs.GetCallsign(c); + m_Callsign.SetCallsign((char *)c); } // xlx constructor @@ -95,6 +98,9 @@ CDvFramePacket::CDvFramePacket(const CDvFramePacket &DvFrame) ::memcpy(m_uiDvData, DvFrame.m_uiDvData, sizeof(m_uiDvData)); ::memcpy(m_uiAmbePlus, DvFrame.m_uiAmbePlus, sizeof(m_uiAmbePlus)); ::memcpy(m_uiDvSync, DvFrame.m_uiDvSync, sizeof(m_uiDvSync)); + uint8_t c[12]; + DvFrame.GetMyCallsign().GetCallsign(c); + m_Callsign.SetCallsign((char *)c); } //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/cdvframepacket.h b/src/cdvframepacket.h index cddad5d..c3cbdaa 100644 --- a/src/cdvframepacket.h +++ b/src/cdvframepacket.h @@ -26,6 +26,7 @@ #define cdvframepacket_h #include "cpacket.h" +#include "ccallsign.h" //////////////////////////////////////////////////////////////////////////////////////// // defines @@ -55,7 +56,7 @@ public: CDvFramePacket(); CDvFramePacket(const struct dstar_dvframe *, uint16, uint8); CDvFramePacket(const uint8 *, const uint8 *, uint16, uint8, uint8); - CDvFramePacket(const uint8 *, uint16, uint8, uint8, uint8); + CDvFramePacket(const uint8 *, uint16, uint8, uint8, uint8, CCallsign); CDvFramePacket(uint16, uint8, const uint8 *, const uint8 *, uint8, uint8, const uint8 *, const uint8 *); CDvFramePacket(const CDvFramePacket &); @@ -75,6 +76,7 @@ public: const uint8 *GetAmbePlus(void) const { return m_uiAmbePlus; } const uint8 *GetDvData(void) const { return m_uiDvData; } const uint8 *GetDvSync(void) const { return m_uiDvSync; } + const CCallsign &GetMyCallsign(void) const { return m_Callsign; } // set void SetDvData(uint8 *); @@ -95,6 +97,7 @@ protected: // data (dmr) uint8 m_uiAmbePlus[AMBEPLUS_SIZE]; uint8 m_uiDvSync[DVSYNC_SIZE]; + CCallsign m_Callsign; }; diff --git a/src/cdvheaderpacket.cpp b/src/cdvheaderpacket.cpp index 3a281b2..4ff4926 100644 --- a/src/cdvheaderpacket.cpp +++ b/src/cdvheaderpacket.cpp @@ -48,7 +48,17 @@ CDvHeaderPacket::CDvHeaderPacket(const struct dstar_header *buffer, uint16 sid, m_uiFlag2 = buffer->Flag2; m_uiFlag3 = buffer->Flag3; m_csUR.SetCallsign(buffer->UR, CALLSIGN_LEN); - m_csRPT1.SetCallsign(buffer->RPT1, CALLSIGN_LEN); + + if((buffer->RPT1)[7] == 0x20){ + char rptr1[8]; + memcpy(rptr1, buffer->RPT1, 8); + rptr1[7] = DPLUS_DEFAULT_RPTR1_SUFFIX; + m_csRPT1.SetCallsign(rptr1, CALLSIGN_LEN); + } + else{ + m_csRPT1.SetCallsign(buffer->RPT1, CALLSIGN_LEN); + } + m_csRPT2.SetCallsign(buffer->RPT2, CALLSIGN_LEN); m_csMY.SetCallsign(buffer->MY, CALLSIGN_LEN); m_csMY.SetSuffix(buffer->SUFFIX, CALLSUFFIX_LEN); diff --git a/src/cdvlastframepacket.cpp b/src/cdvlastframepacket.cpp index eb44f4d..6e5fc96 100644 --- a/src/cdvlastframepacket.cpp +++ b/src/cdvlastframepacket.cpp @@ -59,8 +59,8 @@ CDvLastFramePacket::CDvLastFramePacket // ysf constructor -CDvLastFramePacket::CDvLastFramePacket(const uint8 *ambe, uint16 sid, uint8 pid, uint8 spid, uint8 fid) - : CDvFramePacket(ambe, sid, pid, spid, fid) +CDvLastFramePacket::CDvLastFramePacket(const uint8 *ambe, uint16 sid, uint8 pid, uint8 spid, uint8 fid, CCallsign cs) + : CDvFramePacket(ambe, sid, pid, spid, fid, cs) { } diff --git a/src/cdvlastframepacket.h b/src/cdvlastframepacket.h index 8dc339d..502c35f 100644 --- a/src/cdvlastframepacket.h +++ b/src/cdvlastframepacket.h @@ -42,7 +42,7 @@ public: CDvLastFramePacket(); CDvLastFramePacket(const struct dstar_dvframe *, uint16, uint8); CDvLastFramePacket(const uint8 *, const uint8 *, uint16, uint8, uint8); - CDvLastFramePacket(const uint8 *, uint16, uint8, uint8, uint8); + CDvLastFramePacket(const uint8 *, uint16, uint8, uint8, uint8, CCallsign); CDvLastFramePacket(uint16, uint8, const uint8 *, const uint8 *, uint8, uint8, const uint8 *, const uint8 *); CDvLastFramePacket(const CDvLastFramePacket &); diff --git a/src/cysfprotocol.cpp b/src/cysfprotocol.cpp index f0573a3..e0eafb4 100644 --- a/src/cysfprotocol.cpp +++ b/src/cysfprotocol.cpp @@ -441,6 +441,7 @@ bool CYsfProtocol::IsValidDvPacket(const CBuffer &Buffer, CYSFFICH *Fich) bool CYsfProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CYSFFICH &Fich, const CBuffer &Buffer, CDvHeaderPacket **header, CDvFramePacket **frames) { + CCallsign csMY; bool valid = false; *header = NULL; frames[0] = NULL; @@ -460,7 +461,7 @@ bool CYsfProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CYSFFICH &Fich, co char sz[YSF_CALLSIGN_LENGTH+1]; ::memcpy(sz, &(Buffer.data()[14]), YSF_CALLSIGN_LENGTH); sz[YSF_CALLSIGN_LENGTH] = 0; - CCallsign csMY = CCallsign((const char *)sz); + csMY = CCallsign((const char *)sz); ::memcpy(sz, &(Buffer.data()[4]), YSF_CALLSIGN_LENGTH); sz[YSF_CALLSIGN_LENGTH] = 0; CCallsign rpt1 = CCallsign((const char *)sz); @@ -478,12 +479,12 @@ bool CYsfProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CYSFFICH &Fich, co { uint8 uiAmbe[AMBE_SIZE]; ::memset(uiAmbe, 0x00, sizeof(uiAmbe)); - frames[0] = new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 0, 0); - frames[1] = new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 1, 0); + frames[0] = new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 0, 0, csMY); + frames[1] = new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 1, 0, csMY); } // check validity of packets - if ( ((*header) == NULL) || !(*header)->IsValid() || + if ( ((*header) == NULL) || //!(*header)->IsValid() || (frames[0] == NULL) || !(frames[0]->IsValid()) || (frames[1] == NULL) || !(frames[1]->IsValid()) ) @@ -494,6 +495,7 @@ bool CYsfProtocol::IsValidDvHeaderPacket(const CIp &Ip, const CYSFFICH &Fich, co delete frames[1]; frames[0] = NULL; frames[1] = NULL; + valid = false; } else { @@ -531,12 +533,23 @@ bool CYsfProtocol::IsValidDvFramePacket(const CIp &Ip, const CYSFFICH &Fich, con CYsfUtils::DecodeVD2Vchs((unsigned char *)&(Buffer.data()[35]), ambes); // get DV frames + char sz[YSF_CALLSIGN_LENGTH+1]; + ::memcpy(sz, &(Buffer.data()[14]), YSF_CALLSIGN_LENGTH); + sz[YSF_CALLSIGN_LENGTH] = 0; + + for(int i = 0; i < YSF_CALLSIGN_LENGTH; ++i){ + if( (sz[i] == '/') || (sz[i] == '\\') || (sz[i] == '-') || (sz[i] == ' ') ){ + sz[i] = 0; + } + } + + CCallsign csMY = CCallsign((const char *)sz); uint8 fid = Buffer.data()[34]; - frames[0] = new CDvFramePacket(ambe0, uiStreamId, Fich.getFN(), 0, fid); - frames[1] = new CDvFramePacket(ambe1, uiStreamId, Fich.getFN(), 1, fid); - frames[2] = new CDvFramePacket(ambe2, uiStreamId, Fich.getFN(), 2, fid); - frames[3] = new CDvFramePacket(ambe3, uiStreamId, Fich.getFN(), 3, fid); - frames[4] = new CDvFramePacket(ambe4, uiStreamId, Fich.getFN(), 4, fid); + frames[0] = new CDvFramePacket(ambe0, uiStreamId, Fich.getFN(), 0, fid, csMY); + frames[1] = new CDvFramePacket(ambe1, uiStreamId, Fich.getFN(), 1, fid, csMY); + frames[2] = new CDvFramePacket(ambe2, uiStreamId, Fich.getFN(), 2, fid, csMY); + frames[3] = new CDvFramePacket(ambe3, uiStreamId, Fich.getFN(), 3, fid, csMY); + frames[4] = new CDvFramePacket(ambe4, uiStreamId, Fich.getFN(), 4, fid, csMY); // check validity of packets if ( (frames[0] == NULL) || !(frames[0]->IsValid()) || @@ -582,8 +595,19 @@ bool CYsfProtocol::IsValidDvLastFramePacket(const CIp &Ip, const CYSFFICH &Fich, { uint8 uiAmbe[AMBE_SIZE]; ::memset(uiAmbe, 0x00, sizeof(uiAmbe)); - frames[0] = new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 0, 0); - frames[1] = new CDvLastFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 1, 0); + char sz[YSF_CALLSIGN_LENGTH+1]; + ::memcpy(sz, &(Buffer.data()[14]), YSF_CALLSIGN_LENGTH); + sz[YSF_CALLSIGN_LENGTH] = 0; + + for(int i = 0; i < YSF_CALLSIGN_LENGTH; ++i){ + if( (sz[i] == '/') || (sz[i] == '\\') || (sz[i] == '-') || (sz[i] == ' ') ){ + sz[i] = 0; + } + } + + CCallsign csMY = CCallsign((const char *)sz); + frames[0] = new CDvFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 0, 0, csMY); + frames[1] = new CDvLastFramePacket(uiAmbe, uiStreamId, Fich.getFN(), 1, 0, csMY); } // check validity of packets diff --git a/src/main.h b/src/main.h index 4212a3e..842a069 100644 --- a/src/main.h +++ b/src/main.h @@ -91,6 +91,7 @@ #define DPLUS_PORT 20001 // UDP port #define DPLUS_KEEPALIVE_PERIOD 1 // in seconds #define DPLUS_KEEPALIVE_TIMEOUT (DPLUS_KEEPALIVE_PERIOD*10) // in seconds +#define DPLUS_DEFAULT_RPTR1_SUFFIX ' ' // RPTR1 suffix to append when missing, use ' ' to leave unchanged // DCS #define DCS_PORT 30051 // UDP port @@ -116,6 +117,7 @@ #define DMRMMDVM_KEEPALIVE_TIMEOUT (DMRMMDVM_KEEPALIVE_PERIOD*10) // in seconds #define DMRMMDVM_REFLECTOR_SLOT DMR_SLOT2 #define DMRMMDVM_REFLECTOR_COLOUR 1 +#define DMRMMDVM_DEFAULTID 3161894 // Default DMRID used for unrecognized callsigns from other modes. 0 = unused // YSF #define YSF_PORT 42000 // UDP port