diff --git a/Makefile b/Makefile index ba5da27..b5cb9a0 100644 --- a/Makefile +++ b/Makefile @@ -29,13 +29,13 @@ IRCDDBOBJS = IRCDDB.o IRCClient.o IRCReceiver.o IRCMessageQueue.o IRCProtocol.o all : $(PROGRAMS) -g2_ircddb : g2_ircddb.cpp $(IRCDDBOBJS) versions.h +g2_ircddb : g2_ircddb.cpp $(IRCDDBOBJS) aprs.h g2_typedefs.h versions.h g++ $(CPPFLAGS) -o g2_ircddb g2_ircddb.cpp $(IRCDDBOBJS) $(LDFLAGS) -pthread g2_link : g2_link.cpp versions.h g++ $(CPPFLAGS) -o g2_link g2_link.cpp -lrt -lconfig++ -pthread -dvap_rptr : dvap_rptr.cpp DVAPDongle.o dstar_dv.o golay23.o DVAPDongle.h versions.h +dvap_rptr : dvap_rptr.cpp DVAPDongle.o dstar_dv.o golay23.o DVAPDongle.h g2_typedefs.h versions.h g++ $(CPPFLAGS) -o dvap_rptr dvap_rptr.cpp DVAPDongle.o golay23.o dstar_dv.o -I/usr/include -L/usr/lib -lrt -lconfig++ -pthread dvrptr : dvrptr.cpp dstar_dv.o golay23.o diff --git a/dvap_rptr.cpp b/dvap_rptr.cpp index 21e9730..5c98ba6 100644 --- a/dvap_rptr.cpp +++ b/dvap_rptr.cpp @@ -48,54 +48,13 @@ using namespace libconfig; #include "DVAPDongle.h" +#include "g2_typedefs.h" #define VERSION DVAP_VERSION #define CALL_SIZE 8 #define RPTR_SIZE 8 #define IP_SIZE 15 -// we need to be sure these structures don't have any dead space -#pragma pack(push, 1) -// for communicating with the g2 gateway -typedef struct pkt_tag { - unsigned char pkt_id[4]; - unsigned char nothing1[2]; - unsigned char flag[2]; - unsigned char nothing2[2]; - union { - struct { - unsigned char mycall[8]; - unsigned char rpt[8]; - } spkt; - struct { - struct { - unsigned char icm_id; - unsigned char dst_rptr_id; - unsigned char snd_rptr_id; - unsigned char snd_term_id; - uint16_t streamid; - unsigned char ctrl; - } myicm; - union { - struct { - unsigned char flag[3]; - unsigned char rpt1[8]; - unsigned char rpt2[8]; - unsigned char urcall[8]; - unsigned char mycall[8]; - unsigned char sfx[4]; - unsigned char pfcs[2]; - } hdr; // 41 byte header - struct { - unsigned char voice[9]; - unsigned char text[3]; - } vasd; // 12 byte voice and slow data - }; - } vpkt; - }; -} SPKT; -#pragma pack(pop) - typedef struct dvap_ack_arg_tag { char mycall[8]; float ber; @@ -431,8 +390,6 @@ static int open_sock() static void readFrom20000() { - struct sockaddr_in from; - socklen_t fromlen; int len; fd_set readfd; struct timeval tv; @@ -454,13 +411,12 @@ static void readFrom20000() tv.tv_sec = 0; tv.tv_usec = WAIT_FOR_PACKETS; - fromlen = sizeof(struct sockaddr); FD_ZERO (&readfd); FD_SET (insock, &readfd); select(insock + 1, &readfd, NULL, NULL, &tv); if (FD_ISSET(insock, &readfd)) { - len = recvfrom(insock, (char *)&net_buf, 58, 0, (struct sockaddr *)&from, &fromlen); + len = recv(insock, (char *)&net_buf, 58, 0); if (len == 58) { if (busy20000) { FD_CLR (insock, &readfd); @@ -968,8 +924,7 @@ static void ReadDVAPThread() /* prepare the S server status packet */ memcpy(spack.pkt_id, "DSTR", 4); - spack.nothing1[0] = 0x00; - spack.nothing1[1] = 0x00; + spack.counter = 0; spack.flag[0] = 0x73; spack.flag[1] = 0x21; spack.nothing2[0] = 0x00; @@ -980,8 +935,7 @@ static void ReadDVAPThread() /* send the S packet if needed */ if ((tnow - S_ctrl_msg_time) > 60) { - spack.nothing1[1] = (unsigned char)(C_COUNTER & 0xff); - spack.nothing1[0] = ((C_COUNTER >> 8) & 0xff); + spack.counter = C_COUNTER; memcpy(spack.spkt.mycall, OWNER, 7); spack.spkt.mycall[7] = 'S'; memcpy(spack.spkt.rpt, OWNER, 7); @@ -1137,8 +1091,7 @@ static void ReadDVAPThread() net_buf.vpkt.hdr.flag[1] = net_buf.vpkt.hdr.flag[2] = 0x00; /* for icom g2 */ - spack.nothing1[1] = (unsigned char)(C_COUNTER & 0xff); - spack.nothing1[0] = ((C_COUNTER >> 8) & 0xff); + spack.counter = C_COUNTER; memcpy(spack.spkt.mycall, net_buf.vpkt.hdr.mycall, 8); memcpy(spack.spkt.rpt, OWNER, 7); spack.spkt.rpt[7] = RPTR_MOD; @@ -1152,8 +1105,7 @@ static void ReadDVAPThread() memcpy(net_buf.vpkt.hdr.rpt1, OWNER, 7); memcpy(net_buf.pkt_id, "DSTR", 4); - net_buf.nothing1[0] = ((C_COUNTER >> 8) & 0xff); - net_buf.nothing1[1] = (unsigned char)(C_COUNTER & 0xff); + net_buf.counter = C_COUNTER; net_buf.flag[0] = 0x73; net_buf.flag[1] = 0x12; net_buf.nothing2[0] = 0x00; @@ -1183,8 +1135,7 @@ static void ReadDVAPThread() if (dvap_busy) { the_end = ((dr.frame.framepos & 0x40) == 0x40); - net_buf.nothing1[0] = ((C_COUNTER >> 8) & 0xff); - net_buf.nothing1[1] = (unsigned char)(C_COUNTER & 0xff); + net_buf.counter = C_COUNTER; net_buf.nothing2[1] = 0x13; net_buf.vpkt.myicm.ctrl = sequence++; if (the_end) diff --git a/g2_ircddb.cpp b/g2_ircddb.cpp index 7458ff6..fecf9c0 100644 --- a/g2_ircddb.cpp +++ b/g2_ircddb.cpp @@ -59,6 +59,7 @@ using namespace libconfig; #include "IRCDDB.h" #include "IRCutils.h" #include "versions.h" +#include "g2_typedefs.h" #include "aprs.h" #define IP_SIZE 15 @@ -73,13 +74,13 @@ using namespace libconfig; typedef struct echo_tag { time_t last_time; - unsigned char streamid[2]; + unsigned short streamid; int fd; char file[FILENAME_MAX + 1]; } SECHO; typedef struct to_remote_g2_tag { - unsigned char streamid[2]; + unsigned short streamid; struct sockaddr_in toDst4; time_t last_time; } STOREMOTEG2; @@ -89,7 +90,7 @@ typedef struct torepeater_tag { unsigned char saved_hdr[58]; // repeater format uint32_t saved_adr; - unsigned char streamid[2]; + unsigned short streamid; uint32_t adr; struct sockaddr_in band_addr; time_t last_time; @@ -163,7 +164,7 @@ static int srv_sock = -1; static unsigned char readBuffer[2000]; // 58 or 29 or 32, max is 58 static struct sockaddr_in fromRptr; -static unsigned char end_of_audio[29]; +static SPKT end_of_audio; static std::atomic keep_running(true); @@ -513,7 +514,7 @@ static int open_port(const SPORTIP &pip) sin.sin_addr.s_addr = inet_addr(pip.ip.c_str()); if (bind(sock, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) != 0) { - traceit("filed to bind %s:%d, errno=%d\n", pip.ip.c_str(), pip.port, errno); + traceit("Failed to bind %s:%d, errno=%d\n", pip.ip.c_str(), pip.port, errno); close(sock); return -1; } @@ -829,10 +830,10 @@ static void runit() if (recd[i].last_time != 0) { time(&t_now); if ((t_now - recd[i].last_time) > echotest_rec_timeout) { - traceit("Inactivity on echotest recording mod %d, removing stream id=%d,%d\n", - i,recd[i].streamid[0], recd[i].streamid[1]); + traceit("Inactivity on echotest recording mod %d, removing stream id=%04x\n", + i, recd[i].streamid); - recd[i].streamid[0] = recd[i].streamid[1] = 0x00; + recd[i].streamid = 0; recd[i].last_time = 0; close(recd[i].fd); recd[i].fd = -1; @@ -855,10 +856,10 @@ static void runit() if (vm[i].last_time != 0) { time(&t_now); if ((t_now - vm[i].last_time) > voicemail_rec_timeout) { - traceit("Inactivity on voicemail recording mod %d, removing stream id=%d,%d\n", - i, vm[i].streamid[0], vm[i].streamid[1]); + traceit("Inactivity on voicemail recording mod %d, removing stream id=%04x\n", + i, vm[i].streamid); - vm[i].streamid[0] = vm[i].streamid[1] = 0x00; + vm[i].streamid = 0; vm[i].last_time = 0; close(vm[i].fd); vm[i].fd = -1; @@ -873,28 +874,27 @@ static void runit() // so we could use either FROM_LOCAL_RPTR_TIMEOUT or FROM_REMOTE_G2_TIMEOUT // but FROM_REMOTE_G2_TIMEOUT makes more sense, probably is a bigger number if ((t_now - toRptr[i].last_time) > from_remote_g2_timeout) { - traceit("Inactivity to local rptr mod index %d, removing stream id %d,%d\n", i, toRptr[i].streamid[0], toRptr[i].streamid[1]); + traceit("Inactivity to local rptr mod index %d, removing stream id %04x\n", + i, toRptr[i].streamid); // Send end_of_audio to local repeater. // Let the repeater re-initialize - end_of_audio[5] = (unsigned char)(toRptr[i].G2_COUNTER & 0xff); - end_of_audio[4] = (unsigned char)((toRptr[i].G2_COUNTER >> 8) & 0xff); + end_of_audio.counter = toRptr[i].G2_COUNTER; if (i == 0) - end_of_audio[13] = 0x03; + end_of_audio.vpkt.myicm.snd_term_id = 0x03; else if (i == 1) - end_of_audio[13] = 0x01; + end_of_audio.vpkt.myicm.snd_term_id = 0x01; else - end_of_audio[13] = 0x02; - end_of_audio[14] = toRptr[i].streamid[0]; - end_of_audio[15] = toRptr[i].streamid[1]; - end_of_audio[16] = toRptr[i].sequence | 0x40; + end_of_audio.vpkt.myicm.snd_term_id = 0x02; + end_of_audio.vpkt.myicm.streamid = toRptr[i].streamid; + end_of_audio.vpkt.myicm.ctrl = toRptr[i].sequence | 0x40; for (j = 0; j < 2; j++) - sendto(srv_sock, end_of_audio, 29, 0, (struct sockaddr *)&toRptr[i].band_addr, sizeof(struct sockaddr_in)); + sendto(srv_sock, end_of_audio.pkt_id, 29, 0, (struct sockaddr *)&toRptr[i].band_addr, sizeof(struct sockaddr_in)); toRptr[i].G2_COUNTER++; - toRptr[i].streamid[0] = toRptr[i].streamid[1] = '\0'; + toRptr[i].streamid = 0; toRptr[i].adr = 0; toRptr[i].last_time = 0; } @@ -933,12 +933,11 @@ static void runit() if (to_remote_g2[i].toDst4.sin_addr.s_addr != 0) { time(&t_now); if ((t_now - to_remote_g2[i].last_time) > from_local_rptr_timeout) { - traceit("Inactivity from local rptr mod %d, removing stream id %d,%d\n", - i, to_remote_g2[i].streamid[0], to_remote_g2[i].streamid[1]); + traceit("Inactivity from local rptr mod %d, removing stream id %04x\n", + i, to_remote_g2[i].streamid); memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].streamid[0] = '\0'; - to_remote_g2[i].streamid[1] = '\0'; + to_remote_g2[i].streamid = 0; to_remote_g2[i].last_time = 0; } } @@ -1005,8 +1004,7 @@ static void runit() toRptr[i].saved_adr = fromDst4.sin_addr.s_addr; /* This is the active streamid */ - toRptr[i].streamid[0] = readBuffer2[12]; - toRptr[i].streamid[1] = readBuffer2[13]; + toRptr[i].streamid = readBuffer2[12] + 256u * readBuffer2[13]; toRptr[i].adr = fromDst4.sin_addr.s_addr; /* time it, in case stream times out */ @@ -1028,7 +1026,7 @@ static void runit() /* find out which repeater module to send the data to */ for (i = 0; i < 3; i++) { /* streamid match ? */ - if ((memcmp(toRptr[i].streamid, readBuffer2 + 12, 2) == 0) && + if ((memcmp(&toRptr[i].streamid, readBuffer2 + 12, 2) == 0) && (toRptr[i].adr == fromDst4.sin_addr.s_addr)) { memcpy(readBuffer,"DSTR", 4); readBuffer[5] = (unsigned char)(toRptr[i].G2_COUNTER & 0xff); @@ -1057,8 +1055,7 @@ static void runit() toRptr[i].saved_adr = 0; toRptr[i].last_time = 0; - toRptr[i].streamid[0] = '\0'; - toRptr[i].streamid[1] = '\0'; + toRptr[i].streamid = 0; toRptr[i].adr = 0; } break; @@ -1104,8 +1101,7 @@ static void runit() sendto(srv_sock, readBuffer, 29, 0, (struct sockaddr *)&toRptr[i].band_addr, sizeof(struct sockaddr_in)); /* make sure that any more audio arriving will be accepted */ - toRptr[i].streamid[0] = readBuffer2[12]; - toRptr[i].streamid[1] = readBuffer2[13]; + toRptr[i].streamid = readBuffer2[12] + 256u * readBuffer2[13]; toRptr[i].adr = fromDst4.sin_addr.s_addr; /* time it, in case stream times out */ @@ -1285,8 +1281,8 @@ static void runit() result = get_yrcall_rptr(temp_radio_user, arearp_cs, zonerp_cs, &temp_mod, ip, 'R'); if (result) { /* it is a repeater */ /* set the destination */ - memcpy(to_remote_g2[i].streamid, readBuffer + 14, 2); - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + memcpy(&to_remote_g2[i].streamid, readBuffer + 14, 2); + memset(&to_remote_g2[i].toDst4, 0, sizeof(struct sockaddr_in)); to_remote_g2[i].toDst4.sin_family = AF_INET; to_remote_g2[i].toDst4.sin_port = htons(g2_external.port); to_remote_g2[i].toDst4.sin_addr.s_addr = inet_addr(ip); @@ -1366,8 +1362,8 @@ static void runit() /* one radio user on a repeater module at a time */ if (to_remote_g2[i].toDst4.sin_addr.s_addr == 0) { /* set the destination */ - memcpy(to_remote_g2[i].streamid, readBuffer + 14, 2); - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); + memcpy(&to_remote_g2[i].streamid, readBuffer + 14, 2); + memset(&to_remote_g2[i].toDst4, 0, sizeof(struct sockaddr_in)); to_remote_g2[i].toDst4.sin_family = AF_INET; to_remote_g2[i].toDst4.sin_port = htons(g2_external.port); to_remote_g2[i].toDst4.sin_addr.s_addr = inet_addr(ip); @@ -1445,8 +1441,7 @@ static void runit() sendto(srv_sock, readBuffer, 58, 0, (struct sockaddr *)&toRptr[i].band_addr, sizeof(struct sockaddr_in)); /* This is the active streamid */ - toRptr[i].streamid[0] = readBuffer[14]; - toRptr[i].streamid[1] = readBuffer[15]; + toRptr[i].streamid = readBuffer[14] + 256u * readBuffer[15]; toRptr[i].adr = fromRptr.sin_addr.s_addr; /* time it, in case stream times out */ @@ -1527,7 +1522,7 @@ static void runit() vm[i].file); time(&vm[i].last_time); - memcpy(vm[i].streamid, readBuffer + 14, 2); + memcpy(&vm[i].streamid, readBuffer + 14, 2); memcpy(recbuf, "DSVT", 4); recbuf[4] = 0x10; @@ -1583,7 +1578,7 @@ static void runit() recd[i].file); time(&recd[i].last_time); - memcpy(recd[i].streamid, readBuffer + 14, 2); + memcpy(&recd[i].streamid, readBuffer + 14, 2); memcpy(recbuf, "DSVT", 4); recbuf[4] = 0x10; @@ -1649,8 +1644,7 @@ static void runit() sendto(srv_sock, readBuffer,58,0, (struct sockaddr *)&toRptr[i].band_addr, sizeof(struct sockaddr_in)); /* This is the active streamid */ - toRptr[i].streamid[0] = readBuffer[14]; - toRptr[i].streamid[1] = readBuffer[15]; + toRptr[i].streamid = readBuffer[14] + 256u * readBuffer[15]; toRptr[i].adr = fromRptr.sin_addr.s_addr; /* time it, in case stream times out */ @@ -2095,7 +2089,7 @@ static void runit() for (i = 0; i < 3; i++) { /* find out if data must go to the remote G2 */ - if (memcmp(to_remote_g2[i].streamid, readBuffer + 14, 2) == 0) { + if (memcmp(&to_remote_g2[i].streamid, readBuffer + 14, 2) == 0) { memcpy(readBuffer2, "DSVT", 4); readBuffer2[4] = 0x20; readBuffer2[5] = readBuffer2[6] = readBuffer2[7] = 0x00; @@ -2111,15 +2105,14 @@ static void runit() /* Is this the end-of-stream */ if ((readBuffer[16] & 0x40) != 0) { - memset(&(to_remote_g2[i].toDst4),0,sizeof(struct sockaddr_in)); - to_remote_g2[i].streamid[0] = to_remote_g2[i].streamid[1] = '\0'; + memset(&to_remote_g2[i].toDst4,0,sizeof(struct sockaddr_in)); + to_remote_g2[i].streamid = 0; to_remote_g2[i].last_time = 0; } break; } else /* Is the data to be recorded for echotest */ - if ((recd[i].fd >= 0) && - (memcmp(recd[i].streamid, readBuffer + 14, 2) == 0)) { + if (recd[i].fd>=0 && 0==memcmp(&recd[i].streamid, readBuffer + 14, 2)) { time(&recd[i].last_time); memcpy(recbuf, "DSVT", 4); @@ -2142,8 +2135,7 @@ static void runit() (void)write(recd[i].fd, (char *)recbuf, rec_len); if ((readBuffer[16] & 0x40) != 0) { - recd[i].streamid[0] = 0x00; - recd[i].streamid[1] = 0x00; + recd[i].streamid = 0; recd[i].last_time = 0; close(recd[i].fd); recd[i].fd = -1; @@ -2163,7 +2155,7 @@ static void runit() } else /* Is the data to be recorded for voicemail */ if ((vm[i].fd >= 0) && - (memcmp(vm[i].streamid, readBuffer + 14, 2) == 0)) { + (memcmp(&vm[i].streamid, readBuffer + 14, 2) == 0)) { time(&vm[i].last_time); memcpy(recbuf, "DSVT", 4); @@ -2186,8 +2178,7 @@ static void runit() (void)write(vm[i].fd, (char *)recbuf, rec_len); if ((readBuffer[16] & 0x40) != 0) { - vm[i].streamid[0] = 0x00; - vm[i].streamid[1] = 0x00; + vm[i].streamid = 0; vm[i].last_time = 0; close(vm[i].fd); vm[i].fd = -1; @@ -2196,7 +2187,7 @@ static void runit() break; } else /* or maybe this is cross-banding data */ - if ((memcmp(toRptr[i].streamid, readBuffer + 14, 2) == 0) && (toRptr[i].adr == fromRptr.sin_addr.s_addr)) { + if ((memcmp(&toRptr[i].streamid, readBuffer + 14, 2) == 0) && (toRptr[i].adr == fromRptr.sin_addr.s_addr)) { sendto(srv_sock, readBuffer, 29, 0, (struct sockaddr *)&toRptr[i].band_addr, sizeof(struct sockaddr_in)); /* timeit */ @@ -2210,8 +2201,7 @@ static void runit() /* End of stream ? */ if ((readBuffer[16] & 0x40) != 0) { toRptr[i].last_time = 0; - toRptr[i].streamid[0] = '\0'; - toRptr[i].streamid[1] = '\0'; + toRptr[i].streamid = 0; toRptr[i].adr = 0; } break; @@ -2220,7 +2210,7 @@ static void runit() if ((readBuffer[16] & 0x40) != 0) { if (bool_qso_details) - traceit("END from rptr: cntr=%02x %02x, streamID=%d,%d, %d bytes\n", + traceit("END from rptr: cntr=%02x %02x, streamID=%02x,%02x, %d bytes\n", readBuffer[4], readBuffer[5], readBuffer[14],readBuffer[15],recvlen); } @@ -2715,13 +2705,13 @@ int main(int argc, char **argv) for (i = 0; i < 3; i++) { // recording for echotest on local repeater modules recd[i].last_time = 0; - recd[i].streamid[0] = recd[i].streamid[1] = 0x0; + recd[i].streamid = 0; recd[i].fd = -1; memset(recd[i].file, 0, sizeof(recd[i].file)); // recording for voicemail on local repeater modules vm[i].last_time = 0; - vm[i].streamid[0] = vm[i].streamid[1] = 0x0; + vm[i].streamid = 0; vm[i].fd = -1; memset(vm[i].file, 0, sizeof(vm[i].file)); @@ -2738,7 +2728,7 @@ int main(int argc, char **argv) memset(toRptr[i].saved_hdr, 0, sizeof(toRptr[i].saved_hdr)); toRptr[i].saved_adr = 0; - toRptr[i].streamid[0] = toRptr[i].streamid[1] = '\0'; + toRptr[i].streamid = 0; toRptr[i].adr = 0; toRptr[i].band_addr.sin_family = AF_INET; @@ -2755,24 +2745,23 @@ int main(int argc, char **argv) Initialize the end_of_audio that will be sent to the local repeater when audio from remote G2 has timed out */ - memcpy(end_of_audio, "DSTR", 4); - end_of_audio[6] = 0x73; - end_of_audio[7] = 0x12; - end_of_audio[8] = 0x00; - end_of_audio[9] = 0x13; - end_of_audio[10] = 0x20; - end_of_audio[11] = 0x00; - end_of_audio[12] = 0x01; - memset(end_of_audio + 17, '\0', 9); - end_of_audio[26] = 0x70; - end_of_audio[27] = 0x4f; - end_of_audio[28] = 0x93; + memcpy(end_of_audio.pkt_id, "DSTR", 4); + end_of_audio.flag[0] = 0x73; + end_of_audio.flag[1] = 0x12; + end_of_audio.nothing2[0] = 0x00; + end_of_audio.nothing2[1] = 0x13; + end_of_audio.vpkt.myicm.icm_id = 0x20; + end_of_audio.vpkt.myicm.dst_rptr_id = 0x00; + end_of_audio.vpkt.myicm.snd_rptr_id = 0x01; + memset(end_of_audio.vpkt.vasd.voice, '\0', 9); + end_of_audio.vpkt.vasd.text[0] = 0x70; + end_of_audio.vpkt.vasd.text[1] = 0x4f; + end_of_audio.vpkt.vasd.text[2] = 0x93; /* to remote systems */ for (i = 0; i < 3; i++) { - memset(&(to_remote_g2[i].toDst4), 0, sizeof(struct sockaddr_in)); - to_remote_g2[i].streamid[0] = '\0'; - to_remote_g2[i].streamid[1] = '\0'; + memset(&to_remote_g2[i].toDst4, 0, sizeof(struct sockaddr_in)); + to_remote_g2[i].streamid = 0; to_remote_g2[i].last_time = 0; } @@ -2812,7 +2801,7 @@ int main(int argc, char **argv) for (i = 0; i < 3; i++) { recd[i].last_time = 0; - recd[i].streamid[0] = recd[i].streamid[1] = 0x0; + recd[i].streamid = 0; if (recd[i].fd >= 0) { close(recd[i].fd); unlink(recd[i].file); diff --git a/g2_typedefs.h b/g2_typedefs.h new file mode 100644 index 0000000..650d165 --- /dev/null +++ b/g2_typedefs.h @@ -0,0 +1,61 @@ +#pragma once +/* + * Copyright 2017 by Thomas Early, AC2IE + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +// for communicating with the g2 gateway + +#pragma pack(push, 1) // we need to be sure these structures don't have any dead space +typedef struct pkt_tag { + unsigned char pkt_id[4]; + unsigned short counter; + unsigned char flag[2]; + unsigned char nothing2[2]; + union { + struct { + unsigned char mycall[8]; + unsigned char rpt[8]; + } spkt; + struct { + struct { + unsigned char icm_id; + unsigned char dst_rptr_id; + unsigned char snd_rptr_id; + unsigned char snd_term_id; + uint16_t streamid; + unsigned char ctrl; + } myicm; + union { + struct { + unsigned char flag[3]; + unsigned char rpt1[8]; + unsigned char rpt2[8]; + unsigned char urcall[8]; + unsigned char mycall[8]; + unsigned char sfx[4]; + unsigned char pfcs[2]; + } hdr; // 41 byte header + struct { + unsigned char voice[9]; + unsigned char text[3]; + } vasd; // 12 byte voice and slow data + }; + } vpkt; + }; +} SPKT; +#pragma pack(pop) +