diff options
Diffstat (limited to 'Src/Network/Network_CB.cpp')
-rw-r--r-- | Src/Network/Network_CB.cpp | 1823 |
1 files changed, 1823 insertions, 0 deletions
diff --git a/Src/Network/Network_CB.cpp b/Src/Network/Network_CB.cpp new file mode 100644 index 0000000..3a91cc2 --- /dev/null +++ b/Src/Network/Network_CB.cpp @@ -0,0 +1,1823 @@ +/* + * 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 3 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); + } + } +}
\ No newline at end of file |