linbpq/WinRPRHelper.c

487 lines
9.6 KiB
C

#define _CRT_SECURE_NO_DEPRECATE
#include <windows.h>
#include <stdio.h>
struct RIGPORTINFO
{
char IOBASE[80];
char PTTIOBASE[80]; // Port for Hardware PTT - may be same as control port.
int SPEED;
HANDLE hDevice; // COM device Handle
int ReopenDelay;
SOCKET remoteSock; // Socket for use with WINMORCONROL
struct sockaddr remoteDest; // Dest for above
UCHAR TXBuffer[500]; // Last message sent - saved for Retry
int TXLen; // Len of last sent
int CONNECTED; // for HAMLIB
int CONNECTING;
int Alerted;
};
struct RIGPORTINFO PORTS[4];
char PTTCATPort[4][64] = {"", "", "", ""};
HANDLE PTTCATHandles[4] = {0, 0, 0, 0};
int RealMux[4] = {0, 0, 0, 0}; // BPQ Virtual or Real
VOID PTTCATThread();
VOID ConnecttoHAMLIB(struct RIGPORTINFO * PORT);
char * strlop(char * buf, char delim)
{
// Terminate buf at delim, and return rest of string
char * ptr;
if (buf == NULL) return NULL; // Protect
ptr = strchr(buf, delim);
if (ptr == NULL) return NULL;
*(ptr)++=0;
return ptr;
}
void SendHamLib(struct RIGPORTINFO * PORT, int PTTState)
{
char cmd[32];
int Len = sprintf(cmd, "T %d\n", PTTState);
Len = send(PORT->remoteSock, cmd, Len, 0);
Len = GetLastError();
}
int DecodeHAMLIBAddr(struct RIGPORTINFO * PORT, char * ptr)
{
// Param is IPADDR:PORT. Only Allow numeric addresses
struct sockaddr_in * destaddr = (SOCKADDR_IN *)&PORT->remoteDest;
char * port;
strcpy(PORT->IOBASE, ptr);
port = strlop(ptr, ':');
if (port == NULL)
return 0;
destaddr->sin_family = AF_INET;
destaddr->sin_addr.s_addr = inet_addr(ptr);
destaddr->sin_port = htons(atoi(port));
return 1;
}
void HAMLIBProcessMessage(struct RIGPORTINFO * PORT)
{
// Called from Background thread. I think we just need to read and discard
char RXBuffer[512];
int InputLen = recv(PORT->remoteSock, RXBuffer, 500, 0);
if (InputLen == 0 || InputLen == SOCKET_ERROR)
{
if (PORT->remoteSock)
closesocket(PORT->remoteSock);
PORT->remoteSock = 0;
PORT->CONNECTED = FALSE;
PORT->hDevice = 0;
return;
}
}
int main(int argc, char ** argv)
{
struct RIGPORTINFO * PORT;
int n = 0;
WSADATA WsaData; // receives data from WSAStartup
if (argc < 3)
{
printf ("Missing parameters - you need COM port and IP Address and rigctl port of BPQ, eg \r\n"
" WinRPRHelper com10 192.168.1.64:4532\r\n\r\n"
"Press any key to exit\r\n");
getchar();
exit (0);
}
WSAStartup(MAKEWORD(2, 0), &WsaData);
while (argc > 2)
{
PORT = &PORTS[n];
strcpy(PTTCATPort[n], argv[n + n +1]);
DecodeHAMLIBAddr(PORT, argv[n + n + 2]);
n++;
argc -= 2;
}
_beginthread(PTTCATThread, 0, 0);
for (n = 0; n < 4; n++)
{
if (PTTCATPort[n][0]) // Serial port RTS to HAMLIB PTT
{
PORT = &PORTS[n];
ConnecttoHAMLIB(PORT);
}
}
Sleep(2000);
printf("WinRPRHelper running - Press ctrl/c to exit\r\n");
fflush(stdout);
while(1)
{
Sleep(1000);
for (n = 0; n < 4; n++)
{
if (PTTCATPort[n][0]) // Serial port RTS to HAMLIB PTT
{
PORT = &PORTS[n];
if (PORT->hDevice == 0)
{
// Try to reopen every 15 secs
PORT->ReopenDelay++;
if (PORT->ReopenDelay > 15)
{
PORT->ReopenDelay = 0;
ConnecttoHAMLIB(PORT);
}
}
}
}
}
}
VOID PTTCATThread()
{
DWORD dwLength = 0;
int Length, ret, i;
UCHAR * ptr1;
UCHAR * ptr2;
UCHAR c;
UCHAR Block[4][80];
UCHAR CurrentState[4] = {0};
#define RTS 2
#define DTR 4
HANDLE Event;
HANDLE Handle[4];
DWORD EvtMask[4];
OVERLAPPED Overlapped[4];
char Port[32];
int PIndex = 0;
int HIndex = 0;
int rc;
while (PIndex < 4 && PTTCATPort[PIndex][0])
{
RealMux[HIndex] = 0;
sprintf(Port, "\\\\.\\pipe\\BPQ%s", PTTCATPort[PIndex]);
Handle[HIndex] = CreateFile(Port, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
if (Handle[HIndex] == (HANDLE) -1)
{
int Err = GetLastError();
printf("PTTMUX port BPQ%s Open failed code %d - trying real com port\r\n", PTTCATPort[PIndex], Err);
// See if real com port
sprintf(Port, "\\\\.\\\\%s", PTTCATPort[PIndex]);
Handle[HIndex] = CreateFile(Port, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
RealMux[HIndex] = 1;
if (Handle[HIndex] == (HANDLE) -1)
{
int Err = GetLastError();
printf("PTTMUX port %s Open failed code %d\r\n", PTTCATPort[PIndex], Err);
}
else
{
rc = SetCommMask(Handle[HIndex], EV_CTS | EV_DSR); // Request notifications
HIndex++;
printf("PTTMUX port %s Opened\r\n", PTTCATPort[PIndex]);
}
}
else
HIndex++;
PIndex++;
}
if (PIndex == 0)
return; // No ports
Event = CreateEvent(NULL, TRUE, FALSE, NULL);
for (i = 0; i < HIndex; i ++)
{
memset(&Overlapped[i], 0, sizeof(OVERLAPPED));
Overlapped[i].hEvent = Event;
if (RealMux[i])
{
// Request Interface change notifications
rc = WaitCommEvent(Handle[i], &EvtMask[i], &Overlapped[i]);
rc = GetLastError();
}
else
{
// Prime a read on each handle
ReadFile(Handle[i], Block[i], 80, &Length, &Overlapped[i]);
}
}
while (1)
{
WaitAgain:
ret = WaitForSingleObject(Event, 1000);
if (ret == WAIT_TIMEOUT)
goto WaitAgain;
ResetEvent(Event);
// See which request(s) have completed
for (i = 0; i < HIndex; i ++)
{
ret = GetOverlappedResult(Handle[i], &Overlapped[i], &Length, FALSE);
if (ret)
{
if (RealMux[i])
{
// Request Interface change notifications
DWORD Mask;
GetCommModemStatus(Handle[i], &Mask);
if (Mask & MS_CTS_ON)
SendHamLib(&PORTS[i], TRUE);
else
SendHamLib(&PORTS[i], FALSE);
memset(&Overlapped[i], 0, sizeof(OVERLAPPED));
Overlapped[i].hEvent = Event;
WaitCommEvent(Handle[i], &EvtMask[i], &Overlapped[i]);
}
else
{
ptr1 = Block[i];
ptr2 = Block[i];
while (Length > 0)
{
c = *(ptr1++);
Length--;
if (c == 0xff)
{
c = *(ptr1++);
Length--;
if (c == 0xff) // ff ff means ff
{
Length--;
}
else
{
// This is connection / RTS/DTR statua from other end
// Convert to CAT Command
if (c == CurrentState[i])
continue;
if (c & RTS)
SendHamLib(&PORTS[i], TRUE);
else
SendHamLib(&PORTS[i], FALSE);
CurrentState[i] = c;
continue;
}
}
}
memset(&Overlapped[i], 0, sizeof(OVERLAPPED));
Overlapped[i].hEvent = Event;
ReadFile(Handle[i], Block[i], 80, &Length, &Overlapped[i]);
}
}
}
}
}
VOID HAMLIBThread(struct RIGPORTINFO * PORT);
VOID ConnecttoHAMLIB(struct RIGPORTINFO * PORT)
{
_beginthread(HAMLIBThread, 0, (void *)PORT);
return ;
}
VOID HAMLIBThread(struct RIGPORTINFO * PORT)
{
// Opens sockets and looks for data
char Msg[255];
int err, i, ret;
u_long param=1;
BOOL bcopt=TRUE;
fd_set readfs;
fd_set errorfs;
struct timeval timeout;
if (PORT->remoteSock)
{
closesocket(PORT->remoteSock);
}
PORT->remoteSock = 0;
PORT->remoteSock = socket(AF_INET,SOCK_STREAM,0);
if (PORT->remoteSock == INVALID_SOCKET)
{
i=sprintf(Msg, "Socket Failed for HAMLIB socket - error code = %d\r\n", WSAGetLastError());
printf(Msg);
PORT->CONNECTING = FALSE;
return;
}
setsockopt(PORT->remoteSock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt, 4);
setsockopt(PORT->remoteSock, IPPROTO_TCP, TCP_NODELAY, (const char FAR *)&bcopt, 4);
if (connect(PORT->remoteSock,(LPSOCKADDR) &PORT->remoteDest,sizeof(PORT->remoteDest)) == 0)
{
//
// Connected successful
//
ioctlsocket(PORT->remoteSock, FIONBIO, &param);
printf("Connected to HAMLIB socket Addr %s\r\n", PORT->IOBASE);
}
else
{
if (PORT->Alerted == FALSE)
{
struct sockaddr_in * destaddr = (SOCKADDR_IN * )&PORT->remoteDest;
err = WSAGetLastError();
sprintf(Msg, "Connect Failed for HAMLIB socket - error code = %d Addr %s\r\n", err, PORT->IOBASE);
printf(Msg);
PORT->Alerted = TRUE;
}
closesocket(PORT->remoteSock);
PORT->remoteSock = 0;
PORT->CONNECTING = FALSE;
return;
}
PORT->CONNECTED = TRUE;
PORT->hDevice = (HANDLE)1; // simplifies check code
PORT->Alerted = TRUE;
while (PORT->CONNECTED)
{
FD_ZERO(&readfs);
FD_ZERO(&errorfs);
FD_SET(PORT->remoteSock,&readfs);
FD_SET(PORT->remoteSock,&errorfs);
timeout.tv_sec = 5;
timeout.tv_usec = 0;
ret = select((int)PORT->remoteSock + 1, &readfs, NULL, &errorfs, &timeout);
if (ret == SOCKET_ERROR)
{
printf("HAMLIB Select failed %d r\n", WSAGetLastError());
goto Lost;
}
if (ret > 0)
{
// See what happened
if (FD_ISSET(PORT->remoteSock, &readfs))
{
HAMLIBProcessMessage(PORT);
}
if (FD_ISSET(PORT->remoteSock, &errorfs))
{
Lost:
sprintf(Msg, "HAMLIB Connection lost for Addr %s\r\n", PORT->IOBASE);
printf(Msg);
PORT->CONNECTED = FALSE;
PORT->Alerted = FALSE;
PORT->hDevice = 0; // simplifies check code
closesocket(PORT->remoteSock);
PORT->remoteSock = 0;
return;
}
continue;
}
else
{
}
}
sprintf(Msg, "HAMLIB Thread Terminated Addr %s\r\n", PORT->IOBASE);
printf(Msg);
}