diff --git a/APRSCode.c b/APRSCode.c
index a9af47a..34c9062 100644
--- a/APRSCode.c
+++ b/APRSCode.c
@@ -2187,7 +2187,7 @@ static int APRSProcessLine(char * buf)
 		CrossPortMap[Port][0] = FALSE;		// Cancel Default APRSIS
 
 		if (Context == NULL || Context[0] == 0)
-			return FALSE;
+			return TRUE;
 
 		ptr = strtok_s(NULL, ",\t\n\r", &Context);
 
diff --git a/APRSStdPages.c b/APRSStdPages.c
index dc253ed..300df3c 100644
--- a/APRSStdPages.c
+++ b/APRSStdPages.c
@@ -3279,31 +3279,40 @@ char * get_aprs()
 		"\n"
 		"var myTimeout;\n"
 		"\n"
-		"var server1 = \"http://server1.g8bpq.net:7383\"\n"
-		"var server2 = \"http://server2.g8bpq.net:7383\"\n"
+
+//https://tile.openstreetmap.org/{zoom}/{x}/{y}.png
+
+//		"var server1 = \"http://server1.g8bpq.net:7383\"\n"
+//		"var server2 = \"http://server2.g8bpq.net:7383\"\n"
+
+		"var server1 = \"tile.openstreetmap.org\"\n"
+		"var server2 = \"tile.openstreetmap.org\"\n"
 		"\n"
 		"function getMap(p)\n"
 		"{\n"
-		"  var gl = L.maplibreGL({style: server1 + '/styles/G8BPQ/style.json'});\n"
-		"  gl.addTo(p);\n"
-		"   var maplibreMap = gl.getMaplibreMap();\n"
-		"\n"
-		"  // if load from first server fails, switch to backup\n"
-		"\n"
-		"  maplibreMap.on('error', e =>\n"
-		"   {\n"
-		"	console.log(e.error);\n"
-		"\n"
-		"		if (e && e.error == 'Error: Failed to fetch')\n"
-		"		{\n"
-		"		  console.log('failed to load from ' + server1 + ', trying ' + server2);\n"
-		"		  var gl2 = L.maplibreGL({style: server2 + '/styles/G8BPQ/style.json'});\n"
-		"		  p.removeLayer(gl)\n"
-		"		  gl2.addTo(p);\n"
-		"		}\n"
-		"    });\n"
-		"\n"
-		"	p.attributionControl.addAttribution('Map data from OpenStreetMap using maplibre-gl Styles based on Mapbox gl');\n"
+
+	"	L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {attribution: '© OpenStreetMap contributors'}).addTo(p);\r\n"
+
+	//	"  var gl = L.maplibreGL({style: server1 + '/styles/G8BPQ/style.json'});\n"
+	//	"  gl.addTo(p);\n"
+	//	"   var maplibreMap = gl.getMaplibreMap();\n"
+	//	"\n"
+	//	"  // if load from first server fails, switch to backup\n"
+	//	"\n"
+	//	"  maplibreMap.on('error', e =>\n"
+	//	"   {\n"
+	//	"	console.log(e.error);\n"
+	//	"\n"
+	//	"		if (e && e.error == 'Error: Failed to fetch')\n"
+	//	"		{\n"
+	//	"		  console.log('failed to load from ' + server1 + ', trying ' + server2);\n"
+	//	"		  var gl2 = L.maplibreGL({style: server2 + '/styles/G8BPQ/style.json'});\n"
+	//	"		  p.removeLayer(gl)\n"
+	//	"		  gl2.addTo(p);\n"
+	//	"		}\n"
+	//	"    });\n"
+	//	"\n"
+	//	"	p.attributionControl.addAttribution('Map data from OpenStreetMap using maplibre-gl Styles based on Mapbox gl');\n"
 		"	L.control.scale().addTo(p);\n"
 		"}\n"
 		"\n"
diff --git a/BBSUtilities.c b/BBSUtilities.c
index 833d3f9..6c542ba 100644
--- a/BBSUtilities.c
+++ b/BBSUtilities.c
@@ -225,7 +225,7 @@ extern BOOL EventsEnabled;
 
 extern BPQVECSTRUC BPQHOSTVECTOR[BPQHOSTSTREAMS + 5];
 
-/* --- TAJ PG Server--- */
+/* --- G7TAJ PG Server--- */
 
 void run_pg( CIRCUIT * conn, struct UserInfo * user );
 void startrun_pgThread( RUNPGARGS_PTR Args );
@@ -234,7 +234,7 @@ char * SERVERLIST[256][3];
 
 int NUM_SERVERS = 0;
 
-/*------- TAJ END ----------*/
+/*------- G7TAJ END ----------*/
 
 
 #ifdef LINBPQ
@@ -1038,20 +1038,6 @@ Next:
 	}
 
 	SortBBSChain();
-
-/*------- TAJ PG SERVER ----------*/
-
-#ifndef WIN32
- printf("Number of PG Servers = %d\n", NUM_SERVERS );
-
- for ( int i=0; i< NUM_SERVERS; i++ ) {
-   printf("Server #%d\t%s\tExec->%s\tDESC->%s\n", i, SERVERLIST[i][0], SERVERLIST[i][1], SERVERLIST[i][2]);
- }
-
-
-#endif
-/*------- TAJ END ----------*/
-
 }
 
 VOID CopyUserDatabase()
@@ -8241,6 +8227,7 @@ InBand:
 		else
 			Delay = 1000;
 
+
 		conn->BBSFlags &= ~RunningConnectScript;	// so it doesn't get reentered
 		Disconnect(conn->BPQStream);
 
@@ -8385,6 +8372,14 @@ InBand:
 				goto LoopBack;
 			}
 
+			if (_memicmp(Cmd, "IDLETIME ", 9) == 0)
+			{
+				int idle = atoi(&Cmd[9]);
+
+				ChangeSessionIdletime(conn->BPQStream, idle);
+				goto LoopBack;
+			}
+
 			if (_memicmp(Cmd, "RADIO AUTH", 10) == 0)
 			{
 				// Generate a Password to enable RADIO commands on a remote node
@@ -9185,12 +9180,14 @@ VOID FWDTimerProc()
 	struct	BBSForwardingInfo * ForwardingInfo ;
 	time_t NOW = time(NULL);
 
+	// Entered every 2 seconds
+
 	for (user = BBSChain; user; user = user->BBSNext)
 	{
 		// See if any messages are queued for this BBS
 
 		ForwardingInfo = user->ForwardingInfo;
-		ForwardingInfo->FwdTimer+=10;
+		ForwardingInfo->FwdTimer += 2;
 
 		if (ForwardingInfo->FwdTimer >= ForwardingInfo->FwdInterval)
 		{
@@ -10852,15 +10849,15 @@ int Disconnected (int Stream)
 				conn->InputBufferLen = 0;
 			}
 
-			/* ---- TAJ PG SERVER ---- */
+			/* ---- G7TAJ PG SERVER ---- */
 			if (conn->UserPointer && conn->UserPointer->Temp && conn->UserPointer->Temp->RUNPGPARAMS)
 			{
-				printf("Freeing RUNPGPARAMS\n");
+				Debugprintf("Freeing RUNPGPARAMS");
 				free(conn->UserPointer->Temp->RUNPGPARAMS);
 				conn->UserPointer->Temp->RUNPGPARAMS = NULL;
 			}
 
-			/*------- TAJ END --------- */
+			/*------- G7TAJ END --------- */
 
 			if (conn->InputMode == 'B')
 			{
@@ -10977,7 +10974,7 @@ int DoReceivedData(int Stream)
 				}
 
 
-			/* ---------- TAJ START - PG server  --------- */
+			/* ---------- G7TAJ START - PG server  --------- */
 
 				if (conn->InputMode == 'P')			// Inside PG Server
 				{
@@ -10985,7 +10982,7 @@ int DoReceivedData(int Stream)
 					run_pg(conn, user);
 					return 0;
 				}
-			/* ---------- TAJ END --------- */
+			/* ---------- G7TAJ END --------- */
 
 				if (conn->InputMode == 'B')
 				{
@@ -11736,7 +11733,7 @@ extern UCHAR * infile;
 
 BOOL CheckforMIME(SocketConn * sockptr, char * Msg, char ** Body, int * MsgLen);
 
-/* ---TAJ PG Server --- */
+/* ---G7TAJ PG Server --- */
 #ifndef WIN32
 
 #define verbose 1
@@ -11758,22 +11755,23 @@ typedef struct _POPENRET
 void run_pgTimeoutThread( pid_t process )
 {
 
-   printf("watchdog thread: PID of subprocess: %d\n", process);
-   fflush(stdout);
-   Sleep(5000);
-   // if still running PID (?) then kill.
-   if ( getpgid(process) >= 0 ) {
-	   printf("watchdog thread: Still running, so killing %d ... ", process);
-//	   if ( kill( process, SIGTERM  ) == 0 ) {
-	   if ( kill( -process, SIGKILL ) == 0 ) {
-		printf("Killed\n");
-	   } else {
-		printf("Failed\n");
-   	   }
-   }
-   printf("watchdog thread: PID=%d Exit\n", process);
-   fflush(stdout);
-   //return;
+	printf("watchdog thread: PID of subprocess: %d\n", process);
+	fflush(stdout);
+	Sleep(5000);
+	// if still running PID (?) then kill.
+	if ( getpgid(process) >= 0 )
+	{
+		Debugprintf("watchdog thread: Still running, so killing %d ... ", process);
+		if ( kill( -process, SIGKILL ) == 0 )
+			Debugprintf("Killed PG watchdog Process %d", process);
+		else
+			Debugprintf("Failed to kill PG watchdog Process %d", process);   
+	}
+
+
+	Debugprintf("watchdog thread: PID=%d Exit", process);
+	fflush(stdout);
+	//return;
 }
 
 
@@ -11802,7 +11800,7 @@ POPENRET my_popen(char *program, char *type, CIRCUIT *conn)
 		if (*type == 'r') {
 			if (pdes[1] != 1) {
 				dup2(pdes[1], 1);
-				dup2(pdes[1], 2);	/* stderr, too! */
+				dup2(pdes[1], 2);
 				(void)close(pdes[1]);
 			}
 			(void)close(pdes[0]);
@@ -11819,9 +11817,8 @@ POPENRET my_popen(char *program, char *type, CIRCUIT *conn)
 		_exit(1);
 	}
 
-	/* parent; assume fdopen can't fail...  */
+	/* parent */
 
-        printf("PID=%d\n", pid );
        _beginthread((void (*)(void *))run_pgTimeoutThread, 0, (VOID *) pid );
 
 	if (*type == 'r') {
@@ -11833,17 +11830,13 @@ POPENRET my_popen(char *program, char *type, CIRCUIT *conn)
 	}
 
   	char buffer[128];
-	while (fgets(buffer, sizeof(buffer), iop) != NULL) {
-	   BBSputs(conn, buffer);
-//           printf("%s", buffer);
-//	   sleep(200);
-	  buffer[0] = '\0';
+	while (fgets(buffer, sizeof(buffer), iop) != NULL)
+	{
+		BBSputs(conn, buffer);
+		buffer[0] = '\0';
   	}
-//	BBSputs(conn,"\n");
 	PRET.fp = iop;
 	PRET.pid= pid;
-//	(void)close(pdes[0]);
-//	(void)close(pdes[1]);
 
 	return(PRET);
 }
@@ -11869,92 +11862,82 @@ my_pclose( POPENRET pret )
 	sigprocmask(SIG_SETMASK, &omask, NULL);
 	if (pid == -1 || !WIFEXITED(stat_loc))
 		return -1;
-//	return WEXITSTATUS(stat_loc);
-	printf( "return = %d\n", WEXITSTATUS(stat_loc));
 	return stat_loc;
 }
 
 
 int run_server (char **cmd, int nb_cmd, int mode, char *log, char *pgdir, char *data, CIRCUIT * conn)
 {
-        int i;
-        int ret = 0;
-        FILE *fp;
+	int i;
+	int ret = 0;
+	FILE *fp;
 	POPENRET PRET;
 	pid_t pid;
-        char *ptr;
-        char file[256];
-        char buf[256];
-        char dir[256];
-        char arg[256];
+	char *ptr;
+	char file[256];
+	char buf[256];
+	char dir[256];
+	char arg[256];
 
-        if (mode)
-//              sprintf (file, " %s", log);
-//              sprintf (file, " >>%s", log);
-//              sprintf (file, " | tee -a %s", log);
+	if (mode)
+		//              sprintf (file, " >>%s", log);
+		//              sprintf (file, " | tee -a %s", log);
 		sprintf(file, "" );
-        else
-                sprintf (file, " > 8;
 
-                if (verbose) {
-                        printf ("Debug: command = {%s}\n", buf);
-                        printf ("Debug: exit code = %d\n", ret);
-                }
+		if (verbose) {
+			Debugprintf ("Debug: command = {%s}\n", buf);
+			Debugprintf ("Debug: exit code = %d\n", ret);
+		}
 
-                /* fail-safe bypass if filter executable isn't found (exit code 127) (was ret ==127)*/
-                if (ret > 5)      // should never be more than 5
-                        ret = 0;
-         }
-         return ( ret );
+		/* fail-safe bypass if executable isn't found (exit code 127) (was ret ==127)*/
+		if (ret > 5)      // should never be more than 5
+			ret = 0;
+	}
+	return ( ret );
 }
 
 
@@ -11962,7 +11945,6 @@ void run_pg( CIRCUIT * conn, struct UserInfo * user )
 {
 
   if (!user->Temp->RUNPGPARAMS) {
-//	printf("Allocating new RUNPGPARAMS\n");
 	user->Temp->RUNPGPARAMS = (RUNPGARGS_PTR) zalloc(sizeof(RUNPGARGS));
   }
 
@@ -11972,7 +11954,7 @@ void run_pg( CIRCUIT * conn, struct UserInfo * user )
   user->Temp->RUNPGPARAMS->Len = conn->InputLen;
 
   if ( conn == 0 || user == 0 ) {
- 	printf("run_pg null err\n");
+ 	Debugprintf("run_pg null err");
 	return;
   }
 
@@ -11984,65 +11966,80 @@ void run_pg( CIRCUIT * conn, struct UserInfo * user )
 
 void startrun_pgThread( RUNPGARGS_PTR Args ) {
 
-  CIRCUIT * conn = Args->conn;
-  struct UserInfo * user = Args->user;
+	CIRCUIT * conn = Args->conn;
+	struct UserInfo * user = Args->user;
 
-  char cmd[20];
-  sprintf( cmd, "./%s", SERVERLIST[user->Temp->PG_SERVER][1] );
-  char *ptr = cmd;
-  char pg_dir[] = "/home/pi/linbpq/linbpq/downloads/new/linbpq/pg/";
-  char log_file[50] = "pg.log";
-  char call[6];
-  char data[80];
-  char line[80];
-  char *line_ptr = line;
-  int  index;
-  char *data_ptr = data;
-  size_t bufsize = 80;
+	char cmd[20];
+	sprintf( cmd, "./%s", SERVERLIST[user->Temp->PG_SERVER][1] );
+	char *ptr = cmd;
+	char pg_dir[MAX_PATH];
+	char log_file[50] = "pg.log";
+	char call[6];
+	char data[80];
+	char line[80];
+	char *line_ptr = line;
+	int  index;
+	char *data_ptr = data;
+	size_t bufsize = 80;
 
-  strcpy( call, conn->UserPointer->Call);
-//  sprintf( log_file, "%s-%d.log", call, conn);
-  index = user->Temp->PG_INDEX;
+	strcpy(pg_dir, BaseDir);
+	strcat(pg_dir, "/PG/");
 
-  line[0] = '\0';
-  int Len = Args->Len;
-  UCHAR * Msg = Args->InputBuffer;
-  strncpy( line, Msg, Len);
-  line[ Len - 1 ] = 0;   //remove LF
+	sprintf(line, "%s%s", pg_dir, SERVERLIST[user->Temp->PG_SERVER][1]);
 
-  sprintf( data, "%s %d 0 0 %s", call, index, line);
+	// check file exists and is executable
+	if (access(line, F_OK) == -1 || access(line, X_OK) == -1) {
+		Debugprintf("%s FileNotFound || Not EXE", line);
+		BBSputs(conn, "Error running PG Server\r");
+		conn->InputMode=0;
+		SendPrompt(conn, user);
+		return;
+	}
 
-  // clear the input queue
-  conn->InputLen = 0;
-  conn->InputBufferLen = 0;
 
-  int ret = run_server (&ptr, 1, 1, log_file, pg_dir, data_ptr, conn);
+	strcpy( call, conn->UserPointer->Call);
+	//  sprintf( log_file, "%s-%d.log", call, conn);
+	index = user->Temp->PG_INDEX;
 
-  switch (ret)
-      {
-		 case -1:	// ERROR or forced closed
-                  case 0:       index=0;			// Goodbye/Exit
-				conn->InputMode=0;
-				SendPrompt(conn, user);
-                                break;
-                  case 1:       index++;			// inc & keep in PG
-                                break;
-                  case 2:       index=0;			// disconnect
-				conn->InputMode=0;
-				Disconnect(conn->BPQStream);
-                                break;
-                  case 3:       printf("data->BBS & end\n");
-                                break;
-                  case 4:       printf("data->BBS and inc %d\n", index++);
-                                break;
-                  case 5:       printf("call no inc %d\n", ret);
-                                break;
+	line[0] = '\0';
+	int Len = Args->Len;
+	UCHAR * Msg = Args->InputBuffer;
+	strncpy( line, Msg, Len);
+	line[ Len - 1 ] = 0;   //remove LF
 
-         }
+	sprintf( data, "%s %d 0 0 %s", call, index, line);
+
+	// clear the input queue
+	conn->InputLen = 0;
+	conn->InputBufferLen = 0;
+
+	int ret = run_server (&ptr, 1, 1, log_file, pg_dir, data_ptr, conn);
+
+	switch (ret)
+	{
+	case -1:	// ERROR or forced closed
+	case 0:       index=0;			// Goodbye/Exit
+		conn->InputMode=0;
+		SendPrompt(conn, user);
+		break;
+	case 1:       index++;			// inc & keep in PG
+		break;
+	case 2:       index=0;			// disconnect
+		conn->InputMode=0;
+		Disconnect(conn->BPQStream);
+		break;
+	case 3:       Debugprintf("data->BBS & end");
+		break;
+	case 4:       Debugprintf("data->BBS and inc %d", index++);
+		break;
+	case 5:       Debugprintf("call no inc %d", ret);
+		break;
+
+	}
 
 	user->Temp->PG_INDEX=index;
 }
-/*---- TAJ END ----- */
+/*---- G7TAJ END ----- */
 
 #else
 
@@ -12075,7 +12072,7 @@ void run_pg( CIRCUIT * conn, struct UserInfo * user )
 	int index = 0;
 	int ret = 0;
 
-	// if first entay allocate RUNPGPARAMS
+	// if first entry allocate RUNPGPARAMS
 	if (!user->Temp->RUNPGPARAMS)
 	{
 		user->Temp->RUNPGPARAMS = (RUNPGARGS_PTR) zalloc(sizeof(RUNPGARGS));
@@ -13063,7 +13060,7 @@ VOID ProcessLine(CIRCUIT * conn, struct UserInfo * user, char* Buffer, int len)
 		return;
 	}
 
-	/*---- TAJ PG Server ----- */
+	/*---- G7TAJ PG Server ----- */
 
 
 	if (_stricmp(Cmd, "PG") == 0)
@@ -13106,11 +13103,13 @@ VOID ProcessLine(CIRCUIT * conn, struct UserInfo * user, char* Buffer, int len)
 					return;
 				}
 			}
+			BBSputs(conn, "No server found\r");
+			SendPrompt(conn, user);
+			return;
 		}
-
 	}
 
-	/*---- TAJ END ---- */
+	/*---- G7TAJ END ---- */
 
 	if (conn->Flags == 0)
 	{
@@ -15750,6 +15749,7 @@ VOID GetPGConfig()
 	char buf[256],errbuf[256];
 	char * p_prog, * p_name, * p_desc;
 	int n = 0;
+	int i = 0;
 
 
 	strcpy(FN, BaseDir);
@@ -15761,6 +15761,9 @@ VOID GetPGConfig()
 	
 	while(fgets(buf, 255, file) != NULL)
 	{
+		if ( buf[0] == '#')
+			continue;
+
 		strcpy(errbuf,buf);			// save in case of error
 
 		p_prog = strtok(buf, ",\n\r");
@@ -15784,6 +15787,15 @@ VOID GetPGConfig()
 
 	NUM_SERVERS = n;
 	fclose(file);
+	
+	/*------- G7TAJ PG SERVER ----------*/
+	Debugprintf("Number of PG Servers = %d", NUM_SERVERS );
+	for (i=0; i< NUM_SERVERS; i++ )
+	{
+		Debugprintf("Server #%d,%s,%s,%s", i, SERVERLIST[i][0], SERVERLIST[i][1], SERVERLIST[i][2]);
+	}
+	/*------- G7TAJ END ----------*/
+
 }
 
 void SendMessageReadEvent(char * call, struct MsgInfo * Msg)
diff --git a/BPQChat.vcproj.NOTTSDESKTOP.John.user b/BPQChat.vcproj.NOTTSDESKTOP.John.user
new file mode 100644
index 0000000..fa82c00
--- /dev/null
+++ b/BPQChat.vcproj.NOTTSDESKTOP.John.user
@@ -0,0 +1,65 @@
+
+
+	
+		
+			
+		
+		
+			
+		
+	
+
diff --git a/BPQMail.c b/BPQMail.c
index bbc9ece..2ca2985 100644
--- a/BPQMail.c
+++ b/BPQMail.c
@@ -1131,6 +1131,8 @@
 //	Add Send P to multiple BBS's when routing on HR (30)
 //	Fix Traffic stats for T messages received via B2 forwarding  (31)
 //	Fix possible failure to update last listed count when user disconnects without using B command
+//	Add short random delay (<30 secs) when forward new Messages immediately is enabled (35)
+//  Fix Connect Script IDLETIME (38)
 
 #include "bpqmail.h"
 #include "winstdint.h"
@@ -2160,7 +2162,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 				CheckTimer();
 				TCPTimer();
 				BBSSlowTimer();
-				FWDTimerProc();
 				if (MaintClock < NOW)
 				{
 					while (MaintClock < NOW)		// in case large time step
@@ -2182,6 +2183,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 			}
 			My__except_Routine("Slow Timer");
 		}
