/*
 * Video On Demand Samples
 *
 * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * You may also obtain this software under a propriety license from Microchip.
 * Please contact Microchip for further information.
 *
 */

#include <stdint.h>
#include <stddef.h>
#include "SafeVector.h"
#include "Network.h"
#include "NetworkDevice.h"
#include "DriverConfiguration.h"
#include "MacAddr.h"
#include "Board.h"
#include "Console.h"
#include "NodeDatabase.h"

#define PRINT_ALL_INFOS()

void CNetwork::OnSync( void *source, bool isSynced )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    ConsolePrintf( PRIO_MEDIUM, "CNetwork::OnSync(deviceInstance:%d, isSynced:%d\n", devInstance, isSynced );

    if( isSynced )
    {
        device->SetNetstate( NetworkState_Unknown );
        device->AttachV3();
    }
}

void CNetwork::OnNetworkState( void *source, bool mpValChanged, bool systemNotOk, bool mostAvailable,
    uint8_t availableSubState, uint8_t availableTransition, uint16_t nodeAddress, uint8_t nodePos, uint8_t maxPos,
    uint16_t packetBW )
{
    if( NULL == source || !allowNetworkRun )
        return;
    if (0x100 != nodeAddress && 0x1 != nodeAddress && 0xFFFF != nodeAddress)
        return;
    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    ConsolePrintf( PRIO_HIGH,
        YELLOW"CNetwork::OnNetworkState(inst:%d, mpChanged:%d, " \
        "notOk:%d, available:%d, sub:0x%X, trans:0x%X, address:0x%X, pos:%d, " \
        "mpr:%d, bw:%d"RESETCOLOR"\n", devInstance, mpValChanged,
        systemNotOk, mostAvailable, availableSubState, availableTransition,
        nodeAddress, nodePos, maxPos, packetBW );

    NetworkState_t curState = device->GetNetState();
    if (NetworkState_ShutdownInProgress == curState)
    {
        ConsolePrintf( PRIO_HIGH, "Ignoring OnNetworkState, because shutdown is still in progress\n");
        return;
    }
    
    for( uint32_t i = 0; i < allListeners.Size(); i++ )
    {
        allListeners[i]->OnNetworkState(devInstance, mostAvailable, maxPos, packetBW);
    }
    
    if( mostAvailable )
    {
        if( NetworkState_Available ==  curState )
        {
            if( 0x10 == availableSubState )
            {
                ConsolePrintf( PRIO_ERROR, RED"Unlock detected, shutting down MOST."RESETCOLOR"\n" );
                device->SetNetstate( NetworkState_ShutdownInProgress );
                device->ClearAllPendingActions();
                device->MostNetworkShutdownV3();
                return;
            }
            else if( mpValChanged && 0xFF != maxPos )
            {
                ConsolePrintf( PRIO_ERROR, RED"MPR change detected, shutting down MOST."RESETCOLOR"\n" );
                device->SetNetstate( NetworkState_ShutdownInProgress );
                device->ClearAllPendingActions();
                device->MostNetworkShutdownV3();
                return;
            }
            else if( 0x11 == availableSubState )
            {
                ConsolePrintf( PRIO_MEDIUM, YELLOW"CNetwork::OnNetworkState was called with the same mostAvailable (%d) value as before, ignoring.."RESETCOLOR"\n",
                    mostAvailable );
                return;
            }
        }
    }
    else
    {
        if( 0x02 == availableSubState )
        {
            ConsolePrintf( PRIO_HIGH, YELLOW"INIC enters Ring Break Diagnosis mode!"RESETCOLOR"\n" );
            device->GetRingBreakResultV3( 1, 0 );
        }
        if( NetworkState_Unavailable == curState )
        {
            ConsolePrintf( PRIO_MEDIUM, YELLOW"CNetwork::OnNetworkState was called with the same mostAvailable (%d) value as before, ignoring.."RESETCOLOR"\n",
                mostAvailable );
            return;
        }
    }

    bool isTimingMaster = device->IsTimingMaster();
    uint32_t asyncBandwidth = device->GetAsyncBandwidth();

    if( !mostAvailable )
    {
        device->SetNetstate( NetworkState_Unavailable );
        device->ClearAllPendingActions();
        DestroyAllResources( device, 0x1 );
        //Clear all existing connection information for this MOST instance
        while( true )
        {
            bool deleted = false;
            for( uint16_t i = 0; i < CNodeEntry::GetAmountOfNodeEntries(); i++ )
            {
                CNodeEntry *entry = CNodeEntry::GetNodeEntry( i );
                if( NULL == entry )
                    continue;
                if( devInstance == entry->deviceInstance )
                {
                    for( uint16_t j = 0; j < entry->GetAmountOfConnections(); j++ )
                    {
                        CNodeConnectionEntry *connection = entry->GetConnectionByIndex( j );
                        RaiseUnavailable( connection );
                    }
                    CNodeEntry::DeleteNodeEntry( i );
                    deleted = true;
                    break;
                }
            }
            if( !deleted )
                break;
        }
        if( 2 == device->GetDeviceApi() )
        {
            ConsolePrintf( PRIO_ERROR, RED"Error, device API V2 is not supported by "\
                "this version of NetworkManager!"RESETCOLOR );
        }
        else if( 3 == device->GetDeviceApi() && isTimingMaster )
        {
            ConsolePrintf( PRIO_MEDIUM, "CNetwork::OnNetworkState calling MostNetworkStartupV3\n" );
            device->MostNetworkStartupV3( 0xFFFF, asyncBandwidth );
        }
		else 
        {
            ConsolePrintf( PRIO_ERROR, RED"Error, device API '%d' is not supported by "\
                "this version of NetworkManager!"RESETCOLOR, device->GetDeviceApi() );
        }
    }
    else if (asyncBandwidth != packetBW)
    {
        ConsolePrintf( PRIO_ERROR, RED"Packet Bandwidth does not match."\
            " Expected:%d Is:%d, forcing MOST shutdown"RESETCOLOR"\n", asyncBandwidth, packetBW );
        device->SetNetstate( NetworkState_ShutdownInProgress );
        device->MostNetworkShutdownV3();
    }
    else if( !systemNotOk
        && ( maxPos <= 64 )
        && ( packetBW <= 372 )
        && ( 0x11 == availableSubState ) )
    {
        //Everything is ok. Start query network devices
        device->SetNetstate( NetworkState_Available );
        if( isTimingMaster )
        {
            device->ToggleNotOk();
        }
        device->GetGroupAddresses( maxPos );
    }
}

void CNetwork::OnNetworkStartupV3( void *source, bool success )
{
    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    if( success )
    {
        ConsolePrintf( PRIO_MEDIUM, GREEN"CNetwork::OnNetworkStartupV3 success!"RESETCOLOR"\n" );
    }
    else
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnNetworkStartupV3 failed, retrying.."RESETCOLOR"\n" );
        device->ScriptPause(500);
        device->MostNetworkStartupV3();
    }
}

void CNetwork::OnNetworkShutdownV3( void *source, bool success )
{
    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    if( success )
    {
        ConsolePrintf( PRIO_HIGH, GREEN"CNetwork::OnNetworkShutdownV2 success"RESETCOLOR"\n" );
    }
    else
    {
        ConsolePrintf( PRIO_ERROR, RED"CNetwork::OnNetworkShutdownV2 failed"RESETCOLOR"\n" );
    }
    device->SetNetstate( NetworkState_Unknown );
    device->InicUnsychronizeV3();
}

void CNetwork::OnMostDeviceType( void *source, bool success, uint16_t nodeAddress, uint16_t deviceType )
{
    if( NULL == source )
        return;
    if( nodeAddress >= 0x400 && nodeAddress <= 0x4FF )
        nodeAddress = nodeAddress - 0x300;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnMostDeviceType reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddress );
        ShutdownMostBecauseOfErrors( device );
        return;
    }
    ConsolePrintf( PRIO_MEDIUM, "CNetwork::OnMostDeviceType(deviceInstance:%d, nodeAddress:0x%X, deviceType: 0x%X)\n",
        devInstance, nodeAddress, deviceType );

    CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddress );
    sem_wait( &vodXmlMutex );
    if( ( NULL == entry ) || ( NULL == vodXml ) )
    {
        sem_post( &vodXmlMutex );
        return;
    }
    entry->deviceType = deviceType;
    CSafeVector<CChannelConfiguration *> allChannels;
    uint32_t apiVer = vodXml->GetDeviceApi( deviceType );
    
    if( 0xFFFFFFFF == apiVer )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnMostDeviceType reports unknown API version '%d' for"\
            " device 0x%X with node address 0x%X, please check GroupAddress in ConfigString or edit configuration file"\
            RESETCOLOR"\n", apiVer, deviceType, nodeAddress );
        sem_post( &vodXmlMutex );
        RaiseUknownConnection( devInstance, nodeAddress, EP_Unknown );
        return;
    }
    else if( 2 == apiVer || apiVer > 3 )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnMostDeviceType reports API version '%d' for"\
            " device 0x%X with node address 0x%X, this is not longer supported by this version of NetworkManager"\
            RESETCOLOR"\n", apiVer, deviceType, nodeAddress );
        sem_post( &vodXmlMutex );
        RaiseUknownConnection( devInstance, nodeAddress, EP_Unknown );
        return;
    }

    //Set MAC address regardless if set permanently or not. This MAC address contains MOST specific informations.
    //This is necessary, because the bytes in the MAC address are used to identify the streams in the multiplexer.
    CMacAddr *macAddress = SetMacAddress( device, devInstance, nodeAddress, apiVer );
    if( NULL != macAddress )
    {
        if( NULL != entry->macAddress )
        {
            CMacAddr *temp = entry->macAddress;
            entry->macAddress = macAddress;
            delete temp;
        }
        else
        {
            entry->macAddress = macAddress;
        }
        for( uint16_t i = 0; i < entry->GetAmountOfConnections(); i++ )
        {
            CNodeConnectionEntry *connection = entry->GetConnectionByIndex( i );
            if( NULL != connection )
            {
                RaiseAvailable( connection );
            }
        }
    }
    else
    {
        ConsolePrintf( PRIO_ERROR, RED"Setting MAC address failed!"RESETCOLOR"\n" );
        RaiseUknownConnection( devInstance, nodeAddress, EP_Unknown );
    }

    if( vodXml->GetChannelConfigurations( deviceType, allChannels ) )
    {
        if( 0 == allChannels.Size() )
        {
            RaiseUknownConnection( devInstance, nodeAddress, EP_Unused );
        }
        else
            for( uint32_t i = 0; i < allChannels.Size(); i++ )
            {
                CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( allChannels[i]->channelId, true );
                if( NULL == connection->channelConfig )
                {
                    connection->channelConfig = allChannels[i];
                }

                if( 1 == apiVer )
                {
                    /*------------------------------------*/
                    /*-        INIC API VERSION 1         */
                    /*------------------------------------*/

                    if( ( PORT_MLB == connection->channelConfig->inSocket.port )
                        || ( PORT_MLB == connection->channelConfig->outSocket.port ) )
                    {
                        EPDirection_t direction = EPDIR_Unknown;
                        CSocketConfiguration *conf = NULL;
                        if( PORT_MLB == connection->channelConfig->inSocket.port )
                        {
                            if( connection->inSocketState != NodeConnection_NotUsed )
                                continue;
                            connection->inSocketState = NodeConnection_Pending_Up;
                            direction = EPDIR_IN;
                            conf = &connection->channelConfig->inSocket;
                        }
                        else
                        {
                            if( connection->outSocketState != NodeConnection_NotUsed )
                                continue;
                            connection->outSocketState = NodeConnection_Pending_Up;
                            direction = EPDIR_OUT;
                            conf = &connection->channelConfig->outSocket;
                        }
                        if( !entry->isMlbPortOpened )
                        {
                            entry->isMlbPortOpened = true;
                            device->OpenMlbV1( nodeAddress, vodXml->GetDeviceMlbPortSpeed( deviceType ) );
                        }
                        if( 0xFFFFFFFF == conf->splittedOffset )
                        {
                            //Normal socket is used
                            device->CreateMlbSocketV1( nodeAddress, conf->type, direction, conf->address,
                                conf->blockWidth, allChannels[i]->channelId );
                        }
                        else
                        {
                            //Enhanced (Splitted) Sockets are used
                            device->CreateSplittedMlbSocketV1( nodeAddress, conf->type, direction, conf->address,
                                conf->blockWidth, conf->splittedOffset, conf->subbufferSize,
                                allChannels[i]->channelId );
                        }
                    }
                    if( ( PORT_TSI == connection->channelConfig->inSocket.port )
                        || ( PORT_TSI == connection->channelConfig->outSocket.port ) )
                    {
                        EPDirection_t direction = EPDIR_Unknown;
                        CSocketConfiguration *conf = NULL;
                        if( PORT_TSI == connection->channelConfig->inSocket.port )
                        {
                            if( connection->inSocketState != NodeConnection_NotUsed )
                                continue;
                            connection->inSocketState = NodeConnection_Pending_Up;
                            direction = EPDIR_IN;
                            conf = &connection->channelConfig->inSocket;
                        }
                        else
                        {
                            if( connection->outSocketState != NodeConnection_NotUsed )
                                continue;
                            connection->outSocketState = NodeConnection_Pending_Up;
                            direction = EPDIR_OUT;
                            conf = &connection->channelConfig->outSocket;
                        }
                        if( !entry->isTsiPortOpened )
                        {
                            entry->isTsiPortOpened = true;
                            device->OpenTsiV1( nodeAddress, conf->tsiConfig.tsiPortInstance, 
                                    conf->tsiConfig.tsiPortMode );
                        }
                        device->CreateTsiSocketV1( nodeAddress, conf->tsiConfig.tsiPortInstance, conf->type, direction,
                                conf->blockWidth, allChannels[i]->channelId );
                    }
                    if( ( PORT_I2S == connection->channelConfig->inSocket.port )
                        || ( PORT_I2S == connection->channelConfig->outSocket.port ) )
                    {
                        EPDirection_t direction = EPDIR_Unknown;
                        CSocketConfiguration *conf = NULL;
                        if( PORT_I2S == connection->channelConfig->inSocket.port )
                        {
                            if( connection->inSocketState != NodeConnection_NotUsed )
                                continue;
                            connection->inSocketState = NodeConnection_Pending_Up;
                            direction = EPDIR_IN;
                            conf = &connection->channelConfig->inSocket;
                        }
                        else
                        {
                            if( connection->outSocketState != NodeConnection_NotUsed )
                                continue;
                            connection->outSocketState = NodeConnection_Pending_Up;
                            direction = EPDIR_OUT;
                            conf = &connection->channelConfig->outSocket;
                        }
                        if( !entry->isI2SPortOpened )
                        {
                            if( V1I2sClockModeUnknown != conf->i2sConfig.portClkDriveModeV1
                                && V1I2sDataFormatUnknown != conf->i2sConfig.streamingDataFormatV1 )
                            {
                                entry->isI2SPortOpened = true;
                                device->OpenStreamPortV1( nodeAddress, conf->i2sConfig.portClkDriveModeV1,
                                    conf->i2sConfig.portOptionV1, conf->i2sConfig.streamingDataFormatV1,
                                    allChannels[i]->channelId );
                            }
                        }
                        if( 0xFFFFFFFF == conf->splittedOffset )
                        {
                            //Normal socket is used
                        device->CreateStreamSocketV1( nodeAddress, direction, conf->blockWidth, conf->i2sConfig.pinV1,
                            allChannels[i]->channelId );
                    }
                        else
                        {
                            //Enhanced (Splitted) Sockets are used
                            device->CreateSplittedStreamSocketV1( nodeAddress, direction,
                                conf->blockWidth, conf->splittedOffset, conf->subbufferSize, conf->i2sConfig.pinV1,
                                allChannels[i]->channelId );
                        }
                        
                    }

                    if( PORT_MOST == connection->channelConfig->outSocket.port )
                    {
                        //Open MOST in case of out-connections
                        if( connection->outSocketState != NodeConnection_NotUsed )
                            continue;
                        connection->outSocketState = NodeConnection_Pending_Up;
                        CSocketConfiguration *conf = &connection->channelConfig->outSocket;
                        device->CreateMostSocketV1( nodeAddress, conf->type, EPDIR_OUT, conf->address,
                            conf->blockWidth, allChannels[i]->channelId );
                    }
                    else if( ( PORT_MOST == connection->channelConfig->inSocket.port )
                        && ( 0xFFFFFFFF != connection->channelConfig->inSocket.address ) )
                    {
                        //Or open MOST in case of in-connections with set connection label
                        if( connection->inSocketState != NodeConnection_NotUsed )
                            continue;
                        connection->inSocketState = NodeConnection_Pending_Up;
                        CSocketConfiguration *conf = &connection->channelConfig->inSocket;
                        ConsolePrintf( PRIO_MEDIUM,
                            "Creating MOST socket for preconfigured Connection Label %d (0x%X)\n", conf->address,
                            conf->address );
                        device->CreateMostSocketV1( nodeAddress, conf->type, EPDIR_IN, conf->address, conf->blockWidth,
                            allChannels[i]->channelId );
                    }
                }
                else if(  3 == apiVer )
                {
                    /*--------------------------------------------*/
                    /*-INIC API VERSION 3 (OS81118-D-Rev FW2.3.0) */
                    /*--------------------------------------------*/
                    if (0 == i)
                        device->GetDeviceVersion( nodeAddress );
                    
                    //Destroy all resources
                    if( !entry->isUsbPortOpened && ( 0x1 != nodeAddress ) )
                    {
                        entry->isUsbPortOpened = true;
                        device->DeviceSyncV3( nodeAddress, true );
                    }

                    if( ( PORT_USB == connection->channelConfig->inSocket.port )
                        || ( PORT_USB == connection->channelConfig->outSocket.port ) )
                    {
                        EPDirection_t direction = EPDIR_Unknown;
                        CSocketConfiguration *conf = NULL;
                        if( PORT_USB == connection->channelConfig->inSocket.port )
                        {
                            if( connection->inSocketState != NodeConnection_NotUsed )
                                continue;
                            connection->inSocketState = NodeConnection_Pending_Up;
                            direction = EPDIR_IN;
                            conf = &connection->channelConfig->inSocket;
                        }
                        else
                        {
                            if( connection->outSocketState != NodeConnection_NotUsed )
                                continue;
                            connection->outSocketState = NodeConnection_Pending_Up;
                            direction = EPDIR_OUT;
                            conf = &connection->channelConfig->outSocket;
                        }
                        if( 0xFFFFFFFF == conf->splittedOffset )
                        {
                            //No Splitter / No Combiner
                            device->CreateUsbSocketV3( nodeAddress, conf->type, direction, conf->address,
                                conf->packetsPerTransaction, allChannels[i]->channelId );
                        }
                        else
                        {
                            //Splitter or Combiner is used
                            //Do not create multiple USB sockets for a single Splitter / Combiner connection
                            bool skip = false;
                            for( uint16_t j = 0; j < entry->GetAmountOfConnections(); j++ )
                            {
                                CNodeConnectionEntry *checkConn = entry->GetConnectionByIndex( j );
                                CSocketConfiguration *checkConf = NULL;
                                if( EPDIR_IN == direction )
                                    checkConf = &checkConn->channelConfig->inSocket;
                                else
                                    checkConf = &checkConn->channelConfig->outSocket;

                                if( ( checkConf != conf ) && ( conf->address == checkConf->address ) )
                                {
                                    skip = true;
                                    break;
                                }
                            }
                            RaiseAvailable( connection );
                            if( !skip )
                                device->CreateSplittedUsbSocketV3( nodeAddress, conf->type, direction, conf->address,
                                    conf->packetsPerTransaction, conf->subbufferSize, allChannels[i]->channelId );
                        }
                    }
                    if( ( PORT_MLB == connection->channelConfig->inSocket.port )
                        || ( PORT_MLB == connection->channelConfig->outSocket.port ) )
                    {
                        EPDirection_t direction = EPDIR_Unknown;
                        CSocketConfiguration *conf = NULL;
                        if( PORT_MLB == connection->channelConfig->inSocket.port )
                        {
                            if( connection->inSocketState != NodeConnection_NotUsed )
                                continue;
                            connection->inSocketState = NodeConnection_Pending_Up;
                            direction = EPDIR_IN;
                            conf = &connection->channelConfig->inSocket;
                        }
                        else
                        {
                            if( connection->outSocketState != NodeConnection_NotUsed )
                                continue;
                            connection->outSocketState = NodeConnection_Pending_Up;
                            direction = EPDIR_OUT;
                            conf = &connection->channelConfig->outSocket;
                        }
                        if( !entry->isMlbPortOpened )
                        {
                            entry->isMlbPortOpened = true;
                            device->OpenMlbV3( nodeAddress, vodXml->GetDeviceMlbPortSpeed( deviceType ) );
                        }
                        if( 0xFFFFFFFF == conf->splittedOffset )
                        {
                            //No Splitter / No Combiner
                            device->CreateMlbSocketV3( nodeAddress, ( uint16_t )0x0A00, //Const value for first instance of MLB bus
                                conf->type, direction, conf->address, conf->blockWidth, allChannels[i]->channelId );
                        }
                        else
                        {
                            //Splitter or Combiner is used
                            //Do not create multiple MLB sockets for a single Splitter / Combiner connection
                            bool skip = false;
                            for( uint16_t j = 0; j < entry->GetAmountOfConnections(); j++ )
                            {
                                CNodeConnectionEntry *checkConn = entry->GetConnectionByIndex( j );
                                CSocketConfiguration *checkConf = NULL;
                                if( EPDIR_IN == direction )
                                    checkConf = &checkConn->channelConfig->inSocket;
                                else
                                    checkConf = &checkConn->channelConfig->outSocket;

                                if( ( checkConf != conf ) && ( conf->address == checkConf->address ) )
                                {
                                    skip = true;
                                    break;
                                }
                            }
                            RaiseAvailable( connection );
                            if( !skip )
                                device->CreateSplittedMlbSocketV3( nodeAddress, ( uint16_t )0x0A00, //Const value for first instance of MLB bus
                                    conf->type, direction, conf->address, conf->blockWidth, conf->subbufferSize,
                                    allChannels[i]->channelId );
                        }
                    }
                    if( ( PORT_I2S == connection->channelConfig->inSocket.port )
                        || ( PORT_I2S == connection->channelConfig->outSocket.port ) )
                    {
                        EPDirection_t direction = EPDIR_Unknown;
                        CSocketConfiguration *conf = NULL;
                        uint8_t portInst = 0xFF;
                        if( PORT_I2S == connection->channelConfig->inSocket.port )
                        {
                            if( connection->inSocketState != NodeConnection_NotUsed )
                                continue;
                            connection->inSocketState = NodeConnection_Pending_Up;
                            direction = EPDIR_IN;
                            conf = &connection->channelConfig->inSocket;
                        }
                        else
                        {
                            if( connection->outSocketState != NodeConnection_NotUsed )
                                continue;
                            connection->outSocketState = NodeConnection_Pending_Up;
                            direction = EPDIR_OUT;
                            conf = &connection->channelConfig->outSocket;
                        }
                        switch( conf->i2sConfig.pin )
                        {
                        case V3I2SSRXA0:
                        case V3I2SSRXA1:
                            portInst = 0;
                            break;
                        case V3I2SSRXB0:
                        case V3I2SSRXB1:
                            portInst = 1;
                            break;
                        default:
                            break;
                        }
                        if( !entry->isI2SPortOpened )
                        {
                            if( V3I2SOptionUnknown != conf->i2sConfig.portOption )
                            {
                                entry->isI2SPortOpened = true;
                                device->ConfigureStreamPortV3( nodeAddress, 0, conf->i2sConfig.portOption,
                                    conf->i2sConfig.clockMode, conf->i2sConfig.delayMode, allChannels[i]->channelId );
                                device->ConfigureStreamPortV3( nodeAddress, 1, conf->i2sConfig.portOption,
                                    V3I2SClockModeWildcard, V3I2SDelayWildcard, allChannels[i]->channelId );
                            }
                            if( V3I2SSpeedUnknown != conf->i2sConfig.portSpeed )
                            {
                                entry->isI2SPortOpened = true;
                                device->CreateStreamPortV3( nodeAddress, 0, conf->i2sConfig.portSpeed,
                                    conf->i2sConfig.alignment, allChannels[i]->channelId );
                                device->CreateStreamPortV3( nodeAddress, 1, V3I2SSpeedWildcard,
                                    conf->i2sConfig.alignment, allChannels[i]->channelId );
                            }
                        }
                        if( 0xFFFFFFFF == conf->splittedOffset )
                        {
                            //No Splitter / No Combiner
                            device->CreateStreamSocketV3( nodeAddress, portInst, direction, conf->blockWidth,
                                conf->i2sConfig.pin, allChannels[i]->channelId );
                        }
                        else
                        {
                            //Splitter or Combiner is used
                            //Do not create multiple I2S sockets for a single Splitter / Combiner connection
                            bool skip = false;
                            for( uint16_t j = 0; j < entry->GetAmountOfConnections(); j++ )
                            {
                                CNodeConnectionEntry *checkConn = entry->GetConnectionByIndex( j );
                                CSocketConfiguration *checkConf = NULL;
                                if( EPDIR_IN == direction )
                                    checkConf = &checkConn->channelConfig->inSocket;
                                else
                                    checkConf = &checkConn->channelConfig->outSocket;

                                if( ( checkConf != conf ) && ( conf->i2sConfig.pin == checkConf->i2sConfig.pin ) )
                                {
                                    skip = true;
                                    break;
                                }
                            }
                            RaiseAvailable( connection );
                            if( !skip )
                                device->CreateSplittedStreamSocketV3( nodeAddress, portInst, direction,
                                    conf->blockWidth, conf->i2sConfig.pin, conf->subbufferSize,
                                    allChannels[i]->channelId );
                        }

                    }
                    if( PORT_MOST == connection->channelConfig->outSocket.port )
                    {
                        //Open MOST in case of out-connections
                        if( connection->outSocketState != NodeConnection_NotUsed )
                            continue;
                        connection->outSocketState = NodeConnection_Pending_Up;
                        CSocketConfiguration *conf = &connection->channelConfig->outSocket;
                        device->CreateMostSocketV3( nodeAddress, conf->type, EPDIR_OUT, conf->address,
                            conf->blockWidth, allChannels[i]->channelId );
                    }
                    else if( ( PORT_MOST == connection->channelConfig->inSocket.port )
                        && ( 0xFFFFFFFF != connection->channelConfig->inSocket.address ) )
                    {
                        //Or open MOST in case of in-connections with set connection label
                        if( connection->inSocketState != NodeConnection_NotUsed )
                            continue;
                        connection->inSocketState = NodeConnection_Pending_Up;
                        CSocketConfiguration *conf = &connection->channelConfig->inSocket;
                        ConsolePrintf( PRIO_MEDIUM,
                            "Creating MOST socket for preconfigured Connection Label %d (0x%X)\n", conf->address,
                            conf->address );
                        device->CreateMostSocketV3( nodeAddress, conf->type, EPDIR_IN, conf->address, conf->blockWidth,
                            allChannels[i]->channelId );
                    }
                }
                else
                {
                    ConsolePrintf( PRIO_ERROR, RED"Unknown INIC api version:%d"RESETCOLOR"\n", apiVer );
                }
                //Perform external script at the end
                if( i == ( allChannels.Size() - 1 ) )
                {
                    if( NULL != connection->channelConfig->externalScipt )
                    {
                        char configPath[300];
                        if( NULL != searchPath )
                            snprintf( configPath, sizeof ( configPath ), "%s/%s", searchPath,
                                connection->channelConfig->externalScipt );
                        else
                            strncpy( configPath, connection->channelConfig->externalScipt, sizeof ( configPath ) );
                        device->ExecuteMcmScript( nodeAddress, configPath );
                    }
                }
            }
    }
    else
    {
        ConsolePrintf( PRIO_ERROR,
            YELLOW"CNetwork::OnMostDeviceType(deviceType: 0x%X) there is no channel configuration for this device type."RESETCOLOR"\n",
            deviceType );
        RaiseUknownConnection( devInstance, nodeAddress, EP_Unknown );
    }
    sem_post( &vodXmlMutex );
}

void CNetwork::OnCreateTsiSocketV1( void *source, bool success, uint16_t nodeAddr, V1TsiPortInstance_t tsiPortInst,
        EPDataType_t epType, EPDirection_t epDir, uint16_t blockWidthTsi, uint16_t socketHandle, uint32_t tag )
{
    assert(EP_Isochron == epType);
    if( NULL == source || EP_Isochron != epType )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();

    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnCreateTsiSocketV1 reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddr );
        ShutdownMostBecauseOfErrors( device );
        return;
    }
    ConsolePrintf( PRIO_MEDIUM,
        "Network::OnCreateTsiSocketV1, inst:%d, addr:0x%X, port:%d, type:%d, dir:%d, bwTsi:%d, handle:0x%X, tag:0x%X\n", 
            devInstance, nodeAddr, tsiPortInst, epType, epDir, blockWidthTsi, socketHandle, tag );

    CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddr );
    if( NULL != entry )
    {
        CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( tag, true );
        if( NULL != connection )
        {
            if( EPDIR_IN == epDir )
            {
                connection->inSocketState = NodeConnection_Used;
                connection->inHandle = socketHandle;
            }
            else if( EPDIR_OUT == epDir )
            {
                connection->outSocketState = NodeConnection_Used;
                connection->outHandle = socketHandle;
            }
            else
            {
                ConsolePrintf(
                    PRIO_ERROR, RED"Network::OnCreateTsiSocketV1, Channel configuration is invalid, because direction of stream is unknown"RESETCOLOR"\n" );
            }
            TryToConnectSockets( devInstance, nodeAddr, tag );
            RaiseAvailable( connection );
        }
    }
    PRINT_ALL_INFOS();
}

void CNetwork::OnCreateMlbSocketV1( void *source, bool success, uint16_t nodeAddr, EPDataType_t epType,
    EPDirection_t epDir, uint16_t blockWidthMlb, uint8_t mlbChannelAddress, uint16_t socketHandle, uint32_t tag )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();

    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnCreateMlbSocketV1 reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddr );
        ShutdownMostBecauseOfErrors( device );
        return;
    }
    ConsolePrintf( PRIO_MEDIUM,
        "Network::OnCreateMlbSocketV1, inst:%d, addr:0x%X, type:%d, dir:%d, bwMlb:%d, mlbAddr:0x%X, handle:0x%X, tag:0x%X\n", devInstance, nodeAddr, epType, epDir, blockWidthMlb, mlbChannelAddress, socketHandle, tag );

    CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddr );
    if( NULL != entry )
    {
        CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( tag, true );
        if( NULL != connection )
        {
            AimType_t aimType = AIM_UNKNOWN;
            uint32_t amountOfBuffers = 0xFFFFFFFF;
            uint32_t bufferSize = 0xFFFFFFFF;
            uint32_t subbufferSize = 0xFFFFFFFF;
            uint32_t packetsPerTransaction = 0xFFFFFFFF;
            uint32_t splittedOffset = 0xFFFFFFFF;
            if( EPDIR_IN == epDir )
            {
                connection->inSocketState = NodeConnection_Used;
                connection->inHandle = socketHandle;
                amountOfBuffers = connection->channelConfig->inSocket.amountOfBuffers;
                bufferSize = connection->channelConfig->inSocket.bufferSize;
                subbufferSize = connection->channelConfig->inSocket.subbufferSize;
                packetsPerTransaction =
                    connection->channelConfig->inSocket.packetsPerTransaction;
                aimType = connection->channelConfig->inSocket.aimType;
                splittedOffset = connection->channelConfig->inSocket.splittedOffset;
            }
            else if( EPDIR_OUT == epDir )
            {
                connection->outSocketState = NodeConnection_Used;
                connection->outHandle = socketHandle;
                amountOfBuffers = connection->channelConfig->outSocket.amountOfBuffers;
                bufferSize = connection->channelConfig->outSocket.bufferSize;
                subbufferSize = connection->channelConfig->outSocket.subbufferSize;
                packetsPerTransaction =
                    connection->channelConfig->outSocket.packetsPerTransaction;
                aimType = connection->channelConfig->outSocket.aimType;
                splittedOffset = connection->channelConfig->outSocket.splittedOffset;
            }
            else
            {
                ConsolePrintf(
                    PRIO_ERROR, RED"Network::OnCreateMlbSocketV1, Channel configuration is invalid, because direction of stream is unknown"RESETCOLOR"\n" );
            }
            if( EP_Asynchron == epType )
            {
                connection->channelConfig->outSocket.type = EP_Asynchron;
                connection->channelConfig->inSocket.type = EP_Asynchron;
                connection->inSocketState = NodeConnection_Used;
                connection->outSocketState = NodeConnection_Used;
                connection->connectedSocketState = NodeConnection_Used;
                connection->mostConnectionLabel = 0xA;
            }
            else if( EP_Unknown == epType || EP_Unused == epType )
            {
                ConsolePrintf(
                    PRIO_ERROR, RED"Network::OnCreateMlbSocketV1, Channel configuration is invalid, because data type is unknown"RESETCOLOR"\n" );
            }

            TryToConnectSockets( devInstance, nodeAddr, tag );
            if( 0x1 == entry->nodeAddress && ( 0xFFFFFFFF == splittedOffset || 0x0 == splittedOffset ) )
            {
                connection->bufferSize = bufferSize;
                switch( epType )
                {
                case EP_Synchron:
                case EP_Isochron:
                    device->ConfigureMlbChannel( aimType, mlbChannelAddress, epType, epDir,
                        connection->deviceName, sizeof( connection->deviceName ), amountOfBuffers, bufferSize,
                        subbufferSize, packetsPerTransaction );
                    break;
                case EP_Unknown:
                case EP_Unused:
                    //Do nothing
                    break;
                default:
                    device->ConfigureMlbChannel( mlbChannelAddress, epType, epDir,
                        connection->deviceName, sizeof( connection->deviceName ), amountOfBuffers, bufferSize );
                    break;
                }
            }
            RaiseAvailable( connection );
        }
    }
    PRINT_ALL_INFOS();
}

void CNetwork::OnCreateMostSocketV1( void *source, bool success, uint16_t nodeAddr, EPDataType_t epType,
    EPDirection_t epDir, uint16_t blockwidthMost, uint16_t connectionLabel, uint16_t socketHandle, uint32_t tag )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnCreateMostSocketV1 reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddr );
        ShutdownMostBecauseOfErrors( device );
        return;
    }
    ConsolePrintf( PRIO_MEDIUM,
        "Network::OnCreateMostSocketV1, inst:%d, addr:0x%X, type:%d, dir:%d, bwMost:%d, conLabel:0x%X, handle:0x%X, tag:0x%X\n", devInstance, nodeAddr, epType, epDir, blockwidthMost, connectionLabel, socketHandle, tag );

    CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddr );
    if( NULL != entry )
    {
        CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( tag, true );
        if( NULL != connection )
        {
            connection->mostConnectionLabel = connectionLabel;
            if( EPDIR_IN == epDir )
            {
                connection->inSocketState = NodeConnection_Used;
                connection->inHandle = socketHandle;
            }
            else if( EPDIR_OUT == epDir )
            {
                connection->outSocketState = NodeConnection_Used;
                connection->outHandle = socketHandle;
            }
            TryToConnectSockets( devInstance, nodeAddr, tag );
            RaiseAvailable( connection );
        }
    }
    PRINT_ALL_INFOS();
}

void CNetwork::OnConnectSocketsV1( void *source, bool success, uint16_t nodeAddr, uint16_t inSocketHandle,
    uint16_t outSocketHandle, uint16_t connectionHandle, uint32_t tag )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnConnectSocketsV1 reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddr );
        ShutdownMostBecauseOfErrors( device );
        return;
    }
    ConsolePrintf( PRIO_MEDIUM,
        "Network::OnConnectSocketsV1, inst:%d, addr:0x%X, inHandle:0x%X, outHandle:0x%X, conHandle:0x%X, tag:0x%X\n",
        devInstance, nodeAddr, inSocketHandle, outSocketHandle, connectionHandle, tag );

    CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddr );
    if( NULL != entry )
    {
        CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( tag, true );
        if( NULL != connection )
        {
            connection->connectedSocketState = NodeConnection_Used;
            connection->connectHandle = connectionHandle;
            RaiseAvailable( connection );
        }
    }
    PRINT_ALL_INFOS();
}

void CNetwork::OnDestroySocketV1( void *source, bool success, uint16_t nodeAddr, uint16_t handle, uint32_t tag )
{
    if( NULL == source )
        return;
    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnDestroySocketV1 reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddr );
        return;
    }
    ConsolePrintf( PRIO_MEDIUM,
        "CNetwork::OnDestroySocketV1(deviceInstance:%d, nodeAddress:0x%X, handle:0x%X, tag:0x%X\n", devInstance,
        nodeAddr, handle, tag );
    CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddr );
    if( NULL != entry )
    {
        CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( tag, true );
        if( NULL != connection )
        {
            if( ( handle == connection->inHandle ) &&
                ( NodeConnection_Pending_Down == connection->inSocketState ) )
            {
                connection->inHandle = ( 0xFFFFFFFF );
                connection->inSocketState = NodeConnection_NotUsed;
                if( ( NULL != connection->channelConfig )
                    && ( PORT_MOST == connection->channelConfig->inSocket.port ) )
                {
                    connection->mostConnectionLabel = 0xFFFFFFFF;
                }
            }
            else if( ( handle == connection->outHandle ) &&
                ( NodeConnection_Pending_Down == connection->outSocketState ) )
            {
                connection->outHandle = ( 0xFFFFFFFF );
                connection->outSocketState = NodeConnection_NotUsed;
                if( ( NULL != connection->channelConfig )
                    && ( PORT_MOST == connection->channelConfig->outSocket.port ) )
                {
                    connection->mostConnectionLabel = 0xFFFFFFFF;
                }
            }
            RaiseUnavailable( connection );
        }
    }
    PRINT_ALL_INFOS();
}

void CNetwork::OnDisconnectSocketsV1( void *source, bool success, uint16_t nodeAddr, uint16_t handle, uint32_t tag )
{
    if( NULL == source )
        return;
    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnDisconnectSocketsV1 reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddr );
        return;
    }
    ConsolePrintf( PRIO_MEDIUM,
        "CNetwork::OnDisconnectSocketsV1(deviceInstance:%d, nodeAddress:0x%X, handle:0x%X, tag:0x%X\n", devInstance,
        nodeAddr, handle, tag );
    CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddr );
    if( NULL != entry )
    {
        CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( tag, true );
        if( NULL != connection )
        {
            if( ( handle == connection->connectHandle )
                && ( NodeConnection_Pending_Down == connection->connectedSocketState ) )
            {
                connection->connectHandle = ( 0xFFFFFFFF );
                connection->connectedSocketState = NodeConnection_NotUsed;
            }
            RaiseUnavailable( connection );
        }
    }
    PRINT_ALL_INFOS();
}

void CNetwork::OnCreateI2SSocketV1( void *source, bool success, uint16_t nodeAddr, EPDirection_t epDir,
    uint16_t blockWidthI2S, V1I2SPin_t pin, uint16_t socketHandle, uint32_t tag )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnCreateI2SSocketV1 reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddr );
        ShutdownMostBecauseOfErrors( device );
        return;
    }
    ConsolePrintf( PRIO_MEDIUM,
        "Network::OnCreateI2SSocketV1, addr:0x%X, port:%d, dir:%d, blockwidth:%d, pin:%d, handle:0x%X, tag:0x%X\n",
        devInstance, nodeAddr, epDir, blockWidthI2S, pin, socketHandle, tag );

    CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddr );
    if( NULL != entry )
    {
        CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( tag, true );
        if( NULL != connection )
        {
            if( EPDIR_IN == epDir )
            {
                connection->inSocketState = NodeConnection_Used;
                connection->inHandle = socketHandle;
            }
            else if( EPDIR_OUT == epDir )
            {
                connection->outSocketState = NodeConnection_Used;
                connection->outHandle = socketHandle;
            }
            else
            {
                ConsolePrintf(
                    PRIO_ERROR, RED"Network::OnCreateI2SSocket, Channel configuration is invalid, because direction of stream is unknown"RESETCOLOR"\n" );
            }
            TryToConnectSockets( devInstance, nodeAddr, tag );
            RaiseAvailable( connection );
        }
    }
    PRINT_ALL_INFOS();
}

