2020-10-20 23:26:05 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
2020-10-25 12:56:28 +01:00
|
|
|
"bytes"
|
2020-10-25 18:24:36 +01:00
|
|
|
"encoding/binary"
|
2020-10-25 12:56:28 +01:00
|
|
|
"time"
|
2020-10-20 23:26:05 +02:00
|
|
|
)
|
|
|
|
|
|
2020-10-25 12:55:41 +01:00
|
|
|
const maxSerialFrameLength = 80 // Max. frame length according to Hamlib.
|
2020-11-21 11:02:52 +01:00
|
|
|
const serialRxSeqBufLength = 300 * time.Millisecond
|
2020-10-25 12:55:41 +01:00
|
|
|
|
2020-10-20 23:26:05 +02:00
|
|
|
type serialStream struct {
|
|
|
|
|
common streamCommon
|
|
|
|
|
|
2020-10-25 12:00:04 +01:00
|
|
|
sendSeq uint16
|
|
|
|
|
|
2020-10-25 18:29:31 +01:00
|
|
|
rxSeqBuf seqBuf
|
|
|
|
|
rxSeqBufEntryChan chan seqBufEntry
|
2020-10-25 18:24:36 +01:00
|
|
|
|
|
|
|
|
receivedSerialData bool
|
|
|
|
|
lastReceivedSeq uint16
|
|
|
|
|
|
2020-10-25 12:56:28 +01:00
|
|
|
readFromSerialPort struct {
|
|
|
|
|
buf bytes.Buffer
|
|
|
|
|
frameStarted bool
|
|
|
|
|
frameTimeout *time.Timer
|
|
|
|
|
}
|
|
|
|
|
|
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 {
|
|
|
|
|
l := byte(len(d))
|
2020-10-25 20:18:24 +01:00
|
|
|
p := append([]byte{0x15 + l, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
2020-10-25 12:00:04 +01:00
|
|
|
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...)
|
2020-10-25 20:18:24 +01:00
|
|
|
if err := s.common.pkt0.sendTrackedPacket(&s.common, p); err != nil {
|
2020-10-25 12:00:04 +01:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
s.sendSeq++
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *serialStream) sendOpenClose(close bool) error {
|
|
|
|
|
var magic byte
|
|
|
|
|
if close {
|
|
|
|
|
magic = 0x00
|
|
|
|
|
} else {
|
|
|
|
|
magic = 0x05
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-25 20:18:24 +01:00
|
|
|
p := []byte{0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
2020-10-25 12:00:04 +01:00
|
|
|
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}
|
2020-10-25 20:18:24 +01:00
|
|
|
if err := s.common.pkt0.sendTrackedPacket(&s.common, p); err != nil {
|
2020-10-25 12:00:04 +01:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
s.sendSeq++
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-25 18:24:36 +01:00
|
|
|
func (s *serialStream) handleRxSeqBufEntry(e seqBufEntry) {
|
|
|
|
|
gotSeq := uint16(e.seq)
|
|
|
|
|
if s.receivedSerialData {
|
2020-11-21 18:44:08 +01:00
|
|
|
// Out of order packets can happen if we receive a retransmitted packet, but too late.
|
|
|
|
|
if s.rxSeqBuf.leftOrRightCloserToSeq(e.seq, seqNum(s.lastReceivedSeq)) != left {
|
|
|
|
|
log.Debug("got out of order pkt seq #", e.seq)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-25 18:24:36 +01:00
|
|
|
expectedSeq := s.lastReceivedSeq + 1
|
|
|
|
|
if expectedSeq != gotSeq {
|
|
|
|
|
var missingPkts int
|
|
|
|
|
if gotSeq > expectedSeq {
|
|
|
|
|
missingPkts = int(gotSeq) - int(expectedSeq)
|
|
|
|
|
} else {
|
|
|
|
|
missingPkts = int(gotSeq) + 65536 - int(expectedSeq)
|
|
|
|
|
}
|
2020-10-28 18:03:35 +01:00
|
|
|
netstat.reportLoss(missingPkts)
|
2020-10-25 18:24:36 +01:00
|
|
|
log.Error("lost ", missingPkts, " packets")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
s.lastReceivedSeq = gotSeq
|
|
|
|
|
s.receivedSerialData = true
|
2020-10-25 16:15:39 +01:00
|
|
|
|
2020-10-25 20:18:24 +01:00
|
|
|
if s.common.pkt0.isPkt0(e.data) {
|
2020-10-25 18:24:36 +01:00
|
|
|
return
|
|
|
|
|
}
|
2020-10-25 16:15:39 +01:00
|
|
|
|
2020-10-25 18:24:36 +01:00
|
|
|
e.data = e.data[21:]
|
|
|
|
|
|
2020-11-04 10:18:32 +01:00
|
|
|
if !civControl.decode(e.data) {
|
|
|
|
|
return
|
|
|
|
|
}
|
2020-10-29 09:39:13 +01:00
|
|
|
|
2020-10-28 22:32:45 +01:00
|
|
|
if serialPort.write != nil {
|
|
|
|
|
serialPort.write <- e.data
|
2020-10-25 20:59:35 +01:00
|
|
|
}
|
2020-10-28 22:32:45 +01:00
|
|
|
if serialTCPSrv.isClientConnected() {
|
|
|
|
|
serialTCPSrv.toClient <- e.data
|
2020-10-25 18:24:36 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *serialStream) handleSerialPacket(r []byte) error {
|
|
|
|
|
gotSeq := binary.LittleEndian.Uint16(r[6:8])
|
2020-11-21 11:01:37 +01:00
|
|
|
return s.rxSeqBuf.add(seqNum(gotSeq), r)
|
2020-10-25 18:24:36 +01:00
|
|
|
}
|
2020-10-25 12:00:04 +01:00
|
|
|
|
2020-10-25 18:24:36 +01:00
|
|
|
func (s *serialStream) handleRead(r []byte) error {
|
2020-10-25 20:18:24 +01:00
|
|
|
// We add both idle pkt0 and serial data to the seqbuf.
|
|
|
|
|
if s.common.pkt0.isIdlePkt0(r) || (len(r) >= 22 && r[16] == 0xc1 && r[0]-0x15 == r[17]) {
|
2020-10-25 18:24:36 +01:00
|
|
|
return s.handleSerialPacket(r)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
2020-10-20 23:26:05 +02:00
|
|
|
}
|
|
|
|
|
|
2020-10-25 16:15:39 +01:00
|
|
|
func (s *serialStream) gotDataForRadio(r []byte) {
|
2020-10-25 14:16:12 +01:00
|
|
|
for len(r) > 0 && !s.readFromSerialPort.frameStarted {
|
|
|
|
|
if s.readFromSerialPort.buf.Len() > 1 {
|
|
|
|
|
s.readFromSerialPort.buf.Reset()
|
|
|
|
|
}
|
|
|
|
|
if s.readFromSerialPort.buf.Len() == 0 {
|
|
|
|
|
// Cut until we find the frame start byte.
|
|
|
|
|
for r[0] != 0xfe {
|
|
|
|
|
r = r[1:]
|
|
|
|
|
if len(r) == 0 {
|
|
|
|
|
return
|
2020-10-25 12:56:28 +01:00
|
|
|
}
|
2020-10-25 14:16:12 +01:00
|
|
|
}
|
|
|
|
|
// Found the first start byte.
|
|
|
|
|
s.readFromSerialPort.buf.WriteByte(r[0])
|
|
|
|
|
r = r[1:]
|
|
|
|
|
}
|
|
|
|
|
if len(r) > 0 && s.readFromSerialPort.buf.Len() == 1 {
|
|
|
|
|
if r[0] != 0xfe {
|
|
|
|
|
s.readFromSerialPort.buf.Reset()
|
|
|
|
|
r = r[1:]
|
|
|
|
|
} else {
|
|
|
|
|
// Found the second start byte.
|
2020-10-25 12:56:28 +01:00
|
|
|
s.readFromSerialPort.buf.WriteByte(r[0])
|
|
|
|
|
r = r[1:]
|
2020-10-25 14:16:12 +01:00
|
|
|
s.readFromSerialPort.frameTimeout.Reset(100 * time.Millisecond)
|
|
|
|
|
s.readFromSerialPort.frameStarted = true
|
2020-10-25 12:56:28 +01:00
|
|
|
}
|
|
|
|
|
}
|
2020-10-25 14:16:12 +01:00
|
|
|
}
|
2020-10-25 12:56:28 +01:00
|
|
|
|
2020-10-25 14:16:12 +01:00
|
|
|
for _, b := range r {
|
|
|
|
|
s.readFromSerialPort.buf.WriteByte(b)
|
|
|
|
|
if b == 0xfc || b == 0xfd || s.readFromSerialPort.buf.Len() == maxSerialFrameLength {
|
|
|
|
|
if err := s.send(s.readFromSerialPort.buf.Bytes()); err != nil {
|
|
|
|
|
reportError(err)
|
|
|
|
|
}
|
|
|
|
|
if !s.readFromSerialPort.frameTimeout.Stop() {
|
|
|
|
|
<-s.readFromSerialPort.frameTimeout.C
|
2020-10-25 12:56:28 +01:00
|
|
|
}
|
2020-10-25 14:16:12 +01:00
|
|
|
s.readFromSerialPort.buf.Reset()
|
|
|
|
|
s.readFromSerialPort.frameStarted = false
|
|
|
|
|
break
|
2020-10-25 12:56:28 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-23 14:00:59 +02:00
|
|
|
func (s *serialStream) loop() {
|
2020-10-25 20:59:35 +01:00
|
|
|
if enableSerialDevice {
|
|
|
|
|
for {
|
|
|
|
|
select {
|
2020-10-28 22:32:45 +01:00
|
|
|
case r := <-serialPort.read:
|
2020-10-27 17:27:39 +01:00
|
|
|
s.gotDataForRadio(r)
|
|
|
|
|
|
2020-10-25 20:59:35 +01:00
|
|
|
case r := <-s.common.readChan:
|
|
|
|
|
if err := s.handleRead(r); err != nil {
|
|
|
|
|
reportError(err)
|
|
|
|
|
}
|
|
|
|
|
case e := <-s.rxSeqBufEntryChan:
|
|
|
|
|
s.handleRxSeqBufEntry(e)
|
2020-10-28 22:32:45 +01:00
|
|
|
case r := <-serialTCPSrv.fromClient:
|
2020-10-25 20:59:35 +01:00
|
|
|
s.gotDataForRadio(r)
|
|
|
|
|
case <-s.readFromSerialPort.frameTimeout.C:
|
|
|
|
|
s.readFromSerialPort.buf.Reset()
|
|
|
|
|
s.readFromSerialPort.frameStarted = false
|
|
|
|
|
case <-s.deinitNeededChan:
|
|
|
|
|
s.deinitFinishedChan <- true
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for {
|
|
|
|
|
select {
|
|
|
|
|
case r := <-s.common.readChan:
|
|
|
|
|
if err := s.handleRead(r); err != nil {
|
|
|
|
|
reportError(err)
|
|
|
|
|
}
|
|
|
|
|
case e := <-s.rxSeqBufEntryChan:
|
|
|
|
|
s.handleRxSeqBufEntry(e)
|
2020-10-28 22:32:45 +01:00
|
|
|
case r := <-serialTCPSrv.fromClient:
|
2020-10-25 20:59:35 +01:00
|
|
|
s.gotDataForRadio(r)
|
|
|
|
|
case <-s.readFromSerialPort.frameTimeout.C:
|
|
|
|
|
s.readFromSerialPort.buf.Reset()
|
|
|
|
|
s.readFromSerialPort.frameStarted = false
|
|
|
|
|
case <-s.deinitNeededChan:
|
|
|
|
|
s.deinitFinishedChan <- true
|
|
|
|
|
return
|
2020-10-25 18:24:36 +01:00
|
|
|
}
|
2020-10-20 23:26:05 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-26 09:13:30 +01:00
|
|
|
func (s *serialStream) init(devName string) error {
|
2020-10-26 10:33:24 +01:00
|
|
|
if err := s.common.init("serial", serialStreamPort); err != nil {
|
2020-10-26 09:13:30 +01:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-25 20:59:35 +01:00
|
|
|
if enableSerialDevice {
|
2020-10-28 22:32:45 +01:00
|
|
|
if err := serialPort.initIfNeeded(devName); err != nil {
|
2020-10-25 20:59:35 +01:00
|
|
|
return err
|
|
|
|
|
}
|
2020-10-23 14:00:59 +02:00
|
|
|
}
|
2020-10-28 22:32:45 +01:00
|
|
|
if err := serialTCPSrv.initIfNeeded(); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2020-10-23 14:00:59 +02:00
|
|
|
|
2020-10-26 08:56:30 +01:00
|
|
|
if err := s.common.start(); err != nil {
|
2020-10-23 14:00:59 +02:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s.common.pkt7.startPeriodicSend(&s.common, 1, false)
|
2020-10-28 09:47:51 +01:00
|
|
|
s.common.pkt0.init(&s.common)
|
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
|
|
|
|
2020-10-26 08:56:30 +01:00
|
|
|
log.Print("stream started")
|
|
|
|
|
|
2020-10-26 09:13:30 +01:00
|
|
|
s.rxSeqBufEntryChan = make(chan seqBufEntry)
|
2020-11-21 11:01:37 +01:00
|
|
|
s.rxSeqBuf.init(serialRxSeqBufLength, 0xffff, 0, s.rxSeqBufEntryChan, s.common.requestRetransmit)
|
2020-10-26 09:13:30 +01:00
|
|
|
|
2020-10-23 14:00:59 +02:00
|
|
|
s.deinitNeededChan = make(chan bool)
|
|
|
|
|
s.deinitFinishedChan = make(chan bool)
|
2020-10-25 12:56:28 +01:00
|
|
|
|
|
|
|
|
s.readFromSerialPort.frameTimeout = time.NewTimer(0)
|
|
|
|
|
<-s.readFromSerialPort.frameTimeout.C
|
|
|
|
|
|
2020-11-09 11:50:36 +01:00
|
|
|
civControl.deinit()
|
2020-11-09 10:05:39 +01:00
|
|
|
civControl = civControlStruct{}
|
2020-10-30 22:12:30 +01:00
|
|
|
if err := civControl.init(s); err != nil {
|
2020-10-29 09:39:13 +01:00
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-23 14:00:59 +02:00
|
|
|
go s.loop()
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *serialStream) deinit() {
|
2020-10-25 16:15:39 +01:00
|
|
|
if s.common.conn != nil {
|
2020-10-25 12:00:04 +01:00
|
|
|
_ = s.sendOpenClose(true)
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-23 14:00:59 +02:00
|
|
|
if s.deinitNeededChan != nil {
|
|
|
|
|
s.deinitNeededChan <- true
|
|
|
|
|
<-s.deinitFinishedChan
|
|
|
|
|
}
|
2020-11-09 10:05:39 +01:00
|
|
|
civControl.deinit()
|
2020-10-23 14:00:59 +02:00
|
|
|
s.common.deinit()
|
2020-10-25 18:24:36 +01:00
|
|
|
s.rxSeqBuf.deinit()
|
2020-10-20 23:26:05 +02:00
|
|
|
}
|