From 980038c3ea2f7ce387e4c29aeb8adfea70c1e8de Mon Sep 17 00:00:00 2001 From: Tobias Kaupat Date: Fri, 2 Mar 2018 16:35:56 +0100 Subject: [PATCH 1/3] Allow to set initial RTS and DTR state after connect --- serial.go | 10 ++++++---- serial_unix.go | 3 +++ serial_windows.go | 8 ++++++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/serial.go b/serial.go index 3e4f3b1..674069b 100644 --- a/serial.go +++ b/serial.go @@ -74,10 +74,12 @@ func GetPortsList() ([]string, error) { // Mode describes a serial port configuration. type Mode struct { - BaudRate int // The serial port bitrate (aka Baudrate) - DataBits int // Size of the character (must be 5, 6, 7 or 8) - Parity Parity // Parity (see Parity type for more info) - StopBits StopBits // Stop bits (see StopBits type for more info) + BaudRate int // The serial port bitrate (aka Baudrate) + DataBits int // Size of the character (must be 5, 6, 7 or 8) + Parity Parity // Parity (see Parity type for more info) + StopBits StopBits // Stop bits (see StopBits type for more info) + InitialRTS bool // Initial state for RTS + InitialDTR bool // Initial state for DTR } // Parity describes a serial port parity setting diff --git a/serial_unix.go b/serial_unix.go index d7c7078..2f7e1d1 100644 --- a/serial_unix.go +++ b/serial_unix.go @@ -235,6 +235,9 @@ func nativeOpen(portName string, mode *Mode) (*unixPort, error) { // Explicitly disable RTS/CTS flow control setTermSettingsCtsRts(false, settings) + port.SetDTR(mode.InitialDTR) + port.SetRTS(mode.InitialRTS) + if port.setTermSettings(settings) != nil { port.Close() return nil, &PortError{code: InvalidSerialPort} diff --git a/serial_windows.go b/serial_windows.go index af9a620..dd0715c 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -451,9 +451,13 @@ func nativeOpen(portName string, mode *Mode) (*windowsPort, error) { return nil, &PortError{code: InvalidSerialPort} } params.Flags &= dcbRTSControlDisbaleMask - params.Flags |= dcbRTSControlEnable + if mode.InitialRTS { + params.Flags |= dcbRTSControlEnable + } params.Flags &= dcbDTRControlDisableMask - params.Flags |= dcbDTRControlEnable + if mode.InitialDTR { + params.Flags |= dcbDTRControlEnable + } params.Flags &^= dcbOutXCTSFlow params.Flags &^= dcbOutXDSRFlow params.Flags &^= dcbDSRSensitivity From 3c9f14262a33bf0e6ee4d647088b1ec755e02da9 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 1 Sep 2022 16:18:52 +0200 Subject: [PATCH 2/3] Default status bits to 'on' --- serial.go | 20 +++++++++++++------- serial_unix.go | 23 ++++++++++++++++++++--- serial_windows.go | 15 ++++++++++----- 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/serial.go b/serial.go index 674069b..43f0f74 100644 --- a/serial.go +++ b/serial.go @@ -53,7 +53,7 @@ type Port interface { // NoTimeout should be used as a parameter to SetReadTimeout to disable timeout. var NoTimeout time.Duration = -1 -// ModemStatusBits contains all the modem status bits for a serial port (CTS, DSR, etc...). +// ModemStatusBits contains all the modem input status bits for a serial port (CTS, DSR, etc...). // It can be retrieved with the Port.GetModemStatusBits() method. type ModemStatusBits struct { CTS bool // ClearToSend status @@ -62,6 +62,13 @@ type ModemStatusBits struct { DCD bool // DataCarrierDetect status } +// ModemOutputBits contains all the modem output bits for a serial port. +// This is used in the Mode.InitialStatusBits struct to specify the initial status of the bits. +type ModemOutputBits struct { + RTS bool // ReadyToSend status + DTR bool // DataTerminalReady status +} + // Open opens the serial port using the specified modes func Open(portName string, mode *Mode) (Port, error) { return nativeOpen(portName, mode) @@ -74,12 +81,11 @@ func GetPortsList() ([]string, error) { // Mode describes a serial port configuration. type Mode struct { - BaudRate int // The serial port bitrate (aka Baudrate) - DataBits int // Size of the character (must be 5, 6, 7 or 8) - Parity Parity // Parity (see Parity type for more info) - StopBits StopBits // Stop bits (see StopBits type for more info) - InitialRTS bool // Initial state for RTS - InitialDTR bool // Initial state for DTR + BaudRate int // The serial port bitrate (aka Baudrate) + DataBits int // Size of the character (must be 5, 6, 7 or 8) + Parity Parity // Parity (see Parity type for more info) + StopBits StopBits // Stop bits (see StopBits type for more info) + InitialStatusBits *ModemOutputBits // Initial output modem bits status (if nil defaults to DTR=true and RTS=true) } // Parity describes a serial port parity setting diff --git a/serial_unix.go b/serial_unix.go index 2f7e1d1..4a8ef66 100644 --- a/serial_unix.go +++ b/serial_unix.go @@ -235,14 +235,31 @@ func nativeOpen(portName string, mode *Mode) (*unixPort, error) { // Explicitly disable RTS/CTS flow control setTermSettingsCtsRts(false, settings) - port.SetDTR(mode.InitialDTR) - port.SetRTS(mode.InitialRTS) - if port.setTermSettings(settings) != nil { port.Close() return nil, &PortError{code: InvalidSerialPort} } + if mode.InitialStatusBits != nil { + status, err := port.getModemBitsStatus() + if err != nil { + return nil, &PortError{code: InvalidSerialPort, causedBy: err} + } + if mode.InitialStatusBits.DTR { + status |= unix.TIOCM_DTR + } else { + status &^= unix.TIOCM_DTR + } + if mode.InitialStatusBits.RTS { + status |= unix.TIOCM_RTS + } else { + status &^= unix.TIOCM_RTS + } + if err := port.setModemBitsStatus(status); err != nil { + return nil, &PortError{code: InvalidSerialPort, causedBy: err} + } + } + // MacOSX require that this operation is the last one otherwise an // 'Invalid serial port' error is returned... don't know why... if port.SetMode(mode) != nil { diff --git a/serial_windows.go b/serial_windows.go index dd0715c..4b652b5 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -450,13 +450,18 @@ func nativeOpen(portName string, mode *Mode) (*windowsPort, error) { port.Close() return nil, &PortError{code: InvalidSerialPort} } - params.Flags &= dcbRTSControlDisbaleMask - if mode.InitialRTS { - params.Flags |= dcbRTSControlEnable - } params.Flags &= dcbDTRControlDisableMask - if mode.InitialDTR { + params.Flags &= dcbRTSControlDisbaleMask + if mode.InitialStatusBits == nil { params.Flags |= dcbDTRControlEnable + params.Flags |= dcbRTSControlEnable + } else { + if mode.InitialStatusBits.DTR { + params.Flags |= dcbDTRControlEnable + } + if mode.InitialStatusBits.RTS { + params.Flags |= dcbRTSControlEnable + } } params.Flags &^= dcbOutXCTSFlow params.Flags &^= dcbOutXDSRFlow From 3099149a031a72dcd4b85593c5eceadeb4d0b111 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Sat, 3 Sep 2022 18:04:47 +0200 Subject: [PATCH 3/3] Added a doc notice for posix 'pulse' problem --- serial.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/serial.go b/serial.go index 43f0f74..e072d42 100644 --- a/serial.go +++ b/serial.go @@ -64,6 +64,9 @@ type ModemStatusBits struct { // ModemOutputBits contains all the modem output bits for a serial port. // This is used in the Mode.InitialStatusBits struct to specify the initial status of the bits. +// Note: Linux and MacOSX (and basically all unix-based systems) can not set the status bits +// before opening the port, even if the initial state of the bit is set to false they will go +// anyway to true for a few milliseconds, resulting in a small pulse. type ModemOutputBits struct { RTS bool // ReadyToSend status DTR bool // DataTerminalReady status