From 1b32e598713681cbac2986178ce88fe926d32190 Mon Sep 17 00:00:00 2001 From: Frank Palazzolo Date: Mon, 14 Nov 2022 08:58:11 -0500 Subject: [PATCH 1/2] Remove unnecessary code, originally for checking disconnects The old code is no more needed when using overlapped I/O, getOverlappedEvent() returns all required error codes. Calling getCommState()/setCommState() every second in some applications contributes to other downstream issues. For examples: https://github.com/bugst/go-serial/issues/60#issuecomment-625749122 https://github.com/arduino/arduino-ide/issues/375 --- serial_windows.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/serial_windows.go b/serial_windows.go index 4b652b5..96b021c 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -114,17 +114,6 @@ func (port *windowsPort) Read(p []byte) (int, error) { return 0, nil } } - - // At the moment it seems that the only reliable way to check if - // a serial port is alive in Windows is to check if the SetCommState - // function fails. - - params := &dcb{} - getCommState(port.handle, params) - if err := setCommState(port.handle, params); err != nil { - port.Close() - return 0, err - } } } From 5d3a516f129c780bbacec69cdb4caf06de49a1b7 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Thu, 24 Nov 2022 17:14:03 +0100 Subject: [PATCH 2/2] Removed port-alive-check loop on Windows implementation --- serial_windows.go | 81 +++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 48 deletions(-) diff --git a/serial_windows.go b/serial_windows.go index 96b021c..1a3db7a 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -24,9 +24,8 @@ import ( ) type windowsPort struct { - mu sync.Mutex - handle syscall.Handle - readTimeoutCycles int64 + mu sync.Mutex + handle syscall.Handle } func nativeGetPortsList() ([]string, error) { @@ -83,38 +82,26 @@ func (port *windowsPort) Read(p []byte) (int, error) { } defer syscall.CloseHandle(ev.HEvent) - cycles := int64(0) - for { - err := syscall.ReadFile(port.handle, p, &readed, ev) - if err == syscall.ERROR_IO_PENDING { - err = getOverlappedResult(port.handle, ev, &readed, true) - } - switch err { - case nil: - // operation completed successfully - case syscall.ERROR_OPERATION_ABORTED: - // port may have been closed - return int(readed), &PortError{code: PortClosed, causedBy: err} - default: - // error happened - return int(readed), err - } - - if readed > 0 { - return int(readed), nil - } - if err := resetEvent(ev.HEvent); err != nil { - return 0, err - } - - if port.readTimeoutCycles != -1 { - cycles++ - if cycles == port.readTimeoutCycles { - // Timeout - return 0, nil - } - } + err = syscall.ReadFile(port.handle, p, &readed, ev) + if err == syscall.ERROR_IO_PENDING { + err = getOverlappedResult(port.handle, ev, &readed, true) } + switch err { + case nil: + // operation completed successfully + case syscall.ERROR_OPERATION_ABORTED: + // port may have been closed + return int(readed), &PortError{code: PortClosed, causedBy: err} + default: + // error happened + return int(readed), err + } + if readed > 0 { + return int(readed), nil + } + + // Timeout + return 0, nil } func (port *windowsPort) Write(p []byte) (int, error) { @@ -372,26 +359,24 @@ func (port *windowsPort) GetModemStatusBits() (*ModemStatusBits, error) { } func (port *windowsPort) SetReadTimeout(timeout time.Duration) error { - var cycles, cycleDuration int64 - if timeout == NoTimeout { - cycles = -1 - cycleDuration = 1000 - } else { - cycles = timeout.Milliseconds()/1000 + 1 - cycleDuration = timeout.Milliseconds() / cycles - } - - err := setCommTimeouts(port.handle, &commTimeouts{ + commTimeouts := &commTimeouts{ ReadIntervalTimeout: 0xFFFFFFFF, ReadTotalTimeoutMultiplier: 0xFFFFFFFF, - ReadTotalTimeoutConstant: uint32(cycleDuration), + ReadTotalTimeoutConstant: 0xFFFFFFFE, WriteTotalTimeoutConstant: 0, WriteTotalTimeoutMultiplier: 0, - }) - if err != nil { + } + if timeout != NoTimeout { + ms := timeout.Milliseconds() + if ms > 0xFFFFFFFE || ms < 0 { + return &PortError{code: InvalidTimeoutValue} + } + commTimeouts.ReadTotalTimeoutConstant = uint32(ms) + } + + if err := setCommTimeouts(port.handle, commTimeouts); err != nil { return &PortError{code: InvalidTimeoutValue, causedBy: err} } - port.readTimeoutCycles = cycles return nil }