From cee35213531f1903d97e26e9cdf4dc64799023fb Mon Sep 17 00:00:00 2001 From: Madhur Jain Date: Fri, 13 Mar 2015 12:19:32 +0530 Subject: [PATCH] Adding Flush() to flush serial port I/O buffers - Current implementation will flush both Input and Output buffers - Added Flush to Windows calling PurgeComm() - Added Flush to POSIX calling tcflush() - Added Flush to Linux using syscall IOCTL with TCFLSH - Tested on Windows, POSIX and Linux environment --- serial.go | 2 -- serial_linux.go | 16 ++++++++++++++-- serial_posix.go | 10 ++++++++-- serial_windows.go | 23 ++++++++++++++++++++++- 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/serial.go b/serial.go index 143d75f..0748cab 100644 --- a/serial.go +++ b/serial.go @@ -118,8 +118,6 @@ func posixTimeoutValues(readTimeout time.Duration) (vmin uint8, vtime uint8) { return minBytesToRead, uint8(readTimeoutInDeci) } -// func Flush() - // func SendBreak() // func RegisterBreakHandler(func()) diff --git a/serial_linux.go b/serial_linux.go index fefd946..9489972 100644 --- a/serial_linux.go +++ b/serial_linux.go @@ -86,13 +86,14 @@ func openPort(name string, baud int, readTimeout time.Duration) (p *Port, err er return } - return &Port{f: f}, nil + return &Port{f: f, fd: fd}, nil } type Port struct { // We intentionly do not use an "embedded" struct so that we // don't export File - f *os.File + f *os.File + fd uintptr } func (p *Port) Read(b []byte) (n int, err error) { @@ -103,6 +104,17 @@ func (p *Port) Write(b []byte) (n int, err error) { return p.f.Write(b) } +func (p *Port) Flush() error { + const TCFLSH = 0x540B + _, _, err := syscall.Syscall( + syscall.SYS_IOCTL, + uintptr(p.fd), + uintptr(TCFLSH), + uintptr(syscall.TCIOFLUSH), + ) + return err +} + func (p *Port) Close() (err error) { return p.f.Close() } diff --git a/serial_posix.go b/serial_posix.go index 2b6ebb4..23222a5 100644 --- a/serial_posix.go +++ b/serial_posix.go @@ -116,13 +116,14 @@ func openPort(name string, baud int, readTimeout time.Duration) (p *Port, err er } */ - return &Port{f: f}, nil + return &Port{f: f, fd: fd}, nil } type Port struct { // We intentionly do not use an "embedded" struct so that we // don't export File - f *os.File + f *os.File + fd C.int } func (p *Port) Read(b []byte) (n int, err error) { @@ -133,6 +134,11 @@ func (p *Port) Write(b []byte) (n int, err error) { return p.f.Write(b) } +func (p *Port) Flush() error { + _, err := C.tcflush(p.fd, C.TCIOFLUSH) + return err +} + func (p *Port) Close() (err error) { return p.f.Close() } diff --git a/serial_windows.go b/serial_windows.go index 5ca47f5..ea99e68 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -127,6 +127,10 @@ func (p *Port) Read(buf []byte) (int, error) { return getOverlappedResult(p.fd, p.ro) } +func (p *Port) Flush() error { + return purgeComm(p.fd) +} + var ( nSetCommState, nSetCommTimeouts, @@ -134,7 +138,9 @@ var ( nSetupComm, nGetOverlappedResult, nCreateEvent, - nResetEvent uintptr + nResetEvent, + nPurgeComm, + nFlushFileBuffers uintptr ) func init() { @@ -151,6 +157,8 @@ func init() { nGetOverlappedResult = getProcAddr(k32, "GetOverlappedResult") nCreateEvent = getProcAddr(k32, "CreateEventW") nResetEvent = getProcAddr(k32, "ResetEvent") + nPurgeComm = getProcAddr(k32, "PurgeComm") + nFlushFileBuffers = getProcAddr(k32, "FlushFileBuffers") } func getProcAddr(lib syscall.Handle, name string) uintptr { @@ -254,6 +262,19 @@ func resetEvent(h syscall.Handle) error { return nil } +func purgeComm(h syscall.Handle) error { + const PURGE_TXABORT = 0x0001 + const PURGE_RXABORT = 0x0002 + const PURGE_TXCLEAR = 0x0004 + const PURGE_RXCLEAR = 0x0008 + r, _, err := syscall.Syscall(nPurgeComm, 2, uintptr(h), + PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR, 0) + if r == 0 { + return err + } + return nil +} + func newOverlapped() (*syscall.Overlapped, error) { var overlapped syscall.Overlapped r, _, err := syscall.Syscall6(nCreateEvent, 4, 0, 1, 0, 0, 0, 0)