From f5e97f0f6b42274dd99bdb948e69b81145227b56 Mon Sep 17 00:00:00 2001 From: hackerman-kl Date: Sun, 12 Apr 2026 11:12:15 +0200 Subject: [PATCH] milan-avb: adjust the msrp/adp and acmp state machine to communicate talker discovery and srp reserveration --- .../acmp-cmds-resps/acmp-milan-v12.c | 89 +++++++++++-------- .../acmp-cmds-resps/acmp-milan-v12.h | 11 ++- src/modules/module-avb/acmp.c | 18 ++-- src/modules/module-avb/acmp.h | 10 ++- src/modules/module-avb/adp.c | 10 +-- src/modules/module-avb/msrp.c | 16 +++- 6 files changed, 97 insertions(+), 57 deletions(-) diff --git a/src/modules/module-avb/acmp-cmds-resps/acmp-milan-v12.c b/src/modules/module-avb/acmp-cmds-resps/acmp-milan-v12.c index 88c189af5..94db86975 100644 --- a/src/modules/module-avb/acmp-cmds-resps/acmp-milan-v12.c +++ b/src/modules/module-avb/acmp-cmds-resps/acmp-milan-v12.c @@ -1977,15 +1977,41 @@ static int acmp_generic_timer_handler_milan_v12(struct acmp *acmp, uint64_t now, return cmd->state_handler(acmp, si_state, tmr->saved_packet, tmr->saved_packet_len, now); } -static int acmp_generic_adp_srp_evt_lt_handler_milan_v12(struct acmp *acmp, - uint64_t entity_id, enum fsm_acmp_evt_milan_v12 event) +static int acmp_generic_srp_evt_lt_handler_milan_v12(struct acmp *acmp, + struct avb_msrp_attribute *msrp_attr, + enum fsm_acmp_evt_milan_v12 event, uint64_t now) { - const struct listener_fsm_cmd *cmd; + struct stream_common *sc; + struct aecp_aem_stream_input_state *stream_in; struct aecp_aem_stream_input_state_milan_v12 *si_state; + const struct listener_fsm_cmd *cmd; + + sc = SPA_CONTAINER_OF(msrp_attr, struct stream_common, lstream_attr); + stream_in = SPA_CONTAINER_OF(sc, struct aecp_aem_stream_input_state, common); + si_state = SPA_CONTAINER_OF(stream_in, + struct aecp_aem_stream_input_state_milan_v12, stream_in_sta); + + cmd = &cmd_listeners_states[si_state->acmp_status.fsm_acmp_state][event]; + if (!cmd->state_handler) { + pw_log_warn("No handler: STATE:%s EVT:%s - ignoring", + fsm_acmp_state_milan_v12_str[si_state->acmp_status.fsm_acmp_state], + fsm_acmp_evt_milan_v12_str[event]); + return 0; + } + + return cmd->state_handler(acmp, si_state, NULL, 0, now); +} + +static int acmp_generic_adp_evt_lt_handler_milan_v12(struct acmp *acmp, + uint64_t entity_id, enum fsm_acmp_evt_milan_v12 event, uint64_t now) +{ + struct aecp_aem_stream_input_state_milan_v12 *si_state; + const struct listener_fsm_cmd *cmd; struct descriptor *desc; - enum fsm_acmp_state_milan_v12 fsm_state; uint16_t desc_type = AVB_AEM_DESC_STREAM_INPUT; - int rc; + int rc = 0; + + (void)entity_id; for (uint16_t desc_index = 0; desc_index < UINT16_MAX; desc_index++) { desc = server_find_descriptor(acmp->server, desc_type, desc_index); @@ -1993,33 +2019,22 @@ static int acmp_generic_adp_srp_evt_lt_handler_milan_v12(struct acmp *acmp, break; si_state = (struct aecp_aem_stream_input_state_milan_v12 *)desc->ptr; - fsm_state = si_state->acmp_status.fsm_acmp_state; - cmd = &cmd_listeners_states[fsm_state][event]; - - if (!cmd) { - pw_log_warn("Invalid transition STATE:%s EVT:%s - ignoring", - fsm_acmp_state_milan_v12_str[fsm_state], + cmd = &cmd_listeners_states[si_state->acmp_status.fsm_acmp_state][event]; + if (!cmd->state_handler) { + pw_log_warn("No handler: STATE:%s EVT:%s - ignoring", + fsm_acmp_state_milan_v12_str[si_state->acmp_status.fsm_acmp_state], fsm_acmp_evt_milan_v12_str[event]); continue; } - rc = cmd->state_handler(acmp, si_state, NULL, 0, 0); - if (rc){ + rc = cmd->state_handler(acmp, si_state, NULL, 0, now); + if (rc) pw_log_error("cmd failed for stream %p", si_state); - } } - return 0; + return rc; } -#if 0 -static int acmp_generic_srp_evt_handler_milan_v12(struct acmp *acmp, uint64_t now, - uint64_t entity_id, enum fsm_acmp_evt_milan_v12 event) -{ - return 0; -} -#endif - int acmp_init_talker_stream_milan_v12(struct acmp *acmp, void *acmp_status) { return 0; @@ -2061,28 +2076,32 @@ int handle_get_rx_state_command_milan_v12(struct acmp *acmp, uint64_t now, FSM_ACMP_EVT_MILAN_V12_RCV_GET_RX_STATE); } -int handle_evt_tk_discovered_milan_v12(struct acmp *acmp, uint64_t talker_guid) +int handle_evt_tk_discovered_milan_v12(struct acmp *acmp, uint64_t talker_guid, + uint64_t now) { - return acmp_generic_adp_srp_evt_lt_handler_milan_v12(acmp, talker_guid, - FSM_ACMP_EVT_MILAN_V12_TK_DISCOVERED); + return acmp_generic_adp_evt_lt_handler_milan_v12(acmp, talker_guid, + FSM_ACMP_EVT_MILAN_V12_TK_DISCOVERED, now); } -int handle_evt_tk_departed_milan_v12(struct acmp *acmp, uint64_t talker_guid) +int handle_evt_tk_departed_milan_v12(struct acmp *acmp, uint64_t talker_guid, + uint64_t now) { - return acmp_generic_adp_srp_evt_lt_handler_milan_v12(acmp, talker_guid, - FSM_ACMP_EVT_MILAN_V12_TK_DEPARTED); + return acmp_generic_adp_evt_lt_handler_milan_v12(acmp, talker_guid, + FSM_ACMP_EVT_MILAN_V12_TK_DEPARTED, now); } -int handle_evt_tk_registered_milan_v12(struct acmp *acmp, uint64_t talker_guid) +int handle_evt_tk_registered_milan_v12(struct acmp *acmp, + struct avb_msrp_attribute *msrp_attr, uint64_t now) { - return acmp_generic_adp_srp_evt_lt_handler_milan_v12(acmp, talker_guid, - FSM_ACMP_EVT_MILAN_V12_TK_REGISTERED); + return acmp_generic_srp_evt_lt_handler_milan_v12(acmp, msrp_attr, + FSM_ACMP_EVT_MILAN_V12_TK_REGISTERED, now); } -int handle_evt_tk_unregistered_milan_v12(struct acmp *acmp, uint64_t talker_guid) +int handle_evt_tk_unregistered_milan_v12(struct acmp *acmp, + struct avb_msrp_attribute *msrp_attr, uint64_t now) { - return acmp_generic_adp_srp_evt_lt_handler_milan_v12(acmp, talker_guid, - FSM_ACMP_EVT_MILAN_V12_TK_UNREGISTERED); + return acmp_generic_srp_evt_lt_handler_milan_v12(acmp, msrp_attr, + FSM_ACMP_EVT_MILAN_V12_TK_UNREGISTERED, now); } int handle_probe_tx_command_milan_v12(struct acmp *acmp, uint64_t now, diff --git a/src/modules/module-avb/acmp-cmds-resps/acmp-milan-v12.h b/src/modules/module-avb/acmp-cmds-resps/acmp-milan-v12.h index 63a26eb02..3a7ba6458 100644 --- a/src/modules/module-avb/acmp-cmds-resps/acmp-milan-v12.h +++ b/src/modules/module-avb/acmp-cmds-resps/acmp-milan-v12.h @@ -6,6 +6,7 @@ #include #include "acmp-common.h" +#include "../msrp.h" /** Milan v1.2 ACMP */ enum fsm_acmp_state_milan_v12 { @@ -51,11 +52,13 @@ int handle_probe_tx_response_milan_v12(struct acmp *acmp, uint64_t now, int handle_get_rx_state_command_milan_v12(struct acmp *acmp, uint64_t now, const void *m, int len); -int handle_evt_tk_discovered_milan_v12(struct acmp *acmp, uint64_t entity); -int handle_evt_tk_departed_milan_v12(struct acmp *acmp, uint64_t entity); +int handle_evt_tk_discovered_milan_v12(struct acmp *acmp, uint64_t entity, uint64_t now); +int handle_evt_tk_departed_milan_v12(struct acmp *acmp, uint64_t entity, uint64_t now); -int handle_evt_tk_registered_milan_v12(struct acmp *acmp, uint64_t talker_guid); -int handle_evt_tk_unregistered_milan_v12(struct acmp *acmp, uint64_t talker_guid); +int handle_evt_tk_registered_milan_v12(struct acmp *acmp, + struct avb_msrp_attribute *msrp_attr, uint64_t now); +int handle_evt_tk_unregistered_milan_v12(struct acmp *acmp, + struct avb_msrp_attribute *msrp_attr, uint64_t now); int acmp_tmr_no_resp_milan_v12(struct acmp *acmp, uint64_t now); int acmp_tmr_retry_milan_v12(struct acmp *acmp, uint64_t now); diff --git a/src/modules/module-avb/acmp.c b/src/modules/module-avb/acmp.c index 5f0d75d32..c88027c4d 100644 --- a/src/modules/module-avb/acmp.c +++ b/src/modules/module-avb/acmp.c @@ -254,13 +254,13 @@ static void acmp_periodic(void *data, uint64_t now) } -int handle_evt_tk_discovered(struct avb_acmp *avb_acmp, uint64_t entity) +int handle_evt_tk_discovered(struct avb_acmp *avb_acmp, uint64_t entity, uint64_t now) { struct acmp *acmp = (struct acmp*)avb_acmp; switch (acmp->server->avb_mode) { case AVB_MODE_MILAN_V12: - return handle_evt_tk_discovered_milan_v12(acmp, entity); + return handle_evt_tk_discovered_milan_v12(acmp, entity, now); break; case AVB_MODE_LEGACY: pw_log_warn("not implemented for legacy avb"); @@ -273,13 +273,13 @@ int handle_evt_tk_discovered(struct avb_acmp *avb_acmp, uint64_t entity) return -1; } -int handle_evt_tk_departed(struct avb_acmp *avb_acmp, uint64_t entity) +int handle_evt_tk_departed(struct avb_acmp *avb_acmp, uint64_t entity, uint64_t now) { struct acmp *acmp = (struct acmp*)avb_acmp; switch (acmp->server->avb_mode) { case AVB_MODE_MILAN_V12: - return handle_evt_tk_departed_milan_v12(acmp, entity); + return handle_evt_tk_departed_milan_v12(acmp, entity, now); break; case AVB_MODE_LEGACY: pw_log_warn("not implemented for legacy avb"); @@ -292,13 +292,14 @@ int handle_evt_tk_departed(struct avb_acmp *avb_acmp, uint64_t entity) return 0; } -int handle_evt_tk_registered(struct avb_acmp *avb_acmp, uint64_t entity) +int handle_evt_tk_registered(struct avb_acmp *avb_acmp, + struct avb_msrp_attribute *msrp_attr, uint64_t now) { struct acmp *acmp = (struct acmp*)avb_acmp; switch (acmp->server->avb_mode) { case AVB_MODE_MILAN_V12: - return handle_evt_tk_registered_milan_v12(acmp, entity); + return handle_evt_tk_registered_milan_v12(acmp, msrp_attr, now); break; case AVB_MODE_LEGACY: pw_log_warn("not implemented for legacy avb"); @@ -311,13 +312,14 @@ int handle_evt_tk_registered(struct avb_acmp *avb_acmp, uint64_t entity) return -1; } -int handle_evt_tk_unregistered(struct avb_acmp *avb_acmp, uint64_t entity) +int handle_evt_tk_unregistered(struct avb_acmp *avb_acmp, + struct avb_msrp_attribute *msrp_attr, uint64_t now) { struct acmp *acmp = (struct acmp*)avb_acmp; switch (acmp->server->avb_mode) { case AVB_MODE_MILAN_V12: - return handle_evt_tk_unregistered_milan_v12(acmp, entity); + return handle_evt_tk_unregistered_milan_v12(acmp, msrp_attr, now); break; case AVB_MODE_LEGACY: pw_log_warn("not implemented for legacy avb"); diff --git a/src/modules/module-avb/acmp.h b/src/modules/module-avb/acmp.h index 7f5495af1..e9e706314 100644 --- a/src/modules/module-avb/acmp.h +++ b/src/modules/module-avb/acmp.h @@ -105,10 +105,12 @@ int acmp_fini_listener_stream(struct avb_acmp *avb_acmp, struct avb_acmp *avb_acmp_register(struct server *server); void avb_acmp_unregister(struct avb_acmp *acmp); -int handle_evt_tk_discovered(struct avb_acmp *avb_acmp, uint64_t entity); -int handle_evt_tk_departed(struct avb_acmp *avb_acmp, uint64_t entity); +int handle_evt_tk_discovered(struct avb_acmp *avb_acmp, uint64_t entity, uint64_t now); +int handle_evt_tk_departed(struct avb_acmp *avb_acmp, uint64_t entity, uint64_t now); -int handle_evt_tk_registered(struct avb_acmp *avb_acmp, uint64_t entity); -int handle_evt_tk_unregistered(struct avb_acmp *avb_acmp, uint64_t entity); +int handle_evt_tk_registered(struct avb_acmp *avb_acmp, + struct avb_msrp_attribute *msrp_attr, uint64_t now); +int handle_evt_tk_unregistered(struct avb_acmp *avb_acmp, + struct avb_msrp_attribute *msrp_attr, uint64_t now); #endif /* AVB_ACMP_H */ diff --git a/src/modules/module-avb/adp.c b/src/modules/module-avb/adp.c index 95ea491db..c9cf57d30 100644 --- a/src/modules/module-avb/adp.c +++ b/src/modules/module-avb/adp.c @@ -132,7 +132,7 @@ static int adp_message(void *data, uint64_t now, const void *message, int len) if (server->avb_mode == AVB_MODE_MILAN_V12) { //Milan V1.2 Section 5.6.4.5.1 - if (handle_evt_tk_discovered(server->acmp, entity_id)) { + if (handle_evt_tk_discovered(server->acmp, entity_id, now)) { pw_log_info("handling available event"); return -1; } @@ -146,7 +146,7 @@ static int adp_message(void *data, uint64_t now, const void *message, int len) SPA_PTROFF(h_saved, sizeof(*h_saved), void); if (p_saved->available_index != p->available_index) { - if (handle_evt_tk_departed(server->acmp, entity_id)) { + if (handle_evt_tk_departed(server->acmp, entity_id, now)) { pw_log_info("handling departing event"); return -1; } @@ -162,7 +162,7 @@ static int adp_message(void *data, uint64_t now, const void *message, int len) return 0; } - if (handle_evt_tk_discovered(server->acmp, entity_id)) { + if (handle_evt_tk_discovered(server->acmp, entity_id, now)) { pw_log_warn("handling available event"); return -1; } @@ -178,7 +178,7 @@ static int adp_message(void *data, uint64_t now, const void *message, int len) if (e != NULL) { if (server->avb_mode == AVB_MODE_MILAN_V12) { // Milan v1.2 Section 5.6.4.5.3 - handle_evt_tk_departed(server->acmp, entity_id); + handle_evt_tk_departed(server->acmp, entity_id, now); } pw_log_info("entity %s departing", @@ -232,7 +232,7 @@ static void check_timeout(struct adp *adp, uint64_t now) pw_log_info("entity %s timeout", avb_utils_format_id(buf, sizeof(buf), e->entity_id)); - handle_evt_tk_departed(avb_acmp, e->entity_id); + handle_evt_tk_departed(avb_acmp, e->entity_id, now); if (e->advertise) send_departing(adp, now, e); diff --git a/src/modules/module-avb/msrp.c b/src/modules/module-avb/msrp.c index 5449dc655..6b55e5b21 100644 --- a/src/modules/module-avb/msrp.c +++ b/src/modules/module-avb/msrp.c @@ -12,6 +12,7 @@ #include "utils.h" #include "msrp.h" +#include "acmp.h" static const uint8_t msrp_mac[6] = AVB_MSRP_MAC; @@ -55,6 +56,11 @@ static void notify_talker(struct msrp *msrp, uint64_t now, struct attr *attr, ui { pw_log_info("> notify talker advertise: %s", avb_mrp_notify_name(notify)); 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) + handle_evt_tk_discovered(msrp->server->acmp, stream_id, now); + else if (notify == AVB_MRP_NOTIFY_LEAVE) + handle_evt_tk_departed(msrp->server->acmp, stream_id, now); } } @@ -71,12 +77,14 @@ static int process_talker(struct msrp *msrp, uint64_t now, uint8_t attr_type, { const struct avb_packet_msrp_talker *t = m; struct attr *a; - spa_list_for_each(a, &msrp->attributes, link) + spa_list_for_each(a, &msrp->attributes, link) { if (a->attr->type == attr_type && a->attr->attr.talker.stream_id == t->stream_id) { a->attr->attr.talker = *t; avb_mrp_attribute_rx_event(a->attr->mrp, now, event); } + } + return 0; } static int encode_talker(struct msrp *msrp, struct attr *a, void *m) @@ -146,6 +154,12 @@ static void notify_listener(struct msrp *msrp, uint64_t now, struct attr *attr, pw_log_info("> notify listener: %s", avb_mrp_notify_name(notify)); debug_msrp_listener(&attr->attr->attr.listener, attr->attr->param); + if (msrp->server->avb_mode == AVB_MODE_MILAN_V12) { + 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); + } } static int process_listener(struct msrp *msrp, uint64_t now, uint8_t attr_type,