+		if (wParam == 3)		// Forward (2 Secs)
+		{
+			__try
+			{
+				FWDTimerProc();
+			}
+			My__except_Routine("Fwd Timer");
+		}
 		else
 			__try
 			{
@@ -3310,6 +3319,7 @@ BOOL Initialise()
 	
 	SetTimer(hWnd,1,10000,NULL);	// Slow Timer (10 Secs)
 	SetTimer(hWnd,2,100,NULL);		// Send to Node and TCP Poll (100 ms)
+	SetTimer(hWnd,3,2000,NULL);		// Forward Check  (2 secs)
 
 	// Calulate time to run Housekeeping
 	{
diff --git a/BPQWinAPP.vcproj.NOTTSDESKTOP.John.user b/BPQWinAPP.vcproj.NOTTSDESKTOP.John.user
new file mode 100644
index 0000000..fa82c00
--- /dev/null
+++ b/BPQWinAPP.vcproj.NOTTSDESKTOP.John.user
@@ -0,0 +1,65 @@
+
+
+	
+		
+			
+		
+		
+			
+		
+	
+
diff --git a/Bpq32.c b/Bpq32.c
index ea24778..d333e5a 100644
--- a/Bpq32.c
+++ b/Bpq32.c
@@ -1213,6 +1213,12 @@ along with LinBPQ/BPQ32.  If not, see http://www.gnu.org/licenses
 //	Improve validation of Web Beacon Config (33)
 //	Support SNMP via host ip stack as well as IPGateway (34)
 
+//	Switch APRS Map to OSM tile servers (36)
+//	Fix potential buffer overflow in Telnet login (36)
+//	Allow longer serial device names (37)
+//	Fix ICF8101 Mode setting (37)
+
+
 #define CKernel
 
 #include "Versions.h"
diff --git a/CBPQ32.vcproj.NOTTSDESKTOP.John.user b/CBPQ32.vcproj.NOTTSDESKTOP.John.user
index f4ba73a..270b67b 100644
--- a/CBPQ32.vcproj.NOTTSDESKTOP.John.user
+++ b/CBPQ32.vcproj.NOTTSDESKTOP.John.user
@@ -37,7 +37,7 @@
 			Name="Release|Win32"
 			>
 			 0)
 	{
 		ret = write(fd, &Block[Sent], ToSend);
 
@@ -2596,6 +2597,12 @@ BOOL WriteCOMBlock(HANDLE fd, char * Block, int BytesToWrite)
 		Sent += ret;
 		ToSend -= ret;
 	}
+
+//	if (ToSend)
+//	{
+//		// Send timed out. Close and reopen device
+//
+//	}
 	return TRUE;
 }
 
diff --git a/HSMODEM.c b/HSMODEM.c
index 5362b87..de045c2 100644
--- a/HSMODEM.c
+++ b/HSMODEM.c
@@ -639,8 +639,8 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
 
 			if (buffptr == 0) return (0);			// No buffers, so ignore
 
-			buffptr->Len = 36;
-			memcpy(&buffptr->Data[0], "No Connection to TNC\r", 36);
+			buffptr->Len = 21;
+			memcpy(&buffptr->Data[0], "No Connection to TNC\r", 21);
 
 			C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr);
 			
diff --git a/IPCode.c b/IPCode.c
index 808840c..ded97db 100644
--- a/IPCode.c
+++ b/IPCode.c
@@ -2220,7 +2220,10 @@ BOOL CheckIPChecksum(PIPMSG IPptr)
 
 	checksum = cksum((unsigned short *)IPptr, 20);
 
-	if (checksum == 0xffff) return TRUE; else return FALSE;
+	if (checksum == 0xffff)
+		return TRUE;
+	else 
+		return FALSE;
 
 }
 BOOL Check_Checksum(VOID * ptr1, int Len)
@@ -2229,7 +2232,10 @@ BOOL Check_Checksum(VOID * ptr1, int Len)
 
 	checksum = cksum((unsigned short *)ptr1, Len);
 
-	if (checksum == 0xffff) return TRUE; else return FALSE;
+	if (checksum == 0xffff)
+		return TRUE;
+	else 
+		return FALSE;
 
 }
 USHORT Generate_CHECKSUM(VOID * ptr1, int Len)
diff --git a/L2Code.c b/L2Code.c
index 718f012..234e7d4 100644
--- a/L2Code.c
+++ b/L2Code.c
@@ -174,7 +174,7 @@ VOID L2Routine(struct PORTCONTROL * PORT, PMESSAGE Buffer)
 
 	if (c == ' ')					// Blank Call
 	{
-		Debugprintf("BPQ32 Blank Call Port &%", PORT->PORTNUMBER);
+		Debugprintf("BPQ32 Blank Call Port %d", PORT->PORTNUMBER);
 		ReleaseBuffer(Buffer);
 		return;
 	}
@@ -1775,7 +1775,7 @@ VOID L2_PROCESS(struct _LINKTABLE * LINK, struct PORTCONTROL * PORT, MESSAGE * B
 	
 		switch (CTL & 0x0f)
 		{
-			// is there any harm in accepoting SREJ even if we don't
+			// is there any harm in accepting SREJ even if we don't
 			// otherwise support 2.2?
 
 		case REJ:
@@ -3004,6 +3004,8 @@ VOID ACKMSG(struct _LINKTABLE * LINK)
 			Debugprintf("Missing frame to ack Seq %d Calls %s %s", LINK->LINKOWS, Call1, Call2);
 		}
 
+		LINK->IFrameRetryCounter = 0;
+
 		LINK->LINKOWS++;			// INCREMENT OLD WINDOW START
 		LINK->LINKOWS &= 7;			// MODULO 8
 
@@ -3018,6 +3020,18 @@ VOID ACKMSG(struct _LINKTABLE * LINK)
 	{
 		//	NOT ALL I-FRAMES HAVE BEEN ACK'ED - RESTART TIMER
 
+		//	Need to kill link if we are getting repeated RR(F) after timeout 
+		//	(Indicating other station is seeing our RR(P) but not the resent I frame)
+
+		if (LINK->IFrameRetryCounter++ > LINK->LINKPORT->PORTN2)
+		{
+			Debugprintf("Too many repeats of same I frame - closing connection");
+			LINK->L2TIMER = 1;		// USE TIMER TO SEND DISC
+			LINK->L2STATE = 4;		// DISCONNECTING
+			return;
+		}
+
+
 		LINK->L2TIMER = LINK->L2TIME;
 		return;
 	}
@@ -3033,7 +3047,7 @@ VOID ACKMSG(struct _LINKTABLE * LINK)
 
 	//	IF DISCONNECT REQUEST OUTSTANDING, AND NO FRAMES ON TX QUEUE,  SEND DISC
 
-	if (LINK->L2FLAGS & DISCPENDING && LINK->TX_Q == 0)
+	if ((LINK->L2FLAGS & DISCPENDING) && LINK->TX_Q == 0)
 	{
 		LINK->L2FLAGS &=  ~DISCPENDING;
 
diff --git a/LinBPQ.c b/LinBPQ.c
index 084ee45..6146500 100644
--- a/LinBPQ.c
+++ b/LinBPQ.c
@@ -75,6 +75,7 @@ int upnpClose();
 void SaveAIS();
 void initAIS();
 void DRATSPoll();
+VOID GetPGConfig();
 
 extern uint64_t timeLoadedMS;
 
@@ -1138,6 +1139,7 @@ int main(int argc, char * argv[])
 	GetBIDDatabase();
 	GetBadWordFile();
 	GetHTMLForms();
+	GetPGConfig();
 
 	// Make sure there is a user record for the BBS, with BBS bit set.
 
@@ -1557,13 +1559,15 @@ int main(int argc, char * argv[])
 		{
 			PollStreams();
 
+			if ((Slowtimer % 20) == 0)
+				FWDTimerProc();
+
 			if (Slowtimer > 100)		// 10 secs
 			{
 				time_t NOW = time(NULL);
 				struct tm * tm;
 
 				TCPTimer();
-				FWDTimerProc();
 				BBSSlowTimer();
 
 				if (MaintClock < NOW)
diff --git a/MailCommands.c b/MailCommands.c
index 8550439..dbb3245 100644
--- a/MailCommands.c
+++ b/MailCommands.c
@@ -351,7 +351,7 @@ VOID DoSetIdleTime(CIRCUIT * conn, struct UserInfo * user, char * Arg1, char * C
 		return;
 	}
 
-	nodeprintf(conn, "Idle Tine set to %d\r", IdleTime);
+	nodeprintf(conn, "Idle Time set to %d\r", IdleTime);
 	SendPrompt(conn, user);
 	return;
 }
diff --git a/MailNode.vcproj.NOTTSDESKTOP.John.user b/MailNode.vcproj.NOTTSDESKTOP.John.user
index fa82c00..34131b7 100644
--- a/MailNode.vcproj.NOTTSDESKTOP.John.user
+++ b/MailNode.vcproj.NOTTSDESKTOP.John.user
@@ -10,7 +10,7 @@
 			>
 			ForwardingInfo;
 		
-	if (ForwardToMe || _stricmp(bbs->Call, BBSName) != 0) // Dont forward to ourself - already here! (unless ForwardToMe set)
+	if (ForwardToMe || _stricmp(bbs->Call, BBSName) != 0) // Don't forward to ourself - already here! (unless ForwardToMe set)
 	{
 		if ((conn == NULL) || (!(conn->BBSFlags & BBS) || (_stricmp(conn->UserPointer->Call, bbs->Call) != 0))) // Dont send back
 		{
 			set_fwd_bit(Msg->fbbs, bbs->BBSNumber);
 			ForwardingInfo->MsgCount++;
 			if (ForwardingInfo->SendNew)
-				ForwardingInfo->FwdTimer = ForwardingInfo->FwdInterval;
+				ForwardingInfo->FwdTimer = ForwardingInfo->FwdInterval - (2 + (rand() % 30)); //Short delay to prevent all starting at once
 		}
 	}
 	else
diff --git a/RigControl.c b/RigControl.c
index ea7b5c2..4c32caa 100644
--- a/RigControl.c
+++ b/RigControl.c
@@ -1543,11 +1543,19 @@ int Rig_CommandEx(struct RIGPORTINFO * PORT, struct RIGINFO * RIG, TRANSPORTENTR
 					*(CmdPtr++) = 0x1A;
 					*(CmdPtr++) = 0x36;		// Set mode command
 					*(CmdPtr++) = 0;
-					if (ModeNo > 10)
+					if (ModeNo > 19)
+						*(CmdPtr++) = ModeNo + 12;
+					else if (ModeNo > 9)
 						*(CmdPtr++) = ModeNo + 6;
 					else
 						*(CmdPtr++) = ModeNo;
 					*(CmdPtr++) = 0xFD;
+
+//			Mode = (Msg[7] >> 4);
+//			Mode *= 10;
+//			Mode += Msg[7] & 0xf;
+
+
 				}
 			}
 			else
@@ -3980,6 +3988,8 @@ SetFinished:
 			strcpy(RIG->ModeString, Modes[Mode]);
 			SetWindowText(RIG->hMODE, RIG->WEB_MODE);
 
+
+
 			return;
 		}
 	}
@@ -6995,7 +7005,10 @@ CheckScan:
 				*(CmdPtr++) = 0x1A;
 				*(CmdPtr++) = 0x36;		// Set mode command
 				*(CmdPtr++) = 0;
-				if (ModeNo > 10)
+
+				if (ModeNo > 19)
+					*(CmdPtr++) = ModeNo + 12;
+				else if (ModeNo > 9)
 					*(CmdPtr++) = ModeNo + 6;
 				else
 					*(CmdPtr++) = ModeNo;
