Skip to content

Commit

Permalink
Return a more concrete *Port instead of an io.ReadWriteCloser. This w…
Browse files Browse the repository at this point in the history
…ill let us add more methods

This is potentially a backwards compatible change, so also update the
import path to avoid breaking people's code.  This will also align
better with 'go get' (which came out after this package's path and
name were set).

Also update the README to reflect use the go tool, point to godoc, and
add timeout information to the package.
  • Loading branch information
Tarmigan Casebolt committed Feb 26, 2015
1 parent 1402275 commit 1d5ebfa
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 32 deletions.
33 changes: 17 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
GoSerial
[![GoDoc](https://godoc.org/github.com/tarm/serial?status.svg)](http://godoc.org/github.com/tarm/serial)

Serial
========
A simple go package to allow you to read and write from the
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. Unfortunately goinstall
does not currently let you cross compile so you will have to do it
manually:
compile for windows from another platform.

GOOS=windows make clean install
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. 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.
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
Expand All @@ -33,8 +33,9 @@ Usage
package main

import (
"github.com/tarm/goserial"
"log"

"github.com/tarm/serial"
)

func main() {
Expand All @@ -60,12 +61,12 @@ func main() {

NonBlocking Mode
----------------
By default goserial 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.
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}
Expand Down
3 changes: 1 addition & 2 deletions serial.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ Example usage:
package serial

import (
"io"
"time"
)

Expand Down Expand Up @@ -92,7 +91,7 @@ type Config struct {
}

// OpenPort opens a serial port with the specified configuration
func OpenPort(c *Config) (io.ReadWriteCloser, error) {
func OpenPort(c *Config) (*Port, error) {
return openPort(c.Name, c.Baud, c.ReadTimeout)
}

Expand Down
24 changes: 20 additions & 4 deletions serial_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@
package serial

import (
"io"
"os"
"syscall"
"time"
"unsafe"
)

func openPort(name string, baud int, readTimeout time.Duration) (rwc io.ReadWriteCloser, err error) {

func openPort(name string, baud int, readTimeout time.Duration) (p *Port, err error) {
var bauds = map[int]uint32{
50: syscall.B50,
75: syscall.B75,
Expand Down Expand Up @@ -88,5 +86,23 @@ func openPort(name string, baud int, readTimeout time.Duration) (rwc io.ReadWrit
return
}

return f, nil
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)
}

func (p *Port) Close() (err error) {
return p.f.Close()
}
23 changes: 20 additions & 3 deletions serial_posix.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@ import "C"
import (
"errors"
"fmt"
"io"
"os"
"syscall"
"time"
//"unsafe"
)

func openPort(name string, baud int, readTimeout time.Duration) (rwc io.ReadWriteCloser, err error) {
func openPort(name string, baud int, 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
Expand Down Expand Up @@ -117,5 +116,23 @@ func openPort(name string, baud int, readTimeout time.Duration) (rwc io.ReadWrit
}
*/

return f, nil
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)
}

func (p *Port) Close() (err error) {
return p.f.Close()
}
13 changes: 6 additions & 7 deletions serial_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ package serial

import (
"fmt"
"io"
"os"
"sync"
"syscall"
"time"
"unsafe"
)

type serialPort struct {
type Port struct {
f *os.File
fd syscall.Handle
rl sync.Mutex
Expand All @@ -38,7 +37,7 @@ type structTimeouts struct {
WriteTotalTimeoutConstant uint32
}

func openPort(name string, baud int, readTimeout time.Duration) (rwc io.ReadWriteCloser, err error) {
func openPort(name string, baud int, readTimeout time.Duration) (p *Port, err error) {
if len(name) > 0 && name[0] != '\\' {
name = "\\\\.\\" + name
}
Expand Down Expand Up @@ -81,7 +80,7 @@ func openPort(name string, baud int, readTimeout time.Duration) (rwc io.ReadWrit
if err != nil {
return
}
port := new(serialPort)
port := new(Port)
port.f = f
port.fd = h
port.ro = ro
Expand All @@ -90,11 +89,11 @@ func openPort(name string, baud int, readTimeout time.Duration) (rwc io.ReadWrit
return port, nil
}

func (p *serialPort) Close() error {
func (p *Port) Close() error {
return p.f.Close()
}

func (p *serialPort) Write(buf []byte) (int, error) {
func (p *Port) Write(buf []byte) (int, error) {
p.wl.Lock()
defer p.wl.Unlock()

Expand All @@ -109,7 +108,7 @@ func (p *serialPort) Write(buf []byte) (int, error) {
return getOverlappedResult(p.fd, p.wo)
}

func (p *serialPort) Read(buf []byte) (int, error) {
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)
}
Expand Down

0 comments on commit 1d5ebfa

Please sign in to comment.