From fa1aee0f75510f884846c6a977a5fe7b9f33d37f Mon Sep 17 00:00:00 2001
From: Rob Swindell <rob@synchro.net>
Date: Tue, 8 Feb 2022 00:05:21 -0800
Subject: [PATCH] Allow ByteSize and StopBits to be configured

in sexpots.ini [COM] section(s).

Fixed bug where Parity was only initially set (in sexpots) if BaudRate was non-zero.
---
 src/comio/comio.h       |  5 +----
 src/comio/comio_nix.c   | 33 +++++++++++++++++++++++++++++++++
 src/comio/comio_win32.c | 13 +++++++++++++
 src/sexpots/sexpots.c   | 30 +++++++++++++++++++++---------
 4 files changed, 68 insertions(+), 13 deletions(-)

diff --git a/src/comio/comio.h b/src/comio/comio.h
index 47a650302c..00efdd21d4 100644
--- a/src/comio/comio.h
+++ b/src/comio/comio.h
@@ -1,9 +1,5 @@
-/* comio.h */
-
 /* Synchronet Serial Communications (COM) I/O Library */
 
-/* $Id: comio.h,v 1.15 2020/06/26 19:56:48 rswindell Exp $ */
-
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
@@ -136,6 +132,7 @@ COMIOEXPORT size_t		comReadLine(COM_HANDLE, char* buf, size_t buflen
 COMIOEXPORT BOOL		comPurgeInput(COM_HANDLE);
 COMIOEXPORT BOOL		comPurgeOutput(COM_HANDLE);
 COMIOEXPORT BOOL		comSetParity(COM_HANDLE, BOOL enable, BOOL odd);
+COMIOEXPORT BOOL		comSetBits(COM_HANDLE, size_t byteSize, size_t stopBits);
 
 #if defined(__cplusplus)
 }
diff --git a/src/comio/comio_nix.c b/src/comio/comio_nix.c
index eb96c7ce90..0d03aeee80 100644
--- a/src/comio/comio_nix.c
+++ b/src/comio/comio_nix.c
@@ -360,6 +360,39 @@ BOOL comSetParity(COM_HANDLE handle, BOOL enable, BOOL odd)
     return TRUE;
 }
 
+BOOL comSetBits(COM_HANDLE handle, size_t byteSize, size_t stopBits)
+{
+    struct termios t;
+
+    if(tcgetattr(handle, &t)==-1)
+        return FALSE;
+
+	t.c_cflag &= ~CSIZE;
+	switch(byteSize) {
+		case 5:
+			t.c_cflag |= CS5;
+			break;
+		case 6:
+			t.c_cflag |= CS6;
+			break;
+		case 7:
+			t.c_cflag |= CS7;
+			break;
+		default:
+			t.c_cflag |= CS8;
+			break;
+	}
+	if(stopBits == 2)
+		t.c_cflag |= CSTOPB;
+	else
+		t.c_cflag &= ~CSTOPB;
+
+    if(tcsetattr(handle, TCSANOW, &t)==-1)
+        return FALSE;
+
+    return TRUE;
+}
+
 int comGetModemStatus(COM_HANDLE handle)
 {
     int status;
diff --git a/src/comio/comio_win32.c b/src/comio/comio_win32.c
index 0b171157ec..24a5c1b34e 100644
--- a/src/comio/comio_win32.c
+++ b/src/comio/comio_win32.c
@@ -170,6 +170,19 @@ BOOL comSetParity(COM_HANDLE handle, BOOL enable, BOOL odd)
 	return SetCommState(handle, &dcb);
 }
 
