add 0x3400 command fallback for dante subscription discovery
This commit is contained in:
@@ -204,6 +204,9 @@ func (t *Tendrils) queryDanteDeviceWithPort(ip net.IP, port int) *DanteDeviceInf
|
|||||||
|
|
||||||
if info.RxChannelCount > 0 || info.TxChannelCount > 0 {
|
if info.RxChannelCount > 0 || info.TxChannelCount > 0 {
|
||||||
info.Subscriptions, info.HasMulticast = t.queryDanteSubscriptions(conn, ip, info.RxChannelCount, info.TxChannelCount)
|
info.Subscriptions, info.HasMulticast = t.queryDanteSubscriptions(conn, ip, info.RxChannelCount, info.TxChannelCount)
|
||||||
|
if len(info.Subscriptions) == 0 && info.RxChannelCount > 0 {
|
||||||
|
info.Subscriptions = t.queryDanteSubscriptions3400(conn, ip, info.RxChannelCount)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if info.TxChannelCount > 0 {
|
if info.TxChannelCount > 0 {
|
||||||
@@ -453,6 +456,94 @@ func extractNullTerminatedString(data []byte, offset int) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Tendrils) queryDanteSubscriptions3400(conn *net.UDPConn, ip net.IP, rxCount int) []DanteSubscription {
|
||||||
|
var subscriptions []DanteSubscription
|
||||||
|
|
||||||
|
pagesNeeded := (rxCount + 15) / 16
|
||||||
|
startChannel := 1
|
||||||
|
for page := 0; page < pagesNeeded; page++ {
|
||||||
|
pageNum := page + 1
|
||||||
|
args := make([]byte, 24)
|
||||||
|
args[7] = 0x01
|
||||||
|
binary.BigEndian.PutUint16(args[8:10], uint16(pageNum))
|
||||||
|
binary.BigEndian.PutUint16(args[10:12], uint16(startChannel))
|
||||||
|
|
||||||
|
resp := t.sendDanteCommand(conn, ip, 0x3400, args)
|
||||||
|
if resp == nil || len(resp) < 44 {
|
||||||
|
if t.DebugDante {
|
||||||
|
log.Printf("[dante] %s: 0x3400 page %d: no response or too short", ip, pageNum)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
status := binary.BigEndian.Uint16(resp[8:10])
|
||||||
|
if status != 0x8112 && status != 0x0001 {
|
||||||
|
if t.DebugDante {
|
||||||
|
log.Printf("[dante] %s: 0x3400 status=0x%04x", ip, status)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
recordCount := 0
|
||||||
|
for i := 12; i < 44 && i+1 < len(resp); i += 2 {
|
||||||
|
offset := int(binary.BigEndian.Uint16(resp[i : i+2]))
|
||||||
|
if offset == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
recordCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < recordCount; i++ {
|
||||||
|
offsetPos := 12 + i*2
|
||||||
|
if offsetPos+2 > len(resp) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
recordOffset := int(binary.BigEndian.Uint16(resp[offsetPos : offsetPos+2]))
|
||||||
|
if recordOffset == 0 || recordOffset >= len(resp) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
rxChannelName := extractNullTerminatedString(resp, recordOffset)
|
||||||
|
if rxChannelName == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
txDeviceStart := recordOffset + len(rxChannelName) + 1
|
||||||
|
txDeviceName := extractNullTerminatedString(resp, txDeviceStart)
|
||||||
|
if txDeviceName == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
txChannelName := ""
|
||||||
|
searchStart := txDeviceStart + len(txDeviceName) + 1
|
||||||
|
for j := searchStart; j < recordOffset+64 && j < len(resp)-1; j++ {
|
||||||
|
if resp[j] >= '0' && resp[j] <= '9' {
|
||||||
|
candidate := extractNullTerminatedString(resp, j)
|
||||||
|
if len(candidate) >= 1 && len(candidate) <= 4 {
|
||||||
|
txChannelName = candidate
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rxChannel := startChannel + i
|
||||||
|
if t.DebugDante {
|
||||||
|
log.Printf("[dante] %s: 0x3400 sub: rx=%d rxName=%q txDev=%q txCh=%q", ip, rxChannel, rxChannelName, txDeviceName, txChannelName)
|
||||||
|
}
|
||||||
|
|
||||||
|
subscriptions = append(subscriptions, DanteSubscription{
|
||||||
|
RxChannel: rxChannel,
|
||||||
|
TxDeviceName: txDeviceName,
|
||||||
|
TxChannelName: txChannelName,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
startChannel += 16
|
||||||
|
}
|
||||||
|
|
||||||
|
return subscriptions
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Tendrils) probeDanteDevice(ip net.IP) {
|
func (t *Tendrils) probeDanteDevice(ip net.IP) {
|
||||||
t.probeDanteDeviceWithPort(ip, danteControlPort)
|
t.probeDanteDeviceWithPort(ip, danteControlPort)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user