aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/tarm
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2017-08-27 17:22:56 +0200
committerDimitri Sokolyuk <demon@dim13.org>2017-08-27 17:22:56 +0200
commit3ee2c48a1d5599c4e6754636d1755b1e1e897301 (patch)
treeba857ebb21b0b13248192e1711af496227a2b202 /vendor/github.com/tarm
parent41acedced077f9da2c6b62a3932d661566af3ca6 (diff)
Add vendor
Diffstat (limited to 'vendor/github.com/tarm')
-rw-r--r--vendor/github.com/tarm/serial/.travis.yml10
-rw-r--r--vendor/github.com/tarm/serial/LICENSE27
-rw-r--r--vendor/github.com/tarm/serial/README.md82
-rw-r--r--vendor/github.com/tarm/serial/basic_test.go69
-rw-r--r--vendor/github.com/tarm/serial/serial.go167
-rw-r--r--vendor/github.com/tarm/serial/serial_linux.go157
-rw-r--r--vendor/github.com/tarm/serial/serial_posix.go196
-rw-r--r--vendor/github.com/tarm/serial/serial_windows.go327
8 files changed, 1035 insertions, 0 deletions
diff --git a/vendor/github.com/tarm/serial/.travis.yml b/vendor/github.com/tarm/serial/.travis.yml
new file mode 100644
index 0000000..1759ba5
--- /dev/null
+++ b/vendor/github.com/tarm/serial/.travis.yml
@@ -0,0 +1,10 @@
+sudo: false
+language: go
+go:
+ - 1.4
+ - 1.6
+ - tip
+env:
+ - GOOS=linux CGO=1
+ - GOOS=linux CGO=0
+ - GOOS=windows GOARCH=386
diff --git a/vendor/github.com/tarm/serial/LICENSE b/vendor/github.com/tarm/serial/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/github.com/tarm/serial/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/tarm/serial/README.md b/vendor/github.com/tarm/serial/README.md
new file mode 100644
index 0000000..d2fa899
--- /dev/null
+++ b/vendor/github.com/tarm/serial/README.md
@@ -0,0 +1,82 @@
+[![GoDoc](https://godoc.org/github.com/tarm/serial?status.svg)](http://godoc.org/github.com/tarm/serial)
+[![Build Status](https://travis-ci.org/tarm/serial.svg?branch=master)](https://travis-ci.org/tarm/serial)
+
+Serial
+========
+A Go package to allow you to read and write from the
+serial port as a stream of bytes.
+
+Details
+-------
+It aims to have the same API on all platforms, including windows. As
+an added bonus, the windows package does not use cgo, so you can cross
+compile for windows from another platform.
+
+You can cross compile with
+ GOOS=windows GOARCH=386 go install github.com/tarm/serial
+
+Currently there is very little in the way of configurability. You can
+set the baud rate. Then you can Read(), Write(), or Close() the
+connection. By default Read() will block until at least one byte is
+returned. Write is the same.
+
+Currently all ports are opened with 8 data bits, 1 stop bit, no
+parity, no hardware flow control, and no software flow control. This
+works fine for many real devices and many faux serial devices
+including usb-to-serial converters and bluetooth serial ports.
+
+You may Read() and Write() simulantiously on the same connection (from
+different goroutines).
+
+Usage
+-----
+```go
+package main
+
+import (
+ "log"
+
+ "github.com/tarm/serial"
+)
+
+func main() {
+ c := &serial.Config{Name: "COM45", Baud: 115200}
+ s, err := serial.OpenPort(c)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ n, err := s.Write([]byte("test"))
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ buf := make([]byte, 128)
+ n, err = s.Read(buf)
+ if err != nil {
+ log.Fatal(err)
+ }
+ log.Printf("%q", buf[:n])
+}
+```
+
+NonBlocking Mode
+----------------
+By default the returned Port reads in blocking mode. Which means
+`Read()` will block until at least one byte is returned. If that's not
+what you want, specify a positive ReadTimeout and the Read() will
+timeout returning 0 bytes if no bytes are read. Please note that this
+is the total timeout the read operation will wait and not the interval
+timeout between two bytes.
+
+```go
+ c := &serial.Config{Name: "COM45", Baud: 115200, ReadTimeout: time.Second * 5}
+
+ // In this mode, you will want to suppress error for read
+ // as 0 bytes return EOF error on Linux / POSIX
+ n, _ = s.Read(buf)
+```
+
+Possible Future Work
+--------------------
+- better tests (loopback etc)
diff --git a/vendor/github.com/tarm/serial/basic_test.go b/vendor/github.com/tarm/serial/basic_test.go
new file mode 100644
index 0000000..7b9af3e
--- /dev/null
+++ b/vendor/github.com/tarm/serial/basic_test.go
@@ -0,0 +1,69 @@
+// +build linux
+
+package serial
+
+import (
+ "os"
+ "testing"
+ "time"
+)
+
+func TestConnection(t *testing.T) {
+ port0 := os.Getenv("PORT0")
+ port1 := os.Getenv("PORT1")
+ if port0 == "" || port1 == "" {
+ t.Skip("Skipping test because PORT0 or PORT1 environment variable is not set")
+ }
+ c0 := &Config{Name: port0, Baud: 115200}
+ c1 := &Config{Name: port1, Baud: 115200}
+
+ s1, err := OpenPort(c0)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ s2, err := OpenPort(c1)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ch := make(chan int, 1)
+ go func() {
+ buf := make([]byte, 128)
+ var readCount int
+ for {
+ n, err := s2.Read(buf)
+ if err != nil {
+ t.Fatal(err)
+ }
+ readCount++
+ t.Logf("Read %v %v bytes: % 02x %s", readCount, n, buf[:n], buf[:n])
+ select {
+ case <-ch:
+ ch <- readCount
+ close(ch)
+ default:
+ }
+ }
+ }()
+
+ if _, err = s1.Write([]byte("hello")); err != nil {
+ t.Fatal(err)
+ }
+ if _, err = s1.Write([]byte(" ")); err != nil {
+ t.Fatal(err)
+ }
+ time.Sleep(time.Second)
+ if _, err = s1.Write([]byte("world")); err != nil {
+ t.Fatal(err)
+ }
+ time.Sleep(time.Second / 10)
+
+ ch <- 0
+ s1.Write([]byte(" ")) // We could be blocked in the read without this
+ c := <-ch
+ exp := 5
+ if c >= exp {
+ t.Fatalf("Expected less than %v read, got %v", exp, c)
+ }
+}
diff --git a/vendor/github.com/tarm/serial/serial.go b/vendor/github.com/tarm/serial/serial.go
new file mode 100644
index 0000000..f61ea28
--- /dev/null
+++ b/vendor/github.com/tarm/serial/serial.go
@@ -0,0 +1,167 @@
+/*
+Goserial is a simple go package to allow you to read and write from
+the serial port as a stream of bytes.
+
+It aims to have the same API on all platforms, including windows. As
+an added bonus, the windows package does not use cgo, so you can cross
+compile for windows from another platform. Unfortunately goinstall
+does not currently let you cross compile so you will have to do it
+manually:
+
+ GOOS=windows make clean install
+
+Currently there is very little in the way of configurability. You can
+set the baud rate. Then you can Read(), Write(), or Close() the
+connection. Read() will block until at least one byte is returned.
+Write is the same. There is currently no exposed way to set the
+timeouts, though patches are welcome.
+
+Currently all ports are opened with 8 data bits, 1 stop bit, no
+parity, no hardware flow control, and no software flow control. This
+works fine for many real devices and many faux serial devices
+including usb-to-serial converters and bluetooth serial ports.
+
+You may Read() and Write() simulantiously on the same connection (from
+different goroutines).
+
+Example usage:
+
+ package main
+
+ import (
+ "github.com/tarm/serial"
+ "log"
+ )
+
+ func main() {
+ c := &serial.Config{Name: "COM5", Baud: 115200}
+ s, err := serial.OpenPort(c)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ n, err := s.Write([]byte("test"))
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ buf := make([]byte, 128)
+ n, err = s.Read(buf)
+ if err != nil {
+ log.Fatal(err)
+ }
+ log.Print("%q", buf[:n])
+ }
+*/
+package serial
+
+import (
+ "errors"
+ "time"
+)
+
+const DefaultSize = 8 // Default value for Config.Size
+
+type StopBits byte
+type Parity byte
+
+const (
+ Stop1 StopBits = 1
+ Stop1Half StopBits = 15
+ Stop2 StopBits = 2
+)
+
+const (
+ ParityNone Parity = 'N'
+ ParityOdd Parity = 'O'
+ ParityEven Parity = 'E'
+ ParityMark Parity = 'M' // parity bit is always 1
+ ParitySpace Parity = 'S' // parity bit is always 0
+)
+
+// Config contains the information needed to open a serial port.
+//
+// Currently few options are implemented, but more may be added in the
+// future (patches welcome), so it is recommended that you create a
+// new config addressing the fields by name rather than by order.
+//
+// For example:
+//
+// c0 := &serial.Config{Name: "COM45", Baud: 115200, ReadTimeout: time.Millisecond * 500}
+// or
+// c1 := new(serial.Config)
+// c1.Name = "/dev/tty.usbserial"
+// c1.Baud = 115200
+// c1.ReadTimeout = time.Millisecond * 500
+//
+type Config struct {
+ Name string
+ Baud int
+ ReadTimeout time.Duration // Total timeout
+
+ // Size is the number of data bits. If 0, DefaultSize is used.
+ Size byte
+
+ // Parity is the bit to use and defaults to ParityNone (no parity bit).
+ Parity Parity
+
+ // Number of stop bits to use. Default is 1 (1 stop bit).
+ StopBits StopBits
+
+ // RTSFlowControl bool
+ // DTRFlowControl bool
+ // XONFlowControl bool
+
+ // CRLFTranslate bool
+}
+
+// ErrBadSize is returned if Size is not supported.
+var ErrBadSize error = errors.New("unsupported serial data size")
+
+// ErrBadStopBits is returned if the specified StopBits setting not supported.
+var ErrBadStopBits error = errors.New("unsupported stop bit setting")
+
+// ErrBadParity is returned if the parity is not supported.
+var ErrBadParity error = errors.New("unsupported parity setting")
+
+// OpenPort opens a serial port with the specified configuration
+func OpenPort(c *Config) (*Port, error) {
+ size, par, stop := c.Size, c.Parity, c.StopBits
+ if size == 0 {
+ size = DefaultSize
+ }
+ if par == 0 {
+ par = ParityNone
+ }
+ if stop == 0 {
+ stop = Stop1
+ }
+ return openPort(c.Name, c.Baud, size, par, stop, c.ReadTimeout)
+}
+
+// Converts the timeout values for Linux / POSIX systems
+func posixTimeoutValues(readTimeout time.Duration) (vmin uint8, vtime uint8) {
+ const MAXUINT8 = 1<<8 - 1 // 255
+ // set blocking / non-blocking read
+ var minBytesToRead uint8 = 1
+ var readTimeoutInDeci int64
+ if readTimeout > 0 {
+ // EOF on zero read
+ minBytesToRead = 0
+ // convert timeout to deciseconds as expected by VTIME
+ readTimeoutInDeci = (readTimeout.Nanoseconds() / 1e6 / 100)
+ // capping the timeout
+ if readTimeoutInDeci < 1 {
+ // min possible timeout 1 Deciseconds (0.1s)
+ readTimeoutInDeci = 1
+ } else if readTimeoutInDeci > MAXUINT8 {
+ // max possible timeout is 255 deciseconds (25.5s)
+ readTimeoutInDeci = MAXUINT8
+ }
+ }
+ return minBytesToRead, uint8(readTimeoutInDeci)
+}
+
+// func SendBreak()
+
+// func RegisterBreakHandler(func())
diff --git a/vendor/github.com/tarm/serial/serial_linux.go b/vendor/github.com/tarm/serial/serial_linux.go
new file mode 100644
index 0000000..adf18c6
--- /dev/null
+++ b/vendor/github.com/tarm/serial/serial_linux.go
@@ -0,0 +1,157 @@
+// +build linux,!cgo
+
+package serial
+
+import (
+ "os"
+ "syscall"
+ "time"
+ "unsafe"
+)
+
+func openPort(name string, baud int, databits byte, parity Parity, stopbits StopBits, readTimeout time.Duration) (p *Port, err error) {
+ var bauds = 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,
+ }
+
+ rate := bauds[baud]
+
+ if rate == 0 {
+ return
+ }
+
+ f, err := os.OpenFile(name, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666)
+ if err != nil {
+ return nil, err
+ }
+
+ defer func() {
+ if err != nil && f != nil {
+ f.Close()
+ }
+ }()
+
+ // Base settings
+ cflagToUse := syscall.CREAD | syscall.CLOCAL | rate
+ switch databits {
+ case 5:
+ cflagToUse |= syscall.CS5
+ case 6:
+ cflagToUse |= syscall.CS6
+ case 7:
+ cflagToUse |= syscall.CS7
+ case 8:
+ cflagToUse |= syscall.CS8
+ default:
+ return nil, ErrBadSize
+ }
+ // Stop bits settings
+ switch stopbits {
+ case Stop1:
+ // default is 1 stop bit
+ case Stop2:
+ cflagToUse |= syscall.CSTOPB
+ default:
+ // Don't know how to set 1.5
+ return nil, ErrBadStopBits
+ }
+ // Parity settings
+ switch parity {
+ case ParityNone:
+ // default is no parity
+ case ParityOdd:
+ cflagToUse |= syscall.PARENB
+ cflagToUse |= syscall.PARODD
+ case ParityEven:
+ cflagToUse |= syscall.PARENB
+ default:
+ return nil, ErrBadParity
+ }
+ fd := f.Fd()
+ vmin, vtime := posixTimeoutValues(readTimeout)
+ t := syscall.Termios{
+ Iflag: syscall.IGNPAR,
+ Cflag: cflagToUse,
+ Cc: [32]uint8{syscall.VMIN: vmin, syscall.VTIME: vtime},
+ Ispeed: rate,
+ Ospeed: rate,
+ }
+
+ if _, _, errno := syscall.Syscall6(
+ syscall.SYS_IOCTL,
+ uintptr(fd),
+ uintptr(syscall.TCSETS),
+ uintptr(unsafe.Pointer(&t)),
+ 0,
+ 0,
+ 0,
+ ); errno != 0 {
+ return nil, errno
+ }
+
+ if err = syscall.SetNonblock(int(fd), false); err != nil {
+ return
+ }
+
+ return &Port{f: f}, nil
+}
+
+type Port struct {
+ // We intentionly do not use an "embedded" struct so that we
+ // don't export File
+ f *os.File
+}
+
+func (p *Port) Read(b []byte) (n int, err error) {
+ return p.f.Read(b)
+}
+
+func (p *Port) Write(b []byte) (n int, err error) {
+ return p.f.Write(b)
+}
+
+// Discards data written to the port but not transmitted,
+// or data received but not read
+func (p *Port) Flush() error {
+ const TCFLSH = 0x540B
+ _, _, err := syscall.Syscall(
+ syscall.SYS_IOCTL,
+ uintptr(p.f.Fd()),
+ uintptr(TCFLSH),
+ uintptr(syscall.TCIOFLUSH),
+ )
+ return err
+}
+
+func (p *Port) Close() (err error) {
+ return p.f.Close()
+}
diff --git a/vendor/github.com/tarm/serial/serial_posix.go b/vendor/github.com/tarm/serial/serial_posix.go
new file mode 100644
index 0000000..3e8bc7c
--- /dev/null
+++ b/vendor/github.com/tarm/serial/serial_posix.go
@@ -0,0 +1,196 @@
+// +build !windows,cgo
+
+package serial
+
+// #include <termios.h>
+// #include <unistd.h>
+import "C"
+
+// TODO: Maybe change to using syscall package + ioctl instead of cgo
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "syscall"
+ "time"
+ //"unsafe"
+)
+
+func openPort(name string, baud int, databits byte, parity Parity, stopbits StopBits, readTimeout time.Duration) (p *Port, err error) {
+ f, err := os.OpenFile(name, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666)
+ if err != nil {
+ return
+ }
+
+ fd := C.int(f.Fd())
+ if C.isatty(fd) != 1 {
+ f.Close()
+ return nil, errors.New("File is not a tty")
+ }
+
+ var st C.struct_termios
+ _, err = C.tcgetattr(fd, &st)
+ if err != nil {
+ f.Close()
+ return nil, err
+ }
+ var speed C.speed_t
+ switch baud {
+ case 115200:
+ speed = C.B115200
+ case 57600:
+ speed = C.B57600
+ case 38400:
+ speed = C.B38400
+ case 19200:
+ speed = C.B19200
+ case 9600:
+ speed = C.B9600
+ case 4800:
+ speed = C.B4800
+ case 2400:
+ speed = C.B2400
+ case 1200:
+ speed = C.B1200
+ case 600:
+ speed = C.B600
+ case 300:
+ speed = C.B300
+ case 200:
+ speed = C.B200
+ case 150:
+ speed = C.B150
+ case 134:
+ speed = C.B134
+ case 110:
+ speed = C.B110
+ case 75:
+ speed = C.B75
+ case 50:
+ speed = C.B50
+ default:
+ f.Close()
+ return nil, fmt.Errorf("Unknown baud rate %v", baud)
+ }
+
+ _, err = C.cfsetispeed(&st, speed)
+ if err != nil {
+ f.Close()
+ return nil, err
+ }
+ _, err = C.cfsetospeed(&st, speed)
+ if err != nil {
+ f.Close()
+ return nil, err
+ }
+
+ // Turn off break interrupts, CR->NL, Parity checks, strip, and IXON
+ st.c_iflag &= ^C.tcflag_t(C.BRKINT | C.ICRNL | C.INPCK | C.ISTRIP | C.IXOFF | C.IXON | C.PARMRK)
+
+ // Select local mode, turn off parity, set to 8 bits
+ st.c_cflag &= ^C.tcflag_t(C.CSIZE | C.PARENB)
+ st.c_cflag |= (C.CLOCAL | C.CREAD)
+ // databits
+ switch databits {
+ case 5:
+ st.c_cflag |= C.CS5
+ case 6:
+ st.c_cflag |= C.CS6
+ case 7:
+ st.c_cflag |= C.CS7
+ case 8:
+ st.c_cflag |= C.CS8
+ default:
+ return nil, ErrBadSize
+ }
+ // Parity settings
+ switch parity {
+ case ParityNone:
+ // default is no parity
+ case ParityOdd:
+ st.c_cflag |= C.PARENB
+ st.c_cflag |= C.PARODD
+ case ParityEven:
+ st.c_cflag |= C.PARENB
+ default:
+ return nil, ErrBadParity
+ }
+ // Stop bits settings
+ switch stopbits {
+ case Stop1:
+ // as is, default is 1 bit
+ case Stop2:
+ st.c_cflag |= C.CSTOPB
+ default:
+ return nil, ErrBadStopBits
+ }
+ // Select raw mode
+ st.c_lflag &= ^C.tcflag_t(C.ICANON | C.ECHO | C.ECHOE | C.ISIG)
+ st.c_oflag &= ^C.tcflag_t(C.OPOST)
+
+ // set blocking / non-blocking read
+ /*
+ * http://man7.org/linux/man-pages/man3/termios.3.html
+ * - Supports blocking read and read with timeout operations
+ */
+ vmin, vtime := posixTimeoutValues(readTimeout)
+ st.c_cc[C.VMIN] = C.cc_t(vmin)
+ st.c_cc[C.VTIME] = C.cc_t(vtime)
+
+ _, err = C.tcsetattr(fd, C.TCSANOW, &st)
+ if err != nil {
+ f.Close()
+ return nil, err
+ }
+
+ //fmt.Println("Tweaking", name)
+ r1, _, e := syscall.Syscall(syscall.SYS_FCNTL,
+ uintptr(f.Fd()),
+ uintptr(syscall.F_SETFL),
+ uintptr(0))
+ if e != 0 || r1 != 0 {
+ s := fmt.Sprint("Clearing NONBLOCK syscall error:", e, r1)
+ f.Close()
+ return nil, errors.New(s)
+ }
+
+ /*
+ r1, _, e = syscall.Syscall(syscall.SYS_IOCTL,
+ uintptr(f.Fd()),
+ uintptr(0x80045402), // IOSSIOSPEED
+ uintptr(unsafe.Pointer(&baud)));
+ if e != 0 || r1 != 0 {
+ s := fmt.Sprint("Baudrate syscall error:", e, r1)
+ f.Close()
+ return nil, os.NewError(s)
+ }
+ */
+
+ return &Port{f: f}, nil
+}
+
+type Port struct {
+ // We intentionly do not use an "embedded" struct so that we
+ // don't export File
+ f *os.File
+}
+
+func (p *Port) Read(b []byte) (n int, err error) {
+ return p.f.Read(b)
+}
+
+func (p *Port) Write(b []byte) (n int, err error) {
+ return p.f.Write(b)
+}
+
+// Discards data written to the port but not transmitted,
+// or data received but not read
+func (p *Port) Flush() error {
+ _, err := C.tcflush(C.int(p.f.Fd()), C.TCIOFLUSH)
+ return err
+}
+
+func (p *Port) Close() (err error) {
+ return p.f.Close()
+}
diff --git a/vendor/github.com/tarm/serial/serial_windows.go b/vendor/github.com/tarm/serial/serial_windows.go
new file mode 100644
index 0000000..a41bf4f
--- /dev/null
+++ b/vendor/github.com/tarm/serial/serial_windows.go
@@ -0,0 +1,327 @@
+// +build windows
+
+package serial
+
+import (
+ "fmt"
+ "os"
+ "sync"
+ "syscall"
+ "time"
+ "unsafe"
+)
+
+type Port struct {
+ f *os.File
+ fd syscall.Handle
+ rl sync.Mutex
+ wl sync.Mutex
+ ro *syscall.Overlapped
+ wo *syscall.Overlapped
+}
+
+type structDCB struct {
+ DCBlength, BaudRate uint32
+ flags [4]byte
+ wReserved, XonLim, XoffLim uint16
+ ByteSize, Parity, StopBits byte
+ XonChar, XoffChar, ErrorChar, EofChar, EvtChar byte
+ wReserved1 uint16
+}
+
+type structTimeouts struct {
+ ReadIntervalTimeout uint32
+ ReadTotalTimeoutMultiplier uint32
+ ReadTotalTimeoutConstant uint32
+ WriteTotalTimeoutMultiplier uint32
+ WriteTotalTimeoutConstant uint32
+}
+
+func openPort(name string, baud int, databits byte, parity Parity, stopbits StopBits, readTimeout time.Duration) (p *Port, err error) {
+ if len(name) > 0 && name[0] != '\\' {
+ name = "\\\\.\\" + name
+ }
+
+ h, err := syscall.CreateFile(syscall.StringToUTF16Ptr(name),
+ syscall.GENERIC_READ|syscall.GENERIC_WRITE,
+ 0,
+ nil,
+ syscall.OPEN_EXISTING,
+ syscall.FILE_ATTRIBUTE_NORMAL|syscall.FILE_FLAG_OVERLAPPED,
+ 0)
+ if err != nil {
+ return nil, err
+ }
+ f := os.NewFile(uintptr(h), name)
+ defer func() {
+ if err != nil {
+ f.Close()
+ }
+ }()
+
+ if err = setCommState(h, baud, databits, parity, stopbits); err != nil {
+ return nil, err
+ }
+ if err = setupComm(h, 64, 64); err != nil {
+ return nil, err
+ }
+ if err = setCommTimeouts(h, readTimeout); err != nil {
+ return nil, err
+ }
+ if err = setCommMask(h); err != nil {
+ return nil, err
+ }
+
+ ro, err := newOverlapped()
+ if err != nil {
+ return nil, err
+ }
+ wo, err := newOverlapped()
+ if err != nil {
+ return nil, err
+ }
+ port := new(Port)
+ port.f = f
+ port.fd = h
+ port.ro = ro
+ port.wo = wo
+
+ return port, nil
+}
+
+func (p *Port) Close() error {
+ return p.f.Close()
+}
+
+func (p *Port) Write(buf []byte) (int, error) {
+ p.wl.Lock()
+ defer p.wl.Unlock()
+
+ if err := resetEvent(p.wo.HEvent); err != nil {
+ return 0, err
+ }
+ var n uint32
+ err := syscall.WriteFile(p.fd, buf, &n, p.wo)
+ if err != nil && err != syscall.ERROR_IO_PENDING {
+ return int(n), err
+ }
+ return getOverlappedResult(p.fd, p.wo)
+}
+
+func (p *Port) Read(buf []byte) (int, error) {
+ if p == nil || p.f == nil {
+ return 0, fmt.Errorf("Invalid port on read %v %v", p, p.f)
+ }
+
+ p.rl.Lock()
+ defer p.rl.Unlock()
+
+ if err := resetEvent(p.ro.HEvent); err != nil {
+ return 0, err
+ }
+ var done uint32
+ err := syscall.ReadFile(p.fd, buf, &done, p.ro)
+ if err != nil && err != syscall.ERROR_IO_PENDING {
+ return int(done), err
+ }
+ return getOverlappedResult(p.fd, p.ro)
+}
+
+// Discards data written to the port but not transmitted,
+// or data received but not read
+func (p *Port) Flush() error {
+ return purgeComm(p.fd)
+}
+
+var (
+ nSetCommState,
+ nSetCommTimeouts,
+ nSetCommMask,
+ nSetupComm,
+ nGetOverlappedResult,
+ nCreateEvent,
+ nResetEvent,
+ nPurgeComm,
+ nFlushFileBuffers uintptr
+)
+
+func init() {
+ k32, err := syscall.LoadLibrary("kernel32.dll")
+ if err != nil {
+ panic("LoadLibrary " + err.Error())
+ }
+ defer syscall.FreeLibrary(k32)
+
+ nSetCommState = getProcAddr(k32, "SetCommState")
+ nSetCommTimeouts = getProcAddr(k32, "SetCommTimeouts")
+ nSetCommMask = getProcAddr(k32, "SetCommMask")
+ nSetupComm = getProcAddr(k32, "SetupComm")
+ nGetOverlappedResult = getProcAddr(k32, "GetOverlappedResult")
+ nCreateEvent = getProcAddr(k32, "CreateEventW")
+ nResetEvent = getProcAddr(k32, "ResetEvent")
+ nPurgeComm = getProcAddr(k32, "PurgeComm")
+ nFlushFileBuffers = getProcAddr(k32, "FlushFileBuffers")
+}
+
+func getProcAddr(lib syscall.Handle, name string) uintptr {
+ addr, err := syscall.GetProcAddress(lib, name)
+ if err != nil {
+ panic(name + " " + err.Error())
+ }
+ return addr
+}
+
+func setCommState(h syscall.Handle, baud int, databits byte, parity Parity, stopbits StopBits) error {
+ var params structDCB
+ params.DCBlength = uint32(unsafe.Sizeof(params))
+
+ params.flags[0] = 0x01 // fBinary
+ params.flags[0] |= 0x10 // Assert DSR
+
+ params.BaudRate = uint32(baud)
+
+ params.ByteSize = databits
+
+ switch parity {
+ case ParityNone:
+ params.Parity = 0
+ case ParityOdd:
+ params.Parity = 1
+ case ParityEven:
+ params.Parity = 2
+ case ParityMark:
+ params.Parity = 3
+ case ParitySpace:
+ params.Parity = 4
+ default:
+ return ErrBadParity
+ }
+
+ switch stopbits {
+ case Stop1:
+ params.StopBits = 0
+ case Stop1Half:
+ params.StopBits = 1
+ case Stop2:
+ params.StopBits = 2
+ default:
+ return ErrBadStopBits
+ }
+
+ r, _, err := syscall.Syscall(nSetCommState, 2, uintptr(h), uintptr(unsafe.Pointer(&params)), 0)
+ if r == 0 {
+ return err
+ }
+ return nil
+}
+
+func setCommTimeouts(h syscall.Handle, readTimeout time.Duration) error {
+ var timeouts structTimeouts
+ const MAXDWORD = 1<<32 - 1
+
+ // blocking read by default
+ var timeoutMs int64 = MAXDWORD - 1
+
+ if readTimeout > 0 {
+ // non-blocking read
+ timeoutMs = readTimeout.Nanoseconds() / 1e6
+ if timeoutMs < 1 {
+ timeoutMs = 1
+ } else if timeoutMs > MAXDWORD-1 {
+ timeoutMs = MAXDWORD - 1
+ }
+ }
+
+ /* From http://msdn.microsoft.com/en-us/library/aa363190(v=VS.85).aspx
+
+ For blocking I/O see below:
+
+ Remarks:
+
+ If an application sets ReadIntervalTimeout and
+ ReadTotalTimeoutMultiplier to MAXDWORD and sets
+ ReadTotalTimeoutConstant to a value greater than zero and
+ less than MAXDWORD, one of the following occurs when the
+ ReadFile function is called:
+
+ If there are any bytes in the input buffer, ReadFile returns
+ immediately with the bytes in the buffer.
+
+ If there are no bytes in the input buffer, ReadFile waits
+ until a byte arrives and then returns immediately.
+
+ If no bytes arrive within the time specified by
+ ReadTotalTimeoutConstant, ReadFile times out.
+ */
+
+ timeouts.ReadIntervalTimeout = MAXDWORD
+ timeouts.ReadTotalTimeoutMultiplier = MAXDWORD
+ timeouts.ReadTotalTimeoutConstant = uint32(timeoutMs)
+
+ r, _, err := syscall.Syscall(nSetCommTimeouts, 2, uintptr(h), uintptr(unsafe.Pointer(&timeouts)), 0)
+ if r == 0 {
+ return err
+ }
+ return nil
+}
+
+func setupComm(h syscall.Handle, in, out int) error {
+ r, _, err := syscall.Syscall(nSetupComm, 3, uintptr(h), uintptr(in), uintptr(out))
+ if r == 0 {
+ return err
+ }
+ return nil
+}
+
+func setCommMask(h syscall.Handle) error {
+ const EV_RXCHAR = 0x0001
+ r, _, err := syscall.Syscall(nSetCommMask, 2, uintptr(h), EV_RXCHAR, 0)
+ if r == 0 {
+ return err
+ }
+ return nil
+}
+
+func resetEvent(h syscall.Handle) error {
+ r, _, err := syscall.Syscall(nResetEvent, 1, uintptr(h), 0, 0)
+ if r == 0 {
+ return err
+ }
+ return nil
+}
+
+func purgeComm(h syscall.Handle) error {
+ const PURGE_TXABORT = 0x0001
+ const PURGE_RXABORT = 0x0002
+ const PURGE_TXCLEAR = 0x0004
+ const PURGE_RXCLEAR = 0x0008
+ r, _, err := syscall.Syscall(nPurgeComm, 2, uintptr(h),
+ PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR, 0)
+ if r == 0 {
+ return err
+ }
+ return nil
+}
+
+func newOverlapped() (*syscall.Overlapped, error) {
+ var overlapped syscall.Overlapped
+ r, _, err := syscall.Syscall6(nCreateEvent, 4, 0, 1, 0, 0, 0, 0)
+ if r == 0 {
+ return nil, err
+ }
+ overlapped.HEvent = syscall.Handle(r)
+ return &overlapped, nil
+}
+
+func getOverlappedResult(h syscall.Handle, overlapped *syscall.Overlapped) (int, error) {
+ var n int
+ r, _, err := syscall.Syscall6(nGetOverlappedResult, 4,
+ uintptr(h),
+ uintptr(unsafe.Pointer(overlapped)),
+ uintptr(unsafe.Pointer(&n)), 1, 0, 0)
+ if r == 0 {
+ return n, err
+ }
+
+ return n, nil
+}