summaryrefslogtreecommitdiff
path: root/lib/avtp_pipeline/platform/Linux/endpoint/openavb_endpoint_osal_maap.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/avtp_pipeline/platform/Linux/endpoint/openavb_endpoint_osal_maap.c')
-rw-r--r--lib/avtp_pipeline/platform/Linux/endpoint/openavb_endpoint_osal_maap.c596
1 files changed, 596 insertions, 0 deletions
diff --git a/lib/avtp_pipeline/platform/Linux/endpoint/openavb_endpoint_osal_maap.c b/lib/avtp_pipeline/platform/Linux/endpoint/openavb_endpoint_osal_maap.c
new file mode 100644
index 00000000..0f754236
--- /dev/null
+++ b/lib/avtp_pipeline/platform/Linux/endpoint/openavb_endpoint_osal_maap.c
@@ -0,0 +1,596 @@
+/*************************************************************************************************************
+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.
+*************************************************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#include "openavb_platform.h"
+#include "openavb_trace.h"
+#include "openavb_maap.h"
+#include "maap_iface.h"
+#include "openavb_list.h"
+#include "openavb_rawsock.h"
+
+// These are used to support saving the MAAP Address
+#include "openavb_endpoint_cfg.h"
+extern openavb_endpoint_cfg_t x_cfg;
+
+#define AVB_LOG_COMPONENT "Endpoint MAAP"
+//#define AVB_LOG_LEVEL AVB_LOG_LEVEL_DEBUG
+#include "openavb_pub.h"
+#include "openavb_log.h"
+
+#define MAAP_DYNAMIC_POOL_BASE 0x91E0F0000000LL /**< MAAP dynamic allocation pool base address - Defined in IEEE 1722-2016 Table B.9 */
+#define MAAP_DYNAMIC_POOL_SIZE 0xFE00 /**< MAAP dynamic allocation pool size - Defined in IEEE 1722-2016 Table B.9 */
+
+
+/*******************************************************************************
+ * MAAP proxies
+ ******************************************************************************/
+
+typedef struct {
+ struct ether_addr destAddr;
+ bool taken;
+} maapAlloc_t;
+
+static maapAlloc_t maapAllocList[MAX_AVB_STREAMS];
+static openavbMaapRestartCb_t *maapRestartCallback = NULL;
+static struct ether_addr *maapPreferredAddress = NULL;
+
+static bool maapRunning = FALSE;
+static pthread_t maapThreadHandle;
+static void* maapThread(void *arg);
+
+enum maapState_t {
+ MAAP_STATE_UNKNOWN,
+ MAAP_STATE_INITIALIZING, // Waiting for initialization
+ MAAP_STATE_REQUESTING, // Waiting address block request
+ MAAP_STATE_CONNECTED, // Have block of addresses
+ MAAP_STATE_RELEASING, // Releasing the block of addresses
+ MAAP_STATE_RELEASED, // Released the block of addresses
+ MAAP_STATE_NOT_AVAILABLE, // MAAP not configured, or freed
+ MAAP_STATE_ERROR
+};
+static enum maapState_t maapState = MAAP_STATE_UNKNOWN;
+static int maapReservationId = 0;
+
+static char maapDaemonPort[6] = {0};
+
+static MUTEX_HANDLE(maapMutex);
+#define MAAP_LOCK() { MUTEX_CREATE_ERR(); MUTEX_LOCK(maapMutex); MUTEX_LOG_ERR("Mutex lock failure"); }
+#define MAAP_UNLOCK() { MUTEX_CREATE_ERR(); MUTEX_UNLOCK(maapMutex); MUTEX_LOG_ERR("Mutex unlock failure"); }
+
+static unsigned long long MaapMacAddrToLongLong(const struct ether_addr *addr)
+{
+ unsigned long long nAddress = 0ull;
+ int i;
+ for (i = 0; i < ETH_ALEN; ++i) {
+ nAddress = (nAddress << 8) | addr->ether_addr_octet[i];
+ }
+ return nAddress;
+}
+
+static void MaapResultToMacAddr(unsigned long long nAddress, struct ether_addr *destAddr)
+{
+ int i;
+ for (i = ETH_ALEN - 1; i >= 0; --i) {
+ destAddr->ether_addr_octet[i] = (U8)(nAddress & 0xFF);
+ nAddress >>= 8;
+ }
+}
+
+static void process_maap_notify(Maap_Notify *mn, int socketfd)
+{
+ assert(mn);
+
+ switch (mn->result)
+ {
+ case MAAP_NOTIFY_ERROR_NONE:
+ /* No error. Don't display anything. */
+ break;
+ case MAAP_NOTIFY_ERROR_REQUIRES_INITIALIZATION:
+ AVB_LOG_ERROR("MAAP is not initialized, so the command cannot be performed.");
+ break;
+ case MAAP_NOTIFY_ERROR_ALREADY_INITIALIZED:
+ AVB_LOG_ERROR("MAAP is already initialized, so the values cannot be changed.");
+ break;
+ case MAAP_NOTIFY_ERROR_RESERVE_NOT_AVAILABLE:
+ AVB_LOG_ERROR("The MAAP reservation is not available, or yield cannot allocate a replacement block. "
+ "Try again with a smaller address block size.");
+ break;
+ case MAAP_NOTIFY_ERROR_RELEASE_INVALID_ID:
+ AVB_LOG_ERROR("The MAAP reservation ID is not valid, so cannot be released or report its status.");
+ break;
+ case MAAP_NOTIFY_ERROR_OUT_OF_MEMORY:
+ AVB_LOG_ERROR("The MAAP application is out of memory.");
+ break;
+ case MAAP_NOTIFY_ERROR_INTERNAL:
+ AVB_LOG_ERROR("The MAAP application experienced an internal error.");
+ break;
+ default:
+ AVB_LOGF_ERROR("The MAAP application returned an unknown error %d.", mn->result);
+ break;
+ }
+
+ switch (mn->kind)
+ {
+ case MAAP_NOTIFY_INITIALIZED:
+ if (mn->result == MAAP_NOTIFY_ERROR_NONE) {
+ AVB_LOGF_DEBUG("MAAP initialized: 0x%012llx-0x%012llx (Size: %d)",
+ (unsigned long long) mn->start,
+ (unsigned long long) mn->start + mn->count - 1,
+ (unsigned int) mn->count);
+
+ // We successfully initialized. Reserve a block of addresses.
+ Maap_Cmd maapcmd;
+ memset(&maapcmd, 0, sizeof(Maap_Cmd));
+ maapcmd.kind = MAAP_CMD_RESERVE;
+ maapcmd.start = 0; // No preferred address
+ maapcmd.count = MAX_AVB_STREAMS;
+ if (maapPreferredAddress != NULL) {
+ // Suggest the addresses from the previous time this application was run.
+ maapcmd.start = MaapMacAddrToLongLong(maapPreferredAddress);
+ AVB_LOGF_DEBUG("MAAP Preferred Address: 0x%012llx", maapcmd.start);
+ }
+ if (send(socketfd, (char *) &maapcmd, sizeof(Maap_Cmd), 0) < 0)
+ {
+ /* Something went wrong. Abort! */
+ AVB_LOGF_ERROR("MAAP: Error %d writing to network socket (%s)", errno, strerror(errno));
+ maapState = MAAP_STATE_ERROR;
+ } else {
+ maapState = MAAP_STATE_REQUESTING;
+ }
+ } else {
+ AVB_LOGF_ERROR("MAAP previously initialized to 0x%012llx-0x%012llx (Size: %d)",
+ (unsigned long long) mn->start,
+ (unsigned long long) mn->start + mn->count - 1,
+ (unsigned int) mn->count);
+ maapState = MAAP_STATE_ERROR;
+ }
+ break;
+ case MAAP_NOTIFY_ACQUIRING:
+ if (mn->result == MAAP_NOTIFY_ERROR_NONE) {
+ AVB_LOGF_DEBUG("MAAP address range %d querying: 0x%012llx-0x%012llx (Size %d)",
+ mn->id,
+ (unsigned long long) mn->start,
+ (unsigned long long) mn->start + mn->count - 1,
+ mn->count);
+ } else {
+ AVB_LOGF_ERROR("MAAP unknown address range %d acquisition error", mn->id);
+ maapState = MAAP_STATE_ERROR;
+ }
+ break;
+ case MAAP_NOTIFY_ACQUIRED:
+ if (mn->result == MAAP_NOTIFY_ERROR_NONE) {
+ AVB_LOGF_INFO("MAAP address range %d acquired: 0x%012llx-0x%012llx (Size %d)",
+ mn->id,
+ (unsigned long long) mn->start,
+ (unsigned long long) mn->start + mn->count - 1,
+ mn->count);
+
+ // Update the stored addresses.
+ MAAP_LOCK();
+ int i = 0;
+ for (i = 0; i < mn->count && i < MAX_AVB_STREAMS; i++) {
+ MaapResultToMacAddr(mn->start + i, &(maapAllocList[i].destAddr));
+ if (maapAllocList[i].taken && maapRestartCallback) {
+ // Use the callback to notify that a change has occurred.
+ MAAP_UNLOCK();
+ maapRestartCallback(&(maapAllocList[i]), &(maapAllocList[i].destAddr));
+ MAAP_LOCK();
+ }
+ }
+ MAAP_UNLOCK();
+
+ // Save the address so we can request it in the future.
+ if (maapPreferredAddress != NULL) {
+ struct ether_addr assignedAddress;
+ MaapResultToMacAddr((unsigned long long) mn->start, &assignedAddress);
+ if (memcmp(maapPreferredAddress, &assignedAddress, sizeof(struct ether_addr)) != 0) {
+ // Save the updated settings. Done immediately, so they won't get lost on device reboot.
+ memcpy(maapPreferredAddress, &assignedAddress, sizeof(struct ether_addr));
+ openavbSaveConfig(DEFAULT_SAVE_INI_FILE, &x_cfg);
+ }
+ }
+
+ // We now have addresses we can use.
+ maapReservationId = mn->id;
+ maapState = MAAP_STATE_CONNECTED;
+ } else if (mn->id != -1) {
+ AVB_LOGF_ERROR("MAAP address range %d of size %d not acquired",
+ mn->id, mn->count);
+ maapState = MAAP_STATE_ERROR;
+ } else {
+ AVB_LOGF_ERROR("MAAP address range of size %d not acquired",
+ mn->count);
+ maapState = MAAP_STATE_ERROR;
+ }
+ break;
+ case MAAP_NOTIFY_RELEASED:
+ if (mn->result == MAAP_NOTIFY_ERROR_NONE) {
+ AVB_LOGF_DEBUG("MAAP address range %d released: 0x%012llx-0x%012llx (Size %d)",
+ mn->id,
+ (unsigned long long) mn->start,
+ (unsigned long long) mn->start + mn->count - 1,
+ mn->count);
+ maapState = MAAP_STATE_RELEASED;
+ } else {
+ AVB_LOGF_WARNING("MAAP address range %d not released",
+ mn->id);
+ }
+ break;
+ case MAAP_NOTIFY_STATUS:
+ if (mn->result == MAAP_NOTIFY_ERROR_NONE) {
+ AVB_LOGF_DEBUG("MAAP ID %d is address range 0x%012llx-0x%012llx (Size %d)",
+ mn->id,
+ (unsigned long long) mn->start,
+ (unsigned long long) mn->start + mn->count - 1,
+ mn->count);
+ } else {
+ AVB_LOGF_DEBUG("MAAP ID %d is not valid",
+ mn->id);
+ }
+ break;
+ case MAAP_NOTIFY_YIELDED:
+ if (mn->result != MAAP_NOTIFY_ERROR_REQUIRES_INITIALIZATION && mn->result != MAAP_NOTIFY_ERROR_RELEASE_INVALID_ID) {
+ if (mn->result != MAAP_NOTIFY_ERROR_NONE) {
+ AVB_LOGF_ERROR("MAAP Address range %d yielded: 0x%012llx-0x%012llx (Size %d). A new address range will not be allocated.",
+ mn->id,
+ (unsigned long long) mn->start,
+ (unsigned long long) mn->start + mn->count - 1,
+ mn->count);
+ maapState = MAAP_STATE_ERROR;
+ }
+ else {
+ AVB_LOGF_WARNING("MAAP Address range %d yielded: 0x%012llx-0x%012llx (Size %d)",
+ mn->id,
+ (unsigned long long) mn->start,
+ (unsigned long long) mn->start + mn->count - 1,
+ mn->count);
+ }
+ } else {
+ AVB_LOGF_ERROR("ID %d is not valid", mn->id);
+ }
+ break;
+ default:
+ AVB_LOGF_ERROR("MAAP notification type %d not recognized", mn->kind);
+ break;
+ }
+}
+
+
+/* Local function to interact with the MAAP daemon. */
+static void* maapThread(void *arg)
+{
+ int socketfd;
+ struct addrinfo hints, *ai, *p;
+ int ret;
+
+ fd_set master, read_fds;
+ int fdmax;
+
+ char recvbuffer[200];
+ int recvbytes;
+ Maap_Cmd maapcmd;
+
+ AVB_LOG_DEBUG("MAAP Thread Starting");
+
+ /* Create a localhost socket. */
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = 0;
+ if ((ret = getaddrinfo("localhost", maapDaemonPort, &hints, &ai)) != 0) {
+ AVB_LOGF_ERROR("getaddrinfo failure %s", gai_strerror(ret));
+ maapState = MAAP_STATE_ERROR;
+ return NULL;
+ }
+
+ for(p = ai; p != NULL; p = p->ai_next) {
+ socketfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
+ if (socketfd == -1) {
+ continue;
+ }
+ ret = connect(socketfd, p->ai_addr, p->ai_addrlen);
+ if (ret == -1) {
+ close(socketfd);
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ freeaddrinfo(ai);
+
+ if (p == NULL) {
+ AVB_LOGF_ERROR("MAAP: Unable to connect to the daemon, error %d (%s)", errno, strerror(errno));
+ maapState = MAAP_STATE_ERROR;
+ return NULL;
+ }
+
+ if (fcntl(socketfd, F_SETFL, O_NONBLOCK) < 0)
+ {
+ AVB_LOG_ERROR("MAAP: Could not set the socket to non-blocking");
+ close(socketfd);
+ maapState = MAAP_STATE_ERROR;
+ return NULL;
+ }
+
+ FD_ZERO(&read_fds);
+ FD_ZERO(&master);
+ FD_SET(STDIN_FILENO, &master);
+ FD_SET(socketfd, &master);
+ fdmax = socketfd;
+
+ // Initialize the MAAP daemon.
+ // We will request a block of addresses when we get a response to the initialization.
+ maapState = MAAP_STATE_INITIALIZING;
+ memset(&maapcmd, 0, sizeof(Maap_Cmd));
+ maapcmd.kind = MAAP_CMD_INIT;
+ maapcmd.start = MAAP_DYNAMIC_POOL_BASE;
+ maapcmd.count = MAAP_DYNAMIC_POOL_SIZE;
+ if (send(socketfd, (char *) &maapcmd, sizeof(Maap_Cmd), 0) < 0)
+ {
+ /* Something went wrong. Abort! */
+ AVB_LOGF_ERROR("MAAP: Error %d writing to network socket (%s)", errno, strerror(errno));
+ maapState = MAAP_STATE_ERROR;
+ return NULL;
+ }
+
+
+ /*
+ * Main event loop
+ */
+
+ while (maapRunning || maapState <= MAAP_STATE_CONNECTED)
+ {
+ if (!maapRunning && maapState == MAAP_STATE_CONNECTED)
+ {
+ // Tell the MAAP daemon to release the addresses.
+ memset(&maapcmd, 0, sizeof(Maap_Cmd));
+ maapcmd.kind = MAAP_CMD_RELEASE;
+ maapcmd.id = maapReservationId;
+ if (send(socketfd, (char *) &maapcmd, sizeof(Maap_Cmd), 0) > 0)
+ {
+ maapState = MAAP_STATE_RELEASING;
+ // Use the wait below to give the daemon time to respond.
+ }
+ else
+ {
+ maapState = MAAP_STATE_NOT_AVAILABLE;
+ break;
+ }
+ }
+
+ /* Wait for something to happen. */
+ struct timeval tv_timeout = { 1, 0 };
+ read_fds = master;
+ ret = select(fdmax+1, &read_fds, NULL, NULL, &tv_timeout);
+ if (ret < 0)
+ {
+ AVB_LOGF_ERROR("MAAP: select() error %d (%s)", errno, strerror(errno));
+ maapState = MAAP_STATE_ERROR;
+ break;
+ }
+
+ /* Handle any responses received. */
+ if (FD_ISSET(socketfd, &read_fds))
+ {
+ while ((recvbytes = recv(socketfd, recvbuffer, sizeof(Maap_Notify), 0)) > 0)
+ {
+ recvbuffer[recvbytes] = '\0';
+
+ /* Process the response data (will be binary). */
+ if (recvbytes == sizeof(Maap_Notify))
+ {
+ process_maap_notify((Maap_Notify *) recvbuffer, socketfd);
+ }
+ else
+ {
+ AVB_LOGF_WARNING("MAAP: Received unexpected response of size %d", recvbytes);
+ }
+ }
+ if (recvbytes == 0)
+ {
+ /* The MAAP daemon closed the connection. Assume it shut down, and we should too. */
+ // AVDECC_TODO: Should we try to reconnect?
+ AVB_LOG_ERROR("MAAP daemon exited.");
+ maapState = MAAP_STATE_ERROR;
+ break;
+ }
+ if (recvbytes < 0 && errno != EWOULDBLOCK)
+ {
+ /* Something went wrong. Abort! */
+ AVB_LOGF_ERROR("MAAP: Error %d reading from network socket (%s)", errno, strerror(errno));
+ maapState = MAAP_STATE_ERROR;
+ break;
+ }
+ }
+ }
+
+ if (maapState < MAAP_STATE_NOT_AVAILABLE) {
+ maapState = MAAP_STATE_NOT_AVAILABLE;
+ }
+
+ close(socketfd);
+
+ AVB_LOG_DEBUG("MAAP Thread Done");
+ return NULL;
+}
+
+bool openavbMaapInitialize(const char *ifname, unsigned int maapPort, struct ether_addr *maapPrefAddr, openavbMaapRestartCb_t* cbfn)
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_MAAP);
+
+ // Save the supplied callback function.
+ maapRestartCallback = cbfn;
+ maapPreferredAddress = maapPrefAddr;
+
+ MUTEX_ATTR_HANDLE(mta);
+ MUTEX_ATTR_INIT(mta);
+ MUTEX_ATTR_SET_TYPE(mta, MUTEX_ATTR_TYPE_DEFAULT);
+ MUTEX_ATTR_SET_NAME(mta, "maapMutex");
+ MUTEX_CREATE_ERR();
+ MUTEX_CREATE(maapMutex, mta);
+ MUTEX_LOG_ERR("Could not create/initialize 'maapMutex' mutex");
+
+ // Default to using addresses from the MAAP locally administered Pool.
+ int i = 0;
+ U8 destAddr[ETH_ALEN] = {0x91, 0xe0, 0xf0, 0x00, 0xfe, 0x80};
+ for (i = 0; i < MAX_AVB_STREAMS; i++) {
+ memcpy(maapAllocList[i].destAddr.ether_addr_octet, destAddr, ETH_ALEN);
+ maapAllocList[i].taken = false;
+ destAddr[5] += 1;
+ }
+
+ if (maapPort == 0) {
+ maapState = MAAP_STATE_NOT_AVAILABLE;
+ }
+ else {
+ maapState = MAAP_STATE_UNKNOWN;
+ sprintf(maapDaemonPort, "%u", maapPort);
+
+ maapRunning = TRUE;
+ int err = pthread_create(&maapThreadHandle, NULL, maapThread, NULL);
+ if (err) {
+ maapRunning = FALSE;
+ maapState = MAAP_STATE_ERROR;
+ AVB_LOGF_ERROR("Failed to start MAAP thread: %s", strerror(err));
+ }
+ }
+
+ AVB_TRACE_EXIT(AVB_TRACE_MAAP);
+ return true;
+}
+
+void openavbMaapFinalize()
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_MAAP);
+
+ maapRestartCallback = NULL;
+ maapPreferredAddress = NULL;
+
+ if (maapRunning) {
+ // Stop the MAAP thread.
+ maapRunning = FALSE;
+ pthread_join(maapThreadHandle, NULL);
+ }
+
+ MUTEX_CREATE_ERR();
+ MUTEX_DESTROY(maapMutex);
+ MUTEX_LOG_ERR("Error destroying mutex");
+
+ AVB_TRACE_EXIT(AVB_TRACE_MAAP);
+}
+
+bool openavbMaapDaemonAvailable(void)
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_MAAP);
+
+ if (!maapRunning) {
+ AVB_TRACE_EXIT(AVB_TRACE_MAAP);
+ return FALSE;
+ }
+
+ // Wait up to 10 seconds for the daemon to give us a block of addresses.
+ int j;
+ for (j = 0; j < 10 * 1000 / 50 && maapState < MAAP_STATE_CONNECTED; ++j) {
+ AVB_LOG_DEBUG("Waiting for MAAP Daemon status");
+ SLEEP_MSEC(50);
+ }
+
+ if (maapState != MAAP_STATE_CONNECTED) {
+ if (maapState != MAAP_STATE_NOT_AVAILABLE) {
+ AVB_LOG_WARNING("MAAP Daemon not available. Fallback multicast address allocation will be used.");
+ }
+ AVB_TRACE_EXIT(AVB_TRACE_MAAP);
+ return FALSE;
+ }
+
+ AVB_TRACE_EXIT(AVB_TRACE_MAAP);
+ return TRUE;
+}
+
+void* openavbMaapAllocate(int count, /* out */ struct ether_addr *addr)
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_MAAP);
+ assert(count == 1);
+
+ // Wait up to 10 seconds for the daemon to give us a block of addresses.
+ int j;
+ for (j = 0; j < 10 * 1000 / 50 && maapState < MAAP_STATE_CONNECTED; ++j) {
+ AVB_LOG_DEBUG("Waiting for MAAP Daemon status");
+ SLEEP_MSEC(50);
+ }
+
+ MAAP_LOCK();
+
+ // Find the next non-allocated address.
+ int i = 0;
+ while (i < MAX_AVB_STREAMS && maapAllocList[i].taken) {
+ i++;
+ }
+
+ // Allocate an address from the pool.
+ if (i < MAX_AVB_STREAMS) {
+ maapAllocList[i].taken = true;
+ memcpy(addr, maapAllocList[i].destAddr.ether_addr_octet, sizeof(struct ether_addr));
+ AVB_LOGF_INFO("Allocated MAAP address " ETH_FORMAT, ETH_OCTETS(addr->ether_addr_octet));
+
+ MAAP_UNLOCK();
+
+ AVB_TRACE_EXIT(AVB_TRACE_MAAP);
+ return &maapAllocList[i];
+ }
+
+ MAAP_UNLOCK();
+
+ AVB_LOG_ERROR("All MAAP addresses already allocated");
+ AVB_TRACE_EXIT(AVB_TRACE_MAAP);
+ return NULL;
+}
+
+void openavbMaapRelease(void* handle)
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_MAAP);
+
+ MAAP_LOCK();
+ maapAlloc_t *elem = handle;
+ elem->taken = false;
+ AVB_LOGF_DEBUG("Freed MAAP address " ETH_FORMAT, ETH_OCTETS(elem->destAddr.ether_addr_octet));
+ MAAP_UNLOCK();
+
+ AVB_TRACE_EXIT(AVB_TRACE_MAAP);
+}