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

package repeater
import (
"errors"
"fmt"
"github.com/tehmaze/go-dmr/bit"
"github.com/tehmaze/go-dmr/bptc"
"github.com/tehmaze/go-dmr/dmr"
"github.com/tehmaze/go-dmr/fec"
"github.com/tehmaze/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)
}