2020-10-21 09:26:21 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
2020-10-21 13:59:56 +02:00
|
|
|
"os"
|
|
|
|
|
|
2020-10-21 09:26:21 +02:00
|
|
|
"github.com/google/goterm/term"
|
|
|
|
|
"github.com/nonoo/kappanhang/log"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type serialPortStruct struct {
|
2020-10-23 14:00:59 +02:00
|
|
|
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:26:21 +02:00
|
|
|
}
|
|
|
|
|
|
2020-10-21 09:37:26 +02:00
|
|
|
func (s *serialPortStruct) writeLoop() {
|
|
|
|
|
s.write = make(chan []byte)
|
|
|
|
|
var b []byte
|
|
|
|
|
for {
|
2020-10-23 14:00:59 +02:00
|
|
|
select {
|
|
|
|
|
case b = <-s.write:
|
|
|
|
|
case <-s.writeLoopDeinitNeededChan:
|
|
|
|
|
s.writeLoopDeinitFinishedChan <- true
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-21 09:37:26 +02:00
|
|
|
bytesToWrite := len(b)
|
|
|
|
|
|
|
|
|
|
for bytesToWrite > 0 {
|
|
|
|
|
written, err := s.pty.Master.Write(b)
|
|
|
|
|
if err != nil {
|
2020-10-21 13:59:56 +02:00
|
|
|
if _, ok := err.(*os.PathError); !ok {
|
2020-10-23 14:00:59 +02:00
|
|
|
reportError(err)
|
2020-10-21 13:59:56 +02:00
|
|
|
}
|
2020-10-21 09:37:26 +02:00
|
|
|
}
|
|
|
|
|
b = b[written:]
|
|
|
|
|
bytesToWrite -= 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 {
|
2020-10-23 14:00:59 +02:00
|
|
|
reportError(err)
|
2020-10-21 13:59:56 +02:00
|
|
|
}
|
2020-10-21 09:37:26 +02:00
|
|
|
}
|
2020-10-23 14:00:59 +02:00
|
|
|
|
|
|
|
|
select {
|
|
|
|
|
case s.read <- b[:n]:
|
|
|
|
|
case <-s.readLoopDeinitNeededChan:
|
|
|
|
|
s.readLoopDeinitFinishedChan <- true
|
|
|
|
|
return
|
|
|
|
|
}
|
2020-10-21 09:37:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-23 14:00:59 +02:00
|
|
|
func (s *serialPortStruct) init(devName string) (err error) {
|
2020-10-21 09:26:21 +02:00
|
|
|
s.pty, err = term.OpenPTY()
|
|
|
|
|
if err != nil {
|
2020-10-23 14:00:59 +02:00
|
|
|
return err
|
2020-10-21 09:26:21 +02:00
|
|
|
}
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-21 09:26:21 +02:00
|
|
|
n, err := s.pty.PTSName()
|
|
|
|
|
if err != nil {
|
2020-10-23 14:00:59 +02:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
s.symlink = "/tmp/kappanhang-" + devName + ".pty"
|
|
|
|
|
_ = os.Remove(s.symlink)
|
|
|
|
|
if err := os.Symlink(n, s.symlink); err != nil {
|
|
|
|
|
return err
|
2020-10-21 09:26:21 +02:00
|
|
|
}
|
2020-10-23 14:00:59 +02:00
|
|
|
log.Print("opened ", n, " as ", s.symlink)
|
2020-10-21 09:37:26 +02:00
|
|
|
|
2020-10-23 14:00:59 +02:00
|
|
|
s.readLoopDeinitNeededChan = make(chan bool)
|
|
|
|
|
s.readLoopDeinitFinishedChan = make(chan bool)
|
2020-10-21 09:37:26 +02:00
|
|
|
go s.readLoop()
|
2020-10-23 14:00:59 +02:00
|
|
|
s.writeLoopDeinitNeededChan = make(chan bool)
|
|
|
|
|
s.writeLoopDeinitFinishedChan = make(chan bool)
|
2020-10-21 09:37:26 +02:00
|
|
|
go s.writeLoop()
|
2020-10-23 14:00:59 +02:00
|
|
|
return nil
|
2020-10-21 09:26:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *serialPortStruct) deinit() {
|
|
|
|
|
if s.pty != nil {
|
|
|
|
|
s.pty.Close()
|
|
|
|
|
}
|
2020-10-23 14:00:59 +02:00
|
|
|
_ = os.Remove(s.symlink)
|
|
|
|
|
if s.readLoopDeinitNeededChan != nil {
|
|
|
|
|
s.readLoopDeinitNeededChan <- true
|
|
|
|
|
<-s.readLoopDeinitFinishedChan
|
|
|
|
|
}
|
|
|
|
|
if s.writeLoopDeinitNeededChan != nil {
|
|
|
|
|
s.writeLoopDeinitNeededChan <- true
|
|
|
|
|
<-s.writeLoopDeinitFinishedChan
|
|
|
|
|
}
|
2020-10-21 09:26:21 +02:00
|
|
|
}
|