@@ -7480,7 +7493,11 @@ VOID PTTCATThread(struct RIGINFO *RIG)
 		if (Handle[HIndex] == (HANDLE) -1)
 		{
 			int Err = GetLastError();
-			Consoleprintf("PTTMUX port BPQCOM%s Open failed code %d - trying real com port", RIG->PTTCATPort[PIndex], Err);
+			char errmsg[256] = "";
+
+			// Only report if both BPQCOM and Real COM fail
+
+			sprintf(errmsg, "PTTMUX port BPQCOM%s Open failed code %d - trying real com port", RIG->PTTCATPort[PIndex], Err);
 
 			// See if real com port
 
@@ -7494,7 +7511,11 @@ VOID PTTCATThread(struct RIGINFO *RIG)
 			if (Handle[HIndex] == (HANDLE) -1)
 			{
 				int Err = GetLastError();
-				Consoleprintf("PTTMUX port COM%s Open failed code %d", RIG->PTTCATPort[PIndex], Err);
+				if (errmsg[0])
+				{
+					Consoleprintf("%s", errmsg);
+					Consoleprintf("PTTMUX port COM%s Open failed code %d", RIG->PTTCATPort[PIndex], Err);
+				}
 			}
 			else
 			{
diff --git a/SCSPactor.c b/SCSPactor.c
index c5a5ab0..798d5ce 100644
--- a/SCSPactor.c
+++ b/SCSPactor.c
@@ -423,7 +423,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
 		
 		if (TNC->PortRecord->PORTCONTROL.PortStopped == 0)
 			OpenCOMMPort(TNC, TNC->PortRecord->PORTCONTROL.SerialPortName, TNC->PortRecord->PORTCONTROL.BAUDRATE, TRUE);
-
+		
 		if (TNC->hDevice == 0)
 			return 0;
 
diff --git a/SCSPactor.c.bak b/SCSPactor.c.bak
new file mode 100644
index 0000000..78f96db
--- /dev/null
+++ b/SCSPactor.c.bak
@@ -0,0 +1,4322 @@
+/*
+Copyright 2001-2022 John Wiseman G8BPQ
+
+This file is part of LinBPQ/BPQ32.
+
+LinBPQ/BPQ32 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 3 of the License, or
+(at your option) any later version.
+
+LinBPQ/BPQ32 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 LinBPQ/BPQ32.  If not, see http://www.gnu.org/licenses
+*/	
+
+//
+//	DLL to inteface SCS TNC in Pactor Mode to BPQ32 switch 
+//
+//	Uses BPQ EXTERNAL interface
+
+
+// Dec 29 2009
+
+//	Add Scan Control using %W Hostmode Command
+//	Map Rig control port to a Virtual Serial Port.
+//	Add Support for packet port(s).
+
+// July 2010
+
+// Support up to 32 BPQ Ports
+
+// Version 1.1.1.14 August 2010 
+
+// Drop RTS as well as DTR on close
+
+// Version 1.2.1.1 August 2010 
+
+// Save Minimized State
+
+// Version 1.2.1.2 August 2010 
+
+// Implement scan bandwidth change
+
+// Version 1.2.1.3 September 2010 
+
+// Don't connect if channel is busy
+// Add WL2K reporting
+// Add PACKETCHANNELS config command
+// And Port Selector (P1 or P2) for Packet Ports
+
+// Version 1.2.1.4 September 2010
+
+// Fix Freq Display after Node reconfig
+// Only use AutoConnect APPL for Pactor Connects
+
+// Version 1.2.2.1 September 2010
+
+// Add option to get config from bpq32.cfg
+
+// October 2011
+
+// Changes for P4Dragon
+
+#define _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_DEPRECATE
+
+
+#include 
+#include 
+#include "time.h"
+
+//#include 
+//#include 
+
+#define MaxStreams 10			// First is used for Pactor, even though Pactor uses channel 31
+
+#include "CHeaders.h"
+#include "tncinfo.h"
+
+#include "bpq32.h"
+
+#ifndef WIN32
+#ifndef MACBPQ
+#ifndef FREEBSD
+
+#include 
+#include 
+#endif
+#endif
+#endif
+
+static char ClassName[]="PACTORSTATUS";
+static char WindowTitle[] = "SCS Pactor";
+static int RigControlRow = 185;
+
+
+#define NARROWMODE 12		// PI/II
+#define WIDEMODE 16			// PIII only
+
+extern UCHAR LogDirectory[];
+
+static RECT Rect;
+
+VOID __cdecl Debugprintf(const char * format, ...);
+
+char NodeCall[11];		// Nodecall, Null Terminated
+
+int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len);
+
+VOID SuspendOtherPorts(struct TNCINFO * ThisTNC);
+VOID ReleaseOtherPorts(struct TNCINFO * ThisTNC);
+
+VOID PTCSuspendPort(struct TNCINFO * TNC, struct TNCINFO * ThisTNC);
+VOID PTCReleasePort(struct TNCINFO * TNC);
+int	KissEncode(UCHAR * inbuff, UCHAR * outbuff, int len);
+int CheckMode(struct TNCINFO * TNC);
+VOID WritetoTrace(struct TNCINFO * TNC, char * Msg, int Len);
+void SCSTryToSendDATA(struct TNCINFO * TNC, int Stream);
+VOID UpdateMHwithDigis(struct TNCINFO * TNC, UCHAR * Call, char Mode, char Direction);
+int standardParams(struct TNCINFO * TNC, char * buf);
+int SendPTCRadioCommand(struct TNCINFO * TNC, char * Block, int Length);
+
+#define	FEND	0xC0	// KISS CONTROL CODES 
+#define	FESC	0xDB
+#define	TFEND	0xDC
+#define	TFESC	0xDD
+
+static FILE * LogHandle[32] = {0};
+
+//char * Logs[4] = {"1", "2", "3", "4"};
+
+static char BaseDir[MAX_PATH]="c:\\";
+
+static BOOL WRITELOG = FALSE;
+
+BOOL SCSStopPort(struct PORTCONTROL * PORT)
+{
+	// Disable Port - close TCP Sockets or Serial Port
+
+	struct TNCINFO * TNC = PORT->TNC;
+
+	TNC->CONNECTED = FALSE;
+	TNC->Alerted = FALSE;
+
+	if (TNC->Streams[0].Attached)
+		TNC->Streams[0].ReportDISC = TRUE;
+
+	if (TNC->hDevice)
+	{
+		CloseCOMPort(TNC->hDevice);
+		TNC->hDevice = 0;
+	}
+
+	TNC->HostMode = FALSE;
+
+	sprintf(PORT->TNC->WEB_COMMSSTATE, "%s", "Port Stopped");
+	MySetWindowText(PORT->TNC->xIDC_COMMSSTATE, PORT->TNC->WEB_COMMSSTATE);
+
+	return TRUE;
+}
+
+BOOL SCSStartPort(struct PORTCONTROL * PORT)
+{
+	// Restart Port - Open Sockets or Serial Port
+
+	struct TNCINFO * TNC = PORT->TNC;
+
+	TNC->ReopenTimer = 999;				// Reopen immediately
+		
+	sprintf(PORT->TNC->WEB_COMMSSTATE, "%s", "Port Restarted");
+	MySetWindowText(PORT->TNC->xIDC_COMMSSTATE, PORT->TNC->WEB_COMMSSTATE);
+
+	return TRUE;
+}
+
+
+
+static VOID CloseLogFile(int Flags)
+{
+	if (WRITELOG)
+	{
+		fclose(LogHandle[Flags]);
+		LogHandle[Flags] = NULL;
+	}
+}
+
+static BOOL OpenLogFile(int Flags)
+{
+	if (WRITELOG)
+	{
+		UCHAR FN[MAX_PATH];
+
+		time_t T;
+		struct tm * tm;
+
+		T = time(NULL);
+		tm = gmtime(&T);	
+
+		sprintf(FN,"%s/logs/SCSLog_%02d%02d_%d.txt", LogDirectory, tm->tm_mon + 1, tm->tm_mday, Flags);
+
+		LogHandle[Flags] = fopen(FN, "ab");
+	
+		return (LogHandle[Flags] != NULL);
+	}
+	return 0;
+}
+
+static void WriteLogLine(int Flags, char * Msg, int MsgLen)
+{
+	if (WRITELOG)
+	{
+		if (LogHandle[Flags])
+		{
+			fwrite(Msg, 1, MsgLen, LogHandle[Flags]); 
+			fwrite("\r\n", 1, 2, LogHandle[Flags]); 
+		}
+	}
+}
+
+
+static int DontAddPDUPLEX = 0;
+
+
+static int ProcessLine(char * buf, int Port)
+{
+	UCHAR * ptr,* p_cmd;
+	char * p_ipad = 0;
+	char * p_port = 0;
+	unsigned short WINMORport = 0;
+	int BPQport;
+	int len=510;
+	struct TNCINFO * TNC;
+	char errbuf[256];
+
+	BPQport = Port;
+	
+	TNC = TNCInfo[BPQport] = malloc(sizeof(struct TNCINFO));
+	memset(TNC, 0, sizeof(struct TNCINFO));
+
+	TNC->InitScript = malloc(1000);
+	TNC->InitScript[0] = 0;
+	
+	goto ConfigLine;
+
+
+	// Read Initialisation lines
+
+	while(TRUE)
+	{
+		if (GetLine(buf) == 0)
+			return TRUE;
+ConfigLine:
+
+		strcpy(errbuf, buf);
+
+		if (memcmp(buf, "****", 4) == 0)
+			return TRUE;
+
+		ptr = strchr(buf, ';');
+		if (ptr)
+		{
+			*ptr++ = 13;
+			*ptr = 0;
+		}
+		
+		if (_memicmp(buf, "DEBUGLOG", 8) == 0)	// Write Debug Log
+			WRITELOG = atoi(&buf[9]);
+		else
+		if (_memicmp(buf, "APPL", 4) == 0)
+		{
+			p_cmd = strtok(&buf[5], " \t\n\r");
+
+			if (p_cmd && p_cmd[0] != ';' && p_cmd[0] != '#')
+				TNC->ApplCmd=_strdup(_strupr(p_cmd));
+		}
+		else			
+		if (_memicmp(buf, "PACKETCHANNELS", 14) == 0)	// Packet Channels
+			TNC->PacketChannels = atoi(&buf[14]);
+
+		else
+		if (_memicmp(buf, "SCANFORROBUSTPACKET", 19) == 0)
+		{
+			// Spend a percentage of scan time in Robust Packet Mode
+
+			double Robust = atof(&buf[20]);
+			#pragma warning(push)
+			#pragma warning(disable : 4244)
+			TNC->RobustTime = Robust * 10;
+			#pragma warning(pop)
+		}
+		else
+		if (_memicmp(buf, "USEAPPLCALLS", 12) == 0 && buf[12] != 'F' && buf[12] != 'f')
+			TNC->UseAPPLCalls = TRUE;
+		else
+		if (_memicmp(buf, "USEAPPLCALLSFORPACTOR", 21) == 0)
+			TNC->UseAPPLCallsforPactor = TRUE;
+		else
+		if (_memicmp(buf, "DRAGON", 6) == 0)
+		{
+			TNC->Dragon = TRUE;
+			if (_memicmp(&buf[7], "SINGLE", 6) == 0)
+				TNC->DragonSingle = TRUE;
+
+			if (_memicmp(&buf[7], "KISS", 4) == 0)
+				TNC->DragonKISS = TRUE;
+		}
+		else
+		if (_memicmp(buf, "DEFAULT ROBUST", 14) == 0)
+			TNC->RobustDefault = TRUE;
+		else
+		if (_memicmp(buf, "DontAddPDUPLEX", 14) == 0)
+			DontAddPDUPLEX = TRUE;
+		else
+		if (_memicmp(buf, "FORCE ROBUST", 12) == 0)
+			TNC->ForceRobust = TNC->RobustDefault = TRUE;
+		else
+		if (_memicmp(buf, "MAXLEVEL", 8) == 0)		// Maximum Pactor Level to use.
+			TNC->MaxLevel = atoi(&buf[8]);
+		else
+		if (_memicmp(buf, "DATE", 4) == 0)
+		{
+			char Cmd[32];
+			time_t T;
+			struct tm * tm;
+
+			T = time(NULL);
+			tm = gmtime(&T);	
+
+			sprintf(Cmd,"DATE %02d%02d%02d\r",  tm->tm_mday, tm->tm_mon + 1, tm->tm_year - 100);
+
+			strcat (TNC->InitScript, Cmd);
+		}
+		else if (_memicmp(buf, "TIME", 4) == 0)
+		{
+			char Cmd[32];
+			time_t T;
+			struct tm * tm;
+
+			T = time(NULL);
+			tm = gmtime(&T);	
+
+			sprintf(Cmd,"TIME %02d%02d%02d\r",  tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+			strcat (TNC->InitScript, Cmd);
+		}
+		else if (standardParams(TNC, buf) == FALSE)
+			strcat (TNC->InitScript, buf);
+	}
+	
+	return (TRUE);
+	
+}
+
+struct TNCINFO * CreateTTYInfo(int port, int speed);
+
+BOOL CloseConnection(struct TNCINFO * conn);
+BOOL WriteCommBlock(struct TNCINFO * TNC);
+BOOL DestroyTTYInfo(int port);
+void SCSCheckRX(struct TNCINFO * TNC);
+VOID SCSPoll(int Port);
+VOID CRCStuffAndSend(struct TNCINFO * TNC, UCHAR * Msg, int Len);
+unsigned short int compute_crc(unsigned char *buf,int len);
+int Unstuff(UCHAR * MsgIn, UCHAR * MsgOut, int len);
+VOID ProcessDEDFrame(struct TNCINFO * TNC, UCHAR * rxbuff, int len);
+VOID ProcessTermModeResponse(struct TNCINFO * TNC);
+static VOID ExitHost(struct TNCINFO * TNC);
+static VOID DoTNCReinit(struct TNCINFO * TNC);
+static VOID DoTermModeTimeout(struct TNCINFO * TNC);
+static VOID DoMonitor(struct TNCINFO * TNC, UCHAR * Msg, int Len);
+int Switchmode(struct TNCINFO * TNC, int Mode);
+VOID SwitchToPactor(struct TNCINFO * TNC);
+VOID SwitchToPacket(struct TNCINFO * TNC);
+
+
+char status[8][8] = {"ERROR",  "REQUEST", "TRAFFIC", "IDLE", "OVER", "PHASE", "SYNCH", ""};
+
+char ModeText[8][14] = {"STANDBY", "AMTOR-ARQ",  "PACTOR-ARQ", "AMTOR-FEC", "PACTOR-FEC", "RTTY / CW", "LISTEN", "Channel-Busy"};
+
+char PactorLevelText[5][14] = {"Not Connected", "PACTOR-I", "PACTOR-II", "PACTOR-III", "PACTOR-IV"};
+
+char PleveltoMode[5] = {30, 11, 14, 16, 20};	// WL2K Reporting Modes - RP, P1, P2, P3, P4
+
+
+static size_t ExtProc(int fn, int port, PDATAMESSAGE buff)
+{
+	int txlen = 0;
+	PMSGWITHLEN buffptr;
+	struct TNCINFO * TNC = TNCInfo[port];
+	size_t Param;
+	int Stream = 0;
+	struct STREAMINFO * STREAM = &TNC->Streams[0];
+	char PLevel;
+	struct ScanEntry * Scan;
+
+	if (TNC == NULL)
+		return 0;
+	
+	if (TNC->hDevice == 0)
+	{
+		// Clear anything from UI_Q
+
+		while (TNC->PortRecord->UI_Q)
+		{
+			buffptr = Q_REM(&TNC->PortRecord->UI_Q);
+			ReleaseBuffer(buffptr);
+		}
+
+		// Try to reopen every 30 secs
+
+		if (fn > 3  && fn < 7)
+			goto ok;
+
+		TNC->ReopenTimer++;
+
+		if (TNC->ReopenTimer < 300)
+			return 0;
+
+		TNC->ReopenTimer = 0;
+		
+		if (TNC->PortRecord->PORTCONTROL.PortStopped == 0)
+			OpenCOMMPort(TNC, TNC->PortRecord->PORTCONTROL.SerialPortName, TNC->PortRecord->PORTCONTROL.BAUDRATE, TRUE);
+		
+		if (TNC->hDevice == 0)
+			return 0;
+
+#ifndef WIN32
+#ifndef MACBPQ
+#ifndef FREEBSD
+
+		if (TNC->Dragon)
+		{
+			struct serial_struct sstruct;
+
+			// Need to set custom baud rate
+
+			if (ioctl(TNC->hDevice, TIOCGSERIAL, &sstruct) < 0)
+			{
+				Debugprintf("Error: Dragon could not get comm ioctl\n");
+			}
+			else
+			{
+				// set custom divisor to get 829440 baud
+	
+				sstruct.custom_divisor = 29;
+				sstruct.flags |= ASYNC_SPD_CUST;
+
+				// set serial_struct
+		
+				if (ioctl(TNC->hDevice, TIOCSSERIAL, &sstruct) < 0)
+					Debugprintf("Error: Dragon could not set custom comm baud divisor\n");
+				else
+					Debugprintf("Dragon custom baud rate set\n");
+			}
+		}
+#endif
+#endif
+#endif
+
+	}
+ok:
+	switch (fn)
+	{
+	case 7:			
+
+		// 100 mS Timer. May now be needed, as Poll can be called more frequently in some circumstances
+
+		// G7TAJ's code to record activity for stats display
+			
+		if ( TNC->BusyFlags && CDBusy )
+			TNC->PortRecord->PORTCONTROL.ACTIVE += 2;
+
+		if ( TNC->PTTState )
+			TNC->PortRecord->PORTCONTROL.SENDING += 2;
+
+		SCSCheckRX(TNC);
+		SCSPoll(port);
+
+		return 0;
+
+	case 1:				// poll
+
+		// Check session limit timer
+
+		if ((STREAM->Connecting || STREAM->Connected) && !STREAM->Disconnecting)
+		{
+			if (TNC->SessionTimeLimit && STREAM->ConnectTime && time(NULL) > (TNC->SessionTimeLimit + STREAM->ConnectTime))
+			{
+				STREAM->CmdSet = STREAM->CmdSave = malloc(100);
+				sprintf(STREAM->CmdSet, "D\r");	
+				STREAM->Disconnecting = TRUE;
+			}
+		}
+
+		for (Stream = 0; Stream <= MaxStreams; Stream++)
+		{
+			if (TNC->Streams[Stream].ReportDISC)
+			{
+				TNC->Streams[Stream].ReportDISC = FALSE;
+				buff->PORT = Stream;
+
+				return -1;
+			}
+		}
+	
+		if (TNC->EnterExit)
+			return 0;						// Switching to Term mode to change bandwidth
+		
+		for (Stream = 0; Stream <= MaxStreams; Stream++)
+		{
+			if (TNC->Streams[Stream].PACTORtoBPQ_Q !=0)
+			{
+				int datalen;
+			
+				buffptr = Q_REM(&TNC->Streams[Stream].PACTORtoBPQ_Q);
+				datalen = (int)buffptr->Len;
+
+				buff->PORT = Stream;						// Compatibility with Kam Driver
+				buff->PID = 0xf0;
+				memcpy(&buff->L2DATA, &buffptr->Data[0], datalen);		// Data goes to + 7, but we have an extra byte
+				datalen += sizeof(void *) + 4;
+
+				PutLengthinBuffer(buff, datalen);
+				
+				ReleaseBuffer(buffptr);
+	
+				return (1);
+			}
+		}
+	
+		return 0;
+
+	case 2:				// send
+
+		buffptr = GetBuff();
+
+		if (buffptr == 0) return 0;			// No buffers, so ignore
+
+		Stream = buff->PORT;
+
+		if (!TNC->TNCOK)
+		{
+			// Send Error Response
+
+			buffptr->Len = sprintf(buffptr->Data, "No Connection to PACTOR TNC\r");
+			C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr);
+			
+			return 0;
+		}
+
+		txlen = GetLengthfromBuffer(buff) - (MSGHDDRLEN + 1);		// 1 as no PID
+
+		if (txlen == 1 && buff->L2DATA[0] == 0)			// Keepalive Packet
+		{
+			ReleaseBuffer(buffptr);
+			return 0;
+		}
+
+		buffptr->Len = txlen;
+		memcpy(buffptr->Data, buff->L2DATA, txlen);
+		
+		C_Q_ADD(&TNC->Streams[Stream].BPQtoPACTOR_Q, buffptr);
+
+		TNC->Streams[Stream].FramesOutstanding++;
+		
+		// See if possible to send immediately
+
+		SCSTryToSendDATA(TNC, Stream);
+
+		return 0;
+
+	case 3:				// CHECK IF OK TO SEND. Also used to check if TNC is responding
+
+		Stream = (int)(size_t)buff;
+
+		STREAM = &TNC->Streams[Stream];
+
+		if (Stream == 0)
+		{
+			if (TNC->Dragon)
+			{
+				if (STREAM->FramesOutstanding  > 25)
+					return (1 | TNC->HostMode << 8 | STREAM->Disconnecting << 15);
+			}
+			else
+			{
+				if (STREAM->FramesOutstanding  > 10)
+					return (1 | TNC->HostMode << 8 | STREAM->Disconnecting << 15);
+			}
+		}
+		else
+		{
+			if (STREAM->FramesOutstanding > 3 || TNC->Buffers < 200)	
+				return (1 | TNC->HostMode << 8 | STREAM->Disconnecting << 15);		}
+
+		return TNC->HostMode << 8 | STREAM->Disconnecting << 15;		// OK, but lock attach if disconnecting
+
+
+	case 4:				// reinit
+
+		// Ensure in Pactor
+
+		TNC->TXBuffer[2] = 31;
+		TNC->TXBuffer[3] = 0x1;
+		TNC->TXBuffer[4] = 0x1;
+		memcpy(&TNC->TXBuffer[5], "PT", 2);
+
+		CRCStuffAndSend(TNC, TNC->TXBuffer, 7);
+
+		Sleep(25);
+		ExitHost(TNC);
+		Sleep(50);
+		CloseCOMPort(TNC->hDevice);
+		TNC->hDevice =(HANDLE)0;
+		TNC->ReopenTimer = 250;
+		TNC->HostMode = FALSE;
+
+		return (0);
+
+	case 5:				// Close
+
+		// Ensure in Pactor
+
+		TNC->TXBuffer[2] = 31;
+		TNC->TXBuffer[3] = 0x1;
+		TNC->TXBuffer[4] = 0x1;
+		memcpy(&TNC->TXBuffer[5], "PT", 2);
+
+		CRCStuffAndSend(TNC, TNC->TXBuffer, 7);
+
+		Sleep(25);
+
+		ExitHost(TNC);
+
+		Sleep(25);
+
+		CloseCOMPort(TNCInfo[port]->hDevice);
+				
+		return (0);
+
+	case 6:				// Scan Interface
+
+		Param = (size_t)buff;
+
+		switch (Param)
+		{
+		case 1:		// Request Permission
+
+			if (TNC->TNCOK)
+			{
+				// If been in Sync a long time, or if using applcalls and
+				// Scan had been locked too long just let it change
+				
+				if (TNC->UseAPPLCallsforPactor)
+				{
+					if (TNC->PTCStatus == 6)	// Sync
+					{
+						int insync = (int)(time(NULL) - TNC->TimeEnteredSYNCMode);
+						if (insync > 4)
+						{
+							Debugprintf("SCS Scan - in SYNC for %d Secs - allow change regardless", insync);
+							return 0;
+						}
+					}
+					else if (TNC->TimeScanLocked)
+					{
+						time_t timeLocked = time(NULL) - TNC->TimeScanLocked;
+						if (timeLocked > 4)
+						{
+							Debugprintf("SCS Scan - Scan Locked for %d Secs - allow change regardless", timeLocked);
+							TNC->TimeScanLocked = 0;
+							return 0;
+						}
+					}
+				}
+
+				TNC->WantToChangeFreq = TRUE;
+				TNC->OKToChangeFreq = FALSE;
+				return TRUE;
+			}
+			return 0;		// Don't lock scan if TNC isn't responding
+		
+
+		case 2:		// Check  Permission
+			return TNC->OKToChangeFreq;
+
+		case 3:		// Release  Permission
+		
+			TNC->WantToChangeFreq = FALSE;
+			
+			if (TNC->DontReleasePermission)			// Disable connects during this interval?
+			{
+				TNC->DontReleasePermission = FALSE;
+				if (TNC->SyncSupported == FALSE)
+					TNC->TimeScanLocked = time(NULL) + 100;	// Make sure doesnt time out
+				return 0;
+			}
+
+			TNC->DontWantToChangeFreq = TRUE;
+			return 0;
+
+		default: // Param is Address of a struct ScanEntry
+
+			Scan = (struct ScanEntry *)buff;
+
+			PLevel = Scan->PMaxLevel;
+
+			if (PLevel == 0 && (Scan->HFPacketMode || Scan->RPacketMode))
+			{
+				// Switch to Packet for this Interval
+				
+				if (TNC->RIG->RIG_DEBUG)
+					Debugprintf("SCS Switching to Packet, %d", TNC->HFPacket);
+
+				if (TNC->HFPacket == FALSE)
+					SwitchToPacket(TNC);
+
+				return 0;
+			}
+
+			if (PLevel > '0' && PLevel < '5')		// 1 - 4 
+			{
+				if (TNC->Bandwidth != PLevel  || TNC->MinLevel != (Scan->PMinLevel - '0'))
+				{
+					TNC->Bandwidth = PLevel;
+					TNC->MinLevel = Scan->PMinLevel - '0';
+					Switchmode(TNC, PLevel - '0');
+				}
+
+				if (TNC->UseAPPLCallsforPactor && Scan->APPLCALL[0])
+				{
+					// Switch callsign
+
+					STREAM = &TNC->Streams[0];
+					STREAM->CmdSet = STREAM->CmdSave = malloc(100);
+
+					strcpy(STREAM->MyCall, Scan->APPLCALL);
+
+					sprintf(STREAM->CmdSet, "I%s\rI\r", STREAM->MyCall);
+					if (TNC->RIG->RIG_DEBUG)
+						Debugprintf("SCS Pactor APPLCALL Set to  %s", STREAM->MyCall);
+				}
+
+				else
+				{
+					if (TNC->HFPacket)
+						SwitchToPactor(TNC);
+				}
+			}
+
+			if (Scan->RPacketMode)
+				if (TNC->RobustTime)
+					SwitchToPacket(TNC);			// Always start in packet, switch to pactor after RobustTime ticks
+			
+			if (PLevel == '0')
+				TNC->DontReleasePermission = TRUE;	// Dont allow connects in this interval
+			else
+				TNC->DontReleasePermission = FALSE;
+
+			return 0;
+		}
+	}
+	return 0;
+}
+
+int DoScanLine(struct TNCINFO * TNC, char * Buff, int Len)
+{
+	struct RIGINFO * RIG = TNC->RIG;
+
+	if (RIG && RIG->WEB_Label)
+	{
+		Len += sprintf(&Buff[Len], "");
+		Len += sprintf(&Buff[Len], "| %s", RIG->WEB_Label);
+		Len += sprintf(&Buff[Len], " | %s", RIG->WEB_FREQ);
+		Len += sprintf(&Buff[Len], " | %s", RIG->WEB_MODE);
+		Len += sprintf(&Buff[Len], " | %c", RIG->WEB_SCAN);
+		Len += sprintf(&Buff[Len], " | %c | 
", RIG->WEB_PTT);
+
+
+		if (TNC->TXRIG && TNC->TXRIG != TNC->RIG)
+		{
+			struct RIGINFO * RIG = TNC->TXRIG;
+
+			Len += sprintf(&Buff[Len], "%s", RIG->WEB_Label);
+			Len += sprintf(&Buff[Len], " | %s", RIG->WEB_FREQ);
+			Len += sprintf(&Buff[Len], " | %s", RIG->WEB_MODE);
+			Len += sprintf(&Buff[Len], " | %c", RIG->WEB_SCAN);
+			Len += sprintf(&Buff[Len], " | %c | 
", RIG->WEB_PTT);
+		}
+		Len += sprintf(&Buff[Len], "");
+	}
+	return Len;
+}
+
+static int WebProc(struct TNCINFO * TNC, char * Buff, BOOL LOCAL)
+{
+	int Len = sprintf(Buff, ""
+	"SCS Pactor StatusSCS Pactor Status
");
+
+	Len += sprintf(&Buff[Len], "");
+
+	Len += sprintf(&Buff[Len], "| Comms State | %s | 
", TNC->WEB_COMMSSTATE);
+	Len += sprintf(&Buff[Len], "| TNC State | %s | 
", TNC->WEB_TNCSTATE);
+	Len += sprintf(&Buff[Len], "| Mode | %s | 
", TNC->WEB_MODE);
+	Len += sprintf(&Buff[Len], "| Status | %s | 
", TNC->WEB_STATE);
+	Len += sprintf(&Buff[Len], "| TX/RX State | %s | 
", TNC->WEB_TXRX);
+	Len += sprintf(&Buff[Len], "| Buffers | %s | 
", TNC->WEB_BUFFERS);
+	Len += sprintf(&Buff[Len], "| Traffic | %s | 
", TNC->WEB_TRAFFIC);
+	Len += sprintf(&Buff[Len], "| Mode | %s | 
", TNC->WEB_PACTORLEVEL);
+	Len += sprintf(&Buff[Len], "
");
+
+	Len += sprintf(&Buff[Len], "", TNC->WebBuffer);
+	Len = DoScanLine(TNC, Buff, Len);
+
+	return Len;
+}
+
+void * SCSExtInit(EXTPORTDATA *  PortEntry)
+{
+	char msg[500];
+	struct TNCINFO * TNC;
+	int port;
+	char * ptr;
+	int Stream = 0;
+	char * TempScript;
+
+	//
+	//	Will be called once for each Pactor Port
+	//	The COM port number is in IOBASE
+	//
+
+	DontAddPDUPLEX = 0;
+
+	sprintf(msg,"SCS Pactor %s", PortEntry->PORTCONTROL.SerialPortName);
+	WritetoConsole(msg);
+
+	port=PortEntry->PORTCONTROL.PORTNUMBER;
+
+	ReadConfigFile(port, ProcessLine);
+
+	TNC = TNCInfo[port];
+
+	if (TNC == NULL)
+	{
+		// Not defined in Config file
+
+		sprintf(msg," ** Error - no info in BPQ32.cfg for this port\n");
+		WritetoConsole(msg);
+
+		return ExtProc;
+	}
+	
+	TNC->Port = port;
+	TNC->Hardware = H_SCS;
+
+	OpenLogFile(TNC->Port);
+	CloseLogFile(TNC->Port);
+
+
+	if (TNC->BusyHold == 0)
+		TNC->BusyHold = 3;
+
+	if (TNC->BusyWait == 0)
+		TNC->BusyWait = 10;
+
+	if (TNC->MaxLevel == 0)
+		TNC->MaxLevel = 3;
+
+	// Set up DED addresses for streams (first stream (Pactor) = DED 31
+	
+	TNC->Streams[0].DEDStream = 31;
+
+	for (Stream = 1; Stream <= MaxStreams; Stream++)
+	{
+		TNC->Streams[Stream].DEDStream = Stream;
+	}
+
+	if (TNC->PacketChannels > MaxStreams)
+		TNC->PacketChannels = MaxStreams;
+
+	PortEntry->MAXHOSTMODESESSIONS = TNC->PacketChannels + 1;
+	PortEntry->PERMITGATEWAY = TRUE;					// Can change ax.25 call on each stream
+	PortEntry->SCANCAPABILITIES = CONLOCK;				// Scan Control 3 stage/conlock 
+
+	TNC->PortRecord = PortEntry;
+
+	if (PortEntry->PORTCONTROL.PORTINTERLOCK && TNC->RXRadio == 0 && TNC->TXRadio == 0)
+		TNC->RXRadio = TNC->TXRadio = PortEntry->PORTCONTROL.PORTINTERLOCK;
+
+	if (PortEntry->PORTCONTROL.PORTCALL[0] == 0)
+		memcpy(TNC->NodeCall, MYNODECALL, 10);
+	else
+		ConvFromAX25(&PortEntry->PORTCONTROL.PORTCALL[0], TNC->NodeCall);
+		
+	PortEntry->PORTCONTROL.PROTOCOL = 10;
+	PortEntry->PORTCONTROL.PORTQUALITY = 0;
+
+	if (PortEntry->PORTCONTROL.PORTPACLEN == 0)
+		PortEntry->PORTCONTROL.PORTPACLEN = 100;
+
+	TNC->SuspendPortProc = PTCSuspendPort;
+	TNC->ReleasePortProc = PTCReleasePort;
+
+	PortEntry->PORTCONTROL.PORTSTARTCODE = SCSStartPort;
+	PortEntry->PORTCONTROL.PORTSTOPCODE = SCSStopPort;
+
+	PortEntry->PORTCONTROL.UICAPABLE = TRUE;
+
+	ptr=strchr(TNC->NodeCall, ' ');
+	if (ptr) *(ptr) = 0;					// Null Terminate
+
+	// get NODECALL for RP tests
+
+	memcpy(NodeCall, MYNODECALL, 10);
+		
+	ptr=strchr(NodeCall, ' ');
+	if (ptr) *(ptr) = 0;					// Null Terminate
+
+
+	// Set TONES to 4
+
+	TempScript = malloc(1000);
+
+	strcpy(TempScript, "QUIT\r");				// In case in pac: mode
+	strcat(TempScript, "TONES 4\r");			// Tones may be changed but I want this as standard
+	strcat(TempScript, "MAXERR 30\r");			// Max retries 
+	strcat(TempScript, "MODE 0\r");				// ASCII mode, no PTC II compression (Forwarding will use FBB Compression)
+	strcat(TempScript, "MAXSUM 20\r");			// Max count for memory ARQ
+	strcat(TempScript, "CWID 0 2\r");			// CW ID disabled
+	strcat(TempScript, "PTCC 0\r");				// Dragon out of PTC Compatibility Mode
+	strcat(TempScript, "VER\r");				// Try to determine Controller Type
+
+	sprintf(msg, "MYLEVEL %d\r", TNC->MaxLevel);
+	strcat(TempScript, msg);					// Default Level to MAXLEVEL
+
+	strcat(TempScript, TNC->InitScript);
+
+	free(TNC->InitScript);
+	TNC->InitScript = TempScript;
+
+	// Others go on end so they can't be overriden
+
+	strcat(TNC->InitScript, "ADDLF 0\r");      //      Auto Line Feed disabled
+	strcat(TNC->InitScript, "ARX 0\r");      //        Amtor Phasing disabled
+	strcat(TNC->InitScript, "BELL 0\r");      //       Disable Bell
+	strcat(TNC->InitScript, "BC 0\r");      //         FEC reception is disabled
+	strcat(TNC->InitScript, "BKCHR 2\r");      //      Breakin Char = 2
+	strcat(TNC->InitScript, "CHOBELL 0\r");      //    Changeover Bell off
+	strcat(TNC->InitScript, "CMSG 0\r");      //       Connect Message Off
+	strcat(TNC->InitScript, "LFIGNORE 0\r");      //   No insertion of Line feed
+	strcat(TNC->InitScript, "LISTEN 0\r");      //     Pactor Listen disabled
+	strcat(TNC->InitScript, "MAIL 0\r");      //       Disable internal mailbox reporting
+	strcat(TNC->InitScript, "REMOTE 0\r");      //     Disable remote control
+	strcat(TNC->InitScript, "PAC CBELL 0\r");      //  
+	strcat(TNC->InitScript, "PAC CMSG 0\r");      //  
+	strcat(TNC->InitScript, "PAC PRBOX 0\r");      //  	Turn off Packet Radio Mailbox
+	
+	//  Automatic Status must be enabled for BPQ32
+	//  Pactor must use Host Mode Chanel 31
+	//  PDuplex must be set. The Node code relies on automatic IRS/ISS changeover
+	//	5 second duplex timer
+
+	strcat(TNC->InitScript, "STATUS 2\rPTCHN 31\rPDTIMER 5\r");
+
+	if (DontAddPDUPLEX == 0)
+		strcat(TNC->InitScript, "PDUPLEX 1\r");
+
+	sprintf(msg, "MYCALL %s\rPAC MYCALL %s\r", TNC->NodeCall, TNC->NodeCall);
+	strcat(TNC->InitScript, msg);
+
+	PortEntry->PORTCONTROL.TNC = TNC;
+
+	TNC->WebWindowProc = WebProc;
+	TNC->WebWinX = 510;
+	TNC->WebWinY = 280;
+
+	TNC->WEB_COMMSSTATE = zalloc(100);
+	TNC->WEB_TNCSTATE = zalloc(100);
+	strcpy(TNC->WEB_TNCSTATE, "Free");
+	TNC->WEB_MODE = zalloc(100);
+	TNC->WEB_TRAFFIC = zalloc(100);
+	TNC->WEB_BUFFERS = zalloc(100);
+	TNC->WEB_STATE = zalloc(100);
+	TNC->WEB_TXRX = zalloc(100);
+	TNC->WEB_PACTORLEVEL = zalloc(100);
+	TNC->WebBuffer = zalloc(5000);
+
+
+#ifndef LINBPQ
+
+	CreatePactorWindow(TNC, ClassName, WindowTitle, RigControlRow, PacWndProc, 500, 500, ForcedClose);
+ 
+	CreateWindowEx(0, "STATIC", "Comms State", WS_CHILD | WS_VISIBLE, 10,6,120,20, TNC->hDlg, NULL, hInstance, NULL);
+	TNC->xIDC_COMMSSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,6,386,20, TNC->hDlg, NULL, hInstance, NULL);
+	
+	CreateWindowEx(0, "STATIC", "TNC State", WS_CHILD | WS_VISIBLE, 10,28,106,20, TNC->hDlg, NULL, hInstance, NULL);
+	TNC->xIDC_TNCSTATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,28,520,20, TNC->hDlg, NULL, hInstance, NULL);
+
+	CreateWindowEx(0, "STATIC", "Mode", WS_CHILD | WS_VISIBLE, 10,50,80,20, TNC->hDlg, NULL, hInstance, NULL);
+	TNC->xIDC_MODE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,50,200,20, TNC->hDlg, NULL, hInstance, NULL);
+ 
+	CreateWindowEx(0, "STATIC", "Status", WS_CHILD | WS_VISIBLE, 10,72,110,20, TNC->hDlg, NULL, hInstance, NULL);
+	TNC->xIDC_STATE = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 116,72,144,20, TNC->hDlg, NULL, hInstance, NULL);
+
+ 	CreateWindowEx(0, "STATIC", "TX/RX State", WS_CHILD | WS_VISIBLE,10,94,80,20, TNC->hDlg, NULL, hInstance, NULL);
+	TNC->xIDC_TXRX = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE,116,94,374,20 , TNC->hDlg, NULL, hInstance, NULL);
+ 
+	CreateWindowEx(0, "STATIC", "Buffers", WS_CHILD | WS_VISIBLE,10,116,80,20, TNC->hDlg, NULL, hInstance, NULL);
+	TNC->xIDC_BUFFERS = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE,116,116,374,20 , TNC->hDlg, NULL, hInstance, NULL);
+	
+	CreateWindowEx(0, "STATIC", "Traffic", WS_CHILD | WS_VISIBLE,10,138,80,20, TNC->hDlg, NULL, hInstance, NULL);
+	TNC->xIDC_TRAFFIC = CreateWindowEx(0, "STATIC", "RX 0 TX 0 ACKED 0", WS_CHILD | WS_VISIBLE,116,138,374,20 , TNC->hDlg, NULL, hInstance, NULL);
+
+	TNC->xIDC_PACTORLEVEL = CreateWindowEx(0, "STATIC", "Mode", WS_CHILD | WS_VISIBLE,10,160,430,20, TNC->hDlg, NULL, hInstance, NULL);
+
+	TNC->hMonitor= CreateWindowEx(0, "LISTBOX", "", WS_CHILD |  WS_VISIBLE  | LBS_NOINTEGRALHEIGHT | 
+            LBS_DISABLENOSCROLL | WS_HSCROLL | WS_VSCROLL,
+			0,RigControlRow + 44,250,300, TNC->hDlg, NULL, hInstance, NULL);
+
+	TNC->ClientHeight = 500;
+	TNC->ClientWidth = 500;
+
+	sprintf(TNC->WEB_BUFFERS, "%05d Queued %05d", TNC->Buffers, TNC->Streams[0].FramesOutstanding);
+	SetWindowText(TNC->xIDC_BUFFERS, TNC->WEB_BUFFERS);
+
+
+	MoveWindows(TNC);
+#endif
+	OpenCOMMPort(TNC, PortEntry->PORTCONTROL.SerialPortName, PortEntry->PORTCONTROL.BAUDRATE, FALSE);
+
+#ifndef WIN32
+#ifndef MACBPQ
+#ifndef FREEBSD
+
+	if (TNC->Dragon)
+	{
+		struct serial_struct sstruct;
+
+		// Need to set custom baud rate
+
+		if (ioctl(TNC->hDevice, TIOCGSERIAL, &sstruct) < 0)
+		{
+			printf("Error: Dragon could not get comm ioctl\n");
+		}
+		else
+		{
+			// set custom divisor to get 829440 baud
+	
+			sstruct.custom_divisor = 29;
+			sstruct.flags |= ASYNC_SPD_CUST;
+
+			// set serial_struct
+		
+			if (ioctl(TNC->hDevice, TIOCSSERIAL, &sstruct) < 0)
+				Debugprintf("Error: Dragon could not set custom comm baud divisor\n");
+			else
+				Debugprintf("Dragon custom baud rate set\n");
+		}
+	}
+#endif
+#endif
+#endif
+	if (TNC->RobustDefault)
+		SwitchToPacket(TNC);
+
+	WritetoConsole("\n");
+
+	return ExtProc;
+}
+
+void SCSCheckRX(struct TNCINFO * TNC)
+{
+	int Length, Len;
+	unsigned short crc;
+	char UnstuffBuffer[500];
+
+	if (TNC->RXLen == 500)
+		TNC->RXLen = 0;
+
+	Len = ReadCOMBlock(TNC->hDevice, &TNC->RXBuffer[TNC->RXLen], 500 - TNC->RXLen);
+
+	if (Len == 0)
+		return;
+	
+	TNC->RXLen += Len;
+
+	Length = TNC->RXLen;
+
+	// DED mode doesn't have an end of frame delimiter. We need to know if we have a full frame
+
+	// Fortunately this is a polled protocol, so we only get one frame at a time
+
+	// If first char != 170, then probably a Terminal Mode Frame. Wait for CR on end
+
+	// If first char is 170, we could check rhe length field, but that could be corrupt, as
+	// we haen't checked CRC. All I can think of is to check the CRC and if it is ok, assume frame is
+	// complete. If CRC is duff, we will eventually time out and get a retry. The retry code
+	// can clear the RC buffer
+
+	if (TNC->UsingTermMode)
+	{
+		// Send response to Host if connected
+
+		PMSGWITHLEN buffptr;
+		int Len = TNC->RXLen;
+		int Posn = 0;
+
+		// First message is probably ACK of JHO4T -  AA AA 1F 00 1E 19
+
+		if (TNC->RXBuffer[0] == 0xaa && Len > 6)
+		{
+			memmove(TNC->RXBuffer, &TNC->RXBuffer[6], Len - 6);
+			Len -= 6;
+		}
+
+		// TNC seems to send 1e f7 or 1e 87 regularly
+
+		while (TNC->RXBuffer[0] == 0x1e && Len > 1)
+		{
+			memmove(TNC->RXBuffer, &TNC->RXBuffer[2], Len - 2);
+			Len -= 2;
+		}
+
+		if (Len == 0)
+		{
+			TNC->RXLen = 0;		// Ready for next frame
+			return;
+		}
+
+		while (Len > 250)
+		{
+			buffptr = GetBuff();
+			buffptr->Len = 250;
+			memcpy(buffptr->Data, &TNC->RXBuffer[Posn], 250);
+			C_Q_ADD(&TNC->Streams[0].PACTORtoBPQ_Q, buffptr);
+			Len -= 250;
+			Posn += 250;
+		}
+
+		buffptr = GetBuff();
+		buffptr->Len = Len;
+		memcpy(buffptr->Data, &TNC->RXBuffer[Posn], Len);
+		C_Q_ADD(&TNC->Streams[0].PACTORtoBPQ_Q, buffptr);
+
+		TNC->RXLen = 0;		// Ready for next frame
+		return;
+	}
+
+			
+	if (TNC->RXBuffer[0] != 170)
+	{
+		// Char Mode Frame I think we need to see cmd: on end
+
+		// If we think we are in host mode, then to could be noise - just discard.
+
+		if (TNC->HostMode)
+		{
+			TNC->RXLen = 0;		// Ready for next frame
+			return;
+		}
+
+		TNC->RXBuffer[TNC->RXLen] = 0;
+
+//		if (TNC->Streams[Stream].RXBuffer[TNC->Streams[Stream].RXLen-2] != ':')
+
+		if (strlen(TNC->RXBuffer) < TNC->RXLen)
+			TNC->RXLen = 0;
+
+		if ((strstr(TNC->RXBuffer, "cmd: ") == 0) && (strstr(TNC->RXBuffer, "pac: ") == 0))
+
+			return;				// Wait for rest of frame
+
+		// Complete Char Mode Frame
+
+		OpenLogFile(TNC->Port);
+		WriteLogLine(TNC->Port, TNC->RXBuffer, (int)strlen(TNC->RXBuffer));
+		CloseLogFile(TNC->Port);
+
+		TNC->RXLen = 0;		// Ready for next frame
+					
+		if (TNC->HostMode == 0)
+		{
+			// We think TNC is in Terminal Mode
+			ProcessTermModeResponse(TNC);
+			return;
+		}
+		// We thought it was in Host Mode, but are wrong.
+
+		TNC->HostMode = FALSE;
+		return;
+	}
+
+	// Receiving a Host Mode frame
+
+	if (Length < 6)				// Minimum Frame Sise
+		return;
+
+	if (TNC->RXBuffer[2] == 170)
+	{
+		// Retransmit Request
+	
+		TNC->RXLen = 0;
+		return;				// Ignore for now
+	}
+
+	// Can't unstuff into same buffer - fails if partial msg received, and we unstuff twice
+
+
+	Length = Unstuff(&TNC->RXBuffer[2], &UnstuffBuffer[2], Length - 2);
+
+	if (Length == -1)
+	{
+		// Unstuff returned an errors (170 not followed by 0)
+
+		TNC->RXLen = 0;
+		return;				// Ignore for now
+	}
+	crc = compute_crc(&UnstuffBuffer[2], Length);
+
+	if (crc == 0xf0b8)		// Good CRC
+	{
+		TNC->RXLen = 0;		// Ready for next frame
+		ProcessDEDFrame(TNC, UnstuffBuffer, Length);
+
+		// If there are more channels to poll (more than 1 entry in general poll response,
+		// and link is not active, poll the next one
+
+		if (TNC->Timeout == 0)
+		{
+			UCHAR * Poll = TNC->TXBuffer;
+
+			if (TNC->NexttoPoll[0])
+			{
+				UCHAR Chan = TNC->NexttoPoll[0] - 1;
+
+				memmove(&TNC->NexttoPoll[0], &TNC->NexttoPoll[1], 19);
+
+				Poll[2] = Chan;			// Channel
+				Poll[3] = 0x1;			// Command
+
+				if (Chan == 254)		// Status - Send Extended Status (G3)
+				{
+					Poll[4] = 1;			// Len-1
+					Poll[5] = 'G';			// Extended Status Poll
+					Poll[6] = '3';
+				}
+				else
+				{
+					Poll[4] = 0;			// Len-1
+					Poll[5] = 'G';			// Poll
+				}
+
+				CRCStuffAndSend(TNC, Poll, Poll[4] + 6);
+				TNC->InternalCmd = FALSE;
+
+				return;
+			}
+			else
+			{
+				// if last message wasn't a general poll, send one now
+
+				if (TNC->PollSent)
+					return;
+
+				TNC->PollSent = TRUE;
+
+				// Use General Poll (255)
+
+				Poll[2] = 255 ;			// Channel
+				Poll[3] = 0x1;			// Command
+
+				Poll[4] = 0;			// Len-1
+				Poll[5] = 'G';			// Poll
+
+				CRCStuffAndSend(TNC, Poll, 6);
+				TNC->InternalCmd = FALSE;
+			}
+		}
+		return;
+	}
+
+	// Bad CRC - assume incomplete frame, and wait for rest. If it was a full bad frame, timeout and retry will recover link.
+
+	return;
+}
+
+BOOL WriteCommBlock(struct TNCINFO * TNC)
+{
+	BOOL ret = WriteCOMBlock(TNC, TNC->TXBuffer, TNC->TXLen);
+
+	TNC->Timeout = 20;				// 2 secs
+	return ret;
+}
+
+VOID SCSPoll(int Port)
+{
+	struct TNCINFO * TNC = TNCInfo[Port];
+	UCHAR * Poll = TNC->TXBuffer;
+	char Status[80];
+	int Stream = 0;
+	int nn;
+	struct STREAMINFO * STREAM;
+
+	if (TNC->UsingTermMode)
+	{
+		if (TNC->Streams[Stream].BPQtoPACTOR_Q)
+		{
+			PMSGWITHLEN buffptr = Q_REM(&TNC->Streams[Stream].BPQtoPACTOR_Q);
+
+			// See if enter host mode command
+
+			if (_memicmp(buffptr->Data, "ENTERHOST\r", buffptr->Len) == 0)
+			{
+				TNC->UsingTermMode = FALSE;	
+				
+				memcpy(Poll, "JHOST4\r", 7);
+				TNC->TXLen = 7;
+				WriteCommBlock(TNC);
+
+				// No response expected
+
+				Sleep(10);
+
+				Poll[2] = 255;			// Channel
+				TNC->Toggle = 0;
+				Poll[3] = 0x41;
+				Poll[4] = 0;			// Len-1
+				Poll[5] = 'G';			// Poll
+
+				CRCStuffAndSend(TNC, Poll, 6);
+				TNC->InternalCmd = FALSE;
+				TNC->Timeout = 5;		// 1/2 sec - In case missed
+
+
+			}
+			else
+			{
+				// Send to TNC
+
+				memcpy(&Poll[0], buffptr->Data, buffptr->Len);
+				TNC->TXLen = buffptr->Len;;
+				WriteCommBlock(TNC);
+			}
+			ReleaseBuffer(buffptr);
+		}
+		return;
+	}
+
+	if (TNC->MinLevelTimer)
+	{
+		TNC->MinLevelTimer--;
+
+		if (TNC->MinLevelTimer == 0)
+		{
+			// Failed to reach min level in 15 secs
+
+			STREAM = &TNC->Streams[0];
+
+			if (STREAM->Connected)
+			{
+				PMSGWITHLEN buffptr;
+
+				Debugprintf("Required Min Level not reached - disconnecting");
+
+				// Discard Queued Data, Send a Message, then a disconnect
+
+				while (STREAM->BPQtoPACTOR_Q)
+					ReleaseBuffer(Q_REM(&STREAM->BPQtoPACTOR_Q));
+
+				STREAM->NeedDisc = 15;				// 1 secs
+
+				buffptr = GetBuff();
+				if (buffptr == 0) return;			// No buffers, so ignore
+
+				buffptr->Len = sprintf(buffptr->Data,
+					"This port only allows Pactor Level %d or above - Disconnecting\r\n", TNC->MinLevel);
+
+				C_Q_ADD(&STREAM->BPQtoPACTOR_Q, buffptr);
+			}
+		}
+	}
+
+	if (TNC->SwitchToPactor)
+	{
+		TNC->SwitchToPactor--;
+
+		if (TNC->SwitchToPactor == 0)
+			SwitchToPactor(TNC);
+	}
+
+	for (Stream = 0; Stream <= MaxStreams; Stream++)
+	{
+		if (TNC->PortRecord->ATTACHEDSESSIONS[Stream] && TNC->Streams[Stream].Attached == 0)
+		{
+			// New Attach
+
+			// If Pactor, stop scanning and take out of listen mode.
+
+			// Set call to connecting user's call
+
+			// If Stream 0 Put in Pactor Mode so Busy Detect will work
+
+			int calllen=0;
+
+			STREAM = &TNC->Streams[Stream];
+			Debugprintf("SCS New Attach Stream %d DEDStream %d", Stream, STREAM->DEDStream);
+
+			if (Stream == 0)
+				STREAM->DEDStream = 31;	// Pactor
+
+			STREAM->Attached = TRUE;
+
+			calllen = ConvFromAX25(TNC->PortRecord->ATTACHEDSESSIONS[Stream]->L4USER, STREAM->MyCall);
+
+			STREAM->MyCall[calllen] = 0;
+
+			STREAM->CmdSet = STREAM->CmdSave = malloc(100);
+
+			if (Stream == 0)
+			{
+				// Release Scan Lock if it is held
+
+				TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit;		// Reset Limit
+
+				if (TNC->DontReleasePermission)
+				{
+					TNC->DontReleasePermission = FALSE;
+					TNC->DontWantToChangeFreq = TRUE;
+				}
+
+				sprintf(STREAM->CmdSet, "I%s\r", "SCSPTC");
+
+				Debugprintf("SCS Pactor CMDSet = %s", STREAM->CmdSet);
+
+				SuspendOtherPorts(TNC);			// Prevent connects on other ports in same scan gruop
+
+				sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall);
+				SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
+
+				// Stop Scanner
+
+				sprintf(Status, "%d SCANSTOP", TNC->Port);
+				TNC->SwitchToPactor = 0;						// Cancel any RP to Pactor switch
+
+				Rig_Command((TRANSPORTENTRY *) -1, Status);
+			}
+			else
+			{
+				sprintf(STREAM->CmdSet, "I%s\r", STREAM->MyCall);
+				Debugprintf("SCS Pactor Attach CMDSet = %s", STREAM->CmdSet);
+			}
+		}
+	}
+
+	if (TNC->Timeout)
+	{
+		TNC->Timeout--;
+
+		if (TNC->Timeout)			// Still waiting
+			return;
+
+		TNC->Retries--;
+
+		if(TNC->Retries)
+		{
+			WriteCommBlock(TNC);	// Retransmit Block
+			return;
+		}
+
+		// Retried out.
+
+		if (TNC->HostMode == 0)
+		{
+			DoTermModeTimeout(TNC);
+			return;
+		}
+
+		// Retried out in host mode - Clear any connection and reinit the TNC
+
+		Debugprintf("PACTOR - Link to TNC Lost");
+		TNC->TNCOK = FALSE;
+
+		sprintf(TNC->WEB_COMMSSTATE,"%s Open but TNC not responding", TNC->PortRecord->PORTCONTROL.SerialPortName);
+		SetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE);
+
+		// Clear anything from UI_Q
+
+		while (TNC->PortRecord->UI_Q)
+		{
+			UINT * buffptr = Q_REM(&TNC->PortRecord->UI_Q);
+			ReleaseBuffer(buffptr);
+		}
+
+
+		TNC->HostMode = 0;
+		TNC->ReinitState = 0;
+
+		for (Stream = 0; Stream <= MaxStreams; Stream++)
+		{
+			if (TNC->PortRecord->ATTACHEDSESSIONS[Stream])		// Connected
+			{
+				TNC->Streams[Stream].Connected = FALSE;		// Back to Command Mode
+				TNC->Streams[Stream].ReportDISC = TRUE;		// Tell Node
+			}
+		}
+	}
+
+	// We delay clearing busy for BusyHold secs
+
+	if (TNC->Busy)
+		if (TNC->Mode != 7)
+			TNC->Busy--;
+
+	if (TNC->BusyDelay)		// Waiting to send connect
+	{
+		// Still Busy?
+
+		if (InterlockedCheckBusy(TNC) == 0)
+		{
+			// No, so send
+
+			TNC->Streams[0].CmdSet = TNC->ConnectCmd;
+			TNC->Streams[0].Connecting = TRUE;
+			TNC->Streams[0].ConnectTime = time(NULL);
+
+			sprintf(TNC->WEB_TNCSTATE, "%s Connecting to %s", TNC->Streams[0].MyCall, TNC->Streams[0].RemoteCall);
+			SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
+
+			Debugprintf("SCS Pactor CMDSet = %s", TNC->Streams[0].CmdSet);
+
+			TNC->BusyDelay = 0;
+			return;
+		}
+		else
+		{
+			// Wait Longer
+
+			TNC->BusyDelay--;
+
+			if (TNC->BusyDelay == 0)
+			{
+				// Timed out - Send Error Response
+
+				PMSGWITHLEN buffptr = GetBuff();
+
+				if (buffptr == 0) return;			// No buffers, so ignore
+
+				buffptr->Len = 39;
+				memcpy(buffptr->Data,"Sorry, Can't Connect - Channel is busy\r", 39);
+
+				C_Q_ADD(&TNC->Streams[0].PACTORtoBPQ_Q, buffptr);
+
+				free(TNC->ConnectCmd);
+
+			}
+		}
+	}
+
+	for (Stream = 0; Stream <= MaxStreams; Stream++)
+	{
+		STREAM = &TNC->Streams[Stream];
+
+		if (STREAM->Attached)
+			CheckForDetach(TNC, Stream, STREAM, TidyClose, ForcedClose, CloseComplete);
+
+		if (STREAM->NeedDisc)
+		{
+			STREAM->NeedDisc--;
+
+			if (STREAM->NeedDisc == 0)
+				STREAM->ReportDISC = TRUE;
+
+		}
+
+		if (TNC->Timeout)
+			return;				// We've sent something
+	}
+
+	// if we have just restarted or TNC appears to be in terminal mode, run Initialisation Sequence
+
+	if (!TNC->HostMode)
+	{
+		DoTNCReinit(TNC);
+		return;
+	}
+
+	TNC->PollSent = FALSE;
+
+	//If sending internal command list, send next element
+
+	for (Stream = 0; Stream <= MaxStreams; Stream++)
+	{
+		if (TNC->Streams[Stream].CmdSet)
+		{
+			unsigned char * start, * end;
+			int len;
+
+			start = TNC->Streams[Stream].CmdSet;
+
+			if (*(start) == 250)			// 2nd part of long KISS packet
+			{
+				len = start[1];
+
+				Poll[2] = 250;				// KISS Channel
+				Poll[3] = 0;				// Data
+				Poll[4] = len - 1;
+				memcpy(&Poll[5], &start[2], len);
+
+				CRCStuffAndSend(TNC, Poll, len + 5);
+
+				free(TNC->Streams[Stream].CmdSave);
+				TNC->Streams[Stream].CmdSet = NULL;
+				return;
+			}
+
+			if (*(start) == 0)			// End of Script
+			{
+				free(TNC->Streams[Stream].CmdSave);
+				TNC->Streams[Stream].CmdSet = NULL;
+			}
+			else
+			{
+				end = strchr(start, 13);
+				len = (int)(++end - start - 1);	// exclude cr
+				TNC->Streams[Stream].CmdSet = end;
+
+				if (*(start) == 1)
+				{
+					// This is UI data, not a command. Send it to channel 0
+
+					len --;
+
+					Poll[2] = 0;				// UI Channel
+					Poll[3] = 0;				// Data
+					Poll[4] = len - 1;
+					memcpy(&Poll[5], &start[1], len);
+
+					CRCStuffAndSend(TNC, Poll, len + 5);
+
+					return;
+				}
+
+				if (*(start) == 2)
+				{
+					// This is a UI command Send it to channel 0
+
+					len--;
+
+					Poll[2] = 0;				// UI Channel
+					Poll[3] = 1;				// Command
+					Poll[4] = len - 1;
+					memcpy(&Poll[5], &start[1], len);
+
+					CRCStuffAndSend(TNC, Poll, len + 5);
+
+					return;
+				}
+
+				Poll[2] = TNC->Streams[Stream].DEDStream;		// Channel
+				Poll[3] = 1;			// Command
+				Poll[4] = len - 1;
+				memcpy(&Poll[5], start, len);
+
+
+				OpenLogFile(TNC->Port);
+				WriteLogLine(TNC->Port, &Poll[5], len);
+				CloseLogFile(TNC->Port);
+
+				CRCStuffAndSend(TNC, Poll, len + 5);
+
+				return;
+			}
+		}
+	}
+	// if Freq Change needed, check if ok to do it.
+
+	if (TNC->TNCOK)
+	{
+		if (TNC->WantToChangeFreq)
+		{
+			Poll[2] = 31;			// Command
+			Poll[3] = 1;			// Command
+			Poll[4] = 2;			// Len -1
+			Poll[5] = '%';
+			Poll[6] = 'W';
+			Poll[7] = '0';
+
+			CRCStuffAndSend(TNC, Poll, 8);
+
+			TNC->InternalCmd = TRUE;
+			TNC->WantToChangeFreq = FALSE;
+
+			if (TNC->RIG->RIG_DEBUG)
+				Debugprintf("Scan Debug SCS Pactor Requesting permission from TNC");
+
+			return;
+		}
+
+		if (TNC->DontWantToChangeFreq)
+		{
+			Poll[2] = 31;			// Command
+			Poll[3] = 1;			// Command
+			Poll[4] = 2;			// Len -1
+			Poll[5] = '%';
+			Poll[6] = 'W';
+			Poll[7] = '1';
+
+			CRCStuffAndSend(TNC, Poll, 8);
+
+			TNC->InternalCmd = TRUE;
+			TNC->DontWantToChangeFreq = FALSE;
+			TNC->OKToChangeFreq = FALSE;
+
+			if (TNC->RIG->RIG_DEBUG)
+				Debugprintf("Scan Debug SCS Pactor Release Scan Lock sent to TNC");
+
+			return;
+		}
+	}
+
+	// Send Radio Command if avail
+
+	if (TNC->TNCOK && TNC->BPQtoRadio_Q)
+	{
+		int datalen;
+		PMSGWITHLEN buffptr;
+
+		buffptr = Q_REM(&TNC->BPQtoRadio_Q);
+
+		datalen = (int)buffptr->Len;
+
+		Poll[2] = 253;		// Radio Channel
+		Poll[3] = 0;		// Data?
+		Poll[4] = datalen - 1;
+
+		memcpy(&Poll[5], buffptr->Data, datalen);
+
+		ReleaseBuffer(buffptr);
+
+		CRCStuffAndSend(TNC, Poll, datalen + 5);
+
+		if (TNC->RIG->RIG_DEBUG)
+		{
+			Debugprintf("SCS Rig Command Queued, Len = %d", datalen );
+			Debugprintf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
+				Poll[5], Poll[6], Poll[7], Poll[8], Poll[9], Poll[10], Poll[11], Poll[12],
+				Poll[13], Poll[14], Poll[15], Poll[16], Poll[17], Poll[18], Poll[19], Poll[20]);
+		}
+
+		//		Debugprintf("SCS Sending Rig Command");
+
+		return;
+	}
+
+	if (TNC->TNCOK && TNC->PortRecord->UI_Q)
+	{
+		int datalen;
+		char * Buffer;
+		char ICall[16];
+		char CCMD[80] = "C";
+		char Call[12] = "           ";	
+		struct _MESSAGE * buffptr;
+
+		buffptr = Q_REM(&TNC->PortRecord->UI_Q);
+
+		datalen = buffptr->LENGTH - MSGHDDRLEN;
+		Buffer = &buffptr->DEST[0];		// Raw Frame
+
+		Buffer[datalen] = 0;
+
+		// If a Dragon with KISS over Hostmade we can just send it
+
+		if (TNC->DragonKISS)
+		{
+			int EncLen;
+
+			Poll[2] = 250;				// KISS Channel
+			Poll[3] = 0;				// CMD
+			Poll[4] = datalen + 2;		// 3 extrac chars, but need Len - 1
+
+			Buffer--;
+			*(Buffer) = 0;			// KISS Control on front
+			EncLen = KissEncode(Buffer, &Poll[5], datalen + 1);
+
+			// We can only send 256 bytes in HostMode, so if longer will
+			// have to fragemt
+
+			if (EncLen > 256)
+			{
+				//We have to wait for response before sending rest, so use CmdSet
+
+				// We need to save the extra first, as CRC will overwrite the first two bytes
+
+				UCHAR * ptr = TNC->Streams[0].CmdSet = TNC->Streams[0].CmdSave = zalloc(400);
+
+				(*ptr++) = 250;			// KISS Channel
+				(*ptr++) = EncLen - 256;
+				memcpy(ptr, &Poll[5 + 256], EncLen - 256);
+
+				// Send first 256
+
+				Poll[4] = 255;			//need Len - 1
+				CRCStuffAndSend(TNC, Poll, 261);	
+			}
+			else
+			{
+				Poll[4] = EncLen - 1;	//need Len - 1
+				CRCStuffAndSend(TNC, Poll, EncLen + 5);	
+			}
+
+			ReleaseBuffer((UINT *)buffptr);
+			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
+
+		// But we cant set digipeated bit in call, so if we find one, skip message
+
+		// This doesn't seem to work
+
+
+		ConvFromAX25(Buffer + 7, ICall);		// Origin
+		strlop(ICall, ' ');
+
+		ConvFromAX25(Buffer, &Call[1]);			// Dest
+		strlop(&Call[1], ' ');
+		strcat(CCMD, Call);
+		Buffer += 14;							// Skip Origin
+		datalen -= 7;
+
+		while ((Buffer[-1] & 1) == 0)
+		{
+			if (Buffer[6] & 0x80)				// Digied bit set?
+			{
+				ReleaseBuffer((UINT *)buffptr);
+				return;
+			}
+
+			ConvFromAX25(Buffer, &Call[1]);
+			strlop(&Call[1], ' ');
+			strcat(CCMD, Call);
+			Buffer += 7;	// End of addr
+			datalen -= 7;
+		}
+
+		if (Buffer[0] == 3)				// UI
+		{
+			Buffer += 2;
+			datalen -= 2;
+
+			Poll[2] = 0;				// UI Channel
+			Poll[3] = 1;				// CMD
+			Poll[4] = (int)strlen(CCMD) - 1;
+			strcpy(&Poll[5], CCMD);
+			CRCStuffAndSend(TNC, Poll, Poll[4] + 6);	// Set Dest and Path
+
+			TNC->Streams[0].CmdSet = TNC->Streams[0].CmdSave = zalloc(400);
+			sprintf(TNC->Streams[0].CmdSet, "%cI%s\r%c%s\r%cI%s\r",
+				2, ICall,			// Flag as Chan 0 Command
+				1, Buffer,			// Flag CmdSet as Data
+				2, TNC->NodeCall);	// Flag as Chan 0 Command
+		}
+
+		ReleaseBuffer((UINT *)buffptr);
+		return;
+	}
+
+
+	// Check status Periodically
+
+	if (TNC->TNCOK)
+	{
+		if (TNC->IntCmdDelay == 6)
+		{
+			Poll[2] = 254;			// Channel
+			Poll[3] = 0x1;			// Command
+			Poll[4] = 1;			// Len-1
+			Poll[5] = 'G';			// Extended Status Poll
+			Poll[6] = '3';
+
+			CRCStuffAndSend(TNC, Poll, 7);
+
+			TNC->InternalCmd = TRUE;
+			TNC->IntCmdDelay--;
+
+			return;
+		}
+
+		if (TNC->IntCmdDelay == 4)
+		{
+			Poll[2] = 31;			 // Channel
+			Poll[3] = 0x1;			// Command
+			Poll[4] = 1;			// Len-1
+			Poll[5] = '%';			// Bytes acked Status
+			Poll[6] = 'T';
+
+			CRCStuffAndSend(TNC, Poll, 7);
+
+			TNC->InternalCmd = TRUE;
+			TNC->IntCmdDelay--;
+
+			return;
+		}
+
+		if (TNC->IntCmdDelay <=0)
+		{
+			Poll[2] = 31;			// Channel
+			Poll[3] = 0x1;			// Command
+			Poll[4] = 1;			// Len-1
+			Poll[5] = '@';			// Buffer Status
+			Poll[6] = 'B';
+
+			CRCStuffAndSend(TNC, Poll, 7);
+
+			TNC->InternalCmd = TRUE;
+			TNC->IntCmdDelay = 20;	// Every 2 secs
+
+			return;
+		}
+		else
+			TNC->IntCmdDelay--;
+	}
+
+	// If busy, send status poll, send Data if avail
+
+	// We need to start where we last left off, or a busy stream will lock out the others
+
+	for (nn = 0; nn <= MaxStreams; nn++)
+	{
+		Stream = TNC->LastStream++;
+
+		if (TNC->LastStream > MaxStreams)
+			TNC->LastStream = 0;
+
+		if (TNC->TNCOK && TNC->Streams[Stream].BPQtoPACTOR_Q)
+		{
+			int datalen;
+			PMSGWITHLEN buffptr;
+			char * Buffer;
+
+			// Dont send to Pactor if waiting for Min Level to be reached
+
+			if (TNC->MinLevelTimer && Stream == 0)
+				continue;
+
+			buffptr = Q_REM(&TNC->Streams[Stream].BPQtoPACTOR_Q);
+
+			datalen = (int)buffptr->Len;
+			Buffer = buffptr->Data;	// Data portion of frame
+
+			Poll[2] = TNC->Streams[Stream].DEDStream;		// Channel
+
+			if (TNC->Streams[Stream].Connected)
+			{
+				if (TNC->SwallowSignon && Stream == 0)
+				{
+					TNC->SwallowSignon = FALSE;	
+					if (strstr(Buffer, "Connected"))	// Discard *** connected
+					{
+						ReleaseBuffer(buffptr);
+						return;
+					}
+				}
+
+				Poll[3] = 0;			// Data?
+				TNC->Streams[Stream].BytesTXed += datalen;
+
+				Poll[4] = datalen - 1;
+				memcpy(&Poll[5], Buffer, datalen);
+
+				WritetoTrace(TNC, Buffer, datalen);
+
+				ReleaseBuffer(buffptr);
+				OpenLogFile(TNC->Port);
+				WriteLogLine(TNC->Port, &Poll[5], datalen);
+				CloseLogFile(TNC->Port);
+
+				CRCStuffAndSend(TNC, Poll, datalen + 5);
+
+				TNC->Streams[Stream].InternalCmd = TNC->Streams[Stream].Connected;
+
+				if (STREAM->Disconnecting && TNC->Streams[Stream].BPQtoPACTOR_Q == 0)
+					TidyClose(TNC, 0);
+
+				return;
+			}
+
+			// Command. Do some sanity checking and look for things to process locally
+
+			Poll[3] = 1;			// Command
+			datalen--;				// Exclude CR
+			Buffer[datalen] = 0;	// Null Terminate
+			_strupr(Buffer);
+
+			if (_memicmp(Buffer, "DD", 2) == 0)
+			{
+				// Send DD (Dirty Disconnect)
+
+				// Uses "Hidden" feature where you can send any normal mode command
+				// in host mode by preceeding with a #
+
+				Poll[2] = 31;
+				Poll[3] = 0x1;
+				Poll[4] = 2;
+				sprintf(&Poll[5], "#DD\r");
+				CRCStuffAndSend(TNC, Poll, 8);
+
+				// It looks like there isn't a response
+
+				TNC->Timeout = 0;	
+
+				OpenLogFile(TNC->Port);
+				WriteLogLine(TNC->Port, &Poll[5], 4);
+				CloseLogFile(TNC->Port);
+
+				ReleaseBuffer(buffptr);
+				return;
+			}
+
+			if (_memicmp(Buffer, "D", 1) == 0)
+			{
+				TNC->Streams[Stream].ReportDISC = TRUE;		// Tell Node
+				ReleaseBuffer(buffptr);
+				return;
+			}
+
+			if (memcmp(Buffer, "RADIO ", 6) == 0)
+			{
+				sprintf(&Buffer[40], "%d %s", TNC->Port, &Buffer[6]);
+
+				if (Rig_Command(TNC->PortRecord->ATTACHEDSESSIONS[0]->L4CROSSLINK, &Buffer[40]))
+				{
+					ReleaseBuffer(buffptr);
+				}
+				else
+				{
+					buffptr->Len = sprintf(buffptr->Data, "%s", &Buffer[40]);
+					C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr);
+				}
+				return;
+			}
+
+			if (_memicmp(Buffer, "SessionTimeLimit", 16) == 0)
+			{
+				if (Buffer[16] != 13)
+				{					
+					PMSGWITHLEN buffptr = (PMSGWITHLEN)GetBuff();
+
+					TNC->SessionTimeLimit = atoi(&Buffer[16]) * 60;
+
+					if (buffptr)
+					{
+						buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], "SCS} OK\r");
+						C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr);
+					}
+					return;
+				}
+			}
+
+			if (memcmp(Buffer, "MYLEVEL ", 8) == 0)
+			{
+				Switchmode(TNC, Buffer[8] - '0');
+				TNC->Bandwidth = Buffer[8]; // so scanner knows where we are
+
+				buffptr->Len = sprintf(buffptr->Data, "Ok\r");		
+				C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr);
+
+				return;
+			}
+
+			if (memcmp(Buffer, "CHECKLEVEL", 10) == 0)
+			{
+				CheckMode(TNC);
+
+				buffptr->Len = sprintf(buffptr->Data, "%s\r", &TNC->RXBuffer[2]);		
+				C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr);
+
+				return;
+			}
+
+			if (_memicmp(Buffer, "OVERRIDEBUSY", 12) == 0)
+			{
+				TNC->OverrideBusy = TRUE;
+
+				buffptr->Len = sprintf(buffptr->Data, "SCS} OK\r");
+				C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr);
+
+				return;
+			}
+
+			if ((Stream == 0) && memcmp(Buffer, "RPACKET", 7) == 0)
+			{
+				TNC->HFPacket = TRUE;
+				buffptr->Len = sprintf(buffptr->Data, "SCS} OK\r");
+				C_Q_ADD(&TNC->Streams[0].PACTORtoBPQ_Q, buffptr);
+				return;
+			}
+
+			if ((Stream == 0) && memcmp(Buffer, "PACTOR", 6) == 0)
+			{
+				TNC->HFPacket = FALSE;
+				buffptr->Len = sprintf(buffptr->Data, "SCS} OK\r");
+				C_Q_ADD(&TNC->Streams[0].PACTORtoBPQ_Q, buffptr);
+				return;
+			}
+
+
+			if ((Stream == 0) && memcmp(Buffer, "EXITHOST", 8) == 0)
+			{
+				UCHAR * Poll = TNC->TXBuffer;
+
+				TNC->UsingTermMode = 1;
+				
+				ExitHost(TNC);
+
+				// Send CR to get prompt from TNC
+				
+				Poll[0] = 13;
+				TNC->TXLen = 1;
+				WriteCommBlock(TNC);
+				
+				ReleaseBuffer(buffptr);
+				return;
+			}
+			if (Stream == 0 && Buffer[0] == 'C' && datalen > 2)	    // Pactor Connect
+				Poll[2] = TNC->Streams[0].DEDStream = 31;			// Pactor Channel
+
+			if (Stream == 0 && Buffer[0] == 'R' && Buffer[1] == 'C')	// Robust Packet Connect
+			{
+				Poll[2] = TNC->Streams[0].DEDStream = 30;			// Last Packet Channel
+				memmove(Buffer, &Buffer[1], datalen--);
+			}
+
+			if (Buffer[0] == 'C' && datalen > 2)	// Connect
+			{
+				if (*(++Buffer) == ' ') Buffer++;		// Space isn't needed
+
+				if ((memcmp(Buffer, "P1 ", 3) == 0) ||(memcmp(Buffer, "P2 ", 3) == 0))
+				{
+					// Port Selector for Packet Connect convert to 2:CALL
+
+					Buffer[0] = Buffer[1];		
+					Buffer[1] = ':';
+					memmove(&Buffer[2], &Buffer[3], datalen--);
+					//Buffer += 2;
+				}
+
+				memcpy(TNC->Streams[Stream].RemoteCall, Buffer, 9);
+
+				TNC->Streams[Stream].Connecting = TRUE;
+
+				if (Stream == 0)
+				{
+					// Send Call, Mode Command followed by connect 
+
+					TNC->Streams[0].CmdSet = TNC->Streams[0].CmdSave = malloc(100);
+
+					if (TNC->Dragon)
+						sprintf(TNC->Streams[0].CmdSet, "I%s\r%s\r", TNC->Streams[0].MyCall, buffptr->Data);
+					else
+					{
+						if (TNC->Streams[0].DEDStream == 31)
+							sprintf(TNC->Streams[0].CmdSet, "I%s\rPT\r%s\r", TNC->Streams[0].MyCall, buffptr->Data);
+						else
+							sprintf(TNC->Streams[0].CmdSet, "I%s\rPR\r%s\r", TNC->Streams[0].MyCall, buffptr->Data);
+					}
+
+					ReleaseBuffer(buffptr);
+
+					// See if Busy
+
+					if (InterlockedCheckBusy(TNC))
+					{
+						// Channel Busy. Unless override set, wait
+
+						if (TNC->OverrideBusy == 0)
+						{
+							// Send Mode Command now, save command, and wait up to 10 secs
+							// No, leave in Pactor, or Busy Detect won't work. Queue the whole conect sequence
+
+							TNC->ConnectCmd = TNC->Streams[0].CmdSet;
+							TNC->Streams[0].CmdSet = NULL;
+
+							sprintf(TNC->WEB_TNCSTATE, "Waiting for clear channel");
+							SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
+
+							TNC->BusyDelay = TNC->BusyWait * 10;
+							TNC->Streams[Stream].Connecting = FALSE;	// Not connecting Yet
+
+							return;
+						}
+					}
+
+					TNC->OverrideBusy = FALSE;
+
+					sprintf(TNC->WEB_TNCSTATE, "%s Connecting to %s", TNC->Streams[Stream].MyCall, TNC->Streams[Stream].RemoteCall);
+					SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
+
+					Debugprintf("SCS Pactor CMDSet = %s", TNC->Streams[Stream].CmdSet);
+
+					TNC->Streams[0].InternalCmd = FALSE;
+					return;
+				}
+			}
+	
+
+			Poll[4] = datalen - 1;
+			memcpy(&Poll[5], buffptr->Data, datalen);
+
+			// if it starts with # the tnc won't respond, so send OK now.
+
+			if (Buffer[0] == '#')
+			{
+				TNC->HFPacket = TRUE;
+				buffptr->Len = sprintf(buffptr->Data, "SCS} OK\r");
+				C_Q_ADD(&TNC->Streams[0].PACTORtoBPQ_Q, buffptr);
+			}
+			else
+				ReleaseBuffer(buffptr);
+
+			OpenLogFile(TNC->Port);
+			WriteLogLine(TNC->Port, &Poll[5], datalen);
+			CloseLogFile(TNC->Port);
+
+			CRCStuffAndSend(TNC, Poll, datalen + 5);
+
+			TNC->Streams[Stream].InternalCmd = TNC->Streams[Stream].Connected;
+
+			return;
+		}
+
+		// if frames outstanding, issue a poll
+
+		if (TNC->Streams[Stream].FramesOutstanding)
+		{
+			Poll[2] = TNC->Streams[Stream].DEDStream;
+			Poll[3] = 0x1;			// Command
+			Poll[4] = 0;			// Len-1
+			Poll[5] = 'L';			// Status
+
+			CRCStuffAndSend(TNC, Poll, 6);
+
+			TNC->InternalCmd = TRUE;
+			TNC->IntCmdDelay--;
+			return;
+		}
+
+	}
+
+	TNC->PollSent = TRUE;
+
+	// Use General Poll (255)
+
+	Poll[2] = 255 ;			// Channel
+	Poll[3] = 0x1;			// Command
+
+	if (TNC->ReinitState == 3)
+	{
+		TNC->ReinitState = 0;
+		Poll[3] = 0x41;
+	}
+
+	Poll[4] = 0;			// Len-1
+	Poll[5] = 'G';			// Poll
+
+	CRCStuffAndSend(TNC, Poll, 6);
+	TNC->InternalCmd = FALSE;
+
+	return;
+
+}
+
+void SCSTryToSendDATA(struct TNCINFO * TNC, int Stream)
+{
+	// Used after queuing data to see if it can be sent immediately
+
+	struct STREAMINFO * STREAM = &TNC->Streams[Stream];
+	int datalen;
+	PMSGWITHLEN buffptr;
+	char * Buffer;
+	UCHAR * Poll = TNC->TXBuffer;
+
+	if (TNC->TNCOK == 0 || STREAM->BPQtoPACTOR_Q == 0 || STREAM->Connected == 0)
+		return;
+
+
+	// Dont send to Pactor if waiting for Min Level to be reached
+
+	if (TNC->MinLevelTimer && Stream == 0)
+		return;;
+
+	Sleep(10);				// Give TNC time to respond
+	
+	SCSCheckRX(TNC);		// See if anything received
+
+	if (TNC->Timeout)
+		return;				// Link busy
+			
+	buffptr = Q_REM(&STREAM->BPQtoPACTOR_Q);
+
+	datalen = (int)buffptr->Len;
+	Buffer = buffptr->Data;	// Data portion of frame
+
+	Poll[2] = STREAM->DEDStream;		// Channel
+
+	if (TNC->SwallowSignon && Stream == 0)
+	{
+		TNC->SwallowSignon = FALSE;	
+	
+		if (strstr(Buffer, "Connected"))	// Discard *** connected
+		{
+			ReleaseBuffer(buffptr);
+			return;
+		}
+	}
+
+	Poll[3] = 0;			// Data
+	STREAM->BytesTXed += datalen;
+
+	Poll[4] = datalen - 1;
+	memcpy(&Poll[5], Buffer, datalen);
+				
+	WritetoTrace(TNC, Buffer, datalen);
+	
+	ReleaseBuffer(buffptr);
+	OpenLogFile(TNC->Port);
+	
+	WriteLogLine(TNC->Port, &Poll[5], datalen);
+	CloseLogFile(TNC->Port);
+		
+	CRCStuffAndSend(TNC, Poll, datalen + 5);
+
+	if (STREAM->Disconnecting && STREAM->BPQtoPACTOR_Q == 0)
+		TidyClose(TNC, Stream);
+
+	return;
+}
+			
+
+VOID DoTNCReinit(struct TNCINFO * TNC)
+{
+	UCHAR * Poll = TNC->TXBuffer;
+
+	if (TNC->ReinitState == 0)
+	{
+		// Just Starting - Send a TNC Mode Command to see if in Terminal or Host Mode
+	
+		TNC->TNCOK = FALSE;
+		sprintf(TNC->WEB_COMMSSTATE,"%s Initialising TNC", TNC->PortRecord->PORTCONTROL.SerialPortName);
+		SetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE);
+
+		Poll[0] = 13;
+		Poll[1] = 0x1B;
+		TNC->TXLen = 2;
+
+		if (WriteCommBlock(TNC) == FALSE)
+		{
+			CloseCOMPort(TNC->hDevice);
+			OpenCOMMPort(TNC, TNC->PortRecord->PORTCONTROL.SerialPortName, TNC->PortRecord->PORTCONTROL.BAUDRATE, TRUE);
+		}
+
+		TNC->Retries = 1;
+	}
+
+	if (TNC->ReinitState == 1)		// Forcing back to Term
+		TNC->ReinitState = 0;
+
+	if (TNC->ReinitState == 2)		// In Term State, Sending Initialisation Commands
+	{
+		char * start, * end;
+		int len;
+
+		start = TNC->InitPtr;
+		
+		if (*(start) == 0)			// End of Script
+		{
+			// Put into Host Mode
+
+			Debugprintf("DOTNCReinit Complete - Entering Hostmode");
+
+			TNC->TXBuffer[2] = 0;
+			TNC->Toggle = 0;
+
+			memcpy(Poll, "JHOST4\r", 7);
+
+			TNC->TXLen = 7;
+			WriteCommBlock(TNC);
+
+			// Timeout will enter host mode
+
+			TNC->Timeout = 1;
+			TNC->Retries = 1;
+			TNC->Toggle = 0;
+			TNC->ReinitState = 3;	// Set toggle force bit
+			TNC->OKToChangeFreq = 1;	// In case failed whilst waiting for permission
+
+			return;
+		}
+		
+		end = strchr(start, 13);
+		len = (int)(++end - start);
+		TNC->InitPtr = end;
+		memcpy(Poll, start, len);
+
+		OpenLogFile(TNC->Port);
+		WriteLogLine(TNC->Port, Poll, len);
+		CloseLogFile(TNC->Port);
+
+		TNC->TXLen = len;
+		WriteCommBlock(TNC);
+
+		TNC->Retries = 2;
+	}
+}
+
+static VOID DoTermModeTimeout(struct TNCINFO * TNC)
+{
+	UCHAR * Poll = TNC->TXBuffer;
+
+	if (TNC->ReinitState == 0)
+	{
+		//Checking if in Terminal Mode - Try to set back to Term Mode
+
+		TNC->ReinitState = 1;
+		ExitHost(TNC);
+		TNC->Retries = 1;
+
+		return;
+	}
+
+	if (TNC->ReinitState == 1)
+	{
+		// Forcing back to Term Mode
+
+		TNC->ReinitState = 0;
+		DoTNCReinit(TNC);				// See if worked
+		return;
+	}
+
+	if (TNC->ReinitState == 3)
+	{
+		// Entering Host Mode
+	
+		// Assume ok
+
+		TNC->HostMode = TRUE;
+		TNC->IntCmdDelay = 10;
+
+		return;
+	}
+}
+
+BOOL CheckRXText(struct TNCINFO * TNC)
+{
+	int Length;
+
+	// only try to read number of bytes in queue 
+
+	if (TNC->RXLen == 500)
+		TNC->RXLen = 0;
+
+	Length = ReadCOMBlock(TNC->hDevice, &TNC->RXBuffer[TNC->RXLen], 500 - TNC->RXLen);
+
+	if (Length == 0)
+		return FALSE;					// Nothing doing
+	
+	TNC->RXLen += Length;
+
+	Length = TNC->RXLen;
+
+	TNC->RXBuffer[TNC->RXLen] = 0;
+
+	if (strlen(TNC->RXBuffer) < TNC->RXLen)
+		TNC->RXLen = 0;
+
+	if ((strstr(TNC->RXBuffer, "cmd: ") == 0) && (strstr(TNC->RXBuffer, "pac: ") == 0))
+		return 0;				// Wait for rest of frame
+
+	// Complete Char Mode Frame
+
+	OpenLogFile(TNC->Port);
+	WriteLogLine(TNC->Port, TNC->RXBuffer, TNC->RXLen);
+	CloseLogFile(TNC->Port);
+
+	TNC->RXBuffer[TNC->RXLen] = 0;
+	
+	if (TNC->RIG->RIG_DEBUG)
+		Debugprintf(TNC->RXBuffer);
+
+	TNC->RXLen = 0;		// Ready for next frame
+
+	return TRUE;				
+}
+
+BOOL CheckRXHost(struct TNCINFO * TNC, char * UnstuffBuffer)
+{
+	int Length;
+	unsigned short crc;
+
+	// only try to read number of bytes in queue 
+
+	if (TNC->RXLen == 500)
+		TNC->RXLen = 0;
+
+	Length = ReadCOMBlock(TNC->hDevice, &TNC->RXBuffer[TNC->RXLen], 500 - TNC->RXLen);
+
+	if (Length == 0)
+		return FALSE;					// Nothing doing
+	
+	TNC->RXLen += Length;
+
+	Length = TNC->RXLen;
+
+	if (Length < 6)				// Minimum Frame Sise
+		return FALSE;
+
+	if (TNC->RXBuffer[2] == 170)
+	{
+		// Retransmit Request
+	
+		TNC->RXLen = 0;
+		return FALSE;				// Ignore for now
+	}
+
+	// Can't unstuff into same buffer - fails if partial msg received, and we unstuff twice
+
+	Length = Unstuff(&TNC->RXBuffer[2], &UnstuffBuffer[2], Length - 2);
+
+	if (Length == -1)
+	{
+		// Unstuff returned an errors (170 not followed by 0)
+
+		TNC->RXLen = 0;
+		return FALSE;				// Ignore for now
+	}
+
+	crc = compute_crc(&UnstuffBuffer[2], Length);
+
+	if (crc == 0xf0b8)		// Good CRC
+	{
+		TNC->RXLen = 0;		// Ready for next frame
+		return TRUE;
+	}
+
+	// Bad CRC - assume incomplete frame, and wait for rest. If it was a full bad frame, timeout and retry will recover link.
+
+	return FALSE;
+}
+
+
+//#include "Mmsystem.h"
+
+int Sleeptime = 250;
+
+int CheckMode(struct TNCINFO * TNC)
+{
+	int n;
+	char UnstuffBuffer[500];	
+
+	UCHAR * Poll = TNC->TXBuffer;
+
+	if (TNC->HostMode == 0)
+		return 0;							// Don't try if initialising
+
+	TNC->EnterExit = TRUE;
+
+	Poll[2] = 31;
+	Poll[3] = 0x41;
+	Poll[4] = 0x5;
+	memcpy(&Poll[5], "JHOST0", 6);
+
+	CRCStuffAndSend(TNC, Poll, 11);
+
+	n = 0;
+
+	while (CheckRXHost(TNC, UnstuffBuffer) == FALSE)
+	{
+		Sleep(5);
+		n++;
+
+		if (n > 100) break;
+	}
+
+
+	sprintf(Poll, "MYL\r");
+	
+	OpenLogFile(TNC->Port);
+	WriteLogLine(TNC->Port, Poll, 3);
+	CloseLogFile(TNC->Port);
+
+	TNC->TXLen = 4;
+	WriteCommBlock(TNC);
+
+	n = 0;
+
+	while (CheckRXText(TNC) == FALSE)
+	{
+		Sleep(5);
+		n++;
+		if (n > 100) break;
+	}
+
+	memcpy(Poll, "JHOST4\r", 7);
+
+	TNC->TXLen = 7;
+	WriteCommBlock(TNC);
+
+	// No response expected
+
+	Sleep(10);
+
+	Poll[2] = 255;			// Channel
+	TNC->Toggle = 0;
+	Poll[3] = 0x41;
+	Poll[4] = 0;			// Len-1
+	Poll[5] = 'G';			// Poll
+
+	CRCStuffAndSend(TNC, Poll, 6);
+	TNC->InternalCmd = FALSE;
+	TNC->Timeout = 5;		// 1/2 sec - In case missed
+
+	TNC->EnterExit = FALSE;
+	return 0;
+}
+
+
+int Switchmode(struct TNCINFO * TNC, int Mode)
+{
+	int n;
+	char UnstuffBuffer[500];	
+
+	UCHAR * Poll = TNC->TXBuffer;
+
+	if (TNC->HostMode == 0)
+		return 0;							// Don't try if initialising
+
+	if (TNC->HFPacket)
+	{
+		Poll[2] = 31;
+		Poll[3] = 0x1;
+		Poll[4] = 0x1;
+		memcpy(&Poll[5], "PT", 2);
+		CRCStuffAndSend(TNC, Poll, 7);
+		OpenLogFile(TNC->Port);
+		WriteLogLine(TNC->Port, "SwitchModes - Setting Pactor", 28);
+		CloseLogFile(TNC->Port);
+
+		TNC->HFPacket = FALSE;
+		TNC->Streams[0].DEDStream = 31;		// Pactor Channel
+
+		n = 0;
+		while (CheckRXHost(TNC, UnstuffBuffer) == FALSE)
+		{
+			Sleep(5);
+			n++;
+			if (n > 100) break;
+		}
+
+//		Debugprintf("Set Pactor ACK received in %d mS, Sleeping for %d", 5 * n, Sleeptime);
+		Sleep(Sleeptime);
+	}
+
+	// Uses "Hidden" feature where you can send any normal mode command
+	// in host mode by preceeding with a #
+
+	Poll[2] = 31;
+	Poll[3] = 0x1;
+	Poll[4] = 5;
+	sprintf(&Poll[5], "#MYL %d\r", Mode);
+	CRCStuffAndSend(TNC, Poll, 11);
+			
+	// It looks like there isn't a response
+
+	TNC->Timeout = 0;	
+
+	OpenLogFile(TNC->Port);
+	WriteLogLine(TNC->Port, &Poll[5], 6);
+	CloseLogFile(TNC->Port);
+
+	return 0;
+}
+
+VOID SwitchToPactor(struct TNCINFO * TNC)
+{
+	if (TNC->ForceRobust)
+		return;
+
+	TNC->Streams[0].CmdSet = TNC->Streams[0].CmdSave = malloc(100);
+	sprintf(TNC->Streams[0].CmdSet, "PT\r");
+
+	TNC->HFPacket = FALSE;
+	TNC->Streams[0].DEDStream = 31;		// Pactor Channel
+
+	if (TNC->RIG->RIG_DEBUG)
+		Debugprintf("BPQ32 Scan - switch to Pactor");
+}
+
+VOID SwitchToPacket(struct TNCINFO * TNC)
+{
+	TNC->Streams[0].CmdSet = TNC->Streams[0].CmdSave = malloc(100);
+	sprintf(TNC->Streams[0].CmdSet, "PR\r");
+
+	TNC->HFPacket = TRUE;
+	TNC->Streams[0].DEDStream = 30;		// Packet Channel
+
+	TNC->SwitchToPactor = TNC->RobustTime;
+
+	if (TNC->RIG->RIG_DEBUG)
+		Debugprintf("BPQ32 Scan - switch to Packet");
+}
+
+VOID ExitHost(struct TNCINFO * TNC)
+{
+	UCHAR * Poll = TNC->TXBuffer;
+
+	// Try to exit Host Mode
+
+	TNC->TXBuffer[2] = 31;
+	TNC->TXBuffer[3] = 0x41;
+	TNC->TXBuffer[4] = 0x5;
+	memcpy(&TNC->TXBuffer[5], "JHOST0", 6);
+
+	CRCStuffAndSend(TNC, Poll, 11);
+	return;
+}
+
+VOID CRCStuffAndSend(struct TNCINFO * TNC, UCHAR * Msg, int Len)
+{
+	unsigned short int crc;
+	UCHAR StuffedMsg[500];
+	int i, j;
+
+    Msg[3] |= TNC->Toggle;
+	TNC->Toggle ^= 0x80;
+
+	crc = compute_crc(&Msg[2], Len-2);
+	crc ^= 0xffff;
+
+	Msg[Len++] = (crc&0xff);
+	Msg[Len++] = (crc>>8);
+
+	for (i = j = 2; i < Len; i++)
+	{
+		StuffedMsg[j++] = Msg[i];
+		if (Msg[i] == 170)
+		{
+			StuffedMsg[j++] = 0;
+		}
+	}
+
+	if (j != i)
+	{
+		Len = j;
+		memcpy(Msg, StuffedMsg, j);
+	}
+
+	TNC->TXLen = Len;
+
+	Msg[0] = 170;
+	Msg[1] = 170;
+
+	WriteCommBlock(TNC);
+
+	TNC->Retries = 5;
+}
+
+int Unstuff(UCHAR * MsgIn, UCHAR * MsgOut, int len)
+{
+	int i, j=0;
+
+	for (i=0; iTXBuffer;
+
+	if (TNC->ReinitState == 0)
+	{
+		// Testing if in Term Mode. It is, so can now send Init Commands
+
+		TNC->InitPtr = TNC->InitScript;
+		TNC->ReinitState = 2;
+
+		// Send Restart to make sure PTC is in a known state
+
+		strcpy(Poll, "RESTART\r");
+
+		OpenLogFile(TNC->Port);
+		WriteLogLine(TNC->Port, Poll, 7);
+		CloseLogFile(TNC->Port);
+
+		TNC->TXLen = 8;
+		WriteCommBlock(TNC);
+
+		TNC->Timeout = 60;				// 6 secs
+
+		return;
+	}
+	if (TNC->ReinitState == 2)
+	{
+		// Sending Init Commands
+
+		if (strstr(TNC->RXBuffer, "SCS P4dragon"))
+		{
+			TNC->Dragon = TRUE;
+			Debugprintf("SCSPactor in P4dragon mode");
+		}
+
+		DoTNCReinit(TNC);		// Send Next Command
+		return;
+	}
+}
+
+VOID ProcessIncomingCall(struct TNCINFO * TNC, struct STREAMINFO * STREAM, int Stream)
+{
+	APPLCALLS * APPL;
+	char * ApplPtr = APPLS;
+	int App;
+	char Appl[10];
+	char FreqAppl[10] = "";				// Frequecy-specific application
+	char DestCall[10];
+	TRANSPORTENTRY * SESS;
+	struct WL2KInfo * WL2K = TNC->WL2K;
+	UCHAR * ptr;
+	UCHAR Buffer[80];	
+	PMSGWITHLEN buffptr;
+	BOOL PactorCall = FALSE;
+	
+	char * Call = STREAM->RemoteCall;
+
+	if (Stream > 0 && Stream < 30)
+		ProcessIncommingConnectEx(TNC, Call, Stream, FALSE, TRUE);	// No CTEXT
+	else
+		ProcessIncommingConnectEx(TNC, Call, Stream, TRUE, TRUE);
+
+	SESS = TNC->PortRecord->ATTACHEDSESSIONS[Stream];
+
+	if (SESS == NULL)
+		return;							// Cant do much without one
+
+	if (Stream > 0 && Stream < 30)
+	{
+		// Packet Connect. Much safer to process here, even though it means
+		// duplicating some code, or the Pactor/RP mode tests get very complicated
+
+		int Len = 0;
+		struct PORTCONTROL * PORT = &TNC->PortRecord->PORTCONTROL;
+
+		strcpy(DestCall, STREAM->MyCall);
+		Debugprintf("PTC Packet Incoming Call - MYCALL = *%s*", DestCall);
+					
+		for (App = 0; App < 32; App++)
+		{
+			APPL=&APPLCALLTABLE[App];
+			memcpy(Appl, APPL->APPLCALL_TEXT, 10);
+
+			ptr=strchr(Appl, ' ');
+								
+			if (ptr)
+				*ptr = 0;
+
+			if (_stricmp(DestCall, Appl) == 0)
+				break;
+		}
+
+		if (App < 32)
+		{
+			char AppName[13];
+			
+			memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12);
+			AppName[12] = 0;
+
+			// Make sure app is available
+
+			Debugprintf("Connect is to APPL %s", AppName);
+
+			if (CheckAppl(TNC, AppName))
+			{
+				int MsgLen = sprintf(Buffer, "%s\r", AppName);
+
+				buffptr = GetBuff();
+
+				if (buffptr == 0) return;			// No buffers, so ignore
+
+				buffptr->Len = MsgLen;
+
+				memcpy(buffptr->Data, Buffer, MsgLen);
+
+				C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr);
+				TNC->SwallowSignon = TRUE;
+			}
+			else
+			{
+				char Msg[] = "Application not available\r\n";
+					
+				// Send a Message, then a disconenct
+					
+				buffptr = GetBuff();
+
+				if (buffptr == 0) return;			// No buffers, so ignore
+
+				buffptr->Len = (int)strlen(Msg);
+				memcpy(buffptr->Data, Msg, strlen(Msg));
+				C_Q_ADD(&STREAM->BPQtoPACTOR_Q, buffptr);
+
+				STREAM->NeedDisc = 100;	// 10 secs
+			}							
+			return;			
+		}				
+		
+		// Not to a known appl - drop through to Node
+
+		if (PORT->CTEXT)
+		{
+			Len = strlen(PORT->CTEXT);
+			ptr = PORT->CTEXT;
+		}
+		else if (CTEXTLEN)
+		{
+			Len = CTEXTLEN;
+			ptr = CTEXTMSG;
+		}
+		else
+			return;
+
+		while (Len > 0)
+		{
+			int sendLen = TNC->PortRecord->ATTACHEDSESSIONS[Stream]->SESSPACLEN;
+
+			if (sendLen == 0)
+				sendLen = 80;
+
+			if (Len < sendLen)
+				sendLen = Len;
+
+			buffptr = GetBuff();
+			if (buffptr == 0) return;			// No buffers, so ignore
+
+			buffptr->Len = sendLen;
+			memcpy(buffptr->Data, ptr, sendLen);
+			C_Q_ADD(&STREAM->BPQtoPACTOR_Q, buffptr);
+
+			ptr += sendLen;
+			Len -= sendLen;
+		}
+		return;
+	}
+
+	//Connect on HF port. May be Pactor or RP on some models
+	
+	if (STREAM->DEDStream == 31)
+		PactorCall = TRUE;
+
+	if (TNC->RIG && TNC->RIG != &TNC->DummyRig)
+	{
+		sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound Freq %s", STREAM->RemoteCall, TNC->NodeCall, TNC->RIG->Valchar);
+		SESS->Frequency = (int)(atof(TNC->RIG->Valchar) * 1000000.0) + 1500;		// Convert to Centre Freq
+
+		// If Scan Entry has a Appl, save it
+
+		if (PactorCall && TNC->RIG->FreqPtr && TNC->RIG->FreqPtr[0]->APPL[0])
+			strcpy(FreqAppl, &TNC->RIG->FreqPtr[0]->APPL[0]);
+	}
+	else
+	{
+		sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Inbound", STREAM->RemoteCall, TNC->NodeCall);
+		if (WL2K)
+			SESS->Frequency = WL2K->Freq;
+	}
+
+	if (WL2K)
+		strcpy(SESS->RMSCall, WL2K->RMSCall);						
+
+	SESS->Mode = PleveltoMode[TNC->Streams[Stream].PTCStatus1];
+
+	SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
+
+	if (PactorCall && TNC->MinLevel > 1)
+		TNC->MinLevelTimer = 150;		// Check we have reached right level
+					
+	// See which application the connect is for
+	
+	strcpy(DestCall, STREAM->MyCall);
+
+	if (PactorCall)
+		Debugprintf("Pactor Incoming Call - MYCALL = *%s*", DestCall);					
+	else					
+		Debugprintf("HF Packet/RP Incoming Call - MYCALL = *%s*", DestCall);					
+
+	if ((PactorCall && TNC->UseAPPLCallsforPactor) || (PactorCall == 0 && TNC->UseAPPLCalls))
+		//   Test for Richard - Should drop through to Node if not to an APPLCALL  
+		//&& strcmp(DestCall, TNC->NodeCall) != 0)		// Not Connect to Node Call
+	{		
+		for (App = 0; App < 32; App++)
+		{
+			APPL=&APPLCALLTABLE[App];
+			memcpy(Appl, APPL->APPLCALL_TEXT, 10);
+			ptr=strchr(Appl, ' ');
+
+			if (ptr)
+				*ptr = 0;
+	
+			if (_stricmp(DestCall, Appl) == 0)
+				break;
+		}
+
+		if (App < 32)
+		{
+			char AppName[13];
+
+			memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12);
+			AppName[12] = 0;
+
+			// if SendTandRtoRelay set and Appl is RMS change to RELAY
+
+			if (TNC->SendTandRtoRelay && memcmp(AppName, "RMS ", 4) == 0
+				&& (strstr(Call, "-T" ) || strstr(Call, "-R")))
+					strcpy(AppName, "RELAY       ");
+
+			// Make sure app is available
+
+			Debugprintf("Connect is to APPL %s", AppName);
+
+			if (CheckAppl(TNC, AppName))
+			{
+				int MsgLen = sprintf(Buffer, "%s\r", AppName);
+				buffptr = GetBuff();
+
+				if (buffptr == 0) return;			// No buffers, so ignore
+
+				buffptr->Len = MsgLen;
+				memcpy(buffptr->Data, Buffer, MsgLen);
+
+				C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr);
+				TNC->SwallowSignon = TRUE;
+			}
+			else
+			{
+				char Msg[] = "Application not available\r\n";
+					
+				// Send a Message, then a disconenct
+					
+				buffptr = GetBuff();
+				if (buffptr == 0) return;			// No buffers, so ignore
+
+				buffptr->Len = strlen(Msg);
+				memcpy(buffptr->Data, Msg, strlen(Msg));
+				C_Q_ADD(&STREAM->BPQtoPACTOR_Q, buffptr);
+
+				STREAM->NeedDisc = 100;	// 10 secs
+			}
+			return;		
+		}
+
+		// Not to a known appl - drop through to Node		
+	}
+
+	if (!PactorCall && TNC->UseAPPLCalls)
+		goto DontUseAPPLCmd;				// Don't use APPL= for Packet Calls
+
+	// if SendTandRtoRelay set and Appl is RMS change to RELAY
+
+	if (TNC->SendTandRtoRelay && strcmp(FreqAppl, "RMS") == 0
+		&& (strstr(Call, "-T" ) || strstr(Call, "-R")))
+			strcpy(FreqAppl, "RELAY");
+
+	Debugprintf("Pactor Call is %s Freq Specific Appl is %s Freq is %s",
+		DestCall, FreqAppl, TNC->RIG->Valchar);
+						
+	if (FreqAppl[0])			// Frequency specific APPL overrides TNC APPL
+	{
+		buffptr = GetBuff();
+		if (buffptr == 0) return;			// No buffers, so ignore
+
+		Debugprintf("Using Freq Specific Appl %s", FreqAppl);
+
+		buffptr->Len = sprintf(buffptr->Data, "%s\r", FreqAppl);
+		C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr);
+		TNC->SwallowSignon = TRUE;
+		return;
+	}
+
+	// If an autoconnect APPL is defined, send it
+					
+	if (TNC->ApplCmd)	
+	{
+		char App[16];
+
+		buffptr = GetBuff();
+		if (buffptr == 0) return;			// No buffers, so ignore
+
+		strcpy(App, TNC->ApplCmd);
+
+		Debugprintf("Using Default Appl *%s*, connecting call is %s", App, Call);
+
+		// if SendTandRtoRelay set and Appl is RMS change to RELAY
+
+		if (TNC->SendTandRtoRelay && memcmp(App, "RMS", 3) == 0
+			&& (strstr(Call, "-T" ) || strstr(Call, "-R")))
+		{
+			strcpy(App, "RELAY");
+			Debugprintf("Radio Only Call - Connecting to RELAY");
+		}
+
+		buffptr->Len = sprintf(buffptr->Data, "%s\r", App);
+		C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr);
+		TNC->SwallowSignon = TRUE;
+		return;
+	}
+		
+DontUseAPPLCmd:
+			
+	if (FULL_CTEXT && CTEXTLEN && HFCTEXTLEN == 0)
+	{
+		int Len = CTEXTLEN, CTPaclen = 100;
+		int Next = 0;
+
+		while (Len > CTPaclen)		// CTEXT Paclen
+		{
+			buffptr = GetBuff();
+			if (buffptr == 0) return;			// No buffers, so ignore
+
+			buffptr->Len = CTPaclen;
+			memcpy(buffptr->Data, &CTEXTMSG[Next], CTPaclen);
+			C_Q_ADD(&STREAM->BPQtoPACTOR_Q, buffptr);
+
+			Next += CTPaclen;
+			Len -= CTPaclen;
+		}
+
+		buffptr = GetBuff();
+		if (buffptr == 0) return;			// No buffers, so ignore
+
+		buffptr->Len = Len;
+		memcpy(buffptr->Data, &CTEXTMSG[Next], Len);
+		C_Q_ADD(&STREAM->BPQtoPACTOR_Q, buffptr);
+	}
+}
+
+VOID ProcessDEDFrame(struct TNCINFO * TNC, UCHAR * Msg, int framelen)
+{
+	PMSGWITHLEN buffptr;
+	UCHAR * Buffer;				// Data portion of frame
+	char Status[80];
+	unsigned int Stream = 0, RealStream;
+
+	if (TNC->HostMode == 0)
+		return;
+
+	// Any valid frame is an ACK
+
+	TNC->Timeout = 0;
+
+	if (TNC->TNCOK == FALSE)
+	{
+		// Just come up
+
+		struct RIGPORTINFO * PORT;
+		
+		TNC->TNCOK = TRUE;
+		sprintf(TNC->WEB_COMMSSTATE,"%s TNC link OK", TNC->PortRecord->PORTCONTROL.SerialPortName);
+		SetWindowText(TNC->xIDC_COMMSSTATE, TNC->WEB_COMMSSTATE);
+
+		// If using an FT847 on PTC Port it needa a "Cat On" Command. Send it here
+
+		if (TNC->RIG->PORT && TNC->RIG->PORT->PTC)
+		{
+			PORT = TNC->RIG->PORT;
+
+			if (strcmp(PORT->Rigs[0].RigName, "FT847") == 0)
+			{
+				UCHAR CATON[6] = {0,0,0,0,0};
+				SendPTCRadioCommand(PORT->PTC, CATON, 5);
+			}
+		}
+	}
+
+	Stream = RealStream = Msg[2];
+
+	if (Stream > 29)
+		Stream = 0;				// 31 = Pactor or 30 = Robust Packet Outgoing
+
+	//	if in Dragon Single Mode (Pactor and Packet on Same Port)
+	//	we only use stream 0, so if a packet frame, set DEDStream
+
+	//	Im not convinced this is the bast place to do this, but let's try
+
+	if (TNC->DragonSingle && RealStream && RealStream < 31)	// Not a Pactor or control frame
+	{
+		//	must be packet
+
+		TNC->Streams[0].DEDStream = RealStream;		// Packet Channel
+		Stream = 0;
+	}
+
+	if (TNC->TXBuffer[5] == '#')	// Shouldnt happen!
+		return;
+
+
+	//	See if Poll Reply or Data
+	
+	if (Msg[3] == 0)
+	{
+		// Success - Nothing Follows
+
+		if (Stream < 32)
+			if (TNC->Streams[Stream].CmdSet)
+				return;						// Response to Command Set
+
+		if ((TNC->TXBuffer[3] & 1) == 0)	// Data
+			return;
+
+		// If the response to a Command, then we should convert to a text "Ok" for forward scripts, etc
+
+		if (TNC->TXBuffer[5] == 'G')	// Poll
+			return;
+
+		if (TNC->TXBuffer[5] == 'C')	// Connect - reply we need is async
+			return;
+
+		if (TNC->TXBuffer[5] == 'L')	// Shouldnt happen!
+			return;
+
+		if (TNC->TXBuffer[5] == '#')	// Shouldnt happen!
+			return;
+
+		if (TNC->TXBuffer[5] == '%' && TNC->TXBuffer[6] == 'W')	// Scan Control - Response to W1
+			if (TNC->InternalCmd)
+				return;					// Just Ignore
+
+		if (TNC->TXBuffer[5] == 'J')	// JHOST
+		{
+			if (TNC->TXBuffer[10] == '0')	// JHOST0
+			{
+				TNC->Timeout = 1;			// 
+				return;
+			}
+		}
+		
+		if (TNC->Streams[Stream].Connected)
+			return;
+
+		buffptr = GetBuff();
+
+		if (buffptr == NULL) return;			// No buffers, so ignore
+
+		buffptr->Len = sprintf(buffptr->Data,"Pactor} Ok\r");
+
+		OpenLogFile(TNC->Port);
+		WriteLogLine(TNC->Port, buffptr->Data, (int)buffptr->Len);
+		CloseLogFile(TNC->Port);
+
+		C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr);
+		return;
+	}
+
+	if (Msg[3] > 0 && Msg[3] < 6)
+	{
+		// Success with message - null terminated
+
+		UCHAR * ptr;
+		int len;
+
+		if (Msg[2] == 0xff)			// General Poll Response
+		{
+			UCHAR * Poll = TNC->TXBuffer;
+			UCHAR Chan = Msg[4] - 1;
+
+			if (Chan == 255)			// Nothing doing
+				return;	
+		
+			if (Msg[5] != 0)
+			{
+				// More than one to poll - save the list of channels to poll
+
+				strcpy(TNC->NexttoPoll, &Msg[5]);
+			}
+
+			// Poll the channel that had data
+
+			Poll[2] = Chan;			// Channel
+			Poll[3] = 0x1;			// Command
+
+			if (Chan == 254)		// Status - Send Extended Status (G3)
+			{
+				Poll[4] = 1;			// Len-1
+				Poll[5] = 'G';			// Extended Status Poll
+				Poll[6] = '3';
+			}
+			else
+			{
+				Poll[4] = 0;			// Len-1
+				Poll[5] = 'G';			// Poll
+			}
+
+			CRCStuffAndSend(TNC, Poll, Poll[4] + 6);
+			TNC->InternalCmd = FALSE;
+
+			return;
+		}
+
+		Buffer = &Msg[4];
+		
+		ptr = strchr(Buffer, 0);
+
+		if (ptr == 0)
+			return;
+
+		*(ptr++) = 13;
+		*(ptr) = 0;
+
+		len = (int)(ptr - Buffer);
+
+		if (len > 256)
+			return;
+
+		// See if we need to process locally (Response to our command, Incoming Call, Disconencted, etc
+
+		if (Msg[3] < 3)						// 1 or 2 - Success or Fail
+		{
+			char LastCmd = TNC->TXBuffer[5];
+			struct STREAMINFO * STREAM = &TNC->Streams[Stream];
+			
+			// See if a response to internal command
+
+			if (TNC->RIG->RIG_DEBUG)
+				if (LastCmd == 'I')
+					Debugprintf("SCS I Cmd Response %s", Buffer);
+
+			if (LastCmd == 'I' && STREAM->CheckingCall == TRUE)
+			{
+				// We've received a connect and are checking MYCALL
+
+				Debugprintf("SCS Incoming Call I Cmd Response %s Stream %d DED Stream %d", Buffer, Stream, RealStream);
+
+				strlop(Buffer, 13);
+				strcpy(STREAM->MyCall, Buffer);
+
+				ProcessIncomingCall(TNC, STREAM, Stream);
+				STREAM->CheckingCall = FALSE;
+				return;
+			}
+
+			if (TNC->InternalCmd)
+			{
+				// Process it
+
+				if (LastCmd == 'L')		// Status
+				{
+					int s1, s2, s3, s4, s5, s6, num;
+
+					num = sscanf(Buffer, "%d %d %d %d %d %d", &s1, &s2, &s3, &s4, &s5, &s6);
+			
+					TNC->Streams[Stream].FramesOutstanding = s3;
+	
+					// flow control debug
+
+					sprintf(TNC->WEB_BUFFERS, "%d Q %d", TNC->Buffers, 	TNC->Streams[0].FramesOutstanding);
+					SetWindowText(TNC->xIDC_BUFFERS, TNC->WEB_BUFFERS);
+
+					return;
+				}
+
+				if (LastCmd == '@')		// @ Commands
+				{
+					if (TNC->TXBuffer[6]== 'B')	// Buffer Status
+					{
+						TNC->Buffers = atoi(Buffer);
+						sprintf(TNC->WEB_BUFFERS, "%d Q %d", TNC->Buffers, 	TNC->Streams[0].FramesOutstanding);
+						SetWindowText(TNC->xIDC_BUFFERS, TNC->WEB_BUFFERS);
+						return;
+					}
+				}
+
+				if (LastCmd == '%')		// % Commands
+				{					
+					if (TNC->TXBuffer[6]== 'T')	// TX count Status
+					{
+						sprintf(TNC->WEB_TRAFFIC, "RX %d TX %d ACKED %s", TNC->Streams[Stream].BytesRXed, TNC->Streams[Stream].BytesTXed, Buffer);
+						SetWindowText(TNC->xIDC_TRAFFIC, TNC->WEB_TRAFFIC);
+						return;
+					}
+
+					if (TNC->TXBuffer[6] == 'W')	// Scan Control
+					{
+						if (Msg[4] == '1')			// Ok to Change
+						{
+							TNC->OKToChangeFreq = 1;
+							TNC->TimeScanLocked = 0;
+							if (TNC->RIG->RIG_DEBUG)
+								Debugprintf("Scan Debug SCS Pactor TNC gave permission");
+						}
+						else
+						{
+							TNC->OKToChangeFreq = -1;
+							if (TNC->SyncSupported == FALSE && TNC->UseAPPLCallsforPactor && TNC->TimeScanLocked == 0)	
+								TNC->TimeScanLocked = time(NULL);
+
+							if (TNC->RIG->RIG_DEBUG)
+								Debugprintf("Scan Debug SCS Pactor TNC refused permission");
+
+						}
+					}
+				}
+				return;
+			}
+		}
+
+		if (Msg[3] == 3)					// Status
+		{			
+			struct STREAMINFO * STREAM = &TNC->Streams[Stream];
+
+			if (strstr(Buffer, "DISCONNECTED") || strstr(Buffer, "LINK FAILURE"))
+			{
+				if ((STREAM->Connecting | STREAM->Connected) == 0)
+					return;
+
+				if (STREAM->Connecting && STREAM->Disconnecting == FALSE)
+				{
+					// Connect Failed
+			
+					buffptr = GetBuff();
+					if (buffptr == 0) return;			// No buffers, so ignore
+
+					buffptr->Len  = sprintf(buffptr->Data, "*** Failure with %s\r", TNC->Streams[Stream].RemoteCall);
+
+					C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr);
+	
+					STREAM->Connecting = FALSE;
+					STREAM->Connected = FALSE;				// In case!
+					STREAM->FramesOutstanding = 0;
+
+					if (Stream == 0)
+					{
+						sprintf(TNC->WEB_TNCSTATE, "In Use by %s", STREAM->MyCall);
+						SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
+					}
+
+					STREAM->ReportDISC = TRUE;		// Tell Node
+					return;
+				}
+					
+				// Must Have been connected or disconnecting - Release Session
+
+				STREAM->Connecting = FALSE;
+				STREAM->Connected = FALSE;		// Back to Command Mode
+				STREAM->FramesOutstanding = 0;
+
+				if (STREAM->Disconnecting == FALSE)
+					STREAM->ReportDISC = TRUE;		// Tell Node
+
+				STREAM->Disconnecting = FALSE;
+				return;
+			}
+
+			if (strstr(Buffer, "CONNECTED"))
+			{
+				char * Call = strstr(Buffer, " to ");
+				char * ptr;
+				char MHCall[30];
+
+				// Do we need to protect against 2nd call in Dragon Single Mode???
+
+				Call += 4;
+
+				if (Call[1] == ':')
+					Call +=2;
+
+				ptr = strchr(Call, ' ');	
+				if (ptr) *ptr = 0;
+
+				ptr = strchr(Call, 13);	
+				if (ptr) *ptr = 0;
+
+				STREAM->Connected = TRUE;			// Subsequent data to data channel
+				STREAM->Connecting = FALSE;
+				STREAM->ConnectTime = time(NULL); 
+				STREAM->BytesRXed = STREAM->BytesTXed = 0;
+
+				//	Stop Scanner
+
+				if (Stream == 0 || TNC->HFPacket)
+				{
+					TNC->SwitchToPactor = 0;						// Cancel any RP to Pactor switch
+
+					sprintf(Status, "%d SCANSTOP", TNC->Port);
+					Rig_Command((TRANSPORTENTRY *) -1, Status);
+
+					SuspendOtherPorts(TNC);			// Prevent connects on other ports in same scan gruop
+
+					memcpy(MHCall, Call, 9);
+					MHCall[9] = 0;
+				}
+
+				if (TNC->PortRecord->ATTACHEDSESSIONS[Stream] == 0)
+				{
+					// Incoming Connect
+
+					TNC->SessionTimeLimit = TNC->DefaultSessionTimeLimit;		// Reset Limit
+			
+					// Check for ExcludeList
+
+					if (ExcludeList[0])
+					{
+						UCHAR AXCALL[7];
+						
+						ConvToAX25(MHCall, AXCALL);			//Permitted calls are stored in ax.25 format
+
+						if (CheckExcludeList(AXCALL) == FALSE)
+						{
+							TidyClose(TNC, Stream);
+							sprintf(Status, "%d SCANSTART 15", TNC->Port);
+							Rig_Command((TRANSPORTENTRY *) -1, Status);
+							Debugprintf("SCS Call from %s rejected", MHCall);
+							return;
+						}
+					}
+
+					//	IF WE HAVE A PERMITTED CALLS LIST, SEE IF HE IS IN IT
+
+					if (TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS)
+					{
+						UCHAR * ptr = TNC->PortRecord->PORTCONTROL.PERMITTEDCALLS;
+						UCHAR AXCALL[7];
+						
+						ConvToAX25(MHCall, AXCALL);			//Permitted calls are stored in ax.25 format
+
+						while (TRUE)
+						{
+							if (memcmp(AXCALL, ptr, 6) == 0)	// Ignore SSID
+								break;
+
+							ptr += 7;
+
+							if ((*ptr) == 0)							// Not in list
+							{
+								char Status[64];
+
+								TidyClose(TNC, 0);
+								sprintf(Status, "%d SCANSTART 15", TNC->Port);
+								Rig_Command((TRANSPORTENTRY *) -1, Status);
+								Debugprintf("Pactor Call from %s not in ValidCalls - rejected", Call);
+								return;
+							}
+						}
+					}
+
+					// Check that we think we are in the right mode
+
+					if (Stream == 0 && TNC->Dragon == 0)	// Dragon runs both at the same time
+					{
+						if (TNC->HFPacket && RealStream == 31)
+						{
+							Debugprintf("Incoming Pactor Call while in Packet Mode");
+							TNC->HFPacket = FALSE;
+							STREAM->DEDStream = 31;
+						}
+						else
+						if (TNC->HFPacket == 0 && RealStream == 30)
+						{
+							Debugprintf("Incoming Packet Call while in Pactor Mode");
+							TNC->HFPacket = TRUE;
+							STREAM->DEDStream = 30;
+						}
+					}
+
+					if (TNC->HFPacket)
+					{
+						char Save = TNC->RIG->CurrentBandWidth;
+						TNC->RIG->CurrentBandWidth = 'R';
+						UpdateMH(TNC, MHCall, '+', 'I');
+						TNC->RIG->CurrentBandWidth = Save;
+					}
+
+					memcpy(STREAM->RemoteCall, Call, 9);	// Save Text Callsign
+
+					//	We need to check what MYCALL is set to, either in case
+					//	Appl Scan has failed to change the callsign or if a
+					//	Packet Call to MYALIAS
+
+					STREAM->CmdSet = STREAM->CmdSave = malloc(100);
+					sprintf(STREAM->CmdSet, "I\r");
+
+					STREAM->CheckingCall = TRUE;
+					return;
+				}
+				else
+				{
+					// Connect Complete
+			
+					buffptr = GetBuff();
+					if (buffptr == 0) return;			// No buffers, so ignore
+
+					buffptr->Len  = sprintf(buffptr->Data, "*** Connected to %s\r", Call);;
+
+					C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr);
+
+					if (Stream == 0)
+					{
+						if (TNC->RIG)
+							sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Outbound Freq %s", STREAM->MyCall, STREAM->RemoteCall, TNC->RIG->Valchar);
+						else
+							sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Outbound", STREAM->MyCall, STREAM->RemoteCall);
+
+						SetWindowText(TNC->xIDC_TNCSTATE, TNC->WEB_TNCSTATE);
+
+						if (STREAM->DEDStream == 30)	// Robust Mode
+						{
+							char Save = TNC->RIG->CurrentBandWidth;
+							TNC->RIG->CurrentBandWidth = 'R';
+							UpdateMH(TNC, Call, '+', 'O');
+							TNC->RIG->CurrentBandWidth = Save;
+						}
+						else
+						{
+							UpdateMH(TNC, Call, '+', 'O');
+						}
+					}
+					return;
+				}
+			}
+			return;
+		}
+
+		if (Msg[3] == 4 || Msg[3] == 5)
+		{
+			struct STREAMINFO * STREAM = &TNC->Streams[1];		// RP Stream
+
+			// Monitor
+
+			if ((TNC->HFPacket || TNC->DragonSingle) && TNC->UseAPPLCalls && strstr(&Msg[4], "SABM") && STREAM->Connected == FALSE)
+			{
+				// See if a call to Nodecall or one of our APPLCALLS - if so, stop scan and switch MYCALL
+
+				char DestCall[10] = "NOCALL  ";
+				char * ptr1 = strstr(&Msg[7], "to ");
+				int i;
+				APPLCALLS * APPL;
+				char Appl[11];
+				char Status[80];
+
+				if (ptr1) memcpy(DestCall, &ptr1[3], 10);
+				
+				ptr1 = strchr(DestCall, ' ');
+				if (ptr1) *(ptr1) = 0;					// Null Terminate
+
+				Debugprintf("RP SABM Received for %s" , DestCall);
+
+				if (strcmp(TNC->NodeCall, DestCall) != 0)
+				{
+					// Not Calling NodeCall/Portcall
+
+					if (strcmp(NodeCall, DestCall) == 0)
+						goto SetThisCall;
+
+					// See if to one of our ApplCalls
+
+					for (i = 0; i < 32; i++)
+					{
+						APPL=&APPLCALLTABLE[i];
+
+						if (APPL->APPLCALL_TEXT[0] > ' ')
+						{
+							char * ptr;
+							memcpy(Appl, APPL->APPLCALL_TEXT, 10);
+							ptr=strchr(Appl, ' ');
+
+							if (ptr) *ptr = 0;
+
+							if (strcmp(Appl, DestCall) == 0)
+							{
+						SetThisCall:
+								Debugprintf("RP SABM is for NODECALL or one of our APPLCalls - setting MYCALL to %s and pausing scan", DestCall);
+
+								sprintf(Status, "%d SCANSTART 30", TNC->Port);
+								Rig_Command((TRANSPORTENTRY *) -1, Status);
+								TNC->SwitchToPactor = 0;		// Stay in RP
+				
+								strcpy(STREAM->MyCall, DestCall);
+								STREAM->CmdSet = STREAM->CmdSave = malloc(100);
+								sprintf(STREAM->CmdSet, "I%s\r", DestCall);
+								TNC->InternalCmd = TRUE;
+								
+								break;
+							}
+						}
+					}
+				}
+			}
+
+			DoMonitor(TNC, &Msg[3], framelen - 3);
+			return;
+
+		}
+
+		// 1, 2, 4, 5 - pass to Appl
+
+		buffptr = GetBuff();
+
+		if (buffptr == NULL) return;			// No buffers, so ignore
+
+		buffptr->Len = sprintf(buffptr->Data,"Pactor} %s", &Msg[4]);
+
+		OpenLogFile(TNC->Port);
+		WriteLogLine(TNC->Port, &Msg[4], (int)strlen(&Msg[4]));
+		CloseLogFile(TNC->Port);
+
+		C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr);
+
+		return;
+	}
+
+	if (Msg[3] == 6)
+	{
+		// Monitor Data With length)
+
+		DoMonitor(TNC, &Msg[3], framelen - 3);
+		return;
+	}
+
+	if (Msg[3] == 7)
+	{
+		char StatusMsg[60];
+		int Status, ISS, Offset;
+		
+		if (Msg[2] == 0xfe)						// Status Poll Response
+		{
+			int PactorLevel = Msg[6] & 7;		// Pactor Level 1-4
+			
+			if (TNC->MinLevelTimer)
+			{
+				if (PactorLevel >= TNC->MinLevel)
+				{
+					Debugprintf("Reached MIN Pactor Level");
+					TNC->MinLevelTimer = 0;
+				}
+				else
+					Debugprintf("Still waiting for Min Level Now %d Need %d", PactorLevel, TNC->MinLevel);
+			}
+
+			Status = Msg[5];
+			
+			TNC->Streams[0].PTCStatus0 = Status;
+			TNC->Streams[0].PTCStatus1 = PactorLevel;		// Pactor Level 1-4
+			TNC->Streams[0].PTCStatus2 = Msg[7];			// Speed Level
+			Offset = Msg[8];
+
+			if (Offset > 128)
+				Offset -= 128;
+
+			TNC->Streams[0].PTCStatus3 = Offset; 
+
+			TNC->Mode = (Status >> 4) & 7;
+			ISS = Status & 8;
+			Status &= 7;
+
+			if (TNC->PTCStatus != Status)		// Changed
+			{
+				Debugprintf("SCS status changed, now %s", status[Status]);
+
+				if (Status == 6)		// SYNCH
+				{
+					// New Sync
+
+					if (TNC->RIG->RIG_DEBUG)
+						Debugprintf("SCS New SYNC Detected");
+	
+					TNC->TimeEnteredSYNCMode = time(NULL);
+					TNC->SyncSupported = TRUE;
+				}
+				else
+				{
+					if (TNC->PTCStatus == 6)
+					{
+						if (TNC->RIG->RIG_DEBUG)
+							Debugprintf("SCS left SYNC, now %s", status[Status]);
+	
+						TNC->TimeEnteredSYNCMode = 0;
+					}
+				}
+				TNC->PTCStatus = Status;
+			}
+			sprintf(StatusMsg, "%x %x %x %x", TNC->Streams[0].PTCStatus0,
+				TNC->Streams[0].PTCStatus1, TNC->Streams[0].PTCStatus2, TNC->Streams[0].PTCStatus3);
+			
+			if (ISS)
+			{
+				SetWindowText(TNC->xIDC_TXRX, "Sender");
+				strcpy(TNC->WEB_TXRX, "Sender"); 
+			}
+			else
+			{
+				SetWindowText(TNC->xIDC_TXRX, "Receiver");
+				strcpy(TNC->WEB_TXRX, "Receiver"); 
+			}
+
+			SetWindowText(TNC->xIDC_STATE, status[Status]);
+			strcpy(TNC->WEB_STATE, status[Status]);
+			SetWindowText(TNC->xIDC_MODE, ModeText[TNC->Mode]);
+			strcpy(TNC->WEB_MODE, ModeText[TNC->Mode]);
+
+			if (TNC->Mode == 7)
+				TNC->Busy = TNC->BusyHold * 10;				// BusyHold  delay
+
+			if (Offset == 128)		// Undefined
+				sprintf(StatusMsg, "Mode %s Speed Level %d Freq Offset Unknown",
+					PactorLevelText[TNC->Streams[0].PTCStatus1], Msg[7]);
+			else
+				sprintf(StatusMsg, "Mode %s Speed Level %d Freq Offset %d",
+					PactorLevelText[TNC->Streams[0].PTCStatus1], Msg[7], Offset);
+
+			strcpy(TNC->WEB_PACTORLEVEL, StatusMsg);
+			SetWindowText(TNC->xIDC_PACTORLEVEL, StatusMsg);
+
+			return;
+		}
+	
+		if (Msg[2] == 248)	// Log Message
+		{
+			// Monitor Data - Length format
+			// first 4 bytes contain a 32 bits long timestamp.
+			// That timestamp holds the number of seconds that elapsed since date 01.01.2000 at 00:00:00.
+			// The MS byte is sent first. The timestamp can be corrected to the usual C timestamp (seconds
+			//since 01.01.1970, 00:00:00) simply by adding 946684800 (seconds) to it.
+			// Teminated with LF
+
+			int datalen = Msg[4] + 1;
+			unsigned int timestamp = (Msg[5] << 24) + (Msg[6] << 16)
+				+ (Msg[6] << 8) + Msg[7] + 946684800;
+
+			Msg[5 + datalen] = 0;
+			Debugprintf("SCS Debug %s", &Msg[9]);
+			return;
+		}
+
+		if (Msg[2] == 253)						// Rig Port Response
+		{
+			// Queue for Rig Control Driver
+			
+			int datalen = Msg[4] + 1;
+			PMSGWITHLEN buffptr;
+
+			// if not configured to use PTC Rig Control, Ignore
+
+			if (TNC->RIG->PORT == NULL || TNC->RIG->PORT->PTC == NULL)
+				return;
+			
+			buffptr = GetBuff();
+
+			if (buffptr)
+			{
+				buffptr->Len = datalen;
+				memcpy(buffptr->Data, &Msg[5], datalen);
+				C_Q_ADD(&TNC->RadiotoBPQ_Q, buffptr);
+				if (TNC->RIG->RIG_DEBUG)
+				{
+					Debugprintf("SCS RIG frame received, len %d", datalen);
+					Debugprintf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
+						Msg[5], Msg[6], Msg[7], Msg[8], Msg[9], Msg[10], Msg[11], Msg[12],
+						Msg[13], Msg[14], Msg[15], Msg[16], Msg[17], Msg[18], Msg[19], Msg[20]);
+		
+				}
+			}
+			return;
+		}
+
+		// Connected Data
+		
+		buffptr = GetBuff();
+
+		if (buffptr == NULL) return;			// No buffers, so ignore
+			
+		buffptr->Len = Msg[4] + 1;				// Length
+		TNC->Streams[Stream].BytesRXed += (int)buffptr->Len;
+		memcpy(buffptr->Data, &Msg[5], buffptr->Len);
+
+		WritetoTrace(TNC, &Msg[5], (int)buffptr->Len);
+
+		C_Q_ADD(&TNC->Streams[Stream].PACTORtoBPQ_Q, buffptr);
+
+		return;
+	}
+}
+
+int GetPTCRadioCommand(struct TNCINFO * TNC, char * Block)
+{
+	PMSGWITHLEN buffptr;
+	int Length;
+
+	if (TNC->RadiotoBPQ_Q == 0)
+		return 0;
+
+	buffptr = Q_REM(&TNC->RadiotoBPQ_Q);
+
+	Length = (int)buffptr->Len;
+		
+	memcpy(Block, buffptr->Data, Length);
+		
+	ReleaseBuffer(buffptr);
+
+//	Debugprintf("SCS Rig Command Queued");
+
+	return Length;;
+}
+
+int SendPTCRadioCommand(struct TNCINFO * TNC, char * Block, int Length)
+{
+	PMSGWITHLEN buffptr;
+
+	if (TNC->TNCOK || (TNC->Hardware == H_ARDOP && TNC->ARDOPCommsMode == 'T'))
+	{
+	}
+	else
+		return 0;
+
+	// Queue for TNC
+
+	buffptr = GetBuff();
+
+	if (buffptr == 0) return (0);			// No buffers, so ignore
+
+	buffptr->Len = Length;
+		
+	memcpy(buffptr->Data, Block, Length);
+		
+	C_Q_ADD(&TNC->BPQtoRadio_Q, buffptr);
+
+   return 0;
+
+}
+
+static MESSAGE Monframe;		// I frames come in two parts.
+
+#define TIMESTAMP 352
+
+MESSAGE * AdjMsg = &Monframe;	// Adjusted for digis
+
+static VOID DoMonitor(struct TNCINFO * TNC, UCHAR * Msg, int Len)
+{
+	// Convert to ax.25 form and pass to monitor
+
+	UCHAR * ptr, * starptr;
+	char * context;
+	char * MHCall = Monframe.ORIGIN;
+
+
+	if (Msg[0] == 6)		// Second part of I or UI
+	{
+		int len = Msg[1] +1;
+
+		memcpy(AdjMsg->L2DATA, &Msg[2], len);
+		Monframe.LENGTH += len;
+
+		time(&Monframe.Timestamp);
+
+		BPQTRACE((MESSAGE *)&Monframe, TRUE);
+		return;
+	}
+
+	Monframe.LENGTH = MSGHDDRLEN + 16;			// Control Frame
+
+	Monframe.PORT = TNC->Port;
+	
+	AdjMsg = &Monframe;					// Adjusted for digis
+	ptr = strstr(Msg, "fm ");
+
+	ConvToAX25(&ptr[3], Monframe.ORIGIN);
+
+	ptr = strstr(ptr, "to ");
+
+	ConvToAX25(&ptr[3], Monframe.DEST);
+
+	ptr = strstr(ptr, "via ");
+
+	if (ptr)
+	{
+		// We have digis
+
+		char Save[100];
+		char * fiddle;
+
+		memcpy(Save, &ptr[4], 60);
+
+		ptr = strtok_s(Save, " ", &context);
+DigiLoop:
+		fiddle = (char *)AdjMsg;
+		fiddle += 7;
+		AdjMsg = (MESSAGE *)fiddle;
+
+		Monframe.LENGTH += 7;
+
+		starptr = strchr(ptr, '*');
+		if (starptr)
+			*(starptr) = 0;
+
+		ConvToAX25(ptr, AdjMsg->ORIGIN);
+
+		if (starptr)
+			AdjMsg->ORIGIN[6] |= 0x80;				// Set end of address
+
+		ptr = strtok_s(NULL, " ", &context);
+
+		if (memcmp(ptr, "ctl", 3))
+			goto DigiLoop;
+	}
+
+	AdjMsg->ORIGIN[6] |= 1;				// Set end of address
+
+	ptr = strstr(Msg, "ctl ");
+
+	if (memcmp(&ptr[4], "SABM", 4) == 0)
+	{
+		AdjMsg->CTL = 0x2f;
+		UpdateMHwithDigis(TNC, MHCall, '.', 0);
+	}
+	else  
+	if (memcmp(&ptr[4], "DISC", 4) == 0)
+		AdjMsg->CTL = 0x43;
+	else 
+	if (memcmp(&ptr[4], "UA", 2) == 0)
+	{
+		AdjMsg->CTL = 0x63;
+		UpdateMHwithDigis(TNC, MHCall, '.', 0);
+	}
+	else  
+	if (memcmp(&ptr[4], "DM", 2) == 0)
+		AdjMsg->CTL = 0x0f;
+	else 
+	if (memcmp(&ptr[4], "UI", 2) == 0)
+	{
+		AdjMsg->CTL = 0x03;
+		UpdateMHwithDigis(TNC, MHCall, '.', 0);
+	}
+	else 
+	if (memcmp(&ptr[4], "RR", 2) == 0)
+		AdjMsg->CTL = 0x1 | (ptr[6] << 5);
+	else 
+	if (memcmp(&ptr[4], "RNR", 3) == 0)
+		AdjMsg->CTL = 0x5 | (ptr[7] << 5);
+	else 
+	if (memcmp(&ptr[4], "REJ", 3) == 0)
+		AdjMsg->CTL = 0x9 | (ptr[7] << 5);
+	else 
+	if (memcmp(&ptr[4], "FRMR", 4) == 0)
+		AdjMsg->CTL = 0x87;
+	else  
+	if (ptr[4] == 'I')
+	{
+		AdjMsg->CTL = (ptr[5] << 5) | (ptr[6] & 7) << 1 ;
+	}
+
+	if (strchr(&ptr[4], '+'))
+	{
+		AdjMsg->CTL |= 0x10;
+		Monframe.DEST[6] |= 0x80;				// SET COMMAND
+	}
+
+	if (strchr(&ptr[4], '-'))	
+	{
+		AdjMsg->CTL |= 0x10;
+		Monframe.ORIGIN[6] |= 0x80;				// SET COMMAND
+	}
+
+	if (Msg[0] == 5)							// More to come
+	{
+		ptr = strstr(ptr, "pid ");	
+		sscanf(&ptr[3], "%x", (int *)&AdjMsg->PID);
+		return;	
+	}
+
+	time(&Monframe.Timestamp);
+
+	BPQTRACE((MESSAGE *)&Monframe, TRUE);
+
+}
+//1:fm G8BPQ to KD6PGI-1 ctl I11^ pid F0
+//fm KD6PGI-1 to G8BPQ ctl DISC+
+
+VOID TidyClose(struct TNCINFO * TNC, int Stream)
+{
+	// Queue it as we may have just sent data
+
+	TNC->Streams[Stream].CmdSet = TNC->Streams[Stream].CmdSave = malloc(100);
+	sprintf(TNC->Streams[Stream].CmdSet, "D\r");
+}
+
+
+VOID ForcedClose(struct TNCINFO * TNC, int Stream)
+{
+	// Sending D twice should do a "Dirty Disconnect"
+
+	// Try thst first. If it still doesn't disconnect maybe try restart
+
+	unsigned char Resp[500] = "";
+	char * Poll = &TNC->TXBuffer[0]; 
+
+	Debugprintf("Failed to disconnect TNC - trying a forced disconnect");
+
+	// Try Normal Mode DD (Dirty Disconnect)
+					
+	// Uses "Hidden" feature where you can send any normal mode command
+	// in host mode by preceeding with a #
+
+	Poll[2] = 31;
+	Poll[3] = 0x1;
+	Poll[4] = 2;
+	sprintf(&Poll[5], "#DD\r");		// Node \r isn't sent but is there for log
+	CRCStuffAndSend(TNC, Poll, 8);
+			
+	// It looks like there isn't a response
+
+	TNC->Timeout = 0;	
+
+	OpenLogFile(TNC->Port);
+	WriteLogLine(TNC->Port, &Poll[5], 4);
+	CloseLogFile(TNC->Port);
+
+/*
+	Poll[2] = 31;
+	Poll[3] = 1;
+	Poll[4] = 0;
+	Poll[5] = 'D';
+
+	CRCStuffAndSend(TNC, Poll, 6);
+
+	// Wait for response before sending another
+
+	n = 0;
+	while (CheckRXHost(TNC, Resp) == FALSE)
+	{
+		Sleep(5);
+		n++;
+		if (n > 100) break;
+	}
+
+	Poll[2] = 31;
+	Poll[3] = 1;
+	Poll[4] = 0;
+	Poll[5] = 'D';
+
+	CRCStuffAndSend(TNC, Poll, 6);
+
+	n = 0;
+	while (CheckRXHost(TNC, Resp) == FALSE)
+	{
+		Sleep(5);
+		n++;
+		if (n > 100) break;
+	}
+
+	// See if it worked
+
+	Poll[2] = 254;			// Channel
+	Poll[3] = 0x1;			// Command
+	Poll[4] = 1;			// Len-1
+	Poll[5] = 'G';			// Extended Status Poll
+	Poll[6] = '3';
+
+	CRCStuffAndSend(TNC, Poll, 7);
+	
+	n = 0;
+	while (CheckRXHost(TNC, Resp) == FALSE)
+	{
+		Sleep(5);
+		n++;
+		if (n > 100) break;
+	}
+
+	Debugprintf("PTC Status Now %x %x %x %x %x %x %x %x",
+		Resp[0], Resp[1], Resp[2], Resp[3], Resp[4], Resp[5], Resp[6], Resp[7]); 
+
+	TNC->Timeout = 0;
+
+	return;
+
+	// Maybe best just to restart the TNC
+
+	if (TNC->PacketChannels == 0)		// Not using packet
+	{
+		Debugprintf("Forced Disconnect Failed - restarting TNC");
+
+		// Ensure in Pactor
+
+		if(TNC->Dragon == 0)
+		{
+			TNC->TXBuffer[2] = 31;
+			TNC->TXBuffer[3] = 0x1;
+			TNC->TXBuffer[4] = 0x1;
+			memcpy(&TNC->TXBuffer[5], "PT", 2);
+
+			CRCStuffAndSend(TNC, TNC->TXBuffer, 7);
+
+			n = 0;
+			while (CheckRXHost(TNC, Resp) == FALSE)
+			{
+				Sleep(5);
+				n++;
+				if (n > 100) break;
+			}
+		}
+
+		Sleep(50);
+		ExitHost(TNC);
+		Sleep(50);
+
+		n = 0;
+		while (CheckRXHost(TNC, Resp) == FALSE)
+		{
+			Sleep(5);
+			n++;
+			if (n > 100) break;
+		}
+
+		TNC->Timeout = 0;
+		TNC->HostMode = FALSE;
+		TNC->ReinitState = 0;
+
+		return;
+	}
+*/
+}
+
+VOID CloseComplete(struct TNCINFO * TNC, int Stream)
+{
+	char Status[80];
+	struct STREAMINFO * STREAM = &TNC->Streams[Stream];
+
+	Debugprintf("SCS Pactor Close Complete - Stream = %d", Stream);
+
+	STREAM->CmdSet = STREAM->CmdSave = malloc(100);
+
+	strcpy(STREAM->MyCall, TNC->NodeCall);
+
+	if (Stream == 0 || TNC->HFPacket)
+	{
+		SetWindowText(TNC->xIDC_TNCSTATE, "Free");
+		strcpy(TNC->WEB_TNCSTATE, "Free");
+		sprintf(Status, "%d SCANSTART 15", TNC->Port);
+		Rig_Command((TRANSPORTENTRY *) -1, Status);
+
+		if (TNC->Dragon)
+		{
+			sprintf(STREAM->CmdSet, "I%s\r", TNC->NodeCall);
+			TNC->Streams[0].DEDStream = 31;		// Pactor Channel
+		}
+		else
+		{
+			if (TNC->HFPacket)
+			{
+				sprintf(STREAM->CmdSet, "I%s\rPR\r", TNC->NodeCall);
+				TNC->Streams[0].DEDStream = 30;		// Packet Channel
+				Debugprintf("BPQ32 Session Closed - switch to Packet");
+			}
+			else
+			{
+				sprintf(STREAM->CmdSet, "I%s\rPT\r", TNC->NodeCall);
+				TNC->Streams[0].DEDStream = 31;		// Pactor Channel
+				Debugprintf("BPQ32 Session Closed - switch to Pactor");
+			}
+		}
+		ReleaseOtherPorts(TNC);
+	}
+	else
+		sprintf(STREAM->CmdSet, "I%s\r", TNC->NodeCall);
+
+	Debugprintf("SCS Pactor CMDSet = %s", STREAM->CmdSet);
+
+}
+
+VOID PTCSuspendPort(struct TNCINFO * TNC, struct TNCINFO * ThisTNC)
+{
+	struct STREAMINFO * STREAM = &TNC->Streams[0];
+
+	STREAM->CmdSet = STREAM->CmdSave = zalloc(100);
+	sprintf(STREAM->CmdSet, "I%s\r", "SCSPTC");		// Should prevent connects
+
+	Debugprintf("SCS Pactor CMDSet = %s", STREAM->CmdSet);
+}
+
+VOID PTCReleasePort(struct TNCINFO * TNC)
+{
+	struct STREAMINFO * STREAM = &TNC->Streams[0];
+
+	STREAM->CmdSet = STREAM->CmdSave = zalloc(100);
+
+	if (TNC->UseAPPLCallsforPactor && TNC->RIG && TNC->RIG != &TNC->DummyRig 
+			&& TNC->RIG->FreqPtr[0]->APPLCALL[0])
+		sprintf(STREAM->CmdSet, "I%s\r", TNC->RIG->FreqPtr[0]->APPLCALL);
+	else
+		sprintf(STREAM->CmdSet, "I%s\r", TNC->NodeCall);
+
+	Debugprintf("SCS Pactor CMDSet = %s", STREAM->CmdSet);
+}
+
+
+
diff --git a/TelnetV6.c b/TelnetV6.c
index a80a325..b139fad 100644
--- a/TelnetV6.c
+++ b/TelnetV6.c
@@ -3882,8 +3882,8 @@ MsgLoop:
 			
 			if (strlen(MsgPtr) > 64)
 			{
-				Debugprintf("Telnet Bad User Name %s", MsgPtr);
 				MsgPtr[64] = 0;
+				Debugprintf("Telnet Bad User Name %s", MsgPtr);
 			}
 
 			sprintf(logmsg,"%d %s User=%s\n", sockptr->Number, Addr, MsgPtr);
