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, 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 descriptor *avb_if_desc;
struct aecp_aem_avb_interface_state *avb_if_state; const struct avb_aem_desc_stream *stream_body = descriptor_body(stream_out_desc);
uint16_t avb_if_index = ntohs(stream_out->desc.avb_interface_index); 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); 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; return false;
}
avb_if_state = avb_if_desc->ptr; avb_if_body = descriptor_body(avb_if_desc);
return memcmp(avb_if_state->desc.mac_address, server->mac_addr, return memcmp(avb_if_body->mac_address, server->mac_addr,
sizeof(server->mac_addr)) == 0; 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; 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; status = AVB_ACMP_STATUS_INCOMPATIBLE_REQUEST;
goto done; 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_ethernet_header *h_reply = (struct avb_ethernet_header *)buf;
struct avb_packet_acmp *reply = SPA_PTROFF(h_reply, sizeof(*h_reply), void); struct avb_packet_acmp *reply = SPA_PTROFF(h_reply, sizeof(*h_reply), void);
struct descriptor *desc; struct descriptor *desc;
struct aecp_aem_stream_output_state *stream_out;
int status = AVB_ACMP_STATUS_SUCCESS; int status = AVB_ACMP_STATUS_SUCCESS;
if (be64toh(p->talker_guid) != server->entity_id) 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; goto done;
} }
stream_out = desc->ptr; if (!stream_output_on_this_iface(server, desc)) {
if (!stream_output_on_this_iface(server, stream_out))
return 0; return 0;
}
reply->stream_id = 0; reply->stream_id = 0;
memset(reply->stream_dest_mac, 0, sizeof(reply->stream_dest_mac)); 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; stream_out = desc->ptr;
if (!stream_output_on_this_iface(server, stream_out)) if (!stream_output_on_this_iface(server, desc)) {
return 0; return 0;
}
reply->stream_id = stream_out->common.tastream_attr.attr.talker.stream_id; reply->stream_id = stream_out->common.tastream_attr.attr.talker.stream_id;
memcpy(reply->stream_dest_mac, stream_out->common.stream.addr, 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) if (d == NULL)
return -1; return -1;
entity = d->ptr; entity = descriptor_body(d);
entity_id = be64toh(entity->entity_id); entity_id = be64toh(entity->entity_id);
if ((e = find_entity_by_id(adp, entity_id)) != NULL) { 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); 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", pw_log_info("entity %s advertise",
avb_utils_format_id(buf, sizeof(buf), entity_id)); 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) if (entity_desc == NULL)
return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len); 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)) if (config_idx >= ntohs(entity->configurations_count))
return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len); 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) { switch (d->type) {
case AVB_AEM_DESC_ENTITY: { case AVB_AEM_DESC_ENTITY: {
const struct avb_aem_desc_entity *e = 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; struct avb_aem_dynamic_info_entity rec;
if (size + sizeof(rec) > sizeof(buf)) { 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: { case AVB_AEM_DESC_AUDIO_UNIT: {
const struct avb_aem_desc_audio_unit *au = 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; struct avb_aem_dynamic_info_audio_unit rec;
if (size + sizeof(rec) > sizeof(buf)) { 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; break;
} }
case AVB_AEM_DESC_STREAM_INPUT: { case AVB_AEM_DESC_STREAM_INPUT: {
const struct aecp_aem_stream_input_state *state = const struct avb_aem_desc_stream *body =
(const struct aecp_aem_stream_input_state *)d->ptr; (const struct avb_aem_desc_stream *)descriptor_body(d);
struct avb_aem_dynamic_info_stream rec; struct avb_aem_dynamic_info_stream rec;
if (size + sizeof(rec) > sizeof(buf)) { 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_type = htons(d->type);
rec.hdr.descriptor_index = htons(d->index); rec.hdr.descriptor_index = htons(d->index);
rec.stream_id = 0; rec.stream_id = 0;
rec.stream_format = state->desc.current_format; rec.stream_format = body->current_format;
if (state->desc.current_format != 0) if (body->current_format != 0) {
rec.stream_info_flags = rec.stream_info_flags =
htonl(AVB_AEM_STREAM_INFO_FLAG_STREAM_FORMAT_VALID); htonl(AVB_AEM_STREAM_INFO_FLAG_STREAM_FORMAT_VALID);
}
memcpy(ptr, &rec, sizeof(rec)); memcpy(ptr, &rec, sizeof(rec));
ptr += sizeof(rec); ptr += sizeof(rec);
psize += sizeof(rec); psize += sizeof(rec);
@ -135,8 +136,8 @@ int handle_cmd_get_dynamic_info_milan_v12(struct aecp *aecp, int64_t now,
break; break;
} }
case AVB_AEM_DESC_STREAM_OUTPUT: { case AVB_AEM_DESC_STREAM_OUTPUT: {
const struct aecp_aem_stream_output_state *state = const struct avb_aem_desc_stream *body =
(const struct aecp_aem_stream_output_state *)d->ptr; (const struct avb_aem_desc_stream *)descriptor_body(d);
struct avb_aem_dynamic_info_stream rec; struct avb_aem_dynamic_info_stream rec;
if (size + sizeof(rec) > sizeof(buf)) { 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_type = htons(d->type);
rec.hdr.descriptor_index = htons(d->index); rec.hdr.descriptor_index = htons(d->index);
rec.stream_id = 0; rec.stream_id = 0;
rec.stream_format = state->desc.current_format; rec.stream_format = body->current_format;
if (state->desc.current_format != 0) if (body->current_format != 0) {
rec.stream_info_flags = rec.stream_info_flags =
htonl(AVB_AEM_STREAM_INFO_FLAG_STREAM_FORMAT_VALID); htonl(AVB_AEM_STREAM_INFO_FLAG_STREAM_FORMAT_VALID);
}
memcpy(ptr, &rec, sizeof(rec)); memcpy(ptr, &rec, sizeof(rec));
ptr += sizeof(rec); ptr += sizeof(rec);
psize += 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: { case AVB_AEM_DESC_CLOCK_DOMAIN: {
const struct avb_aem_desc_clock_domain *cd = 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; struct avb_aem_dynamic_info_clock_domain rec;
if (size + sizeof(rec) > sizeof(buf)) { 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, return reply_status(aecp,
AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len); 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 */ /** Descriptors always keep the network endianness */
sclk_source->clock_source_index = dclk_domain->clock_source_index; 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, return reply_status(aecp,
AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len); 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) { if (clock_src_index >= dclk_domain->clock_sources_count) {
return reply_invalid_clock_source(aecp, dclk_domain, m, len); 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; int rc;
memset(buf, 0, sizeof(buf)); 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 = (struct avb_packet_aecp_aem_setget_configuration *) p->payload;
cfg->configuration_index = htons(entity_desc->current_configuration); cfg->configuration_index = htons(entity_desc->current_configuration);
p->aecp.target_guid = htobe64(aecp->server->entity_id); 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); p_reply = SPA_PTROFF(h_reply, sizeof(*h_reply), void);
cfg = (struct avb_packet_aecp_aem_setget_configuration*) p_reply->payload; 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); cur_cfg_id = ntohs(entity_desc->current_configuration);
req_cfg_id = ntohs(cfg->configuration_index); req_cfg_id = ntohs(cfg->configuration_index);
cfg_count = ntohs(entity_desc->configurations_count); 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); p_reply = SPA_PTROFF(h_reply, sizeof(*h_reply), void);
cfg = (struct avb_packet_aecp_aem_setget_configuration*) p_reply->payload; 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) { if (entity_desc->entity_id != p->aecp.target_guid) {
pw_log_error("Invalid entity id"); 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; struct avb_packet_aecp_aem_setget_control *ae_reply;
int pkt_size; int pkt_size;
ctrl_desc = desc->ptr; ctrl_desc = descriptor_body(desc);
desc_formats = ctrl_desc->value_format; desc_formats = ctrl_desc->value_format;
if (len < 0 || (size_t)len > sizeof(buf)) 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; int rc;
control = (struct avb_packet_aecp_aem_setget_control*)p->payload; 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; desc_formats = ctrl_desc->value_format;
old_value_format = desc_formats; old_value_format = desc_formats;
value_req = (uint8_t *)control->payload; 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, return reply_status(aecp,
AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len); 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); control_type = htobe64(ctrl_desc->control_type);
setter_cb = get_ctrl_setter_common(controls_handlers, setter_cb = get_ctrl_setter_common(controls_handlers,
SPA_N_ELEMENTS(controls_handlers), control_type); 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, return reply_status(aecp,
AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len); 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); control_type = htobe64(ctrl_desc->control_type);
getter_cb = get_ctrl_getter_common(controls_handlers, getter_cb = get_ctrl_getter_common(controls_handlers,
SPA_N_ELEMENTS(controls_handlers), control_type); 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, return reply_status(aecp,
AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len); 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) if (name_ptr == NULL)
return reply_status(aecp, return reply_status(aecp,
AVB_AECP_AEM_STATUS_BAD_ARGUMENTS, m, len); 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, return reply_status(aecp,
AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len); 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) if (name_ptr == NULL)
return reply_status(aecp, return reply_status(aecp,
AVB_AECP_AEM_STATUS_BAD_ARGUMENTS, m, len); 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); AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len);
if (desc_type == AVB_AEM_DESC_AUDIO_UNIT) { 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 /* TODO check if the STREAM_PORT associated with it supportes
* the SSRC/ASRC bit. * 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); AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len);
if (desc_type == AVB_AEM_DESC_AUDIO_UNIT) { 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)); memcpy(&pullfreq, &unit->current_sampling_rate, sizeof(pullfreq));
} else { } else {
return reply_status(aecp, 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, return reply_status(aecp,
AVB_AECP_AEM_STATUS_BAD_ARGUMENTS, m, len); 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)) if (len < 0 || (size_t)len > sizeof(buf))
return reply_status(aecp, 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); 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++) { for (i = 0; i < ntohs(stream_desc->number_of_formats); i++) {
if (stream_desc->stream_formats[i] == new_format) { if (stream_desc->stream_formats[i] == new_format) {
found = true; 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, 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 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 stream_common *sc = &si->stream_in_sta.common;
struct avb_msrp_attribute *lattr = &sc->lstream_attr; struct avb_msrp_attribute *lattr = &sc->lstream_attr;
struct avb_msrp_attribute *taattr = &sc->tastream_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; bool bound, settled, ta_observed, tf_observed, registering;
(void)aecp; (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. */ /* Milan Section 5.3.8.2: bound iff the listener has a saved talker stream id. */
bound = (lattr->attr.listener.stream_id != 0); 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, 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]; uint8_t buf[2048];
struct avb_ethernet_header *h_reply; 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); p_reply = SPA_PTROFF(h_reply, sizeof(*h_reply), void);
reply = (struct avb_packet_aecp_aem_setget_stream_info *)p_reply->payload; 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); return reply_success(aecp, buf, AVB_AECP_GET_STREAM_INFO_RESPONSE_LEN);
} }
static void populate_output_response(struct aecp *aecp, uint16_t desc_index, 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 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 stream_common *sc = &so->common;
struct avb_msrp_attribute *taattr = &sc->tastream_attr; struct avb_msrp_attribute *taattr = &sc->tastream_attr;
const uint8_t zero_mac[6] = {0}; 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, build_stream_info_response(aecp, NULL, 0, reply,
flags_host, flags_ex_host, flags_host, flags_ex_host,
0, 0, 0, 0,
so->desc.current_format, stream_id_be, stream_body->current_format, stream_id_be,
so->presentation_time_offset_ns, dest_mac, so->presentation_time_offset_ns, dest_mac,
0, 0, vlan_id_host); 0, 0, vlan_id_host);
pw_log_debug("populate STREAM_OUTPUT stream_format=0x%016" PRIx64 pw_log_debug("populate STREAM_OUTPUT stream_format=0x%016" PRIx64
" flags=0x%08x flags_ex=0x%08x pres_time_off=%u " " flags=0x%08x flags_ex=0x%08x pres_time_off=%u "
"stream_id=0x%016" PRIx64, "stream_id=0x%016" PRIx64,
be64toh(so->desc.current_format), be64toh(stream_body->current_format),
flags_host, flags_ex_host, flags_host, flags_ex_host,
so->presentation_time_offset_ns, so->presentation_time_offset_ns,
be64toh(stream_id_be)); be64toh(stream_id_be));
} }
static int handle_get_stream_output(struct aecp *aecp, const void *m, int len, 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]; uint8_t buf[2048];
struct avb_ethernet_header *h_reply; 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); p_reply = SPA_PTROFF(h_reply, sizeof(*h_reply), void);
reply = (struct avb_packet_aecp_aem_setget_stream_info *)p_reply->payload; 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); 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) if (desc == NULL)
return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len); return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len);
if (desc_type == AVB_AEM_DESC_STREAM_INPUT) if (desc_type == AVB_AEM_DESC_STREAM_INPUT) {
return handle_get_stream_input(aecp, m, len, return handle_get_stream_input(aecp, m, len, desc);
(struct aecp_aem_stream_input_state_milan_v12 *)desc->ptr); }
if (desc_type == AVB_AEM_DESC_STREAM_OUTPUT) if (desc_type == AVB_AEM_DESC_STREAM_OUTPUT) {
return handle_get_stream_output(aecp, m, len, desc_index, return handle_get_stream_output(aecp, m, len, desc_index, desc);
(struct aecp_aem_stream_output_state *)desc->ptr); }
return reply_status(aecp, AVB_AECP_AEM_STATUS_BAD_ARGUMENTS, m, len); 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_type = htons(desc_type);
body->descriptor_index = htons(desc_index); body->descriptor_index = htons(desc_index);
if (desc_type == AVB_AEM_DESC_STREAM_INPUT) if (desc_type == AVB_AEM_DESC_STREAM_INPUT) {
populate_input_response(aecp, populate_input_response(aecp, desc, body);
(struct aecp_aem_stream_input_state_milan_v12 *)desc->ptr, } else {
body); populate_output_response(aecp, desc_index, desc, body);
else }
populate_output_response(aecp, desc_index,
(struct aecp_aem_stream_output_state *)desc->ptr,
body);
(void)reply_unsolicited_notifications(aecp, &b_state, buf, (void)reply_unsolicited_notifications(aecp, &b_state, buf,
AVB_AECP_GET_STREAM_INFO_RESPONSE_LEN, true); 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 aecp_aem_avb_interface_state {
struct avb_aem_desc_avb_interface desc;
struct avb_msrp_attribute domain_attr; struct avb_msrp_attribute domain_attr;
struct avb_mvrp_attribute vlan_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 * \brief the generic entity state common for all flavor of AVB
*/ */
struct aecp_aem_entity_state { struct aecp_aem_entity_state {
struct avb_aem_desc_entity desc;
struct aecp_aem_lock_state lock_state; struct aecp_aem_lock_state lock_state;
}; };
@ -160,12 +157,7 @@ struct stream_common {
struct avb_msrp_attribute tfstream_attr; struct avb_msrp_attribute tfstream_attr;
}; };
#define AVB_AEM_STREAM_DESC_EXTRA_SIZE 128
struct aecp_aem_stream_input_state { 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 aecp_aem_stream_input_counters counters;
struct stream_common common; struct stream_common common;
struct avb_mvrp_attribute mvrp_attr; struct avb_mvrp_attribute mvrp_attr;
@ -210,9 +202,6 @@ struct aecp_aem_stream_output_counters {
}; };
struct aecp_aem_stream_output_state { 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 aecp_aem_stream_output_counters counters;
struct stream_common common; 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, m, len);
memcpy(buf + size, desc->ptr, desc->size); memcpy(buf + size, descriptor_body(desc), desc->size);
size += desc->size; size += desc->size;
psize += 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)) if (len < 0 || (size_t)len > sizeof(buf))
return reply_status(aecp, AVB_AECP_AEM_STATUS_BAD_ARGUMENTS, m, len); 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); memcpy(buf, m, len);

