summaryrefslogtreecommitdiffstats
path: root/Src/Network/Network.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Network/Network.cpp')
-rw-r--r--Src/Network/Network.cpp433
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" );
+}