@@ -3958,8 +3958,8 @@ MsgLoop:
 						
 			if (strlen(MsgPtr) > 64)
 			{
+				MsgPtr[64] = 0;	
 				Debugprintf("Telnet Bad Password %s", MsgPtr);
-				MsgPtr[64] = 0;
 			}
 
 
@@ -4757,8 +4757,8 @@ MsgLoop:
 						
 			if (strlen(MsgPtr) > 64)
 			{
-				Debugprintf("Telnet Bad User Name %s", MsgPtr);
 				MsgPtr[64] = 0;
+				Debugprintf("Telnet Bad User Name %s", MsgPtr);
 			}
 
 			sprintf(logmsg,"%d %s User=%s\n", sockptr->Number, Addr, MsgPtr);
@@ -4841,8 +4841,8 @@ MsgLoop:
 						
 			if (strlen(MsgPtr) > 64)
 			{
+				MsgPtr[64] = 0;	
 				Debugprintf("Telnet Bad Password %s", MsgPtr);
-				MsgPtr[64] = 0;
 			}
 
 			sprintf(logmsg,"%d %s Password=%s\n", sockptr->Number, Addr, MsgPtr);
diff --git a/Versions.h b/Versions.h
index ebcdca1..38a03fb 100644
--- a/Versions.h
+++ b/Versions.h
@@ -10,8 +10,8 @@
 
 #endif
 
