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 = [ diff --git a/src/modules/module-avb/descriptors.c b/src/modules/module-avb/descriptors.c index b496d713d..3320f4a4b 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,39 @@ 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 */ + 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 +859,5 @@ void init_descriptors(struct server *server) default: pw_log_error("Unknown AVB mode"); break; - } + } } diff --git a/src/modules/module-avb/entity-parser.h b/src/modules/module-avb/entity-parser.h new file mode 100644 index 000000000..635b80fa7 --- /dev/null +++ b/src/modules/module-avb/entity-parser.h @@ -0,0 +1,98 @@ +#ifndef ENTITY_PARSER_H +#define ENTITY_PARSER_H + +#include "aecp-aem-descriptors.h" +#include "avb.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]; + 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) { + // Grab entity field and turn into pw_properties struct + struct avb_entity_config entity_conf; + 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; + + 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; + 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)); + + // 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; + + 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 */