diff --git a/serial.go b/serial.go index 3e4f3b1..e072d42 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,16 @@ 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. +// 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 +} + // Open opens the serial port using the specified modes func Open(portName string, mode *Mode) (Port, error) { return nativeOpen(portName, mode) @@ -74,10 +84,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) + 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 d7c7078..4a8ef66 100644 --- a/serial_unix.go +++ b/serial_unix.go @@ -240,6 +240,26 @@ func nativeOpen(portName string, mode *Mode) (*unixPort, error) { 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 af9a620..4b652b5 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -450,10 +450,19 @@ func nativeOpen(portName string, mode *Mode) (*windowsPort, error) { port.Close() return nil, &PortError{code: InvalidSerialPort} } - params.Flags &= dcbRTSControlDisbaleMask - params.Flags |= dcbRTSControlEnable params.Flags &= dcbDTRControlDisableMask - params.Flags |= dcbDTRControlEnable + 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 params.Flags &^= dcbDSRSensitivity