diff --git a/APRSCode.c b/APRSCode.c index ff1c8c8..6b52b77 100644 --- a/APRSCode.c +++ b/APRSCode.c @@ -103,6 +103,7 @@ void SaveAPRSMessage(struct APRSMESSAGE * ptr); void ClearSavedMessages(); void GetSavedAPRSMessages(); static VOID GPSDConnect(void * unused); +int CanPortDigi(int Port); extern int SemHeldByAPI; extern int APRSMONDECODE(); @@ -664,9 +665,10 @@ Dll BOOL APIENTRY Init_APRS() memset(&CrossPortMap[0][0], 0, sizeof(CrossPortMap)); memset(&APRSBridgeMap[0][0], 0, sizeof(APRSBridgeMap)); - for (i = 1; i <= 32; i++) + for (i = 1; i <= MaxBPQPortNo; i++) { - CrossPortMap[i][i] = TRUE; // Set Defaults - Same Port + if (CanPortDigi(i)) + CrossPortMap[i][i] = TRUE; // Set Defaults - Same Port CrossPortMap[i][0] = TRUE; // and APRS-IS } @@ -1945,7 +1947,7 @@ static int APRSProcessLine(char * buf) { SendTo = atoi(ptr); // this gives zero for IS - if (SendTo > 32) + if (SendTo > MaxBPQPortNo) return FALSE; Object->PortMap[SendTo] = TRUE; @@ -2175,6 +2177,12 @@ static int APRSProcessLine(char * buf) if (GetPortTableEntryFromPortNum(Port) == NULL) return FALSE; + // Check that port can digi (SCS Pactor can't set digi'd bit in calls) + + if (CanPortDigi(Port) == 0) + return FALSE; + + CrossPortMap[Port][Port] = FALSE; // Cancel Default mapping CrossPortMap[Port][0] = FALSE; // Cancel Default APRSIS @@ -2218,7 +2226,7 @@ static int APRSProcessLine(char * buf) { DigiTo = atoi(ptr); // this gives zero for IS - if (DigiTo > 32) + if (DigiTo > MaxBPQPortNo) return FALSE; APRSBridgeMap[Port][DigiTo] = TRUE; diff --git a/Bpq32.c b/Bpq32.c index 370a0b6..32ba43c 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1186,8 +1186,11 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // Add Chat PACLEN config (5) // Fix NC to Application Call (6) // Fix INP3 L3RTT messages on Linux and correct RTT calculation (9) -// Get Beacon config from config file on windows (9) +// Get Beacon config from config file on Windows (9) // fix processing DED TNC Emulator M command with space between M and params (10) +// Fix sending UI frames on SCSPACTOR (11) +// Dont allow ports that can't set digi'ed bit in callsigns to digipeat. (11) +// Add SDRAngel rig control (11) #define CKernel diff --git a/CBPQ32.vcproj b/CBPQ32.vcproj index 079862a..c1c95a2 100644 --- a/CBPQ32.vcproj +++ b/CBPQ32.vcproj @@ -180,7 +180,7 @@ TNC; + + if (TNC == NULL) + return TRUE; + + if (TNC->Hardware == H_SCS || TNC->Hardware == H_TRK || TNC->Hardware == H_TRKM || TNC->Hardware == H_WINRPR) + return FALSE; + + return TRUE; +} + struct PORTCONTROL * APIENTRY GetPortTableEntryFromPortNum(int portnum) { - struct PORTCONTROL * PORTVEC=PORTTABLE; + struct PORTCONTROL * PORTVEC = PORTTABLE; do { @@ -2340,6 +2359,13 @@ BOOL WriteCOMBlock(HANDLE fd, char * Block, int BytesToWrite) DWORD BytesWritten; DWORD ErrorFlags; COMSTAT ComStat; + DWORD Mask = 0; + int Err; + + Err = GetCommModemStatus(fd, &Mask); + +// if ((Mask & MS_CTS_ON) == 0) // trap com0com other end not open +// return TRUE; fWriteStat = WriteFile(fd, Block, BytesToWrite, &BytesWritten, NULL ); diff --git a/Debug/BuildLog.htm b/Debug/BuildLog.htm new file mode 100644 index 0000000..d4e6e16 Binary files /dev/null and b/Debug/BuildLog.htm differ diff --git a/Debug/MCP2221.exe.embed.manifest b/Debug/MCP2221.exe.embed.manifest new file mode 100644 index 0000000..3d9330a --- /dev/null +++ b/Debug/MCP2221.exe.embed.manifest @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Debug/MCP2221.exe.embed.manifest.res b/Debug/MCP2221.exe.embed.manifest.res new file mode 100644 index 0000000..7b55d19 Binary files /dev/null and b/Debug/MCP2221.exe.embed.manifest.res differ diff --git a/Debug/MCP2221.exe.intermediate.manifest b/Debug/MCP2221.exe.intermediate.manifest new file mode 100644 index 0000000..1b520e1 --- /dev/null +++ b/Debug/MCP2221.exe.intermediate.manifest @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/Debug/MCP2221.obj b/Debug/MCP2221.obj new file mode 100644 index 0000000..a0585cf Binary files /dev/null and b/Debug/MCP2221.obj differ diff --git a/Debug/hid.obj b/Debug/hid.obj new file mode 100644 index 0000000..2df9a2a Binary files /dev/null and b/Debug/hid.obj differ diff --git a/Debug/mt.dep b/Debug/mt.dep new file mode 100644 index 0000000..63b503d --- /dev/null +++ b/Debug/mt.dep @@ -0,0 +1 @@ +Manifest resource last updated at 8:23:51.89 on 15/09/2023 diff --git a/Debug/vc80.idb b/Debug/vc80.idb new file mode 100644 index 0000000..eee75b3 Binary files /dev/null and b/Debug/vc80.idb differ diff --git a/Debug/vc80.pdb b/Debug/vc80.pdb new file mode 100644 index 0000000..896b6ca Binary files /dev/null and b/Debug/vc80.pdb differ diff --git a/RigControl.c b/RigControl.c index 83be639..9c1a056 100644 --- a/RigControl.c +++ b/RigControl.c @@ -125,6 +125,16 @@ VOID SetupPortRIGPointers(); VOID PTTCATThread(struct RIGINFO *RIG); VOID ConnecttoHAMLIB(struct RIGPORTINFO * PORT); +// ----- G7TAJ ---- +VOID ConnecttoSDRANGEL(struct RIGPORTINFO * PORT); +VOID SDRANGELPoll(struct RIGPORTINFO * PORT); +void ProcessSDRANGELFrame(struct RIGPORTINFO * PORT); +VOID SDRANGELSendCommand(struct RIGPORTINFO * PORT, char * Command, char * Value); +void SDRANGELProcessMessage(struct RIGPORTINFO * PORT); + +// ----- G7TAJ ---- + + int SendPTCRadioCommand(struct TNCINFO * TNC, char * Block, int Length); int GetPTCRadioCommand(struct TNCINFO * TNC, char * Block); int BuildRigCtlPage(char * _REPLYBUFFER); @@ -184,6 +194,10 @@ int HAMLIBMasterRunning = 0; int HAMLIBSlaveRunning = 0; int FLRIGRunning = 0; +// ---- G7TAJ ---- +int SDRANGELRunning = 0; +// ---- G7TAJ ---- + char * RigWebPage = 0; int RigWebPageLen = 0; @@ -796,6 +810,26 @@ static char Req[] = "\r\n" "\r\n"; +// ---- G7TAJ ---- +static char SDRANGEL_MsgHddr[] = "PATCH HTTP/1.1\r\n" + "User-Agent: BPQ32\r\n" + "Host: %s\r\n" + "accept: application/json" + "Content-Type: application/json" + "Content-length: %d\r\n" + "\r\n%s"; + +static char SDRANGEL_FREQ_DATA[] = "{" + "\"deviceHwType\": \"%s\", " + "\"direction\": 0," + "\"rtlSdrSettings\": {" + " \"centerFrequency\": \"%s\"" + "}}"; + +//freq = 10489630000 + +// ---- G7TAJ ---- + int Rig_CommandEx(struct RIGPORTINFO * PORT, struct RIGINFO * RIG, TRANSPORTENTRY * Session, char * Command) @@ -2074,7 +2108,7 @@ int Rig_CommandEx(struct RIGPORTINFO * PORT, struct RIGINFO * RIG, TRANSPORTENTR memcpy(&cmd[1], &USB, 4); else if (strcmp(Mode, "LSB") == 0) memcpy(&cmd[1], &LSB, 4); - + cmd[0] = 1; len = sendto(PORT->remoteSock, cmd, 5, 0, &PORT->remoteDest, sizeof(struct sockaddr)); } @@ -2084,7 +2118,43 @@ int Rig_CommandEx(struct RIGPORTINFO * PORT, struct RIGINFO * RIG, TRANSPORTENTR sprintf(Command, "Ok\r"); return FALSE; } +// --- G7TAJ ---- + case SDRANGEL: + { + char cmd[80]; + int len = sprintf(cmd, "%.0f", Freq); + strcpy(PORT->ScanEntry.Cmd2Msg, Mode); + strcpy(PORT->ScanEntry.Cmd3Msg, FilterString); + + if (Freq > 0.0) + { + SDRANGELSendCommand(PORT, "FREQSET", cmd); + sprintf(Command, "Ok\r"); + return FALSE; + } +//TODO +/* else if (PORT->ScanEntry.Cmd2Msg[0] && Mode[0] != '*') + { + sprintf(cmd, "%s", PORT->ScanEntry.Cmd2Msg); + FLRIGSendCommand(PORT, "rig.set_mode", cmd); + } + + else if (PORT->ScanEntry.Cmd3Msg[0] && strcmp(PORT->ScanEntry.Cmd3Msg, "0") != 0) + { + sprintf(cmd, "%s", PORT->ScanEntry.Cmd3Msg); + FLRIGSendCommand(PORT, "rig.set_bandwidth", cmd); + } +*/ + else + { + sprintf(Command, "Sorry - Nothing to do\r"); + return FALSE; + } + + PORT->AutoPoll = 0; + } +// --- G7TAJ ---- @@ -2271,6 +2341,14 @@ DllExport BOOL APIENTRY Rig_Init() } else if (PORT->PortType == RTLUDP) ConnecttoRTLUDP(PORT); +//---- G7TAJ ---- + else if (PORT->PortType == SDRANGEL) + { + SDRANGELRunning = 1; + ConnecttoSDRANGEL(PORT); + + } +//---- G7TAJ ---- else if (PORT->HIDDevice) // This is RAWHID, Not CM108 OpenHIDPort(PORT, PORT->IOBASE, PORT->SPEED); else if (PORT->PTC == 0 && _stricmp(PORT->IOBASE, "CM108") != 0) @@ -2421,7 +2499,10 @@ DllExport BOOL APIENTRY Rig_Close() HAMLIBMasterRunning = 0; // Close HAMLIB thread(s) HAMLIBSlaveRunning = 0; // Close HAMLIB thread(s) - FLRIGRunning = 0; // Close FLRIG thread(s) + FLRIGRunning = 0; // Close FLRIG thread(s) +// ---- G7TAJ ---- + SDRANGELRunning = 0; // Close SDRANGEL thread(s) +// ---- G7TAJ ---- for (p = 0; p < NumberofPorts; p++) { @@ -2544,6 +2625,10 @@ BOOL Rig_Poll() ConnecttoFLRIG(PORT); else if (PORT->PortType == RTLUDP) ConnecttoRTLUDP(PORT); +// ---- G7TAJ ---- + else if (PORT->PortType == SDRANGEL) + ConnecttoSDRANGEL(PORT); +// ---- G7TAJ ---- else if (PORT->HIDDevice) OpenHIDPort(PORT, PORT->IOBASE, PORT->SPEED); else if (PORT->PTC == 0 @@ -2632,7 +2717,12 @@ BOOL Rig_Poll() case FLRIG: FLRIGPoll(PORT); + break; +// ---- G7TAJ ---- + case SDRANGEL: + SDRANGELPoll(PORT); break; } +// ---- G7TAJ ---- } // Build page for Web Display @@ -3014,6 +3104,14 @@ BOOL RigWriteCommBlock(struct RIGPORTINFO * PORT) #ifndef WIN32 BytesWritten = write(PORT->hDevice, PORT->TXBuffer, PORT->TXLen); #else + DWORD Mask = 0; + int Err; + + Err = GetCommModemStatus(PORT->hDevice, &Mask); + +// if ((Mask & MS_CTS_ON) == 0) // trap com0com other end not open +// return TRUE; + fWriteStat = WriteFile(PORT->hDevice, PORT->TXBuffer, PORT->TXLen, &BytesWritten, NULL ); #endif if (PORT->TXLen != BytesWritten) @@ -5529,6 +5627,78 @@ struct RIGINFO * RigConfig(struct TNCINFO * TNC, char * buf, int Port) goto CheckOtherParams; } +// ---- G7TAJ ---- + + if (_memicmp(ptr, "sdrangel", 5) == 0) + { + // each instance (ip addr/port) of sdrangle can have one or more sampling devices (eg rltsdr) each with one ot + // more channels (eg ssb demod, ssb mod). each set of sampling device = channel(s) is a device set. + + // We poll all devices/channels at once. we one PORT record plus a RIG record for each channel + + // Need parameters - Host:Port device channel. Device and Channel will default to zero + + int device = 0, channel = 0; + char * Name; + char * nptr1; + char * nptr2; + + + ptr = strtok_s(NULL, " \t\n\r", &Context); + + if (ptr == NULL || strlen(ptr) > 79) return FALSE; + + Name = strtok_s(NULL, " \t\n\r", &Context); + nptr1 = strtok_s(NULL, " \t\n\r", &Context); + nptr2 = strtok_s(NULL, " \t\n\r", &Context); + + if (nptr1 == 0 || nptr2 == 0 || Name == NULL || strlen(Name) > 9) + return FALSE; + + device = atoi(nptr1); + channel = atoi(nptr2); + + // Have a parameter to define port. Will decode it later + + // See if already defined. PORT->IOBASE has Host:Port + + for (i = 0; i < NumberofPorts; i++) + { + PORT = PORTInfo[i]; + + if (strcmp(PORT->IOBASE, ptr) == 0) + goto AngelRigFound; + } + + // New Port + + PORT = PORTInfo[NumberofPorts++] = zalloc(sizeof(struct RIGPORTINFO)); + PORT->PortType = SDRANGEL; + PORT->ConfiguredRigs = 0; + strcpy(PORT->IOBASE, ptr); + + // Decode host + + DecodeHAMLIBAddr(PORT, ptr); + + +AngelRigFound: + + RIG = &PORT->Rigs[PORT->ConfiguredRigs++]; + RIG->RIGOK = TRUE; + RIG->PORT = PORT; + RIG->RigAddr = device; + RIG->Channel = channel; + + strcpy(RIG->RigName, Name); + + ptr = strtok_s(NULL, " \t\n\r", &Context); + + // look for scan params + + goto CheckOtherParams; + } +// ---- G7TAJ ---- if ((_memicmp(ptr, "VCOM", 4) == 0) && TNC->Hardware == H_SCS) // Using Radio Port on PTC COMPort = 0; @@ -9633,8 +9803,616 @@ VOID ConnecttoRTLUDP(struct RIGPORTINFO * PORT) PORT->Alerted = TRUE; } +char * getObjectFromArray(char * Msg); // This gets the next object from an array ({} = object, [] = array + + + +char * getArrayFromMsg(char * Msg) +{ + // This gets the next object from an array ({} = object, [] = array + // We look for the end of the object same number of { and }, teminate after } and return pointer to next object + // So we have terminated Msg, and returned next object in array + + // Only call if Msg is the next array in Msg + + + char * ptr = Msg; + char c; + + int Open = 0; + int Close = 0; + + while (c = *(ptr++)) + { + if (c == '[') Open ++; else if (c == ']') Close ++; + + if (Open == Close) + { + *(ptr++) = 0; + return ptr; + } + } + return 0; +} + + +//----- G7TAJ ----- + +void ProcessSDRANGELFrame(struct RIGPORTINFO * PORT) +{ + + int Length; + + char * msg; + char * rest; + + struct RIGINFO * RIG; + char * ptr, * ptr1, * ptr2, * ptr3, * pos; + int Len, TotalLen; + char cmd[80]; + char ReqBuf[256]; + char SendBuff[256]; + int chunklength; + int headerlen; + int i, n = 0; + char * Sets; + char * Rest; + char * Set; + int channelcount; + char * channels; + char * channel; + char * samplingDevice; + char * save; + + //Debugprintf("Process SDRANGEL Frame %d\n", PORT->RXLen); + + msg = PORT->RXBuffer; + Length = PORT->RXLen; + + msg[Length] = 0; + + ptr1 = strstr(msg, "Transfer-Encoding: chunked" ); + + if (ptr1 == NULL) + return; + + ptr2 = strstr(ptr1, "\r\n\r\n"); + + if (ptr2 == NULL) + return; + + // ptr2 +4 points to the length of the first chunk (in hex), terminated by crlf + + chunklength = (int)strtol(ptr2 + 4, &ptr3, 16); + ptr3 += 2; // pointer to first chunk data + headerlen = ptr3 - msg; + + // make sure we have first chunk + + if (chunklength + headerlen > Length) + return; + + PORT->RXLen = 0; //we have all the frame now + PORT->Timeout = 0; + + if (strstr(ptr3, "deviceSets") == 0) + { + return; + } + + // Message has info for all rigs + + // As we mess with the message, save a copy and restore for each Rig + + save = strdup(ptr3); + + for (i = 0; i < PORT->ConfiguredRigs; i++) + { + strcpy(ptr3, save); + n = 0; + + RIG = &PORT->Rigs[i]; + RIG->RIGOK = 1; + + // we can have one or more sampling devices (eg rltsdr) each with one or + // more channels (eg ssb demod, ssb mod). each set of sampling device = channel(s) is a device set. + + // Find Device Set for this device (in RIG-> + + // Message Structure is + + //{ + // "deviceSets": [...]. + // "devicesetcount": 2, + // "devicesetfocus": 0 + //} + + // Get the device sets (JSON [..] is an array + + Sets = strchr(ptr3, '['); + + if (Sets == 0) + continue; + + Rest = getArrayFromMsg(Sets); + + // Do we need to check devicesetcount ??. Maybe use to loop through sets, or just stop at end + + // get the set for our device + + while (RIG->RigAddr >= n) + { + Set = strchr(Sets, '{'); // Position to start of first Object + + if (Set == 0) + break; + + Sets = getObjectFromArray(Set); + n++; + } + + if (Set == 0) + continue; + + + // Now get the channel. looking for key "index": + + // we could have a number of sampling devices and channels but for now get sampling device freq + // and first channel freq. Channels are in an Array + + if ((ptr = strstr(Set, "channelcount")) == 0) + continue; + + channelcount = atoi(&ptr[15]); + + if ((channels = strchr(Set, '[')) == 0) + continue; + + samplingDevice = getArrayFromMsg(channels); + + while(channelcount--) + { + channel = strchr(channels, '{'); + channels = getObjectFromArray(channel); + + if ((ptr = strstr(channel, "index"))) + { + n = atoi(&ptr[7]); + if (n == RIG->Channel) + break; + } + } + + + + if (pos = strstr(samplingDevice, "centerFrequency")) //"centerFrequency": 10489630000, + { + pos += 18; + strncpy(cmd, pos, 20); + RIG->RigFreq = atof(cmd) / 1000000.0; + } + + if (pos = strstr(channel, "deltaFrequency")) + { + pos += 17; + strncpy(cmd, pos, 20); + RIG->RigFreq += atof(cmd) / 1000000.0; + } + + + _gcvt(RIG->RigFreq, 9, RIG->Valchar); + + sprintf(RIG->WEB_FREQ,"%s", RIG->Valchar); + SetWindowText(RIG->hFREQ, RIG->WEB_FREQ); + + // we could get mode from Title line: + //"title": "SSB Demodulator", + + if (pos = strstr(channel, "title")) + { + pos += 9; + strncpy(cmd, pos, 20); + strlop(pos, ' '); + strncpy(RIG->ModeString, pos, 15); + sprintf(RIG->WEB_MODE, "%s", RIG->ModeString); + SetWindowText(RIG->hMODE, RIG->WEB_MODE); + } + + } + + + /* + while (msg && msg[0]) + { + rest = strlop(msg, ','); + + if ( pos = strstr(msg, "centerFrequency")) //"centerFrequency": 10489630000, + { + pos += 18; + strncpy(cmd, pos,20); + + RIG->RigFreq = atof(cmd) / 1000000.0; + + // printf("FREQ=%f\t%s\n", RIG->RigFreq, cmd); + + _gcvt(RIG->RigFreq, 9, RIG->Valchar); + + sprintf(RIG->WEB_FREQ,"%s", RIG->Valchar); + SetWindowText(RIG->hFREQ, RIG->WEB_FREQ); + } + + else if (memcmp(msg, "Mode:", 5) == 0) + { + if (strlen(&msg[6]) < 15) + strcpy(RIG->ModeString, &msg[6]); + } + + else if (memcmp(msg, "Passband:", 9) == 0) + { + RIG->Passband = atoi(&msg[10]); + sprintf(RIG->WEB_MODE, "%s/%d", RIG->ModeString, RIG->Passband); + SetWindowText(RIG->hMODE, RIG->WEB_MODE); + } + + msg = rest; + } + */ + free (save); +} + + + +VOID SDRANGELThread(struct RIGPORTINFO * PORT); + +VOID ConnecttoSDRANGEL(struct RIGPORTINFO * PORT) +{ + if (SDRANGELRunning) + _beginthread(SDRANGELThread, 0, (void *)PORT); + return ; +} + +VOID SDRANGELThread(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->CONNECTING) + return; + + PORT->RXLen = 0; + PORT->CONNECTING = 1; + + 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 SDRAngel socket - error code = %d\r\n", WSAGetLastError()); + WritetoConsole(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 + // + + ioctl(PORT->remoteSock, FIONBIO, ¶m); + } + else + { + if (PORT->Alerted == FALSE) + { + struct sockaddr_in * destaddr = (SOCKADDR_IN * )&PORT->remoteDest; + + err = WSAGetLastError(); + + sprintf(Msg, "Connect Failed for SDRAngel socket - error code = %d Port %d\r\n", + err, htons(destaddr->sin_port)); + + WritetoConsole(Msg); + PORT->Alerted = TRUE; + } + + closesocket(PORT->remoteSock); + + PORT->remoteSock = 0; + PORT->CONNECTING = FALSE; + return; + } + + PORT->CONNECTED = TRUE; + PORT->CONNECTING = 0; + + PORT->hDevice = (HANDLE)1; // simplifies check code + + PORT->Alerted = TRUE; + + while (PORT->CONNECTED && SDRANGELRunning) + { + 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 (SDRANGELRunning == 0) + return; + + if (ret == SOCKET_ERROR) + { + Debugprintf("SDRAngel Select failed %d ", WSAGetLastError()); + goto Lost; + } + + if (ret > 0) + { + // See what happened + + if (FD_ISSET(PORT->remoteSock, &readfs)) + { + SDRANGELProcessMessage(PORT); + } + + if (FD_ISSET(PORT->remoteSock, &errorfs)) + { +Lost: + sprintf(Msg, "SDRAngel Connection lost for Port %s\r\n", PORT->IOBASE); + WritetoConsole(Msg); + + PORT->CONNECTED = FALSE; + PORT->Alerted = FALSE; + PORT->hDevice = 0; // simplifies check code + + closesocket(PORT->remoteSock); + PORT->remoteSock = 0; + return; + } + continue; + } + else + { + } + } + sprintf(Msg, "SDRAngel Thread Terminated Port %s\r\n", PORT->IOBASE); + WritetoConsole(Msg); +} + +/* +# 10489630000 + +CURL_DATA='{ + "deviceHwType": "RTLSDR", + "direction": 0, + "rtlSdrSettings": { + "centerFrequency": "'$1'" + } + +}'; + + +curl -X PATCH "http://127.0.0.1:8091/sdrangel/deviceset/0/device/settings" \ + -H "accept: application/json" \ + -H "Content-Type: application/json" \ + -d "$CURL_DATA" + + + + + + + + + +*/ + + +VOID SDRANGELPoll(struct RIGPORTINFO * PORT) +{ + UCHAR * Poll = PORT->TXBuffer; + + // SDRAngel can have muliple rigs but we only need to poll once to get info for all rigs so just use first entry + + struct RIGINFO * RIG = &PORT->Rigs[0]; + int Len, i; + char ReqBuf[256]; + char SendBuff[256]; + //char * SDRANGEL_GETheader = "GET /sdrangel/deviceset/%d/device/settings " + // "HTTP/1.1\nHost: %s\nConnection: keep-alive\n\r\n"; + + char * SDRANGEL_GETheader = "GET /sdrangel/devicesets " + "HTTP/1.1\nHost: %s\nConnection: keep-alive\n\r\n"; + + + if (RIG->ScanStopped == 0) + if (RIG->ScanCounter) + RIG->ScanCounter--; + + if (PORT->Timeout) + { + PORT->Timeout--; + + if (PORT->Timeout) // Still waiting + return; + + // Loop through all Rigs + + for (i = 0; i < PORT->ConfiguredRigs; i++) + { + RIG = &PORT->Rigs[i]; + + SetWindowText(RIG->hFREQ, "------------------"); + SetWindowText(RIG->hMODE, "----------"); + strcpy(RIG->WEB_FREQ, "-----------");; + strcpy(RIG->WEB_MODE, "------"); + + RIG->RIGOK = FALSE; + } + return; + } + + // Send Data if avail, else send poll + + if (RIG->NumberofBands && RIG->RIGOK && (RIG->ScanStopped == 0)) + { + if (RIG->ScanCounter <= 0) + { + // Send Next Freq + + if (GetPermissionToChange(PORT, RIG)) + { + char cmd[80]; + double freq; + + if (RIG->RIG_DEBUG) + Debugprintf("BPQ32 Change Freq to %9.4f", PORT->FreqPtr->Freq); + + _gcvt(PORT->FreqPtr->Freq / 1000000.0, 9, RIG->Valchar); // For MH + + // Send the Set Freq here, send set mode when we get a response + + memcpy(&PORT->ScanEntry, PORT->FreqPtr, sizeof(struct ScanEntry)); + +//TODO + sprintf(cmd, "%.0f", PORT->FreqPtr->Freq); + SDRANGELSendCommand(PORT, "SETFREQ", cmd); + + + PORT->CmdSent = 1; + PORT->Retries = 0; + PORT->Timeout = 10; + PORT->AutoPoll = TRUE; + + // There isn't a response to a set command, so clear Scan Lock here + ReleasePermission(RIG); // Release Perrmission + return; + } + } + } + + if (RIG->PollCounter) + { + RIG->PollCounter--; + if (RIG->PollCounter > 1) + return; + } + + if (RIG->RIGOK && (RIG->ScanStopped == 0) && RIG->NumberofBands) + return; // no point in reading freq if we are about to change it + + RIG->PollCounter = 40; + + // Read Frequency +//TODO + + +// Len = sprintf(SendBuff, SDRANGEL_GETheader, 0, &PORT->remoteDest ); // devicenum, host:port + Len = sprintf(SendBuff, SDRANGEL_GETheader, &PORT->remoteDest ); // devicenum, host:port + + if (PORT->CONNECTED) + { + if (send(PORT->remoteSock, SendBuff, Len, 0) != Len) + { + if (PORT->remoteSock) + closesocket(PORT->remoteSock); + + PORT->remoteSock = 0; + PORT->CONNECTED = FALSE; + PORT->hDevice = 0; + return; + } + } + + PORT->Timeout = 10; + PORT->CmdSent = 0; + + PORT->AutoPoll = TRUE; + + return; +} + +VOID SDRANGELSendCommand(struct RIGPORTINFO * PORT, char * Command, char * Value) +{ + int Len, ret; + char ReqBuf[512]; + char SendBuff[512]; + char ValueString[256] =""; + char * SDRANGEL_PATCHheader = "PATCH /sdrangel/deviceset/%d/device/settings " + "HTTP/1.1\nHost: %s\n" + "accept: application/json\n" + "Content-Type: application/json\n" + "Connection: keep-alive\n" + "Content-length: %d\r\n" + "\r\n%s"; + + if (!PORT->CONNECTED) + return; + + sprintf(ValueString, SDRANGEL_FREQ_DATA, "RTLSDR", Value); + + Len = sprintf(SendBuff, SDRANGEL_PATCHheader, 0, &PORT->remoteDest, strlen(ValueString), ValueString); + + ret = send(PORT->remoteSock, SendBuff, Len, 0); + + if (ret != Len) + { + if (PORT->remoteSock) + closesocket(PORT->remoteSock); + + PORT->remoteSock = 0; + PORT->CONNECTED = FALSE; + PORT->hDevice = 0; + } + + return; +} + + +void SDRANGELProcessMessage(struct RIGPORTINFO * PORT) +{ + // Called from Background thread + + int InputLen = recv(PORT->remoteSock, &PORT->RXBuffer[PORT->RXLen], 8192 - PORT->RXLen, 0); + + if (InputLen == 0 || InputLen == SOCKET_ERROR) + { + if (PORT->remoteSock) + closesocket(PORT->remoteSock); + + PORT->remoteSock = 0; + + PORT->CONNECTED = FALSE; + PORT->hDevice = 0; + return; + } + + PORT->RXLen += InputLen; + ProcessSDRANGELFrame(PORT); +} +// ---- G7TAJ ---- diff --git a/SCSPactor.c b/SCSPactor.c index 14c82c6..eff5512 100644 --- a/SCSPactor.c +++ b/SCSPactor.c @@ -1770,9 +1770,6 @@ VOID SCSPoll(int Port) Buffer[datalen] = 0; - // Buffer has an ax.25 header, which we need to pick out and set as channel 0 Connect address - // before sending the beacon - // If a Dragon with KISS over Hostmade we can just send it if (TNC->DragonKISS) @@ -1817,6 +1814,11 @@ VOID SCSPoll(int Port) return; } + // Not dragon KISS + + // Buffer has an ax.25 header, which we need to pick out and set as channel 0 Connect address + // before sending the beacon + // We also need to set Chan 0 Mycall so digi'ing can work, and put // it back after so incoming calls will work @@ -1824,7 +1826,6 @@ VOID SCSPoll(int Port) // This doesn't seem to work -/* ConvFromAX25(Buffer + 7, ICall); // Origin strlop(ICall, ' '); @@ -1867,7 +1868,7 @@ VOID SCSPoll(int Port) 1, Buffer, // Flag CmdSet as Data 2, TNC->NodeCall); // Flag as Chan 0 Command } -*/ + ReleaseBuffer((UINT *)buffptr); return; } diff --git a/TelnetV6.c b/TelnetV6.c index cbf8c4f..ad4c70b 100644 --- a/TelnetV6.c +++ b/TelnetV6.c @@ -780,6 +780,8 @@ scanCTEXT: } TCP->NumberofUsers += 1; } + else if (_memicmp(errbuf, "WL2KREPORT", 10) == 0) + TNC->WL2K = DecodeWL2KReportLine(errbuf); else if (_stricmp(param,"WebTermCSS") == 0) { TCP->WebTermCSS = _strdup(value); @@ -2492,7 +2494,7 @@ nosocks: { Port = atoi(P2); - if (Port > 33 || TCP->CMDPort[Port] == 0) + if (Port > MaxBPQPortNo || TCP->CMDPort[Port] == 0) { buffptr->Len = sprintf(&buffptr->Data[0], "Error - Invalid HOST Port\r"); C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr); diff --git a/UIRoutines.c b/UIRoutines.c index 014fe01..923725b 100644 --- a/UIRoutines.c +++ b/UIRoutines.c @@ -153,7 +153,7 @@ VOID QueueRaw(int Port, PMESSAGEX AXMSG, int Len) AXMSG->LENGTH = Len; AXMSG->CHAIN = 0; // Clear chain in new buffer - memcpy(AXCopy, AXMSG, Len + 10); + memcpy(AXCopy, AXMSG, Len + 11); GetSemaphore(&DGSemaphore, 0); diff --git a/Versions.h b/Versions.h index 534ed21..3b3f657 100644 --- a/Versions.h +++ b/Versions.h @@ -10,8 +10,8 @@ #endif -#define KVers 6,0,24,10 -#define KVerstring "6.0.24.10\0" +#define KVers 6,0,24,11 +#define KVerstring "6.0.24.11\0" #ifdef CKernel diff --git a/cMain.c b/cMain.c index 9acb24a..d29847c 100644 --- a/cMain.c +++ b/cMain.c @@ -939,7 +939,8 @@ BOOL Start() PORT->QUAL_ADJUST = (UCHAR)PortRec->QUALADJUST; PORT->DIGIFLAG = PortRec->DIGIFLAG; - PORT->DIGIPORT = PortRec->DIGIPORT; + if (PortRec->DIGIPORT && CanPortDigi(PortRec->DIGIPORT)) + PORT->DIGIPORT = PortRec->DIGIPORT; PORT->DIGIMASK = PortRec->DIGIMASK; PORT->USERS = (UCHAR)PortRec->USERS; @@ -2075,7 +2076,6 @@ VOID TIMERINTERRUPT() L3FastTimer(); L4TimerProc(); - } // SEE IF ANY FRAMES TO TRACE diff --git a/rigcontrol.h b/rigcontrol.h index e762ea4..2868704 100644 --- a/rigcontrol.h +++ b/rigcontrol.h @@ -74,10 +74,11 @@ struct RIGINFO int ICF8101; // ICOM Land Mobile IC-F8101 char * CM108Device; // Device to open for CM108 GPIO PTT - struct _EXTPORTDATA * PortRecord[32]; // BPQ32 port record(s) for this rig (null terminated list) + struct _EXTPORTDATA * PortRecord[64]; // BPQ32 port record(s) for this rig (null terminated list) UCHAR RigAddr; - uint64_t ScanStopped; // Scanning enabled if zero. Bits used for interlocked scanning (eg winmor/pactor on same port + int Channel; // For sdrangel + uint64_t ScanStopped; // Scanning enabled if zero. Bits used for interlocked scanning (eg winmor/pactor on same port int ScanCounter; int PollCounter; // Don't poll too often; int ScanFreq; // Scan Rate @@ -198,6 +199,9 @@ struct RIGINFO #define RTLUDP 16 #define FLRIG 17 #define SDRRADIO 18 +//G7TAJ +#define SDRANGEL 19 +//G7TAJ // Yease seem to have lots of variants of the same model @@ -234,7 +238,9 @@ struct RIGPORTINFO HANDLE hPTTDevice; // May use a different port for PTT UCHAR TXBuffer[500]; // Last message sent - saved for Retry int TXLen; // Len of last sent - UCHAR RXBuffer[500]; // Message being received - may not arrive all at once +// ---- G7TAJ ---- + UCHAR RXBuffer[8192]; // Message being received - may not arrive all at once. SDRANGLE needs a lot +// ---- G7TAJ ---- int RXLen; // Data in RXBUffer BOOL AutoPoll; // set if last command was a Timer poll // Local ScanStruct for Interactive Commands