mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-04-29 06:46:38 -04:00
first draft for ACMP/ timeout handling, and communication between SRP/ADP and the ACMP state machine
This commit is contained in:
parent
ad543e37f5
commit
4856f85de2
18 changed files with 2970 additions and 285 deletions
|
|
@ -13,7 +13,6 @@
|
|||
#include "internal.h"
|
||||
#include "stream.h"
|
||||
#include "aecp-aem-descriptors.h"
|
||||
#include "aecp-aem-state.h"
|
||||
|
||||
#include "acmp-cmds-resps/acmp-common.h"
|
||||
#include "acmp-cmds-resps/acmp-legacy-avb.h"
|
||||
|
|
@ -27,16 +26,35 @@ static int handle_ignore(struct acmp *acmp, uint64_t now, const void *m, int len
|
|||
}
|
||||
|
||||
static const char * const acmp_cmd_names[] = {
|
||||
[AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_COMMAND] = "connect-tx-command",
|
||||
[AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_RESPONSE] = "connect-tx-response",
|
||||
/** 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",
|
||||
|
||||
[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",
|
||||
[AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_COMMAND] = "connect-rx-command",
|
||||
[AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE] = "connect-rx-response",
|
||||
[AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_COMMAND] = "disconnect-rx-command",
|
||||
[AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE] = "disconnect-rx-response",
|
||||
|
||||
/** 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",
|
||||
|
||||
[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",
|
||||
|
|
@ -51,15 +69,32 @@ struct acmp_cmds {
|
|||
[mtype] = { .handle = handler }
|
||||
|
||||
static const struct acmp_cmds acmp_cmds_legacy_avb[] = {
|
||||
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),
|
||||
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),
|
||||
|
||||
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_TX_STATE_COMMAND, NULL),
|
||||
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),
|
||||
|
||||
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),
|
||||
|
||||
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),
|
||||
|
|
@ -68,19 +103,37 @@ static const struct acmp_cmds acmp_cmds_legacy_avb[] = {
|
|||
};
|
||||
|
||||
static const struct acmp_cmds acmp_cmds_milan_v12[] = {
|
||||
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_COMMAND, NULL),
|
||||
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_RESPONSE, NULL),
|
||||
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_COMMAND, NULL),
|
||||
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_RESPONSE, NULL),
|
||||
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_TX_STATE_COMMAND, NULL),
|
||||
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_TX_STATE_RESPONSE, NULL),
|
||||
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_COMMAND, NULL),
|
||||
|
||||
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,
|
||||
handle_unbind_rx_command_milan_v12),
|
||||
|
||||
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),
|
||||
|
||||
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE, NULL),
|
||||
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_COMMAND, NULL),
|
||||
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE, NULL),
|
||||
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_RX_STATE_COMMAND, NULL),
|
||||
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_RX_STATE_RESPONSE, NULL),
|
||||
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_COMMAND, NULL),
|
||||
|
||||
/** Milan V1.2 Section 5.5.2.2 (PDU) , Milan does not requires them */
|
||||
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_TX_STATE_COMMAND, handle_ignore),
|
||||
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),
|
||||
AVB_ACMP_CMD_HANDLER(AVB_ACMP_MESSAGE_TYPE_GET_TX_CONNECTION_RESPONSE, NULL),
|
||||
};
|
||||
|
||||
|
|
@ -115,7 +168,7 @@ static int acmp_message(void *data, uint64_t now, const void *message, int len)
|
|||
return 0;
|
||||
|
||||
if (memcmp(h->dest, mac, 6) != 0 &&
|
||||
memcmp(h->dest, server->mac_addr, 6) != 0)
|
||||
memcmp(h->dest, server->mac_addr, 6) != 0)
|
||||
return 0;
|
||||
|
||||
if (AVB_PACKET_GET_SUBTYPE(&p->hdr) != AVB_SUBTYPE_ACMP)
|
||||
|
|
@ -126,11 +179,11 @@ static int acmp_message(void *data, uint64_t now, const void *message, int len)
|
|||
pw_log_info("got ACMP message %s", acmp_cmd_names[mtype]);
|
||||
|
||||
if (mtype < 0 || (size_t)mtype >= acmp_cmds_modes[server->avb_mode].count) {
|
||||
return reply_not_supported(acmp, mtype | 1, message, len);
|
||||
return acmp_reply_not_supported(acmp, mtype | 1, message, len);
|
||||
}
|
||||
|
||||
if (acmp_cmds_modes[server->avb_mode].cmds[mtype].handle == NULL)
|
||||
return reply_not_supported(acmp, mtype | 1, message, len);
|
||||
return acmp_reply_not_supported(acmp, mtype | 1, message, len);
|
||||
|
||||
return acmp_cmds_modes[server->avb_mode].cmds[mtype].handle(acmp, now, message, len);
|
||||
}
|
||||
|
|
@ -138,41 +191,27 @@ static int acmp_message(void *data, uint64_t now, const void *message, int len)
|
|||
static void acmp_destroy(void *data)
|
||||
{
|
||||
struct acmp *acmp = data;
|
||||
spa_hook_remove(&acmp->server_listener);
|
||||
pending_destroy(acmp);
|
||||
free(acmp);
|
||||
}
|
||||
|
||||
static void check_timeout(struct acmp *acmp, uint64_t now, uint16_t type)
|
||||
{
|
||||
struct pending *p, *t;
|
||||
|
||||
spa_list_for_each_safe(p, t, &acmp->pending[type], link) {
|
||||
if (p->last_time + p->timeout > now)
|
||||
continue;
|
||||
|
||||
if (p->retry == 0) {
|
||||
pw_log_info("%p: pending timeout, retry", p);
|
||||
retry_pending(acmp, now, p);
|
||||
} else {
|
||||
pw_log_info("%p: pending timeout, fail", p);
|
||||
pending_free(acmp, p);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
spa_hook_remove(&acmp->server_listener);
|
||||
}
|
||||
static void acmp_periodic(void *data, uint64_t now)
|
||||
{
|
||||
struct acmp *acmp = data;
|
||||
check_timeout(acmp, now, PENDING_TALKER);
|
||||
check_timeout(acmp, now, PENDING_LISTENER);
|
||||
check_timeout(acmp, now, PENDING_CONTROLLER);
|
||||
}
|
||||
|
||||
|
||||
static int do_help(struct acmp *acmp, const char *args, FILE *out)
|
||||
{
|
||||
fprintf(out, "{ \"type\": \"help\","
|
||||
"\"text\": \""
|
||||
"/adp/help: this help \\n"
|
||||
" /acmp/help: this help \\n"
|
||||
"\" }");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -189,12 +228,108 @@ static int acmp_command(void *data, uint64_t now, const char *command, const cha
|
|||
|
||||
if (spa_streq(command, "help"))
|
||||
res = do_help(acmp, args, out);
|
||||
else if (spa_streq(command, "milan_v12"))
|
||||
res = handle_acmp_cli_cmd_milan_v12(acmp, args, out);
|
||||
else
|
||||
res = -ENOTSUP;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int handle_evt_tk_discovered(struct avb_acmp *avb_acmp, uint64_t entity)
|
||||
{
|
||||
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);
|
||||
break;
|
||||
case AVB_MODE_LEGACY:
|
||||
pw_log_warn("not implemented for legacy avb");
|
||||
break;
|
||||
default:
|
||||
pw_log_warn("Unknown avb_mode");
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int handle_evt_tk_departed(struct avb_acmp *avb_acmp, uint64_t entity)
|
||||
{
|
||||
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);
|
||||
break;
|
||||
case AVB_MODE_LEGACY:
|
||||
pw_log_warn("not implemented for legacy avb");
|
||||
break;
|
||||
default:
|
||||
pw_log_warn("Unknown avb_mode");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_evt_tk_registered(struct avb_acmp *avb_acmp, uint64_t entity)
|
||||
{
|
||||
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);
|
||||
break;
|
||||
case AVB_MODE_LEGACY:
|
||||
pw_log_warn("not implemented for legacy avb");
|
||||
break;
|
||||
default:
|
||||
pw_log_warn("Unknown avb_mode");
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int handle_evt_tk_unregistered(struct avb_acmp *avb_acmp, uint64_t entity)
|
||||
{
|
||||
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);
|
||||
break;
|
||||
case AVB_MODE_LEGACY:
|
||||
pw_log_warn("not implemented for legacy avb");
|
||||
break;
|
||||
default:
|
||||
pw_log_warn("Unknown avb_mode");
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const struct server_events server_events = {
|
||||
AVB_VERSION_SERVER_EVENTS,
|
||||
.destroy = acmp_destroy,
|
||||
|
|
@ -203,19 +338,81 @@ static const struct server_events server_events = {
|
|||
.command = acmp_command
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
struct avb_acmp *avb_acmp_register(struct server *server)
|
||||
{
|
||||
struct acmp *acmp;
|
||||
|
||||
acmp = calloc(1, sizeof(*acmp));
|
||||
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;
|
||||
}
|
||||
|
||||
if (acmp == NULL)
|
||||
return NULL;
|
||||
|
||||
acmp->server = server;
|
||||
spa_list_init(&acmp->pending[PENDING_TALKER]);
|
||||
spa_list_init(&acmp->pending[PENDING_LISTENER]);
|
||||
spa_list_init(&acmp->pending[PENDING_CONTROLLER]);
|
||||
|
||||
avdecc_server_add_listener(server, &acmp->server_listener, &server_events, acmp);
|
||||
|
||||
return (struct avb_acmp*)acmp;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue