summaryrefslogtreecommitdiff
path: root/lib/avtp_pipeline/avdecc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/avtp_pipeline/avdecc')
-rw-r--r--lib/avtp_pipeline/avdecc/CMakeLists.txt12
-rw-r--r--lib/avtp_pipeline/avdecc/avdecc.ini82
-rw-r--r--lib/avtp_pipeline/avdecc/openavb_avdecc.c509
-rw-r--r--lib/avtp_pipeline/avdecc/openavb_avdecc.h210
-rw-r--r--lib/avtp_pipeline/avdecc/openavb_avdecc_pipeline_interaction_pub.h71
-rw-r--r--lib/avtp_pipeline/avdecc/openavb_avdecc_pub.h145
-rw-r--r--lib/avtp_pipeline/avdecc/openavb_avdecc_read_ini_pub.h197
-rwxr-xr-xlib/avtp_pipeline/avdecc/shutdown_openavb_avdecc.sh18
8 files changed, 1244 insertions, 0 deletions
diff --git a/lib/avtp_pipeline/avdecc/CMakeLists.txt b/lib/avtp_pipeline/avdecc/CMakeLists.txt
new file mode 100644
index 00000000..bccfc799
--- /dev/null
+++ b/lib/avtp_pipeline/avdecc/CMakeLists.txt
@@ -0,0 +1,12 @@
+SET (SRC_FILES ${SRC_FILES}
+ ${AVB_SRC_DIR}/avdecc/openavb_avdecc.c
+ ${AVB_OSAL_DIR}/avdecc/openavb_avdecc_osal.c
+ ${AVB_OSAL_DIR}/avdecc/openavb_avdecc_cfg.c
+ ${AVB_OSAL_DIR}/avdecc/openavb_avdecc_read_ini.c
+ ${AVB_OSAL_DIR}/avdecc/openavb_avdecc_pipeline_interaction.c
+ ${AVB_OSAL_DIR}/avdecc/openavb_avdecc_save_state.c
+ ${AVB_OSAL_DIR}/openavb_osal_avdecc.c
+ ${AVB_OSAL_DIR}/openavb_grandmaster_osal.c
+ ${AVB_SRC_DIR}/avdecc_msg/openavb_avdecc_msg_server.c
+ PARENT_SCOPE
+)
diff --git a/lib/avtp_pipeline/avdecc/avdecc.ini b/lib/avtp_pipeline/avdecc/avdecc.ini
new file mode 100644
index 00000000..d4b4bb60
--- /dev/null
+++ b/lib/avtp_pipeline/avdecc/avdecc.ini
@@ -0,0 +1,82 @@
+[network]
+
+# Interface name on which to use AVDECC
+#ifname=eth2
+
+
+[vlan]
+
+# VLAN ID to use for AVDECC traffic.
+# If VLAN support is not desired, comment out this value.
+#vlanID = 2
+
+# VLAN Priority to use for AVDECC traffic.
+# If VLAN support is not desired, comment out this value.
+#vlanPCP = 3
+
+
+[fast_connect]
+
+# If enable (set to 1), the fast_connect option will cause AVDECC-initiated
+# connections to be saved to an avdecc_save.ini file. When the AVDECC client
+# is restarted after an unexpected shutdown, AVDECC Fast Connect will be
+# attempted.
+#
+# The default value is 0, which disabled the AVDECC Fast Connect and Saved
+# State support.
+fast_connect = 1
+
+
+[discovery]
+
+# The valid_time is the amount of time (in seconds) the device will be
+# considered valid by other devices on the network after the last received
+# discovery packet. A smaller valid_time value will cause the device to be
+# recognized as disappearing more quickly if it is unplugged from the network
+# (or stops working), but will result in more background network traffic.
+#
+# Valid values are 2 to 62 seconds, with only even numbers being allowed.
+# The default value is 62 seconds.
+valid_time = 20
+
+
+[descriptor_entity]
+
+# ID value to be combined with the interface MAC Address to generate the
+# entity_id. For example, a device with MAC Address 00:11:22:33:44:55 and
+# avdeccId of 0x9876 would be assigned an entity_id of
+# 00-01-02-98-76-33-44-55.
+# The default ID value is 0xfffe.
+#avdeccId = 0xfffe
+
+# The entity_model_id is a unique vendor-specific 64-bit number used to
+# identify an AVDECC data model.
+entity_model_id = 0x0000000000000000
+
+# The entity_name is a UTF-8 string defining the device's name
+entity_name = "ACME Audio Processor"
+
+# The firmware_version is a UTF-8 string defining the device's firmware
+# version
+firmware_version = "0.0.0.1"
+
+# The group_name is a UTF-8 string defining the name of the device's group
+group_name = "Acme Processors"
+
+# The serial_number is a UTF-8 string defining the device's serial number
+serial_number = "12345"
+
+
+[localization]
+
+# A UTF-8 string defining the localization language to use for localized
+# strings. The format is "language code - region code".
+# Refer to IEEE Std 1722.1-2013 clause 7.2.11 for more details.
+locale_identifier = "en"
+
+# The vendor_name is a localized UTF-8 string defining the vendor's name
+vendor_name = "Acme Audio Inc."
+
+# The model_name is a localized UTF-8 string defining the device's model name
+model_name = "Acme 2400X"
+
diff --git a/lib/avtp_pipeline/avdecc/openavb_avdecc.c b/lib/avtp_pipeline/avdecc/openavb_avdecc.c
new file mode 100644
index 00000000..9c82a648
--- /dev/null
+++ b/lib/avtp_pipeline/avdecc/openavb_avdecc.c
@@ -0,0 +1,509 @@
+/*************************************************************************************************************
+Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company
+Copyright (c) 2016-2017, Harman International Industries, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS LISTED BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Attributions: The inih library portion of the source code is licensed from
+Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt.
+Complete license and copyright information can be found at
+https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175.
+*************************************************************************************************************/
+
+/*
+ ******************************************************************
+ * MODULE : AVDECC - Top level 1722.1 implementation
+ * MODULE SUMMARY : Top level 1722.1 implementation
+ ******************************************************************
+ */
+
+#include "openavb_rawsock.h"
+#include "openavb_avtp.h"
+
+#define AVB_LOG_COMPONENT "AVDECC"
+#include "openavb_log.h"
+
+#include "openavb_aem.h"
+#include "openavb_adp.h"
+#include "openavb_acmp.h"
+#include "openavb_aecp.h"
+
+#include "openavb_endpoint.h"
+
+#define ADDR_PTR(A) (U8*)(&((A)->ether_addr_octet))
+
+openavb_avdecc_cfg_t gAvdeccCfg;
+openavb_tl_data_cfg_t * streamList = NULL;
+openavb_aem_descriptor_configuration_t *pConfiguration = NULL;
+
+static openavb_avdecc_configuration_cfg_t *pFirstConfigurationCfg = NULL;
+static U8 talker_stream_sources = 0;
+static U8 listener_stream_sources = 0;
+static bool first_talker = 1;
+static bool first_listener = 1;
+
+bool openavbAvdeccStartAdp()
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);
+
+ openavbRC rc = openavbAdpStart();
+ if (IS_OPENAVB_FAILURE(rc)) {
+ openavbAdpStop();
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return TRUE;
+}
+
+void openavbAvdeccStopAdp()
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);
+ openavbAdpStop();
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+}
+
+bool openavbAvdeccStartCmp()
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);
+
+ openavbRC rc = openavbAcmpStart();
+ if (IS_OPENAVB_FAILURE(rc)) {
+ openavbAcmpStop();
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return TRUE;
+}
+
+void openavbAvdeccStopCmp()
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);
+ openavbAcmpStop();
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+}
+
+bool openavbAvdeccStartEcp()
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);
+
+ openavbRC rc = openavbAecpStart();
+ if (IS_OPENAVB_FAILURE(rc)) {
+ openavbAecpStop();
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return TRUE;
+}
+
+void openavbAvdeccStopEcp()
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);
+ openavbAecpStop();
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+}
+
+void openavbAvdeccFindMacAddr(void)
+{
+ // Open a rawsock may be the easiest cross platform way to get the MAC address.
+ void *txSock = openavbRawsockOpen(gAvdeccCfg.ifname, FALSE, TRUE, ETHERTYPE_AVTP, 100, 1);
+ if (txSock) {
+ openavbRawsockGetAddr(txSock, gAvdeccCfg.ifmac);
+ openavbRawsockClose(txSock);
+ txSock = NULL;
+ }
+}
+
+bool openavbAvdeccAddConfiguration(openavb_tl_data_cfg_t *stream)
+{
+ bool first_time = 0;
+ // Create a new config to hold the configuration information.
+ openavb_avdecc_configuration_cfg_t *pCfg = malloc(sizeof(openavb_avdecc_configuration_cfg_t));
+ if (!pCfg) {
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+ memset(pCfg, 0, sizeof(openavb_avdecc_configuration_cfg_t));
+
+ // Add a pointer to the supplied stream information.
+ pCfg->stream = stream;
+
+ // Add the new config to the end of the list of configurations.
+ if (pFirstConfigurationCfg == NULL) {
+ pFirstConfigurationCfg = pCfg;
+ } else {
+ openavb_avdecc_configuration_cfg_t *pLast = pFirstConfigurationCfg;
+ while (pLast->next != NULL) {
+ pLast = pLast->next;
+ }
+ pLast->next = pCfg;
+ }
+
+ // Create a new configuration.
+ U16 nConfigIdx = 0;
+ if (pConfiguration == NULL)
+ {
+ first_time = 1;
+ pConfiguration = openavbAemDescriptorConfigurationNew();
+ if (!openavbAemAddDescriptor(pConfiguration, OPENAVB_AEM_DESCRIPTOR_INVALID, &nConfigIdx)) {
+ AVB_LOG_ERROR("Error adding AVDECC configuration");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+ }
+ // Specify a default user-friendly name to use.
+ // AVDECC_TODO - Allow the user to specify a friendly name, or use the name if the .INI file.
+ if (pCfg->friendly_name[0] == '\0') {
+ snprintf((char *) pCfg->friendly_name, OPENAVB_AEM_STRLEN_MAX, "Configuration %u", nConfigIdx);
+ }
+
+ // Save the stream information in the configuration.
+ if (!openavbAemDescriptorConfigurationInitialize(pConfiguration, nConfigIdx, pCfg)) {
+ AVB_LOG_ERROR("Error initializing AVDECC configuration");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+
+ // Add the descriptors needed for both talkers and listeners.
+ U16 nResultIdx;
+ if (first_time)
+ {
+ openavb_aem_descriptor_avb_interface_t *pNewAvbInterface = openavbAemDescriptorAvbInterfaceNew();
+ if (!openavbAemAddDescriptor(pNewAvbInterface, nConfigIdx, &nResultIdx) ||
+ !openavbAemDescriptorAvbInterfaceInitialize(pNewAvbInterface, nConfigIdx, pCfg)) {
+ AVB_LOG_ERROR("Error adding AVDECC AVB Interface to configuration");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+ openavb_aem_descriptor_audio_unit_t *pNewAudioUnit = openavbAemDescriptorAudioUnitNew();
+ if (!openavbAemAddDescriptor(pNewAudioUnit, nConfigIdx, &nResultIdx) ||
+ !openavbAemDescriptorAudioUnitInitialize(pNewAudioUnit, nConfigIdx, pCfg)) {
+ AVB_LOG_ERROR("Error adding AVDECC Audio Unit to configuration");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+ }
+ else
+ {
+ openavb_aem_descriptor_audio_unit_t *pAudioUnitDescriptor =
+ (openavb_aem_descriptor_audio_unit_t *) openavbAemGetDescriptor(nConfigIdx, OPENAVB_AEM_DESCRIPTOR_AUDIO_UNIT, 0);
+ if (pAudioUnitDescriptor != NULL)
+ {
+ if (!openavbAemDescriptorAudioUnitInitialize(pAudioUnitDescriptor, nConfigIdx, pCfg)) {
+ AVB_LOG_ERROR("Error updating AVDECC Audio Unit to configuration");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+ }
+ else
+ {
+ AVB_LOG_ERROR("Error getting AVDECC Audio Unit descriptor");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+ }
+
+ // AVDECC_TODO: Add other descriptors as needed. Future options include:
+ // VIDEO_UNIT
+ // SENSOR_UNIT
+ // CONTROL
+
+ if (stream->role == AVB_ROLE_TALKER) {
+ gAvdeccCfg.bTalker = TRUE;
+
+ openavb_aem_descriptor_stream_io_t *pNewStreamOutput = openavbAemDescriptorStreamOutputNew();
+ if (!openavbAemAddDescriptor(pNewStreamOutput, nConfigIdx, &nResultIdx) ||
+ !openavbAemDescriptorStreamOutputInitialize(pNewStreamOutput, nConfigIdx, pCfg)) {
+ AVB_LOG_ERROR("Error adding AVDECC Stream Output to configuration");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+ if (first_talker)
+ {
+ first_talker = 0;
+ openavb_aem_descriptor_clock_source_t *pNewClockSource = openavbAemDescriptorClockSourceNew();
+ if (!openavbAemAddDescriptor(pNewClockSource, nConfigIdx, &nResultIdx) ||
+ !openavbAemDescriptorClockSourceInitialize(pNewClockSource, nConfigIdx, pCfg)) {
+ AVB_LOG_ERROR("Error adding AVDECC Clock Source to configuration");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+ openavb_aem_descriptor_clock_domain_t *pNewClockDomain = openavbAemDescriptorClockDomainNew();
+ if (!openavbAemAddDescriptor(pNewClockDomain, nConfigIdx, &nResultIdx) ||
+ !openavbAemDescriptorClockDomainInitialize(pNewClockDomain, nConfigIdx, pCfg)) {
+ AVB_LOG_ERROR("Error adding AVDECC Clock Domain to configuration");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+ }
+
+ // AVDECC_TODO: Add other descriptors as needed. Future options include:
+ // JACK_INPUT
+ talker_stream_sources++;
+
+ // Add the class specific to the talker.
+ if (stream->sr_class == SR_CLASS_A) { gAvdeccCfg.bClassASupported = TRUE; }
+ if (stream->sr_class == SR_CLASS_B) { gAvdeccCfg.bClassBSupported = TRUE; }
+
+ AVB_LOG_DEBUG("AVDECC talker configuration added");
+ }
+ if (stream->role == AVB_ROLE_LISTENER) {
+ gAvdeccCfg.bListener = TRUE;
+
+ openavb_aem_descriptor_stream_io_t *pNewStreamInput = openavbAemDescriptorStreamInputNew();
+ if (!openavbAemAddDescriptor(pNewStreamInput, nConfigIdx, &nResultIdx) ||
+ !openavbAemDescriptorStreamInputInitialize(pNewStreamInput, nConfigIdx, pCfg)) {
+ AVB_LOG_ERROR("Error adding AVDECC Stream Input to configuration");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+ if (first_listener)
+ {
+ openavb_aem_descriptor_clock_source_t *pNewClockSource = openavbAemDescriptorClockSourceNew();
+ if (!openavbAemAddDescriptor(pNewClockSource, nConfigIdx, &nResultIdx) ||
+ !openavbAemDescriptorClockSourceInitialize(pNewClockSource, nConfigIdx, pCfg)) {
+ AVB_LOG_ERROR("Error adding AVDECC Clock Source to configuration");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+ openavb_aem_descriptor_clock_domain_t *pNewClockDomain = openavbAemDescriptorClockDomainNew();
+ if (!openavbAemAddDescriptor(pNewClockDomain, nConfigIdx, &nResultIdx) ||
+ !openavbAemDescriptorClockDomainInitialize(pNewClockDomain, nConfigIdx, pCfg)) {
+ AVB_LOG_ERROR("Error adding AVDECC Clock Domain to configuration");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+ }
+
+ // AVDECC_TODO: Add other descriptors as needed. Future options include:
+ // JACK_OUTPUT
+ listener_stream_sources++;
+
+ // Listeners support both Class A and Class B.
+ gAvdeccCfg.bClassASupported = TRUE;
+ gAvdeccCfg.bClassBSupported = TRUE;
+
+ AVB_LOG_DEBUG("AVDECC listener configuration added");
+ }
+
+ if (first_time)
+ {
+ // Add the localized strings to the configuration.
+ if (!openavbAemDescriptorLocaleStringsHandlerAddToConfiguration(gAvdeccCfg.pAemDescriptorLocaleStringsHandler, nConfigIdx)) {
+ AVB_LOG_ERROR("Error adding AVDECC locale strings to configuration");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+////////////////////////////////
+// Public functions
+////////////////////////////////
+extern DLL_EXPORT bool openavbAvdeccInitialize()
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);
+
+ gAvdeccCfg.pDescriptorEntity = openavbAemDescriptorEntityNew();
+ if (!gAvdeccCfg.pDescriptorEntity) {
+ AVB_LOG_ERROR("Failed to allocate an AVDECC descriptor");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+
+ openavbAvdeccFindMacAddr();
+
+ if (!openavbAemDescriptorEntitySet_entity_id(gAvdeccCfg.pDescriptorEntity, NULL, gAvdeccCfg.ifmac, gAvdeccCfg.avdeccId)) {
+ AVB_LOG_ERROR("Failed to set the AVDECC descriptor");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+
+ // Create the Entity Model
+ openavbRC rc = openavbAemCreate(gAvdeccCfg.pDescriptorEntity);
+ if (IS_OPENAVB_FAILURE(rc)) {
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+
+ // Copy the supplied non-localized strings to the descriptor.
+ openavbAemDescriptorEntitySet_entity_model_id(gAvdeccCfg.pDescriptorEntity, gAvdeccCfg.entity_model_id);
+ openavbAemDescriptorEntitySet_entity_name(gAvdeccCfg.pDescriptorEntity, gAvdeccCfg.entity_name);
+ openavbAemDescriptorEntitySet_firmware_version(gAvdeccCfg.pDescriptorEntity, gAvdeccCfg.firmware_version);
+ openavbAemDescriptorEntitySet_group_name(gAvdeccCfg.pDescriptorEntity, gAvdeccCfg.group_name);
+ openavbAemDescriptorEntitySet_serial_number(gAvdeccCfg.pDescriptorEntity, gAvdeccCfg.serial_number);
+
+ // Initialize the localized strings support.
+ gAvdeccCfg.pAemDescriptorLocaleStringsHandler = openavbAemDescriptorLocaleStringsHandlerNew();
+ if (gAvdeccCfg.pAemDescriptorLocaleStringsHandler) {
+ // Add the strings to the locale strings hander.
+ openavbAemDescriptorLocaleStringsHandlerSet_local_string(
+ gAvdeccCfg.pAemDescriptorLocaleStringsHandler, gAvdeccCfg.locale_identifier, gAvdeccCfg.vendor_name, LOCALE_STRING_VENDOR_NAME_INDEX);
+ openavbAemDescriptorLocaleStringsHandlerSet_local_string(
+ gAvdeccCfg.pAemDescriptorLocaleStringsHandler, gAvdeccCfg.locale_identifier, gAvdeccCfg.model_name, LOCALE_STRING_MODEL_NAME_INDEX);
+
+ // Have the descriptor entity reference the locale strings.
+ openavbAemDescriptorEntitySet_vendor_name(gAvdeccCfg.pDescriptorEntity, 0, LOCALE_STRING_VENDOR_NAME_INDEX);
+ openavbAemDescriptorEntitySet_model_name(gAvdeccCfg.pDescriptorEntity, 0, LOCALE_STRING_MODEL_NAME_INDEX);
+ }
+
+ gAvdeccCfg.bTalker = gAvdeccCfg.bListener = FALSE;
+
+ // Add a configuration for each talker or listener stream.
+ openavb_tl_data_cfg_t *current_stream = streamList;
+ while (current_stream != NULL) {
+ // Create a new configuration with the information from this stream.
+ if (!openavbAvdeccAddConfiguration(current_stream)) {
+ AVB_LOG_ERROR("Error adding AVDECC configuration");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+
+ // Proceed to the next stream.
+ current_stream = current_stream->next;
+ }
+
+ if (!gAvdeccCfg.bTalker && !gAvdeccCfg.bListener) {
+ AVB_LOG_ERROR("No AVDECC Configurations -- Aborting");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+
+ // Add non-top-level descriptors. These are independent of the configurations.
+ // STRINGS are handled by gAvdeccCfg.pAemDescriptorLocaleStringsHandler, so not included here.
+ U16 nResultIdx;
+ if (!openavbAemAddDescriptor(openavbAemDescriptorAudioClusterNew(), OPENAVB_AEM_DESCRIPTOR_INVALID, &nResultIdx)) {
+ AVB_LOG_ERROR("Error adding AVDECC Audio Cluster");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+ if (gAvdeccCfg.bTalker) {
+ if (!openavbAemAddDescriptor(openavbAemDescriptorStreamPortOutputNew(), OPENAVB_AEM_DESCRIPTOR_INVALID, &nResultIdx)) {
+ AVB_LOG_ERROR("Error adding AVDECC Output Stream Port");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+ }
+ if (gAvdeccCfg.bListener) {
+ if (!openavbAemAddDescriptor(openavbAemDescriptorStreamPortInputNew(), OPENAVB_AEM_DESCRIPTOR_INVALID, &nResultIdx)) {
+ AVB_LOG_ERROR("Error adding AVDECC Input Stream Port");
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+ }
+
+ // AVDECC_TODO: Add other descriptors as needed. Future options include:
+ // EXTERNAL_PORT_INPUT
+ // EXTERNAL_PORT_OUTPUT
+ // INTERNAL_PORT_INPUT
+ // INTERNAL_PORT_OUTPUT
+ // VIDEO_CLUSTER
+ // SENSOR_CLUSTER
+ // AUDIO_MAP
+ // VIDEO_MAP
+ // SENSOR_MAP
+
+ // Fill in the descriptor capabilities.
+ // AVDECC_TODO: Set these based on the available capabilities.
+ if (!gAvdeccCfg.bClassASupported && !gAvdeccCfg.bClassBSupported) {
+ // If the user didn't specify a traffic class, assume both are supported.
+ gAvdeccCfg.bClassASupported = gAvdeccCfg.bClassBSupported = TRUE;
+ }
+ openavbAemDescriptorEntitySet_entity_capabilities(gAvdeccCfg.pDescriptorEntity,
+ OPENAVB_ADP_ENTITY_CAPABILITIES_AEM_SUPPORTED |
+ (gAvdeccCfg.bClassASupported ? OPENAVB_ADP_ENTITY_CAPABILITIES_CLASS_A_SUPPORTED : 0) |
+ (gAvdeccCfg.bClassBSupported ? OPENAVB_ADP_ENTITY_CAPABILITIES_CLASS_B_SUPPORTED : 0) |
+ OPENAVB_ADP_ENTITY_CAPABILITIES_GPTP_SUPPORTED);
+
+ if (gAvdeccCfg.bTalker) {
+ // AVDECC_TODO: Set these based on the available capabilities.
+ openavbAemDescriptorEntitySet_talker_capabilities(gAvdeccCfg.pDescriptorEntity, talker_stream_sources,
+ OPENAVB_ADP_TALKER_CAPABILITIES_IMPLEMENTED |
+ OPENAVB_ADP_TALKER_CAPABILITIES_AUDIO_SOURCE |
+ OPENAVB_ADP_TALKER_CAPABILITIES_MEDIA_CLOCK_SOURCE);
+ }
+ if (gAvdeccCfg.bListener) {
+ // AVDECC_TODO: Set these based on the available capabilities.
+ openavbAemDescriptorEntitySet_listener_capabilities(gAvdeccCfg.pDescriptorEntity, listener_stream_sources,
+ OPENAVB_ADP_LISTENER_CAPABILITIES_IMPLEMENTED |
+ OPENAVB_ADP_LISTENER_CAPABILITIES_AUDIO_SINK);
+ }
+
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return TRUE;
+}
+
+// Start the AVDECC protocols.
+extern DLL_EXPORT bool openavbAvdeccStart()
+{
+ if (!openavbAvdeccStartCmp()) {
+ AVB_LOG_ERROR("openavbAvdeccStartCmp() failure!");
+ return FALSE;
+ }
+ if (!openavbAvdeccStartEcp()) {
+ AVB_LOG_ERROR("openavbAvdeccStartEcp() failure!");
+ return FALSE;
+ }
+ if (!openavbAvdeccStartAdp()) {
+ AVB_LOG_ERROR("openavbAvdeccStartAdp() failure!");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// Stop the AVDECC protocols.
+extern DLL_EXPORT void openavbAvdeccStop(void)
+{
+ openavbAvdeccStopCmp();
+ openavbAvdeccStopEcp();
+ openavbAvdeccStopAdp();
+}
+
+extern DLL_EXPORT bool openavbAvdeccCleanup(void)
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);
+
+ openavbRC rc = openavbAemDestroy();
+
+ while (pFirstConfigurationCfg) {
+ openavb_avdecc_configuration_cfg_t *pDel = pFirstConfigurationCfg;
+ pFirstConfigurationCfg = pFirstConfigurationCfg->next;
+ free(pDel);
+ }
+
+ if (IS_OPENAVB_FAILURE(rc)) {
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return FALSE;
+ }
+
+ AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
+ return TRUE;
+}
diff --git a/lib/avtp_pipeline/avdecc/openavb_avdecc.h b/lib/avtp_pipeline/avdecc/openavb_avdecc.h
new file mode 100644
index 00000000..6c32b7e4
--- /dev/null
+++ b/lib/avtp_pipeline/avdecc/openavb_avdecc.h
@@ -0,0 +1,210 @@
+/*************************************************************************************************************
+Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company
+Copyright (c) 2016-2017, Harman International Industries, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS LISTED BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Attributions: The inih library portion of the source code is licensed from
+Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt.
+Complete license and copyright information can be found at
+https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175.
+*************************************************************************************************************/
+
+/*
+ ******************************************************************
+ * MODULE : AVDECC - Top level 1722.1 implementation
+ * MODULE SUMMARY : Top level 1722.1 implementation
+ ******************************************************************
+ */
+
+#ifndef OPENAVB_AVDECC_H
+#define OPENAVB_AVDECC_H 1
+
+#include "openavb_platform.h"
+
+#include "openavb_avdecc_pub.h"
+#include "openavb_avdecc_osal.h"
+#include "openavb_types.h"
+#include "openavb_trace.h"
+
+#ifndef DATA_ALIGNMENT_ADJUSTMENT
+// No Data alignment precaution needed.
+
+// Octet based data 2 buffer macros
+#define OCT_D2BMEMCP(d, s) {size_t data_size = sizeof(s); memcpy(d, s, data_size); d += data_size;} // Uses data_size variable to avoid compiler warnings
+#define OCT_D2BBUFCP(d, s, len) memcpy(d, s, len); d += len;
+#define OCT_D2BHTONB(d, s) *(U8 *)(d) = s; d += sizeof(s);
+#define OCT_D2BHTONS(d, s) *(U16 *)(d) = htons(s); d += sizeof(s);
+#define OCT_D2BHTONL(d, s) *(U32 *)(d) = htonl(s); d += sizeof(s);
+
+// Bit based data 2 buffer macros
+#define BIT_D2BHTONB(d, s, shf, inc) *(U8 *)(d) |= s << shf; d += inc;
+#define BIT_D2BHTONS(d, s, shf, inc) *(U16 *)(d) |= htons((U16)(s << shf)); d += inc;
+#define BIT_D2BHTONL(d, s, shf, inc) *(U32 *)(d) |= htonl((U32)(s << shf)); d += inc;
+
+
+// Octet based buffer 2 data macros
+#define OCT_B2DMEMCP(d, s) {size_t data_size = sizeof(d); memcpy(d, s, data_size); s += data_size;} // Uses data_size variable to avoid compiler warnings
+#define OCT_B2DBUFCP(d, s, len) memcpy(d, s, len); s += len;
+#define OCT_B2DNTOHB(d, s) d = *(U8 *)(s); s += sizeof(d);
+#define OCT_B2DNTOHS(d, s) d = ntohs(*(U16 *)(s)); s += sizeof(d);
+#define OCT_B2DNTOHL(d, s) d = ntohl(*(U32 *)(s)); s += sizeof(d);
+
+// Bit based buffer 2 data macros
+#define BIT_B2DNTOHB(d, s, msk, shf, inc) d = (*(U8 *)(s) & (U8)msk) >> shf; s += inc;
+#define BIT_B2DNTOHS(d, s, msk, shf, inc) d = (ntohs(*(U16 *)(s)) & (U16)msk) >> shf; s += inc;
+#define BIT_B2DNTOHL(d, s, msk, shf, inc) d = (ntohl(*(U32 *)(s)) & (U32)msk) >> shf; s += inc;
+
+#else
+// Data alignment precaution needed.
+
+// Octet based data 2 buffer macros
+#define OCT_D2BMEMCP(d, s) {size_t data_size = sizeof(s); memcpy(d, s, data_size); d += data_size;} // Uses data_size variable to avoid compiler warnings
+
+#define OCT_D2BBUFCP(d, s, len) memcpy(d, s, len); d += len;
+
+//#define OCT_D2BHTONB(d, s) *(U8 *)(d) = s; d += sizeof(s);
+#define OCT_D2BHTONB(d, s) \
+{ \
+memcpy(d, &s, sizeof(U8)); \
+d += sizeof(U8); \
+}
+
+//#define OCT_D2BHTONS(d, s) *(U16 *)(d) = htons(s); d += sizeof(s);
+#define OCT_D2BHTONS(d, s) \
+{ \
+U16 sAlign16 = s; \
+sAlign16 = htons(sAlign16); \
+memcpy(d, &sAlign16, sizeof(U16)); \
+d += sizeof(U16); \
+}
+
+//#define OCT_D2BHTONL(d, s) *(U32 *)(d) = htonl(s); d += sizeof(s);
+#define OCT_D2BHTONL(d, s) \
+{ \
+U32 sAlign32 = s; \
+sAlign32 = htonl(sAlign32); \
+memcpy(d, &sAlign32, sizeof(U32)); \
+d += sizeof(U32); \
+}
+
+// Bit based data 2 buffer macros
+//#define BIT_D2BHTONB(d, s, shf, inc) *(U8 *)(d) |= s << shf; d += inc;
+#define BIT_D2BHTONB(d, s, shf, inc) \
+{ \
+U8 sAlign8 = s << shf; \
+U8 dAlign8; \
+memcpy(&dAlign8, d, sizeof(U8)); \
+dAlign8 |= sAlign8; \
+memcpy(d, &dAlign8, sizeof(U8)); \
+d += inc; \
+}
+
+//#define BIT_D2BHTONS(d, s, shf, inc) *(U16 *)(d) |= htons((U16)(s << shf)); d += inc;
+#define BIT_D2BHTONS(d, s, shf, inc) \
+{ \
+U16 sAlign16 = htons((U16)(s << shf)); \
+U16 dAlign16; \
+memcpy(&dAlign16, d, sizeof(U16)); \
+dAlign16 |= sAlign16; \
+memcpy(d, &dAlign16, sizeof(U16)); \
+d += inc; \
+}
+
+//#define BIT_D2BHTONL(d, s, shf, inc) *(U32 *)(d) |= htonl((U32)(s << shf)); d += inc;
+#define BIT_D2BHTONL(d, s, shf, inc) \
+{ \
+U32 sAlign32 = htonl((U32)(s << shf)); \
+U32 dAlign32; \
+memcpy(&dAlign32, d, sizeof(U32)); \
+dAlign32 |= sAlign32; \
+memcpy(d, &dAlign32, sizeof(U32)); \
+d += inc; \
+}
+
+
+// Octet based buffer 2 data macros
+#define OCT_B2DMEMCP(d, s) {size_t data_size = sizeof(d); memcpy(d, s, data_size); s += data_size;} // Uses data_size variable to avoid compiler warnings
+
+#define OCT_B2DBUFCP(d, s, len) memcpy(d, s, len); s += len;
+
+//#define OCT_B2DNTOHB(d, s) d = *(U8 *)(s); s += sizeof(d);
+#define OCT_B2DNTOHB(d, s) \
+{ \
+memcpy(&d, s, sizeof(U8)); \
+s += sizeof(U8); \
+}
+
+//#define OCT_B2DNTOHS(d, s) d = ntohs(*(U16 *)(s)); s += sizeof(d);
+#define OCT_B2DNTOHS(d, s) \
+{ \
+U16 sAlign16; \
+memcpy(&sAlign16, s, sizeof(U16)); \
+sAlign16 = ntohs(sAlign16); \
+memcpy(&d, &sAlign16, sizeof(U16)); \
+s += sizeof(U16); \
+}
+
+//#define OCT_B2DNTOHL(d, s) d = ntohl(*(U32 *)(s)); s += sizeof(d);
+#define OCT_B2DNTOHL(d, s) \
+{ \
+U32 sAlign32; \
+memcpy(&sAlign32, s, sizeof(U32)); \
+sAlign32 = ntohl(sAlign32); \
+memcpy(&d, &sAlign32, sizeof(U32)); \
+s += sizeof(U32); \
+}
+
+// Bit based buffer 2 data macros
+//#define BIT_B2DNTOHB(d, s, msk, shf, inc) d = (*(U8 *)(s) & (U8)msk) >> shf; s += inc;
+#define BIT_B2DNTOHB(d, s, msk, shf, inc) \
+{ \
+U8 sAlign8; \
+memcpy(&sAlign8, s, sizeof(U8)); \
+sAlign8 = (sAlign8 & (U8)msk) >>shf; \
+memcpy(&d, &sAlign8, sizeof(U8)); \
+s += inc; \
+}
+
+//#define BIT_B2DNTOHS(d, s, msk, shf, inc) d = (ntohs(*(U16 *)(s)) & (U16)msk) >> shf; s += inc;
+#define BIT_B2DNTOHS(d, s, msk, shf, inc) \
+{ \
+U16 sAlign16; \
+memcpy(&sAlign16, s, sizeof(U16)); \
+sAlign16 = (ntohs(sAlign16) & (U16)msk) >> shf; \
+memcpy(&d, &sAlign16, sizeof(U16)); \
+s += inc; \
+}
+
+//#define BIT_B2DNTOHL(d, s, msk, shf, inc) d = (ntohl(*(U32 *)(s)) & (U32)msk) >> shf; s += inc;
+#define BIT_B2DNTOHL(d, s, msk, shf, inc) \
+{ \
+U32 sAlign32; \
+memcpy(&sAlign32, s, sizeof(U32)); \
+sAlign32 = (ntohs(sAlign32) & (U32)msk) >> shf; \
+memcpy(&d, &sAlign32, sizeof(U32)); \
+s += inc; \
+}
+
+#endif
+
+#endif // OPENAVB_AVDECC_H
diff --git a/lib/avtp_pipeline/avdecc/openavb_avdecc_pipeline_interaction_pub.h b/lib/avtp_pipeline/avdecc/openavb_avdecc_pipeline_interaction_pub.h
new file mode 100644
index 00000000..c7edac96
--- /dev/null
+++ b/lib/avtp_pipeline/avdecc/openavb_avdecc_pipeline_interaction_pub.h
@@ -0,0 +1,71 @@
+/*************************************************************************************************************
+Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company
+Copyright (c) 2016-2017, Harman International Industries, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS LISTED BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Attributions: The inih library portion of the source code is licensed from
+Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt.
+Complete license and copyright information can be found at
+https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175.
+*************************************************************************************************************/
+
+#ifndef OPENAVB_AVDECC_PIPELINE_INTERACTION_PUB_H
+#define OPENAVB_AVDECC_PIPELINE_INTERACTION_PUB_H 1
+
+#include "openavb_acmp.h"
+#include "openavb_descriptor_stream_io_pub.h"
+#include "openavb_avdecc_msg.h"
+
+
+// Run a single talker or listener.
+bool openavbAVDECCRunListener(openavb_aem_descriptor_stream_io_t *pDescriptorStreamInput, U16 configIdx, openavb_acmp_ListenerStreamInfo_t *pListenerStreamInfo);
+bool openavbAVDECCRunTalker(openavb_aem_descriptor_stream_io_t *pDescriptorStreamOutput, U16 configIdx, openavb_acmp_TalkerStreamInfo_t *pTalkerStreamInfo);
+
+// Stop a single talker or listener.
+bool openavbAVDECCStopListener(openavb_aem_descriptor_stream_io_t *pDescriptorStreamInput, U16 configIdx, openavb_acmp_ListenerStreamInfo_t *pListenerStreamInfo);
+bool openavbAVDECCStopTalker(openavb_aem_descriptor_stream_io_t *pDescriptorStreamOutput, U16 configIdx, openavb_acmp_TalkerStreamInfo_t *pTalkerStreamInfo);
+
+// Get talker stream details. Structure members in TalkerStreamInfo will be filled.
+bool openavbAVDECCGetTalkerStreamInfo(openavb_aem_descriptor_stream_io_t *pDescriptorStreamOutput, U16 configIdx, openavb_acmp_TalkerStreamInfo_t *pTalkerStreamInfo);
+
+// Set talker stream details. The settings will be passed to the Talker to use for future connections
+bool openavbAVDECCSetTalkerStreamInfo(
+ openavb_aem_descriptor_stream_io_t *pDescriptorStreamOutput,
+ U8 sr_class,
+ U8 stream_id_valid, const U8 stream_src_mac[6], U16 stream_uid,
+ U8 stream_dest_valid, const U8 stream_dest_mac[6],
+ U8 stream_vlan_id_valid, U16 stream_vlan_id);
+
+// Get the streaming state (stopped, running, paused, etc.) AVDECC told the talker or listener to use.
+openavbAvdeccMsgStateType_t openavbAVDECCGetRequestedState(openavb_aem_descriptor_stream_io_t *pDescriptorStreamInput, U16 configIdx);
+
+// Get the streaming state (stopped, running, paused, etc.) last reported by the talker or listener.
+openavbAvdeccMsgStateType_t openavbAVDECCGetStreamingState(openavb_aem_descriptor_stream_io_t *pDescriptorStreamInput, U16 configIdx);
+
+// Pause or resume the stream.
+void openavbAVDECCPauseStream(openavb_aem_descriptor_stream_io_t *pDescriptor, bool bPause);
+
+// Get the current counter value in pValue. Returns TRUE if the counter is supported, FALSE otherwise.
+bool openavbAVDECCGetCounterValue(void *pDescriptor, U16 descriptorType, U32 counterFlag, U32 *pValue);
+
+#endif // OPENAVB_AVDECC_PIPELINE_INTERACTION_PUB_H
diff --git a/lib/avtp_pipeline/avdecc/openavb_avdecc_pub.h b/lib/avtp_pipeline/avdecc/openavb_avdecc_pub.h
new file mode 100644
index 00000000..803438ed
--- /dev/null
+++ b/lib/avtp_pipeline/avdecc/openavb_avdecc_pub.h
@@ -0,0 +1,145 @@
+/*************************************************************************************************************
+Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company
+Copyright (c) 2016-2017, Harman International Industries, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS LISTED BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Attributions: The inih library portion of the source code is licensed from
+Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt.
+Complete license and copyright information can be found at
+https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175.
+*************************************************************************************************************/
+
+/*
+ ******************************************************************
+ * MODULE : AVDECC - Top level AVDECC (1722.1) Public Interface
+ * MODULE SUMMARY : Top level AVDECC (1722.1) Public Interface
+ ******************************************************************
+ */
+
+#ifndef OPENAVB_AVDECC_PUB_H
+#define OPENAVB_AVDECC_PUB_H 1
+
+// Entity Model public includes
+#include "openavb_aem_pub.h"
+#include "openavb_descriptor_entity_pub.h"
+#include "openavb_descriptor_configuration_pub.h"
+#include "openavb_descriptor_audio_unit_pub.h"
+#include "openavb_descriptor_stream_io_pub.h"
+#include "openavb_descriptor_jack_io_pub.h"
+#include "openavb_descriptor_avb_interface_pub.h"
+#include "openavb_descriptor_clock_source_pub.h"
+#include "openavb_descriptor_locale_pub.h"
+#include "openavb_descriptor_strings_pub.h"
+#include "openavb_descriptor_control_pub.h"
+#include "openavb_descriptor_stream_port_io_pub.h"
+#include "openavb_descriptor_external_port_io_pub.h"
+#include "openavb_descriptor_audio_cluster_pub.h"
+#include "openavb_descriptor_audio_map_pub.h"
+#include "openavb_descriptor_clock_domain_pub.h"
+#include "openavb_descriptor_locale_strings_handler_pub.h"
+
+// Discovery protocol public includes
+#include "openavb_adp_pub.h"
+
+// Connection management public includes
+#include "openavb_acmp_pub.h"
+
+// Enumeration and control public includes
+#include "openavb_aecp_pub.h"
+
+// openavb_tl_data_cfg_t definition
+#include "openavb_avdecc_read_ini_pub.h"
+
+#ifndef IFNAMSIZ
+#define IFNAMSIZ 16
+#endif
+#ifndef ETH_ALEN
+#define ETH_ALEN 6
+#endif
+
+// Indexes for localized strings.
+// (These are defined for internal use, and can be changed as needed.)
+#define LOCALE_STRING_VENDOR_NAME_INDEX 0
+#define LOCALE_STRING_MODEL_NAME_INDEX 1
+
+typedef struct {
+
+ char ifname[IFNAMSIZ + 10]; // Include space for the socket type prefix (e.g. "simple:eth0")
+ U8 ifmac[ETH_ALEN];
+
+ bool bListener;
+ bool bTalker;
+ bool bClassASupported;
+ bool bClassBSupported;
+
+ U16 vlanID;
+ U8 vlanPCP;
+
+ bool bFastConnectSupported; // FAST_CONNECT and SAVED_STATE supported
+
+ U8 valid_time; // Number of 2-second units
+
+ // Information to add to the descriptor.
+ unsigned avdeccId;
+ U8 entity_model_id[8];
+ char entity_name[OPENAVB_AEM_STRLEN_MAX];
+ char firmware_version[OPENAVB_AEM_STRLEN_MAX];
+ char group_name[OPENAVB_AEM_STRLEN_MAX];
+ char serial_number[OPENAVB_AEM_STRLEN_MAX];
+
+ // Localization strings.
+ char locale_identifier[OPENAVB_AEM_STRLEN_MAX];
+ char vendor_name[OPENAVB_AEM_STRLEN_MAX];
+ char model_name[OPENAVB_AEM_STRLEN_MAX];
+
+ openavb_aem_descriptor_entity_t *pDescriptorEntity;
+ openavb_aem_descriptor_locale_strings_handler_t *pAemDescriptorLocaleStringsHandler;
+} openavb_avdecc_cfg_t;
+
+typedef struct openavb_avdecc_configuration_cfg {
+ struct openavb_avdecc_configuration_cfg *next; // next link list pointer
+
+ // Pointer to the endpoint information.
+ openavb_tl_data_cfg_t *stream;
+
+ // Friendly name
+ char friendly_name[OPENAVB_AEM_STRLEN_MAX];
+
+ // AVDECC_TODO: Add additional information as needed.
+
+} openavb_avdecc_configuration_cfg_t;
+
+
+// General initialization for AVDECC. This must be called before any other AVDECC APIs including AEM APIs
+bool openavbAvdeccInitialize(void);
+
+// Start the AVDECC protocols.
+bool openavbAvdeccStart(void);
+
+// Stop the AVDECC protocols.
+void openavbAvdeccStop(void);
+
+// General Cleanup for AVDECC.
+bool openavbAvdeccCleanup(void);
+
+#endif // OPENAVB_AVDECC_PUB_H
diff --git a/lib/avtp_pipeline/avdecc/openavb_avdecc_read_ini_pub.h b/lib/avtp_pipeline/avdecc/openavb_avdecc_read_ini_pub.h
new file mode 100644
index 00000000..5c71d5b7
--- /dev/null
+++ b/lib/avtp_pipeline/avdecc/openavb_avdecc_read_ini_pub.h
@@ -0,0 +1,197 @@
+/*************************************************************************************************************
+Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company
+Copyright (c) 2016-2017, Harman International Industries, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS LISTED BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Attributions: The inih library portion of the source code is licensed from
+Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt.
+Complete license and copyright information can be found at
+https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175.
+*************************************************************************************************************/
+
+/*
+* HEADER SUMMARY : AVDECC Read INI Public Interface
+*/
+
+#ifndef OPENAVB_AVDECC_READ_INI_PUB_H
+#define OPENAVB_AVDECC_READ_INI_PUB_H 1
+
+#include "openavb_types_pub.h"
+#include "openavb_mediaq_pub.h"
+#include "openavb_avtp_time_pub.h"
+#include "openavb_tl_pub.h"
+
+#define MAX_SAMPLING_RATES_COUNT 91
+
+/** \file
+ * AVDECC Read INI Public Interface.
+ */
+
+struct _avdecc_msg_state;
+typedef struct _avdecc_msg_state avdecc_msg_state_t;
+
+/// Maximum size of the friendly name
+#define FRIENDLY_NAME_SIZE 64
+
+/// Structure containing configuration of the host
+struct openavb_tl_data_cfg {
+ struct openavb_tl_data_cfg *next;
+
+ /// Role of the host
+ avb_role_t role;
+ /// Initial Talker/Listener state
+ tl_init_state_t initial_state;
+ /// MAC address of destination - multicast (talker only if SRP is enabled)
+ cfg_mac_t dest_addr;
+ /// MAC address of the source
+ cfg_mac_t stream_addr;
+ /// Stream UID (has to be unique)
+ U16 stream_uid;
+ /// Maximum number of packets sent during one interval (talker only)
+ U32 max_interval_frames;
+ /// Maximum size of the frame
+ U32 max_frame_size;
+ /// Setting maximum transit time, on talker value is added to PTP Walltime,
+ /// on listener value is validated timestamp range
+ U32 max_transit_usec;
+ /// Maximum transmit deficit in usec - should be set to expected buffer size
+ /// on the listener side (talker only)
+ U32 max_transmit_deficit_usec;
+ /// Specify manual an internal latency (talker only)
+ U32 internal_latency;
+ /// Number of microseconds after which late MediaQItem will be purged as too
+ /// old (listener only)
+ U32 max_stale;
+ /// Number of intervals to handle at once (talker only)
+ U32 batch_factor;
+ /// Statistics reporting frequency
+ U32 report_seconds;
+ /// Start paused
+ bool start_paused;
+ /// Class in which host will operate ::SRClassIdx_t (talker only)
+ U8 sr_class;
+ /// Rank of the stream #SR_RANK_REGULAR or #SR_RANK_EMERGENCY (talker only)
+ U8 sr_rank;
+ /// Number of raw TX buffers that should be used (talker only)
+ U32 raw_tx_buffers;
+ /// Number of raw RX buffers (listener only)
+ U32 raw_rx_buffers;
+ /// Is the interface module blocking in the TX CB.
+ bool tx_blocking_in_intf;
+ /// VLAN ID
+ U16 vlan_id;
+ /// When set incoming packets will trigger a signal to the stream task to wakeup.
+ bool rx_signal_mode;
+ /// Enable fixed timestamping in interface
+ U32 fixed_timestamp;
+ /// Wait for next observation interval by spinning rather than sleeping
+ bool spin_wait;
+ /// Bit mask used for CPU pinning
+ U32 thread_affinity;
+ /// Real time priority of thread.
+ U32 thread_rt_priority;
+ /// The current sample rate of this Audio Unit
+ U32 current_sampling_rate;
+ /// The number of sample rates in the sampling_rates field.
+ U16 sampling_rates_count;
+ /// An array of 4-octet sample rates supported by this Audio Unit
+ U32 sampling_rates[MAX_SAMPLING_RATES_COUNT];
+ /// intf_nv_audio_rate
+ U16 audioRate;
+ /// intf_nv_audio_bit_depth
+ U8 audioBitDepth;
+ /// intf_nv_channels
+ U8 audioChannels;
+ /// Friendly name for this configuration
+ char friendly_name[FRIENDLY_NAME_SIZE];
+ /// The name of the initialize function in the mapper
+ char map_fn[100];
+
+ // Pointer to the client Talker/Listener.
+ // Do not free this item; it is for reference only.
+ const avdecc_msg_state_t * client;
+};
+
+typedef struct openavb_tl_data_cfg openavb_tl_data_cfg_t;
+
+
+/** Read an ini file.
+ *
+ * Parses an input configuration file to populate configuration structures, and
+ * name value pairs. Only used in Operating Systems that have a file system
+ *
+ * \param fileName Pointer to configuration file name
+ * \param pCfg Pointer to configuration structure
+ * \return TRUE on success or FALSE on failure
+ *
+ * \warning Not available on all platforms
+ */
+bool openavbReadTlDataIniFile(const char *fileName, openavb_tl_data_cfg_t *pCfg);
+
+
+/** Save the connection to the saved state
+ *
+ * If fast connect support is enabled, this function is used to save the state
+ * of the connection by a Listener when a connection is successfully made to
+ * a Talker for possible fast connect support later.
+ * #openavbAvdeccClearSavedState() should be called when the connection is closed.
+ *
+ * \param pListener Pointer to configuration for the Listener
+ * \param flags The flags used for the connection (CLASS_B, SUPPORTS_ENCRYPTED, ENCRYPTED_PDU)
+ * \param talker_unique_id The unique id for the Talker
+ * \param talker_entity_id The binary entity id for the Talker
+ * \param controller_entity_id The binary entity id for the Controller that initiated the connection
+ *
+ * \return TRUE on success or FALSE on failure
+ */
+bool openavbAvdeccSaveState(const openavb_tl_data_cfg_t *pListener, U16 flags, U16 talker_unique_id, const U8 talker_entity_id[8], const U8 controller_entity_id[8]);
+
+/** Delete a connection with saved state
+ *
+ * If fast connect support is enabled, this function is used to clear previously
+ * saved state information (from a previous call to #openavbAvdeccSaveState).
+ * This function should be called from the Listener when a Talker/Listener connection is closed
+ * (and fast connects should no longer be attempted in the future).
+ *
+ * \param pListener Pointer to configuration for the Listener
+ *
+ * \return TRUE on success or FALSE on failure
+ */
+bool openavbAvdeccClearSavedState(const openavb_tl_data_cfg_t *pListener);
+
+/** Determine if the connection has a saved state
+ *
+ * If fast connect support is enabled, this function is used to get the last
+ * saved state (from a call to #openavbAvdeccSaveState) for a Listener, if any.
+ *
+ * \param pListener Pointer to configuration for the Listener
+ * \param p_flags Optional pointer to the flags used for the connection (CLASS_B, SUPPORTS_ENCRYPTED, ENCRYPTED_PDU)
+ * \param p_talker_unique_id Optional pointer to the unique id for the Talker
+ * \param p_talker_entity_id Optional pointer to the buffer to fill in the binary entity id for the Talker
+ * \param p_controller_entity_id Optional pointer to the buffer to fill in the binary entity id for the Controller that initiated the connection
+ *
+ * \return TRUE if there is a saved state, or FALSE otherwise
+ */
+bool openavbAvdeccGetSaveStateInfo(const openavb_tl_data_cfg_t *pListener, U16 *p_flags, U16 *p_talker_unique_id, U8 (*p_talker_entity_id)[8], U8 (*p_controller_entity_id)[8]);
+
+#endif // OPENAVB_AVDECC_READ_INI_PUB_H
diff --git a/lib/avtp_pipeline/avdecc/shutdown_openavb_avdecc.sh b/lib/avtp_pipeline/avdecc/shutdown_openavb_avdecc.sh
new file mode 100755
index 00000000..352e5433
--- /dev/null
+++ b/lib/avtp_pipeline/avdecc/shutdown_openavb_avdecc.sh
@@ -0,0 +1,18 @@
+#! /bin/sh
+#
+# AVB AVDECC clean-up script
+#
+# Only needs to be run if the AVDECC process crashes.
+#
+# Removes resources created/loaded by AVDECC, so that a new
+# instance can run.
+
+IFACES=$(cat /proc/net/dev | grep -- : | cut -d: -f1)
+
+echo "removing AVDECC resources"
+
+killall -s SIGINT openavb_avdecc > /dev/null 2>&1
+killall -s SIGINT openavb_harness > /dev/null 2>&1
+killall -s SIGINT openavb_host > /dev/null 2>&1
+rm -f /tmp/avdecc_msg > /dev/null 2>&1
+