diff --git a/QnetGateway.cpp b/QnetGateway.cpp index 46ebca7..12562e2 100644 --- a/QnetGateway.cpp +++ b/QnetGateway.cpp @@ -71,7 +71,7 @@ int CQnetGateway::FindIndex(const int i) const return index; } -bool CQnetGateway::VoicePacketIsSync(const unsigned char *text) +bool CQnetGateway::VoicePacketIsSync(const unsigned char *text) const { return *text==0x55U && *(text+1)==0x2DU && *(text+2)==0x16U; } @@ -682,219 +682,74 @@ bool CQnetGateway::ProcessG2Msg(const unsigned char *data, const int mod, std::s void CQnetGateway::ProcessSlowData(unsigned char *data, const unsigned short sid) { /* extract 20-byte RADIO ID */ - if ((data[0] != 0x55) || (data[1] != 0x2d) || (data[2] != 0x16)) { - - // first, unscramble - const unsigned char c1 = data[0] ^ 0x70u; - const unsigned char c2 = data[1] ^ 0x4fu; - const unsigned char c3 = data[2] ^ 0x93u; - - for (int i=0; i<3; i++) { - if (band_txt[i].streamID == sid) { - if (new_group[i]) { - const unsigned char header_type = c1 & 0xf0; - - // header squelch - if ((header_type == 0x50) || (header_type == 0xc0)) { - new_group[i] = false; - to_print[i] = 0; - ABC_grp[i] = false; - } - else if (header_type == 0x30) { /* GPS or GPS id or APRS */ - new_group[i] = false; - to_print[i] = c1 & 0x0f; - ABC_grp[i] = false; - if (to_print[i] > 5) - to_print[i] = 5; - else if (to_print[i] < 1) - to_print[i] = 1; - - if ((to_print[i] > 1) && (to_print[i] <= 5)) { - /* something went wrong? all bets are off */ - if (band_txt[i].temp_line_cnt > 200) { - printf("Reached the limit in the OLD gps mode\n"); - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - - /* fresh GPS string, re-initialize */ - if ((to_print[i] == 5) && (c2 == '$')) { - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } + if (VoicePacketIsSync(data)) + return; - /* do not copy CR, NL */ - if ((c2 != '\r') && (c2 != '\n')) { - band_txt[i].temp_line[band_txt[i].temp_line_cnt++] = c2; - } - if ((c3 != '\r') && (c3 != '\n')) { - band_txt[i].temp_line[band_txt[i].temp_line_cnt++] = c3; - } + // first, unscramble + const unsigned char c1 = data[0] ^ 0x70u; + const unsigned char c2 = data[1] ^ 0x4fu; + const unsigned char c3 = data[2] ^ 0x93u; - if ((c2 == '\r') || (c3 == '\r')) { - if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) { - memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); - band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; - } else if (band_txt[i].temp_line[0] != '$') { - memcpy(band_txt[i].gpid, band_txt[i].temp_line, band_txt[i].temp_line_cnt); - band_txt[i].gpid[band_txt[i].temp_line_cnt] = '\0'; - if (APRS_ENABLE && !band_txt[i].is_gps_sent) - gps_send(i); - } - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } else if ((c2 == '\n') || (c3 == '\n')) { - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - to_print[i] -= 2; - } else { - /* something went wrong? all bets are off */ - if (band_txt[i].temp_line_cnt > 200) { - printf("Reached the limit in the OLD gps mode\n"); - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } + for (int i=0; i<3; i++) { + if (band_txt[i].streamID == sid) { + if (new_group[i]) { + const unsigned char header_type = c1 & 0xf0; - /* do not copy CR, NL */ - if ((c2 != '\r') && (c2 != '\n')) { - band_txt[i].temp_line[band_txt[i].temp_line_cnt++] = c2; - } + // header squelch + if ((header_type == 0x50) || (header_type == 0xc0)) { + new_group[i] = false; + to_print[i] = 0; + ABC_grp[i] = false; + } + else if (header_type == 0x30) { /* GPS or GPS id or APRS */ + new_group[i] = false; + to_print[i] = c1 & 0x0f; + ABC_grp[i] = false; + if (to_print[i] > 5) + to_print[i] = 5; + else if (to_print[i] < 1) + to_print[i] = 1; - if (c2 == '\r') { - if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) { - memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); - band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; - } else if (band_txt[i].temp_line[0] != '$') { - memcpy(band_txt[i].gpid, band_txt[i].temp_line, band_txt[i].temp_line_cnt); - band_txt[i].gpid[band_txt[i].temp_line_cnt] = '\0'; - if (APRS_ENABLE && !band_txt[i].is_gps_sent) - gps_send(i); - } - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } else if (c2 == '\n') { - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - to_print[i] --; + if ((to_print[i] > 1) && (to_print[i] <= 5)) { + /* something went wrong? all bets are off */ + if (band_txt[i].temp_line_cnt > 200) { + printf("Reached the limit in the OLD gps mode\n"); + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; } - } - else if (header_type == 0x40) { /* ABC text */ - new_group[i] = false; - to_print[i] = 3; - ABC_grp[i] = true; - C_seen[i] = ((c1 & 0x0f) == 0x03) ? true : false; - - band_txt[i].txt[band_txt[i].txt_cnt++] = c2; - - band_txt[i].txt[band_txt[i].txt_cnt++] = c3; - /* We should NOT see any more text, - if we already processed text, - so blank out the codes. */ - if (band_txt[i].sent_key_on_msg) { - data[0] = 0x70; - data[1] = 0x4f; - data[2] = 0x93; + /* fresh GPS string, re-initialize */ + if ((to_print[i] == 5) && (c2 == '$')) { + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; } - if (band_txt[i].txt_cnt >= 20) { - band_txt[i].txt[band_txt[i].txt_cnt] = '\0'; - band_txt[i].txt_cnt = 0; + /* do not copy CR, NL */ + if ((c2 != '\r') && (c2 != '\n')) { + band_txt[i].temp_line[band_txt[i].temp_line_cnt++] = c2; + } + if ((c3 != '\r') && (c3 != '\n')) { + band_txt[i].temp_line[band_txt[i].temp_line_cnt++] = c3; } - } - else { // header type is not header, squelch, gps or message - new_group[i] = false; - to_print[i] = 0; - ABC_grp[i] = false; - } - } - else { // not a new_group, this is the second of a two-voice-frame pair - if (! band_txt[i].sent_key_on_msg && vPacketCount[i] > 100) { - // 100 voice packets received and still no 20-char message! - /*** if YRCALL is CQCQCQ, set dest_rptr ***/ - band_txt[i].txt[0] = '\0'; - if (memcmp(band_txt[i].lh_yrcall, "CQCQCQ", 6) == 0) - set_dest_rptr(i+'A', band_txt[i].dest_rptr); - - int x = FindIndex(i); - if (x >= 0) - ii[x]->sendHeardWithTXMsg(band_txt[i].lh_mycall, band_txt[i].lh_sfx, band_txt[i].lh_yrcall, band_txt[i].lh_rpt1, band_txt[i].lh_rpt2, band_txt[i].flags[0], band_txt[i].flags[1], band_txt[i].flags[2], IS_HF[i] ? "" : band_txt[i].dest_rptr, band_txt[i].txt); - band_txt[i].sent_key_on_msg = true; - } - if (to_print[i] == 3) { - if (ABC_grp[i]) { - band_txt[i].txt[band_txt[i].txt_cnt++] = c1; - - band_txt[i].txt[band_txt[i].txt_cnt++] = c2; - - band_txt[i].txt[band_txt[i].txt_cnt++] = c3; - - /* We should NOT see any more text, - if we already processed text, - so blank out the codes. */ - if (band_txt[i].sent_key_on_msg) { - data[0] = 0x70; - data[1] = 0x4f; - data[2] = 0x93; - } - - if ((band_txt[i].txt_cnt >= 20) || C_seen[i]) { - band_txt[i].txt[band_txt[i].txt_cnt] = '\0'; - if ( ! band_txt[i].sent_key_on_msg) { - /*** if YRCALL is CQCQCQ, set dest_rptr ***/ - if (memcmp(band_txt[i].lh_yrcall, "CQCQCQ", 6) == 0) - set_dest_rptr(i+'A', band_txt[i].dest_rptr); - - // we have the 20-character message, send it to the server... - int x = FindIndex(i); - if (x >= 0) - ii[x]->sendHeardWithTXMsg(band_txt[i].lh_mycall, band_txt[i].lh_sfx, band_txt[i].lh_yrcall, band_txt[i].lh_rpt1, band_txt[i].lh_rpt2, band_txt[i].flags[0], band_txt[i].flags[1], band_txt[i].flags[2], IS_HF[i] ? "" : band_txt[i].dest_rptr, band_txt[i].txt); - band_txt[i].sent_key_on_msg = true; - } - band_txt[i].txt_cnt = 0; - } - if (C_seen[i]) - C_seen[i] = false; - } else { - /* something went wrong? all bets are off */ - if (band_txt[i].temp_line_cnt > 200) { - printf("Reached the limit in the OLD gps mode\n"); - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - - /* do not copy carrige return or newline */ - if ((c1 != '\r') && (c1 != '\n')) { - band_txt[i].temp_line[band_txt[i].temp_line_cnt++] = c1; - } - if ((c2 != '\r') && (c2 != '\n')) { - band_txt[i].temp_line[band_txt[i].temp_line_cnt++] = c2; - } - if ((c3 != '\r') && (c3 != '\n')) { - band_txt[i].temp_line[band_txt[i].temp_line_cnt++] = c3; - } - if ( (c1 == '\r') || (c2 == '\r') || (c3 == '\r') ) { - if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) { - memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); - band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; - } else if (band_txt[i].temp_line[0] != '$') { - memcpy(band_txt[i].gpid, band_txt[i].temp_line, band_txt[i].temp_line_cnt); - band_txt[i].gpid[band_txt[i].temp_line_cnt] = '\0'; - if (APRS_ENABLE && !band_txt[i].is_gps_sent) - gps_send(i); - } - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; - } - else if ((c1 == '\n') || (c2 == '\n') ||(c3 == '\n')) { - band_txt[i].temp_line[0] = '\0'; - band_txt[i].temp_line_cnt = 0; + if ((c2 == '\r') || (c3 == '\r')) { + if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) { + memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); + band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; + } else if (band_txt[i].temp_line[0] != '$') { + memcpy(band_txt[i].gpid, band_txt[i].temp_line, band_txt[i].temp_line_cnt); + band_txt[i].gpid[band_txt[i].temp_line_cnt] = '\0'; + if (APRS_ENABLE && !band_txt[i].is_gps_sent) + gps_send(i); } + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } else if ((c2 == '\n') || (c3 == '\n')) { + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; } - } else if (to_print[i] == 2) { + to_print[i] -= 2; + } else { /* something went wrong? all bets are off */ if (band_txt[i].temp_line_cnt > 200) { printf("Reached the limit in the OLD gps mode\n"); @@ -903,16 +758,11 @@ void CQnetGateway::ProcessSlowData(unsigned char *data, const unsigned short sid } /* do not copy CR, NL */ - if ((c1 != '\r') && (c1 != '\n')) { - band_txt[i].temp_line[band_txt[i].temp_line_cnt] = c1; - band_txt[i].temp_line_cnt++; - } if ((c2 != '\r') && (c2 != '\n')) { - band_txt[i].temp_line[band_txt[i].temp_line_cnt] = c2; - band_txt[i].temp_line_cnt++; + band_txt[i].temp_line[band_txt[i].temp_line_cnt++] = c2; } - if ((c1 == '\r') || (c2 == '\r')) { + if (c2 == '\r') { if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) { memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; @@ -924,11 +774,91 @@ void CQnetGateway::ProcessSlowData(unsigned char *data, const unsigned short sid } band_txt[i].temp_line[0] = '\0'; band_txt[i].temp_line_cnt = 0; - } else if ((c1 == '\n') || (c2 == '\n')) { + } else if (c2 == '\n') { band_txt[i].temp_line[0] = '\0'; band_txt[i].temp_line_cnt = 0; } - } else if (to_print[i] == 1) { + to_print[i] --; + } + } + else if (header_type == 0x40) { /* ABC text */ + new_group[i] = false; + to_print[i] = 3; + ABC_grp[i] = true; + C_seen[i] = ((c1 & 0x0f) == 0x03) ? true : false; + + band_txt[i].txt[band_txt[i].txt_cnt++] = c2; + + band_txt[i].txt[band_txt[i].txt_cnt++] = c3; + + /* We should NOT see any more text, + if we already processed text, + so blank out the codes. */ + if (band_txt[i].sent_key_on_msg) { + data[0] = 0x70; + data[1] = 0x4f; + data[2] = 0x93; + } + + if (band_txt[i].txt_cnt >= 20) { + band_txt[i].txt[band_txt[i].txt_cnt] = '\0'; + band_txt[i].txt_cnt = 0; + } + } + else { // header type is not header, squelch, gps or message + new_group[i] = false; + to_print[i] = 0; + ABC_grp[i] = false; + } + } + else { // not a new_group, this is the second of a two-voice-frame pair + if (! band_txt[i].sent_key_on_msg && vPacketCount[i] > 100) { + // 100 voice packets received and still no 20-char message! + /*** if YRCALL is CQCQCQ, set dest_rptr ***/ + band_txt[i].txt[0] = '\0'; + if (memcmp(band_txt[i].lh_yrcall, "CQCQCQ", 6) == 0) + set_dest_rptr(i+'A', band_txt[i].dest_rptr); + + int x = FindIndex(i); + if (x >= 0) + ii[x]->sendHeardWithTXMsg(band_txt[i].lh_mycall, band_txt[i].lh_sfx, band_txt[i].lh_yrcall, band_txt[i].lh_rpt1, band_txt[i].lh_rpt2, band_txt[i].flags[0], band_txt[i].flags[1], band_txt[i].flags[2], IS_HF[i] ? "" : band_txt[i].dest_rptr, band_txt[i].txt); + band_txt[i].sent_key_on_msg = true; + } + if (to_print[i] == 3) { + if (ABC_grp[i]) { + band_txt[i].txt[band_txt[i].txt_cnt++] = c1; + + band_txt[i].txt[band_txt[i].txt_cnt++] = c2; + + band_txt[i].txt[band_txt[i].txt_cnt++] = c3; + + /* We should NOT see any more text, + if we already processed text, + so blank out the codes. */ + if (band_txt[i].sent_key_on_msg) { + data[0] = 0x70; + data[1] = 0x4f; + data[2] = 0x93; + } + + if ((band_txt[i].txt_cnt >= 20) || C_seen[i]) { + band_txt[i].txt[band_txt[i].txt_cnt] = '\0'; + if ( ! band_txt[i].sent_key_on_msg) { + /*** if YRCALL is CQCQCQ, set dest_rptr ***/ + if (memcmp(band_txt[i].lh_yrcall, "CQCQCQ", 6) == 0) + set_dest_rptr(i+'A', band_txt[i].dest_rptr); + + // we have the 20-character message, send it to the server... + int x = FindIndex(i); + if (x >= 0) + ii[x]->sendHeardWithTXMsg(band_txt[i].lh_mycall, band_txt[i].lh_sfx, band_txt[i].lh_yrcall, band_txt[i].lh_rpt1, band_txt[i].lh_rpt2, band_txt[i].flags[0], band_txt[i].flags[1], band_txt[i].flags[2], IS_HF[i] ? "" : band_txt[i].dest_rptr, band_txt[i].txt); + band_txt[i].sent_key_on_msg = true; + } + band_txt[i].txt_cnt = 0; + } + if (C_seen[i]) + C_seen[i] = false; + } else { /* something went wrong? all bets are off */ if (band_txt[i].temp_line_cnt > 200) { printf("Reached the limit in the OLD gps mode\n"); @@ -936,12 +866,18 @@ void CQnetGateway::ProcessSlowData(unsigned char *data, const unsigned short sid band_txt[i].temp_line_cnt = 0; } - /* do not copy CR, NL */ + /* do not copy carrige return or newline */ if ((c1 != '\r') && (c1 != '\n')) { band_txt[i].temp_line[band_txt[i].temp_line_cnt++] = c1; } + if ((c2 != '\r') && (c2 != '\n')) { + band_txt[i].temp_line[band_txt[i].temp_line_cnt++] = c2; + } + if ((c3 != '\r') && (c3 != '\n')) { + band_txt[i].temp_line[band_txt[i].temp_line_cnt++] = c3; + } - if (c1 == '\r') { + if ( (c1 == '\r') || (c2 == '\r') || (c3 == '\r') ) { if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) { memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; @@ -953,17 +889,189 @@ void CQnetGateway::ProcessSlowData(unsigned char *data, const unsigned short sid } band_txt[i].temp_line[0] = '\0'; band_txt[i].temp_line_cnt = 0; - } else if (c1 == '\n') { + } + else if ((c1 == '\n') || (c2 == '\n') ||(c3 == '\n')) { band_txt[i].temp_line[0] = '\0'; band_txt[i].temp_line_cnt = 0; } } - new_group[i] = true; - to_print[i] = 0; - ABC_grp[i] = false; + } else if (to_print[i] == 2) { + /* something went wrong? all bets are off */ + if (band_txt[i].temp_line_cnt > 200) { + printf("Reached the limit in the OLD gps mode\n"); + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } + + /* do not copy CR, NL */ + if ((c1 != '\r') && (c1 != '\n')) { + band_txt[i].temp_line[band_txt[i].temp_line_cnt] = c1; + band_txt[i].temp_line_cnt++; + } + if ((c2 != '\r') && (c2 != '\n')) { + band_txt[i].temp_line[band_txt[i].temp_line_cnt] = c2; + band_txt[i].temp_line_cnt++; + } + + if ((c1 == '\r') || (c2 == '\r')) { + if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) { + memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); + band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; + } else if (band_txt[i].temp_line[0] != '$') { + memcpy(band_txt[i].gpid, band_txt[i].temp_line, band_txt[i].temp_line_cnt); + band_txt[i].gpid[band_txt[i].temp_line_cnt] = '\0'; + if (APRS_ENABLE && !band_txt[i].is_gps_sent) + gps_send(i); + } + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } else if ((c1 == '\n') || (c2 == '\n')) { + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } + } else if (to_print[i] == 1) { + /* something went wrong? all bets are off */ + if (band_txt[i].temp_line_cnt > 200) { + printf("Reached the limit in the OLD gps mode\n"); + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } + + /* do not copy CR, NL */ + if ((c1 != '\r') && (c1 != '\n')) { + band_txt[i].temp_line[band_txt[i].temp_line_cnt++] = c1; + } + + if (c1 == '\r') { + if (memcmp(band_txt[i].temp_line, "$GPRMC", 6) == 0) { + memcpy(band_txt[i].gprmc, band_txt[i].temp_line, band_txt[i].temp_line_cnt); + band_txt[i].gprmc[band_txt[i].temp_line_cnt] = '\0'; + } else if (band_txt[i].temp_line[0] != '$') { + memcpy(band_txt[i].gpid, band_txt[i].temp_line, band_txt[i].temp_line_cnt); + band_txt[i].gpid[band_txt[i].temp_line_cnt] = '\0'; + if (APRS_ENABLE && !band_txt[i].is_gps_sent) + gps_send(i); + } + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } else if (c1 == '\n') { + band_txt[i].temp_line[0] = '\0'; + band_txt[i].temp_line_cnt = 0; + } } - break; + new_group[i] = true; + to_print[i] = 0; + ABC_grp[i] = false; } + break; + } + } +} + +void CQnetGateway::ProcessIncomingSD(const SDSVT &dsvt) +{ + int i; + for (i=0; i<3; i++) { + if (Rptr.mod[i].defined && (toRptr[i].streamid == dsvt.streamid)) + break; + } + // if i==3, then the streamid of this voice packet didn't match any module + + if (VoicePacketIsSync(dsvt.vasd.text)) + return; + + const unsigned char c[3] = { + static_cast(dsvt.vasd.text[0] ^ 0x70u), + static_cast(dsvt.vasd.text[1] ^ 0x4fu), + static_cast(dsvt.vasd.text[2] ^ 0x93u) + }; // unscramble + + if (Sd[i].first) { + Sd[i].size = 0x0FU & c[0]; + int size = Sd[i].size; + if (size > 2) + size = 2; + Sd[i].type = 0xF0U & c[0]; + switch (Sd[i].type) { + case 0x30U: // GPS data + if (Sd[i].size + Sd[i].ig < 255) { + memcpy(Sd[i].gps+Sd[i].ig, c+1, size); + if (c[1]=='\r' || c[2]=='\r') { + Sd[i].gps[Sd[i].ig + (c[1] == '\r') ? 0 : 1] = '\0'; + printf("GPS String=%s\n", Sd[i].gps); + Sd[i].ig = Sd[i].size = 0; + } else + Sd[i].size -= size; + } else { + printf("GPS string is too large at %d bytes\n", Sd[i].ig + Sd[i].size); + Sd[i].size = 0; + } + Sd[i].first = false; + break; + case 0x40U: // 20 character user message + if (Sd[i].size * 5 == Sd[i].im) { + memcpy(Sd[i].message+(5*size), c+1, 2); + Sd[i].im += 2; + } else { + printf("A message voiceframe, #%d, is out of order because message size is %d\n", Sd[i].size, Sd[i].im); + Sd[i].im = 0; + } + Sd[i].first = false; + break; + case 0x50U: // header + if (Sd[i].size + Sd[i].ih < 41) { + memcpy(Sd[i].header+Sd[i].ih, c+1, size); + Sd[i].ih += size; + if (Sd[i].ih == 41) { + memcpy(sdheader.hdr.flag, Sd[i].header, 39); + calcPFCS(sdheader.title, 56); + printf("Header='%x:%x:%x %s' checksum=%02x%02x, calculated=%02x%02x\n", sdheader.hdr.flag[0], sdheader.hdr.flag[1], sdheader.hdr.flag[2], sdheader.hdr.rpt1, Sd[i].header[39], Sd[i].header[40], sdheader.hdr.pfcs[0], sdheader.hdr.pfcs[1]); + Sd[i].ih = Sd[i].size = 0; + } + } else { + printf("Header overflow, %d bytes\n", Sd[i].size + Sd[i].ih); + Sd[i].ih = Sd[i].size = 0; + } + Sd[i].first = false; + break; + default: + return; + } + } else { + // this is the second of a two voice-frame pair + Sd[i].first = true; + if (0 == Sd[i].size) + return; + switch (Sd[i].type) { + case 0x30U: // GPS + memcpy(Sd[i].gps+Sd[i].ig, c, Sd[i].size); + if (c[0]=='\r' || c[1]=='\r' || c[2]=='\r') { + if (c[0]=='\r') + Sd[i].gps[Sd[i].ig] = '\0'; + else if (c[1]=='\r') + Sd[i].gps[Sd[i].ig+1] = '\0'; + else + Sd[i].gps[Sd[i].ig+2] = '\0'; + printf("GPS string=%s\n", Sd[i].gps); + Sd[i].ig = 0; + } + break; + case 0x40U: // message + memcpy(Sd[i].message+Sd[i].im, c, 3); + Sd[i].im += 3; + if (Sd[i].im >= 20) { + Sd[i].message[20] = '\0'; + printf("Message='%s'\n", Sd[i].message); + Sd[i].im = 0; + } + break; + case 0x50U: // header + if (Sd[i].size != 3) { + Sd[i].ih = 0; + } + memcpy(Sd[i].header+Sd[i].ih, c, Sd[i].size); + Sd[i].ih += Sd[i].size; + break; } } } @@ -976,6 +1084,8 @@ void CQnetGateway::ProcessG2(const ssize_t g2buflen, SDSVT &g2buf, const int sou static std::string superframe[3]; if ( (g2buflen==56 || g2buflen==27) && 0==memcmp(g2buf.title, "DSVT", 4) && (g2buf.config==0x10 || g2buf.config==0x20) && g2buf.id==0x20) { if (g2buflen == 56) { + for (int i=0; i<3; i++) + Sd[i].Init(); // only do the first three // Find out the local repeater module IP/port to send the data to int i = g2buf.hdr.rpt1[7] - 'A'; /* valid repeater module? */ @@ -1031,6 +1141,7 @@ void CQnetGateway::ProcessG2(const ssize_t g2buflen, SDSVT &g2buf, const int sou } } } else { // g2buflen == 27 + ProcessIncomingSD(g2buf); /* find out which repeater module to send the data to */ int i; for (i=0; i<3; i++) { @@ -1123,6 +1234,7 @@ void CQnetGateway::ProcessG2(const ssize_t g2buflen, SDSVT &g2buf, const int sou printf("Final[%c]: %s\n", 'A'+i, superframe[i].c_str()); superframe[i].clear(); } + Sd[3].Init(); if (LOG_QSO) printf("id=%04x END\n", ntohs(g2buf.streamid)); } @@ -2480,6 +2592,10 @@ bool CQnetGateway::Init(char *cfgfile) if (GATEWAY_SEND_QRGS_MAP) qrgs_and_maps(); + + for (int i=0; i<4; i++) + Sd[i].Init(); + return false; } diff --git a/QnetGateway.h b/QnetGateway.h index 25356d9..161d7e1 100644 --- a/QnetGateway.h +++ b/QnetGateway.h @@ -79,6 +79,20 @@ using SBANDTXT = struct band_txt_tag { int num_bit_errors; }; +using SSD = struct sd_tag { + unsigned char header[41]; + char message[21]; + char gps[256]; + int ih, im, ig; + unsigned char type; + bool first; + int size; + void Init() { ih = im = ig = 0; first = true; } +}; + + + + class CQnetGateway : public CKRBase { public: @@ -137,7 +151,7 @@ private: // must be fed into our local repeater modules. STOREPEATER toRptr[3]; // 0=A, 1=B, 2=C - SDSVT end_of_audio; + SDSVT end_of_audio, sdheader; // send packets to g2_link struct sockaddr_in plug; @@ -165,7 +179,7 @@ private: int dtmf_last_frame[3]; unsigned int dtmf_counter[3]; - bool VoicePacketIsSync(const unsigned char *text); + bool VoicePacketIsSync(const unsigned char *text) const; int open_port(const SPORTIP *pip, int family); void calcPFCS(unsigned char *packet, int len); void GetIRCDataThread(const int i); @@ -176,6 +190,7 @@ private: void APRSBeaconThread(); void ProcessTimeouts(); void ProcessSlowData(unsigned char *data, const unsigned short sid); + void ProcessIncomingSD(const SDSVT &dsvt); bool ProcessG2Msg(const unsigned char *data, const int mod, std::string &smrtgrp); void ProcessG2(const ssize_t g2buflen, SDSVT &g2buf, const int sock_source); void ProcessModem(const ssize_t len, SDSVT &dsvt); @@ -196,4 +211,7 @@ private: void set_dest_rptr(const char mod, std::string &call); bool validate_csum(SBANDTXT &bt, bool is_gps); + + // for incoming slow header stuff; + SSD Sd[4]; };