Use Windows serial comm functions from golang.org/x/sys/windows

This commit is contained in:
Tom Payne
2024-04-09 12:51:09 +02:00
committed by Tom Payne
parent 0b7848559a
commit 45e996e1b0
5 changed files with 86 additions and 377 deletions

2
go.mod
View File

@@ -5,7 +5,7 @@ go 1.17
require (
github.com/creack/goselect v0.1.2
github.com/stretchr/testify v1.8.4
golang.org/x/sys v0.17.0
golang.org/x/sys v0.19.0
)
require (

4
go.sum
View File

@@ -12,8 +12,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -19,46 +19,29 @@ package serial
import (
"sync"
"syscall"
"time"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/registry"
)
type windowsPort struct {
mu sync.Mutex
handle syscall.Handle
handle windows.Handle
}
func nativeGetPortsList() ([]string, error) {
subKey, err := syscall.UTF16PtrFromString("HARDWARE\\DEVICEMAP\\SERIALCOMM\\")
key, err := registry.OpenKey(windows.HKEY_LOCAL_MACHINE, `HARDWARE\DEVICEMAP\SERIALCOMM\`, windows.KEY_READ)
if err != nil {
return nil, &PortError{code: ErrorEnumeratingPorts}
return nil, &PortError{code: ErrorEnumeratingPorts, causedBy: err}
}
defer key.Close()
list, err := key.ReadValueNames(0)
if err != nil {
return nil, &PortError{code: ErrorEnumeratingPorts, causedBy: err}
}
var h syscall.Handle
if err := syscall.RegOpenKeyEx(syscall.HKEY_LOCAL_MACHINE, subKey, 0, syscall.KEY_READ, &h); err != nil {
if errno, isErrno := err.(syscall.Errno); isErrno && errno == syscall.ERROR_FILE_NOT_FOUND {
return []string{}, nil
}
return nil, &PortError{code: ErrorEnumeratingPorts}
}
defer syscall.RegCloseKey(h)
var valuesCount uint32
if syscall.RegQueryInfoKey(h, nil, nil, nil, nil, nil, nil, &valuesCount, nil, nil, nil, nil) != nil {
return nil, &PortError{code: ErrorEnumeratingPorts}
}
list := make([]string, valuesCount)
for i := range list {
var data [1024]uint16
dataSize := uint32(len(data))
var name [1024]uint16
nameSize := uint32(len(name))
if regEnumValue(h, uint32(i), &name[0], &nameSize, nil, nil, &data[0], &dataSize) != nil {
return nil, &PortError{code: ErrorEnumeratingPorts}
}
list[i] = syscall.UTF16ToString(data[:])
}
return list, nil
}
@@ -71,7 +54,7 @@ func (port *windowsPort) Close() error {
if port.handle == 0 {
return nil
}
return syscall.CloseHandle(port.handle)
return windows.CloseHandle(port.handle)
}
func (port *windowsPort) Read(p []byte) (int, error) {
@@ -80,16 +63,16 @@ func (port *windowsPort) Read(p []byte) (int, error) {
if err != nil {
return 0, err
}
defer syscall.CloseHandle(ev.HEvent)
defer windows.CloseHandle(ev.HEvent)
err = syscall.ReadFile(port.handle, p, &readed, ev)
if err == syscall.ERROR_IO_PENDING {
err = getOverlappedResult(port.handle, ev, &readed, true)
err = windows.ReadFile(port.handle, p, &readed, ev)
if err == windows.ERROR_IO_PENDING {
err = windows.GetOverlappedResult(port.handle, ev, &readed, true)
}
switch err {
case nil:
// operation completed successfully
case syscall.ERROR_OPERATION_ABORTED:
case windows.ERROR_OPERATION_ABORTED:
// port may have been closed
return int(readed), &PortError{code: PortClosed, causedBy: err}
default:
@@ -110,32 +93,25 @@ func (port *windowsPort) Write(p []byte) (int, error) {
if err != nil {
return 0, err
}
defer syscall.CloseHandle(ev.HEvent)
err = syscall.WriteFile(port.handle, p, &writed, ev)
if err == syscall.ERROR_IO_PENDING {
defer windows.CloseHandle(ev.HEvent)
err = windows.WriteFile(port.handle, p, &writed, ev)
if err == windows.ERROR_IO_PENDING {
// wait for write to complete
err = getOverlappedResult(port.handle, ev, &writed, true)
err = windows.GetOverlappedResult(port.handle, ev, &writed, true)
}
return int(writed), err
}
func (port *windowsPort) Drain() (err error) {
return syscall.FlushFileBuffers(port.handle)
return windows.FlushFileBuffers(port.handle)
}
const (
purgeRxAbort uint32 = 0x0002
purgeRxClear = 0x0008
purgeTxAbort = 0x0001
purgeTxClear = 0x0004
)
func (port *windowsPort) ResetInputBuffer() error {
return purgeComm(port.handle, purgeRxClear|purgeRxAbort)
return windows.PurgeComm(port.handle, windows.PURGE_RXCLEAR|windows.PURGE_RXABORT)
}
func (port *windowsPort) ResetOutputBuffer() error {
return purgeComm(port.handle, purgeTxClear|purgeTxAbort)
return windows.PurgeComm(port.handle, windows.PURGE_TXCLEAR|windows.PURGE_TXABORT)
}
const (
@@ -159,112 +135,37 @@ const (
dcbAbortOnError = 0x00004000
)
type dcb struct {
DCBlength uint32
BaudRate uint32
// Flags field is a bitfield
// fBinary :1
// fParity :1
// fOutxCtsFlow :1
// fOutxDsrFlow :1
// fDtrControl :2
// fDsrSensitivity :1
// fTXContinueOnXoff :1
// fOutX :1
// fInX :1
// fErrorChar :1
// fNull :1
// fRtsControl :2
// fAbortOnError :1
// fDummy2 :17
Flags uint32
wReserved uint16
XonLim uint16
XoffLim uint16
ByteSize byte
Parity byte
StopBits byte
XonChar byte
XoffChar byte
ErrorChar byte
EOFChar byte
EvtChar byte
wReserved1 uint16
}
type commTimeouts struct {
ReadIntervalTimeout uint32
ReadTotalTimeoutMultiplier uint32
ReadTotalTimeoutConstant uint32
WriteTotalTimeoutMultiplier uint32
WriteTotalTimeoutConstant uint32
}
const (
noParity = 0
oddParity = 1
evenParity = 2
markParity = 3
spaceParity = 4
)
var parityMap = map[Parity]byte{
NoParity: noParity,
OddParity: oddParity,
EvenParity: evenParity,
MarkParity: markParity,
SpaceParity: spaceParity,
NoParity: windows.NOPARITY,
OddParity: windows.ODDPARITY,
EvenParity: windows.EVENPARITY,
MarkParity: windows.MARKPARITY,
SpaceParity: windows.SPACEPARITY,
}
const (
oneStopBit = 0
one5StopBits = 1
twoStopBits = 2
)
var stopBitsMap = map[StopBits]byte{
OneStopBit: oneStopBit,
OnePointFiveStopBits: one5StopBits,
TwoStopBits: twoStopBits,
OneStopBit: windows.ONESTOPBIT,
OnePointFiveStopBits: windows.ONE5STOPBITS,
TwoStopBits: windows.TWOSTOPBITS,
}
const (
commFunctionSetXOFF = 1
commFunctionSetXON = 2
commFunctionSetRTS = 3
commFunctionClrRTS = 4
commFunctionSetDTR = 5
commFunctionClrDTR = 6
commFunctionSetBreak = 8
commFunctionClrBreak = 9
)
const (
msCTSOn = 0x0010
msDSROn = 0x0020
msRingOn = 0x0040
msRLSDOn = 0x0080
)
func (port *windowsPort) SetMode(mode *Mode) error {
params := dcb{}
if getCommState(port.handle, &params) != nil {
params := windows.DCB{}
if windows.GetCommState(port.handle, &params) != nil {
port.Close()
return &PortError{code: InvalidSerialPort}
}
port.setModeParams(mode, &params)
if setCommState(port.handle, &params) != nil {
if windows.SetCommState(port.handle, &params) != nil {
port.Close()
return &PortError{code: InvalidSerialPort}
}
return nil
}
func (port *windowsPort) setModeParams(mode *Mode, params *dcb) {
func (port *windowsPort) setModeParams(mode *Mode, params *windows.DCB) {
if mode.BaudRate == 0 {
params.BaudRate = 9600 // Default to 9600
params.BaudRate = windows.CBR_9600 // Default to 9600
} else {
params.BaudRate = uint32(mode.BaudRate)
}
@@ -278,22 +179,22 @@ func (port *windowsPort) setModeParams(mode *Mode, params *dcb) {
}
func (port *windowsPort) SetDTR(dtr bool) error {
// Like for RTS there are problems with the escapeCommFunction
// Like for RTS there are problems with the windows.EscapeCommFunction
// observed behaviour was that DTR is set from false -> true
// when setting RTS from true -> false
// 1) Connect -> RTS = true (low) DTR = true (low) OKAY
// 2) SetDTR(false) -> RTS = true (low) DTR = false (high) OKAY
// 3) SetRTS(false) -> RTS = false (high) DTR = true (low) ERROR: DTR toggled
// 2) SetDTR(false) -> RTS = true (low) DTR = false (heigh) OKAY
// 3) SetRTS(false) -> RTS = false (heigh) DTR = true (low) ERROR: DTR toggled
//
// In addition this way the CommState Flags are not updated
/*
var res bool
var err error
if dtr {
res = escapeCommFunction(port.handle, commFunctionSetDTR)
err = windows.EscapeCommFunction(port.handle, windows.SETDTR)
} else {
res = escapeCommFunction(port.handle, commFunctionClrDTR)
err = windows.EscapeCommFunction(port.handle, windows.CLTDTR)
}
if !res {
if err != nil {
return &PortError{}
}
return nil
@@ -301,15 +202,15 @@ func (port *windowsPort) SetDTR(dtr bool) error {
// The following seems a more reliable way to do it
params := &dcb{}
if err := getCommState(port.handle, params); err != nil {
params := &windows.DCB{}
if err := windows.GetCommState(port.handle, params); err != nil {
return &PortError{causedBy: err}
}
params.Flags &= dcbDTRControlDisableMask
if dtr {
params.Flags |= dcbDTRControlEnable
params.Flags |= windows.DTR_CONTROL_ENABLE
}
if err := setCommState(port.handle, params); err != nil {
if err := windows.SetCommState(port.handle, params); err != nil {
return &PortError{causedBy: err}
}
@@ -325,13 +226,13 @@ func (port *windowsPort) SetRTS(rts bool) error {
// In addition this way the CommState Flags are not updated
/*
var res bool
var err error
if rts {
res = escapeCommFunction(port.handle, commFunctionSetRTS)
err = windows.EscapeCommFunction(port.handle, windows.SETRTS)
} else {
res = escapeCommFunction(port.handle, commFunctionClrRTS)
err = windows.EscapeCommFunction(port.handle, windows.CLRRTS)
}
if !res {
if err != nil {
return &PortError{}
}
return nil
@@ -339,15 +240,15 @@ func (port *windowsPort) SetRTS(rts bool) error {
// The following seems a more reliable way to do it
params := &dcb{}
if err := getCommState(port.handle, params); err != nil {
params := &windows.DCB{}
if err := windows.GetCommState(port.handle, params); err != nil {
return &PortError{causedBy: err}
}
params.Flags &= dcbRTSControlDisableMask
if rts {
params.Flags |= dcbRTSControlEnable
params.Flags |= windows.RTS_CONTROL_ENABLE
}
if err := setCommState(port.handle, params); err != nil {
if err := windows.SetCommState(port.handle, params); err != nil {
return &PortError{causedBy: err}
}
return nil
@@ -355,19 +256,19 @@ func (port *windowsPort) SetRTS(rts bool) error {
func (port *windowsPort) GetModemStatusBits() (*ModemStatusBits, error) {
var bits uint32
if !getCommModemStatus(port.handle, &bits) {
if err := windows.GetCommModemStatus(port.handle, &bits); err != nil {
return nil, &PortError{}
}
return &ModemStatusBits{
CTS: (bits & msCTSOn) != 0,
DCD: (bits & msRLSDOn) != 0,
DSR: (bits & msDSROn) != 0,
RI: (bits & msRingOn) != 0,
CTS: (bits & windows.EV_CTS) != 0,
DCD: (bits & windows.EV_RLSD) != 0,
DSR: (bits & windows.EV_DSR) != 0,
RI: (bits & windows.EV_RING) != 0,
}, nil
}
func (port *windowsPort) SetReadTimeout(timeout time.Duration) error {
commTimeouts := &commTimeouts{
commTimeouts := &windows.CommTimeouts{
ReadIntervalTimeout: 0xFFFFFFFF,
ReadTotalTimeoutMultiplier: 0xFFFFFFFF,
ReadTotalTimeoutConstant: 0xFFFFFFFE,
@@ -382,7 +283,7 @@ func (port *windowsPort) SetReadTimeout(timeout time.Duration) error {
commTimeouts.ReadTotalTimeoutConstant = uint32(ms)
}
if err := setCommTimeouts(port.handle, commTimeouts); err != nil {
if err := windows.SetCommTimeouts(port.handle, commTimeouts); err != nil {
return &PortError{code: InvalidTimeoutValue, causedBy: err}
}
@@ -390,42 +291,42 @@ func (port *windowsPort) SetReadTimeout(timeout time.Duration) error {
}
func (port *windowsPort) Break(d time.Duration) error {
if err := setCommBreak(port.handle); err != nil {
if err := windows.SetCommBreak(port.handle); err != nil {
return &PortError{causedBy: err}
}
time.Sleep(d)
if err := clearCommBreak(port.handle); err != nil {
if err := windows.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
func createOverlappedEvent() (*windows.Overlapped, error) {
h, err := windows.CreateEvent(nil, 1, 0, nil)
return &windows.Overlapped{HEvent: h}, err
}
func nativeOpen(portName string, mode *Mode) (*windowsPort, error) {
portName = "\\\\.\\" + portName
path, err := syscall.UTF16PtrFromString(portName)
path, err := windows.UTF16PtrFromString(portName)
if err != nil {
return nil, err
}
handle, err := syscall.CreateFile(
handle, err := windows.CreateFile(
path,
syscall.GENERIC_READ|syscall.GENERIC_WRITE,
windows.GENERIC_READ|windows.GENERIC_WRITE,
0, nil,
syscall.OPEN_EXISTING,
syscall.FILE_FLAG_OVERLAPPED,
windows.OPEN_EXISTING,
windows.FILE_FLAG_OVERLAPPED,
0)
if err != nil {
switch err {
case syscall.ERROR_ACCESS_DENIED:
case windows.ERROR_ACCESS_DENIED:
return nil, &PortError{code: PortBusy}
case syscall.ERROR_FILE_NOT_FOUND:
case windows.ERROR_FILE_NOT_FOUND:
return nil, &PortError{code: PortNotFound}
}
return nil, err
@@ -436,8 +337,8 @@ func nativeOpen(portName string, mode *Mode) (*windowsPort, error) {
}
// Set port parameters
params := &dcb{}
if getCommState(port.handle, params) != nil {
params := &windows.DCB{}
if windows.GetCommState(port.handle, params) != nil {
port.Close()
return nil, &PortError{code: InvalidSerialPort}
}
@@ -445,14 +346,14 @@ func nativeOpen(portName string, mode *Mode) (*windowsPort, error) {
params.Flags &= dcbDTRControlDisableMask
params.Flags &= dcbRTSControlDisableMask
if mode.InitialStatusBits == nil {
params.Flags |= dcbDTRControlEnable
params.Flags |= dcbRTSControlEnable
params.Flags |= windows.DTR_CONTROL_ENABLE
params.Flags |= windows.RTS_CONTROL_ENABLE
} else {
if mode.InitialStatusBits.DTR {
params.Flags |= dcbDTRControlEnable
params.Flags |= windows.DTR_CONTROL_ENABLE
}
if mode.InitialStatusBits.RTS {
params.Flags |= dcbRTSControlEnable
params.Flags |= windows.RTS_CONTROL_ENABLE
}
}
params.Flags &^= dcbOutXCTSFlow
@@ -468,7 +369,7 @@ func nativeOpen(portName string, mode *Mode) (*windowsPort, error) {
params.XoffLim = 512
params.XonChar = 17 // DC1
params.XoffChar = 19 // C3
if setCommState(port.handle, params) != nil {
if windows.SetCommState(port.handle, params) != nil {
port.Close()
return nil, &PortError{code: InvalidSerialPort}
}

View File

@@ -1,31 +0,0 @@
//
// Copyright 2014-2024 Cristian Maglie. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
package serial
//sys regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, value *uint16, valueLen *uint32) (regerrno error) = advapi32.RegEnumValueW
//sys getCommState(handle syscall.Handle, dcb *dcb) (err error) = GetCommState
//sys setCommState(handle syscall.Handle, dcb *dcb) (err error) = SetCommState
//sys setCommTimeouts(handle syscall.Handle, timeouts *commTimeouts) (err error) = SetCommTimeouts
//sys escapeCommFunction(handle syscall.Handle, function uint32) (res bool) = EscapeCommFunction
//sys getCommModemStatus(handle syscall.Handle, bits *uint32) (res bool) = GetCommModemStatus
//sys createEvent(eventAttributes *uint32, manualReset bool, initialState bool, name *uint16) (handle syscall.Handle, err error) = CreateEventW
//sys resetEvent(handle syscall.Handle) (err error) = ResetEvent
//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

View File

@@ -1,161 +0,0 @@
// Code generated by 'go generate'; DO NOT EDIT.
package serial
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var _ unsafe.Pointer
// Do the interface allocations only once for common
// Errno values.
const (
errnoERROR_IO_PENDING = 997
)
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
errERROR_EINVAL error = syscall.EINVAL
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return errERROR_EINVAL
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
// TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running
// all.bat?)
return e
}
var (
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW")
procClearCommBreak = modkernel32.NewProc("ClearCommBreak")
procCreateEventW = modkernel32.NewProc("CreateEventW")
procEscapeCommFunction = modkernel32.NewProc("EscapeCommFunction")
procGetCommModemStatus = modkernel32.NewProc("GetCommModemStatus")
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) {
r0, _, _ := syscall.Syscall9(procRegEnumValueW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(value)), uintptr(unsafe.Pointer(valueLen)), 0)
if r0 != 0 {
regerrno = syscall.Errno(r0)
}
return
}
func clearCommBreak(handle syscall.Handle) (err error) {
r1, _, e1 := syscall.Syscall(procClearCommBreak.Addr(), 1, uintptr(handle), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func createEvent(eventAttributes *uint32, manualReset bool, initialState bool, name *uint16) (handle syscall.Handle, err error) {
var _p0 uint32
if manualReset {
_p0 = 1
}
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
}
func escapeCommFunction(handle syscall.Handle, function uint32) (res bool) {
r0, _, _ := syscall.Syscall(procEscapeCommFunction.Addr(), 2, uintptr(handle), uintptr(function), 0)
res = r0 != 0
return
}
func getCommModemStatus(handle syscall.Handle, bits *uint32) (res bool) {
r0, _, _ := syscall.Syscall(procGetCommModemStatus.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(bits)), 0)
res = r0 != 0
return
}
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 {
err = errnoErr(e1)
}
return
}
func getOverlappedResult(handle syscall.Handle, overlapEvent *syscall.Overlapped, n *uint32, wait bool) (err error) {
var _p0 uint32
if wait {
_p0 = 1
}
r1, _, e1 := syscall.Syscall6(procGetOverlappedResult.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(overlapEvent)), uintptr(unsafe.Pointer(n)), uintptr(_p0), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func purgeComm(handle syscall.Handle, flags uint32) (err error) {
r1, _, e1 := syscall.Syscall(procPurgeComm.Addr(), 2, uintptr(handle), uintptr(flags), 0)
if r1 == 0 {
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
}