2023-02-08 18:12:00 +01:00
|
|
|
/* AVB support */
|
|
|
|
|
/* SPDX-FileCopyrightText: Copyright © 2022 Wim Taymans */
|
|
|
|
|
/* SPDX-License-Identifier: MIT */
|
2022-03-18 15:18:11 +01:00
|
|
|
|
|
|
|
|
#include <spa/utils/json.h>
|
|
|
|
|
#include <spa/debug/mem.h>
|
|
|
|
|
|
|
|
|
|
#include <pipewire/pipewire.h>
|
|
|
|
|
|
|
|
|
|
#include "acmp.h"
|
2026-04-27 12:21:13 +02:00
|
|
|
#include "aecp-aem.h"
|
2022-03-24 17:00:40 +01:00
|
|
|
#include "msrp.h"
|
2022-03-18 15:18:11 +01:00
|
|
|
#include "internal.h"
|
2022-04-05 18:10:27 +02:00
|
|
|
#include "stream.h"
|
2025-11-27 09:37:37 +01:00
|
|
|
#include "aecp-aem-descriptors.h"
|
2022-03-18 15:18:11 +01:00
|
|
|
|
2026-01-15 09:20:24 +01:00
|
|
|
#include "acmp-cmds-resps/acmp-common.h"
|
|
|
|
|
#include "acmp-cmds-resps/acmp-legacy-avb.h"
|
|
|
|
|
#include "acmp-cmds-resps/acmp-milan-v12.h"
|
|
|
|
|
|
2022-03-22 19:40:23 +01:00
|
|
|
static const uint8_t mac[6] = AVB_BROADCAST_MAC;
|
|
|
|
|
|
2022-04-06 16:46:02 +02:00
|
|
|
static int handle_ignore(struct acmp *acmp, uint64_t now, const void *m, int len)
|
2022-03-18 18:02:18 +01:00
|
|
|
{
|
2022-03-21 13:26:26 +01:00
|
|
|
return 0;
|
2022-03-18 18:02:18 +01:00
|
|
|
}
|
|
|
|
|
|
2026-01-15 09:20:24 +01:00
|
|
|
static const char * const acmp_cmd_names[] = {
|
2026-01-19 09:39:49 +01:00
|
|
|
/** Milan V1.2 Section 5.5.2.2 (PDU) */
|
|
|
|
|
[AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_COMMAND] =
|
|
|
|
|
"connect-tx-command/probe-tx-command",
|
|
|
|
|
|
|
|
|
|
/** Milan V1.2 Section 5.5.2.2 (PDU) */
|
|
|
|
|
[AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_RESPONSE] =
|
|
|
|
|
"connect-tx-response/probe-tx-response",
|
|
|
|
|
|
2026-01-15 09:20:24 +01:00
|
|
|
[AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_COMMAND] = "disconnect-tx-command",
|
|
|
|
|
[AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_RESPONSE] = "disconnect-tx-response",
|
|
|
|
|
[AVB_ACMP_MESSAGE_TYPE_GET_TX_STATE_COMMAND] = "get-tx-state-command",
|
|
|
|
|
[AVB_ACMP_MESSAGE_TYPE_GET_TX_STATE_RESPONSE] = "get-tx-state-response",
|
2026-01-19 09:39:49 +01:00
|
|
|
|
|
|
|
|
/** Milan V1.2 Section 5.5.2.2 (PDU) */
|
|
|
|
|
[AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_COMMAND] =
|
|
|
|
|
"connect-rx-command/bind-rx-command",
|
|
|
|
|
|
|
|
|
|
/** Milan V1.2 Section 5.5.2.2 (PDU) */
|
|
|
|
|
[AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE] =
|
|
|
|
|
"connect-rx-response/bind-rx-response",
|
|
|
|
|
|
|
|
|
|
/** Milan V1.2 Section 5.5.2.2 (PDU) */
|
|
|
|
|
[AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_COMMAND] =
|
|
|
|
|
"disconnect-rx-command/unbind-rx-command",
|
|
|
|
|
|
|
|
|
|
/** Milan V1.2 Section 5.5.2.2 (PDU) */
|
|
|
|
|
[AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE] =
|
|
|
|
|
"disconnect-rx-response/unbind-rx-response",
|
|
|
|
|
|
2026-01-15 09:20:24 +01:00
|
|
|
[AVB_ACMP_MESSAGE_TYPE_GET_RX_STATE_COMMAND] = "get-rx-state-command",
|
|
|
|
|
[AVB_ACMP_MESSAGE_TYPE_GET_RX_STATE_RESPONSE] = "get-rx-state-response",
|
|
|
|
|
[AVB_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_COMMAND] = "get-tx-connection-command",
|
|
|
|
|
[AVB_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_RESPONSE] = "get-tx-connection-response",
|
2022-03-18 15:18:11 +01:00
|
|
|
};
|
|
|
|
|
|
2026-01-15 09:20:24 +01:00
|
|
|
struct acmp_cmds {
|
|
|
|
|
int (*handle) (struct acmp *acmp, uint64_t now, const void *m, int len);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define AVB_ACMP_CMD_HANDLER(mtype, handler) \
|
|
|
|
|
[mtype] = { .handle = handler }
|
|
|
|
|
|
|
|
|
|
static const struct acmp_cmds acmp_cmds_legacy_avb[] = {
|
2026-01-19 09:39:49 +01:00
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_COMMAND,
|
|
|
|
|
handle_connect_tx_command_legacy_avb),
|
|
|
|
|
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_RESPONSE,
|
|
|
|
|
handle_connect_tx_response_legacy_avb),
|
|
|
|
|
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_COMMAND,
|
|
|
|
|
handle_disconnect_tx_command_legacy_avb),
|
|
|
|
|
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_RESPONSE,
|
|
|
|
|
handle_disconnect_tx_response_legacy_avb),
|
|
|
|
|
|
2026-01-15 09:20:24 +01:00
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_TX_STATE_COMMAND, NULL),
|
2026-01-19 09:39:49 +01:00
|
|
|
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_TX_STATE_RESPONSE,
|
|
|
|
|
handle_ignore),
|
|
|
|
|
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_COMMAND,
|
|
|
|
|
handle_connect_rx_command_legacy_avb),
|
|
|
|
|
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE,
|
|
|
|
|
handle_ignore),
|
|
|
|
|
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_COMMAND,
|
|
|
|
|
handle_disconnect_rx_command_legacy_avb),
|
|
|
|
|
|
2026-01-15 09:20:24 +01:00
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE, NULL),
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_RX_STATE_COMMAND, handle_ignore),
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_RX_STATE_RESPONSE, handle_ignore),
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_COMMAND, NULL),
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_RESPONSE, handle_ignore),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const struct acmp_cmds acmp_cmds_milan_v12[] = {
|
2026-01-19 09:39:49 +01:00
|
|
|
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_COMMAND,
|
|
|
|
|
handle_probe_tx_command_milan_v12),
|
|
|
|
|
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_RESPONSE,
|
|
|
|
|
handle_probe_tx_response_milan_v12),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_COMMAND,
|
|
|
|
|
handle_bind_rx_command_milan_v12),
|
|
|
|
|
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_COMMAND,
|
|
|
|
|
handle_unbind_rx_command_milan_v12),
|
|
|
|
|
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_COMMAND,
|
2026-04-18 18:01:48 +02:00
|
|
|
handle_disconnect_tx_command_milan_v12),
|
2026-01-19 09:39:49 +01:00
|
|
|
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_RESPONSE,
|
|
|
|
|
handle_ignore),
|
|
|
|
|
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_RX_STATE_COMMAND,
|
|
|
|
|
handle_get_rx_state_command_milan_v12),
|
|
|
|
|
|
2026-01-15 09:20:24 +01:00
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE, NULL),
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE, NULL),
|
2026-04-18 18:01:48 +02:00
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_COMMAND,
|
|
|
|
|
handle_get_tx_connection_command_milan_v12),
|
2026-01-19 09:39:49 +01:00
|
|
|
|
2026-04-18 18:01:48 +02:00
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_TX_STATE_COMMAND,
|
|
|
|
|
handle_get_tx_state_command_milan_v12),
|
2026-01-19 09:39:49 +01:00
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_TX_STATE_RESPONSE, handle_ignore),
|
|
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_RX_STATE_RESPONSE, NULL),
|
2026-01-15 09:20:24 +01:00
|
|
|
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_RESPONSE, NULL),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const struct {
|
|
|
|
|
const struct acmp_cmds *cmds;
|
|
|
|
|
size_t count;
|
|
|
|
|
} acmp_cmds_modes[AVB_MODE_MAX] = {
|
|
|
|
|
[AVB_MODE_LEGACY] = {
|
|
|
|
|
.cmds = acmp_cmds_legacy_avb,
|
|
|
|
|
.count = SPA_N_ELEMENTS(acmp_cmds_legacy_avb),
|
|
|
|
|
},
|
|
|
|
|
[AVB_MODE_MILAN_V12] = {
|
|
|
|
|
.cmds = acmp_cmds_milan_v12,
|
|
|
|
|
.count = SPA_N_ELEMENTS(acmp_cmds_milan_v12),
|
|
|
|
|
},
|
|
|
|
|
};
|
2022-03-18 15:18:11 +01:00
|
|
|
|
|
|
|
|
static int acmp_message(void *data, uint64_t now, const void *message, int len)
|
|
|
|
|
{
|
|
|
|
|
struct acmp *acmp = data;
|
2022-03-22 19:40:23 +01:00
|
|
|
struct server *server = acmp->server;
|
2022-04-07 15:14:45 +02:00
|
|
|
const struct avb_ethernet_header *h = message;
|
|
|
|
|
const struct avb_packet_acmp *p = SPA_PTROFF(h, sizeof(*h), void);
|
2026-01-15 09:20:24 +01:00
|
|
|
int mtype;
|
2022-03-18 15:18:11 +01:00
|
|
|
|
2026-04-27 12:21:13 +02:00
|
|
|
if (len < 0 ||
|
|
|
|
|
(size_t)len < sizeof(*h) + sizeof(*p) ||
|
|
|
|
|
(size_t)len > AVB_PACKET_MILAN_DEFAULT_MTU)
|
|
|
|
|
return 0;
|
|
|
|
|
|
2022-04-07 15:14:45 +02:00
|
|
|
if (ntohs(h->type) != AVB_TSN_ETH)
|
2022-03-22 19:40:23 +01:00
|
|
|
return 0;
|
2026-01-15 09:20:24 +01:00
|
|
|
|
2022-04-07 15:14:45 +02:00
|
|
|
if (memcmp(h->dest, mac, 6) != 0 &&
|
2026-01-19 09:39:49 +01:00
|
|
|
memcmp(h->dest, server->mac_addr, 6) != 0)
|
2022-03-22 19:40:23 +01:00
|
|
|
return 0;
|
|
|
|
|
|
2022-03-25 10:28:18 +01:00
|
|
|
if (AVB_PACKET_GET_SUBTYPE(&p->hdr) != AVB_SUBTYPE_ACMP)
|
2022-03-18 15:18:11 +01:00
|
|
|
return 0;
|
|
|
|
|
|
2026-01-15 09:20:24 +01:00
|
|
|
mtype = AVB_PACKET_ACMP_GET_MESSAGE_TYPE(p);
|
2022-03-18 15:18:11 +01:00
|
|
|
|
2026-01-15 09:20:24 +01:00
|
|
|
pw_log_info("got ACMP message %s", acmp_cmd_names[mtype]);
|
2026-04-25 08:53:35 +02:00
|
|
|
avb_log_state(server, acmp_cmd_names[mtype]);
|
2022-03-18 15:18:11 +01:00
|
|
|
|
2026-04-19 17:07:30 +02:00
|
|
|
switch (mtype) {
|
|
|
|
|
case AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_COMMAND:
|
|
|
|
|
case AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_COMMAND:
|
|
|
|
|
case AVB_ACMP_MESSAGE_TYPE_GET_RX_STATE_COMMAND:
|
|
|
|
|
if (be64toh(p->listener_guid) != server->entity_id)
|
|
|
|
|
return 0;
|
|
|
|
|
break;
|
|
|
|
|
case AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_COMMAND:
|
|
|
|
|
case AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_COMMAND:
|
|
|
|
|
case AVB_ACMP_MESSAGE_TYPE_GET_TX_STATE_COMMAND:
|
|
|
|
|
case AVB_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_COMMAND:
|
|
|
|
|
if (be64toh(p->talker_guid) != server->entity_id)
|
|
|
|
|
return 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-15 09:20:24 +01:00
|
|
|
if (mtype < 0 || (size_t)mtype >= acmp_cmds_modes[server->avb_mode].count) {
|
2026-04-19 17:07:30 +02:00
|
|
|
if (mtype & 1)
|
|
|
|
|
return 0;
|
2026-01-19 09:39:49 +01:00
|
|
|
return acmp_reply_not_supported(acmp, mtype | 1, message, len);
|
2026-01-15 09:20:24 +01:00
|
|
|
}
|
2022-03-18 15:18:11 +01:00
|
|
|
|
2026-04-19 17:07:30 +02:00
|
|
|
if (acmp_cmds_modes[server->avb_mode].cmds[mtype].handle == NULL) {
|
|
|
|
|
if (mtype & 1)
|
|
|
|
|
return 0;
|
2026-01-19 09:39:49 +01:00
|
|
|
return acmp_reply_not_supported(acmp, mtype | 1, message, len);
|
2026-04-19 17:07:30 +02:00
|
|
|
}
|
2022-03-18 15:18:11 +01:00
|
|
|
|
2026-01-15 09:20:24 +01:00
|
|
|
return acmp_cmds_modes[server->avb_mode].cmds[mtype].handle(acmp, now, message, len);
|
2022-03-18 15:18:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void acmp_destroy(void *data)
|
|
|
|
|
{
|
|
|
|
|
struct acmp *acmp = data;
|
2026-01-19 09:39:49 +01:00
|
|
|
switch (acmp->server->avb_mode) {
|
|
|
|
|
case AVB_MODE_MILAN_V12:
|
|
|
|
|
acmp_destroy_milan_v12(acmp);
|
|
|
|
|
break;
|
|
|
|
|
case AVB_MODE_LEGACY:
|
|
|
|
|
acmp_server_destroy_legacy_avb(acmp);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
pw_log_warn("Unknown avb_mode");
|
|
|
|
|
break;
|
2022-03-18 18:02:18 +01:00
|
|
|
}
|
2026-01-19 09:39:49 +01:00
|
|
|
|
|
|
|
|
spa_hook_remove(&acmp->server_listener);
|
2022-03-18 18:02:18 +01:00
|
|
|
}
|
2026-01-19 09:39:49 +01:00
|
|
|
|
2022-03-18 18:02:18 +01:00
|
|
|
|
2022-03-18 15:18:11 +01:00
|
|
|
static int do_help(struct acmp *acmp, const char *args, FILE *out)
|
|
|
|
|
{
|
|
|
|
|
fprintf(out, "{ \"type\": \"help\","
|
|
|
|
|
"\"text\": \""
|
2026-01-19 09:39:49 +01:00
|
|
|
" /acmp/help: this help \\n"
|
2022-03-18 15:18:11 +01:00
|
|
|
"\" }");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int acmp_command(void *data, uint64_t now, const char *command, const char *args, FILE *out)
|
|
|
|
|
{
|
|
|
|
|
struct acmp *acmp = data;
|
|
|
|
|
int res;
|
|
|
|
|
|
|
|
|
|
if (!spa_strstartswith(command, "/acmp/"))
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
command += strlen("/acmp/");
|
|
|
|
|
|
|
|
|
|
if (spa_streq(command, "help"))
|
|
|
|
|
res = do_help(acmp, args, out);
|
2026-01-19 09:39:49 +01:00
|
|
|
else if (spa_streq(command, "milan_v12"))
|
|
|
|
|
res = handle_acmp_cli_cmd_milan_v12(acmp, args, out);
|
2022-03-18 15:18:11 +01:00
|
|
|
else
|
|
|
|
|
res = -ENOTSUP;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-19 09:39:49 +01:00
|
|
|
static void acmp_periodic(void *data, uint64_t now)
|
|
|
|
|
{
|
|
|
|
|
struct acmp *acmp = (struct acmp*)data;
|
|
|
|
|
|
|
|
|
|
switch (acmp->server->avb_mode) {
|
|
|
|
|
case AVB_MODE_MILAN_V12:
|
|
|
|
|
acmp_periodic_milan_v12(acmp, now);
|
|
|
|
|
break;
|
|
|
|
|
case AVB_MODE_LEGACY:
|
|
|
|
|
acmp_periodic_avb_legacy(acmp, now);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
pw_log_warn("Unknown avb_mode");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-12 11:12:15 +02:00
|
|
|
int handle_evt_tk_discovered(struct avb_acmp *avb_acmp, uint64_t entity, uint64_t now)
|
2026-01-19 09:39:49 +01:00
|
|
|
{
|
|
|
|
|
struct acmp *acmp = (struct acmp*)avb_acmp;
|
|
|
|
|
|
|
|
|
|
switch (acmp->server->avb_mode) {
|
|
|
|
|
case AVB_MODE_MILAN_V12:
|
2026-04-12 11:12:15 +02:00
|
|
|
return handle_evt_tk_discovered_milan_v12(acmp, entity, now);
|
2026-01-19 09:39:49 +01:00
|
|
|
break;
|
|
|
|
|
case AVB_MODE_LEGACY:
|
|
|
|
|
pw_log_warn("not implemented for legacy avb");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
pw_log_warn("Unknown avb_mode");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-12 11:12:15 +02:00
|
|
|
int handle_evt_tk_departed(struct avb_acmp *avb_acmp, uint64_t entity, uint64_t now)
|
2026-01-19 09:39:49 +01:00
|
|
|
{
|
|
|
|
|
struct acmp *acmp = (struct acmp*)avb_acmp;
|
|
|
|
|
|
|
|
|
|
switch (acmp->server->avb_mode) {
|
|
|
|
|
case AVB_MODE_MILAN_V12:
|
2026-04-12 11:12:15 +02:00
|
|
|
return handle_evt_tk_departed_milan_v12(acmp, entity, now);
|
2026-01-19 09:39:49 +01:00
|
|
|
break;
|
|
|
|
|
case AVB_MODE_LEGACY:
|
|
|
|
|
pw_log_warn("not implemented for legacy avb");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
pw_log_warn("Unknown avb_mode");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-12 11:12:15 +02:00
|
|
|
int handle_evt_tk_registered(struct avb_acmp *avb_acmp,
|
|
|
|
|
struct avb_msrp_attribute *msrp_attr, uint64_t now)
|
2026-01-19 09:39:49 +01:00
|
|
|
{
|
|
|
|
|
struct acmp *acmp = (struct acmp*)avb_acmp;
|
|
|
|
|
|
|
|
|
|
switch (acmp->server->avb_mode) {
|
|
|
|
|
case AVB_MODE_MILAN_V12:
|
2026-04-12 11:12:15 +02:00
|
|
|
return handle_evt_tk_registered_milan_v12(acmp, msrp_attr, now);
|
2026-01-19 09:39:49 +01:00
|
|
|
break;
|
|
|
|
|
case AVB_MODE_LEGACY:
|
|
|
|
|
pw_log_warn("not implemented for legacy avb");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
pw_log_warn("Unknown avb_mode");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-12 11:12:15 +02:00
|
|
|
int handle_evt_tk_unregistered(struct avb_acmp *avb_acmp,
|
|
|
|
|
struct avb_msrp_attribute *msrp_attr, uint64_t now)
|
2026-01-19 09:39:49 +01:00
|
|
|
{
|
|
|
|
|
struct acmp *acmp = (struct acmp*)avb_acmp;
|
|
|
|
|
|
|
|
|
|
switch (acmp->server->avb_mode) {
|
|
|
|
|
case AVB_MODE_MILAN_V12:
|
2026-04-12 11:12:15 +02:00
|
|
|
return handle_evt_tk_unregistered_milan_v12(acmp, msrp_attr, now);
|
2026-01-19 09:39:49 +01:00
|
|
|
break;
|
|
|
|
|
case AVB_MODE_LEGACY:
|
|
|
|
|
pw_log_warn("not implemented for legacy avb");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
pw_log_warn("Unknown avb_mode");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-12 13:14:58 +02:00
|
|
|
int handle_evt_tk_registration_failed(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_registration_failed_milan_v12(acmp, msrp_attr, now);
|
|
|
|
|
break;
|
|
|
|
|
case AVB_MODE_LEGACY:
|
|
|
|
|
pw_log_warn("not implemented for legacy avb");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
pw_log_warn("Unknown avb_mode");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-18 15:18:11 +01:00
|
|
|
static const struct server_events server_events = {
|
2022-03-25 10:28:18 +01:00
|
|
|
AVB_VERSION_SERVER_EVENTS,
|
2022-03-18 15:18:11 +01:00
|
|
|
.destroy = acmp_destroy,
|
|
|
|
|
.message = acmp_message,
|
2022-03-18 18:02:18 +01:00
|
|
|
.periodic = acmp_periodic,
|
2022-03-18 15:18:11 +01:00
|
|
|
.command = acmp_command
|
|
|
|
|
};
|
|
|
|
|
|
2026-01-19 09:39:49 +01:00
|
|
|
int acmp_init_listener_stream_output(struct avb_acmp *avb_acmp,
|
|
|
|
|
struct aecp_aem_stream_output_state *stream_st)
|
|
|
|
|
{
|
|
|
|
|
int rc = 0;
|
|
|
|
|
pw_log_warn("Not implemented");
|
|
|
|
|
#if 0
|
|
|
|
|
switch (acmp->server->avb_mode) {
|
|
|
|
|
case AVB_MODE_MILAN_V12:
|
|
|
|
|
rc = acmp_init_talker_stream_milan_v12(acmp, stream_st);
|
|
|
|
|
break;
|
|
|
|
|
case AVB_MODE_LEGACY:
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int acmp_init_listener_stream_input(struct avb_acmp *avb_acmp,
|
|
|
|
|
struct aecp_aem_stream_input_state *stream_st)
|
|
|
|
|
{
|
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
|
|
pw_log_warn("Not implemented");
|
|
|
|
|
#if 0
|
|
|
|
|
switch (acmp->server->avb_mode) {
|
|
|
|
|
case AVB_MODE_MILAN_V12:
|
|
|
|
|
break;
|
|
|
|
|
case AVB_MODE_LEGACY:
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int acmp_fini_stream(struct acmp *acmp, struct stream *stream)
|
|
|
|
|
{
|
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
switch (acmp->server->avb_mode) {
|
|
|
|
|
case AVB_MODE_MILAN_V12:
|
|
|
|
|
rc = acmp_fini_stream_milan_v12(acmp, stream);
|
|
|
|
|
break;
|
|
|
|
|
case AVB_MODE_LEGACY:
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-25 10:28:18 +01:00
|
|
|
struct avb_acmp *avb_acmp_register(struct server *server)
|
2022-03-18 15:18:11 +01:00
|
|
|
{
|
|
|
|
|
struct acmp *acmp;
|
|
|
|
|
|
2026-01-19 09:39:49 +01:00
|
|
|
switch (server->avb_mode) {
|
|
|
|
|
case AVB_MODE_MILAN_V12:
|
|
|
|
|
acmp = acmp_server_init_milan_v12();
|
|
|
|
|
break;
|
|
|
|
|
case AVB_MODE_LEGACY:
|
|
|
|
|
acmp = acmp_server_init_legacy_avb();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
acmp = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-18 15:18:11 +01:00
|
|
|
if (acmp == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
acmp->server = server;
|
|
|
|
|
avdecc_server_add_listener(server, &acmp->server_listener, &server_events, acmp);
|
|
|
|
|
|
2022-03-25 10:28:18 +01:00
|
|
|
return (struct avb_acmp*)acmp;
|
2022-03-18 15:18:11 +01:00
|
|
|
}
|
|
|
|
|
|
2022-03-25 10:28:18 +01:00
|
|
|
void avb_acmp_unregister(struct avb_acmp *acmp)
|
2022-03-18 15:18:11 +01:00
|
|
|
{
|
|
|
|
|
acmp_destroy(acmp);
|
|
|
|
|
}
|