View file

@ -7,121 +7,63 @@
#include "aecp-aem-state.h" #include "aecp-aem-state.h"
#include "utils.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, 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 { struct es_builder_st {
es_builder_cb_t build_descriptor_cb; 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, 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}; return server_add_descriptor(server, type, index,
struct descriptor *desc; sizeof(struct aecp_aem_entity_milan_state), size, ptr);
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;
} }
/**
* \brief A generic function to avoid code duplicate for the streams */
static struct descriptor *es_buidler_desc_stream_general_prepare(struct server *server, 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 descriptor *desc;
struct stream *stream; struct stream *stream;
enum spa_direction direction; enum spa_direction direction;
switch (type) { if (type == AVB_AEM_DESC_STREAM_INPUT) {
case AVB_AEM_DESC_STREAM_INPUT: struct aecp_aem_stream_input_state_milan_v12 *w;
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;
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. */ /* Milan v1.2 Section 5.3.8.7: started/stopped state defaults to started. */
stream_input->started = true; w->stream_in_sta.started = true;
desc = server_add_descriptor(server, type, index, stream = &w->stream_in_sta.common.stream;
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;
direction = SPA_DIRECTION_INPUT; 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, desc = server_add_descriptor(server, type, index,
sizeof(stream_output_w), &stream_output_w); sizeof(*w), size, ptr);
if (!desc) { if (!desc) {
pw_log_error("Allocation failed\n"); pw_log_error("Allocation failed\n");
return NULL; return NULL;
} }
pstream_output = desc->ptr; w = desc->ptr;
stream = &pstream_output->common.stream; /* 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; direction = SPA_DIRECTION_OUTPUT;
} else {
break;
default:
pw_log_error("Only STREAM_INPUT and STREAM_OUTPUT\n"); pw_log_error("Only STREAM_INPUT and STREAM_OUTPUT\n");
return NULL; return NULL;
} }
/**
* In this place the stream register interanlly SRP / MVRP state machines
*/
if (!server_create_stream(server, stream, direction, index)) { if (!server_create_stream(server, stream, direction, index)) {
pw_log_error("Could not create/initialize a stream"); pw_log_error("Could not create/initialize a stream");
return NULL; 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, 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 aecp_aem_avb_interface_state *if_ptr;
struct descriptor *desc; struct descriptor *desc;
memcpy(&if_state.desc, ptr, size); desc = server_add_descriptor(server, type, index,
desc = server_add_descriptor(server, type, index, sizeof(if_state), sizeof(*if_ptr), size, ptr);
&if_state);
if (!desc) { if (!desc) {
pw_log_error("Error durring allocation\n"); pw_log_error("Error durring allocation\n");
spa_assert(0); spa_assert(0);
@ -171,12 +110,10 @@ static struct descriptor *es_buidler_desc_avb_interface(struct server *server,
return desc; return desc;
} }
// Assign a ID to an specific builder
#define HELPER_ES_BUIDLER(type, callback) \ #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[AVB_AEM_DESC_LAST_RESERVED_17221 + 1] =
static const struct es_builder_st es_builder_milan_v12[] =
{ {
HELPER_ES_BUIDLER(AVB_AEM_DESC_ENTITY, es_builder_desc_entity_milan_v12), 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), 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), 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[AVB_AEM_DESC_LAST_RESERVED_17221 + 1] =
static const struct es_builder_st es_builder_legacy_avb[] =
{ {
HELPER_ES_BUIDLER(AVB_AEM_DESC_STREAM_OUTPUT, es_buidler_desc_stream_general_prepare), 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), 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 { static const struct {
const struct es_builder_st *es_builder; const struct es_builder_st *es_builder;
/** Number of elements in the es_builder */
size_t count; size_t count;
} es_builders[] = { } es_builders[] = {
[AVB_MODE_LEGACY] = { [AVB_MODE_LEGACY] = {
.es_builder = es_builder_legacy_avb, .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] = { [AVB_MODE_MILAN_V12] = {
.es_builder = es_builder_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, void es_builder_add_descriptor(struct server *server, uint16_t type,
uint16_t index, size_t size, void *ptr_aem) uint16_t index, size_t size, void *ptr_aem)
{ {
const struct es_builder_st *es_builder; const struct es_builder_st *es_builder;
struct descriptor *desc;
enum avb_mode avb_mode; enum avb_mode avb_mode;
bool std_processing = false; bool std_processing = false;
@ -234,34 +160,26 @@ void es_builder_add_descriptor(struct server *server, uint16_t type,
spa_assert(0); spa_assert(0);
} }
es_builder = es_builders[avb_mode].es_builder; 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; std_processing = true;
} else {
if (!es_builder[type].build_descriptor_cb) {
std_processing = true;
}
} }
if (std_processing) { 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 " pw_log_error("Could not allocate descriptor %u at "
"index %u the avb aem type\n", type, index); "index %u the avb aem type\n", type, index);
spa_assert(0); spa_assert(0);
} }
} else { } else {
desc = es_builder[type].build_descriptor_cb(server, type, if (!es_builder[type].build_descriptor_cb(server, type,
index, size, ptr_aem); index, size, ptr_aem)) {
if (!desc) {
pw_log_error("Could not allocate specific descriptr " pw_log_error("Could not allocate specific descriptr "
"%u at index %u the avb aem type\n", "%u at index %u the avb aem type\n",
type, index); type, index);
spa_assert(0); spa_assert(0);
} }
desc->size = size;
} }
} }

View file

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