void CNetwork::OnCreateUsbSocketV3( void *source, bool success, uint16_t nodeAddr, EPDataType_t epType,
    EPDirection_t epDir, uint8_t endPointAddress, uint16_t socketHandle, uint32_t tag )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnCreateUsbSocketV2 reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddr );
        ShutdownMostBecauseOfErrors( device );
        return;
    }
    ConsolePrintf( PRIO_MEDIUM,
        "Network::OnCreateUsbSocketV2, inst:%d, addr:0x%X, type:%d, dir:%d, epAddr:%d, handle:0x%X, tag:0x%X\n",
        devInstance, nodeAddr, epType, epDir, endPointAddress, socketHandle, tag );


    CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddr );
    if( NULL != entry )
    {
        CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( tag, true );
        if( NULL != connection )
        {
            AimType_t aimType = AIM_UNKNOWN;
            uint32_t amountOfBuffers = 0xFFFFFFFF;
            uint32_t bufferSize = 0xFFFFFFFF;
            uint32_t subbufferSize = 0xFFFFFFFF;
            uint32_t packetsPerTransaction = 0xFFFFFFFF;
            if( EPDIR_IN == epDir )
            {
                connection->inSocketState = NodeConnection_Used;
                connection->inHandle = socketHandle;
                amountOfBuffers = connection->channelConfig->inSocket.amountOfBuffers;
                bufferSize = connection->channelConfig->inSocket.bufferSize;
                subbufferSize = connection->channelConfig->inSocket.subbufferSize;
                packetsPerTransaction =
                    connection->channelConfig->inSocket.packetsPerTransaction;
                aimType = connection->channelConfig->inSocket.aimType;
            }
            else if( EPDIR_OUT == epDir )
            {
                connection->outSocketState = NodeConnection_Used;
                connection->outHandle = socketHandle;
                amountOfBuffers = connection->channelConfig->outSocket.amountOfBuffers;
                bufferSize = connection->channelConfig->outSocket.bufferSize;
                subbufferSize = connection->channelConfig->outSocket.subbufferSize;
                packetsPerTransaction =
                    connection->channelConfig->outSocket.packetsPerTransaction;
                aimType = connection->channelConfig->outSocket.aimType;
            }
            else
            {
                ConsolePrintf(
                    PRIO_ERROR, RED"Network::OnCreateUsbSocketV2, Channel configuration is invalid, because direction of stream is unknown"RESETCOLOR"\n" );
            }
            TryToConnectSockets( devInstance, nodeAddr, tag );

            if( 0x1 == entry->nodeAddress )
            {
                switch( epType )
                {
                case EP_Synchron:
                    connection->bufferSize = bufferSize;
                    device->ConfigureUsbEndpoint( aimType, endPointAddress, epType, epDir,
                        connection->deviceName, sizeof( connection->deviceName ), amountOfBuffers, bufferSize,
                        subbufferSize, packetsPerTransaction );
                    break;
                case EP_Isochron:
                    connection->bufferSize = bufferSize;
                    device->ConfigureUsbEndpoint( aimType, endPointAddress, epType, epDir,
                        connection->deviceName, sizeof( connection->deviceName ), amountOfBuffers, bufferSize,
                        subbufferSize, packetsPerTransaction );
                    break;
                case EP_Unknown:
                    ConsolePrintf(
                        PRIO_ERROR, RED"Network::OnCreateUsbSocketV2, Channel configuration is invalid, because data type is unknown"RESETCOLOR"\n" );
                    break;
                default:
                    connection->bufferSize = bufferSize;
                    device->ConfigureUsbEndpoint( endPointAddress, epType, epDir,
                        connection->deviceName, sizeof( connection->deviceName ), amountOfBuffers, bufferSize );
                    break;
                }
            }
            RaiseAvailable( connection );
        }
    }
    PRINT_ALL_INFOS();
}

void CNetwork::OnCreateSplittedUsbSocketV3( void *source, bool success, uint16_t nodeAddr, EPDataType_t epType,
    EPDirection_t epDir, uint8_t endPointAddress, uint16_t usbHandle, uint16_t splitterHandle, uint32_t tag )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnCreateSplittedUsbSocketV2 reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddr );
        ShutdownMostBecauseOfErrors( device );
        return;
    }
    ConsolePrintf( PRIO_MEDIUM,
        "Network::OnCreateSplittedUsbSocketV2, inst:%d, addr:0x%X, type:%d, dir:%d, epAddr:%d, USB-handle:0x%X, Splitter-handle:0x%X, tag:0x%X\n", devInstance, nodeAddr, epType, epDir, endPointAddress, usbHandle, splitterHandle, tag );

    CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddr );
    if( NULL != entry )
    {
        CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( tag, false );
        if( NULL != connection )
        {
            AimType_t aimType = AIM_UNKNOWN;
            uint32_t amountOfBuffers = 0xFFFFFFFF;
            uint32_t bufferSize = 0xFFFFFFFF;
            uint32_t subbufferSize = 0xFFFFFFFF;
            uint32_t packetsPerTransaction = 0xFFFFFFFF;
            bool valSet = false;
            for( uint16_t j = 0; j < entry->GetAmountOfConnections(); j++ )
            {
                CNodeConnectionEntry *checkConn = entry->GetConnectionByIndex( j );
                if( EPDIR_IN == epDir )
                {
                    if( connection->channelConfig->inSocket.address != checkConn->channelConfig->inSocket.address )
                        continue;
                    checkConn->inSocketState = NodeConnection_Used;
                    checkConn->inHandle = splitterHandle;
                    checkConn->splittedSourceHandle = usbHandle;
                    if( !valSet )
                    {
                        valSet = true;
                        amountOfBuffers = checkConn->channelConfig->inSocket.amountOfBuffers;
                        bufferSize = checkConn->channelConfig->inSocket.bufferSize;
                        subbufferSize = checkConn->channelConfig->inSocket.subbufferSize;
                        packetsPerTransaction =
                            checkConn->channelConfig->inSocket.packetsPerTransaction;
                        aimType = connection->channelConfig->inSocket.aimType;
                    }
                    TryToConnectSockets( devInstance, nodeAddr, checkConn->channelId );
                }
                else if( EPDIR_OUT == epDir )
                {
                    if( connection->channelConfig->outSocket.address != checkConn->channelConfig->outSocket.address )
                        continue;
                    checkConn->outSocketState = NodeConnection_Used;
                    checkConn->outHandle = splitterHandle;
                    checkConn->splittedSourceHandle = usbHandle;
                    if( !valSet )
                    {
                        valSet = true;
                        amountOfBuffers = checkConn->channelConfig->outSocket.amountOfBuffers;
                        bufferSize = checkConn->channelConfig->outSocket.bufferSize;
                        subbufferSize = checkConn->channelConfig->outSocket.subbufferSize;
                        packetsPerTransaction =
                            checkConn->channelConfig->outSocket.packetsPerTransaction;
                        aimType = connection->channelConfig->outSocket.aimType;
                    }
                    TryToConnectSockets( devInstance, nodeAddr, checkConn->channelId );
                }
                else
                {
                    ConsolePrintf(
                        PRIO_ERROR, RED"Network::OnCreateUsbSocketV2, Channel configuration is invalid, because direction of stream is unknown"RESETCOLOR"\n" );
                    return;
                }
            }

            if( 0x1 == entry->nodeAddress )
            {
                switch( epType )
                {
                case EP_Synchron:
                    connection->bufferSize = bufferSize;
                    device->ConfigureUsbEndpoint( aimType, endPointAddress, epType, epDir,
                        connection->deviceName, sizeof ( connection->deviceName ), amountOfBuffers, bufferSize,
                        subbufferSize, packetsPerTransaction );
                    break;
                case EP_Isochron:
                    connection->bufferSize = bufferSize;
                    device->ConfigureUsbEndpoint( aimType, endPointAddress, epType, epDir,
                        connection->deviceName, sizeof ( connection->deviceName ), amountOfBuffers, bufferSize,
                        subbufferSize, packetsPerTransaction );
                    break;
                case EP_Unknown:
                    ConsolePrintf(
                        PRIO_ERROR, RED"Network::OnCreateUsbSocketV2, Channel configuration is invalid, because data type is unknown"RESETCOLOR"\n" );
                    break;
                default:
                    connection->bufferSize = bufferSize;
                    device->ConfigureUsbEndpoint( endPointAddress, epType, epDir,
                        connection->deviceName, sizeof ( connection->deviceName ), amountOfBuffers, bufferSize );
                    break;
                }
            }
            RaiseAvailable( connection );
        }
        PRINT_ALL_INFOS();
    }
}

void CNetwork::OnCreateMlbSocketV3( void *source, bool success, uint16_t nodeAddr, EPDataType_t epType,
    EPDirection_t epDir, uint16_t blockWidthMlb, uint8_t mlbChannelAddress, uint16_t socketHandle, uint32_t tag )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnCreateMlbSocketV2 reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddr );
        ShutdownMostBecauseOfErrors( device );
        return;
    }
    ConsolePrintf( PRIO_MEDIUM,
        "Network::OnCreateMlbSocketV2, inst:%d, addr:0x%X, type:%d, dir:%d, mlbAddr:%d, handle:0x%X, tag:0x%X\n",
        devInstance, nodeAddr, epType, epDir, mlbChannelAddress, socketHandle, tag );

    CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddr );
    if( NULL != entry )
    {
        CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( tag, true );
        if( NULL != connection )
        {
            AimType_t aimType = AIM_UNKNOWN;
            uint32_t amountOfBuffers = 0xFFFFFFFF;
            uint32_t bufferSize = 0xFFFFFFFF;
            uint32_t subbufferSize = 0xFFFFFFFF;
            uint32_t packetsPerTransaction = 0xFFFFFFFF;
            if( EPDIR_IN == epDir )
            {
                connection->inSocketState = NodeConnection_Used;
                connection->inHandle = socketHandle;
                amountOfBuffers = connection->channelConfig->inSocket.amountOfBuffers;
                bufferSize = connection->channelConfig->inSocket.bufferSize;
                subbufferSize = connection->channelConfig->inSocket.subbufferSize;
                packetsPerTransaction =
                    connection->channelConfig->inSocket.packetsPerTransaction;
                aimType = connection->channelConfig->inSocket.aimType;
            }
            else if( EPDIR_OUT == epDir )
            {
                connection->outSocketState = NodeConnection_Used;
                connection->outHandle = socketHandle;
                amountOfBuffers = connection->channelConfig->outSocket.amountOfBuffers;
                bufferSize = connection->channelConfig->outSocket.bufferSize;
                subbufferSize = connection->channelConfig->outSocket.subbufferSize;
                packetsPerTransaction =
                    connection->channelConfig->outSocket.packetsPerTransaction;
                aimType = connection->channelConfig->outSocket.aimType;
            }
            else
            {
                ConsolePrintf(
                    PRIO_ERROR, RED"Network::OnCreateMlbSocketV2, Channel configuration is invalid, because direction of stream is unknown"RESETCOLOR"\n" );
            }
            TryToConnectSockets( devInstance, nodeAddr, tag );
            if( 0x1 == entry->nodeAddress )
            {
                connection->bufferSize = bufferSize;
                switch( epType )
                {
                case EP_Synchron:
                case EP_Isochron:
                    device->ConfigureMlbChannel( aimType, mlbChannelAddress, epType, epDir,
                        connection->deviceName, sizeof( connection->deviceName ), amountOfBuffers, bufferSize,
                        subbufferSize, packetsPerTransaction );
                    break;
                case EP_Unknown:
                    ConsolePrintf(
                        PRIO_ERROR, RED"Network::OnCreateMlbSocketV2, Channel configuration is invalid, because data type is unknown"RESETCOLOR"\n" );
                    break;
                default:
                    device->ConfigureMlbChannel( mlbChannelAddress, epType, epDir,
                        connection->deviceName, sizeof( connection->deviceName ), amountOfBuffers, bufferSize );
                    break;
                }
            }
            RaiseAvailable( connection );
        }
    }
    PRINT_ALL_INFOS();
}

void CNetwork::OnCreateSplittedMlbSocketV3( void *source, bool success, uint16_t nodeAddr, EPDataType_t epType,
    EPDirection_t epDir, uint16_t blockWidthMlb, uint8_t mlbChannelAddress, uint16_t mlbSocketHandle,
    uint16_t splitterHandle, uint32_t tag )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnCreateSplittedMlbSocketV3 reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddr );
        return;
    }
    ConsolePrintf( PRIO_MEDIUM,
        "Network::OnCreateSplittedMlbSocketV3, inst:%d, addr:0x%X, type:%d, dir:%d, mlbAddr:%d, mlb-handle:0x%X, Splitter-handle:0x%X, tag:0x%X\n", devInstance, nodeAddr, epType, epDir, mlbChannelAddress, mlbSocketHandle, splitterHandle, tag );

    CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddr );
    if( NULL != entry )
    {
        CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( tag, true );
        if( NULL != connection )
        {
            AimType_t aimType = AIM_UNKNOWN;
            uint32_t amountOfBuffers = 0xFFFFFFFF;
            uint32_t bufferSize = 0xFFFFFFFF;
            uint32_t subbufferSize = 0xFFFFFFFF;
            uint32_t packetsPerTransaction = 0xFFFFFFFF;
            bool valSet = false;
            for( uint16_t j = 0; j < entry->GetAmountOfConnections(); j++ )
            {
                CNodeConnectionEntry *checkConn = entry->GetConnectionByIndex( j );
                if( EPDIR_IN == epDir )
                {
                    if( connection->channelConfig->inSocket.address != checkConn->channelConfig->inSocket.address )
                        continue;
                    checkConn->inSocketState = NodeConnection_Used;
                    checkConn->inHandle = splitterHandle;
                    checkConn->splittedSourceHandle = mlbSocketHandle;
                    if( !valSet )
                    {
                        valSet = true;
                        amountOfBuffers = checkConn->channelConfig->inSocket.amountOfBuffers;
                        bufferSize = checkConn->channelConfig->inSocket.bufferSize;
                        subbufferSize = checkConn->channelConfig->inSocket.subbufferSize;
                        packetsPerTransaction =
                            checkConn->channelConfig->inSocket.packetsPerTransaction;
                        aimType = connection->channelConfig->inSocket.aimType;
                    }
                    TryToConnectSockets( devInstance, nodeAddr, checkConn->channelId );
                }
                else if( EPDIR_OUT == epDir )
                {
                    if( connection->channelConfig->outSocket.address != checkConn->channelConfig->outSocket.address )
                        continue;
                    checkConn->outSocketState = NodeConnection_Used;
                    checkConn->outHandle = splitterHandle;
                    checkConn->splittedSourceHandle = mlbSocketHandle;
                    if( !valSet )
                    {
                        valSet = true;
                        amountOfBuffers = checkConn->channelConfig->outSocket.amountOfBuffers;
                        bufferSize = checkConn->channelConfig->outSocket.bufferSize;
                        subbufferSize = checkConn->channelConfig->outSocket.subbufferSize;
                        packetsPerTransaction =
                            checkConn->channelConfig->outSocket.packetsPerTransaction;
                        aimType = connection->channelConfig->outSocket.aimType;
                    }
                    TryToConnectSockets( devInstance, nodeAddr, checkConn->channelId );
                }
                else
                {
                    ConsolePrintf(
                        PRIO_ERROR, RED"Network::OnCreateSplittedMlbSocketV3, Channel configuration is invalid, because direction of stream is unknown"RESETCOLOR"\n" );
                    return;
                }
            }
            if( 0x1 == entry->nodeAddress )
            {
                connection->bufferSize = bufferSize;
                switch( epType )
                {
                case EP_Synchron:
                case EP_Isochron:
                    device->ConfigureMlbChannel( aimType, mlbChannelAddress, epType, epDir,
                        connection->deviceName, sizeof( connection->deviceName ), amountOfBuffers, bufferSize,
                        subbufferSize, packetsPerTransaction );
                    break;
                case EP_Unknown:
                    ConsolePrintf(
                        PRIO_ERROR, RED"Network::OnCreateMlbSocketV2, Channel configuration is invalid, because data type is unknown"RESETCOLOR"\n" );
                    break;
                default:
                    device->ConfigureMlbChannel( mlbChannelAddress, epType, epDir,
                        connection->deviceName, sizeof( connection->deviceName ), amountOfBuffers, bufferSize );
                    break;
                }
            }
            RaiseAvailable( connection );
        }
    }
    PRINT_ALL_INFOS();
}

void CNetwork::OnCreateI2SSocketV3( void *source, bool success, uint16_t nodeAddr, uint8_t portInstance,
    EPDirection_t epDir, uint16_t blockWidthI2S, V3I2SPin_t pin, uint16_t socketHandle, uint32_t tag )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnCreateI2SSocket reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddr );
        ShutdownMostBecauseOfErrors( device );
        return;
    }
    ConsolePrintf( PRIO_MEDIUM,
        "Network::OnCreateI2SSocket, inst:%d, addr:0x%X, port:%d, dir:%d, blockwidth:%d, pin:%d, handle:0x%X, tag:0x%X\n", devInstance, nodeAddr, portInstance, epDir, blockWidthI2S, pin, socketHandle, tag );

    CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddr );
    if( NULL != entry )
    {
        CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( tag, true );
        if( NULL != connection )
        {
            if( EPDIR_IN == epDir )
            {
                connection->inSocketState = NodeConnection_Used;
                connection->inHandle = socketHandle;
            }
            else if( EPDIR_OUT == epDir )
            {
                connection->outSocketState = NodeConnection_Used;
                connection->outHandle = socketHandle;
            }
            else
            {
                ConsolePrintf(
                    PRIO_ERROR, RED"Network::OnCreateI2SSocket, Channel configuration is invalid, because direction of stream is unknown"RESETCOLOR"\n" );
            }
            TryToConnectSockets( devInstance, nodeAddr, tag );
            RaiseAvailable( connection );
        }
    }
    PRINT_ALL_INFOS();
}

void CNetwork::OnCreateSplittedI2SSocketV3( void *source, bool success, uint16_t nodeAddr, uint8_t portInstance,
    EPDirection_t epDir, uint16_t blockWidthI2S, V3I2SPin_t pin, uint16_t i2sSocketHandle, uint16_t splitterHandle,
    uint32_t tag )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnCreateSplittedI2SSocketV2 reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddr );
        return;
    }
    ConsolePrintf( PRIO_MEDIUM,
        "Network::OnCreateI2SSocket, inst:%d, addr:0x%X, port:%d, dir:%d, blockwidth:%d, pin:%d, i2s-handle:0x%X, Splitter-handle:0x%X, tag:0x%X\n", devInstance, nodeAddr, portInstance, epDir, blockWidthI2S, pin, i2sSocketHandle, splitterHandle, tag );

    CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddr );
    if( NULL != entry )
    {
        CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( tag, true );
        if( NULL != connection )
        {
            if( EPDIR_IN == epDir )
            {
                //Find all related pin configurations, this is the use case of splitted I2S sockets
                V3I2SPin_t pin = connection->channelConfig->inSocket.i2sConfig.pin;
                uint16_t all = entry->GetAmountOfConnections();
                for (uint16_t i = 0; i < all; i++)
                {
                    CNodeConnectionEntry *con = entry->GetConnectionByIndex(i);
                    if (pin == con->channelConfig->inSocket.i2sConfig.pin)
                    {
                        con->inSocketState = NodeConnection_Used;
                        con->inHandle = splitterHandle;
                        con->splittedSourceHandle = i2sSocketHandle;
                        TryToConnectSockets( devInstance, nodeAddr, con->channelId );
                    }
                }
            }
            else if( EPDIR_OUT == epDir )
            {
                //Find all related pin configurations, this is the use case of splitted I2S sockets
                V3I2SPin_t pin = connection->channelConfig->outSocket.i2sConfig.pin;
                uint16_t all = entry->GetAmountOfConnections();
                for (uint16_t i = 0; i < all; i++)
                {
                    CNodeConnectionEntry *con = entry->GetConnectionByIndex(i);
                    if (pin == con->channelConfig->outSocket.i2sConfig.pin)
                    {
                        con->outSocketState = NodeConnection_Used;
                        con->outHandle = splitterHandle;
                        con->splittedSourceHandle = i2sSocketHandle;
                        TryToConnectSockets( devInstance, nodeAddr, con->channelId );
                    }
                }
            }
            else
            {
                ConsolePrintf(
                    PRIO_ERROR, RED"Network::OnCreateI2SSocket, Channel configuration is invalid, because direction of stream is unknown"RESETCOLOR"\n" );
            }
            RaiseAvailable( connection );
        }
    }
    PRINT_ALL_INFOS();
}

void CNetwork::OnCreateMostSocketV3( void *source, bool success, uint16_t nodeAddr, EPDataType_t epType,
    EPDirection_t epDir, uint16_t blockwidthMost, uint16_t connectionLabel, uint16_t socketHandle, uint32_t tag )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnCreateMostSocketV2 reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddr );
        ShutdownMostBecauseOfErrors( device );
        return;
    }
    ConsolePrintf( PRIO_MEDIUM,
        "Network::OnCreateMostSocketV2, inst:%d, addr:0x%X, type:%d, dir:%d, bwMost:%d, conLabel:0x%X, handle:0x%X, tag:0x%X\n", devInstance, nodeAddr, epType, epDir, blockwidthMost, connectionLabel, socketHandle, tag );

    CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddr );
    if( NULL != entry )
    {
        CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( tag, true );
        if( NULL != connection )
        {
            connection->mostConnectionLabel = connectionLabel;
            if( EPDIR_IN == epDir )
            {
                connection->inSocketState = NodeConnection_Used;
                connection->inHandle = socketHandle;
            }
            else if( EPDIR_OUT == epDir )
            {
                connection->outSocketState = NodeConnection_Used;
                connection->outHandle = socketHandle;
            }
            TryToConnectSockets( devInstance, nodeAddr, tag );
            RaiseAvailable( connection );
        }
    }
    PRINT_ALL_INFOS();
}

void CNetwork::OnConnectSocketsV3( void *source, bool success, uint16_t nodeAddr, EPDataType_t epType,
    uint16_t inSocketHandle, uint16_t outSocketHandle, uint16_t connectionHandle, uint32_t tag )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnConnectSocketsV2 reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddr );
        ShutdownMostBecauseOfErrors( device );
        return;
    }
    ConsolePrintf( PRIO_MEDIUM,
        "Network::OnConnectSocketsV2, inst:%d, addr:0x%X, Type0x%X, inHandle:0x%X, outHandle:0x%X, conHandle:0x%X, tag:0x%X\n", devInstance, nodeAddr, epType, inSocketHandle, outSocketHandle, connectionHandle, tag );

    CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddr );
    if( NULL != entry )
    {
        CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( tag, true );
        if( NULL != connection )
        {
            connection->connectedSocketState = NodeConnection_Used;
            connection->connectHandle = connectionHandle;
            RaiseAvailable( connection );
        }
    }
    PRINT_ALL_INFOS();
}

void CNetwork::OnControlChannelReadEnd( void *source )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    connectionBitMask = connectionBitMask & ~( 1 << devInstance );
    ConsolePrintf( PRIO_ERROR, RED"Destroying NetworkDevice with instance %d, because the reader thread has ended"RESETCOLOR"\n",
        devInstance );

    allNetworkDevices.Remove(device);
    delete device;
}

void CNetwork::OnMostControlMessage( void *source, uint32_t sourceAddr, uint32_t targetAddr, uint32_t nFBlock,
    uint32_t nInst, uint32_t nFunc, uint8_t nOpType, uint32_t nPayloadLen, const uint8_t *Payload )
{
    if( NULL == source )
        return;
    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    for( uint32_t i = 0; i < allListeners.Size(); i++ )
    {
        allListeners[i]->OnMostControlMessage( devInstance, sourceAddr, targetAddr, nFBlock, nInst, nFunc, nOpType,
            nPayloadLen, Payload );
    }
}

void CNetwork::OnRbdResultV3( void *source, uint16_t nodeAddress, uint8_t result, uint8_t position,
    uint8_t status, uint16_t id )
{
    CNetworkDeviceListener::OnRbdResultV3( source, nodeAddress, result, position, status, id );
    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    for( uint32_t i = 0; i < allListeners.Size(); i++ )
    {
        allListeners[i]->OnRingBreakDiagnosisResultV3( devInstance, nodeAddress, result, position, status, id );
    }
}

void CNetwork::OnMostMacAddress( void *source, bool success, uint16_t nodeAddress, uint8_t macAddress1,
        uint8_t macAddress2, uint8_t macAddress3, uint8_t macAddress4, uint8_t macAddress5, uint8_t macAddress6 )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnMostMacAddress reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddress );
        ShutdownMostBecauseOfErrors( device );
        return;
    }
}

void CNetwork::OnConfigureI2SPortV3( void *source, bool success, uint16_t nodeAddr, uint8_t portInstance,
        V3I2SPortOption_t option, V3I2SClockMode_t mode, V3I2SDelayMode_t delay, uint32_t tag )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnConfigureI2SPortV2 reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddr );
        ShutdownMostBecauseOfErrors( device );
        return;
    }
}

void CNetwork::OnCreateI2SPortV3( void *source, bool success, uint16_t nodeAddr, uint8_t portInstance,
        V3I2SPortSpeed_t clock, V3I2SAlignment_t align, uint32_t tag )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnCreateI2SPortV2 reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, nodeAddr );
        return;
    }
}

void CNetwork::OnDeviceVersion( void *source, bool success, uint32_t sourceAddr,
        uint32_t productId, uint32_t fwVersion, uint32_t buildVersion, 
        uint8_t hwVersion, uint16_t diagnosisId, uint32_t tag )
{
    if( NULL == source )
        return;

    CNetworkDevice *device = ( ( CNetworkDevice * )source );
    uint32_t devInstance = device->GetDeviceIndex();
    if( !success )
    {
        ConsolePrintf(
            PRIO_ERROR, RED"CNetwork::OnDeviceVersion reports failure for device:%d, nodeAddress:0x%X"RESETCOLOR"\n",
            devInstance, sourceAddr );
        return;
    }
    ConsolePrintf( PRIO_MEDIUM, "Got Device version for nodeAddress:0x%X, productId:0x%X, fwVersion:0x%X, "\
            "buildVersion:0x%X, hwVersion:%d, diagnosisId:0x%X\n", sourceAddr, productId, fwVersion,
            buildVersion, hwVersion, diagnosisId);
    if( 0x81118 == productId )
    {
        uint8_t exMajor = 2;
        uint8_t exMinor = 4;
        uint8_t exRelease = 0;
        uint32_t expectedFW = exMajor << 24 | exMinor << 16 | exRelease << 8;
        if (fwVersion < expectedFW)
        {
            ConsolePrintf( PRIO_ERROR, RED"Warning, the device with node address:0x%X uses"\
                " too old firmware! Please update to: V%d.%d.%d"RESETCOLOR"\n",
                sourceAddr, exMajor, exMinor, exRelease);
        }
    }
}