-#define KVers 6,0,24,34
-#define KVerstring "6.0.24.34\0"
+#define KVers 6,0,24,38
+#define KVerstring "6.0.24.38\0"
 
 #ifdef CKernel
 
diff --git a/WinRPRHelper.vcproj.NOTTSDESKTOP.John.user b/WinRPRHelper.vcproj.NOTTSDESKTOP.John.user
new file mode 100644
index 0000000..fa82c00
--- /dev/null
+++ b/WinRPRHelper.vcproj.NOTTSDESKTOP.John.user
@@ -0,0 +1,65 @@
+
+
+	
+		
+			
+		
+		
+			
+		
+	
+
diff --git a/WinmorControl.vcproj.NOTTSDESKTOP.John.user b/WinmorControl.vcproj.NOTTSDESKTOP.John.user
new file mode 100644
index 0000000..fa82c00
--- /dev/null
+++ b/WinmorControl.vcproj.NOTTSDESKTOP.John.user
@@ -0,0 +1,65 @@
+
+
+	
+		
+			
+		
+		
+			
+		
+	
+
diff --git a/asmstrucs.h b/asmstrucs.h
index 1b56291..70696b5 100644
--- a/asmstrucs.h
+++ b/asmstrucs.h
@@ -903,6 +903,8 @@ typedef struct _LINKTABLE
 
 	VOID *	L2FRAG_Q;		// DEFRAGMENTATION QUEUE
 
