aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorroot <sina@snix.ir>2022-05-09 20:25:01 +0000
committerroot <sina@snix.ir>2022-05-09 20:25:01 +0000
commit433065e7a8984c09c082c997be950d67a9f9aa93 (patch)
tree3ff637bc08ccfa093edd7e7c207d5bb7f7136f95
userial snix repository
-rw-r--r--example/main.go51
-rw-r--r--go.mod5
-rw-r--r--go.sum2
-rw-r--r--header.go71
-rw-r--r--ports.go93
-rw-r--r--serial.go66
6 files changed, 288 insertions, 0 deletions
diff --git a/example/main.go b/example/main.go
new file mode 100644
index 0000000..76b8079
--- /dev/null
+++ b/example/main.go
@@ -0,0 +1,51 @@
+package main
+
+import (
+ "io"
+ "log"
+ "os"
+
+ "snix.ir/userial"
+)
+
+// we need something to read, so we gonna mess with terminal..
+const cisco_router_cmd = `
+enable
+show ip int br
+
+conf t
+
+int gig0/0
+ip addr 192.168.122.200 255.255.255.0
+no shut
+
+do show ip int br
+
+`
+
+func main() {
+
+ // default conf
+ p, err := serial.NewSerial().OpenPort("/dev/ttyACM0")
+
+ // serial port with custom config
+ //
+ // p_dev := "/dev/ttyACM0"
+ // s := serial.NewSerial().SetBuadRate(serial.B0019200)
+ // p, err = s.SetParity(serial.ParityEvn).OpenPort(p_dev)
+
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ defer p.Close()
+
+ if _, err := p.Write([]byte(cisco_router_cmd)); err != nil {
+ panic(err)
+ }
+
+ if _, err := io.Copy(os.Stdout, p); err != nil {
+ panic(err)
+ }
+
+}
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..2259256
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,5 @@
+module snix.ir/userial
+
+go 1.18
+
+require golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..67ddd69
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,2 @@
+golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60=
+golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/header.go b/header.go
new file mode 100644
index 0000000..9af74ac
--- /dev/null
+++ b/header.go
@@ -0,0 +1,71 @@
+package userial
+
+import (
+ "golang.org/x/sys/unix"
+)
+
+type (
+ baudrates rune
+ paritybit byte
+ databitcs byte
+ stopbitcs byte
+ hwcontrol byte
+)
+
+const (
+ Hardware hwcontrol = iota
+ Softeare
+ None
+)
+
+const (
+ B0000050 baudrates = 0x01 + iota
+ B0000075
+ B0000110
+ B0000134
+ B0000150
+ B0000200
+ B0000300
+ B0000600
+ B0001200
+ B0001800
+ B0002400
+ B0004800
+ B0009600
+ B0019200
+ B0038400
+
+ B0057600 baudrates = 0xFF2 + iota
+ B0115200
+ B0230400
+ B0460800
+ B0500000
+ B0576000
+ B0921600
+ B1000000
+ B1152000
+ B1500000
+ B2000000
+ B2500000
+ B3000000
+ B3500000
+ B4000000
+)
+
+const (
+ ParityNon paritybit = iota
+ ParityEvn
+ ParityOdd
+)
+
+const (
+ StopBitA stopbitcs = 0x00 // stop bit 1
+ StopBitB stopbitcs = unix.CSTOPB // stop bit 2
+)
+
+const (
+ CS5 databitcs = unix.CS5 // databit 5
+ CS6 databitcs = unix.CS6 // databit 6
+ CS7 databitcs = unix.CS7 // databit 7
+ CS8 databitcs = unix.CS8 // databit 8 (default)
+)
diff --git a/ports.go b/ports.go
new file mode 100644
index 0000000..2742e60
--- /dev/null
+++ b/ports.go
@@ -0,0 +1,93 @@
+package userial
+
+import (
+ "math"
+ "os"
+ "time"
+
+ "golang.org/x/sys/unix"
+)
+
+type Port struct{ f *os.File }
+
+// OpenPort opens a named serial device and return a Port data type and error
+func (spops *Serial) OpenPort(path string) (*Port, error) {
+
+ f, err := os.OpenFile(path, unix.O_RDWR|unix.O_NOCTTY|unix.O_NONBLOCK, 0666)
+ if err != nil {
+ return nil, err
+ }
+
+ defer func() {
+ if err != nil && f != nil {
+ f.Close()
+ }
+ }()
+
+ fg := uint32(spops.baud) | uint32(spops.data) | uint32(spops.stop) | spops.cbit
+
+ switch spops.prty {
+ case 1:
+ fg |= unix.PARENB
+ case 2:
+ fg |= unix.PARENB
+ fg |= unix.PARODD
+ }
+
+ t := unix.Termios{
+ Cflag: fg, Iflag: spops.ibit,
+ Ispeed: uint32(spops.baud),
+ Ospeed: uint32(spops.baud),
+ }
+
+ t.Cc[unix.VMIN], t.Cc[unix.VTIME] = timeout(spops.tout)
+
+ if err := unix.IoctlSetTermios(
+ int(f.Fd()), unix.TCSETS, &t); err != nil {
+ return nil, err
+ }
+
+ if err := unix.SetNonblock(int(f.Fd()), false); err != nil {
+ return nil, err
+ }
+
+ return &Port{f: f}, err
+
+}
+
+// Read implement read() method for serial port
+func (p *Port) Read(b []byte) (int, error) { return p.f.Read(b) }
+
+// Write implement write() method for serial port
+func (p *Port) Write(b []byte) (int, error) { return p.f.Write(b) }
+
+// Close implement close() method for serial port
+func (p *Port) Close() error { return p.f.Close() }
+
+// Flush implement flush() method for serial port
+func (p *Port) Flush() error {
+ return unix.IoctlSetInt(int(p.f.Fd()), unix.TCFLSH, unix.TCIOFLUSH)
+}
+
+// SendBreak Sends Break Signal
+func (p *Port) SendBreak(d time.Duration) error {
+ return unix.IoctlSetInt(int(p.f.Fd()), unix.TCSBRKP, int(d))
+}
+
+// Available returns how many bytes are unused in the buffer
+func (p *Port) Available() (int, error) {
+ return unix.IoctlGetInt(int(p.f.Fd()), unix.TIOCINQ)
+}
+
+// Buffered returns the number of bytes that have been written into the current buffer
+func (p *Port) Buffered() (int, error) {
+ return unix.IoctlGetInt(int(p.f.Fd()), unix.TIOCOUTQ)
+}
+
+func timeout(d time.Duration) (byte, byte) {
+ if d > 0x0 {
+ t := math.Min(math.Max(float64(d.Nanoseconds()/1e6/100), 0x01), 0xff)
+ return 0x0, byte(t)
+ }
+ return 0x1, 0x0
+}
diff --git a/serial.go b/serial.go
new file mode 100644
index 0000000..e3cd3cb
--- /dev/null
+++ b/serial.go
@@ -0,0 +1,66 @@
+package userial
+
+import (
+ "time"
+
+ "golang.org/x/sys/unix"
+)
+
+type Serial struct {
+ baud baudrates
+ data databitcs
+ prty paritybit
+ stop stopbitcs
+ cbit uint32
+ ibit uint32
+ tout time.Duration
+}
+
+// NewSerial return a Serial data type with default settings
+func NewSerial() *Serial {
+ return &Serial{
+ baud: B0009600, data: CS8, prty: ParityNon, stop: StopBitA,
+ cbit: unix.CREAD | unix.CLOCAL, ibit: unix.IGNPAR,
+ }
+}
+
+func (p *Serial) GetBuadRate() baudrates { return p.baud }
+func (p *Serial) GetDataBit() databitcs { return p.data }
+func (p *Serial) GetParity() paritybit { return p.prty }
+func (p *Serial) GetStopBit() stopbitcs { return p.stop }
+func (p *Serial) GetTimeout() time.Duration { return p.tout }
+
+func (p *Serial) SetBuadRate(v baudrates) *Serial { p.baud = v; return p }
+func (p *Serial) SetDataBit(v databitcs) *Serial { p.data = v; return p }
+func (p *Serial) SetParity(v paritybit) *Serial { p.prty = v; return p }
+func (p *Serial) SetStopBit(v stopbitcs) *Serial { p.stop = v; return p }
+func (p *Serial) SetTimeout(d time.Duration) *Serial { p.tout = d; return p }
+
+func (p *Serial) SetFlowControl(val hwcontrol) *Serial {
+ switch val {
+ case Hardware:
+ p.ibit &^= unix.IXON | unix.IXOFF | unix.IXANY
+ p.cbit |= unix.CRTSCTS
+ case Softeare:
+ p.ibit |= unix.IXON | unix.IXOFF | unix.IXANY
+ p.cbit &^= unix.CRTSCTS
+ case None:
+ p.ibit &^= unix.IXON | unix.IXOFF | unix.IXANY
+ p.cbit &^= unix.CRTSCTS
+ }
+ return p
+}
+
+func (p *Serial) GetFlowControl() hwcontrol {
+
+ if p.cbit&unix.CRTSCTS == unix.CRTSCTS {
+ return Hardware
+ }
+
+ if p.ibit&(unix.IXON|unix.IXOFF|
+ unix.IXANY) == (unix.IXON | unix.IXOFF | unix.IXANY) {
+ return Softeare
+ }
+
+ return None
+}

Snix LLC Git Repository Holder Copyright(C) 2022 All Rights Reserved Email To Snix.IR