diff options
Diffstat (limited to 'Src/Main.cpp')
-rw-r--r-- | Src/Main.cpp | 1255 |
1 files changed, 1255 insertions, 0 deletions
diff --git a/Src/Main.cpp b/Src/Main.cpp new file mode 100644 index 0000000..b11fd40 --- /dev/null +++ b/Src/Main.cpp @@ -0,0 +1,1255 @@ +/* + * 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. + * + */ + +#define NM_VERSION_MAJOR ((uint8_t)3) +#define NM_VERSION_MINOR ((uint8_t)0) +#define NM_VERSION_BUGFIX ((uint8_t)4) +#define NM_VERSION_BUILD ((uint8_t)0) + +#define IPC_PORT_NUMBER_NM (5533) +#define FBLOCK_NETWORK_MANAGER (10) +#define FUNC_NM_SERVERVERSION (1) +#define FUNC_NM_SUBSCRIBE_MCM (2) +#define FUNC_NM_UNSUBSCRIBE_MCM (3) +#define FUNC_NM_RECEIVED_MCM (4) +#define FUNC_NM_SEND_MCM_ADR (5) +#define FUNC_NM_SEND_MCM_DEV (6) +#define FUNC_NM_COUNTER_ROUTE (10) +#define FUNC_NM_EXECUTE_CONFIG (15) +#define FUNC_NM_EXECUTE_SCRIPT_FILE (20) +#define FUNC_NM_EXECUTE_SCRIPT_MEM (21) +#define FUNC_NM_NET_STATE (30) +#define FUNC_NM_CONNECTION_LIST (100) +#define FUNC_NM_RING_BREAK_DIAGNOSIS (200) + +#define IPC_TEMP_BUFFER_SIZE (200000) + +#define AMOUNT_OF_NETWORK_STATES 10 + +#include <DoxyGenStartPage.h> +#include <stdio.h> +#include <stdint.h> +#include <stddef.h> +#include <unistd.h> +#include <stdlib.h> +#include <signal.h> +#include <pthread.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <sys/stat.h> +#include <unistd.h> +#include <pthread.h> +#include <fcntl.h> +#include <dirent.h> +#include <exception> +#include "Console.h" +#include "Network.h" +#include "Board.h" +#include "MacAddr.h" +#include "MostIpc.h" +#include "ConnectionInfo.h" + +using namespace std; + +class CNetworkManagerHandler; +static CNetworkManagerHandler *s_mainClass = NULL; + +/*----------------------------------------------------------*/ +/*! \brief Structure which holds information to address an MOST device via it's source and target address. + */ +/*----------------------------------------------------------*/ +typedef struct +{ + ///The MOST ring instance, starting with 0 for the first MOST ring. + uint32_t mostInst; + ///The MOST source address (may be not accurate). + uint32_t sourceAddr; + ///The MOST target address. + uint32_t targetAddr; + ///The MOST Function Block Identifier + uint32_t nFBlock; + ///The MOST Function Block Instance Identifier + uint32_t nInst; + ///The MOST Function Block Function Identifier + uint32_t nFunc; + ///The MOST Function Block Function Operation Type + uint32_t nOpType; + ///The amount of bytes stored in Payload + uint32_t nPayloadLen; +} MostMcmAdr_t; + +/*----------------------------------------------------------*/ +/*! \brief Structure which holds information to address an MOST device via it's device id and device instance (like described in the XML file). + */ +/*----------------------------------------------------------*/ +typedef struct +{ + ///The MOST ring instance, starting with 0 for the first MOST ring. + uint32_t mostInst; + ///The device identifier (group address) as specified in the XML file. + uint32_t deviceId; + ///The instance number of the device. Starting with 0 for the first device with deviceId. + uint32_t deviceInst; + ///The MOST Function Block Identifier + uint32_t nFBlock; + ///The MOST Function Block Instance Identifier + uint32_t nInst; + ///The MOST Function Block Function Identifier + uint32_t nFunc; + ///The MOST Function Block Function Operation Type + uint32_t nOpType; + ///The amount of bytes stored in Payload + uint32_t nPayloadLen; +} MostMcmDev_t; + +/*----------------------------------------------------------*/ +/*! \brief Structure which holds information to address an MOST device via it's MOST instance and the MOST target address. + */ +/*----------------------------------------------------------*/ +typedef struct +{ + ///The MOST ring instance, starting with 0 for the first MOST ring. + uint32_t mostInst; + ///The MOST target address. + uint32_t targetAddr; +} MostPacketAddr_t; + +/*----------------------------------------------------------*/ +/*! \brief Structure which holds information of all MOST specific states. + */ +/*----------------------------------------------------------*/ +typedef struct +{ + //If this value is false, all other values must be ignored. + bool isValid; + ///The MOST ring instance, starting with 0 for the first MOST ring. + uint8_t mostInstance; + ///If set to true, the MOST ring is fully functional. Otherwise, no data can be transported. + bool available; + ///Shows the amount of nodes for the specific MOST ring. + uint8_t maxPos; + ///Shows how many bytes in a MOST frame is reserved for Packet (IP) data. + uint16_t packetBW; +} NetworkInformation_t; + +static void PrintMenu(); + +/*! +* \brief Applications main entry point and event handler, as it implements callbacks from CNetworkListener. +* It controls the Network via the CNetwork class. +* Isochronous TX connections will be automatically connected to the CMultiplexer class. +*/ +class CNetworkManagerHandler : public CNetworkListner, public CThread +{ +private: + class MostListener + { + private: + CSafeVector<CMsgAddr *> allListeners; + + public: + MostListener() + { + } + + ~MostListener() + { + for (uint32_t i = 0; i < allListeners.Size(); i++) + allListeners[i]->RemoveReference(); + allListeners.RemoveAll(false); + } + + void RemoveListener( CMsgAddr *pAddr ) + { + if( NULL == pAddr ) + return; + allListeners.Remove(pAddr); + pAddr->RemoveReference(); + } + + void AddListener( CMsgAddr *pAddr ) + { + if( NULL == pAddr ) + return; + + for (uint32_t i = 0; i < allListeners.Size(); i++) + { + CMsgAddr *l = allListeners[i]; + if (NULL != l + && l->GetProtocol() == pAddr->GetProtocol() + && 0 == strcmp(l->GetInetAddress(), pAddr->GetInetAddress())) + { + if (l->GetPort() == pAddr->GetPort()) + { + //Already registered with the same port, do not continue + return; + } + else + { + //The client reconnected with different (random) port. + //Remove old connection + allListeners.Remove(l); + l->RemoveReference(); + break; + } + } + } + pAddr->AddReference(); + allListeners.PushBack( pAddr ); + } + + uint32_t GetCount() + { + return allListeners.Size(); + } + + CMsgAddr *GetListener( uint32_t index ) + { + return allListeners[index]; + } + }; + + NetworkInformation_t allStates[AMOUNT_OF_NETWORK_STATES]; + CNetwork *network; + bool allowThreadRun; + uint32_t updateCount; + static const uint32_t updateCountMaxVal = 3; + + CMostIpc *mostIpc; + CMsgFilter *serverVersion_Get; + CMsgFilter *subscribeMcm_Set; + CMsgFilter *unsubscribeMcm_Set; + CMsgFilter *sendMcmAdr_Set; + CMsgFilter *sendMcmDev_Set; + CMsgFilter *counterRoute_Get; + CMsgFilter *executeConfigFile_Set; + CMsgFilter *executeScriptFile_Set; + CMsgFilter *executeScriptBuffer_Set; + CMsgFilter *connectionList_Get; + CMsgFilter *ringBreakDiagnosis_Get; + CMsgFilter *netState_Get; + + MostListener netStateListener; + MostListener mcmListener; + MostListener connectionListener; + MostListener rbdListener; + +public: + CConnectionInfoContainer infoContainer; + + CNetworkManagerHandler() : CThread( "CNetworkManagerHandler", + false ), allowThreadRun( true ), updateCount( updateCountMaxVal ) + { + memset(allStates, 0, sizeof(allStates)); + + network = CNetwork::GetInstance(); + network->AddListener( this ); + + mostIpc = new CMostIpc( IPC_PORT_NUMBER_NM, true ); + + serverVersion_Get = new CMsgFilter( FBLOCK_NETWORK_MANAGER, FUNC_NM_SERVERVERSION, + CMostMsg::OP_GET, OnServerVersion_Get ); + mostIpc->RegisterMessageHandler( serverVersion_Get ); + + subscribeMcm_Set = new CMsgFilter( FBLOCK_NETWORK_MANAGER, FUNC_NM_SUBSCRIBE_MCM, + CMostMsg::OP_SET, OnSubscribeMcm_Set ); + mostIpc->RegisterMessageHandler( subscribeMcm_Set ); + + unsubscribeMcm_Set = new CMsgFilter( FBLOCK_NETWORK_MANAGER, FUNC_NM_UNSUBSCRIBE_MCM, + CMostMsg::OP_SET, OnUnsubscribeMcm_Set ); + mostIpc->RegisterMessageHandler( unsubscribeMcm_Set ); + + sendMcmAdr_Set = new CMsgFilter( FBLOCK_NETWORK_MANAGER, FUNC_NM_SEND_MCM_ADR, + CMostMsg::OP_SET, OnMcmSendAddress_Set ); + mostIpc->RegisterMessageHandler( sendMcmAdr_Set ); + + sendMcmDev_Set = new CMsgFilter( FBLOCK_NETWORK_MANAGER, FUNC_NM_SEND_MCM_DEV, + CMostMsg::OP_SET, OnMcmSendDevice_Set ); + mostIpc->RegisterMessageHandler( sendMcmDev_Set ); + + counterRoute_Get = new CMsgFilter( FBLOCK_NETWORK_MANAGER, FUNC_NM_COUNTER_ROUTE, + CMostMsg::OP_GET, OnCounterRoute_Get ); + mostIpc->RegisterMessageHandler( counterRoute_Get ); + + executeConfigFile_Set = new CMsgFilter( FBLOCK_NETWORK_MANAGER, FUNC_NM_EXECUTE_CONFIG, + CMostMsg::OP_SET, OnExecuteConfigFile_Set ); + mostIpc->RegisterMessageHandler( executeConfigFile_Set ); + + executeScriptFile_Set = new CMsgFilter( FBLOCK_NETWORK_MANAGER, FUNC_NM_EXECUTE_SCRIPT_FILE, + CMostMsg::OP_SET, OnExecuteScriptFile_Set ); + mostIpc->RegisterMessageHandler( executeScriptFile_Set ); + + executeScriptBuffer_Set = new CMsgFilter( FBLOCK_NETWORK_MANAGER, FUNC_NM_EXECUTE_SCRIPT_MEM, + CMostMsg::OP_SET, OnExecuteScriptBuffer_Set ); + mostIpc->RegisterMessageHandler( executeScriptBuffer_Set ); + + connectionList_Get = new CMsgFilter( FBLOCK_NETWORK_MANAGER, FUNC_NM_CONNECTION_LIST, + CMostMsg::OP_GET, OnConnectionList_Get ); + mostIpc->RegisterMessageHandler( connectionList_Get ); + + ringBreakDiagnosis_Get = new CMsgFilter( FBLOCK_NETWORK_MANAGER, FUNC_NM_RING_BREAK_DIAGNOSIS, + CMostMsg::OP_GET, OnRingBreakDiagnosis_Get ); + mostIpc->RegisterMessageHandler( ringBreakDiagnosis_Get ); + + netState_Get = new CMsgFilter( FBLOCK_NETWORK_MANAGER, FUNC_NM_NET_STATE, + CMostMsg::OP_GET, OnNetState_Get ); + mostIpc->RegisterMessageHandler( netState_Get ); + + Start(); + } + + virtual ~CNetworkManagerHandler() + { + allowThreadRun = false; + Stop(); + infoContainer.DestroyAllInfos(); + if( NULL != network ) + { + network->RemoveListener( this ); + delete network; + network = NULL; + } + if( NULL != mostIpc ) + { + delete mostIpc; + mostIpc = NULL; + } + if( NULL != subscribeMcm_Set ) + { + delete subscribeMcm_Set; + subscribeMcm_Set = NULL; + } + if( NULL != unsubscribeMcm_Set ) + { + delete unsubscribeMcm_Set; + unsubscribeMcm_Set = NULL; + } + if( NULL != sendMcmAdr_Set ) + { + delete sendMcmAdr_Set; + sendMcmAdr_Set = NULL; + } + if( NULL != sendMcmDev_Set ) + { + delete sendMcmDev_Set; + sendMcmDev_Set = NULL; + } + if( NULL != counterRoute_Get ) + { + delete counterRoute_Get; + counterRoute_Get = NULL; + } + if( NULL != executeConfigFile_Set ) + { + delete executeConfigFile_Set; + executeConfigFile_Set = NULL; + } + if( NULL != executeScriptFile_Set ) + { + delete executeScriptFile_Set; + executeScriptFile_Set = NULL; + } + if( NULL != executeScriptBuffer_Set ) + { + delete executeScriptBuffer_Set; + executeScriptBuffer_Set = NULL; + } + if( NULL != connectionList_Get ) + { + delete connectionList_Get; + connectionList_Get = NULL; + } + if( NULL != ringBreakDiagnosis_Get ) + { + delete ringBreakDiagnosis_Get; + ringBreakDiagnosis_Get = NULL; + } + if( NULL != netState_Get ) + { + delete netState_Get; + netState_Get = NULL; + } + } + + static void OnServerVersion_Get( CMsgAddr *pAddr, CMostMsg *pMsg ) + { + if( NULL == s_mainClass || NULL == pAddr || NULL == pMsg ) + { + ConsolePrintf( PRIO_ERROR, RED"OnServerVersion_Get parameters are invalid."RESETCOLOR"\n" ); + return; + } + ConsolePrintf( PRIO_HIGH, + GREEN"MOST-IPC Client connected. ip=%s"RESETCOLOR"\n", pAddr->GetInetAddress() ); + + const uint8_t version[] = + { + NM_VERSION_MAJOR, NM_VERSION_MINOR, + NM_VERSION_BUGFIX, NM_VERSION_BUILD + }; + CMostMsgTx *mostMsg = new CMostMsgTx( pAddr,FBLOCK_NETWORK_MANAGER, + 0, FUNC_NM_SERVERVERSION, CMostMsg::OP_STATUS, sizeof ( version ), + version, 500, NULL, NULL ); + s_mainClass->mostIpc->SendMsg( mostMsg ); + mostMsg->RemoveReference(); + } + + static void OnSubscribeMcm_Set( CMsgAddr *pAddr, CMostMsg *pMsg ) + { + if( NULL == s_mainClass || NULL == pAddr || NULL == pMsg ) + { + ConsolePrintf( PRIO_ERROR, RED"OnSubscribeMcm_Set parameters are invalid."RESETCOLOR"\n" ); + return; + } + ConsolePrintf( PRIO_MEDIUM, + GREEN"MOST-IPC Client subscribed for MCM. ip=%s"RESETCOLOR"\n", pAddr->GetInetAddress() ); + s_mainClass->mcmListener.AddListener( pAddr ); + } + + static void OnUnsubscribeMcm_Set( CMsgAddr *pAddr, CMostMsg *pMsg ) + { + if( NULL == s_mainClass || NULL == pAddr || NULL == pMsg ) + { + ConsolePrintf( PRIO_ERROR, RED"OnUnsubscribeMcm_Set parameters are invalid."RESETCOLOR"\n" ); + return; + } + ConsolePrintf( PRIO_MEDIUM, + GREEN"MOST-IPC Client unsubscribed for MCM. ip=%s"RESETCOLOR"\n", pAddr->GetInetAddress() ); + s_mainClass->mcmListener.RemoveListener( pAddr ); + } + + static void OnMcmSendAddress_Set( CMsgAddr *pAddr, CMostMsg *pMsg ) + { + if( NULL == s_mainClass || NULL == pAddr || NULL == pMsg ) + { + ConsolePrintf( PRIO_ERROR, RED"OnMcmSend_Set parameters are invalid."RESETCOLOR"\n" ); + return; + } + MostMcmAdr_t *mcm = ( MostMcmAdr_t * )pMsg->GetPayload(); + if( NULL == mcm || pMsg->GetPayloadLen() < sizeof( MostMcmAdr_t ) ) + { + ConsolePrintf( PRIO_ERROR, + RED"OnMcmSend_Set payload length is too small to carry a MCM message."RESETCOLOR"\n" ); + return; + } + ConsolePrintfStart( PRIO_MEDIUM, + GREEN"MOST-IPC Client send MCM to MOST address. ip=%s, ring-inst:%d"\ + "target:0x%X, fblock:0x%X, inst:%d, func:0x%x, op:0x%X, p:0x[", pAddr->GetInetAddress(), mcm->mostInst, + mcm->targetAddr, mcm->nFBlock, mcm->nInst, mcm->nFunc, mcm->nOpType ); + uint8_t *payload = &( ( uint8_t * )mcm )[sizeof( MostMcmAdr_t )]; + for( uint32_t i = 0; i < mcm->nPayloadLen; i++ ) + { + ConsolePrintfContinue( " %02X", payload[i] ); + } + ConsolePrintfExit( "]"RESETCOLOR"\n" ); + + s_mainClass->SendMostControlMessage( mcm->mostInst, mcm->targetAddr, mcm->nFBlock, mcm->nInst, mcm->nFunc, + mcm->nOpType, mcm->nPayloadLen, payload ); + } + + static void OnMcmSendDevice_Set( CMsgAddr *pAddr, CMostMsg *pMsg ) + { + if( NULL == s_mainClass || NULL == pAddr || NULL == pMsg ) + { + ConsolePrintf( PRIO_ERROR, RED"OnMcmSend_Set parameters are invalid."RESETCOLOR"\n" ); + return; + } + MostMcmDev_t *mcm = ( MostMcmDev_t * )pMsg->GetPayload(); + if( NULL == mcm || pMsg->GetPayloadLen() < sizeof( MostMcmDev_t ) ) + { + ConsolePrintf( PRIO_ERROR, + RED"OnMcmSend_Set payload length is too small to carry a MCM message."RESETCOLOR"\n" ); + return; + } + ConsolePrintfStart( PRIO_MEDIUM, + GREEN"MOST-IPC Client send MCM to specific device. ip=%s, ring-inst:%d"\ + "device-id:0x%X, device-instance:%d, fblock:0x%X, inst:%d, func:0x%x, op:0x%X, p:0x[", + pAddr->GetInetAddress(), mcm->mostInst, mcm->deviceId, mcm->deviceInst, mcm->nFBlock, mcm->nInst, + mcm->nFunc, mcm->nOpType ); + uint8_t *payload = &( ( uint8_t * )mcm )[sizeof( MostMcmAdr_t )]; + for( uint32_t i = 0; i < mcm->nPayloadLen; i++ ) + { + ConsolePrintfContinue( " %02X", payload[i] ); + } + ConsolePrintfExit( "]"RESETCOLOR"\n" ); + + s_mainClass->SendMostControlMessage( mcm->mostInst, mcm->deviceId, mcm->deviceInst, mcm->nFBlock, mcm->nInst, + mcm->nFunc, mcm->nOpType, mcm->nPayloadLen, payload ); + } + + static void OnCounterRoute_Get( CMsgAddr *pAddr, CMostMsg *pMsg ) + { + if( NULL == s_mainClass || NULL == pAddr || NULL == pMsg ) + { + ConsolePrintf( PRIO_ERROR, RED"OnCounterRoute_Get parameters are invalid."RESETCOLOR"\n" ); + return; + } + CNetwork::Route_t *inRoute = ( CNetwork::Route_t * )pMsg->GetPayload(); + if( NULL == inRoute || pMsg->GetPayloadLen() < sizeof( CNetwork::Route_t ) ) + { + ConsolePrintf( PRIO_ERROR, + RED"OnCounterRoute_Get payload length is too small to carry a Route_t message."RESETCOLOR + "\n" ); + return; + } + CNetwork::Route_t *outRoutes = NULL; + uint32_t routeElements = s_mainClass->network->GetCounterPartOfRoute( inRoute, &outRoutes ); + ConsolePrintfStart( PRIO_MEDIUM, + GREEN"MOST-IPC Client asked for counter route for: (deviceType:0x%X, inst:%d, channelId:%d), Result:", + inRoute->deviceType, inRoute->instance, inRoute->channelId ); + for( uint32_t i = 0; NULL != outRoutes && i < routeElements; i++ ) + { + ConsolePrintfContinue( " (deviceType:0x%X, inst:%d, channelId:%d)", outRoutes[i].deviceType, + outRoutes[i].instance, outRoutes[i].channelId ); + } + ConsolePrintfExit( RESETCOLOR"\n" ); + uint32_t bufferLen = ( routeElements + 1 ) * sizeof( CNetwork::Route_t ); + uint8_t *buffer = ( uint8_t * )malloc( bufferLen ); + if( NULL == buffer ) + { + free( outRoutes ); + ConsolePrintf( PRIO_ERROR, + RED"OnCounterRoute_Get payload failed to allocate memory for response."RESETCOLOR + "\n" ); + return; + } + //Copy request to response element 0 + memcpy( buffer, inRoute, sizeof( CNetwork::Route_t ) ); + //Copy the results beginning at element 1 + if( 0 != routeElements ) + memcpy( &buffer[sizeof( CNetwork::Route_t )], outRoutes, routeElements * sizeof( CNetwork::Route_t ) ); + free( outRoutes ); + + CMostMsgTx *mostMsg = new CMostMsgTx( pAddr, //Addr + FBLOCK_NETWORK_MANAGER, // nFBlock + 0, // nInst + FUNC_NM_COUNTER_ROUTE, // nFunc + CMostMsg::OP_STATUS, // nOpType + bufferLen, //nPayloadLen + buffer, //Payload + 500, //nTimeoutMs + NULL, //MessageSentCB + NULL ); //UserContext + s_mainClass->mostIpc->SendMsg( mostMsg ); + mostMsg->RemoveReference(); + free( buffer ); + } + + static void OnExecuteConfigFile_Set( CMsgAddr *pAddr, CMostMsg *pMsg ) + { + if( NULL == s_mainClass || NULL == pAddr || NULL == pMsg || 0 == pMsg->GetPayloadLen() ) + { + ConsolePrintf( PRIO_ERROR, RED"OnExecuteScriptFile_Set parameters are invalid."RESETCOLOR"\n" ); + return; + } + char *fileName = ( char * )pMsg->GetPayload(); + ConsolePrintf( PRIO_HIGH, "Executing new config file:%s\n", fileName); + s_mainClass->network->LoadConfig(fileName); + } + + static void OnExecuteScriptFile_Set( CMsgAddr *pAddr, CMostMsg *pMsg ) + { + if( NULL == s_mainClass || NULL == pAddr || NULL == pMsg ) + { + ConsolePrintf( PRIO_ERROR, RED"OnExecuteScriptFile_Set parameters are invalid."RESETCOLOR"\n" ); + return; + } + MostPacketAddr_t *addr = ( MostPacketAddr_t * )pMsg->GetPayload(); + if( NULL == addr || pMsg->GetPayloadLen() <= sizeof( MostPacketAddr_t ) ) + { + ConsolePrintf( PRIO_ERROR, + RED"OnExecuteScriptFile_Set payload length is too small to carry a MCM message."RESETCOLOR"\n" ); + return; + } + char *payload = ( char * )( pMsg->GetPayload() + sizeof( MostPacketAddr_t ) ); + s_mainClass->network->ExecuteXmlScriptFromFile( addr->mostInst, addr->targetAddr, payload ); + } + + static void OnExecuteScriptBuffer_Set( CMsgAddr *pAddr, CMostMsg *pMsg ) + { + if( NULL == s_mainClass || NULL == pAddr || NULL == pMsg ) + { + ConsolePrintf( PRIO_ERROR, RED"OnExecuteScriptFile_Set parameters are invalid."RESETCOLOR"\n" ); + return; + } + MostPacketAddr_t *addr = ( MostPacketAddr_t * )pMsg->GetPayload(); + if( NULL == addr || pMsg->GetPayloadLen() <= sizeof( MostPacketAddr_t ) ) + { + ConsolePrintf( PRIO_ERROR, + RED"OnExecuteScriptFile_Set payload length is too small to carry a MCM message."RESETCOLOR"\n" ); + return; + } + char *payload = ( char * )( pMsg->GetPayload() + sizeof( MostPacketAddr_t ) ); + uint32_t payloadLen = pMsg->GetPayloadLen() - sizeof( MostPacketAddr_t ); + s_mainClass->network->ExecuteXmlScriptFromMemory( addr->mostInst, addr->targetAddr, payload, payloadLen ); + } + + static void OnConnectionList_Get( CMsgAddr *pAddr, CMostMsg *pMsg ) + { + if( NULL == s_mainClass || NULL == pAddr || NULL == pMsg ) + { + ConsolePrintf( PRIO_ERROR, RED"OnConnectionList_Get parameters are invalid."RESETCOLOR"\n" ); + return; + } + + s_mainClass->connectionListener.AddListener( pAddr ); + + char *pBuffer = ( char * )malloc( IPC_TEMP_BUFFER_SIZE ); + uint32_t used = s_mainClass->infoContainer.SerializeToString( pBuffer, IPC_TEMP_BUFFER_SIZE ); + CMostMsgTx *mostMsg = new CMostMsgTx( pAddr, //Addr + FBLOCK_NETWORK_MANAGER, // nFBlock + 0, // nInst + FUNC_NM_CONNECTION_LIST, // nFunc + CMostMsg::OP_STATUS, // nOpType + used, //nPayloadLen + ( uint8_t * )pBuffer, //Payload + 500, //nTimeoutMs + NULL, //MessageSentCB + NULL ); //UserContext + s_mainClass->mostIpc->SendMsg( mostMsg ); + mostMsg->RemoveReference(); + free( pBuffer ); + } + + static void OnRingBreakDiagnosis_Get( CMsgAddr *pAddr, CMostMsg *pMsg ) + { + if( NULL == s_mainClass || NULL == pAddr || NULL == pMsg ) + { + ConsolePrintf( PRIO_ERROR, RED"OnRingBreakDiagnosis_Get parameters are invalid."RESETCOLOR"\n" ); + return; + } + s_mainClass->rbdListener.AddListener( pAddr ); + s_mainClass->network->GetRingBreakDiagnosisResult( 0, 1 ); + } + + static void OnNetState_Get( CMsgAddr *pAddr, CMostMsg *pMsg ) + { + if( NULL == s_mainClass || NULL == pAddr || NULL == pMsg ) + { + ConsolePrintf( PRIO_ERROR, RED"OnNetState_Get parameters are invalid."RESETCOLOR"\n" ); + return; + } + s_mainClass->netStateListener.AddListener( pAddr ); + + for (uint32_t i = 0; i < AMOUNT_OF_NETWORK_STATES; i++) + { + if (!s_mainClass->allStates[i].isValid) + continue; + s_mainClass->SendNetworkState(pAddr, s_mainClass->allStates[i].mostInstance, + s_mainClass->allStates[i].available, s_mainClass->allStates[i].maxPos, + s_mainClass->allStates[i].packetBW); + } + } + + void SendNetworkState( CMsgAddr *addr, uint8_t mostInstance, bool available, uint8_t maxPos, uint16_t packetBW ) + { + uint8_t p[5]; + p[0] = mostInstance; + p[1] = available; + p[2] = maxPos; + p[3] = packetBW /256; + p[4] = packetBW %256; + CMostMsgTx *mostMsg = new CMostMsgTx( addr, //Addr + FBLOCK_NETWORK_MANAGER, // nFBlock + 0, // nInst + FUNC_NM_NET_STATE, // nFunc + CMostMsg::OP_STATUS, // nOpType + sizeof(p), //nPayloadLen + p, //Payload + 500, //nTimeoutMs + NULL, //MessageSentCB + NULL ); //UserContext + s_mainClass->mostIpc->SendMsg( mostMsg ); + mostMsg->RemoveReference(); + } + +public: + + static CNetworkManagerHandler *GetInstance() + { + if( NULL == s_mainClass ) + s_mainClass = new CNetworkManagerHandler(); + return s_mainClass; + } + + static void DestroyInstance() + { + if( NULL != s_mainClass ) + { + delete s_mainClass; + s_mainClass = NULL; + } + } + + void SetPromiscuousMode( bool promiscuousMode ) + { + network->SetPromiscuousMode( promiscuousMode ); + } + + virtual void Run() + { + if( allowThreadRun ) + { + if( !network->ActionsPending() + && ( updateCount > 0 ) + && ( 0 == --updateCount ) ) + { + if( 0 != network->GetAmountOfLocalNodes() ) + { + infoContainer.PrintTable( false, false ); + SendConnectionList(); + } + else + { + ConsolePrintf( PRIO_ERROR, RED \ + "No local attached INIC was found. Are the drivers loaded? Was the device found, try 'lsusb'?" \ + RESETCOLOR"\n" ); + } + } + } + usleep( 100000 ); + } + + void SendConnectionList() + { + char *pBuffer = ( char * )malloc( IPC_TEMP_BUFFER_SIZE ); + uint32_t used = s_mainClass->infoContainer.SerializeToString( pBuffer, IPC_TEMP_BUFFER_SIZE ); + for( uint32_t i = 0; i < connectionListener.GetCount(); i++ ) + { + CMostMsgTx *mostMsg = new CMostMsgTx( connectionListener.GetListener( i ), //Addr + FBLOCK_NETWORK_MANAGER, // nFBlock + 0, // nInst + FUNC_NM_CONNECTION_LIST, // nFunc + CMostMsg::OP_STATUS, // nOpType + used, //nPayloadLen + ( uint8_t * )pBuffer, //Payload + 500, //nTimeoutMs + NULL, //MessageSentCB + NULL ); //UserContext + s_mainClass->mostIpc->SendMsg( mostMsg ); + mostMsg->RemoveReference(); + } + free( pBuffer ); + } + + /*----------------------------------------------------------*/ + /*! \brief Determines, if there are ongoing MOST transactions enqueued. + * \return true, if there are still transactions ongoing. false, the system is idle. + */ + /*----------------------------------------------------------*/ + bool ActionsPending() + { + return network->ActionsPending(); + } + + /*----------------------------------------------------------*/ + /*! \brief Loads the given configuration XML file. This will start up the MOST ring, and the + * connections will be created. + * \param szConfigXml - string holding only the filename to the XML file. + * \param szSearchPath - string holding the path to all the XML files. + * \return true, if the file could be parsed, and the initial MOST setup was successful. + */ + /*----------------------------------------------------------*/ + bool LoadConfig( const char *szConfigXml, const char *szSearchPath ) + { + return network->LoadConfig( szConfigXml, szSearchPath ); + } + + /*----------------------------------------------------------*/ + /*! \brief Connects the given source with the given sink. The index is relative to the list, + reported by the PrintTable method of the CConnectionInfo class. + * \return true, if the connection may be acceptable. The transactions were enqueued to be performed asynchronously. + * false, the connection can not be established. + */ + /*----------------------------------------------------------*/ + bool ConnectDevices( uint32_t sourceIndex, uint32_t sinkIndex ) + { + bool success = false; + if( sourceIndex < infoContainer.GetAllInfoAmount() + && sinkIndex < infoContainer.GetAllInfoAmount() ) + { + CConnectionInfo *source = infoContainer.GetInfo( sourceIndex ); + CConnectionInfo *sink = infoContainer.GetInfo( sinkIndex ); + success = network->ConnectSourceToSink( source->macAddr, source->channelId, sink->macAddr, + sink->channelId ); + if( success ) + { + sink->mostConnectionLabel = source->mostConnectionLabel; + } + } + return success; + } + + /*----------------------------------------------------------*/ + /*! \brief Retrieves the corresponding sink index for the given MAC address + * \param pMacAddress - Pointer to the byte array with length 6, holding the MAC address + * \return The sink index if found, otherwise 0xFFFFFFFF + */ + /*----------------------------------------------------------*/ + uint32_t GetSinkIndex( uint8_t *pMacAddress ) + { + uint32_t returnVal = 0xFFFFFFFF; + if( NULL == pMacAddress ) + return returnVal; + CMacAddr *mac1 = new CMacAddr( pMacAddress[0], pMacAddress[1], + pMacAddress[2], pMacAddress[3], pMacAddress[4], pMacAddress[5] ); + for( uint32_t i = 0; i < infoContainer.GetAllInfoAmount(); i++ ) + { + CConnectionInfo *info = infoContainer.GetInfo( i ); + if( NULL == info ) + continue; + CMacAddr *mac2 = info->macAddr; + if( *mac1 == *mac2 ) + { + if( !info->isTX ) + { + returnVal = i; + break; + } + } + } + delete mac1; + return returnVal; + } + + /*----------------------------------------------------------*/ + /*! \brief Sends the given Control Message out to the given MOST ring. + * \param mostInstance - The MOST ring instance, starting with 0 for the first MOST ring. + * \param targetAddr - The MOST target address (0x100, 0x401, etc..) + * \param nFBlock - The MOST Function Block Identifier + * \param nInst - The MOST Function Block Instance Identifier + * \param nFunc - The MOST Function Block Function Identifier + * \param nPayloadLen - The amount of bytes stored in Payload + * \param Payload - The pointer to the payload byte array. + */ + /*----------------------------------------------------------*/ + bool 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 ) + { + return network->SendMostControlMessage( mostInstance, targetAddr, nFBlock, nInst, nFunc, nOpType, nPayloadLen, + Payload ); + } + + bool GetRingBreakDiagnosisResult() + { + return network->GetRingBreakDiagnosisResult( 0, 1 ); + } + + void DebugEnableMost(bool enabled) + { + network->EnableMost(enabled); + } + + /*----------------------------------------------------------*/ + /*! \brief Sends the given Control Message out to the given MOST ring. + * \param mostInstance - The MOST ring instance, starting with 0 for the first MOST ring. + * \param deviceId - The device identifier (group address) as specified in the XML file. + * \param devInst - The instance number of the device. Starting with 0 for the first device with deviceId. + * \param nFBlock - The MOST Function Block Identifier + * \param nInst - The MOST Function Block Instance Identifier + * \param nFunc - The MOST Function Block Function Identifier + * \param nPayloadLen - The amount of bytes stored in Payload + * \param Payload - The pointer to the payload byte array. + */ + /*----------------------------------------------------------*/ + bool 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 ) + { + return network->SendMostControlMessage( mostInstance, deviceId, devInst, nFBlock, nInst, nFunc, nOpType, + nPayloadLen, Payload ); + } + + virtual void OnNetworkState( uint8_t mostInstance, bool available, uint8_t maxPos, uint16_t packetBW ) + { + ConsolePrintf( PRIO_LOW, ">>>>>>>>>>>>>> OnNetworkState available=%s, mpr=%d, sbc=%d\n", + available ? "yes" : "no", maxPos, packetBW ); + + if (mostInstance >= AMOUNT_OF_NETWORK_STATES) + { + ConsolePrintf(PRIO_ERROR, RED"OnNetworkState MOST instance is out "\ + "of range, please increase AMOUNT_OF_NETWORK_STATES define"RESETCOLOR"\n"); + } + else + { + allStates[mostInstance].isValid = true; + allStates[mostInstance].available = available; + allStates[mostInstance].maxPos = maxPos; + allStates[mostInstance].packetBW = packetBW; + } + + for( uint32_t i = 0; i < netStateListener.GetCount(); i++ ) + { + SendNetworkState( netStateListener.GetListener( i ),mostInstance, available, maxPos, packetBW ); + } + } + + virtual void 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 ) + { + if( NULL != macAddr ) + { + CConnectionInfo *info = infoContainer.GetInfo( macAddr, channelId, mostInstance, isSourceDevice ); + if( NULL == info ) + return; + updateCount = updateCountMaxVal; + info->deviceType = deviceId; + info->deviceInstance = devInst; + info->dataType = dataType; + info->reservedBandwidth = reservedBandwidth; + info->bufferSize = bufferSize; + info->inSocketCreated = inSocketCreated; + info->outSocketCreated = outSocketCreated; + info->socketsConnected = socketsConnected; + info->mostConnectionLabel = mostConnectionLabel; + info->splittedOffset = splittedOffset; + info->splittedMaxBandwidth = splittedMaxBandwidth; + info->packetsPerXact = packetsPerXact; + if( NULL != deviceName && strlen( deviceName ) != 0 ) + { + strncpy( info->deviceName, deviceName, sizeof( info->deviceName ) ); + } + } + else + { + ConsolePrintf( PRIO_LOW, ">>>>>>>>>>>>>> OnChannelAvailable, MAC:unknown, channel-Id:%d, " \ + "MOST-Inst:%d, TX:%d, in:%d, out:%d, con:%d, name:%s\n", channelId, mostInstance, isSourceDevice, + inSocketCreated, outSocketCreated, socketsConnected, deviceName ); + } + } + + virtual void OnChannelUnavailable( CMacAddr *macAddr, TChannelId channelId, uint8_t mostInstance ) + { + updateCount = updateCountMaxVal; + ConsolePrintf( PRIO_LOW, ">>>>>>>>>>>>>> OnChannelUnavailable, MAC:%s, channel-Id:%d" \ + ", MOST-Inst:%d\n", macAddr->ToString(), ( uint32_t )channelId, mostInstance ); + + infoContainer.DestroyInfo( macAddr, channelId, mostInstance ); + } + + virtual void 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 ) + { + ConsolePrintfStart( PRIO_MEDIUM, ">>>>>>>>>>>>>> OnMostControlMessage, source:0x%X, " \ + "target:0x%X, FBlock:0x%X, Inst:%d, Func:0x%X, OP:0x%X, Len:%d, P:0x[", sourceAddr, targetAddr, nFBlock, + nInst, nFunc, nOpType, nPayloadLen ); + for( uint32_t i = 0; NULL != Payload && i < nPayloadLen; i++ ) + ConsolePrintfContinue( "%02X ", Payload[i] ); + ConsolePrintfExit( " ]\n" ); + + uint32_t bufLen = sizeof( MostMcmAdr_t ) + nPayloadLen; + MostMcmAdr_t *mcm = ( MostMcmAdr_t * )calloc( 1, bufLen ); + if( NULL == mcm ) + { + ConsolePrintf( PRIO_ERROR, RED"Failed to allocate memory: OnMostControlMessage"RESETCOLOR"\n" ); + return; + } + mcm->sourceAddr = sourceAddr; + mcm->targetAddr = targetAddr; + mcm->nFBlock = nFBlock; + mcm->nInst = nInst; + mcm->nFunc = nFunc; + mcm->nOpType = nOpType; + mcm->nPayloadLen = nPayloadLen; + uint8_t *pBuffer = ( uint8_t * )mcm; + memcpy( &pBuffer[sizeof( MostMcmAdr_t )], Payload, nPayloadLen ); + + for( uint32_t i = 0; i < mcmListener.GetCount(); i++ ) + { + CMsgAddr *c = mcmListener.GetListener( i ); + if( NULL == c ) + break; + CMostMsgTx *mostMsg = new CMostMsgTx( c, FBLOCK_NETWORK_MANAGER, + 0, FUNC_NM_RECEIVED_MCM, CMostMsg::OP_STATUS, bufLen, + pBuffer, 500, NULL, NULL ); + mostIpc->SendMsg( mostMsg ); + mostMsg->RemoveReference(); + } + } + + virtual void OnRingBreakDiagnosisResultV3( uint8_t devInst, uint16_t nodeAddress, uint8_t result, + uint8_t position, uint8_t status, uint16_t id ) + { + uint8_t pBuffer[8]; + pBuffer[0] = devInst; + pBuffer[1] = nodeAddress / 256; + pBuffer[2] = nodeAddress % 256; + pBuffer[3] = result; + pBuffer[4] = position; + pBuffer[5] = status; + pBuffer[6] = id / 256; + pBuffer[7] = id % 256; + + for( uint32_t i = 0; i < rbdListener.GetCount(); i++ ) + { + CMsgAddr *c = rbdListener.GetListener( i ); + if( NULL == c ) + break; + CMostMsgTx *mostMsg = new CMostMsgTx( c, FBLOCK_NETWORK_MANAGER, + 0, FUNC_NM_RING_BREAK_DIAGNOSIS, CMostMsg::OP_STATUS, sizeof( pBuffer ), + pBuffer, 500, NULL, NULL ); + mostIpc->SendMsg( mostMsg ); + mostMsg->RemoveReference(); + } + } +}; + +static void PrintMenu() +{ + ConsolePrintfStart( PRIO_HIGH, "Main Menu, press key and enter:\n" ); + ConsolePrintfContinue( "-------------------------------\n" ); + ConsolePrintfContinue( " m - Print this menu\n" ); + ConsolePrintfContinue( " p - Print Connection List\n" ); + ConsolePrintfContinue( " c - Connect Source and Sink\n" ); + ConsolePrintfContinue( " s - Send sample control message to MOST ring\n" ); + ConsolePrintfContinue( " r - Get Ring Break Diagnosis Result\n" ); + ConsolePrintfContinue( " x - Exit this application\n" ); + ConsolePrintfContinue( "==Debugging==\n" ); + ConsolePrintfContinue( " 0 - Turn off MOST\n" ); + ConsolePrintfContinue( " 1 - Turn on MOST\n" ); + ConsolePrintfExit( "-------------------------------\n" ); +} + +int main( int argc, char *argv[] ) +{ + int sourceIndex, sinkIndex; + + ConsoleInit( false ); + + char *configName = NULL; + char *searchPath = NULL; + bool disableMenu = true; + ConsolePrio_t prio = PRIO_HIGH; + bool promiscuousMode = false; + + if( 2 == argc && strstr( argv[1], ".xml" ) ) + { + configName = argv[1]; + } + else + { + for( int32_t i = 1; i < argc; i++ ) + { + if( strstr( argv[i], "-i" ) ) + { + if( argc <= ( i + 1 ) ) + { + ConsolePrintf( PRIO_ERROR, + RED"-i parameter requires configuration filename as next parameter"RESETCOLOR"\n" ); + return -1; + } + configName = argv[i + 1]; + i++; + } + else if( strstr( argv[i], "-p" ) ) + { + if( argc <= ( i + 1 ) ) + { + ConsolePrintf( PRIO_ERROR, + RED"-p parameter requires search path as next parameter"RESETCOLOR"\n" ); + return -1; + } + searchPath = argv[i + 1]; + i++; + } + else if( strstr( argv[i], "-vv" ) ) + { + prio = PRIO_LOW; + } + else if( strstr( argv[i], "-v" ) ) + { + prio = PRIO_MEDIUM; + } + else if( strstr( argv[i], "--help" ) ) + { + ConsolePrintfStart( PRIO_HIGH, "Usage: %s [OPTION] ... [FILE] ... \n", argv[0] ); + ConsolePrintfContinue( + "Example MOST4.0 NetworkManager, setup and configures all devices in an entire MOST network.\n" ); + + ConsolePrintfContinue( + "\t-i\t\t input configuration file, if there is no other options -i may be left away\n" ); + ConsolePrintfContinue( "\t-p\t\t path to search the configurations file, if not set,"\ + "the path will be extracted from the input configuration file\n" ); + ConsolePrintfContinue( "\t-m\t\t enable user menu\n" ); + ConsolePrintfContinue( "\t-s\t\t enable MEP promiscuous mode (Ethernet SPY)\n" ); + ConsolePrintfContinue( "\t-v\t\t verbose mode - print debug info\n" ); + ConsolePrintfContinue( "\t-vv\t\t super verbose mode - print even more debug info\n" ); + ConsolePrintfContinue( "Example: %s config.xml\n", argv[0] ); + ConsolePrintfContinue( "Example: %s -i /root/config.xml\n", argv[0] ); + ConsolePrintfExit( "Example: %s -i config.xml -p /root\n", argv[0] ); + return 0; + } + else if( strstr( argv[i], "-m" ) ) + { + disableMenu = false; + } + else if( strstr( argv[i], "-s" ) ) + { + ConsolePrintf( PRIO_HIGH, YELLOW"Warning promiscuous mode is activated (-s),"\ + " this may have negative impact on system load"RESETCOLOR"\n" ); + promiscuousMode = true; + } + else + { + ConsolePrintf( PRIO_ERROR, RED"Ignoring command line parameter"\ + " at pos %d: %s, type '%s --help' to see the correct parameter syntax"\ + RESETCOLOR"\n", i, argv[i], argv[0] ); + } + } + } + if( NULL == searchPath && NULL != configName ) + { + uint32_t len = strlen( configName ); + if( 0 != len ) + { + uint32_t stLen = ( len + 1 ); + searchPath = ( char * )calloc( stLen, sizeof( char ) ); + strncpy( searchPath, configName, stLen ); + int32_t pos = len; + for(; pos >= 0; pos-- ) + { + if( '/' == searchPath[pos] ) + { + searchPath[pos] = '\0'; + configName = &searchPath[pos + 1]; + break; + } + } + if( pos <= 0 ) + strncpy( searchPath, ".", stLen ); + } + } + + ConsoleSetPrio( prio ); + ConsolePrintf( PRIO_HIGH, BLUE"========== Network Manager Start =========="RESETCOLOR"\n" ); + CNetworkManagerHandler *mainClass = CNetworkManagerHandler::GetInstance(); + mainClass->SetPromiscuousMode( promiscuousMode ); + + if( NULL != configName && NULL != searchPath ) + { + ConsolePrintf( PRIO_HIGH, "Starting with configuration:'%s'. Search path:'%s'\n", configName, searchPath ); + if( !s_mainClass->LoadConfig( configName, searchPath ) ) + { + ConsolePrintf( PRIO_ERROR, RED"Failed to load configuration"RESETCOLOR"\n" ); + } + } + else + { + ConsolePrintf( PRIO_HIGH, "Starting without configuration. It must then be loaded via IPC command\n" ); + } + + int32_t timeout = 5; + do + { + usleep( 1000000 ); + } + while( mainClass->ActionsPending() && --timeout > 0 ); + if( timeout <= 0 ) + ConsolePrintf( PRIO_ERROR, + RED"Warning: main routine waited unusually long for finishing network setup"RESETCOLOR"\n" ); + + if( disableMenu || !isatty( fileno( stdin ) ) ) + { + while( true ) + sleep( 1 ); + } + else + { + PrintMenu(); + + while( true ) + { + int c = getchar(); + fflush( stdin ); + switch( c ) + { + case 'M': + case 'm': + PrintMenu(); + break; + + case 'R': + case 'r': + mainClass->GetRingBreakDiagnosisResult(); + break; + + case 'P': + case 'p': + mainClass->infoContainer.PrintTable( false, false ); + break; + + case 'C': + case 'c': + mainClass->infoContainer.PrintTable( false, false ); + ConsolePrintf( PRIO_HIGH, "Enter Source and Target Index:" ); + if( 0 != scanf( "%d %d", &sourceIndex, &sinkIndex ) ) + { + ConsolePrintf( PRIO_HIGH, "Connecting Source Index %d with Sink Index %d\n", sourceIndex, + sinkIndex ); + if( mainClass->ConnectDevices( sourceIndex, sinkIndex ) ) + { + do + { + usleep( 100000 ); + ConsolePrintf( PRIO_HIGH, "Wait for connection to be finished.\n" ); + } + while( mainClass->ActionsPending() ); + mainClass->infoContainer.PrintTable( false, false ); + } + else + { + ConsolePrintf( PRIO_ERROR, RED"Failed to connect devices"RESETCOLOR"\n" ); + } + } + break; + + case 'S': + case 's': + { + char test[] = "Hello World!\0"; + mainClass->SendMostControlMessage( 0, 0x3C8, 0xF0, 0, 0x100, 1, + strlen( test ), ( uint8_t * )test ); + break; + } + + case 'X': + case 'x': + CNetworkManagerHandler::DestroyInstance(); + usleep( 1000000 ); + ConsolePrintf( PRIO_HIGH, BLUE"========== Network Manager End =========="RESETCOLOR"\n" ); + ConsoleDeinit(); + return 0; + case '0': + mainClass->DebugEnableMost(false); + break; + case '1': + mainClass->DebugEnableMost(true); + break; + default: + break; + } + usleep( 10000 ); //Avoid high CPU load, if terminal is disconnected (running as daemon) + } + } +} |