Skip to content

Commit

Permalink
Adding Flush() to flush serial port I/O buffers
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
madhurjain committed Mar 13, 2015
1 parent 1d5ebfa commit cee3521
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 7 deletions.
2 changes: 0 additions & 2 deletions serial.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ func posixTimeoutValues(readTimeout time.Duration) (vmin uint8, vtime uint8) {
return minBytesToRead, uint8(readTimeoutInDeci)
}

// func Flush()

// func SendBreak()

// func RegisterBreakHandler(func())
16 changes: 14 additions & 2 deletions serial_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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()
}
10 changes: 8 additions & 2 deletions serial_posix.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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()
}
23 changes: 22 additions & 1 deletion serial_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,20 @@ 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,
nSetCommMask,
nSetupComm,
nGetOverlappedResult,
nCreateEvent,
nResetEvent uintptr
nResetEvent,
nPurgeComm,
nFlushFileBuffers uintptr
)

func init() {
Expand All @@ -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 {
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit cee3521

Please sign in to comment.