diff options
author | root <sina@snix.ir> | 2022-05-09 20:25:01 +0000 |
---|---|---|
committer | root <sina@snix.ir> | 2022-05-09 20:25:01 +0000 |
commit | 433065e7a8984c09c082c997be950d67a9f9aa93 (patch) | |
tree | 3ff637bc08ccfa093edd7e7c207d5bb7f7136f95 /ports.go |
userial snix repository
Diffstat (limited to 'ports.go')
-rw-r--r-- | ports.go | 93 |
1 files changed, 93 insertions, 0 deletions
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 +} |