2020-10-20 23:26:05 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"github.com/nonoo/kappanhang/log"
|
|
|
|
|
)
|
|
|
|
|
|
2020-10-25 12:55:41 +01:00
|
|
|
const maxSerialFrameLength = 80 // Max. frame length according to Hamlib.
|
|
|
|
|
|
2020-10-20 23:26:05 +02:00
|
|
|
type serialStream struct {
|
|
|
|
|
common streamCommon
|
|
|
|
|
|
2020-10-23 14:00:59 +02:00
|
|
|
serialPort serialPortStruct
|
|
|
|
|
|
2020-10-25 12:00:04 +01:00
|
|
|
sendSeq uint16
|
|
|
|
|
|
2020-10-23 14:00:59 +02:00
|
|
|
deinitNeededChan chan bool
|
|
|
|
|
deinitFinishedChan chan bool
|
2020-10-20 23:26:05 +02:00
|
|
|
}
|
|
|
|
|
|
2020-10-25 12:00:04 +01:00
|
|
|
func (s *serialStream) send(d []byte) error {
|
|
|
|
|
s.common.pkt0.sendSeqLock()
|
|
|
|
|
defer s.common.pkt0.sendSeqUnlock()
|
|
|
|
|
|
|
|
|
|
l := byte(len(d))
|
|
|
|
|
p := append([]byte{0x15 + l, 0x00, 0x00, 0x00, 0x00, 0x00, byte(s.common.pkt0.sendSeq), byte(s.common.pkt0.sendSeq >> 8),
|
|
|
|
|
byte(s.common.localSID >> 24), byte(s.common.localSID >> 16), byte(s.common.localSID >> 8), byte(s.common.localSID),
|
|
|
|
|
byte(s.common.remoteSID >> 24), byte(s.common.remoteSID >> 16), byte(s.common.remoteSID >> 8), byte(s.common.remoteSID),
|
|
|
|
|
0xc1, l, 0x00, byte(s.sendSeq >> 8), byte(s.sendSeq)}, d...)
|
|
|
|
|
if err := s.common.send(p); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
s.sendSeq++
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *serialStream) sendOpenClose(close bool) error {
|
|
|
|
|
s.common.pkt0.sendSeqLock()
|
|
|
|
|
defer s.common.pkt0.sendSeqUnlock()
|
|
|
|
|
|
|
|
|
|
var magic byte
|
|
|
|
|
if close {
|
|
|
|
|
magic = 0x00
|
|
|
|
|
} else {
|
|
|
|
|
magic = 0x05
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p := []byte{0x16, 0x00, 0x00, 0x00, 0x00, 0x00, byte(s.common.pkt0.sendSeq), byte(s.common.pkt0.sendSeq >> 8),
|
|
|
|
|
byte(s.common.localSID >> 24), byte(s.common.localSID >> 16), byte(s.common.localSID >> 8), byte(s.common.localSID),
|
|
|
|
|
byte(s.common.remoteSID >> 24), byte(s.common.remoteSID >> 16), byte(s.common.remoteSID >> 8), byte(s.common.remoteSID),
|
|
|
|
|
0xc0, 0x01, 0x00, byte(s.sendSeq >> 8), byte(s.sendSeq), magic}
|
|
|
|
|
if err := s.common.send(p); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
s.sendSeq++
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-20 23:26:05 +02:00
|
|
|
func (s *serialStream) handleRead(r []byte) {
|
2020-10-25 12:00:04 +01:00
|
|
|
if len(r) >= 22 {
|
|
|
|
|
if r[16] == 0xc1 && r[0]-0x15 == r[17] {
|
|
|
|
|
s.serialPort.write <- r[21:]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-20 23:26:05 +02:00
|
|
|
}
|
|
|
|
|
|
2020-10-23 14:00:59 +02:00
|
|
|
func (s *serialStream) loop() {
|
2020-10-20 23:26:05 +02:00
|
|
|
for {
|
|
|
|
|
select {
|
|
|
|
|
case r := <-s.common.readChan:
|
|
|
|
|
s.handleRead(r)
|
2020-10-25 12:00:04 +01:00
|
|
|
case r := <-s.serialPort.read:
|
|
|
|
|
if err := s.send(r); err != nil {
|
|
|
|
|
reportError(err)
|
|
|
|
|
}
|
2020-10-23 14:00:59 +02:00
|
|
|
case <-s.deinitNeededChan:
|
|
|
|
|
s.deinitFinishedChan <- true
|
|
|
|
|
return
|
2020-10-20 23:26:05 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-23 14:00:59 +02:00
|
|
|
func (s *serialStream) start(devName string) error {
|
|
|
|
|
if err := s.serialPort.init(devName); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := s.common.sendPkt3(); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if err := s.common.waitForPkt4Answer(); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if err := s.common.sendPkt6(); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if err := s.common.waitForPkt6Answer(); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.Print("stream started")
|
|
|
|
|
|
|
|
|
|
s.common.pkt7.startPeriodicSend(&s.common, 1, false)
|
2020-10-25 12:00:04 +01:00
|
|
|
s.common.pkt0.startPeriodicSend(&s.common)
|
|
|
|
|
|
|
|
|
|
if err := s.sendOpenClose(false); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2020-10-23 14:00:59 +02:00
|
|
|
|
|
|
|
|
s.deinitNeededChan = make(chan bool)
|
|
|
|
|
s.deinitFinishedChan = make(chan bool)
|
|
|
|
|
go s.loop()
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *serialStream) init() error {
|
|
|
|
|
if err := s.common.init("serial", 50002); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *serialStream) deinit() {
|
2020-10-25 12:00:04 +01:00
|
|
|
if s.common.pkt0.sendTicker != nil { // Stream opened?
|
|
|
|
|
_ = s.sendOpenClose(true)
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-23 14:00:59 +02:00
|
|
|
if s.deinitNeededChan != nil {
|
|
|
|
|
s.deinitNeededChan <- true
|
|
|
|
|
<-s.deinitFinishedChan
|
|
|
|
|
}
|
|
|
|
|
s.common.deinit()
|
|
|
|
|
s.serialPort.deinit()
|
2020-10-20 23:26:05 +02:00
|
|
|
}
|