kappanhang/serial-linux.go

119 lines
2.3 KiB
Go
Raw Normal View History

package main
import (
2020-10-21 13:59:56 +02:00
"os"
"github.com/google/goterm/term"
"github.com/nonoo/kappanhang/log"
)
type serialPortStruct struct {
pty *term.PTY
symlink string
writeLoopDeinitNeededChan chan bool
writeLoopDeinitFinishedChan chan bool
readLoopDeinitNeededChan chan bool
readLoopDeinitFinishedChan chan bool
2020-10-21 09:37:26 +02:00
// Read from this channel to receive serial data.
read chan []byte
// Write to this channel to send serial data.
write chan []byte
}
2020-10-21 09:37:26 +02:00
func (s *serialPortStruct) writeLoop() {
s.write = make(chan []byte)
var b []byte
for {
select {
case b = <-s.write:
case <-s.writeLoopDeinitNeededChan:
s.writeLoopDeinitFinishedChan <- true
return
}
2020-10-25 14:15:52 +01:00
for len(b) > 0 {
2020-10-21 09:37:26 +02:00
written, err := s.pty.Master.Write(b)
if err != nil {
2020-10-21 13:59:56 +02:00
if _, ok := err.(*os.PathError); !ok {
reportError(err)
2020-10-21 13:59:56 +02:00
}
2020-10-21 09:37:26 +02:00
}
b = b[written:]
}
}
}
func (s *serialPortStruct) readLoop() {
s.read = make(chan []byte)
2020-10-25 12:55:41 +01:00
b := make([]byte, maxSerialFrameLength)
2020-10-21 09:37:26 +02:00
for {
n, err := s.pty.Master.Read(b)
if err != nil {
2020-10-21 13:59:56 +02:00
if _, ok := err.(*os.PathError); !ok {
reportError(err)
2020-10-21 13:59:56 +02:00
}
2020-10-21 09:37:26 +02:00
}
select {
case s.read <- b[:n]:
case <-s.readLoopDeinitNeededChan:
s.readLoopDeinitFinishedChan <- true
return
}
2020-10-21 09:37:26 +02:00
}
}
func (s *serialPortStruct) init(devName string) (err error) {
s.pty, err = term.OpenPTY()
if err != nil {
return err
}
2020-10-25 12:55:53 +01:00
var t term.Termios
t.Raw()
err = t.Set(s.pty.Master)
if err != nil {
return err
}
err = t.Set(s.pty.Slave)
if err != nil {
return err
}
n, err := s.pty.PTSName()
if err != nil {
return err
}
s.symlink = "/tmp/kappanhang-" + devName + ".pty"
_ = os.Remove(s.symlink)
if err := os.Symlink(n, s.symlink); err != nil {
return err
}
log.Print("opened ", n, " as ", s.symlink)
2020-10-21 09:37:26 +02:00
s.readLoopDeinitNeededChan = make(chan bool)
s.readLoopDeinitFinishedChan = make(chan bool)
2020-10-21 09:37:26 +02:00
go s.readLoop()
s.writeLoopDeinitNeededChan = make(chan bool)
s.writeLoopDeinitFinishedChan = make(chan bool)
2020-10-21 09:37:26 +02:00
go s.writeLoop()
return nil
}
func (s *serialPortStruct) deinit() {
if s.pty != nil {
s.pty.Close()
}
_ = os.Remove(s.symlink)
if s.readLoopDeinitNeededChan != nil {
s.readLoopDeinitNeededChan <- true
<-s.readLoopDeinitFinishedChan
}
if s.writeLoopDeinitNeededChan != nil {
s.writeLoopDeinitNeededChan <- true
<-s.writeLoopDeinitFinishedChan
}
}