delete some unused files
This commit is contained in:
parent
dc10d3b6de
commit
206c82b9e4
22 changed files with 0 additions and 1570 deletions
1
go.mod
1
go.mod
|
@ -3,6 +3,5 @@ module github.com/DrJosh9000/sungrow
|
||||||
go 1.15
|
go 1.15
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/goburrow/serial v0.1.0
|
|
||||||
github.com/prometheus/client_golang v1.9.0
|
github.com/prometheus/client_golang v1.9.0
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,227 +0,0 @@
|
||||||
// Copyright 2014 Quoc-Viet Nguyen. All rights reserved.
|
|
||||||
// This software may be modified and distributed under the terms
|
|
||||||
// of the BSD license. See the LICENSE file for details.
|
|
||||||
|
|
||||||
package modbus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
asciiStart = ":"
|
|
||||||
asciiEnd = "\r\n"
|
|
||||||
asciiMinSize = 3
|
|
||||||
asciiMaxSize = 513
|
|
||||||
|
|
||||||
hexTable = "0123456789ABCDEF"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ASCIIClientHandler implements Packager and Transporter interface.
|
|
||||||
type ASCIIClientHandler struct {
|
|
||||||
asciiPackager
|
|
||||||
asciiSerialTransporter
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewASCIIClientHandler allocates and initializes a ASCIIClientHandler.
|
|
||||||
func NewASCIIClientHandler(address string) *ASCIIClientHandler {
|
|
||||||
handler := &ASCIIClientHandler{}
|
|
||||||
handler.Address = address
|
|
||||||
handler.Timeout = serialTimeout
|
|
||||||
handler.IdleTimeout = serialIdleTimeout
|
|
||||||
return handler
|
|
||||||
}
|
|
||||||
|
|
||||||
// ASCIIClient creates ASCII client with default handler and given connect string.
|
|
||||||
func ASCIIClient(address string) Client {
|
|
||||||
handler := NewASCIIClientHandler(address)
|
|
||||||
return NewClient(handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// asciiPackager implements Packager interface.
|
|
||||||
type asciiPackager struct {
|
|
||||||
SlaveId byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode encodes PDU in a ASCII frame:
|
|
||||||
// Start : 1 char
|
|
||||||
// Address : 2 chars
|
|
||||||
// Function : 2 chars
|
|
||||||
// Data : 0 up to 2x252 chars
|
|
||||||
// LRC : 2 chars
|
|
||||||
// End : 2 chars
|
|
||||||
func (mb *asciiPackager) Encode(pdu *ProtocolDataUnit) (adu []byte, err error) {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
|
|
||||||
if _, err = buf.WriteString(asciiStart); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err = writeHex(&buf, []byte{mb.SlaveId, pdu.FunctionCode}); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err = writeHex(&buf, pdu.Data); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Exclude the beginning colon and terminating CRLF pair characters
|
|
||||||
var lrc lrc
|
|
||||||
lrc.reset()
|
|
||||||
lrc.pushByte(mb.SlaveId).pushByte(pdu.FunctionCode).pushBytes(pdu.Data)
|
|
||||||
if err = writeHex(&buf, []byte{lrc.value()}); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, err = buf.WriteString(asciiEnd); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
adu = buf.Bytes()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify verifies response length, frame boundary and slave id.
|
|
||||||
func (mb *asciiPackager) Verify(aduRequest []byte, aduResponse []byte) (err error) {
|
|
||||||
length := len(aduResponse)
|
|
||||||
// Minimum size (including address, function and LRC)
|
|
||||||
if length < asciiMinSize+6 {
|
|
||||||
err = fmt.Errorf("modbus: response length '%v' does not meet minimum '%v'", length, 9)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Length excluding colon must be an even number
|
|
||||||
if length%2 != 1 {
|
|
||||||
err = fmt.Errorf("modbus: response length '%v' is not an even number", length-1)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// First char must be a colon
|
|
||||||
str := string(aduResponse[0:len(asciiStart)])
|
|
||||||
if str != asciiStart {
|
|
||||||
err = fmt.Errorf("modbus: response frame '%v'... is not started with '%v'", str, asciiStart)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 2 last chars must be \r\n
|
|
||||||
str = string(aduResponse[len(aduResponse)-len(asciiEnd):])
|
|
||||||
if str != asciiEnd {
|
|
||||||
err = fmt.Errorf("modbus: response frame ...'%v' is not ended with '%v'", str, asciiEnd)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Slave id
|
|
||||||
responseVal, err := readHex(aduResponse[1:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
requestVal, err := readHex(aduRequest[1:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if responseVal != requestVal {
|
|
||||||
err = fmt.Errorf("modbus: response slave id '%v' does not match request '%v'", responseVal, requestVal)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode extracts PDU from ASCII frame and verify LRC.
|
|
||||||
func (mb *asciiPackager) Decode(adu []byte) (pdu *ProtocolDataUnit, err error) {
|
|
||||||
pdu = &ProtocolDataUnit{}
|
|
||||||
// Slave address
|
|
||||||
address, err := readHex(adu[1:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Function code
|
|
||||||
if pdu.FunctionCode, err = readHex(adu[3:]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Data
|
|
||||||
dataEnd := len(adu) - 4
|
|
||||||
data := adu[5:dataEnd]
|
|
||||||
pdu.Data = make([]byte, hex.DecodedLen(len(data)))
|
|
||||||
if _, err = hex.Decode(pdu.Data, data); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// LRC
|
|
||||||
lrcVal, err := readHex(adu[dataEnd:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Calculate checksum
|
|
||||||
var lrc lrc
|
|
||||||
lrc.reset()
|
|
||||||
lrc.pushByte(address).pushByte(pdu.FunctionCode).pushBytes(pdu.Data)
|
|
||||||
if lrcVal != lrc.value() {
|
|
||||||
err = fmt.Errorf("modbus: response lrc '%v' does not match expected '%v'", lrcVal, lrc.value())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// asciiSerialTransporter implements Transporter interface.
|
|
||||||
type asciiSerialTransporter struct {
|
|
||||||
serialPort
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mb *asciiSerialTransporter) Send(aduRequest []byte) (aduResponse []byte, err error) {
|
|
||||||
mb.serialPort.mu.Lock()
|
|
||||||
defer mb.serialPort.mu.Unlock()
|
|
||||||
|
|
||||||
// Make sure port is connected
|
|
||||||
if err = mb.serialPort.connect(); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Start the timer to close when idle
|
|
||||||
mb.serialPort.lastActivity = time.Now()
|
|
||||||
mb.serialPort.startCloseTimer()
|
|
||||||
|
|
||||||
// Send the request
|
|
||||||
mb.serialPort.logf("modbus: sending %q\n", aduRequest)
|
|
||||||
if _, err = mb.port.Write(aduRequest); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Get the response
|
|
||||||
var n int
|
|
||||||
var data [asciiMaxSize]byte
|
|
||||||
length := 0
|
|
||||||
for {
|
|
||||||
if n, err = mb.port.Read(data[length:]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
length += n
|
|
||||||
if length >= asciiMaxSize || n == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
// Expect end of frame in the data received
|
|
||||||
if length > asciiMinSize {
|
|
||||||
if string(data[length-len(asciiEnd):length]) == asciiEnd {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
aduResponse = data[:length]
|
|
||||||
mb.serialPort.logf("modbus: received %q\n", aduResponse)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeHex encodes byte to string in hexadecimal, e.g. 0xA5 => "A5"
|
|
||||||
// (encoding/hex only supports lowercase string).
|
|
||||||
func writeHex(buf *bytes.Buffer, value []byte) (err error) {
|
|
||||||
var str [2]byte
|
|
||||||
for _, v := range value {
|
|
||||||
str[0] = hexTable[v>>4]
|
|
||||||
str[1] = hexTable[v&0x0F]
|
|
||||||
|
|
||||||
if _, err = buf.Write(str[:]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// readHex decodes hexa string to byte, e.g. "8C" => 0x8C.
|
|
||||||
func readHex(data []byte) (value byte, err error) {
|
|
||||||
var dst [1]byte
|
|
||||||
if _, err = hex.Decode(dst[:], data[0:2]); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
value = dst[0]
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -1,210 +0,0 @@
|
||||||
// Copyright 2014 Quoc-Viet Nguyen. All rights reserved.
|
|
||||||
// This software may be modified and distributed under the terms
|
|
||||||
// of the BSD license. See the LICENSE file for details.
|
|
||||||
|
|
||||||
package modbus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
rtuMinSize = 4
|
|
||||||
rtuMaxSize = 256
|
|
||||||
|
|
||||||
rtuExceptionSize = 5
|
|
||||||
)
|
|
||||||
|
|
||||||
// RTUClientHandler implements Packager and Transporter interface.
|
|
||||||
type RTUClientHandler struct {
|
|
||||||
rtuPackager
|
|
||||||
rtuSerialTransporter
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRTUClientHandler allocates and initializes a RTUClientHandler.
|
|
||||||
func NewRTUClientHandler(address string) *RTUClientHandler {
|
|
||||||
handler := &RTUClientHandler{}
|
|
||||||
handler.Address = address
|
|
||||||
handler.Timeout = serialTimeout
|
|
||||||
handler.IdleTimeout = serialIdleTimeout
|
|
||||||
return handler
|
|
||||||
}
|
|
||||||
|
|
||||||
// RTUClient creates RTU client with default handler and given connect string.
|
|
||||||
func RTUClient(address string) Client {
|
|
||||||
handler := NewRTUClientHandler(address)
|
|
||||||
return NewClient(handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// rtuPackager implements Packager interface.
|
|
||||||
type rtuPackager struct {
|
|
||||||
SlaveId byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode encodes PDU in a RTU frame:
|
|
||||||
// Slave Address : 1 byte
|
|
||||||
// Function : 1 byte
|
|
||||||
// Data : 0 up to 252 bytes
|
|
||||||
// CRC : 2 byte
|
|
||||||
func (mb *rtuPackager) Encode(pdu *ProtocolDataUnit) (adu []byte, err error) {
|
|
||||||
length := len(pdu.Data) + 4
|
|
||||||
if length > rtuMaxSize {
|
|
||||||
err = fmt.Errorf("modbus: length of data '%v' must not be bigger than '%v'", length, rtuMaxSize)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
adu = make([]byte, length)
|
|
||||||
|
|
||||||
adu[0] = mb.SlaveId
|
|
||||||
adu[1] = pdu.FunctionCode
|
|
||||||
copy(adu[2:], pdu.Data)
|
|
||||||
|
|
||||||
// Append crc
|
|
||||||
var crc crc
|
|
||||||
crc.reset().pushBytes(adu[0 : length-2])
|
|
||||||
checksum := crc.value()
|
|
||||||
|
|
||||||
adu[length-1] = byte(checksum >> 8)
|
|
||||||
adu[length-2] = byte(checksum)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify verifies response length and slave id.
|
|
||||||
func (mb *rtuPackager) Verify(aduRequest []byte, aduResponse []byte) (err error) {
|
|
||||||
length := len(aduResponse)
|
|
||||||
// Minimum size (including address, function and CRC)
|
|
||||||
if length < rtuMinSize {
|
|
||||||
err = fmt.Errorf("modbus: response length '%v' does not meet minimum '%v'", length, rtuMinSize)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Slave address must match
|
|
||||||
if aduResponse[0] != aduRequest[0] {
|
|
||||||
err = fmt.Errorf("modbus: response slave id '%v' does not match request '%v'", aduResponse[0], aduRequest[0])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode extracts PDU from RTU frame and verify CRC.
|
|
||||||
func (mb *rtuPackager) Decode(adu []byte) (pdu *ProtocolDataUnit, err error) {
|
|
||||||
length := len(adu)
|
|
||||||
// Calculate checksum
|
|
||||||
var crc crc
|
|
||||||
crc.reset().pushBytes(adu[0 : length-2])
|
|
||||||
checksum := uint16(adu[length-1])<<8 | uint16(adu[length-2])
|
|
||||||
if checksum != crc.value() {
|
|
||||||
err = fmt.Errorf("modbus: response crc '%v' does not match expected '%v'", checksum, crc.value())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Function code & data
|
|
||||||
pdu = &ProtocolDataUnit{}
|
|
||||||
pdu.FunctionCode = adu[1]
|
|
||||||
pdu.Data = adu[2 : length-2]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// rtuSerialTransporter implements Transporter interface.
|
|
||||||
type rtuSerialTransporter struct {
|
|
||||||
serialPort
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mb *rtuSerialTransporter) Send(aduRequest []byte) (aduResponse []byte, err error) {
|
|
||||||
// Make sure port is connected
|
|
||||||
if err = mb.serialPort.connect(); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Start the timer to close when idle
|
|
||||||
mb.serialPort.lastActivity = time.Now()
|
|
||||||
mb.serialPort.startCloseTimer()
|
|
||||||
|
|
||||||
// Send the request
|
|
||||||
mb.serialPort.logf("modbus: sending % x\n", aduRequest)
|
|
||||||
if _, err = mb.port.Write(aduRequest); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
function := aduRequest[1]
|
|
||||||
functionFail := aduRequest[1] & 0x80
|
|
||||||
bytesToRead := calculateResponseLength(aduRequest)
|
|
||||||
time.Sleep(mb.calculateDelay(len(aduRequest) + bytesToRead))
|
|
||||||
|
|
||||||
var n int
|
|
||||||
var n1 int
|
|
||||||
var data [rtuMaxSize]byte
|
|
||||||
//We first read the minimum length and then read either the full package
|
|
||||||
//or the error package, depending on the error status (byte 2 of the response)
|
|
||||||
n, err = io.ReadAtLeast(mb.port, data[:], rtuMinSize)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//if the function is correct
|
|
||||||
if data[1] == function {
|
|
||||||
//we read the rest of the bytes
|
|
||||||
if n < bytesToRead {
|
|
||||||
if bytesToRead > rtuMinSize && bytesToRead <= rtuMaxSize {
|
|
||||||
if bytesToRead > n {
|
|
||||||
n1, err = io.ReadFull(mb.port, data[n:bytesToRead])
|
|
||||||
n += n1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if data[1] == functionFail {
|
|
||||||
//for error we need to read 5 bytes
|
|
||||||
if n < rtuExceptionSize {
|
|
||||||
n1, err = io.ReadFull(mb.port, data[n:rtuExceptionSize])
|
|
||||||
}
|
|
||||||
n += n1
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
aduResponse = data[:n]
|
|
||||||
mb.serialPort.logf("modbus: received % x\n", aduResponse)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculateDelay roughly calculates time needed for the next frame.
|
|
||||||
// See MODBUS over Serial Line - Specification and Implementation Guide (page 13).
|
|
||||||
func (mb *rtuSerialTransporter) calculateDelay(chars int) time.Duration {
|
|
||||||
var characterDelay, frameDelay int // us
|
|
||||||
|
|
||||||
if mb.BaudRate <= 0 || mb.BaudRate > 19200 {
|
|
||||||
characterDelay = 750
|
|
||||||
frameDelay = 1750
|
|
||||||
} else {
|
|
||||||
characterDelay = 15000000 / mb.BaudRate
|
|
||||||
frameDelay = 35000000 / mb.BaudRate
|
|
||||||
}
|
|
||||||
return time.Duration(characterDelay*chars+frameDelay) * time.Microsecond
|
|
||||||
}
|
|
||||||
|
|
||||||
func calculateResponseLength(adu []byte) int {
|
|
||||||
length := rtuMinSize
|
|
||||||
switch adu[1] {
|
|
||||||
case FuncCodeReadDiscreteInputs,
|
|
||||||
FuncCodeReadCoils:
|
|
||||||
count := int(binary.BigEndian.Uint16(adu[4:]))
|
|
||||||
length += 1 + count/8
|
|
||||||
if count%8 != 0 {
|
|
||||||
length++
|
|
||||||
}
|
|
||||||
case FuncCodeReadInputRegisters,
|
|
||||||
FuncCodeReadHoldingRegisters,
|
|
||||||
FuncCodeReadWriteMultipleRegisters:
|
|
||||||
count := int(binary.BigEndian.Uint16(adu[4:]))
|
|
||||||
length += 1 + count*2
|
|
||||||
case FuncCodeWriteSingleCoil,
|
|
||||||
FuncCodeWriteMultipleCoils,
|
|
||||||
FuncCodeWriteSingleRegister,
|
|
||||||
FuncCodeWriteMultipleRegisters:
|
|
||||||
length += 4
|
|
||||||
case FuncCodeMaskWriteRegister:
|
|
||||||
length += 6
|
|
||||||
case FuncCodeReadFIFOQueue:
|
|
||||||
// undetermined
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
return length
|
|
||||||
}
|
|
102
modbus/serial.go
102
modbus/serial.go
|
@ -1,102 +0,0 @@
|
||||||
// Copyright 2014 Quoc-Viet Nguyen. All rights reserved.
|
|
||||||
// This software may be modified and distributed under the terms
|
|
||||||
// of the BSD license. See the LICENSE file for details.
|
|
||||||
|
|
||||||
package modbus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/goburrow/serial"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Default timeout
|
|
||||||
serialTimeout = 5 * time.Second
|
|
||||||
serialIdleTimeout = 60 * time.Second
|
|
||||||
)
|
|
||||||
|
|
||||||
// serialPort has configuration and I/O controller.
|
|
||||||
type serialPort struct {
|
|
||||||
// Serial port configuration.
|
|
||||||
serial.Config
|
|
||||||
|
|
||||||
Logger *log.Logger
|
|
||||||
IdleTimeout time.Duration
|
|
||||||
|
|
||||||
mu sync.Mutex
|
|
||||||
// port is platform-dependent data structure for serial port.
|
|
||||||
port io.ReadWriteCloser
|
|
||||||
lastActivity time.Time
|
|
||||||
closeTimer *time.Timer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mb *serialPort) Connect() (err error) {
|
|
||||||
mb.mu.Lock()
|
|
||||||
defer mb.mu.Unlock()
|
|
||||||
|
|
||||||
return mb.connect()
|
|
||||||
}
|
|
||||||
|
|
||||||
// connect connects to the serial port if it is not connected. Caller must hold the mutex.
|
|
||||||
func (mb *serialPort) connect() error {
|
|
||||||
if mb.port == nil {
|
|
||||||
port, err := serial.Open(&mb.Config)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
mb.port = port
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mb *serialPort) Close() (err error) {
|
|
||||||
mb.mu.Lock()
|
|
||||||
defer mb.mu.Unlock()
|
|
||||||
|
|
||||||
return mb.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// close closes the serial port if it is connected. Caller must hold the mutex.
|
|
||||||
func (mb *serialPort) close() (err error) {
|
|
||||||
if mb.port != nil {
|
|
||||||
err = mb.port.Close()
|
|
||||||
mb.port = nil
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mb *serialPort) logf(format string, v ...interface{}) {
|
|
||||||
if mb.Logger != nil {
|
|
||||||
mb.Logger.Printf(format, v...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mb *serialPort) startCloseTimer() {
|
|
||||||
if mb.IdleTimeout <= 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if mb.closeTimer == nil {
|
|
||||||
mb.closeTimer = time.AfterFunc(mb.IdleTimeout, mb.closeIdle)
|
|
||||||
} else {
|
|
||||||
mb.closeTimer.Reset(mb.IdleTimeout)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// closeIdle closes the connection if last activity is passed behind IdleTimeout.
|
|
||||||
func (mb *serialPort) closeIdle() {
|
|
||||||
mb.mu.Lock()
|
|
||||||
defer mb.mu.Unlock()
|
|
||||||
|
|
||||||
if mb.IdleTimeout <= 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
idle := time.Now().Sub(mb.lastActivity)
|
|
||||||
if idle >= mb.IdleTimeout {
|
|
||||||
mb.logf("modbus: closing connection due to idle timeout: %v", idle)
|
|
||||||
mb.close()
|
|
||||||
}
|
|
||||||
}
|
|
3
vendor/github.com/goburrow/serial/.gitattributes
generated
vendored
3
vendor/github.com/goburrow/serial/.gitattributes
generated
vendored
|
@ -1,3 +0,0 @@
|
||||||
* text=auto
|
|
||||||
*.go text
|
|
||||||
*.bat text eol=crlf
|
|
13
vendor/github.com/goburrow/serial/.travis.yml
generated
vendored
13
vendor/github.com/goburrow/serial/.travis.yml
generated
vendored
|
@ -1,13 +0,0 @@
|
||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.7
|
|
||||||
- 1.8
|
|
||||||
- tip
|
|
||||||
|
|
||||||
script:
|
|
||||||
- go test -v ./...
|
|
||||||
- GOOS=linux go build
|
|
||||||
- GOOS=darwin go build
|
|
||||||
- GOOS=freebsd go build
|
|
||||||
- GOOS=windows go build
|
|
19
vendor/github.com/goburrow/serial/LICENSE
generated
vendored
19
vendor/github.com/goburrow/serial/LICENSE
generated
vendored
|
@ -1,19 +0,0 @@
|
||||||
Copyright (c) 2015 Quoc-Viet Nguyen
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
34
vendor/github.com/goburrow/serial/README.md
generated
vendored
34
vendor/github.com/goburrow/serial/README.md
generated
vendored
|
@ -1,34 +0,0 @@
|
||||||
# serial [![Build Status](https://travis-ci.org/goburrow/serial.svg?branch=master)](https://travis-ci.org/goburrow/serial) [![GoDoc](https://godoc.org/github.com/goburrow/serial?status.svg)](https://godoc.org/github.com/goburrow/serial)
|
|
||||||
## Example
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/goburrow/serial"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
port, err := serial.Open(&serial.Config{Address: "/dev/ttyUSB0"})
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer port.Close()
|
|
||||||
|
|
||||||
_, err = port.Write([]byte("serial"))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
### Linux and Mac OS
|
|
||||||
- `socat -d -d pty,raw,echo=0 pty,raw,echo=0`
|
|
||||||
- on Mac OS, the socat command can be installed using homebrew:
|
|
||||||
````brew install socat````
|
|
||||||
|
|
||||||
### Windows
|
|
||||||
- [Null-modem emulator](http://com0com.sourceforge.net/)
|
|
||||||
- [Terminal](https://sites.google.com/site/terminalbpp/)
|
|
2
vendor/github.com/goburrow/serial/generate.bat
generated
vendored
2
vendor/github.com/goburrow/serial/generate.bat
generated
vendored
|
@ -1,2 +0,0 @@
|
||||||
go tool cgo -godefs types_windows.go | gofmt > ztypes_windows.go
|
|
||||||
go generate syscall_windows.go
|
|
64
vendor/github.com/goburrow/serial/serial.go
generated
vendored
64
vendor/github.com/goburrow/serial/serial.go
generated
vendored
|
@ -1,64 +0,0 @@
|
||||||
/*
|
|
||||||
Package serial provides a cross-platform serial reader and writer.
|
|
||||||
*/
|
|
||||||
package serial
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrTimeout is occurred when timing out.
|
|
||||||
ErrTimeout = errors.New("serial: timeout")
|
|
||||||
)
|
|
||||||
|
|
||||||
// Config is common configuration for serial port.
|
|
||||||
type Config struct {
|
|
||||||
// Device path (/dev/ttyS0)
|
|
||||||
Address string
|
|
||||||
// Baud rate (default 19200)
|
|
||||||
BaudRate int
|
|
||||||
// Data bits: 5, 6, 7 or 8 (default 8)
|
|
||||||
DataBits int
|
|
||||||
// Stop bits: 1 or 2 (default 1)
|
|
||||||
StopBits int
|
|
||||||
// Parity: N - None, E - Even, O - Odd (default E)
|
|
||||||
// (The use of no parity requires 2 stop bits.)
|
|
||||||
Parity string
|
|
||||||
// Read (Write) timeout.
|
|
||||||
Timeout time.Duration
|
|
||||||
// Configuration related to RS485
|
|
||||||
RS485 RS485Config
|
|
||||||
}
|
|
||||||
|
|
||||||
// platform independent RS485 config. Thie structure is ignored unless Enable is true.
|
|
||||||
type RS485Config struct {
|
|
||||||
// Enable RS485 support
|
|
||||||
Enabled bool
|
|
||||||
// Delay RTS prior to send
|
|
||||||
DelayRtsBeforeSend time.Duration
|
|
||||||
// Delay RTS after send
|
|
||||||
DelayRtsAfterSend time.Duration
|
|
||||||
// Set RTS high during send
|
|
||||||
RtsHighDuringSend bool
|
|
||||||
// Set RTS high after send
|
|
||||||
RtsHighAfterSend bool
|
|
||||||
// Rx during Tx
|
|
||||||
RxDuringTx bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Port is the interface for controlling serial port.
|
|
||||||
type Port interface {
|
|
||||||
io.ReadWriteCloser
|
|
||||||
// Connect connects to the serial port.
|
|
||||||
Open(*Config) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open opens a serial port.
|
|
||||||
func Open(c *Config) (p Port, err error) {
|
|
||||||
p = New()
|
|
||||||
err = p.Open(c)
|
|
||||||
return
|
|
||||||
}
|
|
93
vendor/github.com/goburrow/serial/serial_bsd.go
generated
vendored
93
vendor/github.com/goburrow/serial/serial_bsd.go
generated
vendored
|
@ -1,93 +0,0 @@
|
||||||
// +build freebsd openbsd netbsd
|
|
||||||
|
|
||||||
package serial
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
var baudRates = map[int]uint32{
|
|
||||||
50: syscall.B50,
|
|
||||||
75: syscall.B75,
|
|
||||||
110: syscall.B110,
|
|
||||||
134: syscall.B134,
|
|
||||||
150: syscall.B150,
|
|
||||||
200: syscall.B200,
|
|
||||||
300: syscall.B300,
|
|
||||||
600: syscall.B600,
|
|
||||||
1200: syscall.B1200,
|
|
||||||
1800: syscall.B1800,
|
|
||||||
2400: syscall.B2400,
|
|
||||||
4800: syscall.B4800,
|
|
||||||
9600: syscall.B9600,
|
|
||||||
19200: syscall.B19200,
|
|
||||||
38400: syscall.B38400,
|
|
||||||
57600: syscall.B57600,
|
|
||||||
115200: syscall.B115200,
|
|
||||||
230400: syscall.B230400,
|
|
||||||
460800: syscall.B460800,
|
|
||||||
}
|
|
||||||
|
|
||||||
var charSizes = map[int]uint32{
|
|
||||||
5: syscall.CS5,
|
|
||||||
6: syscall.CS6,
|
|
||||||
7: syscall.CS7,
|
|
||||||
8: syscall.CS8,
|
|
||||||
}
|
|
||||||
|
|
||||||
// syscallSelect is a wapper for syscall.Select that only returns error.
|
|
||||||
func syscallSelect(n int, r *syscall.FdSet, w *syscall.FdSet, e *syscall.FdSet, tv *syscall.Timeval) error {
|
|
||||||
return syscall.Select(n, r, w, e, tv)
|
|
||||||
}
|
|
||||||
|
|
||||||
// tcsetattr sets terminal file descriptor parameters.
|
|
||||||
// See man tcsetattr(3).
|
|
||||||
func tcsetattr(fd int, termios *syscall.Termios) (err error) {
|
|
||||||
r, _, errno := syscall.Syscall(uintptr(syscall.SYS_IOCTL),
|
|
||||||
uintptr(fd), uintptr(syscall.TIOCSETA), uintptr(unsafe.Pointer(termios)))
|
|
||||||
if errno != 0 {
|
|
||||||
err = errno
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r != 0 {
|
|
||||||
err = fmt.Errorf("tcsetattr failed %v", r)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// tcgetattr gets terminal file descriptor parameters.
|
|
||||||
// See man tcgetattr(3).
|
|
||||||
func tcgetattr(fd int, termios *syscall.Termios) (err error) {
|
|
||||||
r, _, errno := syscall.Syscall(uintptr(syscall.SYS_IOCTL),
|
|
||||||
uintptr(fd), uintptr(syscall.TIOCGETA), uintptr(unsafe.Pointer(termios)))
|
|
||||||
if errno != 0 {
|
|
||||||
err = errno
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r != 0 {
|
|
||||||
err = fmt.Errorf("tcgetattr failed %v", r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// fdget returns index and offset of fd in fds.
|
|
||||||
func fdget(fd int, fds *syscall.FdSet) (index, offset int) {
|
|
||||||
index = fd / (syscall.FD_SETSIZE / len(fds.X__fds_bits)) % len(fds.X__fds_bits)
|
|
||||||
offset = fd % (syscall.FD_SETSIZE / len(fds.X__fds_bits))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// fdset implements FD_SET macro.
|
|
||||||
func fdset(fd int, fds *syscall.FdSet) {
|
|
||||||
idx, pos := fdget(fd, fds)
|
|
||||||
fds.X__fds_bits[idx] = 1 << uint(pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
// fdisset implements FD_ISSET macro.
|
|
||||||
func fdisset(fd int, fds *syscall.FdSet) bool {
|
|
||||||
idx, pos := fdget(fd, fds)
|
|
||||||
return fds.X__fds_bits[idx]&(1<<uint(pos)) != 0
|
|
||||||
}
|
|
90
vendor/github.com/goburrow/serial/serial_darwin.go
generated
vendored
90
vendor/github.com/goburrow/serial/serial_darwin.go
generated
vendored
|
@ -1,90 +0,0 @@
|
||||||
package serial
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
var baudRates = map[int]uint64{
|
|
||||||
50: syscall.B50,
|
|
||||||
75: syscall.B75,
|
|
||||||
110: syscall.B110,
|
|
||||||
134: syscall.B134,
|
|
||||||
150: syscall.B150,
|
|
||||||
200: syscall.B200,
|
|
||||||
300: syscall.B300,
|
|
||||||
600: syscall.B600,
|
|
||||||
1200: syscall.B1200,
|
|
||||||
1800: syscall.B1800,
|
|
||||||
2400: syscall.B2400,
|
|
||||||
4800: syscall.B4800,
|
|
||||||
9600: syscall.B9600,
|
|
||||||
19200: syscall.B19200,
|
|
||||||
38400: syscall.B38400,
|
|
||||||
57600: syscall.B57600,
|
|
||||||
115200: syscall.B115200,
|
|
||||||
230400: syscall.B230400,
|
|
||||||
}
|
|
||||||
|
|
||||||
var charSizes = map[int]uint64{
|
|
||||||
5: syscall.CS5,
|
|
||||||
6: syscall.CS6,
|
|
||||||
7: syscall.CS7,
|
|
||||||
8: syscall.CS8,
|
|
||||||
}
|
|
||||||
|
|
||||||
// syscallSelect is a wapper for syscall.Select that only returns error.
|
|
||||||
func syscallSelect(n int, r *syscall.FdSet, w *syscall.FdSet, e *syscall.FdSet, tv *syscall.Timeval) error {
|
|
||||||
return syscall.Select(n, r, w, e, tv)
|
|
||||||
}
|
|
||||||
|
|
||||||
// tcsetattr sets terminal file descriptor parameters.
|
|
||||||
// See man tcsetattr(3).
|
|
||||||
func tcsetattr(fd int, termios *syscall.Termios) (err error) {
|
|
||||||
r, _, errno := syscall.Syscall(uintptr(syscall.SYS_IOCTL),
|
|
||||||
uintptr(fd), uintptr(syscall.TIOCSETA), uintptr(unsafe.Pointer(termios)))
|
|
||||||
if errno != 0 {
|
|
||||||
err = errno
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r != 0 {
|
|
||||||
err = fmt.Errorf("tcsetattr failed %v", r)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// tcgetattr gets terminal file descriptor parameters.
|
|
||||||
// See man tcgetattr(3).
|
|
||||||
func tcgetattr(fd int, termios *syscall.Termios) (err error) {
|
|
||||||
r, _, errno := syscall.Syscall(uintptr(syscall.SYS_IOCTL),
|
|
||||||
uintptr(fd), uintptr(syscall.TIOCGETA), uintptr(unsafe.Pointer(termios)))
|
|
||||||
if errno != 0 {
|
|
||||||
err = errno
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r != 0 {
|
|
||||||
err = fmt.Errorf("tcgetattr failed %v", r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// fdget returns index and offset of fd in fds.
|
|
||||||
func fdget(fd int, fds *syscall.FdSet) (index, offset int) {
|
|
||||||
index = fd / (syscall.FD_SETSIZE / len(fds.Bits)) % len(fds.Bits)
|
|
||||||
offset = fd % (syscall.FD_SETSIZE / len(fds.Bits))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// fdset implements FD_SET macro.
|
|
||||||
func fdset(fd int, fds *syscall.FdSet) {
|
|
||||||
idx, pos := fdget(fd, fds)
|
|
||||||
fds.Bits[idx] = 1 << uint(pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
// fdisset implements FD_ISSET macro.
|
|
||||||
func fdisset(fd int, fds *syscall.FdSet) bool {
|
|
||||||
idx, pos := fdget(fd, fds)
|
|
||||||
return fds.Bits[idx]&(1<<uint(pos)) != 0
|
|
||||||
}
|
|
103
vendor/github.com/goburrow/serial/serial_linux.go
generated
vendored
103
vendor/github.com/goburrow/serial/serial_linux.go
generated
vendored
|
@ -1,103 +0,0 @@
|
||||||
package serial
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
var baudRates = map[int]uint32{
|
|
||||||
50: syscall.B50,
|
|
||||||
75: syscall.B75,
|
|
||||||
110: syscall.B110,
|
|
||||||
134: syscall.B134,
|
|
||||||
150: syscall.B150,
|
|
||||||
200: syscall.B200,
|
|
||||||
300: syscall.B300,
|
|
||||||
600: syscall.B600,
|
|
||||||
1200: syscall.B1200,
|
|
||||||
1800: syscall.B1800,
|
|
||||||
2400: syscall.B2400,
|
|
||||||
4800: syscall.B4800,
|
|
||||||
9600: syscall.B9600,
|
|
||||||
19200: syscall.B19200,
|
|
||||||
38400: syscall.B38400,
|
|
||||||
57600: syscall.B57600,
|
|
||||||
115200: syscall.B115200,
|
|
||||||
230400: syscall.B230400,
|
|
||||||
460800: syscall.B460800,
|
|
||||||
500000: syscall.B500000,
|
|
||||||
576000: syscall.B576000,
|
|
||||||
921600: syscall.B921600,
|
|
||||||
1000000: syscall.B1000000,
|
|
||||||
1152000: syscall.B1152000,
|
|
||||||
1500000: syscall.B1500000,
|
|
||||||
2000000: syscall.B2000000,
|
|
||||||
2500000: syscall.B2500000,
|
|
||||||
3000000: syscall.B3000000,
|
|
||||||
3500000: syscall.B3500000,
|
|
||||||
4000000: syscall.B4000000,
|
|
||||||
}
|
|
||||||
|
|
||||||
var charSizes = map[int]uint32{
|
|
||||||
5: syscall.CS5,
|
|
||||||
6: syscall.CS6,
|
|
||||||
7: syscall.CS7,
|
|
||||||
8: syscall.CS8,
|
|
||||||
}
|
|
||||||
|
|
||||||
// syscallSelect is a wapper for syscall.Select that only returns error.
|
|
||||||
func syscallSelect(n int, r *syscall.FdSet, w *syscall.FdSet, e *syscall.FdSet, tv *syscall.Timeval) error {
|
|
||||||
_, err := syscall.Select(n, r, w, e, tv)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// tcsetattr sets terminal file descriptor parameters.
|
|
||||||
// See man tcsetattr(3).
|
|
||||||
func tcsetattr(fd int, termios *syscall.Termios) (err error) {
|
|
||||||
r, _, errno := syscall.Syscall(uintptr(syscall.SYS_IOCTL),
|
|
||||||
uintptr(fd), uintptr(syscall.TCSETS), uintptr(unsafe.Pointer(termios)))
|
|
||||||
if errno != 0 {
|
|
||||||
err = errno
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r != 0 {
|
|
||||||
err = fmt.Errorf("tcsetattr failed %v", r)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// tcgetattr gets terminal file descriptor parameters.
|
|
||||||
// See man tcgetattr(3).
|
|
||||||
func tcgetattr(fd int, termios *syscall.Termios) (err error) {
|
|
||||||
r, _, errno := syscall.Syscall(uintptr(syscall.SYS_IOCTL),
|
|
||||||
uintptr(fd), uintptr(syscall.TCGETS), uintptr(unsafe.Pointer(termios)))
|
|
||||||
if errno != 0 {
|
|
||||||
err = errno
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r != 0 {
|
|
||||||
err = fmt.Errorf("tcgetattr failed %v", r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// fdget returns index and offset of fd in fds.
|
|
||||||
func fdget(fd int, fds *syscall.FdSet) (index, offset int) {
|
|
||||||
index = fd / (syscall.FD_SETSIZE / len(fds.Bits)) % len(fds.Bits)
|
|
||||||
offset = fd % (syscall.FD_SETSIZE / len(fds.Bits))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// fdset implements FD_SET macro.
|
|
||||||
func fdset(fd int, fds *syscall.FdSet) {
|
|
||||||
idx, pos := fdget(fd, fds)
|
|
||||||
fds.Bits[idx] = 1 << uint(pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
// fdisset implements FD_ISSET macro.
|
|
||||||
func fdisset(fd int, fds *syscall.FdSet) bool {
|
|
||||||
idx, pos := fdget(fd, fds)
|
|
||||||
return fds.Bits[idx]&(1<<uint(pos)) != 0
|
|
||||||
}
|
|
265
vendor/github.com/goburrow/serial/serial_posix.go
generated
vendored
265
vendor/github.com/goburrow/serial/serial_posix.go
generated
vendored
|
@ -1,265 +0,0 @@
|
||||||
// +build darwin linux freebsd openbsd netbsd
|
|
||||||
|
|
||||||
package serial
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// port implements Port interface.
|
|
||||||
type port struct {
|
|
||||||
fd int
|
|
||||||
oldTermios *syscall.Termios
|
|
||||||
|
|
||||||
timeout time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
rs485Enabled = 1 << 0
|
|
||||||
rs485RTSOnSend = 1 << 1
|
|
||||||
rs485RTSAfterSend = 1 << 2
|
|
||||||
rs485RXDuringTX = 1 << 4
|
|
||||||
rs485Tiocs = 0x542f
|
|
||||||
)
|
|
||||||
|
|
||||||
// rs485_ioctl_opts is used to configure RS485 options in the driver
|
|
||||||
type rs485_ioctl_opts struct {
|
|
||||||
flags uint32
|
|
||||||
delay_rts_before_send uint32
|
|
||||||
delay_rts_after_send uint32
|
|
||||||
padding [5]uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
// New allocates and returns a new serial port controller.
|
|
||||||
func New() Port {
|
|
||||||
return &port{fd: -1}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open connects to the given serial port.
|
|
||||||
func (p *port) Open(c *Config) (err error) {
|
|
||||||
termios, err := newTermios(c)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// See man termios(3).
|
|
||||||
// O_NOCTTY: no controlling terminal.
|
|
||||||
// O_NDELAY: no data carrier detect.
|
|
||||||
p.fd, err = syscall.Open(c.Address, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NDELAY|syscall.O_CLOEXEC, 0666)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Backup current termios to restore on closing.
|
|
||||||
p.backupTermios()
|
|
||||||
if err = p.setTermios(termios); err != nil {
|
|
||||||
// No need to restore termios
|
|
||||||
syscall.Close(p.fd)
|
|
||||||
p.fd = -1
|
|
||||||
p.oldTermios = nil
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err = enableRS485(p.fd, &c.RS485); err != nil {
|
|
||||||
p.Close()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
p.timeout = c.Timeout
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *port) Close() (err error) {
|
|
||||||
if p.fd == -1 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.restoreTermios()
|
|
||||||
err = syscall.Close(p.fd)
|
|
||||||
p.fd = -1
|
|
||||||
p.oldTermios = nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read reads from serial port. Port must be opened before calling this method.
|
|
||||||
// It is blocked until all data received or timeout after p.timeout.
|
|
||||||
func (p *port) Read(b []byte) (n int, err error) {
|
|
||||||
var rfds syscall.FdSet
|
|
||||||
|
|
||||||
fd := p.fd
|
|
||||||
fdset(fd, &rfds)
|
|
||||||
|
|
||||||
var tv *syscall.Timeval
|
|
||||||
if p.timeout > 0 {
|
|
||||||
timeout := syscall.NsecToTimeval(p.timeout.Nanoseconds())
|
|
||||||
tv = &timeout
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
// If syscall.Select() returns EINTR (Interrupted system call), retry it
|
|
||||||
if err = syscallSelect(fd+1, &rfds, nil, nil, tv); err == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if err != syscall.EINTR {
|
|
||||||
err = fmt.Errorf("serial: could not select: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !fdisset(fd, &rfds) {
|
|
||||||
// Timeout
|
|
||||||
err = ErrTimeout
|
|
||||||
return
|
|
||||||
}
|
|
||||||
n, err = syscall.Read(fd, b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write writes data to the serial port.
|
|
||||||
func (p *port) Write(b []byte) (n int, err error) {
|
|
||||||
n, err = syscall.Write(p.fd, b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *port) setTermios(termios *syscall.Termios) (err error) {
|
|
||||||
if err = tcsetattr(p.fd, termios); err != nil {
|
|
||||||
err = fmt.Errorf("serial: could not set setting: %v", err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// backupTermios saves current termios setting.
|
|
||||||
// Make sure that device file has been opened before calling this function.
|
|
||||||
func (p *port) backupTermios() {
|
|
||||||
oldTermios := &syscall.Termios{}
|
|
||||||
if err := tcgetattr(p.fd, oldTermios); err != nil {
|
|
||||||
// Warning only.
|
|
||||||
log.Printf("serial: could not get setting: %v\n", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Will be reloaded when closing.
|
|
||||||
p.oldTermios = oldTermios
|
|
||||||
}
|
|
||||||
|
|
||||||
// restoreTermios restores backed up termios setting.
|
|
||||||
// Make sure that device file has been opened before calling this function.
|
|
||||||
func (p *port) restoreTermios() {
|
|
||||||
if p.oldTermios == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err := tcsetattr(p.fd, p.oldTermios); err != nil {
|
|
||||||
// Warning only.
|
|
||||||
log.Printf("serial: could not restore setting: %v\n", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.oldTermios = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helpers for termios
|
|
||||||
|
|
||||||
func newTermios(c *Config) (termios *syscall.Termios, err error) {
|
|
||||||
termios = &syscall.Termios{}
|
|
||||||
flag := termios.Cflag
|
|
||||||
// Baud rate
|
|
||||||
if c.BaudRate == 0 {
|
|
||||||
// 19200 is the required default.
|
|
||||||
flag = syscall.B19200
|
|
||||||
} else {
|
|
||||||
var ok bool
|
|
||||||
flag, ok = baudRates[c.BaudRate]
|
|
||||||
if !ok {
|
|
||||||
err = fmt.Errorf("serial: unsupported baud rate %v", c.BaudRate)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
termios.Cflag |= flag
|
|
||||||
// Input baud.
|
|
||||||
cfSetIspeed(termios, flag)
|
|
||||||
// Output baud.
|
|
||||||
cfSetOspeed(termios, flag)
|
|
||||||
// Character size.
|
|
||||||
if c.DataBits == 0 {
|
|
||||||
flag = syscall.CS8
|
|
||||||
} else {
|
|
||||||
var ok bool
|
|
||||||
flag, ok = charSizes[c.DataBits]
|
|
||||||
if !ok {
|
|
||||||
err = fmt.Errorf("serial: unsupported character size %v", c.DataBits)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
termios.Cflag |= flag
|
|
||||||
// Stop bits
|
|
||||||
switch c.StopBits {
|
|
||||||
case 0, 1:
|
|
||||||
// Default is one stop bit.
|
|
||||||
// noop
|
|
||||||
case 2:
|
|
||||||
// CSTOPB: Set two stop bits.
|
|
||||||
termios.Cflag |= syscall.CSTOPB
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("serial: unsupported stop bits %v", c.StopBits)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch c.Parity {
|
|
||||||
case "N":
|
|
||||||
// noop
|
|
||||||
case "O":
|
|
||||||
// PARODD: Parity is odd.
|
|
||||||
termios.Cflag |= syscall.PARODD
|
|
||||||
fallthrough
|
|
||||||
case "", "E":
|
|
||||||
// As mentioned in the modbus spec, the default parity mode must be Even parity
|
|
||||||
// PARENB: Enable parity generation on output.
|
|
||||||
termios.Cflag |= syscall.PARENB
|
|
||||||
// INPCK: Enable input parity checking.
|
|
||||||
termios.Iflag |= syscall.INPCK
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("serial: unsupported parity %v", c.Parity)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Control modes.
|
|
||||||
// CREAD: Enable receiver.
|
|
||||||
// CLOCAL: Ignore control lines.
|
|
||||||
termios.Cflag |= syscall.CREAD | syscall.CLOCAL
|
|
||||||
// Special characters.
|
|
||||||
// VMIN: Minimum number of characters for noncanonical read.
|
|
||||||
// VTIME: Time in deciseconds for noncanonical read.
|
|
||||||
// Both are unused as NDELAY is we utilized when opening device.
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// enableRS485 enables RS485 functionality of driver via an ioctl if the config says so
|
|
||||||
func enableRS485(fd int, config *RS485Config) error {
|
|
||||||
if !config.Enabled {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
rs485 := rs485_ioctl_opts{
|
|
||||||
rs485Enabled,
|
|
||||||
uint32(config.DelayRtsBeforeSend / time.Millisecond),
|
|
||||||
uint32(config.DelayRtsAfterSend / time.Millisecond),
|
|
||||||
[5]uint32{0, 0, 0, 0, 0},
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.RtsHighDuringSend {
|
|
||||||
rs485.flags |= rs485RTSOnSend
|
|
||||||
}
|
|
||||||
if config.RtsHighAfterSend {
|
|
||||||
rs485.flags |= rs485RTSAfterSend
|
|
||||||
}
|
|
||||||
if config.RxDuringTx {
|
|
||||||
rs485.flags |= rs485RXDuringTX
|
|
||||||
}
|
|
||||||
|
|
||||||
r, _, errno := syscall.Syscall(
|
|
||||||
syscall.SYS_IOCTL,
|
|
||||||
uintptr(fd),
|
|
||||||
uintptr(rs485Tiocs),
|
|
||||||
uintptr(unsafe.Pointer(&rs485)))
|
|
||||||
if errno != 0 {
|
|
||||||
return os.NewSyscallError("SYS_IOCTL (RS485)", errno)
|
|
||||||
}
|
|
||||||
if r != 0 {
|
|
||||||
return errors.New("serial: unknown error from SYS_IOCTL (RS485)")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
168
vendor/github.com/goburrow/serial/serial_windows.go
generated
vendored
168
vendor/github.com/goburrow/serial/serial_windows.go
generated
vendored
|
@ -1,168 +0,0 @@
|
||||||
package serial
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
type port struct {
|
|
||||||
handle syscall.Handle
|
|
||||||
|
|
||||||
oldDCB c_DCB
|
|
||||||
oldTimeouts c_COMMTIMEOUTS
|
|
||||||
}
|
|
||||||
|
|
||||||
// New allocates and returns a new serial port controller.
|
|
||||||
func New() Port {
|
|
||||||
return &port{
|
|
||||||
handle: syscall.InvalidHandle,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open connects to the given serial port.
|
|
||||||
func (p *port) Open(c *Config) (err error) {
|
|
||||||
p.handle, err = newHandle(c)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if err != nil {
|
|
||||||
syscall.CloseHandle(p.handle)
|
|
||||||
p.handle = syscall.InvalidHandle
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
err = p.setSerialConfig(c)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = p.setTimeouts(c)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *port) Close() (err error) {
|
|
||||||
if p.handle == syscall.InvalidHandle {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err1 := SetCommTimeouts(p.handle, &p.oldTimeouts)
|
|
||||||
err2 := SetCommState(p.handle, &p.oldDCB)
|
|
||||||
err = syscall.CloseHandle(p.handle)
|
|
||||||
if err == nil {
|
|
||||||
if err1 == nil {
|
|
||||||
err = err2
|
|
||||||
} else {
|
|
||||||
err = err1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.handle = syscall.InvalidHandle
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read reads from serial port.
|
|
||||||
// It is blocked until data received or timeout after p.timeout.
|
|
||||||
func (p *port) Read(b []byte) (n int, err error) {
|
|
||||||
var done uint32
|
|
||||||
if err = syscall.ReadFile(p.handle, b, &done, nil); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if done == 0 {
|
|
||||||
err = ErrTimeout
|
|
||||||
return
|
|
||||||
}
|
|
||||||
n = int(done)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write writes data to the serial port.
|
|
||||||
func (p *port) Write(b []byte) (n int, err error) {
|
|
||||||
var done uint32
|
|
||||||
if err = syscall.WriteFile(p.handle, b, &done, nil); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
n = int(done)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *port) setTimeouts(c *Config) error {
|
|
||||||
var timeouts c_COMMTIMEOUTS
|
|
||||||
// Read and write timeout
|
|
||||||
if c.Timeout > 0 {
|
|
||||||
timeout := toDWORD(int(c.Timeout.Nanoseconds() / 1E6))
|
|
||||||
// wait until a byte arrived or time out
|
|
||||||
timeouts.ReadIntervalTimeout = c_MAXDWORD
|
|
||||||
timeouts.ReadTotalTimeoutMultiplier = c_MAXDWORD
|
|
||||||
timeouts.ReadTotalTimeoutConstant = timeout
|
|
||||||
timeouts.WriteTotalTimeoutConstant = timeout
|
|
||||||
}
|
|
||||||
err := GetCommTimeouts(p.handle, &p.oldTimeouts)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = SetCommTimeouts(p.handle, &timeouts)
|
|
||||||
if err != nil {
|
|
||||||
// reset
|
|
||||||
SetCommTimeouts(p.handle, &p.oldTimeouts)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *port) setSerialConfig(c *Config) error {
|
|
||||||
var dcb c_DCB
|
|
||||||
if c.BaudRate == 0 {
|
|
||||||
dcb.BaudRate = 19200
|
|
||||||
} else {
|
|
||||||
dcb.BaudRate = toDWORD(c.BaudRate)
|
|
||||||
}
|
|
||||||
// Data bits
|
|
||||||
if c.DataBits == 0 {
|
|
||||||
dcb.ByteSize = 8
|
|
||||||
} else {
|
|
||||||
dcb.ByteSize = toBYTE(c.DataBits)
|
|
||||||
}
|
|
||||||
// Stop bits
|
|
||||||
switch c.StopBits {
|
|
||||||
case 0, 1:
|
|
||||||
// Default is one stop bit.
|
|
||||||
dcb.StopBits = c_ONESTOPBIT
|
|
||||||
case 2:
|
|
||||||
dcb.StopBits = c_TWOSTOPBITS
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("serial: unsupported stop bits %v", c.StopBits)
|
|
||||||
}
|
|
||||||
// Parity
|
|
||||||
switch c.Parity {
|
|
||||||
case "", "E":
|
|
||||||
// Default parity mode is Even.
|
|
||||||
dcb.Parity = c_EVENPARITY
|
|
||||||
dcb.Pad_cgo_0[0] |= 0x02 // fParity
|
|
||||||
case "O":
|
|
||||||
dcb.Parity = c_ODDPARITY
|
|
||||||
dcb.Pad_cgo_0[0] |= 0x02 // fParity
|
|
||||||
case "N":
|
|
||||||
dcb.Parity = c_NOPARITY
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("serial: unsupported parity %v", c.Parity)
|
|
||||||
}
|
|
||||||
dcb.Pad_cgo_0[0] |= 0x01 // fBinary
|
|
||||||
|
|
||||||
err := GetCommState(p.handle, &p.oldDCB)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = SetCommState(p.handle, &dcb)
|
|
||||||
if err != nil {
|
|
||||||
SetCommState(p.handle, &p.oldDCB)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func newHandle(c *Config) (handle syscall.Handle, err error) {
|
|
||||||
handle, err = syscall.CreateFile(
|
|
||||||
syscall.StringToUTF16Ptr(c.Address),
|
|
||||||
syscall.GENERIC_READ|syscall.GENERIC_WRITE,
|
|
||||||
0, // mode
|
|
||||||
nil, // security
|
|
||||||
syscall.OPEN_EXISTING, // create mode
|
|
||||||
0, // attributes
|
|
||||||
0) // templates
|
|
||||||
return
|
|
||||||
}
|
|
15
vendor/github.com/goburrow/serial/termios_bsd.go
generated
vendored
15
vendor/github.com/goburrow/serial/termios_bsd.go
generated
vendored
|
@ -1,15 +0,0 @@
|
||||||
// +build freebsd openbsd netbsd
|
|
||||||
|
|
||||||
package serial
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
func cfSetIspeed(termios *syscall.Termios, speed uint32) {
|
|
||||||
termios.Ispeed = speed
|
|
||||||
}
|
|
||||||
|
|
||||||
func cfSetOspeed(termios *syscall.Termios, speed uint32) {
|
|
||||||
termios.Ospeed = speed
|
|
||||||
}
|
|
13
vendor/github.com/goburrow/serial/termios_darwin.go
generated
vendored
13
vendor/github.com/goburrow/serial/termios_darwin.go
generated
vendored
|
@ -1,13 +0,0 @@
|
||||||
package serial
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
func cfSetIspeed(termios *syscall.Termios, speed uint64) {
|
|
||||||
termios.Ispeed = speed
|
|
||||||
}
|
|
||||||
|
|
||||||
func cfSetOspeed(termios *syscall.Termios, speed uint64) {
|
|
||||||
termios.Ospeed = speed
|
|
||||||
}
|
|
15
vendor/github.com/goburrow/serial/termios_linux.go
generated
vendored
15
vendor/github.com/goburrow/serial/termios_linux.go
generated
vendored
|
@ -1,15 +0,0 @@
|
||||||
// +build !mips,!mipsle,!mips64,!mips64le
|
|
||||||
|
|
||||||
package serial
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
func cfSetIspeed(termios *syscall.Termios, speed uint32) {
|
|
||||||
termios.Ispeed = speed
|
|
||||||
}
|
|
||||||
|
|
||||||
func cfSetOspeed(termios *syscall.Termios, speed uint32) {
|
|
||||||
termios.Ospeed = speed
|
|
||||||
}
|
|
16
vendor/github.com/goburrow/serial/termios_mipsx.go
generated
vendored
16
vendor/github.com/goburrow/serial/termios_mipsx.go
generated
vendored
|
@ -1,16 +0,0 @@
|
||||||
// +build linux
|
|
||||||
// +build mips mipsle mips64 mips64le
|
|
||||||
|
|
||||||
package serial
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
func cfSetIspeed(termios *syscall.Termios, speed uint32) {
|
|
||||||
// MIPS has no Ispeed field in termios.
|
|
||||||
}
|
|
||||||
|
|
||||||
func cfSetOspeed(termios *syscall.Termios, speed uint32) {
|
|
||||||
// MIPS has no Ospeed field in termios.
|
|
||||||
}
|
|
67
vendor/github.com/goburrow/serial/zsyscall_windows.go
generated
vendored
67
vendor/github.com/goburrow/serial/zsyscall_windows.go
generated
vendored
|
@ -1,67 +0,0 @@
|
||||||
// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
|
|
||||||
|
|
||||||
package serial
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ unsafe.Pointer
|
|
||||||
|
|
||||||
var (
|
|
||||||
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
|
|
||||||
|
|
||||||
procGetCommState = modkernel32.NewProc("GetCommState")
|
|
||||||
procSetCommState = modkernel32.NewProc("SetCommState")
|
|
||||||
procGetCommTimeouts = modkernel32.NewProc("GetCommTimeouts")
|
|
||||||
procSetCommTimeouts = modkernel32.NewProc("SetCommTimeouts")
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetCommState(handle syscall.Handle, dcb *c_DCB) (err error) {
|
|
||||||
r1, _, e1 := syscall.Syscall(procGetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(dcb)), 0)
|
|
||||||
if r1 == 0 {
|
|
||||||
if e1 != 0 {
|
|
||||||
err = error(e1)
|
|
||||||
} else {
|
|
||||||
err = syscall.EINVAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetCommState(handle syscall.Handle, dcb *c_DCB) (err error) {
|
|
||||||
r1, _, e1 := syscall.Syscall(procSetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(dcb)), 0)
|
|
||||||
if r1 == 0 {
|
|
||||||
if e1 != 0 {
|
|
||||||
err = error(e1)
|
|
||||||
} else {
|
|
||||||
err = syscall.EINVAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetCommTimeouts(handle syscall.Handle, timeouts *c_COMMTIMEOUTS) (err error) {
|
|
||||||
r1, _, e1 := syscall.Syscall(procGetCommTimeouts.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(timeouts)), 0)
|
|
||||||
if r1 == 0 {
|
|
||||||
if e1 != 0 {
|
|
||||||
err = error(e1)
|
|
||||||
} else {
|
|
||||||
err = syscall.EINVAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetCommTimeouts(handle syscall.Handle, timeouts *c_COMMTIMEOUTS) (err error) {
|
|
||||||
r1, _, e1 := syscall.Syscall(procSetCommTimeouts.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(timeouts)), 0)
|
|
||||||
if r1 == 0 {
|
|
||||||
if e1 != 0 {
|
|
||||||
err = error(e1)
|
|
||||||
} else {
|
|
||||||
err = syscall.EINVAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
47
vendor/github.com/goburrow/serial/ztypes_windows.go
generated
vendored
47
vendor/github.com/goburrow/serial/ztypes_windows.go
generated
vendored
|
@ -1,47 +0,0 @@
|
||||||
// Created by cgo -godefs - DO NOT EDIT
|
|
||||||
// cgo -godefs types_windows.go
|
|
||||||
|
|
||||||
package serial
|
|
||||||
|
|
||||||
const (
|
|
||||||
c_MAXDWORD = 0xffffffff
|
|
||||||
c_ONESTOPBIT = 0x0
|
|
||||||
c_TWOSTOPBITS = 0x2
|
|
||||||
c_EVENPARITY = 0x2
|
|
||||||
c_ODDPARITY = 0x1
|
|
||||||
c_NOPARITY = 0x0
|
|
||||||
)
|
|
||||||
|
|
||||||
type c_COMMTIMEOUTS struct {
|
|
||||||
ReadIntervalTimeout uint32
|
|
||||||
ReadTotalTimeoutMultiplier uint32
|
|
||||||
ReadTotalTimeoutConstant uint32
|
|
||||||
WriteTotalTimeoutMultiplier uint32
|
|
||||||
WriteTotalTimeoutConstant uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type c_DCB struct {
|
|
||||||
DCBlength uint32
|
|
||||||
BaudRate uint32
|
|
||||||
Pad_cgo_0 [4]byte
|
|
||||||
WReserved uint16
|
|
||||||
XonLim uint16
|
|
||||||
XoffLim uint16
|
|
||||||
ByteSize uint8
|
|
||||||
Parity uint8
|
|
||||||
StopBits uint8
|
|
||||||
XonChar int8
|
|
||||||
XoffChar int8
|
|
||||||
ErrorChar int8
|
|
||||||
EofChar int8
|
|
||||||
EvtChar int8
|
|
||||||
WReserved1 uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
func toDWORD(val int) uint32 {
|
|
||||||
return uint32(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
func toBYTE(val int) uint8 {
|
|
||||||
return uint8(val)
|
|
||||||
}
|
|
3
vendor/modules.txt
vendored
3
vendor/modules.txt
vendored
|
@ -2,9 +2,6 @@
|
||||||
github.com/beorn7/perks/quantile
|
github.com/beorn7/perks/quantile
|
||||||
# github.com/cespare/xxhash/v2 v2.1.1
|
# github.com/cespare/xxhash/v2 v2.1.1
|
||||||
github.com/cespare/xxhash/v2
|
github.com/cespare/xxhash/v2
|
||||||
# github.com/goburrow/serial v0.1.0
|
|
||||||
## explicit
|
|
||||||
github.com/goburrow/serial
|
|
||||||
# github.com/golang/protobuf v1.4.3
|
# github.com/golang/protobuf v1.4.3
|
||||||
github.com/golang/protobuf/proto
|
github.com/golang/protobuf/proto
|
||||||
github.com/golang/protobuf/ptypes
|
github.com/golang/protobuf/ptypes
|
||||||
|
|
Loading…
Reference in a new issue