Merge pull request #145 from cmaglie/send_break
Added support for sending break (unix + windows)
This commit is contained in:
2
go.mod
2
go.mod
@@ -5,7 +5,7 @@ go 1.17
|
||||
require (
|
||||
github.com/creack/goselect v0.1.2
|
||||
github.com/stretchr/testify v1.7.0
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
|
||||
)
|
||||
|
||||
require (
|
||||
|
||||
2
go.sum
2
go.sum
@@ -9,6 +9,8 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
|
||||
@@ -48,6 +48,9 @@ type Port interface {
|
||||
|
||||
// Close the serial port
|
||||
Close() error
|
||||
|
||||
// Break sends a break for a determined time
|
||||
Break(time.Duration) error
|
||||
}
|
||||
|
||||
// NoTimeout should be used as a parameter to SetReadTimeout to disable timeout.
|
||||
|
||||
@@ -14,6 +14,8 @@ const regexFilter = "^(cu|tty)\\..*"
|
||||
const ioctlTcgetattr = unix.TIOCGETA
|
||||
const ioctlTcsetattr = unix.TIOCSETA
|
||||
const ioctlTcflsh = unix.TIOCFLUSH
|
||||
const ioctlTioccbrk = unix.TIOCCBRK
|
||||
const ioctlTiocsbrk = unix.TIOCSBRK
|
||||
|
||||
func setTermSettingsBaudrate(speed int, settings *unix.Termios) (error, bool) {
|
||||
baudrate, ok := baudrateMap[speed]
|
||||
|
||||
@@ -56,6 +56,8 @@ const tcCRTSCTS uint32 = tcCCTS_OFLOW
|
||||
const ioctlTcgetattr = unix.TIOCGETA
|
||||
const ioctlTcsetattr = unix.TIOCSETA
|
||||
const ioctlTcflsh = unix.TIOCFLUSH
|
||||
const ioctlTioccbrk = unix.TIOCCBRK
|
||||
const ioctlTiocsbrk = unix.TIOCSBRK
|
||||
|
||||
func toTermiosSpeedType(speed uint32) uint32 {
|
||||
return speed
|
||||
|
||||
@@ -63,6 +63,8 @@ const tcCRTSCTS uint32 = unix.CRTSCTS
|
||||
const ioctlTcgetattr = unix.TCGETS
|
||||
const ioctlTcsetattr = unix.TCSETS
|
||||
const ioctlTcflsh = unix.TCFLSH
|
||||
const ioctlTioccbrk = unix.TIOCCBRK
|
||||
const ioctlTiocsbrk = unix.TIOCSBRK
|
||||
|
||||
func toTermiosSpeedType(speed uint32) uint32 {
|
||||
return speed
|
||||
|
||||
@@ -56,6 +56,8 @@ const tcCRTSCTS uint32 = tcCCTS_OFLOW
|
||||
const ioctlTcgetattr = unix.TIOCGETA
|
||||
const ioctlTcsetattr = unix.TIOCSETA
|
||||
const ioctlTcflsh = unix.TIOCFLUSH
|
||||
const ioctlTioccbrk = unix.TIOCCBRK
|
||||
const ioctlTiocsbrk = unix.TIOCSBRK
|
||||
|
||||
func toTermiosSpeedType(speed uint32) int32 {
|
||||
return int32(speed)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
//
|
||||
|
||||
//go:build linux || darwin || freebsd || openbsd
|
||||
// +build linux darwin freebsd openbsd
|
||||
|
||||
package serial
|
||||
@@ -117,6 +118,20 @@ func (port *unixPort) Write(p []byte) (n int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (port *unixPort) Break(t time.Duration) error {
|
||||
if err := unix.IoctlSetInt(port.handle, ioctlTiocsbrk, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
time.Sleep(t)
|
||||
|
||||
if err := unix.IoctlSetInt(port.handle, ioctlTioccbrk, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (port *unixPort) SetMode(mode *Mode) error {
|
||||
settings, err := port.getTermSettings()
|
||||
if err != nil {
|
||||
|
||||
@@ -381,6 +381,20 @@ func (port *windowsPort) SetReadTimeout(timeout time.Duration) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (port *windowsPort) Break(d time.Duration) error {
|
||||
if err := setCommBreak(port.handle); err != nil {
|
||||
return &PortError{causedBy: err}
|
||||
}
|
||||
|
||||
time.Sleep(d)
|
||||
|
||||
if err := clearCommBreak(port.handle); err != nil {
|
||||
return &PortError{causedBy: err}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createOverlappedEvent() (*syscall.Overlapped, error) {
|
||||
h, err := createEvent(nil, true, false, nil)
|
||||
return &syscall.Overlapped{HEvent: h}, err
|
||||
|
||||
@@ -25,3 +25,7 @@ package serial
|
||||
//sys getOverlappedResult(handle syscall.Handle, overlapEvent *syscall.Overlapped, n *uint32, wait bool) (err error) = GetOverlappedResult
|
||||
|
||||
//sys purgeComm(handle syscall.Handle, flags uint32) (err error) = PurgeComm
|
||||
|
||||
//sys setCommBreak(handle syscall.Handle) (err error) = SetCommBreak
|
||||
|
||||
//sys clearCommBreak(handle syscall.Handle) (err error) = ClearCommBreak
|
||||
|
||||
@@ -19,6 +19,7 @@ const (
|
||||
|
||||
var (
|
||||
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
||||
errERROR_EINVAL error = syscall.EINVAL
|
||||
)
|
||||
|
||||
// errnoErr returns common boxed Errno values, to prevent
|
||||
@@ -26,7 +27,7 @@ var (
|
||||
func errnoErr(e syscall.Errno) error {
|
||||
switch e {
|
||||
case 0:
|
||||
return nil
|
||||
return errERROR_EINVAL
|
||||
case errnoERROR_IO_PENDING:
|
||||
return errERROR_IO_PENDING
|
||||
}
|
||||
@@ -41,15 +42,17 @@ var (
|
||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
|
||||
procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW")
|
||||
procGetCommState = modkernel32.NewProc("GetCommState")
|
||||
procSetCommState = modkernel32.NewProc("SetCommState")
|
||||
procSetCommTimeouts = modkernel32.NewProc("SetCommTimeouts")
|
||||
procClearCommBreak = modkernel32.NewProc("ClearCommBreak")
|
||||
procCreateEventW = modkernel32.NewProc("CreateEventW")
|
||||
procEscapeCommFunction = modkernel32.NewProc("EscapeCommFunction")
|
||||
procGetCommModemStatus = modkernel32.NewProc("GetCommModemStatus")
|
||||
procCreateEventW = modkernel32.NewProc("CreateEventW")
|
||||
procResetEvent = modkernel32.NewProc("ResetEvent")
|
||||
procGetCommState = modkernel32.NewProc("GetCommState")
|
||||
procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult")
|
||||
procPurgeComm = modkernel32.NewProc("PurgeComm")
|
||||
procResetEvent = modkernel32.NewProc("ResetEvent")
|
||||
procSetCommBreak = modkernel32.NewProc("SetCommBreak")
|
||||
procSetCommState = modkernel32.NewProc("SetCommState")
|
||||
procSetCommTimeouts = modkernel32.NewProc("SetCommTimeouts")
|
||||
)
|
||||
|
||||
func regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, value *uint16, valueLen *uint32) (regerrno error) {
|
||||
@@ -60,38 +63,27 @@ func regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint3
|
||||
return
|
||||
}
|
||||
|
||||
func getCommState(handle syscall.Handle, dcb *dcb) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procGetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(dcb)), 0)
|
||||
func clearCommBreak(handle syscall.Handle) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procClearCommBreak.Addr(), 1, uintptr(handle), 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func setCommState(handle syscall.Handle, dcb *dcb) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procSetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(dcb)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
func createEvent(eventAttributes *uint32, manualReset bool, initialState bool, name *uint16) (handle syscall.Handle, err error) {
|
||||
var _p0 uint32
|
||||
if manualReset {
|
||||
_p0 = 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func setCommTimeouts(handle syscall.Handle, timeouts *commTimeouts) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procSetCommTimeouts.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(timeouts)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
var _p1 uint32
|
||||
if initialState {
|
||||
_p1 = 1
|
||||
}
|
||||
r0, _, e1 := syscall.Syscall6(procCreateEventW.Addr(), 4, uintptr(unsafe.Pointer(eventAttributes)), uintptr(_p0), uintptr(_p1), uintptr(unsafe.Pointer(name)), 0, 0)
|
||||
handle = syscall.Handle(r0)
|
||||
if handle == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -108,39 +100,10 @@ func getCommModemStatus(handle syscall.Handle, bits *uint32) (res bool) {
|
||||
return
|
||||
}
|
||||
|
||||
func createEvent(eventAttributes *uint32, manualReset bool, initialState bool, name *uint16) (handle syscall.Handle, err error) {
|
||||
var _p0 uint32
|
||||
if manualReset {
|
||||
_p0 = 1
|
||||
} else {
|
||||
_p0 = 0
|
||||
}
|
||||
var _p1 uint32
|
||||
if initialState {
|
||||
_p1 = 1
|
||||
} else {
|
||||
_p1 = 0
|
||||
}
|
||||
r0, _, e1 := syscall.Syscall6(procCreateEventW.Addr(), 4, uintptr(unsafe.Pointer(eventAttributes)), uintptr(_p0), uintptr(_p1), uintptr(unsafe.Pointer(name)), 0, 0)
|
||||
handle = syscall.Handle(r0)
|
||||
if handle == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func resetEvent(handle syscall.Handle) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procResetEvent.Addr(), 1, uintptr(handle), 0, 0)
|
||||
func getCommState(handle syscall.Handle, dcb *dcb) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procGetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(dcb)), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -149,16 +112,10 @@ func getOverlappedResult(handle syscall.Handle, overlapEvent *syscall.Overlapped
|
||||
var _p0 uint32
|
||||
if wait {
|
||||
_p0 = 1
|
||||
} else {
|
||||
_p0 = 0
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall6(procGetOverlappedResult.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(overlapEvent)), uintptr(unsafe.Pointer(n)), uintptr(_p0), 0, 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -166,11 +123,39 @@ func getOverlappedResult(handle syscall.Handle, overlapEvent *syscall.Overlapped
|
||||
func purgeComm(handle syscall.Handle, flags uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procPurgeComm.Addr(), 2, uintptr(handle), uintptr(flags), 0)
|
||||
if r1 == 0 {
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
} else {
|
||||
err = syscall.EINVAL
|
||||
}
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func resetEvent(handle syscall.Handle) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procResetEvent.Addr(), 1, uintptr(handle), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func setCommBreak(handle syscall.Handle) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procSetCommBreak.Addr(), 1, uintptr(handle), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func setCommState(handle syscall.Handle, dcb *dcb) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procSetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(dcb)), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func setCommTimeouts(handle syscall.Handle, timeouts *commTimeouts) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procSetCommTimeouts.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(timeouts)), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user