#define _CRT_SECURE_NO_DEPRECATE #include #include 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, ¶m); 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); }