mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-05-05 06:46:28 -04:00
milan-avb: move teh descriptor FAM at the end of the structure to avoid overflow
This commit is contained in:
parent
4d33f57325
commit
0bf4864d84
14 changed files with 126 additions and 204 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue