milan-avb: aecp-vendor-unique-milan-v12: dispatch via per-cmd table per Milan v1.2 Section 5.4.4

This commit is contained in:
hackerman-kl 2026-04-26 21:04:21 +02:00 committed by Wim Taymans
parent deeea620f6
commit a16f3d704e
8 changed files with 217 additions and 108 deletions

View file

@ -0,0 +1,84 @@
/* SPDX-FileCopyrightText: Copyright © 2025 Alexandre Malki <alexandre.malki@kebag-logic.com> */
/* SPDX-License-Identifier: MIT */
#include <errno.h>
#include <string.h>
#include <arpa/inet.h>
#include <pipewire/pipewire.h>
#include <spa/utils/defs.h>
#include "../aecp.h"
#include "../aecp-vendor-unique-milan-v12.h"
#include "../internal.h"
#include "cmd-get-milan-info.h"
#include "cmd-resp-helpers.h"
/* Milan v1.2 Section 5.4.4.1 GET_MILAN_INFO Response payload. */
struct avb_packet_aecp_mvu_get_milan_info_rsp {
uint32_t protocol_version;
uint32_t features_flags;
uint32_t certification_version;
} __attribute__ ((__packed__));
/* Milan v1.2 Section 5.4.4.1: protocol_version is 1 across every Milan release. */
#define MILAN_MVU_PROTOCOL_VERSION 0x00000001u
/* Milan v1.2 Section 5.4.4.1 Table 5.20: features_flags bit 0 = REDUNDANCY (not
* implemented), upper bits reserved. */
#define MILAN_MVU_FEATURES_FLAGS 0x00000000u
/* Milan v1.2 Section 5.4.4.1: certification_version byte-encoded
* major.minor.revision.build. Milan v1.2 = 0x01020000. */
#define MILAN_MVU_CERTIFICATION_VERSION 0x01020000u
int handle_cmd_mvu_get_milan_info_milan_v12(struct aecp *aecp, int64_t now,
const void *m, int len)
{
struct server *server = aecp->server;
uint8_t buf[2048];
struct avb_ethernet_header *h_reply;
struct avb_packet_aecp_header *aecp_hdr;
struct avb_packet_aecp_vendor_unique *vu_reply;
struct avb_packet_aecp_mvu_get_milan_info_rsp *body;
int total = (int)(sizeof(struct avb_ethernet_header) +
sizeof(struct avb_packet_aecp_vendor_unique) +
sizeof(struct avb_packet_aecp_mvu_get_milan_info_rsp));
int wire = total < 60 ? 60 : total;
(void)now;
if (wire > (int)sizeof(buf))
return -EMSGSIZE;
memcpy(buf, m, len);
if (len < wire)
memset(buf + len, 0, wire - len);
h_reply = (struct avb_ethernet_header *)buf;
aecp_hdr = SPA_PTROFF(h_reply, sizeof(*h_reply), void);
vu_reply = (struct avb_packet_aecp_vendor_unique *)aecp_hdr;
AVB_PACKET_AECP_SET_MESSAGE_TYPE(aecp_hdr,
AVB_AECP_MESSAGE_TYPE_VENDOR_UNIQUE_RESPONSE);
AVB_PACKET_AECP_SET_STATUS(aecp_hdr, AVB_AECP_STATUS_SUCCESS);
/* IEEE 1722-2011 Section 5.3 / IEEE 1722.1-2021 Section 9.2.1.1.7: CDL excludes
* the 12-octet AVTPDU common header. */
AVB_PACKET_SET_LENGTH(&aecp_hdr->hdr,
(uint16_t)(total - sizeof(struct avb_ethernet_header) -
sizeof(struct avb_packet_header) -
sizeof(uint64_t)));
((uint8_t *)&vu_reply->command_type)[0] &= 0x7f;
vu_reply->reserved = 0;
body = (struct avb_packet_aecp_mvu_get_milan_info_rsp *)vu_reply->payload;
body->protocol_version = htonl(MILAN_MVU_PROTOCOL_VERSION);
body->features_flags = htonl(MILAN_MVU_FEATURES_FLAGS);
body->certification_version = htonl(MILAN_MVU_CERTIFICATION_VERSION);
return avb_server_send_packet(server, h_reply->src, AVB_TSN_ETH,
buf, wire);
}

View file

@ -0,0 +1,12 @@
/* SPDX-FileCopyrightText: Copyright © 2025 Alexandre Malki <alexandre.malki@kebag-logic.com> */
/* SPDX-License-Identifier: MIT */
#ifndef __AVB_AECP_MVU_CMD_GET_MILAN_INFO_H__
#define __AVB_AECP_MVU_CMD_GET_MILAN_INFO_H__
#include "../aecp-vendor-unique-milan-v12.h"
int handle_cmd_mvu_get_milan_info_milan_v12(struct aecp *aecp, int64_t now,
const void *m, int len);
#endif /* __AVB_AECP_MVU_CMD_GET_MILAN_INFO_H__ */

View file

@ -0,0 +1,69 @@
/* SPDX-FileCopyrightText: Copyright © 2025 Alexandre Malki <alexandre.malki@kebag-logic.com> */
/* SPDX-License-Identifier: MIT */
#ifndef __AVB_AECP_MVU_HELPERS_H__
#define __AVB_AECP_MVU_HELPERS_H__
#include <errno.h>
#include <stdint.h>
#include <string.h>
#include <spa/utils/defs.h>
#include <pipewire/log.h>
#include "../aecp.h"
#include "../aecp-vendor-unique-milan-v12.h"
#include "../internal.h"
/* Milan v1.2 Section 5.4.3.2.2: r bit is reserved (must be 0) in commands and
* responses. Command vs response is signalled by AECP message_type. */
static inline int reply_mvu_status(struct aecp *aecp, int status,
const void *m, int len)
{
uint8_t buf[2048];
struct server *server = aecp->server;
struct avb_ethernet_header *h = (void *)buf;
struct avb_packet_aecp_header *reply = SPA_PTROFF(h, sizeof(*h), void);
struct avb_packet_aecp_vendor_unique *vu_reply;
int wire = len < 60 ? 60 : len;
if (len < 0 || (size_t)wire > sizeof(buf)) {
pw_log_warn("reply_mvu_status: invalid len %d", len);
return -EINVAL;
}
memcpy(buf, m, len);
if (wire > len)
memset(buf + len, 0, wire - len);
AVB_PACKET_AECP_SET_MESSAGE_TYPE(reply,
AVB_AECP_MESSAGE_TYPE_VENDOR_UNIQUE_RESPONSE);
AVB_PACKET_AECP_SET_STATUS(reply, status);
if ((size_t)wire >= sizeof(*h) + sizeof(*vu_reply)) {
vu_reply = SPA_PTROFF(h, sizeof(*h), void);
((uint8_t *)&vu_reply->command_type)[0] &= 0x7f;
}
return avb_server_send_packet(server, h->src, AVB_TSN_ETH, buf, wire);
}
static inline int reply_mvu_not_implemented(struct aecp *aecp,
const void *m, int len)
{
return reply_mvu_status(aecp, AVB_AECP_STATUS_NOT_IMPLEMENTED, m, len);
}
static inline int direct_reply_mvu_not_implemented(struct aecp *aecp,
int64_t now, const void *m, int len)
{
(void)now;
return reply_mvu_not_implemented(aecp, m, len);
}
static inline int reply_mvu_success(struct aecp *aecp,
const void *m, int len)
{
return reply_mvu_status(aecp, AVB_AECP_STATUS_SUCCESS, m, len);
}
#endif /* __AVB_AECP_MVU_HELPERS_H__ */