diff options
Diffstat (limited to 'Src/Network/Network.cpp')
-rw-r--r-- | Src/Network/Network.cpp | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/Src/Network/Network.cpp b/Src/Network/Network.cpp new file mode 100644 index 0000000..0c4b10d --- /dev/null +++ b/Src/Network/Network.cpp @@ -0,0 +1,433 @@ +/* + * 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" + +using namespace std; + +static CNetwork *staticInstance = NULL; +CSafeVector<CNetworkDevice *> CNetwork::allNetworkDevices; + +CNetwork::CNetwork() : CThread( "CNetwork", false ), allowNetworkRun( false ), + vodXml( NULL ), connectionBitMask( 0 ), promiscuous( false ), retryCounter( 0 ), + retryExecTime( 0 ) +{ + searchPath[0] = 0; + sem_init( &vodXmlMutex, 0, 1 ); //Mutex, initialized to 1 => sem_wait will block at 2nd call + Start(); +} + +CNetwork::~CNetwork() +{ + ConsolePrintf( PRIO_LOW, "Destructor of network called\r\n" ); + Stop(); + allowNetworkRun = false; + CloseAllNetworkDevices(); + sem_wait( &vodXmlMutex ); + if( NULL != vodXml ) + { + delete vodXml; + vodXml = NULL; + } + sem_post( &vodXmlMutex ); + staticInstance = NULL; + ConsolePrintf( PRIO_LOW, "end network\r\n" ); +} + +CNetwork *CNetwork::GetInstance( void ) +{ + if( NULL == staticInstance ) + { + staticInstance = new CNetwork(); + } + return staticInstance; +} + +void CNetwork::AddListener( CNetworkListner *listener ) +{ + allListeners.PushBack( listener ); +} + +void CNetwork::RemoveListener( CNetworkListner *listener ) +{ + allListeners.Remove(listener); +} + +void CNetwork::SetPromiscuousMode( bool enabled ) +{ + promiscuous = enabled; +} + +bool CNetwork::LoadConfig( char *szConfigXml ) +{ + uint32_t len = strlen(szConfigXml); + if( NULL == szConfigXml || 0 == len) + { + ConsolePrintf( PRIO_ERROR, RED"Path to config file was NULL"RESETCOLOR"\n" ); + return false; + } + if ('/' == szConfigXml[0]) + { + char path[300]; + uint32_t i; + uint32_t lastSlash = 0; + for (i = len - 1; i > 0; i--) + { + if ('/' == szConfigXml[i]) + { + lastSlash = i; + break; + } + } + memcpy(path, szConfigXml, lastSlash); + path[lastSlash] = '\0'; + memcpy(szConfigXml, &szConfigXml[lastSlash + 1], (len - lastSlash - 1) ); + szConfigXml[len - lastSlash - 1] = '\0'; + return LoadConfig(szConfigXml, path); + } + else + { + return LoadConfig(szConfigXml, NULL); + } +} + +bool CNetwork::LoadConfig( const char *szConfigXml, const char *szSearchPath ) +{ + char configPath[300]; + if( NULL == szConfigXml || 0 == strlen(szConfigXml)) + { + ConsolePrintf( PRIO_ERROR, RED"Path to config file was NULL"RESETCOLOR"\n" ); + return false; + } + if (NULL != szSearchPath) + strncpy( searchPath, szSearchPath, sizeof( searchPath ) ); + if( NULL != searchPath && '/' != szConfigXml[0]) + snprintf( configPath, sizeof( configPath ), "%s/%s", searchPath, szConfigXml ); + else + strncpy( configPath, szConfigXml, sizeof( configPath ) ); + + allowNetworkRun = true; + + sem_wait( &vodXmlMutex ); + bool success; + if( NULL != vodXml ) + { + delete vodXml; + } + vodXml = new CVodXml( configPath ); + success = ( NULL != vodXml ); + sem_post( &vodXmlMutex ); + + if ( allNetworkDevices.Size() != 0 ) + { + bool tm; + uint32_t bw; + if (vodXml->GetMostParameters( &tm, &bw ) ) + { + for( uint32_t i = 0; i < allNetworkDevices.Size(); i++ ) + { + allNetworkDevices[i]->SetAsyncBandwidth(bw); + allNetworkDevices[i]->SetTimingMaster(tm); + ShutdownMost(allNetworkDevices[i]); + } + } + } + + if( success ) + FindNewNetworkDevices(); + + retryCounter = 0; + return success; +} + +bool CNetwork::ActionsPending() +{ + bool isPending = false; + for( uint32_t i = 0; i < allNetworkDevices.Size(); i++ ) + { + if( allNetworkDevices[i]->ActionsPending() ) + { + isPending = true; + break; + } + } + return isPending; +} + +bool CNetwork::ConnectSourceToSink( CMacAddr *SourceMacAddr, TChannelId SourceChannelId, CMacAddr *SinkMacAddr, + TChannelId SinkChannelId ) +{ + CNodeEntry *inNode = CNodeEntry::GetNodeEntry( SourceMacAddr ); + CNodeEntry *outNode = CNodeEntry::GetNodeEntry( SinkMacAddr ); + return ConnectSourceToSink( inNode, outNode, SourceChannelId, SinkChannelId ); +} + +uint8_t CNetwork::GetAmountOfLocalNodes() +{ + return allNetworkDevices.Size(); +} + +bool CNetwork::SendMostControlMessage( TMostInstace mostInstance, uint32_t targetAddr, uint32_t nFBlock, + uint32_t nInst, uint32_t nFunc, uint8_t nOpType, uint32_t nPayloadLen, const uint8_t *Payload ) +{ + bool success = false; + for( uint32_t i = 0; i < allNetworkDevices.Size(); i++ ) + { + if( allNetworkDevices[i]->GetDeviceIndex() == mostInstance ) + { + if (targetAddr < 0x300 || targetAddr > 0x3FF || targetAddr == 0x3C8) + { + success = allNetworkDevices[i]->SendMostControlMessage( mostInstance, targetAddr, nFBlock, nInst, nFunc, + nOpType, nPayloadLen, Payload ); + } + else + { + success = true; + for (uint16_t j = 0; j < CNodeEntry::GetAmountOfNodeEntries(); j++) + { + CNodeEntry *node = CNodeEntry::GetNodeEntry(j); + if (NULL != node && node->deviceInstance == mostInstance && + node->deviceType == targetAddr) + { + success &= allNetworkDevices[i]->SendMostControlMessage( mostInstance, node->nodeAddress, nFBlock, nInst, nFunc, + nOpType, nPayloadLen, Payload ); + } + } + } + break; + } + } + return success; +} + +bool CNetwork::SendMostControlMessage( TMostInstace mostInstance, TDeviceId deviceId, uint8_t devInst, + uint32_t nFBlock, uint32_t nInst, uint32_t nFunc, uint8_t nOpType, uint32_t nPayloadLen, const uint8_t *Payload ) +{ + bool success = false; + + CNodeEntry *entry = CNodeEntry::GetNodeEntry( mostInstance, deviceId, devInst ); + if( NULL == entry ) + return success; + + for( uint32_t i = 0; i < allNetworkDevices.Size(); i++ ) + { + if( allNetworkDevices[i]->GetDeviceIndex() == mostInstance ) + { + success = allNetworkDevices[i]->SendMostControlMessage( mostInstance, entry->nodeAddress, nFBlock, nInst, + nFunc, nOpType, nPayloadLen, Payload ); + break; + } + } + return success; +} + +bool CNetwork::ExecuteXmlScriptFromFile( TMostInstace mostInstance, uint32_t targetAddr, const char *szFile ) +{ + if (NULL == szFile) + return false; + bool success = false; + char scriptPath[300]; + const char *pPath = szFile; + if( NULL != searchPath && '/' != szFile[0]) + { + snprintf( scriptPath, sizeof( scriptPath ), "%s/%s", searchPath, szFile ); + pPath = scriptPath; + } + for( uint32_t i = 0; i < allNetworkDevices.Size(); i++ ) + { + if( allNetworkDevices[i]->GetDeviceIndex() == mostInstance ) + { + allNetworkDevices[i]->ExecuteMcmScript( targetAddr, pPath ); + success = true; + break; + } + } + return success; +} + +bool CNetwork::ExecuteXmlScriptFromFile( TMostInstace mostInstance, TDeviceId deviceId, uint8_t devInst, + const char *szFile ) +{ + CNodeEntry *entry = CNodeEntry::GetNodeEntry( mostInstance, deviceId, devInst ); + if( NULL == entry ) + return false; + + return ExecuteXmlScriptFromFile( mostInstance, entry->nodeAddress, szFile ); +} + +bool CNetwork::ExecuteXmlScriptFromMemory( TMostInstace mostInstance, uint32_t targetAddr, const char *szBuffer, + uint32_t nBufferLen ) +{ + bool success = false; + for( uint32_t i = 0; i < allNetworkDevices.Size(); i++ ) + { + if( allNetworkDevices[i]->GetDeviceIndex() == mostInstance ) + { + allNetworkDevices[i]->ExecuteMcmScript( targetAddr, szBuffer, nBufferLen ); + success = true; + break; + } + } + return success; +} + +bool CNetwork::ExecuteXmlScriptFromMemory( TMostInstace mostInstance, TDeviceId deviceId, uint8_t devInst, + const char *szBuffer, uint32_t nBufferLen ) +{ + CNodeEntry *entry = CNodeEntry::GetNodeEntry( mostInstance, deviceId, devInst ); + if( NULL == entry ) + return false; + + return ExecuteXmlScriptFromMemory( mostInstance, entry->nodeAddress, szBuffer, nBufferLen ); +} + +uint32_t CNetwork::GetCounterPartOfRoute( const Route_t *pInRoute, Route_t **pOutRouteArray ) +{ + if( ( NULL == pInRoute ) || ( NULL == pOutRouteArray ) ) + { + ConsolePrintf( PRIO_ERROR, RED"GetCounterPartOfRoute was called with wrong parameters"RESETCOLOR"\n" ); + return 0; + } + *pOutRouteArray = NULL; + CSafeVector<CRouteTerminal *> connectedTerminals; + CRouteTerminal terminal; + terminal.deviceType = pInRoute->deviceType; + terminal.instance = pInRoute->instance; + terminal.channelId = pInRoute->channelId; + + sem_wait( &vodXmlMutex ); + bool found = vodXml->GetRouteTerminals( &terminal, connectedTerminals ); + sem_post( &vodXmlMutex ); + if( !found ) + return 0; + uint32_t arrayLen = connectedTerminals.Size(); + *pOutRouteArray = ( Route_t * )calloc( arrayLen, sizeof( Route_t ) ); + if( NULL == *pOutRouteArray ) + { + ConsolePrintf( PRIO_ERROR, RED"GetCounterPartOfRoute failed to allocate memory"RESETCOLOR"\n" ); + return 0; + } + for( uint32_t i = 0; i < arrayLen; i++ ) + { + ( *pOutRouteArray )[i].deviceType = connectedTerminals[i]->deviceType; + ( *pOutRouteArray )[i].instance = connectedTerminals[i]->instance; + ( *pOutRouteArray )[i].channelId = connectedTerminals[i]->channelId; + } + return arrayLen; +} + +bool CNetwork::GetRingBreakDiagnosisResult( TMostInstace mostInstance, uint32_t targetAddr ) +{ + bool success = false; + for( uint32_t i = 0; i < allNetworkDevices.Size(); i++ ) + { + if( allNetworkDevices[i]->GetDeviceIndex() == mostInstance ) + { + allNetworkDevices[i]->GetRingBreakResultV3( 1, 0 ); + success = true; + break; + } + } + return success; +} + +void CNetwork::EnableMost(bool enabled) +{ + allowNetworkRun = enabled; + for( uint32_t i = 0; i < allNetworkDevices.Size(); i++ ) + { + CNetworkDevice *device = allNetworkDevices[i]; + if (enabled) + { + if (NetworkState_Available == device->GetNetState()) + { + ConsolePrintf(PRIO_ERROR, RED"MOST is already in NET ON state"RESETCOLOR"\n"); + return; + } + device->SetNetstate( NetworkState_Unknown ); + bool isTimingMaster = device->IsTimingMaster(); + uint32_t asyncBandwidth = device->GetAsyncBandwidth(); + if( isTimingMaster ) + device->MostNetworkStartupV3( 0xFFFF, asyncBandwidth ); + } + else + { + device->SetNetstate( NetworkState_ShutdownInProgress ); + device->ClearAllPendingActions(); + device->MostNetworkShutdownV3(); + } + } +} + +void CNetwork::Run() +{ + sleep( 5 ); + if (retryCounter > 0 && (GetTickCount() - retryExecTime >= 60000)) + retryCounter = 0; + if( allowNetworkRun ) + FindNewNetworkDevices(); +} + +/*---------------------------------------------*/ +/* Empty implementation of CNetworkListner */ +/*---------------------------------------------*/ + +void CNetworkListner::OnNetworkState( uint8_t mostInstance, bool available, uint8_t maxPos, uint16_t packetBW ) +{ + ConsolePrintf( PRIO_LOW, "CNetwork::OnNetworkState\n" ); +} + +void CNetworkListner::OnChannelAvailable( CMacAddr *macAddr, TDeviceId deviceId, uint8_t devInst, TChannelId channelId, + TMostInstace mostInstance, EPDataType_t dataType, TBlockwidth reservedBandwidth, bool isSourceDevice, + bool inSocketCreated, bool outSocketCreated, bool socketsConnected, int32_t bufferSize, + uint32_t mostConnectionLabel, int16_t splittedOffset, int16_t splittedMaxBandwidth, uint16_t packetsPerXact, + const char *deviceName ) +{ + ConsolePrintf( PRIO_LOW, "CNetwork::OnCharacterDeviceAvailable(%s)\n", deviceName ); +} + +void CNetworkListner::OnChannelUnavailable( CMacAddr *macAddr, TChannelId channelId, uint8_t mostInstance ) +{ + ConsolePrintf( PRIO_LOW, "CNetwork::OnChannelUnavailable\n" ); +} + +void CNetworkListner::OnMostControlMessage( uint8_t devInst, 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 ) +{ + ConsolePrintf( PRIO_LOW, "CNetwork::OnMostControlMessage\n" ); +} + +void CNetworkListner::OnRingBreakDiagnosisResultV3( uint8_t devInst, uint16_t nodeAddress, uint8_t result, + uint8_t position, uint8_t status, uint16_t id ) +{ + ConsolePrintf( PRIO_LOW, "CNetwork::OnRingBreakDiagnosisResultV2\n" ); +} |