From 3eaf0853fbf5552da2d4f9ecf64da49c374852eb Mon Sep 17 00:00:00 2001 From: Charl Wentzel Date: Fri, 1 Dec 2017 10:56:48 +0200 Subject: [PATCH] Important Update: - SelectableCore: - Move Serial port config params to Port/SerialConfig - Only configure serial port if config setting provided in JSON file - Add SerialConfig param to THandle struct, set when serial config given - Rename method: ConfigureSerialPort() -> SetSerialPortConfig() - New method: GetSerialPortConfig() read serial port config into Handle - Split method SetPortHandle(): - SetPortHandle() - only set port type and address - SetPortHandleSerial() - only set serial port parameters --- SelectableCore.cpp | 203 +++++++++++++++++++++++++++++++++------------ SelectableCore.h | 8 +- 2 files changed, 154 insertions(+), 57 deletions(-) diff --git a/SelectableCore.cpp b/SelectableCore.cpp index 521bf37..f7f5449 100644 --- a/SelectableCore.cpp +++ b/SelectableCore.cpp @@ -66,6 +66,7 @@ CSelectableCore::~CSelectableCore() bool CSelectableCore::LoadConfigData() { TDataMember * TempMember; + TDataMember * SerialConfig; THandle * Handle; char * Type; char * Name; @@ -100,32 +101,35 @@ bool CSelectableCore::LoadConfigData() sprintf( Path, "Address/%s/Address", Name ); Address = (char*)DataTree->GetStr( NULL, Path, Address, true ); // Get address list value } + SetPortHandle( Handle, Address ); - ParityText = (char*)DataTree->GetStr( TempMember, "Port/Parity", "none", true ); - if (!strcasecmp( ParityText, "none" )) - Parity = NO_PARITY; - else if (!strcasecmp( ParityText, "odd" )) - Parity = ODD_PARITY; - else if (!strcasecmp( ParityText, "even" )) - Parity = EVEN_PARITY; - else if (!strcasecmp( ParityText, "mark" )) - Parity = MARK_PARITY; + // Update configuration if specified + if ((SerialConfig = DataTree->GetMember( TempMember, "Port/SerialConfig", false ))) + { + ParityText = (char*)DataTree->GetStr( SerialConfig, "Parity", "none", true ); + if (!strcasecmp( ParityText, "none" )) + Parity = NO_PARITY; + else if (!strcasecmp( ParityText, "odd" )) + Parity = ODD_PARITY; + else if (!strcasecmp( ParityText, "even" )) + Parity = EVEN_PARITY; + else if (!strcasecmp( ParityText, "mark" )) + Parity = MARK_PARITY; - FlowCtrlText = (char*)DataTree->GetStr( TempMember, "Port/FlowCtrl", "none", true ); - if (!strcasecmp( FlowCtrlText, "none" )) - FlowCtrl = NO_FLOWCTRL; - else if (!strcasecmp( FlowCtrlText, "hardware" )) - FlowCtrl = HW_FLOWCTRL; - else if (!strcasecmp( FlowCtrlText, "software" )) - FlowCtrl = SW_FLOWCTRL; + FlowCtrlText = (char*)DataTree->GetStr( SerialConfig, "FlowCtrl", "none", true ); + if (!strcasecmp( FlowCtrlText, "none" )) + FlowCtrl = NO_FLOWCTRL; + else if (!strcasecmp( FlowCtrlText, "hardware" )) + FlowCtrl = HW_FLOWCTRL; + else if (!strcasecmp( FlowCtrlText, "software" )) + FlowCtrl = SW_FLOWCTRL; - SetPortHandle( Handle, Address, - DataTree->GetInt( TempMember, "Port/BaudRate", 19200, true ), - DataTree->GetInt( TempMember, "Port/DataBits", 8, true ), - Parity, - DataTree->GetInt( TempMember, "Port/StopBits", 1, true ), - FlowCtrl, - DataTree->GetInt( TempMember, "Port/DataWait", 0, true)); + Handle->SerialConfig = true; + SetPortHandleSerial( Handle, DataTree->GetInt( SerialConfig, "BaudRate", 19200, true ), + DataTree->GetInt( SerialConfig, "DataBits", 8, true ), + Parity, DataTree->GetInt( SerialConfig, "StopBits", 1, true ), + FlowCtrl, DataTree->GetInt( SerialConfig, "DataWait", 0, true )); + } } else if (!strcasecmp( Type, "TCPserver" )) { @@ -275,8 +279,7 @@ bool CSelectableCore::DestroyHandle( THandle * Handle ) } //--------------------------------------------------------------------------- -bool CSelectableCore::SetPortHandle( THandle * Handle, const char * FileName, - int Baudrate, short DataBits, short Parity, short StopBits, short FlowCtrl, int DataWait ) +bool CSelectableCore::SetPortHandle( THandle * Handle, const char * FileName ) { // Validate if (!Handle || ((Handle->Type != ctNone) && (Handle->Type != ctPort)) || !FileName) { @@ -295,6 +298,19 @@ bool CSelectableCore::SetPortHandle( THandle * Handle, const char * FileName, Handle->Path = (char*)malloc( strlen(FileName)+1 ); strcpy( Handle->Path, FileName ); + // Log event + if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Set as Port [%s]", Name, Handle->Name, FileName ); + return true; +} +//--------------------------------------------------------------------------- + +bool CSelectableCore::SetPortHandleSerial( THandle * Handle, int Baudrate, short DataBits, short Parity, short StopBits, short FlowCtrl, int DataWait ) +{ + // Validate + if (!Handle || (Handle->Type != ctPort)) { + return false; + } + Handle->Baudrate = Baudrate; Handle->DataBits = DataBits; Handle->Parity = Parity; @@ -302,8 +318,6 @@ bool CSelectableCore::SetPortHandle( THandle * Handle, const char * FileName, Handle->FlowCtrl = FlowCtrl; Handle->DataWait = DataWait; - // Log event - if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Set as Port [%s]", Name, Handle->Name, FileName ); return true; } //--------------------------------------------------------------------------- @@ -511,7 +525,12 @@ int CSelectableCore::OpenPort( THandle * Handle ) if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Port opened [%s]", Name, Handle->Name, Handle->Path ); // Update port configuration - ConfigureSerialPort( Handle ); + if (Handle->SerialConfig) + SetSerialPortConfig( Handle ); + else + GetSerialPortConfig( Handle ); + if (Log) Log->Message( LogLevel, dlMedium, "%s: Handle '%s' - Port config, B:%d, D:%d, P:%d, S:%d, F:%d", Name, Handle->Name, + Handle->Baudrate, Handle->DataBits, Handle->Parity, Handle->StopBits, Handle->FlowCtrl ); // Add to Select Lists if (Selector) { @@ -1630,11 +1649,11 @@ bool CSelectableCore::Process() //--------------------------------------------------------------------------- // Set serial port configuration parameters -bool CSelectableCore::ConfigureSerialPort( THandle * Handle ) +bool CSelectableCore::SetSerialPortConfig( THandle * Handle ) { struct termios newtio; int flags = 0; - speed_t _baud = 0; + speed_t baud = 0; int mcs = 0; // Get Handle @@ -1656,38 +1675,38 @@ bool CSelectableCore::ConfigureSerialPort( THandle * Handle ) // Process the baud rate switch (Handle->Baudrate) { - case 921600: _baud = B921600; break; - case 576000: _baud = B576000; break; - case 460800: _baud = B460800; break; - case 230400: _baud = B230400; break; + case 921600: baud = B921600; break; + case 576000: baud = B576000; break; + case 460800: baud = B460800; break; + case 230400: baud = B230400; break; //case 128000: _baud = B128000; break; - case 115200: _baud = B115200; break; + case 115200: baud = B115200; break; //case 76800: _baud = B76800; break; - case 57600: _baud = B57600; break; - case 38400: _baud = B38400; break; + case 57600: baud = B57600; break; + case 38400: baud = B38400; break; //case 28800: _baud = B28800; break; - case 19200: _baud = B19200; break; + case 19200: baud = B19200; break; //case 14400: _baud = B14400; break; - case 9600: _baud = B9600; break; - case 4800: _baud = B4800; break; - case 2400: _baud = B2400; break; - case 1800: _baud = B1800; break; - case 1200: _baud = B1200; break; - case 600: _baud = B600; break; - case 300: _baud = B300; break; - case 200: _baud = B200; break; - case 150: _baud = B150; break; - case 134: _baud = B134; break; - case 110: _baud = B110; break; - case 75: _baud = B75; break; - case 50: _baud = B50; break; + case 9600: baud = B9600; break; + case 4800: baud = B4800; break; + case 2400: baud = B2400; break; + case 1800: baud = B1800; break; + case 1200: baud = B1200; break; + case 600: baud = B600; break; + case 300: baud = B300; break; + case 200: baud = B200; break; + case 150: baud = B150; break; + case 134: baud = B134; break; + case 110: baud = B110; break; + case 75: baud = B75; break; + case 50: baud = B50; break; - default: _baud = B9600; break; + default: baud = B9600; break; } // Set Baud rate - cfsetospeed( &newtio, (speed_t)_baud ); - cfsetispeed( &newtio, (speed_t)_baud ); + cfsetospeed( &newtio, (speed_t)baud ); + cfsetispeed( &newtio, (speed_t)baud ); // Generate Mark/Space parity if ((Handle->DataBits == 7) && ((Handle->Parity == MARK_PARITY) || (Handle->Parity == SPACE_PARITY))) @@ -1775,6 +1794,82 @@ bool CSelectableCore::ConfigureSerialPort( THandle * Handle ) } //--------------------------------------------------------------------------- +// Get serial port configuration parameters +bool CSelectableCore::GetSerialPortConfig( THandle * Handle ) +{ + int speed; + unsigned char bits; + struct termios getTermios; + + // Validate handle + if (!Handle || (Handle->Type != ctPort)) { + return false; + } + + // Get port setup + tcgetattr( Handle->FD, &getTermios ); + + // Get Baud Rate + speed = cfgetispeed( &getTermios ); + switch (speed) + { + case B0 : Handle->Baudrate = 0; break; + case B50 : Handle->Baudrate = 50; break; + case B75 : Handle->Baudrate = 75; break; + case B110 : Handle->Baudrate = 110; break; + case B134 : Handle->Baudrate = 134; break; + case B150 : Handle->Baudrate = 150; break; + case B200 : Handle->Baudrate = 200; break; + case B300 : Handle->Baudrate = 300; break; + case B600 : Handle->Baudrate = 600; break; + case B1200 : Handle->Baudrate = 1200; break; + case B1800: Handle->Baudrate = 1800; break; + case B2400: Handle->Baudrate = 2400; break; + case B4800: Handle->Baudrate = 4800; break; + case B9600: Handle->Baudrate = 9600; break; + case B19200: Handle->Baudrate = 19200; break; + case B38400: Handle->Baudrate = 38400; break; + case B57600: Handle->Baudrate = 57600; break; + case B115200: Handle->Baudrate = 115200; break; + case B230400: Handle->Baudrate = 230400; break; + default: Handle->Baudrate = 999; break; + } + + // Get Data Bits + bits = getTermios.c_cflag & CSIZE; + switch (bits) + { + case CS5: Handle->DataBits = 5; break; + case CS6: Handle->DataBits = 6; break; + case CS7: Handle->DataBits = 7; break; + case CS8: Handle->DataBits = 8; break; + default: Handle->DataBits = 255; break; + } + + // Get Stop Bits + if (getTermios.c_cflag & CSTOPB) + Handle->StopBits = 2; + else + Handle->StopBits = 1; + + // Get Parity + if (getTermios.c_iflag & (PARODD | PARENB)) + Handle->Parity = ODD_PARITY; + else if (getTermios.c_iflag & PARENB) + Handle->Parity = EVEN_PARITY; + else + Handle->Parity = NO_PARITY; + + // Get Flow Control + if (getTermios.c_cflag & CRTSCTS) + Handle->FlowCtrl = true; + else + Handle->FlowCtrl = false; + + return true; +} +//--------------------------------------------------------------------------- + bool CSelectableCore::BuildArgs( const char * ExecPath, int &Count, char * Args[] ) { bool ParamStarted = false; diff --git a/SelectableCore.h b/SelectableCore.h index cda5c6a..d77069e 100644 --- a/SelectableCore.h +++ b/SelectableCore.h @@ -94,6 +94,7 @@ struct SHandle { bool AddressFailed; // Indicate failure to connect to address bool KeepAlive; // Socket keep alive + bool SerialConfig; int Baudrate; short DataBits; short Parity; @@ -257,8 +258,8 @@ public: bool SetOutBuffer( THandle * Handle, int OutBufSize ); // Specific port parameters - bool SetPortHandle( THandle * Handle, const char * FileName, - int Baudrate, short DataBits, short Parity, short StopBits, short FlowCtrl, int DataWait ); + bool SetPortHandle( THandle * Handle, const char * FileName ); + bool SetPortHandleSerial( THandle * Handle, int Baudrate, short DataBits, short Parity, short StopBits, short FlowCtrl, int DataWait ); bool SetForkPipeHandle( THandle * Handle, const char * ExecPath ); bool SetSocketHandle( THandle * Handle, EConnectType Type, const char * HostName, const char * PortName, bool KeepAlive ); bool ClearHandle( THandle * Handle ); @@ -281,7 +282,8 @@ public: inline virtual bool Write( const char * HandleName ) { return (Write( GetHandle( HandleName ))); }; inline virtual bool Write( int FD ) { return (Write( GetHandle( FD ))); }; - bool ConfigureSerialPort( THandle * Handle ); + bool SetSerialPortConfig( THandle * Handle ); + bool GetSerialPortConfig( THandle * Handle ); // Info inline EConnectType GetType( const char * HandleName ) {