milan-avb: move teh descriptor FAM at the end of the structure to avoid overflow

This commit is contained in:
hackerman-kl 2026-04-26 13:03:10 +02:00 committed by Wim Taymans
parent 4d33f57325
commit 0bf4864d84
14 changed files with 126 additions and 204 deletions

View file

@ -2197,18 +2197,20 @@ int handle_evt_tk_registration_failed_milan_v12(struct acmp *acmp,
}
static bool stream_output_on_this_iface(struct server *server,
struct aecp_aem_stream_output_state *stream_out)
struct descriptor *stream_out_desc)
{
struct descriptor *avb_if_desc;
struct aecp_aem_avb_interface_state *avb_if_state;
uint16_t avb_if_index = ntohs(stream_out->desc.avb_interface_index);
const struct avb_aem_desc_stream *stream_body = descriptor_body(stream_out_desc);
const struct avb_aem_desc_avb_interface *avb_if_body;
uint16_t avb_if_index = ntohs(stream_body->avb_interface_index);
avb_if_desc = server_find_descriptor(server, AVB_AEM_DESC_AVB_INTERFACE, avb_if_index);
if (avb_if_desc == NULL)
if (avb_if_desc == NULL) {
return false;
}
avb_if_state = avb_if_desc->ptr;
return memcmp(avb_if_state->desc.mac_address, server->mac_addr,
avb_if_body = descriptor_body(avb_if_desc);
return memcmp(avb_if_body->mac_address, server->mac_addr,
sizeof(server->mac_addr)) == 0;
}
@ -2241,7 +2243,7 @@ int handle_probe_tx_command_milan_v12(struct acmp *acmp, uint64_t now,
stream_out = desc->ptr;
if (!stream_output_on_this_iface(server, stream_out)) {
if (!stream_output_on_this_iface(server, desc)) {
status = AVB_ACMP_STATUS_INCOMPATIBLE_REQUEST;
goto done;
}
@ -2282,7 +2284,6 @@ int handle_disconnect_tx_command_milan_v12(struct acmp *acmp, uint64_t now,
struct avb_ethernet_header *h_reply = (struct avb_ethernet_header *)buf;
struct avb_packet_acmp *reply = SPA_PTROFF(h_reply, sizeof(*h_reply), void);
struct descriptor *desc;
struct aecp_aem_stream_output_state *stream_out;
int status = AVB_ACMP_STATUS_SUCCESS;
if (be64toh(p->talker_guid) != server->entity_id)
@ -2298,9 +2299,9 @@ int handle_disconnect_tx_command_milan_v12(struct acmp *acmp, uint64_t now,
goto done;
}
stream_out = desc->ptr;
if (!stream_output_on_this_iface(server, stream_out))
if (!stream_output_on_this_iface(server, desc)) {
return 0;
}
reply->stream_id = 0;
memset(reply->stream_dest_mac, 0, sizeof(reply->stream_dest_mac));
@ -2341,8 +2342,9 @@ int handle_get_tx_state_command_milan_v12(struct acmp *acmp, uint64_t now,
stream_out = desc->ptr;
if (!stream_output_on_this_iface(server, stream_out))
if (!stream_output_on_this_iface(server, desc)) {
return 0;
}
reply->stream_id = stream_out->common.tastream_attr.attr.talker.stream_id;
memcpy(reply->stream_dest_mac, stream_out->common.stream.addr,

View file

@ -280,7 +280,7 @@ static int check_advertise(struct adp *adp, uint64_t now)
if (d == NULL)
return -1;
entity = d->ptr;
entity = descriptor_body(d);
entity_id = be64toh(entity->entity_id);
if ((e = find_entity_by_id(adp, entity_id)) != NULL) {
@ -290,7 +290,7 @@ static int check_advertise(struct adp *adp, uint64_t now)
}
d = server_find_descriptor(server, AVB_AEM_DESC_AVB_INTERFACE, 0);
avb_interface = d ? d->ptr : NULL;
avb_interface = d ? descriptor_body(d) : NULL;
pw_log_info("entity %s advertise",
avb_utils_format_id(buf, sizeof(buf), entity_id));

View file

@ -53,7 +53,7 @@ int handle_cmd_get_dynamic_info_milan_v12(struct aecp *aecp, int64_t now,
if (entity_desc == NULL)
return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len);
entity = (const struct avb_aem_desc_entity *)entity_desc->ptr;
entity = (const struct avb_aem_desc_entity *)descriptor_body(entity_desc);
if (config_idx >= ntohs(entity->configurations_count))
return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len);
@ -76,7 +76,7 @@ int handle_cmd_get_dynamic_info_milan_v12(struct aecp *aecp, int64_t now,
switch (d->type) {
case AVB_AEM_DESC_ENTITY: {
const struct avb_aem_desc_entity *e =
(const struct avb_aem_desc_entity *)d->ptr;
(const struct avb_aem_desc_entity *)descriptor_body(d);
struct avb_aem_dynamic_info_entity rec;
if (size + sizeof(rec) > sizeof(buf)) {
@ -95,7 +95,7 @@ int handle_cmd_get_dynamic_info_milan_v12(struct aecp *aecp, int64_t now,
}
case AVB_AEM_DESC_AUDIO_UNIT: {
const struct avb_aem_desc_audio_unit *au =
(const struct avb_aem_desc_audio_unit *)d->ptr;
(const struct avb_aem_desc_audio_unit *)descriptor_body(d);
struct avb_aem_dynamic_info_audio_unit rec;
if (size + sizeof(rec) > sizeof(buf)) {
@ -112,8 +112,8 @@ int handle_cmd_get_dynamic_info_milan_v12(struct aecp *aecp, int64_t now,
break;
}
case AVB_AEM_DESC_STREAM_INPUT: {
const struct aecp_aem_stream_input_state *state =
(const struct aecp_aem_stream_input_state *)d->ptr;
const struct avb_aem_desc_stream *body =
(const struct avb_aem_desc_stream *)descriptor_body(d);
struct avb_aem_dynamic_info_stream rec;
if (size + sizeof(rec) > sizeof(buf)) {
@ -124,10 +124,11 @@ int handle_cmd_get_dynamic_info_milan_v12(struct aecp *aecp, int64_t now,
rec.hdr.descriptor_type = htons(d->type);
rec.hdr.descriptor_index = htons(d->index);
rec.stream_id = 0;
rec.stream_format = state->desc.current_format;
if (state->desc.current_format != 0)
rec.stream_format = body->current_format;
if (body->current_format != 0) {
rec.stream_info_flags =
htonl(AVB_AEM_STREAM_INFO_FLAG_STREAM_FORMAT_VALID);
}
memcpy(ptr, &rec, sizeof(rec));
ptr += sizeof(rec);
psize += sizeof(rec);
@ -135,8 +136,8 @@ int handle_cmd_get_dynamic_info_milan_v12(struct aecp *aecp, int64_t now,
break;
}
case AVB_AEM_DESC_STREAM_OUTPUT: {
const struct aecp_aem_stream_output_state *state =
(const struct aecp_aem_stream_output_state *)d->ptr;
const struct avb_aem_desc_stream *body =
(const struct avb_aem_desc_stream *)descriptor_body(d);
struct avb_aem_dynamic_info_stream rec;
if (size + sizeof(rec) > sizeof(buf)) {
@ -147,10 +148,11 @@ int handle_cmd_get_dynamic_info_milan_v12(struct aecp *aecp, int64_t now,
rec.hdr.descriptor_type = htons(d->type);
rec.hdr.descriptor_index = htons(d->index);
rec.stream_id = 0;
rec.stream_format = state->desc.current_format;
if (state->desc.current_format != 0)
rec.stream_format = body->current_format;
if (body->current_format != 0) {
rec.stream_info_flags =
htonl(AVB_AEM_STREAM_INFO_FLAG_STREAM_FORMAT_VALID);
}
memcpy(ptr, &rec, sizeof(rec));
ptr += sizeof(rec);
psize += sizeof(rec);
@ -159,7 +161,7 @@ int handle_cmd_get_dynamic_info_milan_v12(struct aecp *aecp, int64_t now,
}
case AVB_AEM_DESC_CLOCK_DOMAIN: {
const struct avb_aem_desc_clock_domain *cd =
(const struct avb_aem_desc_clock_domain *)d->ptr;
(const struct avb_aem_desc_clock_domain *)descriptor_body(d);
struct avb_aem_dynamic_info_clock_domain rec;
if (size + sizeof(rec) > sizeof(buf)) {

View file

@ -89,7 +89,7 @@ int handle_cmd_get_clock_source_milan_v12(struct aecp *aecp, int64_t now,
return reply_status(aecp,
AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len);
dclk_domain = (struct avb_aem_desc_clock_domain*) desc->ptr;
dclk_domain = (struct avb_aem_desc_clock_domain*) descriptor_body(desc);
/** Descriptors always keep the network endianness */
sclk_source->clock_source_index = dclk_domain->clock_source_index;
@ -134,7 +134,7 @@ int handle_cmd_set_clock_source_milan_v12(struct aecp *aecp, int64_t now,
return reply_status(aecp,
AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len);
dclk_domain = (struct avb_aem_desc_clock_domain *) desc->ptr;
dclk_domain = (struct avb_aem_desc_clock_domain *) descriptor_body(desc);
if (clock_src_index >= dclk_domain->clock_sources_count) {
return reply_invalid_clock_source(aecp, dclk_domain, m, len);
}

View file

@ -25,7 +25,7 @@ static int handle_unsol_set_configuration_milan_v12(struct aecp *aecp, struct de
int rc;
memset(buf, 0, sizeof(buf));
entity_desc = (struct avb_aem_desc_entity*) desc->ptr;
entity_desc = (struct avb_aem_desc_entity*) descriptor_body(desc);
cfg = (struct avb_packet_aecp_aem_setget_configuration *) p->payload;
cfg->configuration_index = htons(entity_desc->current_configuration);
p->aecp.target_guid = htobe64(aecp->server->entity_id);
@ -97,7 +97,7 @@ int handle_cmd_set_configuration_milan_v12(struct aecp *aecp, int64_t now,
p_reply = SPA_PTROFF(h_reply, sizeof(*h_reply), void);
cfg = (struct avb_packet_aecp_aem_setget_configuration*) p_reply->payload;
entity_desc = (struct avb_aem_desc_entity*) desc->ptr;
entity_desc = (struct avb_aem_desc_entity*) descriptor_body(desc);
cur_cfg_id = ntohs(entity_desc->current_configuration);
req_cfg_id = ntohs(cfg->configuration_index);
cfg_count = ntohs(entity_desc->configurations_count);
@ -182,7 +182,7 @@ int handle_cmd_get_configuration_common(struct aecp *aecp, int64_t now,
p_reply = SPA_PTROFF(h_reply, sizeof(*h_reply), void);
cfg = (struct avb_packet_aecp_aem_setget_configuration*) p_reply->payload;
entity_desc = (struct avb_aem_desc_entity*) desc->ptr;
entity_desc = (struct avb_aem_desc_entity*) descriptor_body(desc);
if (entity_desc->entity_id != p->aecp.target_guid) {
pw_log_error("Invalid entity id");

View file

@ -109,7 +109,7 @@ static int handle_cmd_get_control_identify(struct aecp *aecp, struct descriptor
struct avb_packet_aecp_aem_setget_control *ae_reply;
int pkt_size;
ctrl_desc = desc->ptr;
ctrl_desc = descriptor_body(desc);
desc_formats = ctrl_desc->value_format;
if (len < 0 || (size_t)len > sizeof(buf))
@ -145,7 +145,7 @@ static int handle_cmd_set_control_identify(struct aecp *aecp, struct descriptor
int rc;
control = (struct avb_packet_aecp_aem_setget_control*)p->payload;
ctrl_desc = desc->ptr;
ctrl_desc = descriptor_body(desc);
desc_formats = ctrl_desc->value_format;
old_value_format = desc_formats;
value_req = (uint8_t *)control->payload;
@ -265,7 +265,7 @@ int handle_cmd_set_control_milan_v12(struct aecp *aecp, int64_t now,
return reply_status(aecp,
AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len);
ctrl_desc = desc->ptr;
ctrl_desc = descriptor_body(desc);
control_type = htobe64(ctrl_desc->control_type);
setter_cb = get_ctrl_setter_common(controls_handlers,
SPA_N_ELEMENTS(controls_handlers), control_type);
@ -307,7 +307,7 @@ int handle_cmd_get_control_milan_v12(struct aecp *aecp, int64_t now,
return reply_status(aecp,
AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len);
ctrl_desc = desc->ptr;
ctrl_desc = descriptor_body(desc);
control_type = htobe64(ctrl_desc->control_type);
getter_cb = get_ctrl_getter_common(controls_handlers,
SPA_N_ELEMENTS(controls_handlers), control_type);

View file

@ -119,7 +119,7 @@ int handle_cmd_get_name_common(struct aecp *aecp, int64_t now,
return reply_status(aecp,
AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len);
name_ptr = get_name_ptr(desc_type, desc->ptr, name_index);
name_ptr = get_name_ptr(desc_type, descriptor_body(desc), name_index);
if (name_ptr == NULL)
return reply_status(aecp,
AVB_AECP_AEM_STATUS_BAD_ARGUMENTS, m, len);
@ -169,7 +169,7 @@ int handle_cmd_set_name_common(struct aecp *aecp, int64_t now,
return reply_status(aecp,
AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len);
name_ptr = get_name_ptr(desc_type, desc->ptr, name_index);
name_ptr = get_name_ptr(desc_type, descriptor_body(desc), name_index);
if (name_ptr == NULL)
return reply_status(aecp,
AVB_AECP_AEM_STATUS_BAD_ARGUMENTS, m, len);

View file

@ -155,7 +155,7 @@ int handle_cmd_set_sampling_rate_milan_v12(struct aecp *aecp, int64_t now,
AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len);
if (desc_type == AVB_AEM_DESC_AUDIO_UNIT) {
struct avb_aem_desc_audio_unit *unit = desc->ptr;
struct avb_aem_desc_audio_unit *unit = descriptor_body(desc);
/* TODO check if the STREAM_PORT associated with it supportes
* the SSRC/ASRC bit.
*/
@ -218,7 +218,7 @@ int handle_cmd_get_sampling_rate_common(struct aecp *aecp, int64_t now,
AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len);
if (desc_type == AVB_AEM_DESC_AUDIO_UNIT) {
struct avb_aem_desc_audio_unit *unit = desc->ptr;
struct avb_aem_desc_audio_unit *unit = descriptor_body(desc);
memcpy(&pullfreq, &unit->current_sampling_rate, sizeof(pullfreq));
} else {
return reply_status(aecp,

View file

@ -62,7 +62,7 @@ int handle_cmd_get_stream_format_milan_v12(struct aecp *aecp, int64_t now,
return reply_status(aecp,
AVB_AECP_AEM_STATUS_BAD_ARGUMENTS, m, len);
stream_desc = (struct avb_aem_desc_stream *)desc->ptr;
stream_desc = (struct avb_aem_desc_stream *)descriptor_body(desc);
if (len < 0 || (size_t)len > sizeof(buf))
return reply_status(aecp,
@ -120,7 +120,7 @@ int handle_cmd_set_stream_format_milan_v12(struct aecp *aecp, int64_t now,
AVB_AECP_AEM_STATUS_BAD_ARGUMENTS, m, len);
}
stream_desc = (struct avb_aem_desc_stream *)desc->ptr;
stream_desc = (struct avb_aem_desc_stream *)descriptor_body(desc);
for (i = 0; i < ntohs(stream_desc->number_of_formats); i++) {
if (stream_desc->stream_formats[i] == new_format) {
found = true;

View file

@ -92,9 +92,11 @@ static int build_stream_info_response(struct aecp *aecp, const void *m, int len,
}
static void populate_input_response(struct aecp *aecp,
struct aecp_aem_stream_input_state_milan_v12 *si,
struct descriptor *desc,
struct avb_packet_aecp_aem_setget_stream_info *reply)
{
struct aecp_aem_stream_input_state_milan_v12 *si = desc->ptr;
const struct avb_aem_desc_stream *stream_body = descriptor_body(desc);
struct stream_common *sc = &si->stream_in_sta.common;
struct avb_msrp_attribute *lattr = &sc->lstream_attr;
struct avb_msrp_attribute *taattr = &sc->tastream_attr;
@ -111,7 +113,7 @@ static void populate_input_response(struct aecp *aecp,
bool bound, settled, ta_observed, tf_observed, registering;
(void)aecp;
stream_format_be = si->stream_in_sta.desc.current_format;
stream_format_be = stream_body->current_format;
/* Milan Section 5.3.8.2: bound iff the listener has a saved talker stream id. */
bound = (lattr->attr.listener.stream_id != 0);
@ -194,7 +196,7 @@ static void populate_input_response(struct aecp *aecp,
}
static int handle_get_stream_input(struct aecp *aecp, const void *m, int len,
struct aecp_aem_stream_input_state_milan_v12 *si)
struct descriptor *desc)
{
uint8_t buf[2048];
struct avb_ethernet_header *h_reply;
@ -207,15 +209,17 @@ static int handle_get_stream_input(struct aecp *aecp, const void *m, int len,
p_reply = SPA_PTROFF(h_reply, sizeof(*h_reply), void);
reply = (struct avb_packet_aecp_aem_setget_stream_info *)p_reply->payload;
populate_input_response(aecp, si, reply);
populate_input_response(aecp, desc, reply);
return reply_success(aecp, buf, AVB_AECP_GET_STREAM_INFO_RESPONSE_LEN);
}
static void populate_output_response(struct aecp *aecp, uint16_t desc_index,
struct aecp_aem_stream_output_state *so,
struct descriptor *desc,
struct avb_packet_aecp_aem_setget_stream_info *reply)
{
struct aecp_aem_stream_output_state *so = desc->ptr;
const struct avb_aem_desc_stream *stream_body = descriptor_body(desc);
struct stream_common *sc = &so->common;
struct avb_msrp_attribute *taattr = &sc->tastream_attr;
const uint8_t zero_mac[6] = {0};
@ -275,21 +279,21 @@ static void populate_output_response(struct aecp *aecp, uint16_t desc_index,
build_stream_info_response(aecp, NULL, 0, reply,
flags_host, flags_ex_host,
0, 0,
so->desc.current_format, stream_id_be,
stream_body->current_format, stream_id_be,
so->presentation_time_offset_ns, dest_mac,
0, 0, vlan_id_host);
pw_log_debug("populate STREAM_OUTPUT stream_format=0x%016" PRIx64
" flags=0x%08x flags_ex=0x%08x pres_time_off=%u "
"stream_id=0x%016" PRIx64,
be64toh(so->desc.current_format),
be64toh(stream_body->current_format),
flags_host, flags_ex_host,
so->presentation_time_offset_ns,
be64toh(stream_id_be));
}
static int handle_get_stream_output(struct aecp *aecp, const void *m, int len,
uint16_t desc_index, struct aecp_aem_stream_output_state *so)
uint16_t desc_index, struct descriptor *desc)
{
uint8_t buf[2048];
struct avb_ethernet_header *h_reply;
@ -302,7 +306,7 @@ static int handle_get_stream_output(struct aecp *aecp, const void *m, int len,
p_reply = SPA_PTROFF(h_reply, sizeof(*h_reply), void);
reply = (struct avb_packet_aecp_aem_setget_stream_info *)p_reply->payload;
populate_output_response(aecp, desc_index, so, reply);
populate_output_response(aecp, desc_index, desc, reply);
return reply_success(aecp, buf, AVB_AECP_GET_STREAM_INFO_RESPONSE_LEN);
}
@ -324,12 +328,12 @@ int handle_cmd_get_stream_info_milan_v12(struct aecp *aecp, int64_t now,
if (desc == NULL)
return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len);
if (desc_type == AVB_AEM_DESC_STREAM_INPUT)
return handle_get_stream_input(aecp, m, len,
(struct aecp_aem_stream_input_state_milan_v12 *)desc->ptr);
if (desc_type == AVB_AEM_DESC_STREAM_OUTPUT)
return handle_get_stream_output(aecp, m, len, desc_index,
(struct aecp_aem_stream_output_state *)desc->ptr);
if (desc_type == AVB_AEM_DESC_STREAM_INPUT) {
return handle_get_stream_input(aecp, m, len, desc);
}
if (desc_type == AVB_AEM_DESC_STREAM_OUTPUT) {
return handle_get_stream_output(aecp, m, len, desc_index, desc);
}
return reply_status(aecp, AVB_AECP_AEM_STATUS_BAD_ARGUMENTS, m, len);
}
@ -438,14 +442,11 @@ void cmd_get_stream_info_emit_unsol_milan_v12(struct server *server,
body->descriptor_type = htons(desc_type);
body->descriptor_index = htons(desc_index);
if (desc_type == AVB_AEM_DESC_STREAM_INPUT)
populate_input_response(aecp,
(struct aecp_aem_stream_input_state_milan_v12 *)desc->ptr,
body);
else
populate_output_response(aecp, desc_index,
(struct aecp_aem_stream_output_state *)desc->ptr,
body);
if (desc_type == AVB_AEM_DESC_STREAM_INPUT) {
populate_input_response(aecp, desc, body);
} else {
populate_output_response(aecp, desc_index, desc, body);
}
(void)reply_unsolicited_notifications(aecp, &b_state, buf,
AVB_AECP_GET_STREAM_INFO_RESPONSE_LEN, true);

View file

@ -92,8 +92,6 @@ struct aecp_aem_avb_interface_counters {
};
struct aecp_aem_avb_interface_state {
struct avb_aem_desc_avb_interface desc;
struct avb_msrp_attribute domain_attr;
struct avb_mvrp_attribute vlan_attr;
@ -113,7 +111,6 @@ struct aecp_aem_avb_interface_state {
* \brief the generic entity state common for all flavor of AVB
*/
struct aecp_aem_entity_state {
struct avb_aem_desc_entity desc;
struct aecp_aem_lock_state lock_state;
};
@ -160,12 +157,7 @@ struct stream_common {
struct avb_msrp_attribute tfstream_attr;
};
#define AVB_AEM_STREAM_DESC_EXTRA_SIZE 128
struct aecp_aem_stream_input_state {
struct avb_aem_desc_stream desc;
uint8_t desc_extra[AVB_AEM_STREAM_DESC_EXTRA_SIZE];
struct aecp_aem_stream_input_counters counters;
struct stream_common common;
struct avb_mvrp_attribute mvrp_attr;
@ -210,9 +202,6 @@ struct aecp_aem_stream_output_counters {
};
struct aecp_aem_stream_output_state {
struct avb_aem_desc_stream desc;
uint8_t desc_extra[AVB_AEM_STREAM_DESC_EXTRA_SIZE];
struct aecp_aem_stream_output_counters counters;
struct stream_common common;

View file

@ -115,7 +115,7 @@ static int handle_read_descriptor_common(struct aecp *aecp, int64_t now, const v
memcpy(buf, m, len);
memcpy(buf + size, desc->ptr, desc->size);
memcpy(buf + size, descriptor_body(desc), desc->size);
size += desc->size;
psize += desc->size;
@ -158,7 +158,7 @@ static int handle_get_avb_info_common(struct aecp *aecp, int64_t now,
if (len < 0 || (size_t)len > sizeof(buf))
return reply_status(aecp, AVB_AECP_AEM_STATUS_BAD_ARGUMENTS, m, len);
avb_interface = desc->ptr;
avb_interface = descriptor_body(desc);
memcpy(buf, m, len);

View file

@ -7,121 +7,63 @@
#include "aecp-aem-state.h"
#include "utils.h"
/**
* \brief The goal of this modules is to create a an entity and
* attache the necessary status or resources to it so they
* do no have to be seperated and referenced somewhere else.
*
* In a sense, it encapsulates the descriptor, and the states
* information that will be altered either by a aecp/acmp commands
* or internal state changes reflected into the counters.
*/
/** The callback type used for the different entity descriptor */
typedef struct descriptor *(*es_builder_cb_t) (struct server *server, uint16_t type,
uint16_t index, size_t size, void *ptr);
uint16_t index, size_t size, const void *ptr);
/** Structure holding all necessary cb
* \todo for the future of compatibility between milan's version
* and plain AVB, add the right callback, that would reduce
* code complexity and increase reusability.
* As well as having multiple entity model defined using different
* entity on the same machine
*/
struct es_builder_st {
es_builder_cb_t build_descriptor_cb;
};
/*
* \brief The Entity keeps track of multiple things, the locks the current
* configuration use for instance. That tragets the Milan V1.2 mode only
*/
static struct descriptor *es_builder_desc_entity_milan_v12(struct server *server,
uint16_t type, uint16_t index, size_t size, void *ptr)
uint16_t type, uint16_t index, size_t size, const void *ptr)
{
struct aecp_aem_entity_milan_state entity_state = {0};
struct descriptor *desc;
struct aecp_aem_entity_state *state =
(struct aecp_aem_entity_state *) &entity_state;
memcpy(&state->desc, ptr, size);
desc = server_add_descriptor(server, type, index, sizeof(entity_state),
&entity_state);
if (!desc) {
pw_log_error("Error during allocation\n");
spa_assert(0);
}
return desc;
return server_add_descriptor(server, type, index,
sizeof(struct aecp_aem_entity_milan_state), size, ptr);
}
/**
* \brief A generic function to avoid code duplicate for the streams */
static struct descriptor *es_buidler_desc_stream_general_prepare(struct server *server,
uint16_t type, uint16_t index, size_t size, void *ptr)
uint16_t type, uint16_t index, size_t size, const void *ptr)
{
struct descriptor *desc;
struct stream *stream;
enum spa_direction direction;
switch (type) {
case AVB_AEM_DESC_STREAM_INPUT:
struct aecp_aem_stream_input_state *pstream_input;
/* Milan v1.2 ACMP code casts the descriptor pointer to
* struct aecp_aem_stream_input_state_milan_v12 * and reads
* acmp_sta, which sits *after* the bare stream input state.
* Allocate the wrapper size so that read/write of acmp_sta is
* within the descriptor buffer. The bare struct is the prefix
* of the wrapper, so existing direct-access paths remain valid. */
struct aecp_aem_stream_input_state_milan_v12 stream_input_w = { 0 };
struct aecp_aem_stream_input_state *stream_input = &stream_input_w.stream_in_sta;
if (type == AVB_AEM_DESC_STREAM_INPUT) {
struct aecp_aem_stream_input_state_milan_v12 *w;
memcpy(&stream_input->desc, ptr, size);
desc = server_add_descriptor(server, type, index,
sizeof(*w), size, ptr);
if (!desc) {
pw_log_error("Allocation failed\n");
return NULL;
}
w = desc->ptr;
/* Milan v1.2 Section 5.3.8.7: started/stopped state defaults to started. */
stream_input->started = true;
desc = server_add_descriptor(server, type, index,
sizeof(stream_input_w), &stream_input_w);
if (!desc) {
pw_log_error("Allocation failed\n");
return NULL;
}
pstream_input = desc->ptr;
stream = &pstream_input->common.stream;
w->stream_in_sta.started = true;
stream = &w->stream_in_sta.common.stream;
direction = SPA_DIRECTION_INPUT;
} else if (type == AVB_AEM_DESC_STREAM_OUTPUT) {
struct aecp_aem_stream_output_state_milan_v12 *w;
break;
case AVB_AEM_DESC_STREAM_OUTPUT:
struct aecp_aem_stream_output_state *pstream_output;
struct aecp_aem_stream_output_state_milan_v12 stream_output_w = { 0 };
struct aecp_aem_stream_output_state *stream_output = &stream_output_w.stream_out_sta;
memcpy(&stream_output->desc, ptr, size);
/* Milan v1.2 Section 5.3.7.6: default presentation time offset is 2 ms. */
stream_output->presentation_time_offset_ns = 2000000;
desc = server_add_descriptor(server, type, index,
sizeof(stream_output_w), &stream_output_w);
sizeof(*w), size, ptr);
if (!desc) {
pw_log_error("Allocation failed\n");
return NULL;
}
pstream_output = desc->ptr;
stream = &pstream_output->common.stream;
w = desc->ptr;
/* Milan v1.2 Section 5.3.7.6: default presentation time offset is 2 ms. */
w->stream_out_sta.presentation_time_offset_ns = 2000000;
stream = &w->stream_out_sta.common.stream;
direction = SPA_DIRECTION_OUTPUT;
break;
default:
} else {
pw_log_error("Only STREAM_INPUT and STREAM_OUTPUT\n");
return NULL;
}
/**
* In this place the stream register interanlly SRP / MVRP state machines
*/
if (!server_create_stream(server, stream, direction, index)) {
pw_log_error("Could not create/initialize a stream");
return NULL;
@ -131,16 +73,13 @@ static struct descriptor *es_buidler_desc_stream_general_prepare(struct server *
}
static struct descriptor *es_buidler_desc_avb_interface(struct server *server,
uint16_t type, uint16_t index, size_t size, void *ptr)
uint16_t type, uint16_t index, size_t size, const void *ptr)
{
struct aecp_aem_avb_interface_state if_state = {0};
struct aecp_aem_avb_interface_state *if_ptr;
struct descriptor *desc;
memcpy(&if_state.desc, ptr, size);
desc = server_add_descriptor(server, type, index, sizeof(if_state),
&if_state);
desc = server_add_descriptor(server, type, index,
sizeof(*if_ptr), size, ptr);
if (!desc) {
pw_log_error("Error durring allocation\n");
spa_assert(0);
@ -171,12 +110,10 @@ static struct descriptor *es_buidler_desc_avb_interface(struct server *server,
return desc;
}
// Assign a ID to an specific builder
#define HELPER_ES_BUIDLER(type, callback) \
[type] = { .build_descriptor_cb = callback }
[type] = { .build_descriptor_cb = callback }
/** All callback that needs a status information for the AVB/Milan V1.2 */
static const struct es_builder_st es_builder_milan_v12[] =
static const struct es_builder_st es_builder_milan_v12[AVB_AEM_DESC_LAST_RESERVED_17221 + 1] =
{
HELPER_ES_BUIDLER(AVB_AEM_DESC_ENTITY, es_builder_desc_entity_milan_v12),
HELPER_ES_BUIDLER(AVB_AEM_DESC_STREAM_OUTPUT, es_buidler_desc_stream_general_prepare),
@ -184,42 +121,31 @@ static const struct es_builder_st es_builder_milan_v12[] =
HELPER_ES_BUIDLER(AVB_AEM_DESC_AVB_INTERFACE, es_buidler_desc_avb_interface),
};
/** All callback that needs a status information for Legacy AVB*/
static const struct es_builder_st es_builder_legacy_avb[] =
static const struct es_builder_st es_builder_legacy_avb[AVB_AEM_DESC_LAST_RESERVED_17221 + 1] =
{
HELPER_ES_BUIDLER(AVB_AEM_DESC_STREAM_OUTPUT, es_buidler_desc_stream_general_prepare),
HELPER_ES_BUIDLER(AVB_AEM_DESC_STREAM_INPUT, es_buidler_desc_stream_general_prepare),
};
/**
* \brief keep the list of the supported avb flavors here
*/
static const struct {
const struct es_builder_st *es_builder;
/** Number of elements in the es_builder */
size_t count;
} es_builders[] = {
[AVB_MODE_LEGACY] = {
.es_builder = es_builder_legacy_avb,
.count = ARRAY_SIZE(es_builder_legacy_avb),
.count = SPA_N_ELEMENTS(es_builder_legacy_avb),
},
[AVB_MODE_MILAN_V12] = {
.es_builder = es_builder_milan_v12,
.count = ARRAY_SIZE(es_builder_milan_v12),
.count = SPA_N_ELEMENTS(es_builder_milan_v12),
},
};
/**
* \brief, should be called when creating an a descriptor, it will attach
* the right state variable that are necessary for counters, stream info
* and so on...
*/
void es_builder_add_descriptor(struct server *server, uint16_t type,
uint16_t index, size_t size, void *ptr_aem)
{
const struct es_builder_st *es_builder;
struct descriptor *desc;
enum avb_mode avb_mode;
bool std_processing = false;
@ -234,34 +160,26 @@ void es_builder_add_descriptor(struct server *server, uint16_t type,
spa_assert(0);
}
es_builder = es_builders[avb_mode].es_builder;
if (type > es_builders[avb_mode].count) {
if (type >= es_builders[avb_mode].count) {
std_processing = true;
} else if (!es_builder[type].build_descriptor_cb) {
std_processing = true;
} else {
if (!es_builder[type].build_descriptor_cb) {
std_processing = true;
}
}
if (std_processing) {
if (!server_add_descriptor(server, type, index, size, ptr_aem)) {
if (!server_add_descriptor(server, type, index, 0, size, ptr_aem)) {
pw_log_error("Could not allocate descriptor %u at "
"index %u the avb aem type\n", type, index);
spa_assert(0);
}
} else {
desc = es_builder[type].build_descriptor_cb(server, type,
index, size, ptr_aem);
if (!desc) {
if (!es_builder[type].build_descriptor_cb(server, type,
index, size, ptr_aem)) {
pw_log_error("Could not allocate specific descriptr "
"%u at index %u the avb aem type\n",
type, index);
spa_assert(0);
}
desc->size = size;
}
}

View file

@ -67,9 +67,15 @@ struct descriptor {
uint16_t type;
uint16_t index;
uint32_t size;
uint32_t state_size;
void *ptr;
};
static inline void *descriptor_body(const struct descriptor *d)
{
return SPA_PTROFF(d->ptr, d->state_size, void);
}
enum avb_mode {
/** The legacy AVB Mode */
@ -142,20 +148,24 @@ static inline struct descriptor *server_find_descriptor(struct server *server,
}
return NULL;
}
static inline void *server_add_descriptor(struct server *server,
uint16_t type, uint16_t index, size_t size, void *ptr)
static inline struct descriptor *server_add_descriptor(struct server *server,
uint16_t type, uint16_t index,
size_t state_size, size_t desc_size, const void *desc_ptr)
{
struct descriptor *d;
if ((d = calloc(1, sizeof(struct descriptor) + size)) == NULL)
if ((d = calloc(1, sizeof(*d) + state_size + desc_size)) == NULL) {
return NULL;
}
d->type = type;
d->index = index;
d->size = size;
d->ptr = SPA_PTROFF(d, sizeof(struct descriptor), void);
if (ptr)
memcpy(d->ptr, ptr, size);
d->size = desc_size;
d->state_size = state_size;
d->ptr = SPA_PTROFF(d, sizeof(*d), void);
if (desc_ptr) {
memcpy(SPA_PTROFF(d->ptr, state_size, void), desc_ptr, desc_size);
}
spa_list_append(&server->descriptors, &d->link);
return d;
}