Created interface Port. Rationalized documentation.
This commit is contained in:
6
doc.go
6
doc.go
@@ -26,17 +26,17 @@ GetPortsList function:
|
|||||||
fmt.Printf("Found port: %v\n", port)
|
fmt.Printf("Found port: %v\n", port)
|
||||||
}
|
}
|
||||||
|
|
||||||
The serial port can be opened with the OpenPort function:
|
The serial port can be opened with the Open function:
|
||||||
|
|
||||||
mode := &serial.Mode{
|
mode := &serial.Mode{
|
||||||
BaudRate: 115200,
|
BaudRate: 115200,
|
||||||
}
|
}
|
||||||
port, err := serial.OpenPort("/dev/ttyUSB0", mode)
|
port, err := serial.Open("/dev/ttyUSB0", mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
The OpenPort command needs a "mode" parameter that specifies the configuration
|
The Open function needs a "mode" parameter that specifies the configuration
|
||||||
options for the serial port. If not specified the default options are 9600_N81,
|
options for the serial port. If not specified the default options are 9600_N81,
|
||||||
in the example above only the speed is changed so the port is opened using 115200_N81.
|
in the example above only the speed is changed so the port is opened using 115200_N81.
|
||||||
The following snippets shows how to declare a configuration for 57600_E71:
|
The following snippets shows how to declare a configuration for 57600_E71:
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import "log"
|
|||||||
import "go.bug.st/serial"
|
import "go.bug.st/serial"
|
||||||
|
|
||||||
func ExampleSerialPort_SetMode() {
|
func ExampleSerialPort_SetMode() {
|
||||||
port, err := serial.OpenPort("/dev/ttyACM0", &serial.Mode{})
|
port, err := serial.Open("/dev/ttyACM0", &serial.Mode{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ func Example_sendAndReceive() {
|
|||||||
DataBits: 8,
|
DataBits: 8,
|
||||||
StopBits: serial.OneStopBit,
|
StopBits: serial.OneStopBit,
|
||||||
}
|
}
|
||||||
port, err := serial.OpenPort(ports[0], mode)
|
port, err := serial.Open(ports[0], mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
30
serial.go
30
serial.go
@@ -6,6 +6,36 @@
|
|||||||
|
|
||||||
package serial // import "go.bug.st/serial"
|
package serial // import "go.bug.st/serial"
|
||||||
|
|
||||||
|
// Port is the interface for a serial Port
|
||||||
|
type Port interface {
|
||||||
|
// SetMode sets all parameters of the serial port
|
||||||
|
SetMode(mode *Mode) error
|
||||||
|
|
||||||
|
// Stores data received from the serial port into the provided byte array
|
||||||
|
// buffer. The function returns the number of bytes read.
|
||||||
|
//
|
||||||
|
// The Read function blocks until (at least) one byte is received from
|
||||||
|
// the serial port or an error occurs.
|
||||||
|
Read(p []byte) (n int, err error)
|
||||||
|
|
||||||
|
// Send the content of the data byte array to the serial port.
|
||||||
|
// Returns the number of bytes written.
|
||||||
|
Write(p []byte) (n int, err error)
|
||||||
|
|
||||||
|
// Close the serial port
|
||||||
|
Close() error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open opens the serial port using the specified modes
|
||||||
|
func Open(portName string, mode *Mode) (Port, error) {
|
||||||
|
return nativeOpen(portName, mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPortsList retrieve the list of available serial ports
|
||||||
|
func GetPortsList() ([]string, error) {
|
||||||
|
return nativeGetPortsList()
|
||||||
|
}
|
||||||
|
|
||||||
// Mode describes a serial port configuration.
|
// Mode describes a serial port configuration.
|
||||||
type Mode struct {
|
type Mode struct {
|
||||||
BaudRate int // The serial port bitrate (aka Baudrate)
|
BaudRate int // The serial port bitrate (aka Baudrate)
|
||||||
|
|||||||
@@ -14,34 +14,24 @@ import "strings"
|
|||||||
import "syscall"
|
import "syscall"
|
||||||
import "unsafe"
|
import "unsafe"
|
||||||
|
|
||||||
// Port is the handler for a serial Port
|
type unixPort struct {
|
||||||
type Port struct {
|
|
||||||
handle int
|
handle int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the serial port
|
func (port *unixPort) Close() error {
|
||||||
func (port *Port) Close() error {
|
|
||||||
port.releaseExclusiveAccess()
|
port.releaseExclusiveAccess()
|
||||||
return syscall.Close(port.handle)
|
return syscall.Close(port.handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stores data received from the serial port into the provided byte array
|
func (port *unixPort) Read(p []byte) (n int, err error) {
|
||||||
// buffer. The function returns the number of bytes read.
|
|
||||||
//
|
|
||||||
// The Read function blocks until (at least) one byte is received from
|
|
||||||
// the serial port or an error occurs.
|
|
||||||
func (port *Port) Read(p []byte) (n int, err error) {
|
|
||||||
return syscall.Read(port.handle, p)
|
return syscall.Read(port.handle, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the content of the data byte array to the serial port.
|
func (port *unixPort) Write(p []byte) (n int, err error) {
|
||||||
// Returns the number of bytes written.
|
|
||||||
func (port *Port) Write(p []byte) (n int, err error) {
|
|
||||||
return syscall.Write(port.handle, p)
|
return syscall.Write(port.handle, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetMode sets all parameters of the serial port
|
func (port *unixPort) SetMode(mode *Mode) error {
|
||||||
func (port *Port) SetMode(mode *Mode) error {
|
|
||||||
settings, err := port.getTermSettings()
|
settings, err := port.getTermSettings()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -61,8 +51,7 @@ func (port *Port) SetMode(mode *Mode) error {
|
|||||||
return port.setTermSettings(settings)
|
return port.setTermSettings(settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenPort opens the serial port using the specified modes
|
func nativeOpen(portName string, mode *Mode) (*unixPort, error) {
|
||||||
func OpenPort(portName string, mode *Mode) (*Port, error) {
|
|
||||||
h, err := syscall.Open(portName, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NDELAY, 0)
|
h, err := syscall.Open(portName, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NDELAY, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch err {
|
switch err {
|
||||||
@@ -73,7 +62,7 @@ func OpenPort(portName string, mode *Mode) (*Port, error) {
|
|||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
port := &Port{
|
port := &unixPort{
|
||||||
handle: h,
|
handle: h,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,8 +91,7 @@ func OpenPort(portName string, mode *Mode) (*Port, error) {
|
|||||||
return port, nil
|
return port, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPortsList retrieve the list of available serial ports
|
func nativeGetPortsList() ([]string, error) {
|
||||||
func GetPortsList() ([]string, error) {
|
|
||||||
files, err := ioutil.ReadDir(devFolder)
|
files, err := ioutil.ReadDir(devFolder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -129,7 +117,7 @@ func GetPortsList() ([]string, error) {
|
|||||||
|
|
||||||
// Check if serial port is real or is a placeholder serial port "ttySxx"
|
// Check if serial port is real or is a placeholder serial port "ttySxx"
|
||||||
if strings.HasPrefix(f.Name(), "ttyS") {
|
if strings.HasPrefix(f.Name(), "ttyS") {
|
||||||
port, err := OpenPort(portName, &Mode{})
|
port, err := nativeOpen(portName, &Mode{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
serr, ok := err.(*PortError)
|
serr, ok := err.(*PortError)
|
||||||
if ok && serr.Code() == InvalidSerialPort {
|
if ok && serr.Code() == InvalidSerialPort {
|
||||||
@@ -230,20 +218,20 @@ func setRawMode(settings *syscall.Termios) {
|
|||||||
|
|
||||||
// native syscall wrapper functions
|
// native syscall wrapper functions
|
||||||
|
|
||||||
func (port *Port) getTermSettings() (*syscall.Termios, error) {
|
func (port *unixPort) getTermSettings() (*syscall.Termios, error) {
|
||||||
settings := &syscall.Termios{}
|
settings := &syscall.Termios{}
|
||||||
err := ioctl(port.handle, ioctlTcgetattr, uintptr(unsafe.Pointer(settings)))
|
err := ioctl(port.handle, ioctlTcgetattr, uintptr(unsafe.Pointer(settings)))
|
||||||
return settings, err
|
return settings, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (port *Port) setTermSettings(settings *syscall.Termios) error {
|
func (port *unixPort) setTermSettings(settings *syscall.Termios) error {
|
||||||
return ioctl(port.handle, ioctlTcsetattr, uintptr(unsafe.Pointer(settings)))
|
return ioctl(port.handle, ioctlTcsetattr, uintptr(unsafe.Pointer(settings)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (port *Port) acquireExclusiveAccess() error {
|
func (port *unixPort) acquireExclusiveAccess() error {
|
||||||
return ioctl(port.handle, syscall.TIOCEXCL, 0)
|
return ioctl(port.handle, syscall.TIOCEXCL, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (port *Port) releaseExclusiveAccess() error {
|
func (port *unixPort) releaseExclusiveAccess() error {
|
||||||
return ioctl(port.handle, syscall.TIOCNXCL, 0)
|
return ioctl(port.handle, syscall.TIOCNXCL, 0)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,13 +18,13 @@ package serial // import "go.bug.st/serial"
|
|||||||
|
|
||||||
import "syscall"
|
import "syscall"
|
||||||
|
|
||||||
type Port struct {
|
type windowsPort struct {
|
||||||
handle syscall.Handle
|
handle syscall.Handle
|
||||||
}
|
}
|
||||||
|
|
||||||
//sys RegEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, value *uint16, valueLen *uint32) (regerrno error) = advapi32.RegEnumValueW
|
//sys RegEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, value *uint16, valueLen *uint32) (regerrno error) = advapi32.RegEnumValueW
|
||||||
|
|
||||||
func GetPortsList() ([]string, error) {
|
func nativeGetPortsList() ([]string, error) {
|
||||||
subKey, err := syscall.UTF16PtrFromString("HARDWARE\\DEVICEMAP\\SERIALCOMM\\")
|
subKey, err := syscall.UTF16PtrFromString("HARDWARE\\DEVICEMAP\\SERIALCOMM\\")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &PortError{code: ErrorEnumeratingPorts}
|
return nil, &PortError{code: ErrorEnumeratingPorts}
|
||||||
@@ -55,11 +55,11 @@ func GetPortsList() ([]string, error) {
|
|||||||
return list, nil
|
return list, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (port *Port) Close() error {
|
func (port *windowsPort) Close() error {
|
||||||
return syscall.CloseHandle(port.handle)
|
return syscall.CloseHandle(port.handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (port *Port) Read(p []byte) (int, error) {
|
func (port *windowsPort) Read(p []byte) (int, error) {
|
||||||
var readed uint32
|
var readed uint32
|
||||||
params := &DCB{}
|
params := &DCB{}
|
||||||
for {
|
for {
|
||||||
@@ -82,7 +82,7 @@ func (port *Port) Read(p []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (port *Port) Write(p []byte) (int, error) {
|
func (port *windowsPort) Write(p []byte) (int, error) {
|
||||||
var writed uint32
|
var writed uint32
|
||||||
err := syscall.WriteFile(port.handle, p, &writed, nil)
|
err := syscall.WriteFile(port.handle, p, &writed, nil)
|
||||||
return int(writed), err
|
return int(writed), err
|
||||||
@@ -170,7 +170,7 @@ const (
|
|||||||
TWOSTOPBITS = 2
|
TWOSTOPBITS = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
func (port *Port) SetMode(mode *Mode) error {
|
func (port *windowsPort) SetMode(mode *Mode) error {
|
||||||
params := DCB{}
|
params := DCB{}
|
||||||
if GetCommState(port.handle, ¶ms) != nil {
|
if GetCommState(port.handle, ¶ms) != nil {
|
||||||
port.Close()
|
port.Close()
|
||||||
@@ -195,7 +195,7 @@ func (port *Port) SetMode(mode *Mode) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func OpenPort(portName string, mode *Mode) (*Port, error) {
|
func nativeOpen(portName string, mode *Mode) (*windowsPort, error) {
|
||||||
portName = "\\\\.\\" + portName
|
portName = "\\\\.\\" + portName
|
||||||
path, err := syscall.UTF16PtrFromString(portName)
|
path, err := syscall.UTF16PtrFromString(portName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -218,7 +218,7 @@ func OpenPort(portName string, mode *Mode) (*Port, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Create the serial port
|
// Create the serial port
|
||||||
port := &Port{
|
port := &windowsPort{
|
||||||
handle: handle,
|
handle: handle,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user