| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- /*
- * SPDX-FileCopyrightText: 2026 Benjamin Harris
- * SPDX-License-Identifier: Apache-2.0
- *
- * Dante device discovery over mDNS / DNS-SD.
- *
- * CLEAN-ROOM: implemented from the behavioural notes in
- * docs/dante-protocol-notes.md (service types, ports, TXT keys), NOT from
- * any GPL/AGPL reference source. See CLAUDE.md.
- *
- * This is the read-only half of Dante discovery: it browses the network for
- * Dante devices and their transmit channels / multicast bundles and reports
- * what it finds. It does not advertise this device (that needs the ARC/CMC
- * servers behind it) and does not touch audio.
- *
- * Dante publishes these DNS-SD service types, all under _udp.local:
- * _netaudio-arc device control endpoint (ARC port, e.g. 4440)
- * _netaudio-cmc device announce endpoint (CMC port, e.g. 8800)
- * _netaudio-chan one instance per TX channel (flow-control port)
- * _netaudio-bund a multicast bundle other devices can join
- */
- #pragma once
- #include <stdint.h>
- #include <stdbool.h>
- #include "esp_err.h"
- #ifdef __cplusplus
- extern "C" {
- #endif
- /* Which Dante DNS-SD service a result came from. */
- typedef enum {
- DANTE_SVC_ARC = 0, /* _netaudio-arc — device control endpoint */
- DANTE_SVC_CMC, /* _netaudio-cmc — device announce endpoint */
- DANTE_SVC_CHAN, /* _netaudio-chan — a transmit channel */
- DANTE_SVC_BUND, /* _netaudio-bund — a multicast bundle */
- DANTE_SVC_COUNT
- } dante_service_type_t;
- /* One discovered service instance, flattened from an mDNS PTR+SRV+TXT+A set.
- * String fields are only valid for the duration of the callback. */
- typedef struct {
- dante_service_type_t service; /* which _netaudio-* type */
- const char *instance; /* DNS-SD instance name, e.g. "chanName@host" */
- const char *hostname; /* SRV target host */
- uint32_t ipv4; /* resolved IPv4 (host byte order), 0 if none */
- uint16_t port; /* SRV port */
- const char *const *txt_keys; /* TXT record keys (txt_count entries) */
- const char *const *txt_vals; /* TXT record values (txt_count entries) */
- size_t txt_count;
- } dante_discovery_result_t;
- /* Callback invoked once per discovered instance. `user` is passed through
- * from the scan/start call. Must not block for long. */
- typedef void (*dante_discovery_cb_t)(const dante_discovery_result_t *result,
- void *user);
- /*
- * One-shot synchronous scan of all Dante service types.
- *
- * Issues an mDNS PTR query per service type, waits up to `timeout_ms` for
- * each, and invokes `cb` for every instance found. If `cb` is NULL, results
- * are logged at INFO level instead. Safe to call whether or not the AES67
- * stack has already initialised mDNS (init is shared and idempotent).
- *
- * Returns ESP_OK if the scan ran (even if nothing was found).
- */
- esp_err_t dante_discovery_scan(uint32_t timeout_ms,
- dante_discovery_cb_t cb, void *user);
- /*
- * Start a background task that repeats dante_discovery_scan() every
- * `interval_ms`. `cb`/`user` are as above. Only one background scanner may
- * run at a time. Pin/priority follow project convention (core 0, low prio).
- */
- esp_err_t dante_discovery_start(uint32_t interval_ms,
- dante_discovery_cb_t cb, void *user);
- /* Stop the background scanner started by dante_discovery_start(). */
- void dante_discovery_stop(void);
- /* Human-readable name for a service type, e.g. "_netaudio-arc". */
- const char *dante_service_type_str(dante_service_type_t svc);
- #ifdef __cplusplus
- }
- #endif
|