diff --git a/serial_linux.go b/serial_linux.go index 65420f3..ceefcd6 100644 --- a/serial_linux.go +++ b/serial_linux.go @@ -159,6 +159,27 @@ func (p *Port) Flush() error { return errno } +// SendBreak sends a break (bus low value) for a given duration. +// In POSIX and linux implementations there are two cases for the duration value: +// +// if duration is zero there a break with at least 0.25 seconds +// but not more than 0.5 seconds will be send. If duration is not zero, +// than it's implementaion specific, which unit is used for duration. +// For more information tae a look at tcsendbreak(3) and ioctl_tty(2) +func (p *Port) SendBreak(d time.Duration) error { + _, _, errno := unix.Syscall( + unix.SYS_IOCTL, + uintptr(p.f.Fd()), + uintptr(unix.TCSBRK), + uintptr(d.Milliseconds()), + ) + + if errno == 0 { + return nil + } + return errno +} + func (p *Port) Close() (err error) { return p.f.Close() } diff --git a/serial_posix.go b/serial_posix.go index d733f0f..02167ea 100644 --- a/serial_posix.go +++ b/serial_posix.go @@ -192,6 +192,18 @@ func (p *Port) Flush() error { return err } +// SendBreak sends a break (bus low value) for a given duration. +// In POSIX and linux implementations there are two cases for the duration value: +// +// if duration is zero there a break with at least 0.25 seconds +// but not more than 0.5 seconds will be send. If duration is not zero, +// than it's implementaion specific, which unit is used for duration. +// For more information tae a look at tcsendbreak(3) and ioctl_tty(2) +func (p *Port) SendBreak(d time.Duration) error { + _, err := C.tcsendbreak(C.int(p.f.Fd()), C.int(d.Milliseconds())) + return err +} + func (p *Port) Close() (err error) { return p.f.Close() } diff --git a/serial_windows.go b/serial_windows.go index 2a9c004..3fc0de5 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -133,6 +133,18 @@ func (p *Port) Flush() error { return purgeComm(p.fd) } +// SendBreak sends a break (bus low value) for a given duration. +// In POSIX and linux implementations the default behavior on zero duration +// is to send at least 0.25 seconds and not more than 0.5 seconds. +// To be compatible to linux and unix behavior we use 0.25 seconds +// as duration if a duration of zero is given. +func (p *Port) SendBreak(d time.Duration) error { + if d.Milliseconds() == 0 { + d = 250 * time.Millisecond + } + return sendCommBread(p.fd, d) +} + var ( nSetCommState, nSetCommTimeouts, @@ -142,6 +154,8 @@ var ( nCreateEvent, nResetEvent, nPurgeComm, + nSetCommBreak, + nClearCommBreak, nFlushFileBuffers uintptr ) @@ -160,6 +174,8 @@ func init() { nCreateEvent = getProcAddr(k32, "CreateEventW") nResetEvent = getProcAddr(k32, "ResetEvent") nPurgeComm = getProcAddr(k32, "PurgeComm") + nSetCommBreak = getProcAddr(k32, "SetCommBreak") + nClearCommBreak = getProcAddr(k32, "ClearCommBreak") nFlushFileBuffers = getProcAddr(k32, "FlushFileBuffers") } @@ -303,6 +319,19 @@ func purgeComm(h syscall.Handle) error { return nil } +func sendCommBreak(h syscall.Hande, d time.duration) error { + r, _, err := syscall.Syscall(nSetCommBreak, 1, uintptr(h), 0, 0) + if r == 0 { + return err + } + time.Sleep(d) + r, _, err = syscall.Syscall(nClearCommBreak, 1, uintptr(h), 0, 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)