From b12694314396a2db12707a9dcf534505ca2d588a Mon Sep 17 00:00:00 2001 From: hackerman-kl Date: Sat, 25 Apr 2026 08:16:27 +0200 Subject: [PATCH] milan-avb: msrp: state logging, Milan listener_observed and log refinements --- src/modules/module-avb/msrp.c | 124 +++++++++++++++++++++++++++++++--- src/modules/module-avb/msrp.h | 2 + 2 files changed, 118 insertions(+), 8 deletions(-) diff --git a/src/modules/module-avb/msrp.c b/src/modules/module-avb/msrp.c index c01af30ce..04d561bed 100644 --- a/src/modules/module-avb/msrp.c +++ b/src/modules/module-avb/msrp.c @@ -14,6 +14,8 @@ #include "msrp.h" #include "acmp.h" #include "stream.h" +#include "aecp-aem.h" +#include "aecp-aem-state.h" static const uint8_t msrp_mac[6] = AVB_MSRP_MAC; @@ -58,8 +60,11 @@ static void debug_msrp_talker(const struct avb_packet_msrp_talker *t) static void notify_talker(struct msrp *msrp, uint64_t now, struct attr *attr, uint8_t notify) { struct stream_common *sc; + char label[64]; - pw_log_info("> notify talker advertise: %s", avb_mrp_notify_name(notify)); + pw_log_debug("> notify talker advertise: %s", avb_mrp_notify_name(notify)); + snprintf(label, sizeof(label), "MSRP talker-adv %s", avb_mrp_notify_name(notify)); + avb_log_state(msrp->server, label); if (msrp->server->avb_mode == AVB_MODE_MILAN_V12) { uint64_t stream_id = be64toh(attr->attr->attr.talker.stream_id); if (notify == AVB_MRP_NOTIFY_NEW || notify == AVB_MRP_NOTIFY_JOIN) @@ -79,7 +84,10 @@ static void notify_talker(struct msrp *msrp, uint64_t now, struct attr *attr, ui static void notify_talker_failed(struct msrp *msrp, uint64_t now, struct attr *attr, uint8_t notify) { - pw_log_info("> notify talker failed: %s", avb_mrp_notify_name(notify)); + char label[64]; + pw_log_debug("> notify talker failed: %s", avb_mrp_notify_name(notify)); + snprintf(label, sizeof(label), "MSRP talker-fail %s", avb_mrp_notify_name(notify)); + avb_log_state(msrp->server, label); if (msrp->server->avb_mode == AVB_MODE_MILAN_V12) { if (notify == AVB_MRP_NOTIFY_NEW || notify == AVB_MRP_NOTIFY_JOIN) @@ -166,14 +174,44 @@ static void debug_msrp_listener(const struct avb_packet_msrp_listener *l, uint8_ static void notify_listener(struct msrp *msrp, uint64_t now, struct attr *attr, uint8_t notify) { - pw_log_info("> notify listener: %s", avb_mrp_notify_name(notify)); - debug_msrp_listener(&attr->attr->attr.listener, attr->attr->param); + struct stream_common *sc; + struct stream *s; + char label[64]; - if (msrp->server->avb_mode == AVB_MODE_MILAN_V12) { + pw_log_debug("> notify listener: %s", avb_mrp_notify_name(notify)); + debug_msrp_listener(&attr->attr->attr.listener, attr->attr->param); + snprintf(label, sizeof(label), "MSRP listener %s", avb_mrp_notify_name(notify)); + avb_log_state(msrp->server, label); + + if (msrp->server->avb_mode != AVB_MODE_MILAN_V12) + return; + + /* Milan Section 4.3.3.1 second condition: a Listener attribute + * matching the Stream Output's stream_id is registered. */ + sc = SPA_CONTAINER_OF(attr->attr, struct stream_common, lstream_attr); + s = &sc->stream; + + if (s->direction == SPA_DIRECTION_INPUT) { if (notify == AVB_MRP_NOTIFY_NEW || notify == AVB_MRP_NOTIFY_JOIN) handle_evt_tk_registered(msrp->server->acmp, attr->attr, now); else if (notify == AVB_MRP_NOTIFY_LEAVE) handle_evt_tk_unregistered(msrp->server->acmp, attr->attr, now); + } else { + struct aecp_aem_stream_output_state *stream_out = + SPA_CONTAINER_OF(sc, struct aecp_aem_stream_output_state, common); + bool prev = stream_out->listener_observed; + + if (notify == AVB_MRP_NOTIFY_NEW || notify == AVB_MRP_NOTIFY_JOIN) + stream_out->listener_observed = true; + else if (notify == AVB_MRP_NOTIFY_LEAVE) + stream_out->listener_observed = false; + + /* listener_observed flips flags_ex.REGISTERING in the + * GET_STREAM_INFO answer (Milan Table 5.12). Hint AECP to + * re-emit so controllers see the update. */ + if (prev != stream_out->listener_observed) + avb_aecp_aem_mark_stream_info_dirty(msrp->server, + AVB_AEM_DESC_STREAM_OUTPUT, s->index); } } @@ -234,7 +272,7 @@ static void debug_msrp_domain(const struct avb_packet_msrp_domain *d) static void notify_domain(struct msrp *msrp, uint64_t now, struct attr *attr, uint8_t notify) { - pw_log_info("> notify domain: %s", avb_mrp_notify_name(notify)); + pw_log_debug("> notify domain: %s", avb_mrp_notify_name(notify)); debug_msrp_domain(&attr->attr->attr.domain); } @@ -455,13 +493,16 @@ static void msrp_event(void *data, uint64_t now, uint8_t event) if (dispatch[a->attr->type].encode == NULL) continue; - pw_log_debug("send %s %s", dispatch[a->attr->type].name, + pw_log_info("MSRP encode %s %s", + dispatch[a->attr->type].name, avb_mrp_send_name(a->attr->mrp->pending_send)); len = dispatch[a->attr->type].encode(msrp, a, msg); if (len < 0) break; + a->attr->mrp->pending_send = 0; + count++; msg = SPA_PTROFF(msg, len, void); total += len; @@ -469,9 +510,11 @@ static void msrp_event(void *data, uint64_t now, uint8_t event) f = (struct avb_packet_mrp_footer *)msg; f->end_mark = 0; - if (count > 0) + if (count > 0) { + pw_log_info("MSRP send: %d attribute(s), %zu bytes", count, total); avb_server_send_packet(msrp->server, msrp_mac, AVB_MSRP_ETH, buffer, total); + } } static const struct avb_mrp_events mrp_events = { @@ -480,6 +523,71 @@ static const struct avb_mrp_events mrp_events = { }; +static const char *msrp_attr_type_name(uint8_t type) +{ + switch (type) { + case AVB_MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE: return "talker-adv"; + case AVB_MSRP_ATTRIBUTE_TYPE_TALKER_FAILED: return "talker-fail"; + case AVB_MSRP_ATTRIBUTE_TYPE_LISTENER: return "listener"; + case AVB_MSRP_ATTRIBUTE_TYPE_DOMAIN: return "domain"; + default: return "?"; + } +} + +void avb_msrp_log_state(struct server *server, const char *label) +{ + struct msrp *msrp = (struct msrp *)server->msrp; + struct attr *a; + char buf[64]; + int n = 0; + + if (msrp == NULL) + return; + + spa_list_for_each(a, &msrp->attributes, link) + n++; + pw_log_debug("[%s] MSRP: %d attribute%s", label, n, n == 1 ? "" : "s"); + + spa_list_for_each(a, &msrp->attributes, link) { + uint8_t app_st = avb_mrp_attribute_get_applicant_state(a->attr->mrp); + uint8_t reg_st = avb_mrp_attribute_get_registrar_state(a->attr->mrp); + switch (a->attr->type) { + case AVB_MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE: + case AVB_MSRP_ATTRIBUTE_TYPE_TALKER_FAILED: + pw_log_debug("[%s] %-11s stream_id=%s app=%s reg=%s", + label, msrp_attr_type_name(a->attr->type), + avb_utils_format_id(buf, sizeof(buf), + be64toh(a->attr->attr.talker.stream_id)), + avb_applicant_state_name(app_st), + avb_registrar_state_name(reg_st)); + break; + case AVB_MSRP_ATTRIBUTE_TYPE_LISTENER: + pw_log_debug("[%s] %-11s stream_id=%s param=%u app=%s reg=%s", + label, msrp_attr_type_name(a->attr->type), + avb_utils_format_id(buf, sizeof(buf), + be64toh(a->attr->attr.listener.stream_id)), + a->attr->param, + avb_applicant_state_name(app_st), + avb_registrar_state_name(reg_st)); + break; + case AVB_MSRP_ATTRIBUTE_TYPE_DOMAIN: + pw_log_debug("[%s] %-11s class_id=%u prio=%u vid=%u app=%s reg=%s", + label, msrp_attr_type_name(a->attr->type), + a->attr->attr.domain.sr_class_id, + a->attr->attr.domain.sr_class_priority, + ntohs(a->attr->attr.domain.sr_class_vid), + avb_applicant_state_name(app_st), + avb_registrar_state_name(reg_st)); + break; + default: + pw_log_debug("[%s] type=%u app=%s reg=%s", label, a->attr->type, + avb_applicant_state_name(app_st), + avb_registrar_state_name(reg_st)); + break; + } + } +} + struct avb_msrp *avb_msrp_register(struct server *server) { struct msrp *msrp; diff --git a/src/modules/module-avb/msrp.h b/src/modules/module-avb/msrp.h index 8d6e3b3a9..c5b33b824 100644 --- a/src/modules/module-avb/msrp.h +++ b/src/modules/module-avb/msrp.h @@ -113,4 +113,6 @@ int avb_msrp_attribute_new(struct avb_msrp *m, struct avb_msrp_attribute *attr, struct avb_msrp *avb_msrp_register(struct server *server); +void avb_msrp_log_state(struct server *server, const char *label); + #endif /* AVB_MSRP_H */