From 4ce6f65a9b7ce31499632e07e09dbf10dd06ad2e Mon Sep 17 00:00:00 2001 From: sirmbcode Date: Sun, 31 May 2026 11:24:14 -0700 Subject: [PATCH 1/5] added entity-parser.h --- src/modules/module-avb/entity-parser.h | 76 ++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/modules/module-avb/entity-parser.h diff --git a/src/modules/module-avb/entity-parser.h b/src/modules/module-avb/entity-parser.h new file mode 100644 index 000000000..2f3886b77 --- /dev/null +++ b/src/modules/module-avb/entity-parser.h @@ -0,0 +1,76 @@ +#ifndef ENTITY_PARSER_H +#define ENTITY_PARSER_H + +#include "aecp-aem-descriptors.h" +#include "avb.h" +#include "entity_model.h" +#include "internal.h" +#include "descriptors.h" + +struct avb_entity_config { + char entity_name[64]; + char group_name[64]; + char serial_number[64]; + char firmware_version[64]; + uint16_t vendor_name; + uint16_t model_name; + uint16_t talker_capabilities; + uint16_t listener_capabilities; + uint32_t entity_capabilities; + uint32_t controller_capabilities; +}; + +static inline struct avb_entity_config conf_load_entity (struct pw_properties *props) { + struct avb_entity_config entity_conf; + char* str; + pw_log_info("Acquiring entity properties from avb.properties.entity"); + str = pw_properties_get(props, "avb.properties.entity"); + struct pw_properties *entity_props; + entity_props = pw_properties_new(NULL,NULL); + pw_properties_update_string(entity_props, str, strlen(str)); + + pw_log_info("Assigning entity properties"); + char* name = pw_properties_get(entity_props, "entity_name"); + char *entity_name = name ? name : DSC_ENTITY_MODEL_ENTITY_NAME; + strncpy(entity_conf.entity_name, entity_name, sizeof(entity_conf.entity_name)); + + char *serial = pw_properties_get(entity_props, "serial_number"); + char *serial_number = serial ? serial : DSC_ENTITY_MODEL_SERIAL_NUMBER; + strncpy(entity_conf.serial_number, serial_number, sizeof(entity_conf.serial_number)); + + char *firmware = pw_properties_get(entity_props, "firmware_version"); + char* firmware_version = firmware ? firmware : DSC_ENTITY_MODEL_FIRMWARE_VERSION; + strncpy(entity_conf.firmware_version, firmware_version, sizeof(entity_conf.firmware_version)); + + char* group = pw_properties_get(entity_props, "group_name"); + char* group_name = group ? group: DSC_ENTITY_MODEL_GROUP_NAME; + strncpy(entity_conf.group_name, group_name, sizeof(entity_conf.group_name)); + + uint32_t vendor_name; + int vn_found = pw_properties_fetch_uint32(entity_props, "vendor_name", &vendor_name); + entity_conf.vendor_name = !vn_found ? (uint16_t)vendor_name : DSC_ENTITY_MODEL_VENDOR_NAME_STRING; + + uint32_t model_name; + int mn_found = pw_properties_fetch_uint32(entity_props, "model_name", &model_name); + entity_conf.model_name = !mn_found ? (uint16_t)model_name : DSC_ENTITY_MODEL_MODEL_NAME_STRING; + + uint32_t talker_capabilities; + int tc_found = pw_properties_fetch_uint32(entity_props, "talker_capabilities", &talker_capabilities); + entity_conf.talker_capabilities = !tc_found ? (uint16_t)talker_capabilities : DSC_ENTITY_MODEL_TALKER_CAPABILITIES; + + uint32_t listener_capabilities; + int lc_found = pw_properties_fetch_uint32(entity_props, "listener_capabilities", &listener_capabilities); + entity_conf.listener_capabilities = !lc_found ? (uint16_t)listener_capabilities : DSC_ENTITY_MODEL_LISTENER_CAPABILITIES; + + uint32_t entity_capabilities; + int ec_found = pw_properties_fetch_uint32(entity_props, "entity_capabilities", &entity_capabilities); + entity_conf.entity_capabilities = !ec_found ? entity_capabilities : DSC_ENTITY_MODEL_ENTITY_CAPABILITIES; + + uint32_t controller_capabilities; + int cc_found = pw_properties_fetch_uint32(entity_props, "controller_capabilities", &controller_capabilities); + entity_conf.controller_capabilities = !cc_found ? controller_capabilities : DSC_ENTITY_MODEL_CONTROLLER_CAPABILITIES; + + return entity_conf; +} + +#endif /* ENTITY_PARSER_H */ From 2862bc96149b1a980016db936f8c1fc7d627f398 Mon Sep 17 00:00:00 2001 From: sirmbcode Date: Sun, 31 May 2026 14:58:01 -0700 Subject: [PATCH 2/5] added entity fields to avb conf --- src/daemon/pipewire-avb.conf.in | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/daemon/pipewire-avb.conf.in b/src/daemon/pipewire-avb.conf.in index 1a9f48499..1b6440d93 100644 --- a/src/daemon/pipewire-avb.conf.in +++ b/src/daemon/pipewire-avb.conf.in @@ -72,6 +72,18 @@ avb.properties = { ifname = "enp3s0" milan = false ptp.management-socket = "/var/run/ptp4lro" + entity = { + #entity_name = "" + #group_name = "" + #serial_number = "" + #firmware_version = "" + #vendor_name = "" + #model_name = "" + #talker_capabilities = "" + #listener_capabilities = "" + #entity_capabilities = "" + #controller_capabilities = "" + } } avb.properties.rules = [ From d73b3b8469499310c252c4add6d0d1f6592dac68 Mon Sep 17 00:00:00 2001 From: sirmbcode Date: Sun, 31 May 2026 15:16:10 -0700 Subject: [PATCH 3/5] added calls to entity-parser.h for entity struct --- src/modules/module-avb/descriptors.c | 37 +++++++++++++++++----------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/modules/module-avb/descriptors.c b/src/modules/module-avb/descriptors.c index b496d713d..ef20c7fc7 100644 --- a/src/modules/module-avb/descriptors.c +++ b/src/modules/module-avb/descriptors.c @@ -12,6 +12,7 @@ #include "es-builder.h" #include "entity-model-milan-v12.h" +#include "entity-parser.h" static void init_descriptor_legacy_avb(struct server *server) { @@ -331,35 +332,41 @@ static void init_descriptor_milan_v12(struct server *server) /**************************************************************************************/ /* IEEE 1722.1-2021, Sec. 7.2.1 - ENTITY Descriptor */ /* Milan v1.2, Sec. 5.3.3.1 */ + // TODO: Add changes made from prev + struct avb_entity_config entity_conf = conf_load_entity(server->impl->props); - es_builder_add_descriptor(server, AVB_AEM_DESC_ENTITY, 0, - sizeof(struct avb_aem_desc_entity), - &(struct avb_aem_desc_entity) + + struct avb_aem_desc_entity entity_desc = { .entity_id = htobe64(server->entity_id), .entity_model_id = htobe64(DSC_ENTITY_MODEL_ID), - .entity_capabilities = htonl(DSC_ENTITY_MODEL_ENTITY_CAPABILITIES), + .entity_capabilities = htonl(entity_conf.entity_capabilities), .talker_stream_sources = htons(DSC_ENTITY_MODEL_TALKER_STREAM_SOURCES), - .talker_capabilities = htons(DSC_ENTITY_MODEL_TALKER_CAPABILITIES), + .talker_capabilities = htons(entity_conf.talker_capabilities), .listener_stream_sinks = htons(DSC_ENTITY_MODEL_LISTENER_STREAM_SINKS), - .listener_capabilities = htons(DSC_ENTITY_MODEL_LISTENER_CAPABILITIES), + .listener_capabilities = htons(entity_conf.listener_capabilities), - .controller_capabilities = htons(DSC_ENTITY_MODEL_CONTROLLER_CAPABILITIES), + .controller_capabilities = htons(entity_conf.controller_capabilities), .available_index = htonl(DSC_ENTITY_MODEL_AVAILABLE_INDEX), .association_id = htobe64(DSC_ENTITY_MODEL_ASSOCIATION_ID), - .entity_name = DSC_ENTITY_MODEL_ENTITY_NAME, - .vendor_name_string = htons(DSC_ENTITY_MODEL_VENDOR_NAME_STRING), - .model_name_string = htons(DSC_ENTITY_MODEL_MODEL_NAME_STRING), - .firmware_version = DSC_ENTITY_MODEL_FIRMWARE_VERSION, - .group_name = DSC_ENTITY_MODEL_GROUP_NAME, - .serial_number = DSC_ENTITY_MODEL_SERIAL_NUMBER, + .vendor_name_string = htons(entity_conf.vendor_name), + .model_name_string = htons(entity_conf.model_name), .configurations_count = htons(DSC_ENTITY_MODEL_CONFIGURATIONS_COUNT), .current_configuration = htons(DSC_ENTITY_MODEL_CURRENT_CONFIGURATION) - }); + }; + + memcpy(entity_desc.entity_name, entity_conf.entity_name, sizeof(entity_desc.entity_name)); + memcpy(entity_desc.firmware_version, entity_conf.firmware_version, sizeof(entity_desc.firmware_version)); + memcpy(entity_desc.group_name, entity_conf.group_name, sizeof(entity_desc.group_name)); + memcpy(entity_desc.serial_number, entity_conf.serial_number, sizeof(entity_desc.serial_number)); + + es_builder_add_descriptor(server, AVB_AEM_DESC_ENTITY, 0, + sizeof(struct avb_aem_desc_entity), + &entity_desc); /**************************************************************************************/ /* IEEE 1722.1-2021, Sec. 7.2.2 - CONFIGURATION Descriptor*/ @@ -854,5 +861,5 @@ void init_descriptors(struct server *server) default: pw_log_error("Unknown AVB mode"); break; - } + } } From e3cf4256f300c52b9dd650ba407fb787f6cf6bc0 Mon Sep 17 00:00:00 2001 From: sirmbcode Date: Sun, 31 May 2026 15:30:14 -0700 Subject: [PATCH 4/5] fixed spacing issues --- src/modules/module-avb/descriptors.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/modules/module-avb/descriptors.c b/src/modules/module-avb/descriptors.c index ef20c7fc7..3320f4a4b 100644 --- a/src/modules/module-avb/descriptors.c +++ b/src/modules/module-avb/descriptors.c @@ -332,10 +332,8 @@ static void init_descriptor_milan_v12(struct server *server) /**************************************************************************************/ /* IEEE 1722.1-2021, Sec. 7.2.1 - ENTITY Descriptor */ /* Milan v1.2, Sec. 5.3.3.1 */ - // TODO: Add changes made from prev struct avb_entity_config entity_conf = conf_load_entity(server->impl->props); - struct avb_aem_desc_entity entity_desc = { .entity_id = htobe64(server->entity_id), From c6974518220b2c9ee9698cb25d463ecfc2d60040 Mon Sep 17 00:00:00 2001 From: sirmbcode Date: Sun, 31 May 2026 17:15:04 -0700 Subject: [PATCH 5/5] added zero padding and utf8-validation to entity parser for first test --- src/modules/module-avb/entity-parser.h | 42 ++++++++++++++++++++------ 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/modules/module-avb/entity-parser.h b/src/modules/module-avb/entity-parser.h index 2f3886b77..635b80fa7 100644 --- a/src/modules/module-avb/entity-parser.h +++ b/src/modules/module-avb/entity-parser.h @@ -3,9 +3,11 @@ #include "aecp-aem-descriptors.h" #include "avb.h" -#include "entity_model.h" +#include "entity-model-milan-v12.h" #include "internal.h" #include "descriptors.h" +#include "strings.h" +#include struct avb_entity_config { char entity_name[64]; @@ -21,31 +23,51 @@ struct avb_entity_config { }; static inline struct avb_entity_config conf_load_entity (struct pw_properties *props) { + // Grab entity field and turn into pw_properties struct struct avb_entity_config entity_conf; - char* str; - pw_log_info("Acquiring entity properties from avb.properties.entity"); - str = pw_properties_get(props, "avb.properties.entity"); + char *str; + pw_log_info("Acquiring entity properties from entity dict in avb.properties"); + str = pw_properties_get(props, "entity"); struct pw_properties *entity_props; entity_props = pw_properties_new(NULL,NULL); pw_properties_update_string(entity_props, str, strlen(str)); + // Assign properties to aem_entity_config struct + // First handle strings + //TODO: with strings, check utf8 format and set as a filled 64 byte char array + // check zero padding and utf8 format pw_log_info("Assigning entity properties"); - char* name = pw_properties_get(entity_props, "entity_name"); - char *entity_name = name ? name : DSC_ENTITY_MODEL_ENTITY_NAME; - strncpy(entity_conf.entity_name, entity_name, sizeof(entity_conf.entity_name)); + char *name = pw_properties_get(entity_props, "entity_name"); + char *entity_name; + + int use_default = name ? 1 : 0; + size_t len; + + if (name){ + len = strnlen(name, 64); + if (validate_utf8(name, len)) entity_name = name; + else use_default = 1; + + if (use_default){ + len = strnlen(name, 64); + entity_name = (char *)DSC_ENTITY_MODEL_ENTITY_NAME; + } + memcpy(entity_conf.entity_name, entity_name, 64); + memset(entity_conf.entity_name + len, 0, 64 - len); char *serial = pw_properties_get(entity_props, "serial_number"); char *serial_number = serial ? serial : DSC_ENTITY_MODEL_SERIAL_NUMBER; strncpy(entity_conf.serial_number, serial_number, sizeof(entity_conf.serial_number)); char *firmware = pw_properties_get(entity_props, "firmware_version"); - char* firmware_version = firmware ? firmware : DSC_ENTITY_MODEL_FIRMWARE_VERSION; + char *firmware_version = firmware ? firmware : DSC_ENTITY_MODEL_FIRMWARE_VERSION; strncpy(entity_conf.firmware_version, firmware_version, sizeof(entity_conf.firmware_version)); - char* group = pw_properties_get(entity_props, "group_name"); - char* group_name = group ? group: DSC_ENTITY_MODEL_GROUP_NAME; + char *group = pw_properties_get(entity_props, "group_name"); + char *group_name = group ? group: DSC_ENTITY_MODEL_GROUP_NAME; strncpy(entity_conf.group_name, group_name, sizeof(entity_conf.group_name)); + // Handle integers uint32_t vendor_name; int vn_found = pw_properties_fetch_uint32(entity_props, "vendor_name", &vendor_name); entity_conf.vendor_name = !vn_found ? (uint16_t)vendor_name : DSC_ENTITY_MODEL_VENDOR_NAME_STRING;