You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
2.3 KiB
Go
109 lines
2.3 KiB
Go
9 years ago
|
package repeater
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
|
||
|
"github.com/pd0mz/go-dmr/bit"
|
||
|
"github.com/pd0mz/go-dmr/bptc"
|
||
|
"github.com/pd0mz/go-dmr/dmr"
|
||
|
"github.com/pd0mz/go-dmr/fec"
|
||
|
"github.com/pd0mz/go-dmr/ipsc"
|
||
|
)
|
||
|
|
||
|
type LC struct {
|
||
|
CallType uint8
|
||
|
DstID, SrcID uint32
|
||
|
}
|
||
|
|
||
|
func (r *Repeater) HandleTerminatorWithLC(p *ipsc.Packet) error {
|
||
|
r.DataCallEnd(p)
|
||
|
|
||
|
var (
|
||
|
err error
|
||
|
payload = make([]byte, 12)
|
||
|
)
|
||
|
if err = bptc.Process(dmr.ExtractInfoBits(p.PayloadBits), payload); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// CRC mask to the checksum. See DMR AI. spec. page 143.
|
||
|
payload[9] ^= 0x99
|
||
|
payload[10] ^= 0x99
|
||
|
payload[11] ^= 0x99
|
||
|
|
||
|
var lc *LC
|
||
|
if lc, err = r.lcDecodeFullLC(payload); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
fmt.Printf(" lc: %d -> %d\n", lc.SrcID, lc.DstID)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (r *Repeater) HandleVoiceLCHeader(p *ipsc.Packet) error {
|
||
|
r.DataCallEnd(p)
|
||
|
|
||
|
var (
|
||
|
err error
|
||
|
payload = make([]byte, 12)
|
||
|
)
|
||
|
if err = bptc.Process(dmr.ExtractInfoBits(p.PayloadBits), payload); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// CRC mask to the checksum. See DMR AI. spec. page 143
|
||
|
for i := 9; i < 12; i++ {
|
||
|
payload[i] ^= 0x99
|
||
|
}
|
||
|
|
||
|
var lc *LC
|
||
|
if lc, err = r.lcDecodeFullLC(payload); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
fmt.Printf(" lc: %d -> %d\n", lc.SrcID, lc.DstID)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (r *Repeater) lcDecode(payload []byte) (*LC, error) {
|
||
|
if payload[0]&bit.B10000000 > 0 {
|
||
|
return nil, errors.New("dmr/lc: protect flag is not 0")
|
||
|
}
|
||
|
if payload[1] != 0 {
|
||
|
return nil, errors.New("dmr/lc: feature set ID is not 0")
|
||
|
}
|
||
|
|
||
|
lc := &LC{}
|
||
|
switch payload[0] & bit.B00111111 {
|
||
|
case 3:
|
||
|
lc.CallType = ipsc.CallTypePrivate
|
||
|
case 0:
|
||
|
lc.CallType = ipsc.CallTypeGroup
|
||
|
default:
|
||
|
return nil, fmt.Errorf("dmr/lc: invalid FCLO; unknown call type %#02x", payload[0]&bit.B00111111)
|
||
|
}
|
||
|
|
||
|
lc.DstID = uint32(payload[3])<<16 | uint32(payload[4])<<8 | uint32(payload[5])
|
||
|
lc.SrcID = uint32(payload[6])<<16 | uint32(payload[7])<<8 | uint32(payload[8])
|
||
|
return lc, nil
|
||
|
}
|
||
|
|
||
|
func (r *Repeater) lcDecodeFullLC(payload []byte) (*LC, error) {
|
||
|
var (
|
||
|
err error
|
||
|
syndrome = fec.RS_12_9_Poly{}
|
||
|
)
|
||
|
if err = fec.RS_12_9_CalcSyndrome(payload, &syndrome); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if fec.RS_12_9_CheckSyndrome(&syndrome) {
|
||
|
if _, err = fec.RS_12_9_Correct(payload, &syndrome); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return r.lcDecode(payload)
|
||
|
}
|