+BOOL comSetBits(COM_HANDLE handle, size_t byteSize, size_t stopBits)
+{
+	DCB dcb;
+
+	if(GetCommState(handle, &dcb) != TRUE)
+		return FALSE;
+
+	dcb.ByteSize = (BYTE)byteSize;
+	dcb.StopBits = stopBits == 2 ? TWOSTOPBITS : ONESTOPBIT;
+
+	return SetCommState(handle, &dcb);
+}
+
 int comGetModemStatus(COM_HANDLE handle)
 {
 	DWORD status=0;
diff --git a/src/sexpots/sexpots.c b/src/sexpots/sexpots.c
index 094b1d48fb..035bea6f93 100644
--- a/src/sexpots/sexpots.c
+++ b/src/sexpots/sexpots.c
@@ -77,6 +77,8 @@ BOOL	com_hangup=TRUE;
 ulong	com_baudrate=0;
 BOOL	com_parity=FALSE;
 BOOL	com_parity_odd=FALSE;
+size_t	com_byte_size=8;
+size_t	com_stop_bits=1;
 BOOL	dcd_ignore=FALSE;
 int		dcd_timeout=10;	/* seconds */
 ulong	dtr_delay=100;	/* milliseconds */
@@ -1396,6 +1398,8 @@ void parse_com_section(const char* section)
 	com_baudrate    = iniGetLongInt(ini, section, "BaudRate", com_baudrate);
 	com_parity		= iniGetBool(ini, section, "Parity", com_parity);
 	com_parity_odd	= iniGetBool(ini, section, "ParityOdd", com_parity_odd);
+	com_byte_size	= iniGetInteger(ini, section, "ByteSize", com_byte_size);
+	com_stop_bits	= iniGetInteger(ini, section, "StopBits", com_stop_bits);
 	com_hangup	    = iniGetBool(ini, section, "Hangup", com_hangup);
 	hangup_attempts = iniGetInteger(ini, section, "HangupAttempts", hangup_attempts);
 	dcd_timeout     = iniGetInteger(ini, section, "DCDTimeout", dcd_timeout);
@@ -1464,6 +1468,21 @@ void parse_ini_file(const char* ini_fname)
 
 }
 
+void com_setup(void)
+{
+	if(com_baudrate!=0) {
+		if(!comSetBaudRate(com_handle,com_baudrate))
+			lprintf(LOG_ERR,"ERROR %u setting DTE rate to %lu bps"
+				,COM_ERROR_VALUE, com_baudrate);
+	}
+	if(!comSetParity(com_handle, com_parity, com_parity_odd))
+		lprintf(LOG_ERR,"ERROR %u setting parity type"
+			,COM_ERROR_VALUE);
+	if(!comSetBits(com_handle, com_byte_size, com_stop_bits))
+		lprintf(LOG_ERR,"ERROR %u setting bits: %u / %u"
+			,COM_ERROR_VALUE, com_byte_size, com_stop_bits);
+}
+
 char	banner[128];
 
 static void 
@@ -1575,14 +1594,7 @@ service_loop(int argc, char** argv)
 	}
 	lprintf(LOG_INFO,"COM Port device handle: %u", com_handle);
 
-	if(com_baudrate!=0) {
-		if(!comSetBaudRate(com_handle,com_baudrate))
-			lprintf(LOG_ERR,"ERROR %u setting DTE rate to %lu bps"
-				,COM_ERROR_VALUE, com_baudrate);
-		if(!comSetParity(com_handle, com_parity, com_parity_odd))
-			lprintf(LOG_ERR,"ERROR %u setting parity type"
-				,COM_ERROR_VALUE);
-	}
+	com_setup();
 
 	lprintf(LOG_INFO,"COM Port DTE rate: %ld bps", comGetBaudRate(com_handle));
 
@@ -1635,7 +1647,7 @@ service_loop(int argc, char** argv)
 				}
 			} else
 				lprintf(LOG_NOTICE, "Timeout (%d seconds) waiting for response to prompt", prompt_timeout);
-			comSetParity(com_handle, com_parity, com_parity_odd);
+			com_setup();
 		}
 		if((sock=connect_socket(host, port)) == INVALID_SOCKET) {
 			comWriteString(com_handle,"\7\r\n!ERROR connecting to TCP port\r\n");
-- 
GitLab