+	int		IFrameRetryCounter;	// Number of times an I frame in repeated without a frame being acked 
+
 } LINKTABLE;
 
 #pragma pack(1)
diff --git a/config.c b/config.c
index 74473ce..4c2c3fb 100644
--- a/config.c
+++ b/config.c
@@ -1,6 +1,5 @@
 /*
 Copyright 2001-2022 John Wiseman G8BPQ
-
 This file is part of LinBPQ/BPQ32.
 
 LinBPQ/BPQ32 is free software: you can redistribute it and/or modify
diff --git a/rigcontrol.h b/rigcontrol.h
index 1f841cf..eeda8f6 100644
--- a/rigcontrol.h
+++ b/rigcontrol.h
@@ -214,8 +214,8 @@ struct RIGPORTINFO
 {
 	int PortType;				// ICOM, Yaesu, Etc
 	int YaesuVariant;			// Yaesu seems to have lots of incompatible subtypes
-	char IOBASE[80];
-	char PTTIOBASE[80];			// Port for Hardware PTT - may be same as control port.
+	char IOBASE[256];
+	char PTTIOBASE[256];			// Port for Hardware PTT - may be same as control port.
 	int SPEED;
 	char * HIDDevice; 
 	struct RIGINFO Rigs[10];	// Rigs off a port