summaryrefslogtreecommitdiffstats
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/ConnectionInfo.cpp712
-rw-r--r--Src/ConnectionInfo.h316
-rw-r--r--Src/Console.c209
-rw-r--r--Src/Console.h113
-rw-r--r--Src/DoxyGenStartPage.h375
-rw-r--r--Src/IP/MostIpc.cpp510
-rw-r--r--Src/IP/MostIpc.h164
-rw-r--r--Src/IP/MostMsg.cpp405
-rw-r--r--Src/IP/MostMsg.h184
-rw-r--r--Src/IP/MostMsgTx.cpp86
-rw-r--r--Src/IP/MostMsgTx.h96
-rw-r--r--Src/IP/MsgAddr.cpp71
-rw-r--r--Src/IP/MsgAddr.h73
-rw-r--r--Src/IP/MsgFilter.cpp47
-rw-r--r--Src/IP/MsgFilter.h72
-rw-r--r--Src/MacAddr.cpp165
-rw-r--r--Src/MacAddr.h153
-rw-r--r--Src/Main.cpp1255
-rw-r--r--Src/Network/IndustrialStack.cpp275
-rw-r--r--Src/Network/IndustrialStack.h238
-rw-r--r--Src/Network/IndustrialStack_ApiGeneric.h125
-rw-r--r--Src/Network/IndustrialStack_ApiV1.h712
-rw-r--r--Src/Network/IndustrialStack_ApiV3.h1123
-rw-r--r--Src/Network/IndustrialStack_LLD.cpp278
-rw-r--r--Src/Network/IndustrialStack_LLD.h148
-rw-r--r--Src/Network/IndustrialStack_MNS.cpp414
-rw-r--r--Src/Network/IndustrialStack_MNS.h84
-rw-r--r--Src/Network/IndustrialStack_Types.h159
-rw-r--r--Src/Network/Network.cpp433
-rw-r--r--Src/Network/Network.h498
-rw-r--r--Src/Network/NetworkDevice.cpp903
-rw-r--r--Src/Network/NetworkDevice.h862
-rw-r--r--Src/Network/NetworkDeviceListener.cpp306
-rw-r--r--Src/Network/NetworkDeviceListener.h568
-rw-r--r--Src/Network/Network_CB.cpp1823
-rw-r--r--Src/Network/Network_Private.cpp695
-rw-r--r--Src/Network/NodeDatabase.cpp287
-rw-r--r--Src/Network/NodeDatabase.h379
-rw-r--r--Src/Network/base/.svn/dir-prop-base14
-rw-r--r--Src/Network/base/.svn/entries164
-rw-r--r--Src/Network/base/.svn/prop-base/DriverConfiguration.c.svn-base5
-rw-r--r--Src/Network/base/.svn/prop-base/DriverConfiguration.h.svn-base5
-rw-r--r--Src/Network/base/.svn/text-base/Board.c.svn-base51
-rw-r--r--Src/Network/base/.svn/text-base/Board.h.svn-base63
-rw-r--r--Src/Network/base/.svn/text-base/DriverConfiguration.c.svn-base608
-rw-r--r--Src/Network/base/.svn/text-base/DriverConfiguration.h.svn-base239
-rw-r--r--Src/Network/base/Board.c51
-rw-r--r--Src/Network/base/Board.h63
-rw-r--r--Src/Network/base/DriverConfiguration.c608
-rw-r--r--Src/Network/base/DriverConfiguration.h239
-rw-r--r--Src/SafeVector.h192
-rw-r--r--Src/ScriptXml.cpp200
-rw-r--r--Src/ScriptXml.h88
-rw-r--r--Src/Thread.cpp129
-rw-r--r--Src/Thread.h88
-rw-r--r--Src/Types.h230
-rw-r--r--Src/VodXml.cpp1112
-rw-r--r--Src/VodXml.h361
-rw-r--r--Src/Xml.cpp251
-rw-r--r--Src/Xml.h179
60 files changed, 20256 insertions, 0 deletions
diff --git a/Src/ConnectionInfo.cpp b/Src/ConnectionInfo.cpp
new file mode 100644
index 0000000..927dcb3
--- /dev/null
+++ b/Src/ConnectionInfo.cpp
@@ -0,0 +1,712 @@
+/*
+ * 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 <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+#include "SafeVector.h"
+#include "MacAddr.h"
+#include "Types.h"
+#include "Console.h"
+#include "ConnectionInfo.h"
+
+#define MY_IPC_HEADER "most mac dev-type instance channel-id type bandwidth direction con-label buffer state offset offset-max p-xact dev-name"
+#define MY_IPC_HEADER_LINE_END MY_IPC_HEADER"\n"
+
+CConnectionInfo::CConnectionInfo() : deviceType( 0 ), deviceInstance( 0 ), channelId( 0 ), mostInstance( 0 ),
+ dataType( EP_Unknown ), reservedBandwidth( 0 ), bufferSize( 0 ),
+ isTX( false), inSocketCreated( false ), outSocketCreated( false ), socketsConnected( false ),
+ mostConnectionLabel( 0xFFFFFFFF ), splittedOffset( 0 ), splittedMaxBandwidth( 0 ), packetsPerXact( 0 )
+{
+ macAddr = new CMacAddr();
+ deviceName[0] = '\0';
+}
+
+CConnectionInfo::CConnectionInfo( CMacAddr *macAddr, TChannelId cId, uint8_t mInst,
+ bool isTx ) : deviceType( 0 ), deviceInstance( 0 ), channelId( cId ), mostInstance(mInst),
+ dataType( EP_Unknown ), reservedBandwidth( 0 ), bufferSize( 0 ), isTX( isTx ),
+ inSocketCreated( false ), outSocketCreated( false ), socketsConnected( false ),
+ mostConnectionLabel( 0xFFFFFFFF ), splittedOffset( -1 ), splittedMaxBandwidth( -1 ),
+ packetsPerXact( 0 )
+{
+ this->macAddr = new CMacAddr( macAddr ); //Copy the object
+ deviceName[0] = '\0';
+}
+
+CConnectionInfo::~CConnectionInfo()
+{
+ if( NULL != macAddr )
+ {
+ delete macAddr;
+ macAddr = NULL;
+ }
+}
+
+CConnectionInfoContainer::CConnectionInfoContainer()
+{
+}
+
+CConnectionInfoContainer::~CConnectionInfoContainer()
+{
+ DestroyAllInfos();
+}
+
+uint32_t CConnectionInfoContainer::GetAllInfoAmount()
+{
+ return allInfos.Size();
+}
+
+CConnectionInfo *CConnectionInfoContainer::GetInfo( uint32_t index )
+{
+ if( index >= allInfos.Size() )
+ {
+ ConsolePrintf( PRIO_ERROR,
+ RED"CConnectionInfoContainer::GetInfo was called with index out of range"RESETCOLOR"\n" );
+ return NULL;
+ }
+ return allInfos[index];
+}
+
+bool CConnectionInfoContainer::Compare( CConnectionInfo *c, CConnectionInfo *t )
+{
+ if( NULL == c || NULL == t )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Compare parameter error"RESETCOLOR"\n" );
+ return false;
+ }
+ return ( ( c->bufferSize == t->bufferSize )
+ && ( c->channelId == t->channelId )
+ && ( c->dataType == t->dataType )
+ && ( c->deviceType == t->deviceType )
+ && ( c->mostConnectionLabel == t->mostConnectionLabel )
+ && ( c->mostInstance == t->mostInstance )
+ && ( c->reservedBandwidth == t->reservedBandwidth )
+ && ( 0 == strcmp( c->deviceName, t->deviceName ) )
+ && ( c->isTX == t->isTX )
+ && ( *c->macAddr == *t->macAddr )
+ && ( c->packetsPerXact == t->packetsPerXact )
+ );
+}
+
+bool CConnectionInfoContainer::Compare( CConnectionInfoContainer *remote )
+{
+ if( NULL == remote ||
+ ( remote->GetAllInfoAmount() != GetAllInfoAmount() ) )
+ return false;
+ bool equal = true;
+ for( uint32_t i = 0; equal && i < allInfos.Size(); i++ )
+ {
+ equal = false;
+ CConnectionInfo *t = allInfos[i];
+ if( NULL == t )
+ break;
+ for( uint32_t j = 0; !equal && j < remote->GetAllInfoAmount(); j++ )
+ {
+ CConnectionInfo *c = remote->GetInfo( j );
+ if( NULL == c )
+ break;
+ if( Compare( c, t ) )
+ {
+ equal = true;
+ break;
+ }
+ }
+ }
+ return equal;
+}
+
+bool CConnectionInfoContainer::ExistsEntry( CConnectionInfo *c )
+{
+ if( NULL == c )
+ return false;
+ bool exists = false;
+ for( uint32_t i = 0; !false && i < allInfos.Size(); i++ )
+ {
+ CConnectionInfo *t = allInfos[i];
+ if( NULL == t )
+ break;
+ if( Compare( c, t ) )
+ {
+ exists = true;
+ break;
+ }
+ }
+ return exists;
+}
+
+CConnectionInfo *CConnectionInfoContainer::GetInfo( CMacAddr *macAddr, TChannelId channelId, uint8_t mostInstance )
+{
+ CConnectionInfo *instance = NULL;
+ if( NULL == macAddr )
+ {
+ return NULL;
+ }
+ for( uint32_t i = 0; i < allInfos.Size(); i++ )
+ {
+ CConnectionInfo *temp = allInfos[i];
+ if( NULL != temp && *temp->macAddr == *macAddr
+ && temp->channelId == channelId
+ && temp->mostInstance == mostInstance )
+ {
+ instance = temp;
+ break;
+ }
+ }
+ return instance;
+}
+
+uint8_t CConnectionInfoContainer::GetAmountOfDevices( TMostInstace mostInstance, TDeviceId deviceId )
+{
+ uint8_t amount = 0;
+ CSafeVector<CMacAddr *> allMacs;
+ for( uint32_t i = 0; i < allInfos.Size(); i++ )
+ {
+ CConnectionInfo *temp = allInfos[i];
+ if( NULL != temp && temp->deviceType == deviceId
+ && temp->mostInstance == mostInstance
+ && NULL != temp->macAddr )
+ {
+ bool update = true;
+ for( uint32_t j = 0; j < allMacs.Size(); j++ )
+ {
+ if( *allMacs[j] == *temp->macAddr )
+ {
+ update = false;
+ break;
+ }
+ }
+ if( update )
+ {
+ allMacs.PushBack( temp->macAddr );
+ ++amount;
+ }
+ }
+ }
+ return amount;
+}
+
+CConnectionInfo *CConnectionInfoContainer::GetInfo( CMacAddr *macAddr, TChannelId channelId, uint8_t mostInstance,
+ bool isTx )
+{
+ CConnectionInfo *instance = GetInfo( macAddr, channelId, mostInstance );
+ if( NULL == instance )
+ {
+ instance = new CConnectionInfo( macAddr, channelId, mostInstance, isTx );
+ allInfos.PushBack( instance );
+ }
+ return instance;
+}
+
+void CConnectionInfoContainer::AddInfo( CConnectionInfo *info )
+{
+ if( NULL == info )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"AddInfo parameter error"RESETCOLOR"\n" );
+ return;
+ }
+ allInfos.PushBack( info );
+}
+
+void CConnectionInfoContainer::DestroyAllInfos()
+{
+ allInfos.RemoveAll(true);
+}
+
+void CConnectionInfoContainer::DestroyInfo( CMacAddr *macAddr, TChannelId channelId, uint8_t mostInstance )
+{
+ if( NULL == macAddr )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"DestroyInstance was called with invalid parameters."RESETCOLOR"\n" );
+ return;
+ }
+ for( uint32_t i = 0; i < allInfos.Size(); i++ )
+ {
+ CConnectionInfo *temp = allInfos[i];
+ if( NULL != temp && *temp->macAddr == *macAddr
+ && temp->channelId == channelId
+ && temp->mostInstance == mostInstance )
+ {
+ allInfos.Remove(temp);
+ delete temp;
+ break;
+ }
+ }
+}
+
+void CConnectionInfoContainer::PrintTable( bool hideTx, bool hideRx )
+{
+ char macString[32];
+ char sizeString[10];
+ char stateString[32];
+ char offsetString[32];
+ char lastDeviceName[64];
+ const char *typeString;
+ int16_t lastMaxOffset = -1;
+
+ lastDeviceName[0] = '\0';
+ ConsolePrintfStart( PRIO_HIGH,
+ "Index | MOST | MAC-ADDRESS | DEV | INST | ID | Type | BW | Dir | Con-Label | Buffer | State |DEVICE-NAME \n" );
+ ConsolePrintfContinue(
+ "------|------|-------------------|------|------|-----|-------|-----|-----|-----------|--------|--------|-------------\n" );
+ for( uint32_t i = 0; i < allInfos.Size(); i++ )
+ {
+ CConnectionInfo *temp = allInfos[i];
+ if ( NULL == temp )
+ continue;
+
+ if( hideTx && temp->isTX )
+ continue;
+
+ if( hideRx && !temp->isTX )
+ continue;
+
+ switch( temp->dataType )
+ {
+ case EP_Synchron:
+ typeString = "SYNC ";
+ break;
+ case EP_Asynchron:
+ typeString = "ASYNC";
+ break;
+ case EP_Control:
+ typeString = "CTRL ";
+ break;
+ case EP_Isochron:
+ typeString = "ISOC ";
+ break;
+ case EP_Unused:
+ typeString = "EMPTY";
+ break;
+ case EP_Unknown:
+ default:
+ typeString = "ERROR";
+ break;
+ }
+
+ if( NULL == temp->macAddr || NULL == temp->macAddr->ToString() )
+ strncpy( macString, "Unknown MAC Addr.", sizeof( macString ) );
+ else
+ strncpy( macString, temp->macAddr->ToString(), sizeof( macString ) );
+
+ if( 0 > temp->bufferSize )
+ strncpy( sizeString, "None", sizeof( sizeString ) );
+ else
+ snprintf( sizeString, sizeof ( sizeString ), "%04d", temp->bufferSize );
+
+
+ const char *goodStr = GREEN"X";
+ const char *badStr = RED"o";
+ snprintf( stateString, sizeof ( stateString ), "%s%s%s"RESETCOLOR, ( temp->inSocketCreated ? goodStr :
+ badStr ), ( temp->outSocketCreated ? goodStr : badStr ), ( temp->socketsConnected ? goodStr :
+ badStr ) );
+
+ offsetString[0] = '\0';
+ if( -1 != temp->splittedOffset && -1 != temp->splittedMaxBandwidth )
+ {
+ if( 0 == temp->splittedOffset )
+ {
+ lastMaxOffset = temp->splittedMaxBandwidth;
+ if( 0 != strlen( temp->deviceName ) )
+ strncpy( lastDeviceName, temp->deviceName, sizeof( lastDeviceName ) );
+ }
+ snprintf( offsetString, sizeof( offsetString ), " (offset %d/%d)",
+ temp->splittedOffset, ( 0 == temp->splittedOffset ? temp->splittedMaxBandwidth : lastMaxOffset ) );
+ }
+
+ ConsolePrintfContinue( "%02d ", i );
+ ConsolePrintfContinue( "| %02d ", temp->mostInstance );
+ ConsolePrintfContinue( "| %s ", macString );
+ ConsolePrintfContinue( "| %03X ", temp->deviceType );
+ ConsolePrintfContinue( "| %02d ", temp->deviceInstance );
+ ConsolePrintfContinue( "| %03d ", temp->channelId );
+ ConsolePrintfContinue( "| %s ", typeString );
+ ConsolePrintfContinue( "| %03d ", temp->reservedBandwidth );
+ ConsolePrintfContinue( "| %s ", ( temp->isTX ? "TX" : "RX" ) );
+ ConsolePrintfContinue( "| %03X ", ( temp->mostConnectionLabel != 0xFFFFFFFF ) ? temp->
+ mostConnectionLabel : 0xFFF );
+ ConsolePrintfContinue( "| %s ", sizeString );
+ ConsolePrintfContinue( "| %s ", stateString );
+ ConsolePrintfContinue( "| %s", ( '\0' == offsetString[0] ) ? temp->deviceName : lastDeviceName );
+ ConsolePrintfContinue( "%s\n", offsetString );
+ }
+ ConsolePrintfExit(
+ "------|------|-------------------|------|------|-----|-------|-----|-----|-----------|--------|--------|-------------\n" );
+}
+
+uint32_t CConnectionInfoContainer::SerializeToString( char *pBuffer, uint32_t bufferLen )
+{
+ if( NULL == pBuffer || 0 == bufferLen )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"SerializeToString was called with wrong parameters"RESETCOLOR"\n" );
+ return 0;
+ }
+ uint32_t bytesUsed = strlen( pBuffer );
+ if (bytesUsed > bufferLen)
+ {
+ ConsolePrintf(PRIO_ERROR, RED"CConnectionInfoContainer::SerializeToString given buffer"\
+ " is too small!"RESETCOLOR);
+ return 0;
+ }
+ const char *typeString = NULL;
+ char stringBuffer[200];
+ strncpy( pBuffer, MY_IPC_HEADER_LINE_END, bufferLen );
+
+ for( uint32_t i = 0; i < allInfos.Size(); i++ )
+ {
+ CConnectionInfo *sourceInfo = allInfos[i];
+ if ( NULL == sourceInfo )
+ continue;
+ switch( sourceInfo->dataType )
+ {
+ case EP_Synchron:
+ typeString = "SYNC";
+ break;
+ case EP_Asynchron:
+ typeString = "ASYNC";
+ break;
+ case EP_Control:
+ typeString = "CTRL";
+ break;
+ case EP_Isochron:
+ typeString = "ISOC";
+ break;
+ case EP_Unused:
+ typeString = "EMPTY";
+ break;
+ case EP_Unknown:
+ default:
+ typeString = "ERROR";
+ break;
+ }
+
+ snprintf( stringBuffer, sizeof ( stringBuffer ), "%d %s %d %d %d %s %d %s %d %d %c%c%c %d %d %d %s\n",
+ sourceInfo->mostInstance, sourceInfo->macAddr->ToString(), sourceInfo->deviceType,
+ sourceInfo->deviceInstance, sourceInfo->channelId, typeString,
+ sourceInfo->reservedBandwidth, ( sourceInfo->isTX ? "TX" : "RX" ), sourceInfo->mostConnectionLabel,
+ sourceInfo->bufferSize, ( sourceInfo->inSocketCreated ? 'X' : '0' ), ( sourceInfo->outSocketCreated ? 'X' :
+ '0' ), ( sourceInfo->socketsConnected ? 'X' : '0' ), sourceInfo->splittedOffset,
+ sourceInfo->splittedMaxBandwidth, sourceInfo->packetsPerXact, sourceInfo->deviceName );
+ strncat( pBuffer, stringBuffer, ( bufferLen - bytesUsed ) );
+ bytesUsed = strlen( pBuffer );
+ }
+
+ return strlen( pBuffer ) + 1;
+}
+
+bool CConnectionInfoContainer::DeserializeFromString( char *pBuffer )
+{
+ if( NULL == pBuffer || 0 == strlen( pBuffer ) )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"DeserializeFromString was called with wrong parameters"RESETCOLOR"\n" );
+ return false;
+ }
+ DestroyAllInfos();
+ char *helpPtr;
+ char *token = strtok_r( pBuffer, "\n", &helpPtr );
+ bool first = true;
+ while( NULL != token )
+ {
+ if( first )
+ {
+ first = false;
+ if( 0 != strcmp( MY_IPC_HEADER, token ) )
+ {
+ ConsolePrintf( PRIO_ERROR,
+ RED"DeserializeFromString: Incompatible header found, aborting\n"\
+ "Expected:'%s'\n"\
+ "Got: '%s'"\
+ RESETCOLOR"\n", MY_IPC_HEADER, token );
+ return false;
+ }
+ }
+ else
+ {
+ CConnectionInfo *info = new CConnectionInfo();
+ uint32_t mostInstance;
+ char macString[20];
+ uint32_t deviceType;
+ uint32_t deviceInstance;
+ uint32_t channelId;
+ char typeString[10];
+ uint32_t reservedBandwidth;
+ char deviceDirection[10];
+ uint32_t mostConnectionLabel;
+ uint32_t bufferSize;
+ int32_t offset;
+ int32_t maxOffset;
+ uint32_t xact;
+ char connectString[10];
+ sscanf( token, "%d %s %d %d %d %s %d %s %d %d %s %d %d %d %s\n", &mostInstance,
+ macString, &deviceType, &deviceInstance, &channelId, typeString, &reservedBandwidth,
+ deviceDirection, &mostConnectionLabel, &bufferSize, connectString, &offset, &maxOffset,
+ &xact, info->deviceName );
+
+ info->mostInstance = mostInstance;
+ info->deviceType = deviceType;
+ info->deviceInstance = deviceInstance;
+ info->channelId = channelId;
+ info->reservedBandwidth = reservedBandwidth;
+ info->mostConnectionLabel = mostConnectionLabel;
+ info->bufferSize = bufferSize;
+ info->splittedOffset = offset;
+ info->splittedMaxBandwidth = maxOffset;
+ info->packetsPerXact = xact;
+
+ info->isTX = strstr( deviceDirection, "TX" );
+
+ if( NULL != connectString && 3 == strlen( connectString ) )
+ {
+ info->inSocketCreated = connectString[0] == 'X';
+ info->outSocketCreated = connectString[1] == 'X';
+ info->socketsConnected = connectString[2] == 'X';
+ }
+
+ if( NULL == info->macAddr )
+ info->macAddr = new CMacAddr();
+ info->macAddr->CopyValuesFromString( macString );
+
+ if( strstr( typeString, "ASYNC" ) )
+ {
+ info->dataType = EP_Asynchron;
+ }
+ else if( strstr( typeString, "SYNC" ) )
+ {
+ info->dataType = EP_Synchron;
+ }
+ else if( strstr( typeString, "CTRL" ) )
+ {
+ info->dataType = EP_Control;
+ }
+ else if( strstr( typeString, "ISOC" ) )
+ {
+ info->dataType = EP_Isochron;
+ }
+ else if( strstr( typeString, "EMPTY" ) )
+ {
+ info->dataType = EP_Unused;
+ }
+ else
+ {
+ info->dataType = EP_Unknown;
+ }
+ allInfos.PushBack( info );
+ }
+ token = strtok_r( NULL, "\n", &helpPtr );
+ }
+ return true;
+}
+
+uint32_t CConnectionInfoContainer::GetAmountOfCDevs()
+{
+ uint32_t amount = 0;
+ for( uint32_t i = 0; i < allInfos.Size(); i++ )
+ {
+ CConnectionInfo *temp = allInfos[i];
+ if( NULL != temp && NULL != temp->deviceName && 0 != strlen( temp->deviceName ) )
+ ++amount;
+ }
+ return amount;
+}
+
+CConnectionInfo *CConnectionInfoContainer::GetConnectionInfoOfCdev( uint32_t cdevInst )
+{
+ uint32_t amount = 0;
+ CConnectionInfo *info = NULL;
+ for( uint32_t i = 0; i < allInfos.Size(); i++ )
+ {
+ CConnectionInfo *temp = allInfos[i];
+ if( NULL != temp && NULL != temp->deviceName && 0 != strlen( temp->deviceName ) )
+ {
+ if( cdevInst == amount )
+ {
+ info = temp;
+ break;
+ }
+ ++amount;
+ }
+ }
+ return info;
+}
+
+CConnectionInfo *CConnectionInfoContainer::GetConnectionInfoOfCdev( uint32_t cdevInst, uint32_t splittedIndex )
+{
+ uint32_t amountCdev = 0;
+ uint32_t amountSplit = 0;
+ CConnectionInfo *infoCdev = NULL;
+ CConnectionInfo *infoSplitted = NULL;
+ for( uint32_t i = 0; i < allInfos.Size(); i++ )
+ {
+ CConnectionInfo *temp = allInfos[i];
+ if( NULL == infoCdev )
+ {
+ if( NULL != temp && NULL != temp->deviceName && 0 != strlen( temp->deviceName ) )
+ {
+ if( cdevInst == amountCdev )
+ {
+ infoCdev = temp;
+ if( 0 != infoCdev->splittedOffset )
+ {
+ ConsolePrintf( PRIO_ERROR,
+ RED"CConnectionInfoContainer::GetConnectionInfoOfCdev"\
+ " was called for a non splitted CDEV"RESETCOLOR"\n" );
+ break;
+ }
+ }
+ ++amountCdev;
+ }
+ }
+ else
+ {
+ if( ( 0 == temp->splittedOffset ) || ( -1 == temp->splittedOffset ) )
+ break;
+ if( amountSplit == splittedIndex )
+ {
+ infoSplitted = temp;
+ break;
+ }
+ ++amountSplit;
+ }
+ }
+ return infoSplitted;
+}
+
+uint32_t CConnectionInfoContainer::GetAmountOfSinks()
+{
+ uint32_t amount = 0;
+ for( uint32_t i = 0; i < allInfos.Size(); i++ )
+ {
+ CConnectionInfo *sourceInfo = allInfos[i];
+ if( NULL == sourceInfo || NULL == sourceInfo->macAddr || NULL == sourceInfo->macAddr->ToString() )
+ continue;
+ if( NULL == sourceInfo->deviceName || 0 == strlen( sourceInfo->deviceName ) )
+ continue;
+ if( !sourceInfo->socketsConnected )
+ continue;
+ for( uint32_t j = 0; j < allInfos.Size(); j++ )
+ {
+ CConnectionInfo *sinkInfo = allInfos[j];
+ if( i == j )
+ continue;
+ if( NULL == sinkInfo->macAddr || NULL == sinkInfo->macAddr->ToString() )
+ continue;
+ if( !sinkInfo->socketsConnected )
+ continue;
+ if( sourceInfo->mostConnectionLabel != sinkInfo->mostConnectionLabel )
+ continue;
+ if( sourceInfo->mostInstance != sinkInfo->mostInstance )
+ continue;
+ ++amount;
+ }
+ }
+ return amount;
+}
+
+CConnectionInfo *CConnectionInfoContainer::GetConnectionInfoOfSink( uint32_t sinkInst )
+{
+ uint32_t amount = 0;
+ CConnectionInfo *info = NULL;
+ for( uint32_t i = 0; NULL == info && i < allInfos.Size(); i++ )
+ {
+ CConnectionInfo *sourceInfo = allInfos[i];
+ if( NULL == sourceInfo || NULL == sourceInfo->macAddr || NULL == sourceInfo->macAddr->ToString() )
+ continue;
+ if( NULL == sourceInfo->deviceName || 0 == strlen( sourceInfo->deviceName ) )
+ continue;
+ if( !sourceInfo->socketsConnected )
+ continue;
+ for( uint32_t j = 0; NULL == info && j < allInfos.Size(); j++ )
+ {
+ CConnectionInfo *sinkInfo = allInfos[j];
+ if( i == j )
+ continue;
+ if( NULL == sinkInfo->macAddr || NULL == sinkInfo->macAddr->ToString() )
+ continue;
+ if( !sinkInfo->socketsConnected )
+ continue;
+ if( sourceInfo->mostConnectionLabel != sinkInfo->mostConnectionLabel )
+ continue;
+ if( sourceInfo->mostInstance != sinkInfo->mostInstance )
+ continue;
+ if( sinkInst == amount )
+ {
+ info = sinkInfo;
+ }
+ ++amount;
+ }
+ }
+ return info;
+}
+
+CConnectionInfo *CConnectionInfoContainer::GetConnectionInfoByMacAddress( const uint8_t *mac )
+{
+ if( NULL == mac )
+ return NULL;
+ char macAddr[20];
+ snprintf( ( char * )&macAddr, sizeof( macAddr ), "%02X-%02X-%02X-%02X-%02X-%02X", mac[0], mac[1], mac[2], mac[3],
+ mac[4], mac[5] );
+ CConnectionInfo *info = NULL;
+ for( uint32_t i = 0; i < allInfos.Size(); i++ )
+ {
+ CConnectionInfo *temp = allInfos[i];
+ if( NULL != temp && NULL != temp->macAddr )
+ {
+ if( 0 == strcmp( temp->macAddr->ToString(), macAddr ) )
+ {
+ info = temp;
+ break;
+ }
+ }
+ }
+ return info;
+}
+
+CConnectionInfo *CConnectionInfoContainer::GetRemoteConnectionInfoByMacAddress( const uint8_t *mac )
+{
+ if( NULL == mac )
+ return NULL;
+ char macAddr[20];
+ snprintf( ( char * )&macAddr, sizeof( macAddr ), "%02X-%02X-%02X-%02X-%02X-%02X", mac[0], mac[1], mac[2], mac[3],
+ mac[4], mac[5] );
+ CConnectionInfo *remoteInfo = NULL;
+ CConnectionInfo *info = GetConnectionInfoByMacAddress( mac );
+ if( NULL == info )
+ return NULL;
+ for( uint32_t i = 0; i < allInfos.Size(); i++ )
+ {
+ CConnectionInfo *temp = allInfos[i];
+ if( NULL != temp && NULL != temp->macAddr )
+ {
+ if( 0 == strcmp( temp->macAddr->ToString(), macAddr ) )
+ continue;
+ if( ( temp->mostInstance == info->mostInstance ) &&
+ ( temp->mostConnectionLabel == info->mostConnectionLabel ) &&
+ temp->socketsConnected )
+ {
+ remoteInfo = temp;
+ break;
+ }
+ }
+ }
+ return remoteInfo;
+}
diff --git a/Src/ConnectionInfo.h b/Src/ConnectionInfo.h
new file mode 100644
index 0000000..13016f5
--- /dev/null
+++ b/Src/ConnectionInfo.h
@@ -0,0 +1,316 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains a helper class to store MOST connections
+ */
+/*----------------------------------------------------------*/
+#ifndef CONNECTIONINFO_H
+#define CONNECTIONINFO_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include "SafeVector.h"
+#include "Types.h"
+#include "MacAddr.h"
+
+/*!
+ * \brief This is a helper class for the CNetworkManagerHandler. It keeps track of the reported connections
+ * and the instanced CMultiplexer classes.
+ */
+class CConnectionInfo
+{
+public:
+ CConnectionInfo();
+ CConnectionInfo( CMacAddr *macAddr, TChannelId channelId, uint8_t mostInstance, bool isTx );
+ ~CConnectionInfo();
+
+ ///The Ethernet MAC address of this connection.
+ CMacAddr *macAddr;
+
+ ///The device type as specified in XML file and configured in the config string (Group-Address)
+ TDeviceId deviceType;
+
+ ///The instance count of this device class. Starting at 0 for the first instance. Incremented with every occurrence.
+ uint8_t deviceInstance;
+
+ ///The channel ID as declared in the configuration XML file.
+ TChannelId channelId;
+
+ ///The MOST ring instance. Starting at 0 for the first MOST ring, on the first OS81110.
+ TMostInstace mostInstance;
+
+ ///The MOST data used by this channel.
+ EPDataType_t dataType;
+
+ ///The reserved MOST bandwidth in bytes for this channel.
+ TBlockwidth reservedBandwidth;
+
+ ///The amount of bytes reserved for this channel in Driver. If no buffers were allocated, this value is -1.
+ int32_t bufferSize;
+
+ ///In case this is a local connection, the path of the character device is stored in this variable. (e.g. /dev/mdev0).
+ char deviceName[64];
+
+ ///TRUE if this connections is a source. FALSE if this connection is a sink,
+ bool isTX;
+
+ //TRUE, if the input socket of this connection was successfully created.
+ bool inSocketCreated;
+
+ //TRUE, if the output socket of this connection was successfully created.
+ bool outSocketCreated;
+
+ //TRUE, if the input socket and the output socket of this connection were successfully connected.
+ bool socketsConnected;
+
+ ///The MOST connection label.
+ uint32_t mostConnectionLabel;
+
+ ///If this socket is a splitted / combined socket, this value holds the offset in byte. -1 if this is a normal socket.
+ int16_t splittedOffset;
+
+ ///If this socket is a splitted / combined socket, this value holds the maximum bandwidth of all splitted sockets in byte. -1 if this is a normal socket.
+ int16_t splittedMaxBandwidth;
+
+ ///This is USB specific. It describes how many sub-frames are concatenated into a single USB microframe.
+ uint16_t packetsPerXact;
+};
+
+/*!
+ * \brief This is a storage class holding multiple CConnectionInfo in a container.
+ * It supports adding, removing, serializing and deserializing
+ */
+class CConnectionInfoContainer
+{
+private:
+ CSafeVector<CConnectionInfo *> allInfos;
+ bool Compare( CConnectionInfo *c, CConnectionInfo *t );
+public:
+
+ /*----------------------------------------------------------*/
+ /*! \brief Default Constructor of CConnectionInfoContainer
+ */
+ /*----------------------------------------------------------*/
+ CConnectionInfoContainer();
+
+ /*----------------------------------------------------------*/
+ /*! \brief Default Destructor of CConnectionInfoContainer
+ */
+ /*----------------------------------------------------------*/
+ ~CConnectionInfoContainer();
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets the amount of entries stored in the whole database.
+ * \return The amount of entries.
+ */
+ /*----------------------------------------------------------*/
+ uint32_t GetAllInfoAmount();
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets the information at the corresponding position.
+ * \param index - the position inside the database
+ * \note Use GetAllInfoAmount() to get the max index (n-1).
+ * \return The information if found, NULL if out of range
+ */
+ /*----------------------------------------------------------*/
+ CConnectionInfo *GetInfo( uint32_t index );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Compares to container.
+ * \param containerToCompare - The container to compare.
+ * \return true, if both containers stores the same information. false, otherwise.
+ */
+ /*----------------------------------------------------------*/
+ bool Compare( CConnectionInfoContainer *containerToCompare );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Checks if the given information is already stored inside the database.
+ * \param checkInfo - the information object to be checked
+ * \return true, if the information is already stored inside the database. false, otherwise.
+ */
+ /*----------------------------------------------------------*/
+ bool ExistsEntry( CConnectionInfo *checkInfo );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets an info object with the given parameters
+ * \param macAddr - The MAC address of the device
+ * \param channelId - The channel identifier as used in the XML file.
+ * \param mostInstance - The MOST ring instance, starting 0 for the first MOST instance.
+ * \return The info object if found. NULL, otherwise.
+ */
+ /*----------------------------------------------------------*/
+ CConnectionInfo *GetInfo( CMacAddr *macAddr, TChannelId channelId, uint8_t mostInstance );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets the amount of devices with the same
+ * \param mostInstance - The MOST ring instance. Starting at 0 for the first MOST ring.
+ * \param deviceId - The device ID as declared in the configuration XML file.
+ * \return The Amount of devices found, with the given deviceId
+ */
+ /*----------------------------------------------------------*/
+ uint8_t GetAmountOfDevices( TMostInstace mostInstance, TDeviceId deviceId );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Helper function, which delivers a CConnectionInfo object to the given search parameters.
+ * \param macAddr - Searches for the given MAC address.
+ * \param channelId - Search for the given Channel address.
+ * \param mostInstance - Search on the given MOST ring instance.
+ * \param isTx - true, search for a transmission connection. false, search for a reception connection.
+ * \return An pointer to the matching CConnectionInfo object if found. NULL otherwise.
+ */
+ /*----------------------------------------------------------*/
+ CConnectionInfo *GetInfo( CMacAddr *macAddr, TChannelId channelId, uint8_t mostInstance, bool isTx );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Stores the given information inside the database.
+ * \param info - The information to be stored.
+ */
+ /*----------------------------------------------------------*/
+ void AddInfo( CConnectionInfo *info );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Helper function, which deletes all stored informations retrieved so far.
+ */
+ /*----------------------------------------------------------*/
+ void DestroyAllInfos();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Helper function, which delete the information matching to the given parameters.
+ * \param macAddr - Searches for the given MAC address.
+ * \param channelId - Search for the given Channel address.
+ * \param mostInstance - Search on the given MOST ring instance.
+ */
+ /*----------------------------------------------------------*/
+ void DestroyInfo( CMacAddr *macAddr, TChannelId channelId, uint8_t mostInstance );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Helper function, which prints all available information to the console.
+ * \param hideTx - true, when transmission connections shall not be shown in the table.
+ * \param hideRx - true, when reception connections shall not be shown in the table.
+ */
+ /*----------------------------------------------------------*/
+ void PrintTable( bool hideTx, bool hideRx );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Serializes all connection informations to multi line string.
+ * \param pBuffer, buffer which then will hold the serialized string.
+ * \param bufferLen, the size of the given buffer.
+ * \return The amount of bytes used from the given buffer.
+ */
+ /*----------------------------------------------------------*/
+ uint32_t SerializeToString( char *pBuffer, uint32_t bufferLen );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Deserializes all connection informations to multi line string.
+ * \param pBuffer, buffer which will read of the serialized string.
+ * \return True, if the string could be used to deserialize all data. False, error occurred.
+ * \note The given buffer will be manipulated by strtok operation!
+ */
+ /*----------------------------------------------------------*/
+ bool DeserializeFromString( char *pBuffer );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Returns the amount of entries, which contains a CDEV device name
+ * \return The amount of devices.
+ */
+ /*----------------------------------------------------------*/
+ uint32_t GetAmountOfCDevs();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves the information of the specific CDEV.
+ * \param cdevInst - The index of the CDEV device, starting with 0 for the first device.
+ * \note Use GetAmountOfCDevs() the get the maximum possible index (n-1).
+ * \return The information object, if found. NULL, otherwise.
+ */
+ /*----------------------------------------------------------*/
+ CConnectionInfo *GetConnectionInfoOfCdev( uint32_t cdevInst );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves the information of the specific CDEV.
+ * \param cdevInst - The index of the CDEV device, starting with 0 for the first device.
+ * \param splittedIndex - Index of splitted socket entry, starting with 0 for the first splitted entry which has an offset greater than zero.
+ * \note Use GetAmountOfCDevs() the get the maximum possible index (n-1).
+ * \return The information object, if found. NULL, otherwise.
+ */
+ /*----------------------------------------------------------*/
+ CConnectionInfo *GetConnectionInfoOfCdev( uint32_t cdevInst, uint32_t splittedIndex );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Returns the amount of entries, which acts as a sink channel.
+ * \return The amount of devices.
+ */
+ /*----------------------------------------------------------*/
+ uint32_t GetAmountOfSinks();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves the information of the specific sink.
+ * \param cdevInst - The index of the sink, starting with 0 for the sink.
+ * \note Use GetAmountOfSinks() the get the maximum possible index (n-1).
+ * \return The information object, if found. NULL, otherwise.
+ */
+ /*----------------------------------------------------------*/
+ CConnectionInfo *GetConnectionInfoOfSink( uint32_t sinkInst );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets the information object by the given MAC address.
+ * \param mac - The MAC address of the searched device.
+ * \return The information object, if found. NULL, otherwise.
+ */
+ /*----------------------------------------------------------*/
+ CConnectionInfo *GetConnectionInfoByMacAddress( const uint8_t *mac );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets the opposite device information connected with given MAC address.
+ * \param mac - The MAC address of the device, which then the information of connected opposite device is returned.
+ * \return The information object, if found. NULL, otherwise.
+ */
+ /*----------------------------------------------------------*/
+ CConnectionInfo *GetRemoteConnectionInfoByMacAddress( const uint8_t *mac );
+};
+
+#endif //CONNECTIONINFO_H
diff --git a/Src/Console.c b/Src/Console.c
new file mode 100644
index 0000000..4ae52a3
--- /dev/null
+++ b/Src/Console.c
@@ -0,0 +1,209 @@
+/*
+ * 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 <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include "Console.h"
+
+///Our shared memory key
+static int shmkey = 072162537;
+//The minimum priority
+static ConsolePrio_t minPrio = PRIO_LOW;
+
+/*! \cond PRIVATE */
+typedef struct
+{
+ ///The first process will setup the critical section and set this variable to true.
+ bool initialized;
+ ///If set to true, multiple processeses are synced via shared memory.
+ bool processSynced;
+ ///If set to true, there is an segmented print ongoing (Start, Continue, Exit).
+ bool criticalSection;
+ //If is in a critical segmented print, this variable will hold the prio for Start, Continue, Exit.
+ ConsolePrio_t criticalSectionPrio;
+ ///Handle of the shared mutex.
+ pthread_mutex_t mutex;
+} sharedData_t;
+/*! \endcond */
+
+/*----------------------------------------------------------*/
+/*! \brief Pointer to the shared memory instance.
+ */
+/*----------------------------------------------------------*/
+static sharedData_t *data = NULL;
+
+void ConsoleInit( bool synchronizeProcesses )
+{
+ pthread_mutexattr_t attr;
+
+ if( synchronizeProcesses )
+ {
+ int shmid = shmget( shmkey, sizeof( sharedData_t ), IPC_CREAT | 0666 );
+ if( ( sharedData_t * )-1 == ( data = ( sharedData_t* )shmat( shmid, NULL, 0 ) ) )
+ {
+ data = NULL;
+ fprintf( stderr, RED"ConsoleInit failed, because shared memory could not be accessed."RESETCOLOR"\n" );
+ return;
+ }
+ }
+ else
+ {
+ data = ( sharedData_t * )calloc( 1, sizeof( sharedData_t ) );
+ }
+ if( ( NULL != data ) && !data->initialized )
+ {
+ data->processSynced = synchronizeProcesses;
+ data->initialized = true;
+ data->criticalSection = false;
+
+ pthread_mutexattr_init( &attr );
+ if( synchronizeProcesses )
+ pthread_mutexattr_setpshared( &attr, PTHREAD_PROCESS_SHARED );
+ else
+ pthread_mutexattr_setpshared( &attr, PTHREAD_PROCESS_PRIVATE );
+ pthread_mutex_init( &data->mutex, &attr );
+ }
+}
+
+void ConsoleDeinit( void )
+{
+ if( NULL != data && !data->processSynced )
+ {
+ free( data );
+ data = NULL;
+ }
+}
+
+void ConsoleSetPrio( ConsolePrio_t prio )
+{
+ minPrio = prio;
+}
+
+void ConsolePrintf( ConsolePrio_t prio, const char *statement, ... )
+{
+ int err;
+ if( prio < minPrio || NULL == statement )
+ return;
+ if( NULL == data )
+ {
+ fprintf( stderr, RED"ConsolePrintf data was null"RESETCOLOR"\n" );
+ return;
+ }
+ if( 0 != ( err = pthread_mutex_lock( &data->mutex ) ) )
+ {
+ fprintf( stderr, RED"ConsolePrintf, pthread_mutex_lock error: %d"RESETCOLOR"\n", err );
+ return;
+ }
+
+ va_list args;
+ va_start( args, statement );
+ vfprintf( stderr, statement, args );
+ va_end( args );
+
+ if( 0 != ( err = pthread_mutex_unlock( &data->mutex ) ) )
+ {
+ fprintf( stderr, RED"ConsolePrintf, pthread_mutex_unlock error: %d"RESETCOLOR"\n", err );
+ return;
+ }
+}
+
+void ConsolePrintfStart( ConsolePrio_t prio, const char *statement, ... )
+{
+ int err;
+ if( NULL == data )
+ {
+ fprintf( stderr, RED"ConsolePrintfStart data was null"RESETCOLOR"\n" );
+ return;
+ }
+ if( 0 != ( err = pthread_mutex_lock( &data->mutex ) ) )
+ {
+ fprintf( stderr, RED"ConsolePrintfStart, pthread_mutex_lock error: %d"RESETCOLOR"\n", err );
+ return;
+ }
+ data->criticalSection = true;
+ data->criticalSectionPrio = prio;
+
+ if( data->criticalSectionPrio >= minPrio && NULL != statement )
+ {
+ va_list args;
+ va_start( args, statement );
+ vfprintf( stderr, statement, args );
+ va_end( args );
+ }
+}
+
+void ConsolePrintfContinue( const char *statement, ... )
+{
+ if( NULL == data )
+ {
+ fprintf( stderr, RED"ConsolePrintfContinue data was null"RESETCOLOR"\n" );
+ return;
+ }
+ if( !data->criticalSection )
+ {
+ fprintf( stderr, RED"ConsolePrintfContinue not in critical section"RESETCOLOR"\n" );
+ return;
+ }
+
+ if( data->criticalSectionPrio >= minPrio && NULL != statement )
+ {
+ va_list args;
+ va_start( args, statement );
+ vfprintf( stderr, statement, args );
+ va_end( args );
+ }
+}
+
+void ConsolePrintfExit( const char *statement, ... )
+{
+ int err;
+ if( NULL == data )
+ {
+ fprintf( stderr, RED"ConsolePrintfExit data was null"RESETCOLOR"\n" );
+ return;
+ }
+ if( !data->criticalSection )
+ {
+ fprintf( stderr, RED"ConsolePrintfExit not in critical section"RESETCOLOR"\n" );
+ return;
+ }
+ if( data->criticalSectionPrio >= minPrio && NULL != statement )
+ {
+ va_list args;
+ va_start( args, statement );
+ vfprintf( stderr, statement, args );
+ va_end( args );
+ }
+ data->criticalSection = false;
+ if( 0 != ( err = pthread_mutex_unlock( &data->mutex ) ) )
+ {
+ fprintf( stderr, RED"ConsolePrintfExit, pthread_mutex_unlock error: %d"RESETCOLOR"\n", err );
+ }
+}
diff --git a/Src/Console.h b/Src/Console.h
new file mode 100644
index 0000000..aab7e71
--- /dev/null
+++ b/Src/Console.h
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains C-functions starting with "Console" to provide
+ * process and thread safe access to the console output.
+ */
+/*----------------------------------------------------------*/
+#ifndef _CONSOLE_H_
+#define _CONSOLE_H_
+
+#define RESETCOLOR "\033[0m"
+#define GREEN "\033[0;32m"
+#define RED "\033[0;31m"
+#define YELLOW "\033[1;33m"
+#define BLUE "\033[0;34m"
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ typedef enum
+ {
+ PRIO_LOW = 0,
+ PRIO_MEDIUM = 1,
+ PRIO_HIGH = 2,
+ PRIO_ERROR = 0xFF
+ } ConsolePrio_t;
+
+ /*----------------------------------------------------------*/
+ /*! \brief Initializes the resources needed to synchronize between processes and threads.
+ * \note This function must be called before any other function of this component.
+ * \param synchronizeProcesses - If set to true, multiple processes using this component will synchronize their output.
+ *
+ */
+ /*----------------------------------------------------------*/
+ void ConsoleInit( bool synchronizeProcesses );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Destroys the resources needed to synchronize between processes and threads.
+ * \note After this function, any other function (except ConsoleInit) must not be called.
+ *
+ */
+ /*----------------------------------------------------------*/
+ void ConsoleDeinit( void );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Sets the minimum priority to be displayed. Lower priority messages are discarded
+ * \param prio - The minimum priority to display
+ */
+ /*----------------------------------------------------------*/
+ void ConsoleSetPrio( ConsolePrio_t prio );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Uses the board specific PRINT mechanism and provides thread and process safety.
+ *
+ */
+ /*----------------------------------------------------------*/
+ void ConsolePrintf( ConsolePrio_t prio, const char *statement, ... );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Starts to print and stay blocked after exit of this function
+ *
+ */
+ /*----------------------------------------------------------*/
+ void ConsolePrintfStart( ConsolePrio_t prio, const char *statement, ... );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Continue to print and stay blocked after exit of this function
+ * \note ConsolePrintfStart must be called before and when finished ConsolePrintfExit must be called.
+ * \note This function may be called multiple times.
+ */
+ /*----------------------------------------------------------*/
+ void ConsolePrintfContinue( const char *statement, ... );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Continue to print and unblock after finishing.
+ * \note ConsolePrintfStart must be called before. ConsolePrintfContinue may have been called before multiple times.
+ */
+ /*----------------------------------------------------------*/
+ void ConsolePrintfExit( const char *statement, ... );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_CONSOLE_H_
diff --git a/Src/DoxyGenStartPage.h b/Src/DoxyGenStartPage.h
new file mode 100644
index 0000000..1eb98b2
--- /dev/null
+++ b/Src/DoxyGenStartPage.h
@@ -0,0 +1,375 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file generates the start page of the document you are currently reading.
+ */
+/*----------------------------------------------------------*/
+#ifndef DOXYGEN_START_PAGE_H
+#define DOXYGEN_START_PAGE_H
+
+
+/*----------------------------------------------------------*/
+/*! \mainpage
+ *
+ * \section intro_sec Introduction
+ *
+ * This package holds the sample application and the Linux driver to realize a certain use cases like MOST based Video on Demand Service, Slim-Audio Applications and Slim-Camera Applications. \n
+ * All components where written for and tested for the on various Linux distributions on FreeScale i.MX6q, Ubuntu 14.4 LTS 64Bit on PC, Raspbian on Raspbery Pi 2. \n
+ *
+ * \section Package Contents
+ *
+ * \subsection examples Folder: "./Examples"
+ * - All the examples
+ * \subsubsection networkmanager Folder: "./Examples/NetworkManager"
+ * - The main application, which starts up MOST and configure all connections. \n
+ * \subsubsection videoondemand Folder: "./Examples/VideoOnDemand"
+ * - The Video On Demand Streaming Server and client examples \n
+ * <a href="../../../VideoOnDemand/Server/html/index.html">Click here</a> to see the documentation of the VideoOnDemand Example.
+ * \subsubsection audiomixer Folder: "./Examples/AudioMixer"
+ * - The synchronous Audio Mixer example\n
+ * <a href="../../../AudioMixer/doc/html/index.html">Click here</a> to see the documentation of the AudioMixer Example.
+ * \subsubsection PatternCheck Folder: "./Examples/PatternCheck"
+ * - Pattern Generator and Pattern Checker example\n
+ * \subsubsection SlimCamera Folder: "./Examples/SlimCamera"
+ * - SlimCamera example, with helper tool to stream from MOST isochronous channel to Ethernet UDP.\n
+ * \subsection linuxdriver Folder: "./LinuxDriver"
+ * - The Linux driver modules as source code. \n
+ * <a href="../../../../LinuxDriver/html/index.html">Click here</a> to see the documentation of the MOST Linux Driver.
+ * \subsection resources Folder:"./Resources"
+ * - Shell scripts to convert media typess.
+ * - INIC Explorer Windows tool.
+ * - INIC firmware.
+ * - ConfigString sample setups.
+ * - Shell scripts to convert Audio and Video.
+ *
+ * \section install_sec Setup
+ * \note General hint: Do not use white spaces in the path to this package, as some of the commands
+ * listed here need to be adapted otherwise.
+ *
+ * \subsection step1 Step 1: Unpack the delivered file
+ * - Enter:
+ * \code tar xvfz NM-Vx.x.x.tar.gz \endcode
+ * to unpack the folder. Replace the 'x' characters with you version.
+ *
+ * \subsection step2 Step 2: Edit the cross compiling environment variables and load them
+ * Use your favorite text editor to edit "crosscompile.sh".:
+ * - Example:
+ * \code vi crosscompile.sh \endcode
+ * - Or:
+ * \code gedit crosscompile.sh \endcode
+ * - Set your cross-compiler-toolchain path to the "CROSS_COMPILE" variable.
+ * - Set the target Linux kernel sources path to the "KDIR" variable.
+ * - Set the compiler flags (such as platform specific variables or setting up the path where the libraries shall be searched) to the "PROJECT_C_FLAGS".
+ * - Set the path to search for header files to the INCLUDE_PATH variable.
+ * - Set variables needed by the linker to LIBRARIES_PATH.
+ *
+ * - Example configuration made for a Yocto image on iMX6:
+ * \code
+ * #!/bin/sh
+ * source /opt/poky/1.6.2/environment-setup-cortexa9hf-vfp-neon-poky-linux-gnueabi
+ * export ARCH=arm
+ * export CC=${CROSS_COMPILE}gcc
+ * export KDIR=/home/x/fsl-community-bsp/build/tmp/work/imx6qsabreauto-poky-linux-gnueabi/linux-imx/3.10.53-r0/git
+ * export PROJECT_C_FLAGS="-static -L /home/x/fsl-community-bsp/build/tmp/sysroots/imx6qsabreauto/usr/lib -lm -lz -lcrypt -pthread"
+ * export INCLUDE_PATH="-I/home/x/fsl-community-bsp/build/tmp/sysroots/imx6qsabreauto/usr/include/libxml2"
+ * export LIBRARIES_FLAGS="-lm -lz -lcrypt"
+ * \endcode
+ * <br/>
+ * - Example configuration made for a LTIB image on iMX6:
+ * \code
+ * #!/bin/sh
+ * export CROSS_COMPILE=/opt/freescale/usr/local/gcc-4.6.2-glibc-2.13-linaro-multilib-2011.12/fsl-linaro-toolchain/bin/arm-none-linux-gnueabi-
+ * export ARCH=arm
+ * export CC=${CROSS_COMPILE}gcc
+ * export KDIR=/home/x/imx6/sdk/ltib/rpm/BUILD/linux
+ * export PROJECT_C_FLAGS="-L /home/x/imx6/sdk/ltib/rootfs/usr/lib -lm -lz -lcrypt -pthread"
+ * export INCLUDE_PATH="-I/home/x/imx6/sdk/ltib/rootfs/usr/include/libxml2"
+ * export LIBRARIES_FLAGS="-lm -lz -lcrypt"
+ * \endcode
+ * <br/>
+ *
+ * Next load the variables.
+ * - Enter:
+ * \code source crosscompile.sh \endcode
+ * - To check if the variables are set, at any time for a certain terminal, enter:
+ * \code echo $ARCH \endcode
+ * When "arm" is printed, the variables are loaded.
+ * \note The variables are only loaded in the current shell. If you open a new shell or a new tab, the variables have then loaded again.
+ * \note If you want to run the binaries on the same host and you are on a Debian based system, you may skip this step. If you encounter problems anyway, you may have to set the PROJECT_C_FLAGS, INCLUDE_PATH and LIBRARIES_PATH also.
+ *
+ * \subsection step3 Step 3: Compile driver and examples
+ * The VoD server sample application needs the libxml2 library, this may cause problems while compiling and linking. In this case, you have to find the library and the headers for your target. Maybe your platform builder (LTIB, Yocto) can create the needed library.\n
+ * On a Debian based system you can easily install these packages by typing:
+ * \code sudo apt-get install build-essential libxml2-dev \endcode
+ *
+ * Compiling all the examples and the MOST Linux Driver is done by calling make in the root folder of the package.
+ * \code make \endcode
+ *
+ * It may be necessary to patch the Linux Driver source code, depending on the Kernel version you use.
+ * For Kernel Version 3.16.x, enter:
+ * \code
+ * make patch-kernel-3.16
+ * make
+ * \endcode
+ * For Kernel Version 3.18.x, enter:
+ * \code
+ * make patch-kernel-3.18
+ * make
+ * \endcode
+ * If you are facing problems with a different kernel version, please let us know: support-ais-de@microchip.com
+ *
+ * Compiling just the examples, without the MOST Linux Driver, enter:
+ * \code make examples\endcode
+ *
+ * If you want to build also the driver for DIM2-IP, enter:
+ * \code make dim2\endcode
+ *
+ * If you want to clean up the folder, enter:
+ * \code make clean \endcode
+ * \subsection step4 Step 4: Setup Streaming parameters and deploy configuration file
+ * Use your favorite text editor to edit "config.xml". \n
+ * Example:
+ * \code vi config.xml \endcode
+ * or:
+ * \code gedit config.xml \endcode
+ *
+ * The given file is ready to work, but it may be changed to reflect the real use cases.
+ *
+ * The parameters that may be changed by the user are:
+ * - \code network_manager.network_config \endcode Must be instanced only once.
+ *
+ * - \code network_manager.network_config.timing_master \endcode
+ * - 1 = VoD Server will act as timing master on all connected INICs.
+ * - 0 = VoD Server will act as timing slave on all connected INICs.
+ *
+ * - \code network_manager.network_config.async_bandwidth \endcode = The amount of bytes reserved for Ethernet data. \n
+ * - 0 = no Ethernet traffic possible, max isochronous Bandwidth. \n
+ * - 372 = Max Ethernet Bandwidth, no isochronous traffic possible. \n
+ *
+ * - \code network_manager.device \endcode May be instanced multiple times.
+ *
+ * - \code network_manager.device.device_type \endcode Identifier for a specific types of hardware. \n
+ * The implementation uses the INIC group address to hold this value. See Step 5. \n
+ * So make sure to set the value correctly in the ConfigString with INIC Explorer tool. \n
+ *
+ * Here some examples: \n
+ * - 784 (0x310): Server with OS81118 \n
+ * - 810 (0x320): Seat with OS81110 \n
+ * - 816 (0x330): Seat with OS81118 \n
+ * - 832 (0x340): Tuner with OS81110 \n
+ * \note This value must be specified in decimal way. \n Setting hex value with leading 0x will not work. \n
+ *
+ * - \code network_manager.device.device_api_ver \endcode The Port Message Protocol Version number. \n
+ * - OS81110 uses API version 1, so set value to 1. \n
+ * - OS81118 uses API version 2, so set value to 2. \n
+ *
+ * - \code network_manager.device.channel \endcode May be instanced multiple times.
+ *
+ * - \code network_manager.device.channel.channel_id \endcode Unique identifier for this channel.
+ * May be incremented with every new instance inside "network_manager.device".
+ *
+ * - \code network_manager.device.channel.socket \endcode" Must be instanced two times for all data types except of asynchronous channel. \n
+ * One instance is the input socket and the other is the output socket. \n
+ * \note Asynchronous channel must be one channel, specify the bus to the EHC (e.g. MLB). \n
+ * The asynchronous MOST channel will be automatically created.
+ *
+ * - \code network_manager.device.channel.socket.dir \endcode Specifies the direction of the current socket. \n
+ * Possible values are: \n
+ * - "IN" - The current socket will act as source.
+ * - "OUT" - The current socket will act as sink.
+ *
+ * - \code network_manager.device.channel.socket.port_id \endcode Enumeration declaring the type of physical port to use. \n
+ * Possible values are currently: \n
+ * - "MLB" - Media Local Bus, OS81110 and OS81118 \n
+ * - "USB" - Universal Serial Bus, OS81118 \n
+ * - "I2S" - Streaming port, OS81110 and OS81118 \n
+ * - "MOST"
+ *
+ * - \code network_manager.device.channel.socket.data_type \endcode Enumeration declaring the type of data type transmitted. \n
+ * Possible value currently only: \n
+ * - "ISOC" - Isochronous data. \n
+ * - "ASYNC" - Asynchronous data.
+ * - "SYNC" - Synchronous data.
+ *
+ * - \code network_manager.device.channel.socket.channel_addr \endcode Is only valid for non MOST physical ports. \n
+ * - In case of MLB this is the MLB-channel address. \n
+ * - In case of USB this is the USB endpoint address. \n
+ * \note This value must be specified in decimal way. \n Setting hex value with leading 0x will not work. \n
+ *
+ * - \code network_manager.device.channel.socket.blockwidth \endcode Is only valid for the MOST and MLB physical ports.
+ * The value is given as amount of bytes, reserved specific for this socket.
+ *
+ * - \code network_manager.device.channel.socket.number_of_buffers \endcode Is only valid for local attached INICs.
+ * The value is given as amount of buffers used in the driver.
+ * \note This property is optional. If not set, the application will try to use default values.
+ *
+ * - \code network_manager.device.channel.socket.buffer_size \endcode Is only valid for local attached INICs.
+ * The value is given as amount of bytes of a single buffer used in the driver.
+ * \note This property is optional. If not set, the application will try to use default values.
+ *
+ * - \code network_manager.device.channel.socket.packets_per_xact \endcode Is only valid for local attached INICs.
+ * The value is given as amount packets transmitted in one USB frame which is max. 512 byte long.
+ * For datatype ISOC and SYNC stuffing will be used,to fill up the unused bytes of the USB frame.
+ * \note This property is optional. If not set, the application will try to use default values.
+ *
+ * - \code network_manager.device.channel.socket.subbuffer_size \endcode
+ * The value is given as amount of bytes. It measures the width of a subbuffer.
+ * For datatype ISOC this may be for example 188 or 196 byte.
+ * \note This property is optional. If not set, the application will try to use default values.
+ *
+ * Copy the configuration to the target: \n
+ * Example: \n
+ * \code scp config.xml root@192.168.1.100:/root \endcode
+ * \note If you do not cross compile, you can skip the copy process. Otherwise you need to adapt the IP address according to your targets address. The folder is freely choosable, here: "/root".
+ *
+ * \subsection step5 Step 5: Setup INICs on all platforms
+ * \note InicExplorer V1 and Target Manager (InicExplorer V2) will run under Microsoft Windows operating systems only.
+ *
+ * The latest version of InicExplorer V1 can be downloaded from this URL: \n
+ * http://www.k2l.de/products/analysis-and-verification-tools/inic-medialb-tools/inic-explorer/inic-explorer-downloads
+ *
+ * The Target Manager (InicExplorer V2) installer is included in this package in the sub-folder "Resources".
+ *
+ * - The configuration of OS81110 is done with the InicExplorer V1 tool.
+ * - The configuration of OS81118 is done with the Target Manager (InicExplorer V2) tool.
+ *
+ * \note <b>Important hint:</b> The <b>MOST group address</b> set in the ConfigString is interpreted as DeviceType! \n
+ * This means certain types of devices share the same group address. \n
+ * Here some examples, configured by the config.xml shipped along with this package: \n
+ * - 784 (0x310): Server with OS81118
+ * - 810 (0x320): Seat with OS81110
+ * - 816 (0x330): Seat with OS81118
+ * - 832 (0x340): Tuner with OS81110
+ *
+ * Also there are example configuration files, for the Target Manager (InicExplorer V2) (FileEnding.jscs). \n
+ * \n
+ * Currently the VoD server application expects the OS8118 USB endpoints to be configured as following: \n
+ * Receive endpoints:
+ * - EP-81 = RX CONTROL
+ * - EP-82 = RX ASYNC
+ * - EP-83 = RX
+ * - EP-84 = RX
+ * - EP-85 = RX
+ * - EP-86 = RX
+ * - EP-87 = RX
+ *
+ * Transmit endpoints:
+ * - EP-08 = TX CONTROL
+ * - EP-09 = TX ASYNC
+ * - EP-0A = TX
+ * - EP-0B = TX
+ * - EP-0C = TX
+ * - EP-0D = TX
+ * - EP-0E = TX
+ * - EP-0F = TX
+ *
+ * For the OS81118 INICs attached to the server device do following steps:
+ * - Attach InicExplorer hardware to UART and connect it to the INIC connector.
+ * - Open Target Manager (InicExplorer V2)
+ * - Press the "Detect"-button. (If not found, try different COM instance)
+ * - Flash INIC firmware, provided by this package, by pressing "Flash"-button.
+ * - Select "OS81118_Vx_x_x_x_PV.mchpkg" and press the "Open"-button. Replace the 'x' characters with you version.
+ * - Make sure that in the next window there is "configstring" and "firmware"-check-box is checked. Then press "Ok"-Button.
+ * - Flashing takes some minutes.
+ * - After successful flashing, press "Explore"-button.
+ * - Press "Ok"-Button in the upcoming Package Selector dialogue.
+ * - Press "Load"-Button in the Configuration String Editor Window.
+ * - Select "inic-config-ga310.jscs", and press "Open"-Button.
+ * - Verify the settings, if they match to your needs.
+ * - Press "Write"-Button to write the configuration into the INIC.
+ *
+ * \subsection step6 Step 6: Load Linux driver on target
+ * Login into your target. This step will be necessary both for server and clients. \n
+ * Switch to the directory, where you have copied all outputs of the previous steps. \n
+ *
+ * In order to load all drivers and set them up in one step.\n
+ * Enter: \n
+ * \code sudo ./loadDriver.sh &\endcode
+ * \note The trailing "&" will run the script as daemon. It will run in background and set the driver up, whenever a new INIC is detected. \n
+ *
+ * \note If the device does not appear in the /dev folder, check if the USB device was registered to the system by typing: \code lsusb \endcode
+ *
+ * In order to unload the driver and the background daemon.\n
+ * Enter: \n
+ * \code
+ * sudo killall loadDriver.sh
+ * sudo ./unloadDriver.sh
+ * \endcode
+ *
+ *
+ * \subsection step7 Step 7: Enable Ethernet communication on MOST
+ *
+ * The "loadDriver.sh" shell script, started in the previous script, already started the MOST Ethernet device.\n
+ * But in order to get a correct network setup, you have to assign unique IP-addresses to each of your target.
+ *
+ * Login to the client target device. \n
+ * Switch to the directory, where you have copied all outputs of the previous steps. \n
+ * \n
+ * Check if the meth0 device is created. \n
+ * Enter:\n
+ * \code ifconfig\endcode
+ * \n
+ * Display Output:\n
+ * \code
+ * meth0 Link encap:Ethernet HWaddr 02:00:00:00:00:01
+ * inet addr:10.0.0.1 Mask:255.255.255.0
+ * BROADCAST MULTICAST MTU:1500 Metric:1
+ * RX packets:0 errors:0 dropped:0 overruns:0 frame:0
+ * TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
+ * collisions:0 txqueuelen:1000
+ * RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
+ * \endcode
+ * \n
+ * The IP address 10.0.0.1 is already set in the shell script mentioned above.\n
+ * \n
+ * Use your favorite text editor to edit "loadDriver.sh".:
+ * - Example:
+ * \code vi loadDriver.sh \endcode
+ * - Or:
+ * \code gedit loadDriver.sh \endcode
+ *
+ * Scroll down to the StartEthernetUsb function, you will find the ifconfig statement which sets the
+ * IP address to 10.0.0.1. \n
+ *
+ * You have to adapt the address in this way, so it is unique in the whole network. This may be done
+ * by incrementing the last number with every new target (10.0.$i.<b>1</b>).
+ *
+ * \code
+ * #ETHERNET
+ * SetEthChannel $i ep82 rx 2048
+ * SetEthChannel $i ep09 tx 2048 10.0.$i.1
+ * \endcode
+ * \n
+ * \note Do this step for any client.\n
+ *
+ * \subsection Appendix Appendix:
+ * Timing sequence of NetworkManager startup:
+ * <img src="NMSequence.png" alt="NetworkManager startup sequence" width="80%"/>\n
+ */
+/*----------------------------------------------------------*/
+
+
+
+#endif //DOXYGEN_START_PAGE_H
diff --git a/Src/IP/MostIpc.cpp b/Src/IP/MostIpc.cpp
new file mode 100644
index 0000000..86e7341
--- /dev/null
+++ b/Src/IP/MostIpc.cpp
@@ -0,0 +1,510 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <assert.h>
+#include "Console.h"
+#include "MostIpc.h"
+
+
+#define TCP_BUFFER_SIZE (1024*1024)
+
+CMostIpc::CMostIpc( int port, bool server ) : isServer( server ), allowThreadRun( true ),
+ udpRxThreadIsRunning( false ), txThreadIsRunning (false), acceptThreadIsRunning( false )
+{
+ if( isServer && 0 >= port )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"CMostIpc: Server port must be greater than 0!"RESETCOLOR"\n" );
+ return;
+ }
+ pthread_mutex_init( &critical_mutex_tcp, NULL );
+ sem_init( &semTx, 0, 0 ); //Mutex, initialized to 0 => sem_wait will block instantly
+
+ struct sockaddr_in listenAddress;
+ /* Receive address configuration */
+ memset( &listenAddress, 0, sizeof( listenAddress ) );
+ listenAddress.sin_family = AF_INET;
+ listenAddress.sin_addr.s_addr = htonl( INADDR_ANY );
+ listenAddress.sin_port = htons( port );
+
+ if( 0 > ( udpSock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"CMostIpc: Failed to create UDP socket"RESETCOLOR"\n" );
+ return;
+ }
+ if( 0 > ( tcpSock = socket( PF_INET, SOCK_STREAM, 0 ) ) )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"CMostIpc: Failed to create TCP socket"RESETCOLOR"\n" );
+ return;
+ }
+
+ //Avoid hanging socket after killing application, only works with Linux kernel > 3.9
+#if defined (SO_REUSEADDR) && defined (SO_REUSEPORT)
+ int one = 1;
+ setsockopt(udpSock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &one, sizeof(one));
+ setsockopt(tcpSock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &one, sizeof(one));
+#endif
+
+ // this call is what allows broadcast UDP packets to be sent:
+ int enableSocketFlag = 1;
+ if( 0 > setsockopt( udpSock, SOL_SOCKET, SO_BROADCAST, &enableSocketFlag, sizeof( enableSocketFlag ) ) )
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"CMostIpc: setsockopt (SO_BROADCAST) failed, tried to set to: %d"RESETCOLOR"\n", enableSocketFlag );
+ }
+ if( 0 < port )
+ {
+ if( 0 > bind( udpSock, ( struct sockaddr * )&listenAddress, sizeof listenAddress ) )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Failed to bind UDP socket"RESETCOLOR"\n" );
+ }
+ if( 0 > bind( tcpSock, ( struct sockaddr * )&listenAddress, sizeof listenAddress ) )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"CMostIpc: Failed to bind TCP socket"RESETCOLOR"\n" );
+ }
+ }
+ if( isServer )
+ {
+ pthread_t acceptThread;
+ pthread_create( &acceptThread, NULL, CMostIpc::TcpAcceptThread, ( void * )this );
+ }
+ pthread_t udpRxThread, txThread;
+ pthread_create( &udpRxThread, NULL, CMostIpc::UdpWorkerRXThread, ( void * )this );
+ pthread_create( &txThread, NULL, CMostIpc::TXThread, ( void * )this );
+}
+
+CMostIpc::~CMostIpc()
+{
+ allowThreadRun = false;
+ close( udpSock );
+ close( tcpSock );
+ sem_post(&semTx);
+ int32_t timeout = 100;
+ while( ( udpRxThreadIsRunning || txThreadIsRunning || acceptThreadIsRunning ) && ( --timeout > 0 ) )
+ usleep( 10000 );
+ pthread_mutex_lock( &critical_mutex_tcp );
+ for( uint32_t i = 0; i < m_TcpClientConnections.Size(); i++ )
+ {
+ TcpClientInfo_t *var = m_TcpClientConnections[i];
+ if( NULL != var )
+ {
+ if( var->clientSock >= 0 )
+ close( var->clientSock );
+ var->clientSock = -1;
+ }
+ }
+ m_TcpClientConnections.RemoveAll(false);
+ pthread_mutex_unlock( &critical_mutex_tcp );
+}
+
+void CMostIpc::SendMsg( CMostMsgTx *Msg )
+{
+ if( NULL != Msg )
+ {
+ Msg->AddReference();
+ m_MsgTxQueue.PushBack( Msg );
+ sem_post(&semTx);
+ }
+}
+
+void CMostIpc::RegisterMessageHandler( CMsgFilter *Filter )
+{
+ m_MsgFilterQueue.PushBack( Filter );
+}
+
+void CMostIpc::UnregisterMessageHandler( CMsgFilter *Filter )
+{
+ m_MsgFilterQueue.Remove(Filter);
+}
+
+void *CMostIpc::TcpWorkerThread( void *pInst )
+{
+ bool allowWorker = true;
+ TcpClientInfo_t *clientInfo = ( TcpClientInfo_t * )pInst;
+ if( NULL == clientInfo || NULL == clientInfo->ipc || 0 > clientInfo->clientSock )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"TcpWorkerThread: Invalid parameters"RESETCOLOR"\n" );
+ return NULL;
+ }
+ uint8_t *buff = ( uint8_t * )malloc( TCP_BUFFER_SIZE );
+ if( NULL == buff )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"TcpWorkerThread: Failed to allocate buffer"RESETCOLOR"\n" );
+ return NULL;
+ }
+
+ ConsolePrintf( PRIO_MEDIUM, "TcpWorkerThread: Start for IP:%s, Port:%d\n", clientInfo->clientIP, clientInfo->clientPort );
+
+ CMsgAddr *adr = new CMsgAddr( clientInfo->clientIP, clientInfo->clientPort, IpcTcp_V2_0 );
+ CMostMsg *msg = NULL;
+
+ while( clientInfo->ipc->allowThreadRun && allowWorker )
+ {
+ int nRead;
+ if( 0 >= ( nRead = read( clientInfo->clientSock, buff, TCP_BUFFER_SIZE ) ) )
+ {
+ if( clientInfo->ipc->allowThreadRun )
+ {
+ if( 0 == nRead )
+ ConsolePrintf( PRIO_MEDIUM, GREEN"TcpWorkerThread: TCP Client disconnected (IP:%s)"RESETCOLOR"\n",
+ clientInfo->clientIP );
+ else
+ ConsolePrintf( PRIO_ERROR, YELLOW"TcpWorkerThread: Read error (return=%d), aborting .."RESETCOLOR"\n", nRead );
+ }
+ allowWorker = false;
+ break;
+ }
+ for( int i = 0; i < nRead; i++ )
+ {
+ if( NULL == msg )
+ msg = new CMostMsg();
+ if( !msg->Parse( buff[i] ) )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"TcpWorkerThread: Parse error, aborting.."RESETCOLOR"\n" );
+ allowWorker = false;
+ break;
+ }
+ if( msg->IsValid() )
+ {
+ clientInfo->ipc->OnMsgReceived( adr, msg );
+ msg->RemoveReference();
+ msg = NULL;
+ }
+ }
+ }
+ ConsolePrintf( PRIO_LOW, "TcpWorkerThread: End\n" );
+ if( clientInfo->clientSock >= 0 )
+ close( clientInfo->clientSock );
+
+ pthread_mutex_t *pMutex = &clientInfo->ipc->critical_mutex_tcp;
+ pthread_mutex_lock( pMutex );
+ clientInfo->ipc->m_TcpClientConnections.Remove(clientInfo);
+ free( clientInfo );
+ pthread_mutex_unlock( pMutex );
+
+ adr->RemoveReference();
+ free( buff );
+ return NULL;
+}
+
+void *CMostIpc::TcpAcceptThread( void *pInst )
+{
+ CMostIpc *ipc = ( CMostIpc * )pInst;
+ if( NULL == ipc || 0 > ipc->tcpSock )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"TcpAcceptThread was called with invalid parameters"RESETCOLOR"\n" );
+ return NULL;
+ }
+
+ ConsolePrintf( PRIO_LOW, "TcpAcceptThread starts\n" );
+ ipc->acceptThreadIsRunning = true;
+ while( ipc->allowThreadRun )
+ {
+ listen( ipc->tcpSock, 5 );
+ socklen_t size = sizeof( struct sockaddr_in );
+ TcpClientInfo_t *var = ( TcpClientInfo_t * )calloc( 1, sizeof( TcpClientInfo_t ) );
+ if( NULL == var )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Failed to allocate memory in TCP accept Thread, aborting.."RESETCOLOR"\n" );
+ break;
+ }
+ struct sockaddr_in clientAddr;
+ var->clientSock = accept( ipc->tcpSock, ( struct sockaddr * )&clientAddr, &size );
+ if( !ipc->allowThreadRun )
+ break;
+ if( -1 == var->clientSock )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Failed to accept connection"RESETCOLOR"\n" );
+ free( var );
+ continue;
+ }
+ var->ipc = ipc;
+ inet_ntop( AF_INET, ( struct sockaddr_in * )&clientAddr.sin_addr, var->clientIP, sizeof ( var->clientIP ) );
+ var->clientPort = ntohs( clientAddr.sin_port );
+ ConsolePrintf( PRIO_MEDIUM, GREEN"TCP Client connected: IP=%s, Port=%d"RESETCOLOR"\n",
+ var->clientIP, var->clientPort );
+ pthread_mutex_lock( &var->ipc->critical_mutex_tcp );
+ var->ipc->m_TcpClientConnections.PushBack( var );
+ pthread_mutex_unlock( &var->ipc->critical_mutex_tcp );
+ pthread_create( &var->workerThread, NULL, CMostIpc::TcpWorkerThread, ( void * )var );
+ }
+ ConsolePrintf( PRIO_LOW, "TcpAcceptThread ends\n" );
+ close( ipc->tcpSock );
+ ipc->acceptThreadIsRunning = false;
+ return NULL;
+}
+
+void CMostIpc::OnMsgReceived( CMsgAddr *Addr, CMostMsg *msg )
+{
+ if( NULL == Addr || NULL == msg )
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"CMostIpc::OnMsgReceived was called with invalid parameters"RESETCOLOR"\n" );
+ return;
+ }
+ ConsolePrintf( PRIO_LOW, "Received MOST-IPC message IP=%s, Protocol:%s, "\
+ "FBlock:0x%X, Func:0x%X, OP:0x%X, PL:%d Bytes\n", Addr->GetInetAddress(), ( Addr->GetProtocol() ==
+ IpcUdp_V2_0 ? "UDP" : "TCP" ), msg->GetFBlock(), msg->GetFunc(), msg->GetOpType(), msg->GetPayloadLen() );
+
+ for( uint32_t i = 0; i < m_MsgFilterQueue.Size(); i++ )
+ {
+ m_MsgFilterQueue[i]->Filter( Addr, msg );
+ }
+}
+
+bool CMostIpc::SendUdp( const char *ipAddress, uint32_t port, const uint8_t *buffer, uint32_t bufferLen )
+{
+ struct sockaddr_in destination;
+ memset( &destination, 0, sizeof ( destination ) );
+ destination.sin_family = AF_INET;
+ destination.sin_addr.s_addr = inet_addr( ipAddress );
+ destination.sin_port = htons( port );
+ ssize_t bytesSent = sendto( udpSock, buffer, bufferLen,
+ 0, ( struct sockaddr * )&destination, sizeof ( destination ) );
+ return ( ( uint32_t )bytesSent == bufferLen );
+}
+
+bool CMostIpc::SendTcp( const char *ipAddress, uint32_t port, const uint8_t *buffer, uint32_t bufferLen )
+{
+ bool success = false;
+ TcpClientInfo_t *tcp = NULL;
+
+ //Find the correct client connection
+ pthread_mutex_lock( &critical_mutex_tcp );
+ for( uint32_t i = 0; i < m_TcpClientConnections.Size(); i++ )
+ {
+ TcpClientInfo_t *t = m_TcpClientConnections[i];
+ if( NULL != t && t->clientPort == port && 0 == strcmp( t->clientIP, ipAddress ) )
+ {
+ tcp = t;
+ break;
+ }
+ }
+ //There is no connection matching to the given address and port, try to connect if we are not master
+ if( !isServer && NULL == tcp )
+ {
+ TcpClientInfo_t *var = ( TcpClientInfo_t * )calloc( 1, sizeof( TcpClientInfo_t ) );
+ if( NULL != var )
+ {
+ var->ipc = this;
+ var->clientPort = port;
+ var->clientSock = tcpSock;
+ strncpy( var->clientIP, ipAddress, sizeof( var->clientIP ) );
+
+ struct hostent *hostp;
+ hostp = gethostbyname( var->clientIP );
+ if( NULL != hostp )
+ {
+ struct sockaddr_in addr;
+ memset( &addr, 0x00, sizeof( struct sockaddr_in ) );
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons( var->clientPort );
+ memcpy( &addr.sin_addr, hostp->h_addr, sizeof( addr.sin_addr ) );
+ if( 0 == connect( tcpSock, ( struct sockaddr * )&addr, sizeof( addr ) ) )
+ {
+ tcp = var;
+ m_TcpClientConnections.PushBack( tcp );
+ pthread_create( &tcp->workerThread, NULL, CMostIpc::TcpWorkerThread, ( void * )tcp );
+ ConsolePrintf( PRIO_MEDIUM, GREEN"Connect to TCP host succeeded: IP=%s Port=%d"RESETCOLOR"\n", tcp->clientIP,
+ tcp->clientPort );
+
+ }
+ else
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Could not connect to host: '%s'"RESETCOLOR"\n", var->clientIP );
+ free( var );
+ }
+ }
+ else
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Could not find host: '%s'"RESETCOLOR"\n", var->clientIP );
+ free( var );
+ }
+ }
+ else
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Failed to allocate memory in SendTcp method"RESETCOLOR"\n" );
+ }
+ }
+
+ if( NULL != tcp )
+ {
+ int result;
+ uint32_t written = 0;
+ success = true;
+ while( written < bufferLen )
+ {
+ result = write( tcp->clientSock, &buffer[written], bufferLen - written );
+ if( result < 0 )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"SendTcp: Write error"RESETCOLOR"\n" );
+ success = false;
+ break;
+ }
+ else if( result == 0 )
+ {
+ //Socket is non blocking, sleep to avoid 100% CPU load
+ usleep( 1000 );
+ }
+ else
+ {
+ written += result;
+ }
+ }
+ pthread_mutex_unlock( &critical_mutex_tcp );
+ }
+ return success;
+}
+
+void *CMostIpc::UdpWorkerRXThread( void *pInst )
+{
+ CMostIpc *ipc = ( CMostIpc * )pInst;
+ if( NULL == ipc || 0 > ipc->udpSock )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"UdpWorkerRXThread was called with invalid parameters"RESETCOLOR"\n" );
+ return NULL;
+ }
+ ipc->udpRxThreadIsRunning = true;
+ while( ipc->allowThreadRun )
+ {
+ //Receive
+ if( ipc->allowThreadRun )
+ {
+ uint8_t tempBuffer[8*1024];
+ char remoteIP[INET6_ADDRSTRLEN];
+ uint32_t port;
+ struct sockaddr_in fromAddr;
+ socklen_t fromAddrLen = sizeof( fromAddr );
+ ssize_t receivedLength;
+ receivedLength = recvfrom
+ ( ipc->udpSock, tempBuffer, sizeof( tempBuffer ),
+ 0, ( struct sockaddr * )&fromAddr, &fromAddrLen );
+ if( receivedLength > 0 )
+ {
+ inet_ntop( AF_INET, ( struct sockaddr_in * )&fromAddr.sin_addr, remoteIP, sizeof( remoteIP ) );
+ port = ntohs( fromAddr.sin_port );
+ CMsgAddr *adr = new CMsgAddr( remoteIP, port );
+ CMostMsg *msg = new CMostMsg();
+ for( int32_t i = 0; i < receivedLength; i++ )
+ {
+ if( !msg->Parse( tempBuffer[i] ) )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"CMostIpc UDP received unparsable message"RESETCOLOR"\n" );
+ break;
+ }
+ }
+ if( msg->IsValid() )
+ ipc->OnMsgReceived( adr, msg );
+ adr->RemoveReference();
+ msg->RemoveReference();
+ }
+ }
+ }
+ ipc->udpRxThreadIsRunning = false;
+ return NULL;
+}
+
+void *CMostIpc::TXThread( void *pInst )
+{
+ CMostIpc *ipc = ( CMostIpc * )pInst;
+ if( NULL == ipc || 0 > ipc->udpSock )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"TXThread was called with invalid parameters"RESETCOLOR"\n" );
+ return NULL;
+ }
+ ipc->txThreadIsRunning = true;
+
+ while( ipc->allowThreadRun )
+ {
+ sem_wait(&ipc->semTx);
+ if (!ipc->allowThreadRun)
+ break;
+ CMostMsgTx *MsgTx = ipc->m_MsgTxQueue.PopFront();
+ assert (NULL != MsgTx);
+ if( NULL != MsgTx )
+ {
+ uint8_t *tempBuffer = NULL;
+ uint32_t bytesUsed = MsgTx->ToByteArray( &tempBuffer );
+ if( NULL == tempBuffer || 0 == bytesUsed )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"MOST-IP: Failed to serialize message"RESETCOLOR"\n" );
+ if (NULL != tempBuffer)
+ free(tempBuffer);
+ MsgTx->MsgSent( false );
+ continue;
+ }
+ CMsgAddr *addr = MsgTx->GetAddr();
+ if( 0 != bytesUsed && NULL != addr )
+ {
+ char *ipAddress = addr->GetInetAddress();
+ uint32_t port = addr->GetPort();
+ if( NULL != ipAddress )
+ {
+ bool success = false;
+ switch( addr->GetProtocol() )
+ {
+ case IpcUdp_V2_0:
+ success = ipc->SendUdp( ipAddress, port, tempBuffer, bytesUsed );
+ break;
+ case IpcTcp_V2_0:
+ success = ipc->SendTcp( ipAddress, port, tempBuffer, bytesUsed );
+ break;
+ default:
+ ConsolePrintf( PRIO_ERROR, RED"MOST-IP: Unknown Protocol"RESETCOLOR"\n" );
+ break;
+ }
+ MsgTx->MsgSent( success );
+ }
+ else
+ {
+ ConsolePrintf( PRIO_ERROR, RED"MOST-IP: Can not resolve IP address"RESETCOLOR"\n" );
+ MsgTx->MsgSent( false );
+ }
+ }
+ else
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Error while sending in MOST IPC."RESETCOLOR"\n" );
+ MsgTx->MsgSent( false );
+ }
+ if (NULL != tempBuffer)
+ free( tempBuffer );
+ MsgTx->RemoveReference();
+ }
+ }
+ ipc->txThreadIsRunning = false;
+ return NULL;
+}
+
diff --git a/Src/IP/MostIpc.h b/Src/IP/MostIpc.h
new file mode 100644
index 0000000..0f8596d
--- /dev/null
+++ b/Src/IP/MostIpc.h
@@ -0,0 +1,164 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CMostIpc class.
+ */
+/*----------------------------------------------------------*/
+#ifndef IPC_H
+#define IPC_H
+
+#include <stdbool.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include "SafeVector.h"
+#include "MsgAddr.h"
+#include "MostMsgTx.h"
+#include "MsgAddr.h"
+#include "MsgFilter.h"
+
+class CMostIpc;
+
+/*! \cond PRIVATE */
+typedef struct
+{
+ pthread_t workerThread;
+ CMostIpc *ipc;
+ int clientSock;
+ char clientIP[46];
+ uint32_t clientPort;
+} TcpClientInfo_t;
+/*! \endcond */
+
+/*----------------------------------------------------------*/
+/*!
+ * \brief Inter Process Communication
+ * 1. sends messages using MOST protocol over UDP
+ * 2. receives messages and forwards them to their
+ * handlers
+ */
+/*----------------------------------------------------------*/
+class CMostIpc
+{
+private:
+ bool isServer;
+ bool allowThreadRun;
+ bool udpRxThreadIsRunning;
+ bool txThreadIsRunning;
+ bool acceptThreadIsRunning;
+ CSafeVector<CMostMsgTx *> m_MsgTxQueue;
+ CSafeVector<CMsgFilter *> m_MsgFilterQueue;
+ CSafeVector<TcpClientInfo_t *> m_TcpClientConnections;
+ pthread_mutex_t critical_mutex_rx;
+ pthread_mutex_t critical_mutex_tcp;
+ sem_t semTx;
+ int udpSock;
+ int tcpSock;
+
+ /*----------------------------------------------------------*/
+ /*! \brief TCP accept thread
+ * \note Never call this method directly!
+ */
+ /*----------------------------------------------------------*/
+ static void *TcpAcceptThread( void *pInst );
+
+ /*----------------------------------------------------------*/
+ /*! \brief TCP read / write thread
+ * \note Never call this method directly!
+ */
+ /*----------------------------------------------------------*/
+ static void *TcpWorkerThread( void *pInst );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief UDP receiving thread
+ * \note Never call this method directly!
+ */
+ /*----------------------------------------------------------*/
+ static void *UdpWorkerRXThread( void *pInst );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Sending thread
+ * \note Never call this method directly!
+ */
+ /*----------------------------------------------------------*/
+ static void *TXThread( void *pInst );
+
+ /*----------------------------------------------------------*/
+ /*! \brief handle a received message
+ */
+ /*----------------------------------------------------------*/
+ void OnMsgReceived( CMsgAddr *Addr, CMostMsg *msg );
+
+ bool SendUdp( const char *ipAddress, uint32_t port, const uint8_t *buffer, uint32_t bufferLen );
+ bool SendTcp( const char *ipAddress, uint32_t port, const uint8_t *buffer, uint32_t bufferLen );
+
+public:
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief constructs Inter Process Communication, which acts as Server
+ * \param port - If set to server by isServer=true, this value is the server port which the UDP and TCP sockets are listening.
+ * If set to client by isServer=false, this is the client socket port. If set to 0 or below, a random port will be chosen.
+ * Otherwise the given port will be used as source port of the connection. The server always can handle random and fixed client port connections.
+ * \param isServer - true, if this component shall act as "the" server. false, if this component shall act as one of many clients.
+ */
+ /*----------------------------------------------------------*/
+ CMostIpc( int port, bool isServer );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Deletes every resources used by Inter Process Communication
+ */
+ /*----------------------------------------------------------*/
+ ~CMostIpc();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief send a MOST message
+ */
+ /*----------------------------------------------------------*/
+ void SendMsg( CMostMsgTx *Msg );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief adds a message handler
+ */
+ /*----------------------------------------------------------*/
+ void RegisterMessageHandler( CMsgFilter *Filter );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief removes a message handler
+ */
+ /*----------------------------------------------------------*/
+ void UnregisterMessageHandler( CMsgFilter *Filter );
+
+};
+
+#endif //IPC_H
+
diff --git a/Src/IP/MostMsg.cpp b/Src/IP/MostMsg.cpp
new file mode 100644
index 0000000..3ca043f
--- /dev/null
+++ b/Src/IP/MostMsg.cpp
@@ -0,0 +1,405 @@
+/*
+ * 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 "Console.h"
+#include "MostMsg.h"
+#include <stdlib.h>
+
+static uint32_t crc32_tab[] =
+{
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+static uint32_t CalcCRC32( const uint8_t *p, uint32_t size )
+{
+ uint32_t crc = ~0U;
+
+ while( size-- )
+ crc = crc32_tab[( crc ^ *p++ ) & 0xFF] ^ ( crc >> 8 );
+
+ return crc ^ ~0U;
+}
+
+
+CMostMsg::CMostMsg() : m_nIsValid( false ), m_nRefCount( 1 ), m_nFBlock( 0 ), m_nFunc( 0 ), m_nInst( 0 ),
+ m_nOpType( 0 ), m_nPayloadLen( 0 ), m_Payload( NULL ), m_nParsePos( 0 ),
+ m_nHeaderCrc( 0 ), m_nPayloadCrc( 0 )
+{
+}
+
+CMostMsg::CMostMsg( uint32_t nFBlock, uint32_t nInst, uint32_t nFunc, uint8_t nOpType, uint32_t nPayloadLen,
+ const uint8_t *Payload ) : m_nIsValid( true ), m_nRefCount( 1 ), m_Payload( NULL ),
+ m_nParsePos( 0xFFFFFFFF ), m_nHeaderCrc( 0 ), m_nPayloadCrc( 0 )
+{
+ m_nFBlock = nFBlock;
+ m_nInst = nInst;
+ m_nFunc = nFunc;
+ m_nOpType = nOpType;
+ m_nPayloadLen = nPayloadLen;
+ if( nPayloadLen > 0 )
+ {
+ m_Payload = ( uint8_t * )malloc( m_nPayloadLen );
+ if( NULL == m_Payload )
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"CMostMsg Constructor failed to allocated %d bytes of memory"RESETCOLOR"\n", m_nPayloadLen );
+ m_nIsValid = false;
+ m_nPayloadLen = 0;
+ return;
+ }
+ memcpy( m_Payload, Payload, nPayloadLen );
+ }
+}
+
+CMostMsg::~CMostMsg()
+{
+ m_nIsValid = false;
+ m_nPayloadLen = 0;
+ if( NULL != m_Payload )
+ {
+ free( m_Payload );
+ m_Payload = NULL;
+ }
+}
+
+void CMostMsg::AddReference()
+{
+ ++m_nRefCount;
+}
+
+void CMostMsg::RemoveReference()
+{
+ if( 0 == --m_nRefCount )
+ delete this;
+}
+
+uint32_t CMostMsg::ToByteArray( uint8_t **ppBuffer )
+{
+ if( NULL == ppBuffer )
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"CMostMsg::ToByteArray ppBuffer is NULL < %d"RESETCOLOR"\n" );
+ return 0;
+ }
+ uint32_t serializedLen = 20;
+ if( 0 != m_nPayloadLen )
+ serializedLen += m_nPayloadLen + 4; //If there is payload, it will be CRC checked
+ uint8_t *b = ( uint8_t * )malloc( serializedLen );
+ if( NULL == b )
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"CMostMsg::ToByteArray failed to allocate %d bytes"RESETCOLOR"\n", ( m_nPayloadLen + 24 ) );
+ *ppBuffer = NULL;
+ return 0;
+ }
+ *ppBuffer = b;
+ b[0] = ( uint8_t )0x49;
+ b[1] = ( uint8_t )0x72;
+ b[2] = ( uint8_t )0x16;
+ b[3] = ( uint8_t )0x25;
+ b[4] = ( uint8_t )( m_nFBlock & 0xFF );
+ b[5] = ( uint8_t )( m_nInst & 0xFF );
+ b[6] = ( uint8_t )( ( m_nFunc >> 8 ) & 0xFF );
+ b[7] = ( uint8_t )( ( m_nFunc )&0xFF );
+ b[8] = ( uint8_t )( m_nOpType );
+ b[9] = ( uint8_t )0x0;
+ b[10] = ( uint8_t )0x0;
+ b[11] = ( uint8_t )0x0;
+ b[12] = ( uint8_t )( ( m_nPayloadLen >> 24 ) & 0xFF );
+ b[13] = ( uint8_t )( ( m_nPayloadLen >> 16 ) & 0xFF );
+ b[14] = ( uint8_t )( ( m_nPayloadLen >> 8 ) & 0xFF );
+ b[15] = ( uint8_t )( m_nPayloadLen & 0xFF );
+
+ uint32_t headerCrc = CalcCRC32( b, 16 );
+
+ b[16] = ( uint8_t )( ( headerCrc >> 24 ) & 0xFF );
+ b[17] = ( uint8_t )( ( headerCrc >> 16 ) & 0xFF );
+ b[18] = ( uint8_t )( ( headerCrc >> 8 ) & 0xFF );
+ b[19] = ( uint8_t )( headerCrc & 0xFF );
+
+ if( 0 != m_nPayloadLen )
+ {
+ for( uint32_t i = 0; i < m_nPayloadLen; i++ )
+ b[20 + i] = m_Payload[i];
+
+ uint32_t payloadCrc = CalcCRC32( &b[20], m_nPayloadLen );
+
+ b[20 + m_nPayloadLen] = ( uint8_t )( ( payloadCrc >> 24 ) & 0xFF );
+ b[21 + m_nPayloadLen] = ( uint8_t )( ( payloadCrc >> 16 ) & 0xFF );
+ b[22 + m_nPayloadLen] = ( uint8_t )( ( payloadCrc >> 8 ) & 0xFF );
+ b[23 + m_nPayloadLen] = ( uint8_t )( payloadCrc & 0xFF );
+ }
+ return serializedLen;
+}
+
+bool CMostMsg::Parse( uint8_t receivedByte )
+{
+ if( 0xFFFFFFFF == m_nParsePos )
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"CMostMsg::Parse was called, but the parse state is invalid"RESETCOLOR"\n" );
+ return false;
+ }
+ bool valid = true;
+ if( m_nParsePos <= 19 )
+ {
+ if( m_nParsePos <= 15 )
+ m_zHeader[m_nParsePos] = receivedByte;
+
+ //Check Header
+ switch( m_nParsePos )
+ {
+ case 0:
+ if( 0x49 != receivedByte )
+ valid = false;
+ break;
+ case 1:
+ if( 0x72 != receivedByte )
+ valid = false;
+ break;
+ case 2:
+ if( 0x16 != receivedByte )
+ valid = false;
+ break;
+ case 3:
+ if( 0x25 != receivedByte )
+ valid = false;
+ break;
+ case 4:
+ m_nFBlock = receivedByte;
+ break;
+ case 5:
+ m_nInst = receivedByte;
+ break;
+ case 6:
+ m_nFunc = receivedByte << 8;
+ break;
+ case 7:
+ m_nFunc += receivedByte;
+ break;
+ case 8:
+ m_nOpType = receivedByte;
+ break;
+ case 9:
+ case 10:
+ case 11:
+ //Reserved for future use cases
+ break;
+ case 12:
+ m_nPayloadLen = receivedByte << 24;
+ break;
+ case 13:
+ m_nPayloadLen += receivedByte << 16;
+ break;
+ case 14:
+ m_nPayloadLen += receivedByte << 8;
+ break;
+ case 15:
+ m_nPayloadLen += receivedByte;
+ break;
+ case 16:
+ m_nHeaderCrc = receivedByte << 24;
+ break;
+ case 17:
+ m_nHeaderCrc += receivedByte << 16;
+ break;
+ case 18:
+ m_nHeaderCrc += receivedByte << 8;
+ break;
+ case 19:
+ m_nHeaderCrc += receivedByte;
+ if( m_nHeaderCrc == CalcCRC32( m_zHeader, 16 ) )
+ {
+ if( 0 != m_nPayloadLen )
+ {
+ //Continue to parse the payload
+ m_Payload = ( uint8_t * )malloc( m_nPayloadLen );
+ if( NULL == m_Payload )
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"MostMsg::Protocol deserializing error, could not allocate %d bytes of memory"RESETCOLOR
+ "\n", m_nPayloadLen );
+ valid = false;
+ m_nPayloadLen = 0;
+ }
+ }
+ else
+ {
+ //No payload, we are finished
+ m_nIsValid = true;
+ m_nParsePos = 0xFFFFFFFF - 1;
+ }
+ }
+ else
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"MostMsg::Protocol error, header CRC does not match"RESETCOLOR"\n" );
+ valid = false;
+ }
+ break;
+ }
+ }
+ else
+ {
+ if( m_nParsePos < ( m_nPayloadLen + 20 ) )
+ {
+ //Check Payload and store it
+ if( NULL != m_Payload )
+ {
+ m_Payload[m_nParsePos - 20] = receivedByte;
+ }
+ else
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"MostMsg::Protocol deserializing error, payload buffer is NULL"RESETCOLOR"\n" );
+ valid = false;
+ m_nPayloadLen = 0;
+ }
+ }
+ else
+ {
+ //Finally check CRC of payload
+ uint32_t crcState = m_nParsePos - m_nPayloadLen - 20;
+ switch( crcState )
+ {
+ case 0:
+ m_nPayloadCrc = receivedByte << 24;
+ break;
+ case 1:
+ m_nPayloadCrc += receivedByte << 16;
+ break;
+ case 2:
+ m_nPayloadCrc += receivedByte << 8;
+ break;
+ case 3:
+ m_nPayloadCrc += receivedByte;
+ if( m_nPayloadCrc == CalcCRC32( m_Payload, m_nPayloadLen ) )
+ {
+ //Payload is successfully received
+ m_nIsValid = true;
+ m_nParsePos = 0xFFFFFFFF - 1;
+ }
+ else
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"MostMsg::Protocol deserializing error, Payload CRC mismatch"RESETCOLOR"\n" );
+ valid = false;
+ }
+ break;
+ default:
+ ConsolePrintf(
+ PRIO_ERROR, RED"MostMsg::Protocol deserializing error, Payload CRC state is out of range"RESETCOLOR"\n" );
+ valid = false;
+ }
+ }
+ }
+
+ if( valid )
+ {
+ ++m_nParsePos;
+ }
+ else
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"CMostMsg::Parse failed at parse position %d"RESETCOLOR"\n", m_nParsePos );
+ m_nParsePos = 0xFFFFFFFF;
+ }
+ return valid;
+}
+
+bool CMostMsg::IsValid()
+{
+ return m_nIsValid;
+}
+
+uint32_t CMostMsg::GetFBlock()
+{
+ return m_nFBlock;
+}
+
+uint32_t CMostMsg::GetFunc()
+{
+ return m_nFunc;
+}
+
+uint32_t CMostMsg::GetInst()
+{
+ return m_nInst;
+}
+
+uint8_t CMostMsg::GetOpType()
+{
+ return m_nOpType;
+}
+
+uint8_t *CMostMsg::GetPayload()
+{
+ return m_Payload;
+}
+
+uint32_t CMostMsg::GetPayloadLen()
+{
+ return m_nPayloadLen;
+}
diff --git a/Src/IP/MostMsg.h b/Src/IP/MostMsg.h
new file mode 100644
index 0000000..fb4bdd8
--- /dev/null
+++ b/Src/IP/MostMsg.h
@@ -0,0 +1,184 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CMostMsg class.
+ */
+/*----------------------------------------------------------*/
+#ifndef MOSTMSG_H
+#define MOSTMSG_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+
+/*----------------------------------------------------------*/
+/*!
+ * \brief class holding a MOST message, it support serializing and deserializing
+ * \note Serialize-Protocol is: </br>
+ * p[0] = 0x49 (Start) </br>
+ * p[1] = 0x72 (Start) </br>
+ * p[2] = 0x16 (Start) </br>
+ * p[3] = 0x25 (Start) </br>
+ * p[4] = FBlock Identifier </br>
+ * p[5] = Instance Identifier </br>
+ * p[6] = Function Identifier << 8 </br>
+ * p[7] = Function Identifier << 0 </br>
+ * p[8] = OP Type </br>
+ * p[9] = 0x0 (Reserved) </br>
+ * p[10] = 0x0 (Reserved) </br>
+ * p[11] = 0x0 (Reserved) </br>
+ * p[12] = Payload Length << 24 </br>
+ * p[13] = Payload Length << 16 </br>
+ * p[14] = Payload Length << 8 </br>
+ * p[15] = Payload Length << 0 </br>
+ * p[16] = Header CRC32(p[0] - p[15]) << 24 </br>
+ * p[17] = Header CRC32(p[0] - p[15]) << 16 </br>
+ * p[18] = Header CRC32(p[0] - p[15]) << 8 </br>
+ * p[19] = Header CRC32(p[0] - p[15]) << 0 </br>
+ * p[20] - p[n] = Payload </br>
+ * p[n+1] = Payload CRC32(p[20] - p[n]) << 24 </br>
+ * p[n+2] = Payload CRC32(p[20] - p[n]) << 16 </br>
+ * p[n+3] = Payload CRC32(p[20] - p[n]) << 8 </br>
+ * p[n+4] = Payload CRC32(p[20] - p[n]) << 0 </br>
+ */
+
+/*----------------------------------------------------------*/
+class CMostMsg
+{
+private:
+ bool m_nIsValid;
+ int32_t m_nRefCount;
+ uint32_t m_nFBlock;
+ uint32_t m_nFunc;
+ uint32_t m_nInst;
+ uint8_t m_nOpType;
+ uint32_t m_nPayloadLen;
+ uint8_t *m_Payload;
+ uint32_t m_nParsePos;
+ uint32_t m_nHeaderCrc;
+ uint32_t m_nPayloadCrc;
+ uint8_t m_zHeader[16];
+
+protected:
+ /*----------------------------------------------------------*/
+ /*! \brief Default Destructor
+ */
+ /*----------------------------------------------------------*/
+ virtual ~CMostMsg();
+
+public:
+
+ static const uint8_t OP_SET = 0x0;
+ static const uint8_t OP_GET = 0x1;
+ static const uint8_t OP_SETGET = 0x2;
+ static const uint8_t OP_INC = 0x3;
+ static const uint8_t OP_DEC = 0x4;
+ static const uint8_t OP_GETINTERFACE = 0x5;
+ static const uint8_t OP_STATUS = 0xC;
+ static const uint8_t OP_INTERFACE = 0xE;
+ static const uint8_t OP_ERROR = 0xF;
+ static const uint8_t OP_START = 0x0;
+ static const uint8_t OP_ABORT = 0x1;
+ static const uint8_t OP_STARTRESULT = 0x2;
+ static const uint8_t OP_STARTRESULTACK = 0x6;
+ static const uint8_t OP_ABORTACK = 0x7;
+ static const uint8_t OP_STARTACK = 0x8;
+ static const uint8_t OP_ERRORACK = 0x9;
+ static const uint8_t OP_PROCESSINGACK = 0xA;
+ static const uint8_t OP_PROCESSING = 0xB;
+ static const uint8_t OP_RESULT = 0xC;
+ static const uint8_t OP_RESULTACK = 0xD;
+ static const uint8_t OP_REPORTS = 0x9;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief constructs a new message, which is initial not valid.
+ * \note It has to fed by the Parse method until IsValid method reports true.
+ */
+ /*----------------------------------------------------------*/
+ CMostMsg();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief constructs a new message which is fully set up and valid
+ * \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.
+ */
+ /*----------------------------------------------------------*/
+ CMostMsg( uint32_t nFBlock, uint32_t nInst, uint32_t nFunc, uint8_t nOpType, uint32_t nPayloadLen,
+ const uint8_t *Payload );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Increments the reference counter
+ */
+ /*----------------------------------------------------------*/
+ void AddReference();
+
+ /*----------------------------------------------------------*/
+ /*! \brief Decrements the reference counter, if the value reaches 0, this object destroys it self.
+ */
+ /*----------------------------------------------------------*/
+ void RemoveReference();
+
+ /*----------------------------------------------------------*/
+ /*! \brief Fills out an empty CMostMsg (created with default constructor)
+ * \return true, if parsing was valid. false, parser error, no way to continue.
+ * \note Check with IsValid method if parsing is finished.
+ */
+ /*----------------------------------------------------------*/
+ bool Parse( uint8_t receivedByte );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief serializes a message to an byte array
+ * \note The byte array will be created inside this method and has to be freed after usage!
+ * \return The bytes used inside the given buffer.
+ */
+ /*----------------------------------------------------------*/
+ uint32_t ToByteArray( uint8_t **ppBuffer );
+
+
+ bool IsValid();
+
+ uint32_t GetFBlock();
+
+ uint32_t GetFunc();
+
+ uint32_t GetInst();
+
+ uint8_t GetOpType();
+
+ uint8_t *GetPayload();
+
+ uint32_t GetPayloadLen();
+};
+
+
+#endif //MOSTMSG_H
diff --git a/Src/IP/MostMsgTx.cpp b/Src/IP/MostMsgTx.cpp
new file mode 100644
index 0000000..d3c5864
--- /dev/null
+++ b/Src/IP/MostMsgTx.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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 "MostMsgTx.h"
+
+CMostMsgTx::CMostMsgTx( CMsgAddr *Addr, uint32_t nFBlock, uint32_t nInst, uint32_t nFunc, uint8_t nOpType,
+ uint32_t nPayloadLen, const uint8_t *Payload, uint32_t nTimeoutMs, OnMessageSent_t MessageSent,
+ void *UserContext ) : CMostMsg( nFBlock, nInst, nFunc, nOpType, nPayloadLen, Payload )
+{
+ if( NULL != Addr )
+ {
+ Addr->AddReference();
+ m_Addr = Addr;
+ }
+ m_nTimeoutMs = nTimeoutMs;
+ m_MessageSent = MessageSent;
+ m_UserContext = UserContext;
+}
+
+CMostMsgTx::~CMostMsgTx()
+{
+ if( NULL != m_Addr )
+ {
+ m_Addr->RemoveReference();
+ m_Addr = NULL;
+ }
+}
+
+
+
+/*----------------------------------------------------------*/
+/*! \brief calls message handler with the send result
+*/
+
+/*----------------------------------------------------------*/
+void CMostMsgTx::MsgSent( bool bSuccess )
+{
+ if( NULL != m_MessageSent )
+ m_MessageSent( bSuccess, this );
+}
+
+
+
+
+/*----------------------------------------------------------*/
+/*! \brief get target address
+*/
+
+/*----------------------------------------------------------*/
+CMsgAddr *CMostMsgTx::GetAddr()
+{
+ return m_Addr;
+}
+
+
+
+
+/*----------------------------------------------------------*/
+/*! \brief get user context
+*/
+
+/*----------------------------------------------------------*/
+void *CMostMsgTx::GetUserContext()
+{
+ return m_UserContext;
+}
diff --git a/Src/IP/MostMsgTx.h b/Src/IP/MostMsgTx.h
new file mode 100644
index 0000000..00736ae
--- /dev/null
+++ b/Src/IP/MostMsgTx.h
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CMostMsgTx class.
+ */
+/*----------------------------------------------------------*/
+#ifndef MOSTMSGTX_H
+#define MOSTMSGTX_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "MostMsg.h"
+#include "MsgAddr.h"
+
+
+
+
+/*----------------------------------------------------------*/
+/*!
+* \brief class holding a MOST message which needs to be
+* sent
+*/
+
+/*----------------------------------------------------------*/
+class CMostMsgTx : public CMostMsg
+{
+private:
+ typedef void ( *OnMessageSent_t )( bool bSucceeded, CMostMsgTx *Msg );
+ CMsgAddr *m_Addr;
+ uint32_t m_nTimeoutMs;
+ OnMessageSent_t m_MessageSent;
+ void *m_UserContext;
+
+protected:
+ virtual ~CMostMsgTx();
+
+public:
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief constructs a new message
+ *
+ * \param Addr - Target address
+ * \param nFBlock - Function Block ID
+ * \param nInst - Instance ID
+ * \param nFunc - Function ID
+ * \param nOpType - Operation
+ * \param nPayloadLen - length of payload in bytes
+ * \param Payload - Payload
+ * \param nTimeoutMs - Timeout for sending in Milliseconds
+ * \param MessageSentCB - Handler called, after message was sent
+ * \param UserContext - a class passed to the handler
+ */
+ /*----------------------------------------------------------*/
+ CMostMsgTx( CMsgAddr *Addr, uint32_t nFBlock, uint32_t nInst, uint32_t nFunc, uint8_t nOpType,
+ uint32_t nPayloadLen, const uint8_t *Payload, uint32_t nTimeoutMs, OnMessageSent_t MessageSentCB,
+ void *UserContext );
+
+
+ void MsgSent( bool bSuccess );
+
+
+
+
+ CMsgAddr *GetAddr();
+
+
+
+
+ void *GetUserContext();
+};
+
+
+#endif //MOSTMSGTX_H
diff --git a/Src/IP/MsgAddr.cpp b/Src/IP/MsgAddr.cpp
new file mode 100644
index 0000000..6c80222
--- /dev/null
+++ b/Src/IP/MsgAddr.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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 <string.h>
+#include <stdio.h>
+#include "MsgAddr.h"
+#include "Console.h"
+
+CMsgAddr::CMsgAddr( const char *Addr, uint32_t nPort ) : m_nRefCount( 1 ), m_nPort( nPort ),
+ m_protocol( IpcUdp_V2_0 )
+{
+ if( NULL != Addr )
+ strncpy( m_IpAddr, Addr, sizeof( m_IpAddr ) );
+}
+
+CMsgAddr::CMsgAddr( const char *Addr, uint32_t nPort, IpcProtocol_t protocol ) : m_nRefCount( 1 ), m_nPort( nPort ),
+ m_protocol( protocol )
+{
+ if( NULL != Addr )
+ strncpy( m_IpAddr, Addr, sizeof( m_IpAddr ) );
+}
+
+CMsgAddr::~CMsgAddr()
+{
+}
+
+void CMsgAddr::AddReference()
+{
+ ++m_nRefCount;
+}
+
+void CMsgAddr::RemoveReference()
+{
+ if( 0 >= --m_nRefCount )
+ delete this;
+}
+
+char *CMsgAddr::GetInetAddress()
+{
+ return ( char * )m_IpAddr;
+}
+
+uint32_t CMsgAddr::GetPort()
+{
+ return m_nPort;
+}
+
+IpcProtocol_t CMsgAddr::GetProtocol()
+{
+ return m_protocol;
+}
diff --git a/Src/IP/MsgAddr.h b/Src/IP/MsgAddr.h
new file mode 100644
index 0000000..9a3fa80
--- /dev/null
+++ b/Src/IP/MsgAddr.h
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CMsgAddr class.
+ */
+/*----------------------------------------------------------*/
+#ifndef MSGADDR_H
+#define MSGADDR_H
+#include <stdint.h>
+
+typedef enum
+{
+ IpcUdp_V2_0 = 1,
+ IpcTcp_V2_0 = 2
+} IpcProtocol_t;
+
+/*----------------------------------------------------------*/
+/*! \brief Storage class, which holds IP address, IP port and MAC address.
+*/
+/*----------------------------------------------------------*/
+class CMsgAddr
+{
+private:
+ int32_t m_nRefCount;
+ char m_IpAddr[32];
+ uint32_t m_nPort;
+ IpcProtocol_t m_protocol;
+
+public:
+ CMsgAddr( const char *Addr, uint32_t nPort );
+ CMsgAddr( const char *Addr, uint32_t nPort, IpcProtocol_t protocol );
+ ~CMsgAddr();
+
+ /*----------------------------------------------------------*/
+ /*! \brief Increments the reference counter
+ */
+ /*----------------------------------------------------------*/
+ void AddReference();
+
+ /*----------------------------------------------------------*/
+ /*! \brief Decrements the reference counter, if the value reaches 0, this object destroys it self.
+ */
+ /*----------------------------------------------------------*/
+ void RemoveReference();
+
+ char *GetInetAddress();
+ uint32_t GetPort();
+ IpcProtocol_t GetProtocol();
+};
+
+#endif //MSGADDR_H
diff --git a/Src/IP/MsgFilter.cpp b/Src/IP/MsgFilter.cpp
new file mode 100644
index 0000000..f9684f4
--- /dev/null
+++ b/Src/IP/MsgFilter.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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 "Console.h"
+#include "MsgFilter.h"
+
+CMsgFilter::CMsgFilter( uint32_t nFBlock, uint32_t nFunc, uint8_t nOpType, OnMsg_t MsgHandler )
+{
+ m_nFBlock = nFBlock;
+ m_nFunc = nFunc;
+ m_nOpType = nOpType;
+ m_MsgHandler = MsgHandler;
+}
+
+void CMsgFilter::Filter( CMsgAddr *Addr, CMostMsg *Msg )
+{
+ if( NULL == Addr || NULL == Msg )
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"CMsgFilter::Filter was called with invalid parameters"RESETCOLOR"\n" );
+ return;
+ }
+ if( NULL != m_MsgHandler )
+ if( Msg->GetFBlock() == m_nFBlock && Msg->GetFunc() == m_nFunc
+ && Msg->GetOpType() == m_nOpType )
+ m_MsgHandler( Addr, Msg );
+}
diff --git a/Src/IP/MsgFilter.h b/Src/IP/MsgFilter.h
new file mode 100644
index 0000000..72ef45f
--- /dev/null
+++ b/Src/IP/MsgFilter.h
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CMsgFilter class.
+ */
+/*----------------------------------------------------------*/
+#ifndef MSGFILTER_H
+#define MSGFILTER_H
+
+#include <stdint.h>
+#include "MsgAddr.h"
+#include "MostMsg.h"
+
+typedef void ( *OnMsg_t )( CMsgAddr *Addr, CMostMsg *Msg );
+
+/*----------------------------------------------------------*/
+/*!
+ * \brief filters messages and dispatches result to a
+ * handler
+ */
+
+/*----------------------------------------------------------*/
+class CMsgFilter
+{
+ uint32_t m_nFBlock;
+ uint32_t m_nFunc;
+ uint8_t m_nOpType;
+ OnMsg_t m_MsgHandler;
+
+public:
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief construct a message filter
+ */
+ /*----------------------------------------------------------*/
+ CMsgFilter( uint32_t nFBlock, uint32_t nFunc, uint8_t nOpType, OnMsg_t MsgHandler );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief filter an incoming message
+ */
+ /*----------------------------------------------------------*/
+ void Filter( CMsgAddr *Addr, CMostMsg *Msg );
+};
+
+
+#endif //MSGFILTER_H
diff --git a/Src/MacAddr.cpp b/Src/MacAddr.cpp
new file mode 100644
index 0000000..8b1f699
--- /dev/null
+++ b/Src/MacAddr.cpp
@@ -0,0 +1,165 @@
+/*
+ * 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 <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include "MacAddr.h"
+
+
+
+
+CMacAddr::CMacAddr()
+{
+ memset( m_Mac, 0, sizeof( m_Mac ) );
+}
+
+
+
+CMacAddr::CMacAddr( const uint8_t *pAddress )
+{
+ if( NULL == pAddress )
+ {
+ memset( m_Mac, 0, sizeof( m_Mac ) );
+ return;
+ }
+ m_Mac[0] = pAddress[0];
+ m_Mac[1] = pAddress[1];
+ m_Mac[2] = pAddress[2];
+ m_Mac[3] = pAddress[3];
+ m_Mac[4] = pAddress[4];
+ m_Mac[5] = pAddress[5];
+}
+
+
+
+CMacAddr::CMacAddr( uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5 )
+{
+ m_Mac[0] = b0;
+ m_Mac[1] = b1;
+ m_Mac[2] = b2;
+ m_Mac[3] = b3;
+ m_Mac[4] = b4;
+ m_Mac[5] = b5;
+}
+
+
+
+CMacAddr::CMacAddr( CMacAddr *copySouce )
+{
+ if( NULL != copySouce )
+ {
+ memcpy( m_Mac, copySouce->m_Mac, sizeof( m_Mac ) );
+ }
+}
+
+
+const char *CMacAddr::ToString()
+{
+ snprintf( stringRep, sizeof( stringRep ), "%02X-%02X-%02X-%02X-%02X-%02X", m_Mac[0], m_Mac[1], m_Mac[2], m_Mac[3],
+ m_Mac[4], m_Mac[5] );
+ return stringRep;
+}
+
+
+const uint8_t *CMacAddr::GetBytes()
+{
+ return m_Mac;
+}
+
+
+
+void CMacAddr::CopyValuesFromByteArray( const uint8_t *pAddress )
+{
+ if( NULL == pAddress )
+ return;
+ m_Mac[0] = pAddress[0];
+ m_Mac[1] = pAddress[1];
+ m_Mac[2] = pAddress[2];
+ m_Mac[3] = pAddress[3];
+ m_Mac[4] = pAddress[4];
+ m_Mac[5] = pAddress[5];
+}
+
+
+
+void CMacAddr::CopyValuesFromString( const char *pAddress )
+{
+ if( NULL == pAddress )
+ return;
+ uint8_t pos = 0;
+ char buf[64];
+ char *tok;
+ char *tkPtr;
+ strncpy( buf, pAddress, sizeof( buf ) );
+ tok = strtok_r( buf, "-: ,.", &tkPtr );
+ while( NULL != tok && pos < sizeof( m_Mac ) )
+ {
+ uint32_t val;
+ sscanf( tok, "%X", &val );
+ m_Mac[pos++] = val;
+ tok = strtok_r( NULL, "-: ,.", &tkPtr );
+ }
+}
+
+
+
+CMacAddr::CMacAddr( uint8_t deviceInstance, uint16_t nodeAddress )
+{
+ if( 0x01 == nodeAddress )
+ nodeAddress = 0x100;
+
+ m_Mac[0] =
+ 0x02; //Local defined MAC address flag. Has to be unique in the local network.
+ m_Mac[1] = 0;
+ m_Mac[2] = deviceInstance;
+ m_Mac[3] = ( uint8_t )( nodeAddress & 0xFF );
+ m_Mac[4] = ( uint8_t )( ( nodeAddress >> 8 ) & 0xFF );
+ m_Mac[5] = ( uint8_t )( nodeAddress & 0xFF );
+}
+
+
+
+
+CMacAddr::~CMacAddr()
+{
+}
+
+
+
+
+
+
+
+uint8_t CMacAddr::operator[]( int nByte )
+{
+ return ( 5 < nByte ) ? 0 : m_Mac[nByte];
+}
+
+
+
+
+bool CMacAddr::operator==( CMacAddr const &rhs )
+{
+ return ( 0 == memcmp( m_Mac, rhs.m_Mac, sizeof( m_Mac ) ) );
+}
diff --git a/Src/MacAddr.h b/Src/MacAddr.h
new file mode 100644
index 0000000..0ff9858
--- /dev/null
+++ b/Src/MacAddr.h
@@ -0,0 +1,153 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CMacAddr class.
+ */
+/*----------------------------------------------------------*/
+#ifndef _MACADDR_H_
+#define _MACADDR_H_
+
+#include <stdint.h>
+
+/*----------------------------------------------------------*/
+/*! \brief Class to deal with MAC addresses.
+ */
+/*----------------------------------------------------------*/
+class CMacAddr
+{
+private:
+ uint8_t m_Mac[6];
+ char stringRep[32];
+
+public:
+ /*----------------------------------------------------------*/
+ /*! \brief Default constructor of CMacAddr.
+ */
+ /*----------------------------------------------------------*/
+ CMacAddr();
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Default destructor of CMacAddr.
+ */
+ /*----------------------------------------------------------*/
+ ~CMacAddr();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Constructor of CMacAddr, which uses the given bytes to initialize this class.
+ * \param pAddress - 6 Byte array containing the MAC address.
+ */
+ /*----------------------------------------------------------*/
+ CMacAddr( const uint8_t *pAddress );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Constructor of CMacAddr, which uses the given bytes to initialize this class.
+ * \param b0 - The 1st byte of the MAC address.
+ * \param b1 - The 2nd byte of the MAC address.
+ * \param b2 - The 3rd byte of the MAC address.
+ * \param b3 - The 4th byte of the MAC address.
+ * \param b4 - The 5th byte of the MAC address.
+ * \param b5 - The 6th byte of the MAC address.
+ */
+ /*----------------------------------------------------------*/
+ CMacAddr( uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5 );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Constructor of CMacAddr, which uses the given parameters to create a system wide unique MAC address.
+ * \param deviceIndex - The index of the physical device instance of the server device.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ */
+ /*----------------------------------------------------------*/
+ CMacAddr( uint8_t deviceInstance, uint16_t nodeAddress );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Copy-Constructor of CMacAddr, which creates a new instance out of the given object (deep copy).
+ * \param copySouce - The object, to copy.
+ */
+ /*----------------------------------------------------------*/
+ CMacAddr( CMacAddr *copySouce );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets a zero terminated string representation of this MAC address. The delimiter is '-'.
+ * \return A string representation of this MAC address.
+ */
+ /*----------------------------------------------------------*/
+ const char *ToString();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets a Byte array with the length of 6 containing the MAC address
+ * \return MAC address byte array.
+ */
+ /*----------------------------------------------------------*/
+ const uint8_t *GetBytes();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Copy the MAC address value from a given byte array.
+ * \param pAddress - 6 Byte array containing the MAC address.
+ */
+ /*----------------------------------------------------------*/
+ void CopyValuesFromByteArray( const uint8_t *pAddress );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Copy the MAC address value from a given string.
+ * \param pAddress - String containing the MAC address.
+ */
+ /*----------------------------------------------------------*/
+ void CopyValuesFromString( const char *pAddress );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Access the MAC address byte wise.
+ * \param nByte - offset of the byte array of the MAC address. Must be between 0 - 5.
+ * \return The byte value of the MAC address on the given byte offset.
+ */
+ /*----------------------------------------------------------*/
+ uint8_t operator[]( int nByte );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Compares the given CMacAddr instance with this one.
+ * \param rhs - The source CMacAddr instance, which then will be compared.
+ * \return true, if the value of the MAC address is equal. false, the value of the MAC address is different.
+ */
+ /*----------------------------------------------------------*/
+ bool operator==( CMacAddr const &rhs );
+};
+
+#endif
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)
+ }
+ }
+}
diff --git a/Src/Network/IndustrialStack.cpp b/Src/Network/IndustrialStack.cpp
new file mode 100644
index 0000000..e84ab22
--- /dev/null
+++ b/Src/Network/IndustrialStack.cpp
@@ -0,0 +1,275 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CIndustrialStack class.
+ */
+/*----------------------------------------------------------*/
+
+//#define CON_TRACE
+
+#define DISABLE_PARALLEL_MODE
+
+#include <assert.h>
+#include "IndustrialStack.h"
+
+CIndustrialStack::CIndustrialStack(uint8_t deviceApi, int controlRxHandle, int controlTxHandle)
+{
+ msnw = new CISNetServiceWrapper(deviceApi, controlRxHandle, controlTxHandle);
+ msnw->AddListener(this);
+ GetQueue(0x3C8); //Make sure that Broadcast queue is the first one
+}
+
+CIndustrialStack::~CIndustrialStack()
+{
+ delete msnw;
+ deviceQueues.RemoveAll(true);
+ intEventListeners.RemoveAll(false);
+}
+
+void CIndustrialStack::EnqueueElement(uint16_t nodeAddress, IISElement *element)
+{
+ CISDeviceQueue *dev = GetQueue(nodeAddress);
+ assert(NULL != dev);
+ element->AddReference();
+ dev->elements.PushBack(element);
+}
+
+void CIndustrialStack::ServiceStack(uint32_t time)
+{
+ for (uint32_t i = 0; i < deviceQueues.Size(); i++)
+ {
+ assert(NULL != deviceQueues[i]);
+ if (deviceQueues[i]->elements.Size() == 0)
+ continue;
+ IISElement *element = deviceQueues[i]->elements[0];
+ assert(NULL != element);
+ ISReturn_t state = element->Service(this, time);
+ if (state == ISReturn_NoChange)
+ continue;
+ deviceQueues[i]->elements.PopFront();
+ HandleStateChange(state, element);
+ element->RemoveReference();
+ msnw->ServiceMns();
+ }
+ msnw->ServiceMns();
+}
+
+bool CIndustrialStack::ElementsPending()
+{
+ for (uint32_t i = 0; i < deviceQueues.Size(); i++)
+ {
+ assert(NULL != deviceQueues[i]);
+ if (deviceQueues[i]->elements.Size() != 0)
+ return true;
+ }
+ return false;
+}
+
+bool CIndustrialStack::ElementsPending(uint16_t ingoreNodeAddress)
+{
+ for (uint32_t i = 0; i < deviceQueues.Size(); i++)
+ {
+ CISDeviceQueue *q = deviceQueues[i];
+ assert(NULL != q);
+ if (q->GetNodeAddress() == ingoreNodeAddress)
+ continue;
+ if (q->elements.Size() != 0)
+ return true;
+ }
+ return false;
+}
+
+void CIndustrialStack::ClearAllElements()
+{
+ for (uint32_t i = 0; i < deviceQueues.Size(); i++)
+ {
+ assert(NULL != deviceQueues[i]);
+ deviceQueues[i]->elements.RemoveAll(true);
+ }
+}
+
+bool CIndustrialStack::SendMostMessage(CISMostMsg *message)
+{
+ assert(NULL != msnw);
+ assert(NULL != message);
+ if (NULL == message)
+ return false;
+#ifdef CON_TRACE
+ ConsolePrintfStart(PRIO_HIGH, "IS TX, node:0x%X," \
+ " fblock:0x%X, func:0x%X, op:0x%X pl:0x[", message->TargetAddress,
+ message->FBlock, message->Func, message->OpType);
+ for (uint32_t i = 0; i < message->PayloadLen; i++)
+ ConsolePrintfContinue(" %02X", message->Payload[i]);
+ ConsolePrintfExit(" ]\n");
+#endif
+ bool success = msnw->SendMostMessage(message);
+ for (uint32_t i = 0; success && i < intEventListeners.Size(); i++)
+ {
+ intEventListeners[i]->OnMostMessage(this, message);
+ }
+ return success;
+}
+
+void CIndustrialStack::Unsynchronize()
+{
+ assert(NULL != msnw);
+ return msnw->Unsynchronize();
+}
+
+void CIndustrialStack::AddInternalEventListener(CSInternalEvent* callback)
+{
+ intEventListeners.PushBack(callback);
+}
+
+/*--------------------------
+ * Callback from MSN Wrapper
+ *--------------------------
+ */
+
+void CIndustrialStack::OnReceivedMostMessage(CISMostMsg *rcvMessage)
+{
+ assert(NULL != rcvMessage);
+ assert(rcvMessage->IsValid);
+#ifdef CON_TRACE
+ ConsolePrintfStart(PRIO_HIGH, "IS RX, node:0x%X," \
+ " fblock:0x%X, func:0x%X, op:0x%X pl:0x[", rcvMessage->SourceAddress,
+ rcvMessage->FBlock, rcvMessage->Func, rcvMessage->OpType);
+ for (uint32_t i = 0; i < rcvMessage->PayloadLen; i++)
+ ConsolePrintfContinue(" %02X", rcvMessage->Payload[i]);
+ ConsolePrintfExit(" ]\n");
+#endif
+ if (CISOpType_ERROR == rcvMessage->OpType
+ || CISOpType_ERRORACK == rcvMessage->OpType)
+ {
+ //Ignore Destroy Resource Errors
+ if (rcvMessage->Func != 0x800)
+ {
+ ConsolePrintfStart(PRIO_ERROR, RED"Received error message, node:0x%X," \
+ " fblock:0x%X, func:0x%X, op:0x%X pl:0x[", rcvMessage->SourceAddress,
+ rcvMessage->FBlock, rcvMessage->Func, rcvMessage->OpType);
+ for (uint32_t i = 0; i < rcvMessage->PayloadLen; i++)
+ ConsolePrintfContinue(" %02X", rcvMessage->Payload[i]);
+ ConsolePrintfExit(" ]"RESETCOLOR"\n");
+ }
+ }
+ for (uint32_t i = 0; i < deviceQueues.Size(); i++)
+ {
+ assert(NULL != deviceQueues[i]);
+ IISElement *element = deviceQueues[i]->elements[0];
+ if (NULL == element)
+ continue;
+ ISReturn_t state = element->OnMostMessage(this, rcvMessage);
+ if (state == ISReturn_NoChange)
+ continue;
+ deviceQueues[i]->elements.PopFront();
+ HandleStateChange(state, element);
+ element->RemoveReference();
+ }
+ for (uint32_t i = 0; i < intEventListeners.Size(); i++)
+ {
+ intEventListeners[i]->OnMostMessage(this, rcvMessage);
+ }
+}
+
+void CIndustrialStack::OnSyncStateChanged(bool isSynced)
+{
+ for (uint32_t i = 0; i < intEventListeners.Size(); i++)
+ {
+ assert(NULL != intEventListeners[i]);
+ intEventListeners[i]->OnSyncStateChanged(this, isSynced);
+ }
+}
+
+void CIndustrialStack::OnControlReadEnd()
+{
+ for (uint32_t i = 0; i < intEventListeners.Size(); i++)
+ {
+ assert(NULL != intEventListeners[i]);
+ intEventListeners[i]->OnControlReadEnd(this);
+ }
+}
+
+/*--------------------------
+ * Private helper functions:
+ *--------------------------
+ */
+
+#ifdef DISABLE_PARALLEL_MODE
+CISDeviceQueue *CIndustrialStack::GetQueue(uint16_t nodeAddress)
+{
+ CISDeviceQueue *dev = deviceQueues[0];
+ if (NULL == dev)
+ {
+ ConsolePrintf(PRIO_HIGH, GREEN"Creating new Device Queue"RESETCOLOR"\n");
+ dev = new CISDeviceQueue(0);
+ deviceQueues.PushBack(dev);
+ }
+ return dev;
+}
+#else
+CISDeviceQueue *CIndustrialStack::GetQueue(uint16_t nodeAddress)
+{
+ CISDeviceQueue *dev = NULL;
+ if (nodeAddress >= 0x400 && nodeAddress <= 0x4FF)
+ nodeAddress -= 0x300;
+ for (uint32_t i = 0; i < deviceQueues.Size(); i++)
+ {
+ if (deviceQueues[i]->GetNodeAddress() == nodeAddress)
+ {
+ dev = deviceQueues[i];
+ break;
+ }
+ }
+ if (NULL == dev)
+ {
+ ConsolePrintf(PRIO_HIGH, GREEN"Creating new Device Queue for"\
+ " node address:0x%02X"RESETCOLOR"\n", nodeAddress);
+ dev = new CISDeviceQueue(nodeAddress);
+ deviceQueues.PushBack(dev);
+ }
+ return dev;
+}
+#endif
+
+void CIndustrialStack::HandleStateChange(ISReturn_t state, IISElement * element)
+{
+ assert(NULL != element);
+ switch (state)
+ {
+ case ISReturn_Failure:
+ case ISReturn_Timeout:
+ ConsolePrintf(PRIO_ERROR, RED"Job '%s' %s"RESETCOLOR"\n",
+ element->ElementName, state == ISReturn_Failure ? "failed" : "timed out");
+ case ISReturn_Success:
+ if (NULL != element->Callback)
+ element->Callback->ElementProcessed(this, state, element);
+ break;
+ case ISReturn_NoChange:
+ //Nothing to do
+ break;
+ default:
+ assert(false);
+ }
+}
diff --git a/Src/Network/IndustrialStack.h b/Src/Network/IndustrialStack.h
new file mode 100644
index 0000000..fc42f66
--- /dev/null
+++ b/Src/Network/IndustrialStack.h
@@ -0,0 +1,238 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CIndustrialStack class (common part).
+ */
+/*----------------------------------------------------------*/
+
+#ifndef INDUSTRIAL_STACK_H
+#define INDUSTRIAL_STACK_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+#include "SafeVector.h"
+#include "IndustrialStack_Types.h"
+#include "IndustrialStack_MNS.h"
+#include "Console.h"
+
+class CIndustrialStack : IISNetServiceWrapperCB
+{
+private:
+ CISNetServiceWrapper *msnw;
+ CSafeVector<CISDeviceQueue *> deviceQueues;
+ CSafeVector<CSInternalEvent *> intEventListeners;
+ CISDeviceQueue *GetQueue(uint16_t deviceType);
+ void HandleStateChange(ISReturn_t state, IISElement * element);
+public:
+ CIndustrialStack(uint8_t deviceApi, int controlRxHandle, int controlTxHandle);
+ virtual ~CIndustrialStack();
+ void ServiceStack(uint32_t time);
+ void EnqueueElement(uint16_t nodeAddress, IISElement *element);
+ bool ElementsPending();
+ bool ElementsPending(uint16_t ingoreNodeAddress);
+ void ClearAllElements();
+ bool SendMostMessage(CISMostMsg *message);
+ void Unsynchronize();
+ void AddInternalEventListener(CSInternalEvent* callback);
+
+ /* Callback from IISNetServiceWrapperCB interface */
+ virtual void OnReceivedMostMessage(CISMostMsg *rcvMessage);
+ virtual void OnSyncStateChanged(bool isSynced);
+ virtual void OnControlReadEnd();
+};
+
+class CISWaitElement : public IISElement
+{
+protected:
+ uint32_t startTime;
+ uint32_t timeout;
+public:
+ CISWaitElement() : IISElement(), startTime(0), timeout(2000)
+ {
+ ElementName = "Wait Element";
+ }
+
+ void SetTimeout(uint32_t timeInMillis)
+ {
+ timeout = timeInMillis;
+ }
+
+ virtual ISReturn_t Service(CIndustrialStack *iStack, uint32_t time)
+ {
+ assert(NULL != iStack);
+ if (0 == startTime)
+ startTime = time;
+ else if ( ( time - startTime >= timeout ) )
+ return ISReturn_Success;
+ return ISReturn_NoChange;
+ }
+
+ virtual ISReturn_t OnMostMessage(CIndustrialStack *iStack, CISMostMsg *rcvMessage)
+ {
+ assert(NULL != iStack);
+ return ISReturn_NoChange;
+ }
+};
+
+class CISWaitForPendingElements : public CISWaitElement
+{
+private:
+ uint16_t ignoreNode;
+public:
+ CISWaitForPendingElements(uint16_t ingoreNodeAddress)
+ : CISWaitElement(), ignoreNode(ingoreNodeAddress)
+ {
+ }
+
+ virtual ISReturn_t Service(CIndustrialStack *iStack, uint32_t time)
+ {
+ assert(NULL != iStack);
+ if (!iStack->ElementsPending(ignoreNode))
+ return ISReturn_Success;
+ return (CISWaitElement::Service(iStack, time) == ISReturn_NoChange)
+ ? ISReturn_NoChange : ISReturn_Timeout;
+ }
+};
+
+class CISSendMostMsgElement : public CISWaitElement
+{
+private:
+ uint8_t retryCount;
+public:
+ CISMostMsg Request;
+ CISMostMsg Response;
+ bool WaitForResponse;
+ CISOpType_t WaitForResponseOpType;
+
+ CISSendMostMsgElement() : CISWaitElement(), retryCount(4),
+ WaitForResponse(false),
+ WaitForResponseOpType(CISOpType_INVALID)
+ {
+ timeout = 500;
+ }
+
+ virtual ISReturn_t Service(CIndustrialStack *iStack, uint32_t time)
+ {
+ assert(NULL != iStack);
+ if (0 == startTime)
+ {
+ CISWaitElement::Service(iStack, time);
+ if (Request.IsValid == false || Request.FBlock == 0xFFFFFFFF
+ || Request.Func == 0xFFFFFFFF || Request.Inst == 0xFFFFFFFF
+ || Request.OpType == CISOpType_INVALID)
+ {
+ ConsolePrintf(PRIO_ERROR,
+ RED"CISSendMostMsgElement %s invalid MOST message to be"\
+ " sent"RESETCOLOR"\n", ElementName);
+ return ISReturn_Failure;
+ }
+ bool success = iStack->SendMostMessage(&Request);
+ if (success && !WaitForResponse)
+ return ISReturn_Success;
+ return success ? ISReturn_NoChange : ISReturn_Failure;
+ }
+ ISReturn_t waitState = CISWaitElement::Service(iStack, time);
+ if (ISReturn_Success == waitState)
+ {
+ if (0 == --retryCount)
+ {
+ ConsolePrintf(PRIO_ERROR, RED"All High level retries failed for Request '%s',"\
+ " node 0x%X!"RESETCOLOR"\n",
+ ElementName, Request.TargetAddress);
+ return ISReturn_Timeout;
+ }
+ //Retry sending
+ ConsolePrintf(PRIO_HIGH, YELLOW"High level retry after timeout for Request '%s',"\
+ " node 0x%X"RESETCOLOR"\n",
+ ElementName, Request.TargetAddress);
+ startTime = time;
+ return (iStack->SendMostMessage(&Request)) ? ISReturn_NoChange : ISReturn_Failure;
+ }
+ return ISReturn_NoChange;
+ }
+
+ virtual ISReturn_t OnMostMessage(CIndustrialStack *iStack, CISMostMsg *rcvMessage)
+ {
+ if (!WaitForResponse)
+ return ISReturn_NoChange;
+ assert(NULL != iStack);
+ assert(NULL != rcvMessage);
+ assert(Request.IsValid);
+ assert(rcvMessage->IsValid);
+
+ uint32_t requestAddr = Request.TargetAddress;
+ uint32_t responseAddr = rcvMessage->SourceAddress;
+ if (requestAddr >= 0x400 && requestAddr <= 0x4FF )
+ requestAddr -= 0x300;
+ if (responseAddr >= 0x400 && responseAddr <= 0x4FF )
+ responseAddr -= 0x300;
+
+ if ( ( requestAddr < 0x300 || requestAddr > 0x3FF )
+ && ( responseAddr != requestAddr))
+ return ISReturn_NoChange;
+
+ if ( rcvMessage->FBlock == Request.FBlock
+ && rcvMessage->Func == Request.Func)
+ {
+ if (rcvMessage->OpType == WaitForResponseOpType)
+ {
+ Response.DeepCopy(rcvMessage);
+ return ISReturn_Success;
+ }
+ else if(0 == --retryCount)
+ {
+ Response.DeepCopy(rcvMessage);
+ return ISReturn_Failure;
+ }
+ //Retry sending
+ ConsolePrintf(PRIO_HIGH, YELLOW"High level retry after wrong result for Request '%s',"\
+ " node 0x%X"RESETCOLOR"\n",
+ ElementName, Request.TargetAddress);
+ return (iStack->SendMostMessage(&Request)) ? ISReturn_NoChange : ISReturn_Failure;
+ }
+ return ISReturn_NoChange;
+ }
+};
+
+class CSInternalEvent : public IISElement
+{
+public:
+ virtual ISReturn_t Service(CIndustrialStack *iStack, uint32_t time)
+ {
+ //Must not be called
+ return ISReturn_Failure;
+ }
+ virtual ISReturn_t OnMostMessage(CIndustrialStack *iStack, CISMostMsg *r)
+ {
+ //Must not be called
+ return ISReturn_Failure;
+ }
+ virtual void OnSyncStateChanged(CIndustrialStack *iStack, bool isSynced) {}
+ virtual void OnControlReadEnd(CIndustrialStack *iStack) {}
+};
+
+#endif //INDUSTRIAL_STACK_H
diff --git a/Src/Network/IndustrialStack_ApiGeneric.h b/Src/Network/IndustrialStack_ApiGeneric.h
new file mode 100644
index 0000000..730f157
--- /dev/null
+++ b/Src/Network/IndustrialStack_ApiGeneric.h
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CIndustrialStack class (Generic commands).
+ */
+/*----------------------------------------------------------*/
+
+#ifndef INDUSTRIAL_STACK_API_GENERIC_H
+#define INDUSTRIAL_STACK_API_GENERIC_H
+
+#include "IndustrialStack.h"
+#include "Network.h"
+#include "Types.h"
+
+class CGeneric_SendConfigOk : public CISSendMostMsgElement
+{
+public:
+ CGeneric_SendConfigOk(bool isOkay)
+ {
+ ElementName = "CGeneric_SendConfigOk";
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = 0x3C8;
+ Request.FBlock = 0x2;
+ Request.Func = 0xA00;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STATUS;
+ Request.PayloadLen = 1;
+ Request.Payload[0] = isOkay;
+ }
+};
+
+class CGeneric_GetMacAddress : public CISSendMostMsgElement
+{
+public:
+ CGeneric_GetMacAddress(uint16_t nodeAddress)
+ {
+ ElementName = "CGeneric_GetMacAddress";
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x1;
+ Request.Func = 0x013;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_GET;
+ Request.PayloadLen = 0;
+ }
+};
+
+class CGeneric_GetGroupAddress : public CISSendMostMsgElement
+{
+public:
+ CGeneric_GetGroupAddress(uint16_t nodeAddress)
+ {
+ ElementName = "CGeneric_GetGroupAddress";
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x1;
+ Request.Func = 0x004;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_GET;
+ Request.PayloadLen = 0;
+ }
+};
+
+class CGeneric_SendMostMessage : public CISSendMostMsgElement
+{
+public:
+ CGeneric_SendMostMessage(const uint8_t *pPayload, uint32_t payloadLength,
+ uint16_t nodeAddress, uint8_t fblockId, uint8_t instanceId,
+ uint16_t functionId, uint8_t opTypeRequest, uint8_t opTypeResponse)
+ {
+ if (payloadLength > sizeof(Request.Payload))
+ {
+ ConsolePrintf(PRIO_ERROR, RED"CGeneric_SendMostMessage was called"\
+ " with to big payload size"RESETCOLOR"\n");
+ payloadLength = sizeof(Request.Payload);
+ }
+ ElementName = "CGeneric_SendMostMessage";
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = fblockId;
+ Request.Func = functionId;
+ Request.Inst = instanceId;
+ Request.OpType = (CISOpType_t)opTypeRequest;
+ Request.PayloadLen = payloadLength;
+ if (0 != payloadLength)
+ memcpy(Request.Payload, pPayload, payloadLength);
+ if( 0xFF != opTypeResponse )
+ {
+ WaitForResponse = true;
+ WaitForResponseOpType = (CISOpType_t)opTypeResponse;
+ }
+ }
+};
+
+#endif //INDUSTRIAL_STACK_API_GENERIC_H
diff --git a/Src/Network/IndustrialStack_ApiV1.h b/Src/Network/IndustrialStack_ApiV1.h
new file mode 100644
index 0000000..1c7f45a
--- /dev/null
+++ b/Src/Network/IndustrialStack_ApiV1.h
@@ -0,0 +1,712 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CIndustrialStack class (API V1 commands).
+ */
+/*----------------------------------------------------------*/
+
+#ifndef INDUSTRIAL_STACK_API_V1_H
+#define INDUSTRIAL_STACK_API_V1_H
+
+#define ISO_PACKET_SIZE 188
+
+#include "IndustrialStack.h"
+#include "Network.h"
+#include "Types.h"
+
+class CV1_OnMostRx : public CSInternalEvent
+{
+private:
+ CNetworkDevice *device;
+public:
+ CV1_OnMostRx(CNetworkDevice *d) : device(d)
+ {
+ }
+
+ virtual ISReturn_t OnMostMessage(CIndustrialStack *iStack, CISMostMsg *r)
+ {
+ assert(NULL != device);
+ assert(r->IsValid);
+ if (0x0 == r->FBlock) //INIC Block
+ {
+ switch (r->Func)
+ {
+ case 0x30E: //Change EUI48
+ if (CISOpType_STATUS == r->OpType && r->PayloadLen >= 6)
+ {
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnMostMacAddress(device, true,
+ r->SourceAddress, r->Payload[0], r->Payload[1],
+ r->Payload[2], r->Payload[3], r->Payload[4], r->Payload[5]);
+ }
+ else if (CISOpType_ERROR == r->OpType)
+ {
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnMostMacAddress(device, false,
+ r->SourceAddress, 0,0,0,0,0,0);
+ }
+ break;
+ }
+ }
+ return ISReturn_NoChange;
+ }
+
+ virtual void OnControlReadEnd(CIndustrialStack *iStack)
+ {
+ assert(NULL != device);
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnControlChannelReadEnd(device);
+ }
+};
+
+class CV1_ChangeEUI48 : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+public:
+ CV1_ChangeEUI48(CNetworkDevice *d, uint16_t nodeAddress,
+ uint8_t macAddress1, uint8_t macAddress2, uint8_t macAddress3,
+ uint8_t macAddress4, uint8_t macAddress5, uint8_t macAddress6,
+ bool persistent) : device(d)
+ {
+ ElementName = "CV1_ChangeEUI48";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x30E;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 7;
+ Request.Payload[0] = macAddress1;
+ Request.Payload[1] = macAddress2;
+ Request.Payload[2] = macAddress3;
+ Request.Payload[3] = macAddress4;
+ Request.Payload[4] = macAddress5;
+ Request.Payload[5] = macAddress6;
+ Request.Payload[6] = persistent;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ assert(this == element);
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 6;
+ if (success)
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnMostMacAddress(device, true,
+ Request.TargetAddress, Response.Payload[0],Response.Payload[1],
+ Response.Payload[2], Response.Payload[3], Response.Payload[4],
+ Response.Payload[5]);
+ else
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnMostMacAddress(device, false,
+ Request.TargetAddress, 0, 0, 0, 0, 0, 0);
+ }
+};
+
+class CV1_NetworkStartup : public CISWaitElement
+{
+private:
+ CNetworkDevice *device;
+public:
+ CV1_NetworkStartup(CNetworkDevice *d, bool isTimingMaster, uint16_t packetBW) : device(d)
+ {
+ ElementName = "CV1_NetworkStartup is not implemented!";
+ timeout = 1;
+ }
+};
+
+class CV1_NetworkShutdown : public CISWaitElement
+{
+private:
+ CNetworkDevice *device;
+public:
+ CV1_NetworkShutdown(CNetworkDevice *d) : device(d)
+ {
+ ElementName = "CV1_NetworkShutdown is not implemented!";
+ timeout = 1;
+ }
+};
+
+class CV1_TsiPortCreate : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+public:
+ CV1_TsiPortCreate(CNetworkDevice *d, uint16_t nodeAddress, V1TsiPortInstance_t tsiPort, V1TsiPortMode tsiMode) : device(d)
+ {
+ ElementName = "CV2_TsiPortCreate";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x400;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 2;
+ Request.Payload[0] = tsiPort;
+ Request.Payload[1] = tsiMode;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnOpenTsiV1(device, (ISReturn_Success == result), Request.TargetAddress);
+ }
+};
+
+class CV1_TsiSocketCreate : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ V1TsiPortInstance_t tsiPort;
+ EPDataType_t epType;
+ EPDirection_t epDir;
+ uint16_t blockWidthTsi;
+ uint32_t tag;
+public:
+ CV1_TsiSocketCreate(CNetworkDevice *d, uint16_t nodeAddress, V1TsiPortInstance_t tp,
+ EPDataType_t ept, EPDirection_t epd, uint16_t bw, uint32_t t) :
+ device(d), tsiPort(tp), epType(ept), epDir(epd), blockWidthTsi(bw), tag(t)
+ {
+ if ( EP_Isochron != epType )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"CV1_TsiSocketCreate: Unsupported Data type"RESETCOLOR"\n" );
+ return;
+ }
+ ElementName = "CV1_TsiSocketCreate";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x403;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 7;
+ Request.Payload[0] = tsiPort;
+ Request.Payload[1] = epDir;
+ Request.Payload[2] = epType;
+ Request.Payload[3] = blockWidthTsi / 256;
+ Request.Payload[4] = blockWidthTsi % 256;
+ Request.Payload[5] = ISO_PACKET_SIZE / 256;
+ Request.Payload[6] = ISO_PACKET_SIZE % 256;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ uint8_t tsiPortHandle = 0xFF;
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 1;
+ if (success)
+ tsiPortHandle = Response.Payload[0];
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnCreateTsiSocketV1(device, success, Request.TargetAddress, tsiPort,
+ epType, epDir, blockWidthTsi, tsiPortHandle, tag);
+ }
+};
+
+class CV1_MlbPortCreate : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+public:
+ CV1_MlbPortCreate(CNetworkDevice *d, uint16_t nodeAddress, MlbPortSpeed_t mlbSpeed) : device(d)
+ {
+ ElementName = "CV2_MlbPortCreate";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x400;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 4;
+ Request.Payload[0] = 0x00; //SCM_PORT_ID_MEDIALB;
+ Request.Payload[1] = 0xFF;
+ Request.Payload[2] = 0x00; //SCM_PORT_CFG_MLB_MODE_CTL;
+ Request.Payload[3] = mlbSpeed;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnOpenMlbV1(device, (ISReturn_Success == result), Request.TargetAddress);
+ }
+};
+
+class CV1_MlbSocketCreate : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ EPDataType_t epType;
+ EPDirection_t epDir;
+ uint16_t mlbChannelAddress;
+ uint16_t blockWidthMlb;
+ uint32_t tag;
+public:
+ CV1_MlbSocketCreate(CNetworkDevice *d, uint16_t nodeAddress, EPDataType_t ept, EPDirection_t epd,
+ uint16_t mlb, uint16_t bw, uint32_t t) : device(d), epType(ept), epDir(epd),
+ mlbChannelAddress(mlb), blockWidthMlb(bw), tag(t)
+ {
+ ElementName = "CV1_MlbSocketCreate";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x403;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 7;
+ Request.Payload[0] = 0x00; //SCM_PORT_ID_MEDIALB
+ Request.Payload[1] = epDir;
+ Request.Payload[2] = epType;
+ Request.Payload[3] = blockWidthMlb / 256;
+ Request.Payload[4] = blockWidthMlb % 256;
+ Request.Payload[5] = mlbChannelAddress / 256;
+ Request.Payload[6] = mlbChannelAddress % 256;
+ if ( EP_Isochron == epType )
+ {
+ Request.PayloadLen = 10;
+ Request.Payload[7] = ISO_PACKET_SIZE / 256;
+ Request.Payload[8] = ISO_PACKET_SIZE % 256;
+ Request.Payload[9] = 0x1; //SCM_FLOW_CONTROL_ON
+ }
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ uint8_t mlbPortHandle = 0xFF;
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 1;
+ if (success)
+ mlbPortHandle = Response.Payload[0];
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnCreateMlbSocketV1(device, success, Request.TargetAddress, epType,
+ epDir, blockWidthMlb, mlbChannelAddress, mlbPortHandle, tag);
+ }
+};
+
+class CV1_SplittedMlbSocketCreate : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ EPDataType_t epType;
+ EPDirection_t epDir;
+ uint16_t mlbChannelAddress;
+ uint16_t blockWidthMlb;
+ uint16_t splittedOffset;
+ uint16_t blockWidthCombined;
+ uint32_t tag;
+public:
+ CV1_SplittedMlbSocketCreate(CNetworkDevice *d, uint16_t nodeAddress,
+ EPDataType_t ept, EPDirection_t epd, uint16_t mlb, uint16_t bw,
+ uint16_t so, uint16_t bwc, uint32_t t)
+ : device(d), epType(ept), epDir(epd), mlbChannelAddress(mlb),
+ blockWidthMlb(bw), splittedOffset(so), blockWidthCombined(bwc), tag(t)
+ {
+ ElementName = "CV1_SplittedMlbSocketCreate";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x403;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 9;
+ Request.Payload[0] = 0x00; //SCM_PORT_ID_MEDIALB
+ Request.Payload[1] = epDir;
+ Request.Payload[2] = epType;
+ Request.Payload[3] = blockWidthMlb / 256;
+ Request.Payload[4] = blockWidthMlb % 256;
+ Request.Payload[5] = mlbChannelAddress / 256;
+ Request.Payload[6] = mlbChannelAddress % 256;
+ Request.Payload[7] = ( uint8_t )( splittedOffset & 0xFF );
+ Request.Payload[8] = ( uint8_t )( blockWidthCombined & 0xFF );
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ uint8_t mlbPortHandle = 0xFF;
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 1;
+ if (success)
+ mlbPortHandle = Response.Payload[0];
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnCreateMlbSocketV1(device, success, Request.TargetAddress, epType,
+ epDir, blockWidthMlb, mlbChannelAddress, mlbPortHandle, tag);
+ }
+};
+
+class CV1_MostSocketCreate : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ EPDataType_t epType;
+ EPDirection_t epDir;
+ uint16_t connectionLabel;
+ uint16_t blockWidthMost;
+ uint32_t tag;
+public:
+ CV1_MostSocketCreate(CNetworkDevice *d, uint16_t nodeAddress, EPDataType_t ept, EPDirection_t epd,
+ uint16_t cl, uint16_t bw, uint32_t t) : device(d), epType(ept), epDir(epd),
+ connectionLabel(cl), blockWidthMost(bw), tag(t)
+ {
+ ElementName = "CV1_MostSocketCreate";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x403;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.Payload[0] = 0x02; //SCM_PORT_ID_MOST
+ Request.Payload[1] = epDir;
+ Request.Payload[2] = epType;
+ Request.Payload[3] = blockWidthMost / 256;
+ Request.Payload[4] = blockWidthMost % 256;
+ switch( epType )
+ {
+ case EP_Isochron:
+ Request.Payload[5] = ISO_PACKET_SIZE / 256;
+ Request.Payload[6] = ISO_PACKET_SIZE % 256;
+ if( SCM_IN == epDir )
+ {
+ Request.PayloadLen = 10;
+ Request.Payload[7] = 0x1; //SCM_PA_CL
+ Request.Payload[8] = connectionLabel / 256;
+ Request.Payload[9] = connectionLabel % 256;
+ }
+ else
+ {
+ Request.PayloadLen = 8;
+ Request.Payload[7] = 0x0; //SCM_NOT_PA
+ }
+ break;
+ case EP_Synchron:
+ if( SCM_IN == epDir )
+ {
+ Request.PayloadLen = 8;
+ Request.Payload[5] = 0x1; //SCM_PA_CL
+ Request.Payload[6] = connectionLabel / 256;
+ Request.Payload[7] = connectionLabel % 256;
+ }
+ else
+ {
+ Request.PayloadLen = 6;
+ Request.Payload[5] = 0x0; //SCM_NOT_PA
+ }
+ break;
+ default:
+ timeout = 1;
+ ConsolePrintf( PRIO_ERROR, RED"CreateMostSocket: Unsupported Data type"RESETCOLOR"\n" );
+ return;
+ }
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ uint8_t usbSocketHandle = 0xFF;
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 1;
+ if (success)
+ usbSocketHandle = Response.Payload[0];
+ if( success && SCM_OUT == epDir && Response.PayloadLen >= 4)
+ connectionLabel = ( Response.Payload[2] << 8) | Response.Payload[3];
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnCreateMostSocketV1(device, success, Request.TargetAddress, epType,
+ epDir, blockWidthMost, connectionLabel, usbSocketHandle, tag);
+ }
+};
+
+class CV1_ConnectSockets : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ uint16_t nodeAddress;
+ EPDataType_t epType;
+ uint16_t inHandle;
+ uint16_t outHandle;
+ uint32_t tag;
+public:
+ CV1_ConnectSockets(CNetworkDevice *d, uint16_t nodeAddress, uint16_t iH,
+ uint16_t oH, uint32_t t) : device(d), inHandle(iH), outHandle(oH), tag(t)
+ {
+ ElementName = "CV1_ConnectSockets";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x405;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 2;
+ Request.Payload[0] = inHandle;
+ Request.Payload[1] = outHandle;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ uint8_t conHandle = 0xFF;
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 1;
+ if (success)
+ conHandle = Response.Payload[0];
+
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnConnectSocketsV1(device, success,
+ Request.TargetAddress, inHandle, outHandle, conHandle, tag);
+ }
+};
+
+class CV1_DestroySocket : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ uint8_t handle;
+ uint32_t tag;
+public:
+ CV1_DestroySocket(CNetworkDevice *d, int16_t nodeAddress, uint8_t h,
+ uint32_t t) : device(d), handle(h), tag(t)
+ {
+ ElementName = "CV1_DestroySocket";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x404;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 1;
+ Request.Payload[0] = handle;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnDestroySocketV1(device, (ISReturn_Success == result),
+ Request.TargetAddress, handle, tag);
+ }
+};
+
+class CV1_DisconnectSockets : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ uint8_t handle;
+ uint32_t tag;
+public:
+ CV1_DisconnectSockets(CNetworkDevice *d, int16_t nodeAddress, uint8_t h,
+ uint32_t t) : device(d), handle(h), tag(t)
+ {
+ ElementName = "CV1_DisconnectSockets";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x406;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 1;
+ Request.Payload[0] = handle;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnDisconnectSocketsV1(device, (ISReturn_Success == result),
+ Request.TargetAddress, handle, tag);
+ }
+};
+
+class CV1_StreamPortOpen : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ V1I2SPortClkDriveMode_t portMode;
+ V1I2SStreamingPortMode_t streamPortMode;
+ V1I2SStreamingDataFormat_t format;
+ uint32_t tag;
+public:
+ CV1_StreamPortOpen(CNetworkDevice *d, int16_t nodeAddress,
+ V1I2SPortClkDriveMode_t pm, V1I2SStreamingPortMode_t spm,
+ V1I2SStreamingDataFormat_t f, uint32_t t) : device(d), portMode(pm),
+ streamPortMode(spm), format(f), tag(t)
+ {
+ ElementName = "CV1_StreamPortOpen";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x400;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 4;
+ Request.Payload[0] = 0x03; //Streaming Port
+ Request.Payload[1] = portMode;
+ Request.Payload[2] = streamPortMode;
+ Request.Payload[3] = format;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnOpenI2SPortV1(device, (ISReturn_Success == result),
+ Request.TargetAddress, portMode, format, tag);
+ }
+};
+
+class CV1_StreamSocketCreate : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ EPDirection_t epDir;
+ uint16_t blockWidthI2S;
+ V1I2SPin_t pin;
+ uint32_t tag;
+public:
+ CV1_StreamSocketCreate(CNetworkDevice *d, uint16_t nodeAddress, EPDirection_t epd,
+ uint16_t bw, V1I2SPin_t p, uint32_t t) : device(d), epDir(epd),
+ blockWidthI2S(bw), pin(p), tag(t)
+ {
+ ElementName = "CV1_StreamSocketCreate";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x403;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 6;
+ Request.Payload[0] = 0x03; //Streaming Port
+ Request.Payload[1] = epDir;
+ Request.Payload[2] = 0x0; //SyncData
+ Request.Payload[3] = blockWidthI2S / 256;
+ Request.Payload[4] = blockWidthI2S % 256;
+ Request.Payload[5] = (uint8_t)pin;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ uint8_t i2sSocketHandle = 0xFF;
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 1;
+ if (success)
+ i2sSocketHandle = Response.Payload[0];
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnCreateI2SSocketV1(device, success,
+ Request.TargetAddress, epDir, blockWidthI2S, pin, i2sSocketHandle, tag);
+ }
+};
+
+class CV1_SplittedStreamSocketCreate : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ EPDirection_t epDir;
+ uint16_t blockWidthI2S;
+ V1I2SPin_t pin;
+ uint32_t tag;
+public:
+ CV1_SplittedStreamSocketCreate(CNetworkDevice *d, uint16_t nodeAddress, EPDirection_t epd,
+ uint16_t bw, uint16_t splittedOffset, uint16_t blockWidthCombined, V1I2SPin_t p,
+ uint32_t t) : device(d), epDir(epd), blockWidthI2S(bw), pin(p), tag(t)
+ {
+ ElementName = "CV1_SplittedStreamSocketCreate";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x403;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 7;
+ Request.Payload[0] = 0x03; //Streaming Port
+ Request.Payload[1] = epDir;
+ Request.Payload[2] = 0x0; //SyncData
+ Request.Payload[3] = blockWidthI2S / 256;
+ Request.Payload[4] = blockWidthI2S % 256;
+ Request.Payload[5] = (uint8_t)pin;
+ Request.Payload[6] = ( uint8_t )( splittedOffset & 0xFF );
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ uint8_t i2sSocketHandle = 0xFF;
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 1;
+ if (success)
+ i2sSocketHandle = Response.Payload[0];
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnCreateI2SSocketV1(device, success,
+ Request.TargetAddress, epDir, blockWidthI2S, pin, i2sSocketHandle, tag);
+ }
+};
+
+#endif //INDUSTRIAL_STACK_API_V1_H \ No newline at end of file
diff --git a/Src/Network/IndustrialStack_ApiV3.h b/Src/Network/IndustrialStack_ApiV3.h
new file mode 100644
index 0000000..7e37789
--- /dev/null
+++ b/Src/Network/IndustrialStack_ApiV3.h
@@ -0,0 +1,1123 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CIndustrialStack class (API V3 commands).
+ */
+/*----------------------------------------------------------*/
+
+#ifndef INDUSTRIAL_STACK_API_V3_H
+#define INDUSTRIAL_STACK_API_V3_H
+
+#include "IndustrialStack.h"
+#include "Network.h"
+#include "Types.h"
+
+class CV3_OnMostRx : public CSInternalEvent
+{
+private:
+ CNetworkDevice *device;
+public:
+ CV3_OnMostRx(CNetworkDevice *d) : device(d)
+ {
+ }
+
+ virtual ISReturn_t OnMostMessage(CIndustrialStack *iStack, CISMostMsg *r)
+ {
+ assert(NULL != device);
+ assert(r->IsValid);
+ if (0x0 == r->FBlock) //INIC Block
+ {
+ switch (r->Func)
+ {
+ case 0x520: //MOST Network Status
+ if (CISOpType_STATUS == r->OpType && r->PayloadLen == 11)
+ {
+ bool mpValChanged = ( 0 != ( r->Payload[1] & 0x1 ) ); //This is a 16 Bit value!!
+ bool systemNotOk = false; //Not transmitted any longer
+ bool mostAvailable = ( 0 != ( r->Payload[2] & 0x1 ) );
+ uint8_t availableSubState = r->Payload[3];
+ uint8_t availableTransition = r->Payload[4];
+ uint16_t nodeAddress = r->Payload[5] << 8
+ | r->Payload[6];
+ uint8_t nodePos = ( r->Payload[7] & 0x3F );
+ uint8_t maxPos = ( r->Payload[8] );
+ uint16_t packetBW = r->Payload[9] << 8
+ | r->Payload[10];
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnNetworkState(device,
+ mpValChanged, systemNotOk, mostAvailable, availableSubState,
+ availableTransition, nodeAddress, nodePos, maxPos, packetBW);
+ }
+ break;
+ case 0x524: //MOST Network Startup
+ if (CISOpType_STATUS == r->OpType)
+ {
+ if (r->Payload[0] == 0x20 && r->Payload[1] == 0x04 && r->Payload[2] == 0x40)
+ return ISReturn_NoChange; //Startup was called, but we already have locked network, so ignore this error
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnNetworkStartupV3(device, (CISOpType_STATUS == r->OpType));
+ }
+ break;
+ case 0x527: //RBD Result
+ if (CISOpType_STATUS == r->OpType && r->PayloadLen == 5)
+ {
+ uint8_t result = r->Payload[0];
+ uint8_t position = r->Payload[1];
+ uint8_t status = r->Payload[2];
+ uint16_t id = r->Payload[3] << 8
+ | r->Payload[4];
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnRbdResultV3(device, r->SourceAddress,
+ result, position, status, id);
+ }
+ break;
+ }
+ }
+ else if (0x1 == r->FBlock) //NetBlock FBlock
+ {
+ switch (r->Func)
+ {
+ case 0x004: //GroupAddress Changed
+ if (CISOpType_STATUS == r->OpType && r->PayloadLen >= 2)
+ {
+ uint16_t groupAddress = r->Payload[0] << 8
+ | r->Payload[1];
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnMostDeviceType(device, true, r->SourceAddress, groupAddress );
+ }
+ else if (CISOpType_ERROR == r->OpType)
+ {
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnMostDeviceType(device, false, r->SourceAddress, 0xFFFF );
+ }
+ break;
+ case 0x013: //NetBlock EUI48
+ if (CISOpType_STATUS == r->OpType && r->PayloadLen >= 6)
+ {
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnMostMacAddress(device, true,
+ r->SourceAddress, r->Payload[0], r->Payload[1],
+ r->Payload[2], r->Payload[3], r->Payload[4], r->Payload[5]);
+ }
+ else if (CISOpType_ERROR == r->OpType)
+ {
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnMostMacAddress(device, false,
+ r->SourceAddress, 0,0,0,0,0,0);
+ }
+ break;
+ }
+ }
+ return ISReturn_NoChange;
+ }
+
+ virtual void OnSyncStateChanged(CIndustrialStack *iStack, bool isSynced)
+ {
+ assert(NULL != device);
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnSync(device, isSynced );
+ }
+};
+
+class CV3_NetworkStartup : public CISSendMostMsgElement
+{
+private:
+ CNetworkDevice *device;
+public:
+ CV3_NetworkStartup(CNetworkDevice *d, uint16_t autoForcedNotAvailable, uint16_t packetBW) : device(d)
+ {
+ ElementName = "CV3_NetworkStartup";
+ WaitForResponseOpType = CISOpType_RESULT;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = 0x1;
+ Request.FBlock = 0x0;
+ Request.Func = 0x524;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 4;
+ Request.Payload[0] = autoForcedNotAvailable / 256;
+ Request.Payload[1] = autoForcedNotAvailable % 256;
+ Request.Payload[2] = packetBW / 256;
+ Request.Payload[3] = packetBW % 256;
+ }
+};
+
+class CV3_MostNetworkConfiguration : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+public:
+ CV3_MostNetworkConfiguration(CNetworkDevice *d, uint16_t nodeAddress,
+ uint8_t macAddress1, uint8_t macAddress2, uint8_t macAddress3,
+ uint8_t macAddress4, uint8_t macAddress5, uint8_t macAddress6,
+ bool promiscuous) : device(d)
+ {
+ ElementName = "CV3_MostNetworkConfiguration";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_STATUS;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x521;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_SETGET;
+ Request.PayloadLen = 24;
+ Request.Payload[0] = 0; // HB: MASK
+ Request.Payload[1] =
+ ( 1 << 3 ) // LB: MASK: Packet Filter Mode is considered
+ | ( 1 << 5 ); // LB: MASK: PacketEUI is considered
+ Request.Payload[2] = 0x00; // HB: Node Address (ignored)
+ Request.Payload[3] = 0x08; // LB: Node Address (ignored)
+ Request.Payload[4] = 0x00; // HB: Group Address (ignored)
+ Request.Payload[5] = 0x00; // LB: Group Address (ignored)
+ Request.Payload[6] = 0x00; // Control LLR Block Count (ignored)
+ Request.Payload[7] = 0x00; // HB: FilterMode (reserved)
+ Request.Payload[8] = promiscuous ? 0x0A : 0x08; // LB: FilterMode (Allow all Multicast)
+ Request.Payload[9] = 0x00; // HB: PacketHash_63to48 (ignored)
+ Request.Payload[10] = 0x00; // LB: PacketHash_63to48 (ignored)
+ Request.Payload[11] = 0x00; // HB: PacketHash_47to32 (ignored)
+ Request.Payload[12] = 0x00; // LB: PacketHash_47to32 (ignored)
+ Request.Payload[13] = 0x00; // HB: PacketHash_31to16 (ignored)
+ Request.Payload[14] = 0x00; // LB: PacketHash_31to16 (ignored)
+ Request.Payload[15] = 0x00; // HB: PacketHash_15to0 (ignored)
+ Request.Payload[16] = 0x00; // LB: PacketHash_15to0 (ignored)
+ Request.Payload[17] = macAddress1; // HB: PacketEUI48_47to32
+ Request.Payload[18] = macAddress2; // LB: PacketEUI48_47to32
+ Request.Payload[19] = macAddress3; // HB: PacketEUI48_31to16
+ Request.Payload[20] = macAddress4; // LB: PacketEUI48_31to16
+ Request.Payload[21] = macAddress5; // HB: PacketEUI48_15to0
+ Request.Payload[22] = macAddress6; // LB: PacketEUI48_15to0
+ Request.Payload[23] = 0x00; // PacketLLRTime (ignored)
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ assert(this == element);
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 18;
+ if (success)
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnMostMacAddress(device, true,
+ Request.TargetAddress, Response.Payload[15],Response.Payload[16],
+ Response.Payload[17], Response.Payload[18], Response.Payload[19],
+ Response.Payload[20]);
+ else
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnMostMacAddress(device, false,
+ Request.TargetAddress, 0, 0, 0, 0, 0, 0);
+ }
+};
+
+class CV3_DeviceAttach : public CISSendMostMsgElement
+{
+public:
+ CV3_DeviceAttach()
+ {
+ ElementName = "CV3_DeviceAttach";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = 0x1;
+ Request.FBlock = 0x0;
+ Request.Func = 0x223;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ }
+};
+
+class CV3_Unsynchronize : public IISElement
+{
+public:
+ CV3_Unsynchronize()
+ {
+ ElementName = "CV3_Unsynchronize";
+ }
+
+ virtual ISReturn_t Service(CIndustrialStack *iStack, uint32_t time)
+ {
+ assert(NULL != iStack);
+ iStack->Unsynchronize();
+ return ISReturn_Success;
+ }
+
+ virtual ISReturn_t OnMostMessage(CIndustrialStack *iStack, CISMostMsg *r)
+ {
+ return ISReturn_NoChange;
+ }
+};
+
+class CV3_DeviceSync : public CISSendMostMsgElement
+{
+public:
+ CV3_DeviceSync(uint16_t nodeAddress, bool sync)
+ {
+ if (0x1 == nodeAddress)
+ {
+ ConsolePrintf(PRIO_ERROR, RED"CV3_DeviceSync was called with local" \
+ " node address, this will fail!"RESETCOLOR"\n");
+ }
+ ElementName = "CV3_DeviceSync";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x224;
+ Request.Inst = 0x01;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 1;
+ Request.Payload[0] = sync;
+ }
+};
+
+class CV3_NetworkShutdown : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+public:
+ CV3_NetworkShutdown(CNetworkDevice *d) : device(d)
+ {
+ ElementName = "CV3_NetworkShutdown";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = 0x1;
+ Request.FBlock = 0x0;
+ Request.Func = 0x525;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 0;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnNetworkShutdownV3(device, (ISReturn_Success == result));
+ }
+};
+
+class CV3_MlbPortCreate : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+public:
+ CV3_MlbPortCreate(CNetworkDevice *d, uint16_t nodeAddress, MlbPortSpeed_t mlbSpeed) : device(d)
+ {
+ ElementName = "CV3_MlbPortCreate";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x621;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 2;
+ Request.Payload[0] = 0x00; //Index
+ Request.Payload[1] = mlbSpeed; //ClockConfig
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ uint16_t mlbPortHandle = 0xFFFF;
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 2;
+ if (success)
+ mlbPortHandle = ( Response.Payload[0] << 8 ) | Response.Payload[1];
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnOpenMlbV3(device, success, Request.TargetAddress, mlbPortHandle);
+ }
+};
+
+class CV3_UsbSocketCreate : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ EPDataType_t epType;
+ EPDirection_t epDir;
+ uint8_t endPointAddress;
+ uint16_t packetsPerFrame;
+ uint32_t tag;
+public:
+ CV3_UsbSocketCreate(CNetworkDevice *d, uint16_t nodeAddress, EPDataType_t ept,
+ EPDirection_t epd, uint8_t epa, uint16_t p, uint32_t t) : device(d), epType(ept),
+ epDir(epd), endPointAddress(epa), packetsPerFrame(p), tag(t)
+ {
+ ElementName = "CV3_UsbSocketCreate";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x671;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 7;
+ Request.Payload[0] = 0x12; // HB: UsbPortHandle
+ Request.Payload[1] = 0x00; // LB: UsbPortHandle
+ Request.Payload[2] = epDir; // Direction
+ Request.Payload[3] = epType; // DataType
+ Request.Payload[4] = endPointAddress; // EndpointAddress
+ Request.Payload[5] = packetsPerFrame / 256; // HB: Packets per USB frame
+ Request.Payload[6] = packetsPerFrame % 256; // LB: Packets per USB frame
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ uint16_t usbHandle = 0xFFFF;
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 2;
+ if (success)
+ usbHandle = ( Response.Payload[0] << 8 ) | Response.Payload[1];
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnCreateUsbSocketV3(device, success,
+ Request.TargetAddress, epType, epDir, endPointAddress, usbHandle, tag);
+ }
+};
+
+class CV3_SplittedUsbSocketCreate : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ EPDataType_t epType;
+ EPDirection_t epDir;
+ uint8_t endPointAddress;
+ uint16_t packetsPerUsbFrame;
+ uint16_t bytesPerPacket;
+ uint32_t tag;
+ uint16_t usbHandle;
+public:
+ CV3_SplittedUsbSocketCreate(CNetworkDevice *d, uint16_t nodeAddress, EPDataType_t ept,
+ EPDirection_t epd, uint8_t epa, uint16_t p, uint16_t bp, uint32_t t) : device(d), epType(ept),
+ epDir(epd), endPointAddress(epa), packetsPerUsbFrame(p), bytesPerPacket(bp), tag(t),
+ usbHandle(0xFFFF)
+ {
+ ElementName = "CV3_SplittedUsbSocketCreate-USB";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x671;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 7;
+ Request.Payload[0] = 0x12; // HB: UsbPortHandle
+ Request.Payload[1] = 0x00; // LB: UsbPortHandle
+ Request.Payload[2] = epDir; // Direction
+ Request.Payload[3] = epType; // DataType
+ Request.Payload[4] = endPointAddress; // EndpointAddress
+ Request.Payload[5] = packetsPerUsbFrame / 256; // HB: Packets per USB frame
+ Request.Payload[6] = packetsPerUsbFrame % 256; // LB: Packets per USB frame
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 2;
+ if (!success)
+ {
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnCreateSplittedUsbSocketV3(device, false,
+ Request.TargetAddress, epType, epDir, endPointAddress, 0xFFFF, 0xFFFF, tag);
+ return;
+ }
+ if (0x671 == Response.Func)
+ {
+ usbHandle = ( Response.Payload[0] << 8 ) | Response.Payload[1];
+ CreateSplitter(iStack);
+ }
+ else
+ {
+ uint16_t splitterHandle = ( Response.Payload[0] << 8 ) | Response.Payload[1];
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnCreateSplittedUsbSocketV3(device, success,
+ Request.TargetAddress, epType, epDir, endPointAddress, usbHandle, splitterHandle, tag);
+ }
+ }
+private:
+ void CreateSplitter(CIndustrialStack *iStack)
+ {
+ assert(usbHandle != 0xFFFF);
+ ElementName = "CV3_SplittedUsbSocketCreate-Splitter";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+ startTime = 0;
+ Request.FBlock = 0x0;
+ if( EPDIR_IN == epDir )
+ Request.Func = 0x911; //SplitterCreate
+ else
+ Request.Func = 0x901; //CombinerCreate
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 6;
+ Request.Payload[0] = usbHandle / 256; // HB: SocketHandle IN/OUT
+ Request.Payload[1] = usbHandle % 256; // LB: SocketHandle IN/OUT
+ Request.Payload[2] = 0x0D; // HB: MOSTPortHandle
+ Request.Payload[3] = 0x00; // LB: MOSTPortHandle
+ Request.Payload[4] = bytesPerPacket / 256; // HB: BytesPerFrame
+ Request.Payload[5] = bytesPerPacket % 256; // LB: BytesPerFrame
+ iStack->EnqueueElement(Request.TargetAddress, this);
+ }
+};
+
+class CV3_MlbSocketCreate : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ uint16_t mlbPortHandle;
+ EPDataType_t epType;
+ EPDirection_t epDir;
+ uint8_t mlbChannelAddress;
+ uint16_t blockWidthMlb;
+ uint32_t tag;
+public:
+ CV3_MlbSocketCreate(CNetworkDevice *d, uint16_t nodeAddress, uint16_t mlb, EPDataType_t ept,
+ EPDirection_t epd, uint8_t eca, uint16_t bw, uint32_t t) : device(d), mlbPortHandle(mlb),
+ epType(ept), epDir(epd), mlbChannelAddress(eca), blockWidthMlb(bw), tag(t)
+ {
+ ElementName = "CV3_MlbSocketCreate";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x631;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 8;
+ Request.Payload[0] = mlbPortHandle / 256;
+ Request.Payload[1] = mlbPortHandle % 256;
+ Request.Payload[2] = epDir;
+ Request.Payload[3] = epType;
+ Request.Payload[4] = blockWidthMlb / 256;
+ Request.Payload[5] = blockWidthMlb % 256;
+ Request.Payload[6] = mlbChannelAddress / 256;
+ Request.Payload[7] = mlbChannelAddress % 256;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ uint16_t mlbHandle = 0xFFFF;
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 2;
+ if (success)
+ mlbHandle = ( Response.Payload[0] << 8 ) | Response.Payload[1];
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnCreateMlbSocketV3(device, success,
+ Request.TargetAddress, epType, epDir, blockWidthMlb, mlbChannelAddress, mlbHandle, tag);
+ }
+};
+
+class CV3_SplittedMlbSocketCreate : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ uint16_t mlbPortHandle;
+ EPDataType_t epType;
+ EPDirection_t epDir;
+ uint8_t mlbChannelAddress;
+ uint16_t blockWidthMlb;
+ uint16_t bytesPerPacket;
+ uint16_t mlbHandle;
+ uint32_t tag;
+public:
+ CV3_SplittedMlbSocketCreate(CNetworkDevice *d, uint16_t nodeAddress, uint16_t mlb, EPDataType_t ept,
+ EPDirection_t epd, uint8_t eca, uint16_t bw, uint16_t bp, uint32_t t) : device(d), mlbPortHandle(mlb),
+ epType(ept), epDir(epd), mlbChannelAddress(eca), blockWidthMlb(bw), bytesPerPacket(bp), tag(t)
+ {
+ ElementName = "CV3_SplittedMlbSocketCreate-MLB";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x631;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 8;
+ Request.Payload[0] = mlbPortHandle / 256;
+ Request.Payload[1] = mlbPortHandle % 256;
+ Request.Payload[2] = epDir;
+ Request.Payload[3] = epType;
+ Request.Payload[4] = blockWidthMlb / 256;
+ Request.Payload[5] = blockWidthMlb % 256;
+ Request.Payload[6] = mlbChannelAddress / 256;
+ Request.Payload[7] = mlbChannelAddress % 256;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 2;
+ if (!success)
+ {
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnCreateSplittedMlbSocketV3(device, false,
+ Request.TargetAddress, epType, epDir, blockWidthMlb, mlbChannelAddress,
+ 0xFFFF, 0xFFFF, tag);
+ return;
+ }
+ if (0x631 == Response.Func)
+ {
+ mlbHandle = ( Response.Payload[0] << 8 ) | Response.Payload[1];
+ CreateSplitter(iStack);
+ }
+ else
+ {
+ uint16_t splitterHandle = ( Response.Payload[0] << 8 ) | Response.Payload[1];
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnCreateSplittedMlbSocketV3(device, success,
+ Request.TargetAddress, epType, epDir, blockWidthMlb, mlbChannelAddress,
+ mlbHandle, splitterHandle, tag);
+ }
+ }
+private:
+ void CreateSplitter(CIndustrialStack *iStack)
+ {
+ assert(mlbHandle != 0xFFFF);
+ ElementName = "CV3_SplittedMlbSocketCreate-Splitter";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+ startTime = 0;
+ Request.FBlock = 0x0;
+ if( EPDIR_IN == epDir )
+ Request.Func = 0x911; //SplitterCreate
+ else
+ Request.Func = 0x901; //CombinerCreate
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 6;
+ Request.Payload[0] = mlbHandle / 256; // HB: SocketHandle IN/OUT
+ Request.Payload[1] = mlbHandle % 256; // LB: SocketHandle IN/OUT
+ Request.Payload[2] = 0x0D; // HB: MOSTPortHandle
+ Request.Payload[3] = 0x00; // LB: MOSTPortHandle
+ Request.Payload[4] = bytesPerPacket / 256; // HB: BytesPerFrame
+ Request.Payload[5] = bytesPerPacket % 256; // LB: BytesPerFrame
+ iStack->EnqueueElement(Request.TargetAddress, this);
+ }
+};
+
+class CV3_MostSocketCreate : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ uint16_t nodeAddress;
+ EPDataType_t epType;
+ EPDirection_t epDir;
+ uint16_t connectionLabel;
+ uint16_t blockwidthMost;
+ uint32_t tag;
+public:
+ CV3_MostSocketCreate(CNetworkDevice *d, uint16_t nodeAddress, EPDataType_t ep, EPDirection_t epd,
+ uint16_t cl, uint16_t bw, uint32_t t) : device(d), epType(ep),
+ epDir(epd), connectionLabel(cl), blockwidthMost(bw), tag(t)
+ {
+ ElementName = "CV3_MostSocketCreate";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x611;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 8;
+ Request.Payload[0] = 0x0D; // HB: MostPortHandle
+ Request.Payload[1] = 0x00; // LB: MostPortHandle
+ Request.Payload[2] = epDir; // Dir
+ Request.Payload[3] = epType; // DataType
+ Request.Payload[4] = blockwidthMost / 256; // HB: bandwidth
+ Request.Payload[5] = blockwidthMost % 256; // LB: bandwidth
+ Request.Payload[6] = connectionLabel / 256; // HB: ConnectionLabel
+ Request.Payload[7] = connectionLabel % 256; // LB: ConnectionLabel
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ uint16_t conHandle = 0xFFFF;
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 4;
+ if (success)
+ conHandle = ( Response.Payload[0] << 8 ) | Response.Payload[1];
+
+ if (success && SCM_OUT == epDir && Response.PayloadLen >= 4)
+ connectionLabel = ( Response.Payload[2] << 8 ) | Response.Payload[3];
+
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnCreateMostSocketV3(device, success,
+ Request.TargetAddress, epType, epDir, blockwidthMost, connectionLabel, conHandle, tag);
+ }
+};
+
+class CV3_ConnectSockets : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ uint16_t nodeAddress;
+ EPDataType_t epType;
+ uint16_t inHandle;
+ uint16_t outHandle;
+ uint16_t offset;
+ uint32_t tag;
+public:
+ CV3_ConnectSockets(CNetworkDevice *d, uint16_t nodeAddress, EPDataType_t ep, uint16_t iH,
+ uint16_t oH, uint16_t o, uint32_t t) : device(d), epType(ep), inHandle(iH),
+ outHandle(oH), offset(o), tag(t)
+ {
+ ElementName = "CV3_ConnectSockets";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+
+ switch( epType )
+ {
+ case EP_Isochron:
+ Request.Func = 0x861; //AVPCreate
+ Request.PayloadLen = 6;
+ Request.Payload[0] = inHandle / 256; // HB: in handle (will be filled by decomposerHandleIn)
+ Request.Payload[1] = inHandle % 256; // LB: in handle (will be filled by decomposerHandleIn)
+ Request.Payload[2] = outHandle / 256; // HB: out handle (will be filled by decomposerHandleOut)
+ Request.Payload[3] = outHandle % 256; // LB: out handle (will be filled by decomposerHandleOut)
+ Request.Payload[4] = 0x00; // HB: IsoPacketSize
+ Request.Payload[5] = 188; // LB: IsoPacketSize
+ break;
+ case EP_Synchron:
+ Request.Func = 0x871; // SyncCreate
+ Request.PayloadLen = 8;
+ Request.Payload[0] = inHandle / 256; // HB: in handle (will be filled by decomposerHandleIn)
+ Request.Payload[1] = inHandle % 256; // LB: in handle (will be filled by decomposerHandleIn)
+ Request.Payload[2] = outHandle / 256; // HB: out handle (will be filled by decomposerHandleOut)
+ Request.Payload[3] = outHandle % 256; // LB: out handle (will be filled by decomposerHandleOut)
+ Request.Payload[4] = 0x00; // 0: not muted by default; 1: muted by default
+ Request.Payload[5] = 0x00; // 0: NoMuting, 1:MuteSignal, 2:AutoMute
+ Request.Payload[6] = offset / 256; // HB: Offset
+ Request.Payload[7] = offset % 256; // LB: Offset
+ break;
+ default:
+ WaitForResponse = false;
+ ConsolePrintf( PRIO_ERROR, RED"CV3_ConnectSockets: Unsupported Data type"RESETCOLOR"\n" );
+ return;
+ }
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ assert(this == element);
+ uint16_t conHandle = 0xFFFF;
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 2;
+ if (success)
+ conHandle = ( Response.Payload[0] << 8 ) | Response.Payload[1];
+
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnConnectSocketsV3(device, success,
+ Request.TargetAddress, epType, inHandle, outHandle, conHandle, tag);
+ }
+};
+
+class CV3_ResourceDestroy : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ uint16_t nodeAddress;
+ uint8_t amountOfHandles;
+ uint32_t tag;
+public:
+ CV3_ResourceDestroy(CNetworkDevice *d, int16_t nodeAddress,
+ uint8_t amount, const uint16_t *pHandle, uint32_t t) : device(d),
+ amountOfHandles(amount), tag(t)
+ {
+ ElementName = "CV3_ResourceDestroy";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x800;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+
+ uint8_t index = 0;
+ Request.Payload[index++] = 0x00; // HB: SenderHandle
+ Request.Payload[index++] = 0x00; // LB: SenderHandle
+ for( uint8_t i = 0; i < amountOfHandles; i++ )
+ {
+ Request.Payload[index++] = pHandle[i] / 256; // HB: handle
+ Request.Payload[index++] = pHandle[i] % 256; // LB: handle
+ }
+ Request.PayloadLen = index;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnResourceDestroyV3(device, true,
+ Request.TargetAddress, amountOfHandles, ( uint16_t * )&Request.Payload[2], tag);
+ }
+};
+
+class CV3_StreamPortConfig : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ uint8_t portInstance;
+ V3I2SPortOption_t option;
+ V3I2SClockMode_t mode;
+ V3I2SDelayMode_t delay;
+ uint32_t tag;
+public:
+ CV3_StreamPortConfig(CNetworkDevice *d, uint16_t nodeAddress, uint8_t port,
+ V3I2SPortOption_t opt, V3I2SClockMode_t md, V3I2SDelayMode_t del, uint32_t t)
+ : device(d), portInstance(port), option(opt), mode(md), delay(del), tag(t)
+ {
+ ElementName = "CV3_StreamPortConfig";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x680;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_SETGET;
+ Request.PayloadLen = 5;
+ Request.Payload[0] = portInstance;
+ Request.Payload[1] = 0x00; //Fixed operation mode 0 = Generic
+ Request.Payload[2] = option;
+ Request.Payload[3] = mode;
+ Request.Payload[4] = delay;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnConfigureI2SPortV3(device, (ISReturn_Success == result),
+ Request.TargetAddress, portInstance, option, mode, delay, tag);
+ }
+};
+
+class CV3_StreamPortCreate : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ uint8_t portInstance;
+ V3I2SPortSpeed_t clock;
+ V3I2SAlignment_t align;
+ uint32_t tag;
+public:
+ CV3_StreamPortCreate(CNetworkDevice *d, uint16_t nodeAddress, uint8_t port,
+ V3I2SPortSpeed_t cl, V3I2SAlignment_t al, uint32_t t)
+ : device(d), portInstance(port), clock(cl), align(al), tag(t)
+ {
+ ElementName = "CV3_StreamPortCreate";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x681;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 3;
+ Request.Payload[0] = portInstance;
+ Request.Payload[1] = clock;
+ Request.Payload[2] = align;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnCreateI2SPortV3(device, (ISReturn_Success == result),
+ Request.TargetAddress, portInstance, clock, align, tag);
+ }
+};
+
+class CV3_StreamSocketCreate : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ uint8_t portInstance;
+ EPDirection_t epDir;
+ uint16_t blockWidthI2S;
+ V3I2SPin_t pin;
+ uint32_t tag;
+public:
+ CV3_StreamSocketCreate(CNetworkDevice *d, uint16_t nodeAddress, uint8_t pi, EPDirection_t epd,
+ uint16_t bw, V3I2SPin_t p, uint32_t t) : device(d), portInstance(pi),
+ epDir(epd), blockWidthI2S(bw), pin(p), tag(t)
+ {
+ ElementName = "CV3_StreamSocketCreate";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x691;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 7;
+ Request.Payload[0] = 0x16; //Fixed port handle for I2S
+ Request.Payload[1] = portInstance; //dynamic port handle for I2S (Port A or B)
+ Request.Payload[2] = epDir;
+ Request.Payload[3] = 0x00; //Data type (fixed 0 for sync)
+ Request.Payload[4] = blockWidthI2S / 256;
+ Request.Payload[5] = blockWidthI2S % 256;
+ Request.Payload[6] = pin;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ uint16_t i2sHandle = 0xFFFF;
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 2;
+ if (success)
+ i2sHandle = ( Response.Payload[0] << 8 ) | Response.Payload[1];
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnCreateI2SSocketV3(device, success,
+ Request.TargetAddress, portInstance, epDir, blockWidthI2S, pin, i2sHandle, tag);
+ }
+};
+
+class CV3_SplittedStreamSocketCreate : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ uint8_t portInstance;
+ EPDirection_t epDir;
+ uint16_t blockWidthI2S;
+ V3I2SPin_t pin;
+ uint16_t bytesPerPacket;
+ uint32_t tag;
+ uint16_t i2sHandle;
+public:
+ CV3_SplittedStreamSocketCreate(CNetworkDevice *d, uint16_t nodeAddress, uint8_t pi,
+ EPDirection_t epd, uint16_t bw, V3I2SPin_t p, uint16_t bp, uint32_t t) : device(d),
+ portInstance(pi), epDir(epd), blockWidthI2S(bw), pin(p), bytesPerPacket(bp), tag(t),
+ i2sHandle(0xFFFF)
+ {
+ ElementName = "CV3_SplittedStreamSocketCreate-Stream";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x691;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 7;
+ Request.Payload[0] = 0x16; //Fixed port handle for I2S
+ Request.Payload[1] = portInstance; //dynamic port handle for I2S (Port A or B)
+ Request.Payload[2] = epDir;
+ Request.Payload[3] = 0x00; //Data type (fixed 0 for sync)
+ Request.Payload[4] = blockWidthI2S / 256;
+ Request.Payload[5] = blockWidthI2S % 256;
+ Request.Payload[6] = pin;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 2;
+ if (!success)
+ {
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnCreateSplittedI2SSocketV3(device, false,
+ Request.TargetAddress, portInstance, epDir, blockWidthI2S, pin,
+ 0xFFFF, 0xFFFF, tag);
+ return;
+ }
+ if (0x691 == Response.Func)
+ {
+ i2sHandle = ( Response.Payload[0] << 8 ) | Response.Payload[1];
+ CreateSplitter(iStack);
+ }
+ else
+ {
+ uint16_t splitterHandle = ( Response.Payload[0] << 8 ) | Response.Payload[1];
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnCreateSplittedI2SSocketV3(device, success,
+ Request.TargetAddress, portInstance, epDir, blockWidthI2S, pin,
+ i2sHandle, splitterHandle, tag);
+ }
+ }
+private:
+ void CreateSplitter(CIndustrialStack *iStack)
+ {
+ assert(i2sHandle != 0xFFFF);
+ ElementName = "CV3_SplittedStreamSocketCreate-Splitter";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_RESULT;
+ Callback = this;
+ startTime = 0;
+ Request.FBlock = 0x0;
+ if( EPDIR_IN == epDir )
+ Request.Func = 0x911; //SplitterCreate
+ else
+ Request.Func = 0x901; //CombinerCreate
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_STARTRESULT;
+ Request.PayloadLen = 6;
+ Request.Payload[0] = i2sHandle / 256; // HB: SocketHandle IN/OUT
+ Request.Payload[1] = i2sHandle % 256; // LB: SocketHandle IN/OUT
+ Request.Payload[2] = 0x0D; // HB: MOSTPortHandle
+ Request.Payload[3] = 0x00; // LB: MOSTPortHandle
+ Request.Payload[4] = bytesPerPacket / 256; // HB: BytesPerFrame
+ Request.Payload[5] = bytesPerPacket % 256; // LB: BytesPerFrame
+ iStack->EnqueueElement(Request.TargetAddress, this);
+ }
+};
+
+class CV3_GetRbdResult : public CISSendMostMsgElement
+{
+public:
+ CV3_GetRbdResult(uint16_t nodeAddress)
+ {
+ ElementName = "CV3_GetRbdResult";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_STATUS;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Func = 0x527;
+ Request.Inst = 0x00;
+ Request.OpType = CISOpType_GET;
+ Request.PayloadLen = 0;
+ }
+};
+
+class CV3_DeviceVersion : public CISSendMostMsgElement, public IISElementCallback
+{
+private:
+ CNetworkDevice *device;
+ uint16_t nodeAddress;
+ EPDataType_t epType;
+ uint16_t inHandle;
+ uint16_t outHandle;
+ uint16_t offset;
+ uint32_t tag;
+public:
+ CV3_DeviceVersion(CNetworkDevice *d, uint16_t nodeAddress, uint32_t t) : device(d), tag(t)
+ {
+ ElementName = "CV3_DeviceVersion";
+ WaitForResponse = true;
+ WaitForResponseOpType = CISOpType_STATUS;
+ Callback = this;
+
+ Request.IsValid = true;
+ Request.SourceAddress = 0x2;
+ Request.TargetAddress = nodeAddress;
+ Request.FBlock = 0x0;
+ Request.Inst = 0x00;
+ Request.Func = 0x221;
+ Request.OpType = CISOpType_GET;
+ Request.PayloadLen = 0;
+ }
+
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element)
+ {
+ assert(this == element);
+ bool success = (ISReturn_Success == result) && Response.PayloadLen >= 13;
+
+ uint32_t productId = 0xFFFFFFFF;
+ uint32_t fwVersion = 0xFFFFFFFF;
+ uint32_t buildVersion = 0xFFFFFFFF;
+ uint8_t hwVersion = 0xFF;
+ uint16_t diagnosisId = 0xFFFF;
+
+ if (success)
+ {
+ productId = ( Response.Payload[0] << 24 )
+ | ( Response.Payload[1] << 16 )
+ | ( Response.Payload[2] << 8 )
+ | Response.Payload[3];
+
+ fwVersion = ( Response.Payload[4] << 24 )
+ | ( Response.Payload[5] << 16 )
+ | ( Response.Payload[6] << 8 );
+
+ buildVersion = ( Response.Payload[7] << 24 )
+ | ( Response.Payload[8] << 16 )
+ | ( Response.Payload[9] << 8 )
+ | Response.Payload[10];
+
+ hwVersion = Response.Payload[10];
+
+ diagnosisId = ( Response.Payload[11] << 8 )
+ | Response.Payload[12];
+ }
+
+ for( uint32_t i = 0; NULL != device && i < device->GetAmountOfListners(); i++ )
+ device->GetListener( i )->OnDeviceVersion(device, success, Response.SourceAddress,
+ productId, fwVersion, buildVersion, hwVersion, diagnosisId, tag);
+ }
+};
+
+#endif //INDUSTRIAL_STACK_API_V3_H \ No newline at end of file
diff --git a/Src/Network/IndustrialStack_LLD.cpp b/Src/Network/IndustrialStack_LLD.cpp
new file mode 100644
index 0000000..f025dec
--- /dev/null
+++ b/Src/Network/IndustrialStack_LLD.cpp
@@ -0,0 +1,278 @@
+/*
+ * 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 LLD_TRACE
+
+/*----------------------------------------------------------*/
+/*! \file */
+/*! \brief Base Board initialisation */
+/*----------------------------------------------------------*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <pthread.h>
+#include <assert.h>
+
+#include "Console.h"
+#include "Board.h"
+#include "DriverConfiguration.h"
+#include "IndustrialStack_LLD.h"
+
+/*----------------------------------------------------------*/
+/* Static C helper functions */
+/*----------------------------------------------------------*/
+
+static void Queue_Init( Queue_t *queue )
+{
+ assert(NULL != queue);
+ queue->testPattern = QUEUE_TESTPATTERN;
+ queue->rxPos = 0;
+ queue->txPos = 0;
+ queue->pRx = queue->dataQueue;
+ queue->pTx = queue->dataQueue;
+}
+
+static QueueEntry_t *Queue_GetRxPtr( Queue_t *queue )
+{
+ assert(NULL != queue && QUEUE_TESTPATTERN == queue->testPattern);
+ QueueEntry_t *pEntry = NULL;
+ if( queue->txPos - queue->rxPos > 0 )
+ {
+ pEntry = queue->pRx;
+ }
+ return pEntry;
+}
+
+static void Queue_PopRx( Queue_t *queue )
+{
+ assert(NULL != queue && QUEUE_TESTPATTERN == queue->testPattern);
+ if( ++queue->pRx >= queue->dataQueue + BOARD_PMS_RX_QUEUE )
+ queue->pRx = queue->dataQueue;
+ ++queue->rxPos;
+}
+
+static QueueEntry_t *Queue_GetTxPtr( Queue_t *queue )
+{
+ assert(NULL != queue && QUEUE_TESTPATTERN == queue->testPattern);
+ QueueEntry_t *pEntry = NULL;
+ if( ( uint32_t )BOARD_PMS_RX_QUEUE + queue->rxPos - queue->txPos > 0 )
+ {
+ pEntry = queue->pTx;
+ }
+ return pEntry;
+}
+
+static void Queue_PopTx( Queue_t *queue )
+{
+ assert(NULL != queue && QUEUE_TESTPATTERN == queue->testPattern);
+ if( ++queue->pTx >= queue->dataQueue + BOARD_PMS_RX_QUEUE )
+ queue->pTx = queue->dataQueue;
+ ++queue->txPos;
+}
+
+static void *ReceiveThread( void *tag )
+{
+ assert(NULL != tag);
+ CIndustrialStackLld *var = ( CIndustrialStackLld * )tag;
+ while( var->allowThreadRun )
+ {
+ if( -1 == var->hControlRx )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"File handle for Control-RX is invalid, stopping reader thread."RESETCOLOR"\n" );
+ if (NULL != var->listener)
+ var->listener->OnReadThreadEnd(var);
+ pthread_exit( NULL );
+ }
+ QueueEntry_t *pEntry = Queue_GetTxPtr(&var->rxQueue);
+ if( NULL != pEntry )
+ {
+ int16_t payloadLen = 0;
+ payloadLen = read( var->hControlRx, pEntry->buffer, sizeof( pEntry->buffer ) );
+ if( payloadLen < 0 )
+ {
+ if( var->allowThreadRun )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Stopping reader thread, because of error: '%s'"RESETCOLOR"\n",
+ GetErrnoString() );
+ if (NULL != var->listener)
+ var->listener->OnReadThreadEnd(var);
+ }
+ pthread_exit( NULL );
+ }
+ else if( payloadLen != 0 )
+ {
+ pEntry->payloadLen = payloadLen;
+ Queue_PopTx(&var->rxQueue);
+#ifdef LLD_TRACE
+ {
+ ConsolePrintfStart( PRIO_HIGH, BLUE"%04d: MSG_RX: ", GetTickCountWord());
+ for ( int16_t i = 0; i < pEntry->payloadLen; i++ )
+ {
+ ConsolePrintfContinue( "%02X ", pEntry->buffer[i] );
+ }
+ ConsolePrintfExit(RESETCOLOR"\n");
+ }
+#endif
+ }
+ }
+ else
+ {
+ ConsolePrintf( PRIO_ERROR, RED"WARNING, RX QUEUE FULL !!\nPlease increase BOARD_PMS_RX_QUEUE value, or increase polling speed\n"RESETCOLOR"\n" );
+ usleep( 10000 );
+ }
+ }
+ ConsolePrintf( PRIO_LOW, "Control Receive Thread ends\n" );
+ if( var->allowThreadRun && NULL != var->listener)
+ var->listener->OnReadThreadEnd(var);
+ pthread_exit( NULL );
+}
+
+static void *SendThread( void *tag )
+{
+ assert(NULL != tag);
+ CIndustrialStackLld *var = ( CIndustrialStackLld * )tag;
+ while( var->allowThreadRun )
+ {
+ sem_wait( &var->txSem );
+ if (!var->allowThreadRun)
+ pthread_exit( NULL );
+ QueueEntry_t *pEntry = Queue_GetRxPtr( &var->txQueue );
+ assert(NULL != pEntry);
+ if( -1 == var->hControlTx )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"File handle for Control-TX is invalid, stopping send thread."RESETCOLOR"\n" );
+ pthread_exit( NULL );
+ }
+#ifdef LLD_TRACE
+ {
+ uint32_t i;
+ ConsolePrintfStart( PRIO_MEDIUM, YELLOW"%04d: MSG_TX: ", GetTickCountWord());
+ for ( i = 0; i < pEntry->payloadLen; i++ )
+ {
+ ConsolePrintfContinue( "%02X ", pEntry->buffer[i] );
+ }
+ ConsolePrintfExit(RESETCOLOR"\n");
+ }
+#endif
+ if( write( var->hControlTx, pEntry->buffer, pEntry->payloadLen ) != pEntry->payloadLen )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Failed to send %d bytes to the MOST control channel"RESETCOLOR"\n", pEntry->payloadLen );
+ usleep(1000);
+ }
+ else
+ {
+ Queue_PopRx(&var->txQueue);
+ }
+
+ }
+ pthread_exit( NULL );
+}
+
+/*----------------------------------------------------------*/
+/* Public method implementations */
+/*----------------------------------------------------------*/
+
+CIndustrialStackLld::CIndustrialStackLld( int controlRxHandle, int controlTxHandle )
+ : hControlRx(controlRxHandle), hControlTx(controlTxHandle), allowThreadRun(true), listener(NULL)
+{
+ Queue_Init(&rxQueue);
+ Queue_Init(&txQueue);
+
+ if (sem_init(&txSem, 0, 0) == -1)
+ {
+ ConsolePrintf(PRIO_ERROR, RED"CIndustrialStackLld constructor: sem_init failed"RESETCOLOR"\n");
+ return;
+ }
+
+ pthread_create( &rxThread, NULL, ReceiveThread, this );
+ pthread_create( &txThread, NULL, SendThread, this );
+}
+
+CIndustrialStackLld::~CIndustrialStackLld()
+{
+ void *dummy;
+ allowThreadRun = false;
+ sem_post( &txSem );
+
+ pthread_join( txThread, &dummy );
+ pthread_join( rxThread, &dummy );
+
+ sem_destroy( &txSem );
+}
+
+void CIndustrialStackLld::ClearQueues()
+{
+ ConsolePrintf( PRIO_LOW, "Clearing INIC queues\n" );
+ QueueEntry_t *pEntry;
+ while( NULL != ( pEntry = Queue_GetRxPtr(&rxQueue) ) )
+ Queue_PopRx(&rxQueue);
+ while( NULL != ( pEntry = Queue_GetRxPtr(&txQueue) ) )
+ Queue_PopRx(&txQueue);
+}
+
+uint16_t CIndustrialStackLld::DataAvailable()
+{
+ uint16_t readLen = 0;
+ QueueEntry_t *pEntry = Queue_GetRxPtr(&rxQueue);
+ if( NULL != pEntry )
+ readLen = pEntry->payloadLen;
+ return readLen;
+}
+
+uint16_t CIndustrialStackLld::Read( uint8_t *pData, uint32_t bufferLen )
+{
+ uint16_t readLen = 0;
+ QueueEntry_t *pEntry = Queue_GetRxPtr(&rxQueue);
+ if( NULL != pData && NULL != pEntry )
+ {
+ readLen = pEntry->payloadLen;
+ if (readLen > bufferLen)
+ {
+ ConsolePrintf(PRIO_ERROR, RED"CIndustrialStackLld::Read buffer"\
+ " length is too small"RESETCOLOR"\n");
+ readLen = bufferLen;
+ }
+ memcpy( pData, pEntry->buffer, readLen );
+ Queue_PopRx(&rxQueue);
+ }
+ return readLen;
+}
+
+bool CIndustrialStackLld::Write( uint16_t wLen, uint8_t *pData )
+{
+ if( -1 == hControlTx )
+ return false;
+ QueueEntry_t *pEntry = Queue_GetTxPtr( &txQueue );
+ if( NULL != pData && NULL != pEntry )
+ {
+ memcpy( pEntry->buffer, pData, wLen );
+ pEntry->payloadLen = wLen;
+ Queue_PopTx( &txQueue );
+ sem_post( &txSem );
+ return true;
+ }
+ return false;
+}
diff --git a/Src/Network/IndustrialStack_LLD.h b/Src/Network/IndustrialStack_LLD.h
new file mode 100644
index 0000000..8ae9738
--- /dev/null
+++ b/Src/Network/IndustrialStack_LLD.h
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This component implements the MOST low level driver.
+ */
+/*----------------------------------------------------------*/
+#ifndef INDUSTRIAL_STACK_LLD_H
+#define INDUSTRIAL_STACK_LLD_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <semaphore.h>
+#include "IndustrialStack_Types.h"
+
+#define BOARD_PMS_RX_QUEUE 256
+#define BOARD_PMS_RX_SIZE 64
+#define BOARD_PMS_TX_SIZE 64
+
+typedef struct
+{
+ int16_t payloadLen;
+ uint8_t buffer[BOARD_PMS_RX_SIZE];
+} QueueEntry_t;
+
+#define QUEUE_TESTPATTERN (0x34547382)
+typedef struct
+{
+ uint32_t testPattern;
+ QueueEntry_t dataQueue[BOARD_PMS_RX_QUEUE];
+ QueueEntry_t *pRx;
+ QueueEntry_t *pTx;
+ volatile uint32_t rxPos;
+ volatile uint32_t txPos;
+} Queue_t;
+
+class CIndustrialStackLld
+{
+private:
+ pthread_t txThread;
+ pthread_t rxThread;
+public:
+ ///Do not use directly! (Called internally from thread context)
+ Queue_t txQueue;
+ ///Do not use directly! (Called internally from thread context)
+ Queue_t rxQueue;
+ ///Do not use directly! (Called internally from thread context)
+ int hControlRx;
+ ///Do not use directly! (Called internally from thread context)
+ int hControlTx;
+ ///Do not use directly! (Called internally from thread context)
+ bool allowThreadRun;
+ ///Do not use directly! (Called internally from thread context)
+ sem_t txSem;
+
+ CIndustrialStackLldCB *listener;
+
+ /*----------------------------------------------------------*/
+ /*! \brief initializes LLD
+ *
+ * \param controlRxHandle File handle for the RX character device
+ * \param controlRxHandle File handle for the TX character device
+ * \return nothing.
+ */
+ /*----------------------------------------------------------*/
+ CIndustrialStackLld( int controlRxHandle, int controlTxHandle );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief deinitializes LLD
+ */
+ /*----------------------------------------------------------*/
+ ~CIndustrialStackLld();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief determins if INIC has something to read
+ *
+ * \return The amount of data, which will be delivered by the next call of Read
+ */
+ /*----------------------------------------------------------*/
+ uint16_t DataAvailable();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief receive a control message via USB.
+ *
+ * \param pData - message data
+ *
+ * \return The amount of bytes read.
+ */
+ /*----------------------------------------------------------*/
+ uint16_t Read( uint8_t *pData, uint32_t bufferLen );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Clearing RX and TX queues.
+ *
+ * \return nothing
+ */
+ /*----------------------------------------------------------*/
+ void ClearQueues();
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief send a control message via USB.
+ *
+ * \param wLen - length of message in bytes
+ * \param pData - message data
+ *
+ * \return True if no error.
+ */
+ /*----------------------------------------------------------*/
+ bool Write( uint16_t wLen, uint8_t *pData );
+
+};
+
+class CIndustrialStackLldCB
+{
+public:
+ virtual void OnReadThreadEnd(CIndustrialStackLld *lld) = 0;
+};
+
+#endif // INDUSTRIAL_STACK_LLD_H
diff --git a/Src/Network/IndustrialStack_MNS.cpp b/Src/Network/IndustrialStack_MNS.cpp
new file mode 100644
index 0000000..257db40
--- /dev/null
+++ b/Src/Network/IndustrialStack_MNS.cpp
@@ -0,0 +1,414 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CIndustrialStack class (NetService part).
+ */
+/*----------------------------------------------------------*/
+
+#define ENABLE_INIC_WATCHDOG true
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "IndustrialStack_MNS.h"
+#include "IndustrialStack_Types.h"
+#include "Board.h"
+#include "Console.h"
+
+static bool CheckMnswPointer(void *inst_ptr, const char *functionName);
+static void Lld_CtrlStartC( Mns_Lld_Api_t *callbacks_ptr, void *ns_ptr, void *inst_ptr );
+static void Lld_CtrlStopC( void *inst_ptr );
+static void Lld_CtrlTxTransmitC( Mns_Lld_TxMsg_t *msg_ptr, void *inst_ptr );
+static void Lld_CtrlRxMsgAvailableC( void *inst_ptr );
+static uint16_t GetTickCountWordC();
+static void OnMnslEventC( Mnsl_Event_t event_code, void *inst_ptr );
+static void OnMnslServiceC( void *inst_ptr );
+static void *OnMnslAmsAllocMemC( void *inst_ptr, uint16_t mem_size, Mns_Ams_MemUsage_t type, void** custom_info_pptr );
+static void OnMnslAmsFreeMemC( void *inst_ptr, void *mem_ptr, Mns_Ams_MemUsage_t type, void* custom_info_ptr );
+static void OnIcmRx( void *inst_ptr, Msg_MostTel_t *pRx );
+static void OnRcmRx( void *inst_ptr, Msg_MostTel_t *pRx );
+static void OnMcmRx( void *inst_ptr, Msg_MostTel_t *pRx );
+static void OnTransmissionStatus(void *self, Msg_MostTel_t *tel_ptr, Mns_MsgTxStatus_t status);
+
+CISNetServiceWrapper::CISNetServiceWrapper(uint8_t deviceApi, int controlRxHandle, int controlTxHandle)
+ : testPattern(MNSW_TESTPATTERN), inicWriteError( false ), pMnsInterface(NULL), pMnsInst(NULL)
+ , isSynced(false), wrapperCB(NULL)
+{
+ if( 2 != deviceApi && 3 != deviceApi )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"CISNetServiceWrapper was called with deviceApi set"\
+ " to %d. This is not supported by this branch of NetworkManager"\
+ RESETCOLOR"\n", deviceApi );
+ }
+
+ lld = new CIndustrialStackLld(controlRxHandle, controlTxHandle);
+ lld->listener = this;
+
+ memset(&pLldCb, 0, sizeof(pLldCb));
+ pLldCb.start_fptr = &Lld_CtrlStartC;
+ pLldCb.stop_fptr = &Lld_CtrlStopC;
+ pLldCb.rx_available_fptr = &Lld_CtrlRxMsgAvailableC;
+ pLldCb.tx_transmit_fptr = &Lld_CtrlTxTransmitC;
+
+ Mnsl_InitData_t initData;
+ Mnsl_SetDefaultConfig(&initData, ENABLE_INIC_WATCHDOG);
+ initData.lld.start_fptr = &Lld_CtrlStartC;
+ initData.lld.stop_fptr = &Lld_CtrlStopC;
+ initData.lld.rx_available_fptr = &Lld_CtrlRxMsgAvailableC;
+ initData.lld.tx_transmit_fptr = &Lld_CtrlTxTransmitC;
+
+ initData.general.get_tickcount_fptr = &GetTickCountWordC;
+ initData.general.event_fptr = &OnMnslEventC;
+ initData.general.request_service_fptr = &OnMnslServiceC;
+
+ initData.pms.active_fifos = MNSL_FIFOS_MCM_ICM_RCM;
+ initData.pms.compressed = (2 == deviceApi);
+
+ initData.ams.rx_alloc_mem_fptr = &OnMnslAmsAllocMemC;
+ initData.ams.rx_free_mem_fptr = &OnMnslAmsFreeMemC;
+
+ Mnsl_Init( &mnsl, &initData, this );
+
+ icm_inst_ptr = Mnsl_GetIcmTransceiver( &mnsl ); // Retrieve ICM instance
+ rcm_inst_ptr = Mnsl_GetRcmTransceiver( &mnsl ); // Retrieve RCM instance
+ mcm_inst_ptr = Mnsl_GetMcmTransceiver( &mnsl ); // Retrieve MCM instance
+
+ Trcv_RxAssignReceiver( icm_inst_ptr, &OnIcmRx, this ); // Assign ICM Receiver Callback
+ Trcv_RxAssignReceiver( rcm_inst_ptr, &OnRcmRx, this ); // Assign ICM Receiver Callback
+ Trcv_RxAssignReceiver( mcm_inst_ptr, &OnMcmRx, this ); // Assign ICM Receiver Callback
+
+ Mnsl_Synchronize( &mnsl );
+}
+
+CISNetServiceWrapper::~CISNetServiceWrapper()
+{
+ if (NULL != lld)
+ {
+ delete lld;
+ lld = NULL;
+ }
+}
+
+void CISNetServiceWrapper::ServiceMns()
+{
+ assert(NULL != lld);
+ uint16_t wLen;
+ while( 0 != ( wLen = lld->DataAvailable() ) )
+ {
+ if (NULL != pMnsInterface)
+ {
+ Mns_Lld_RxMsg_t *pRxMsg = pMnsInterface->rx_allocate_fptr( pMnsInst, wLen );
+ if( pRxMsg )
+ {
+ if (wLen != lld->Read( pRxMsg->data_ptr, wLen ))
+ ConsolePrintf( PRIO_ERROR, RED"! LLD read error"RESETCOLOR"\n" ); //Must not happen
+ pRxMsg->data_size = wLen;
+ pMnsInterface->rx_receive_fptr( pMnsInst, pRxMsg );
+ Mnsl_Service( &mnsl );
+ }
+ else
+ ConsolePrintf( PRIO_ERROR, RED"! out of message memory"RESETCOLOR"\n" );
+ }
+ }
+ Mnsl_Service( &mnsl );
+}
+
+void CISNetServiceWrapper::AddListener(IISNetServiceWrapperCB *rcvListener)
+{
+ wrapperCB = rcvListener;
+}
+
+bool CISNetServiceWrapper::SendMostMessage(CISMostMsg *msg)
+{
+ assert(NULL != msg);
+ assert(msg->IsValid);
+
+ CTransceiver *tr = NULL;
+
+ if (0x1 == msg->TargetAddress || 0x100 == msg->TargetAddress)
+ tr = icm_inst_ptr;
+ else if (0x0 == msg->FBlock || 0x1 == msg->FBlock)
+ tr = rcm_inst_ptr;
+ else
+ tr = mcm_inst_ptr;
+
+ Msg_MostTel_t *tel = Trcv_TxAllocateMsg( tr, msg->PayloadLen );
+ if( NULL == tel )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Trcv_TxAllocateMsg failed. Len:"\
+ " %u, Message-Type=%s"RESETCOLOR"\n", msg->PayloadLen,
+ (tr == icm_inst_ptr ? "ICM" : tr == rcm_inst_ptr ? "RCM" : "MCM"));
+ return false;
+ }
+ tel->source_addr = msg->SourceAddress;
+ tel->destination_addr = msg->TargetAddress;
+ tel->id.fblock_id = msg->FBlock;
+ tel->id.function_id = msg->Func;
+ tel->id.instance_id = msg->Inst;
+ tel->id.op_type = (Mns_OpType_t)msg->OpType;
+ tel->tel.tel_len = msg->PayloadLen;
+ tel->tel.tel_id = 0;
+ if (0 != msg->PayloadLen)
+ {
+ if (NULL != tel->tel.tel_data_ptr)
+ {
+ memcpy(tel->tel.tel_data_ptr, msg->Payload, msg->PayloadLen);
+ } else {
+ ConsolePrintf(PRIO_ERROR, RED"CISNetServiceWrapper::SendMostMessage,"\
+ " packet has NULL pointer payload"RESETCOLOR"\n");
+ Trcv_TxReleaseMsg(tel);
+ return false;
+ }
+ }
+ Trcv_TxSendMsgExt( tr, tel, OnTransmissionStatus, NULL );
+ return true;
+}
+
+void CISNetServiceWrapper::Unsynchronize()
+{
+ Mnsl_Unsynchronize( &mnsl, true );
+}
+
+void CISNetServiceWrapper::OnReadThreadEnd(CIndustrialStackLld *lld)
+{
+ if (NULL != wrapperCB)
+ wrapperCB->OnControlReadEnd();
+}
+
+void CISNetServiceWrapper::OnCtrlTxTransmit( Mns_Lld_TxMsg_t *msg_ptr)
+{
+ assert(NULL != msg_ptr);
+ assert(NULL != pMnsInterface);
+ if( msg_ptr && pMnsInterface )
+ {
+ assert(NULL != lld);
+ Mns_Mem_Buffer_t *pMemBuf;
+#define MAX_DATA_LEN 72
+ uint8_t data[MAX_DATA_LEN];
+ uint8_t *pW = data;
+ for( pMemBuf = msg_ptr->memory_ptr; pMemBuf != NULL;
+ pMemBuf = pMemBuf->next_buffer_ptr )
+ {
+ if( pW + pMemBuf->data_size >= data + MAX_DATA_LEN )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"invalid size"RESETCOLOR"\n" );
+ return;
+ }
+ memcpy( pW, pMemBuf->data_ptr, pMemBuf->data_size );
+ pW += pMemBuf->data_size;
+ }
+
+ if( !lld->Write( pW - data, data ) )
+ {
+ if (!inicWriteError)
+ {
+ inicWriteError = true;
+ ConsolePrintf( PRIO_ERROR, RED"! Unable to write to INIC!"RESETCOLOR"\n" );
+ }
+ }
+ else inicWriteError = false;
+
+ pMnsInterface->tx_release_fptr( pMnsInst, msg_ptr );
+ }
+}
+
+void CISNetServiceWrapper::OnMnslEvent( Mnsl_Event_t event_code )
+{
+ bool oldSyncState = isSynced;
+ switch( event_code )
+ {
+ case MNSL_EVENT_SYNC_COMPLETE:
+ isSynced = true;
+ ConsolePrintf( PRIO_MEDIUM, "MNSL Event Callback notifies: MNSL_EVENT_SYNC_COMPLETE\n" );
+ break;
+ case MNSL_EVENT_SYNC_FAILED:
+ isSynced = false;
+ ConsolePrintf( PRIO_ERROR, YELLOW"MNSL Event Callback notifies: MNSL_EVENT_SYNC_FAILED" \
+ ", retrying..\nMake sure that local INIC runs Firmware V2.3.0 or later!"RESETCOLOR"\n" );
+ Mnsl_Synchronize( &mnsl );
+ return; /* Do not report the event */
+ case MNSL_EVENT_SYNC_LOST:
+ isSynced = false;
+ ConsolePrintf( PRIO_ERROR, "MNSL Event Callback notifies: MNSL_EVENT_SYNC_LOST\n" );
+ break;
+ case MNSL_EVENT_UNSYNC_COMPLETE:
+ isSynced = false;
+ ConsolePrintf( PRIO_MEDIUM, YELLOW"MNSL Event Callback notifies: MNSL_EVENT_UNSYNC_COMPLETE, syncing again.."RESETCOLOR"\n" );
+ Mnsl_Synchronize( &mnsl );
+ return; /* Do not report the event */
+ case MNSL_EVENT_UNSYNC_FAILED:
+ isSynced = false;
+ ConsolePrintf( PRIO_ERROR, RED"MNSL Event Callback notifies: MNSL_EVENT_UNSYNC_FAILED"RESETCOLOR"\n" );
+ Mnsl_Synchronize( &mnsl );
+ break;
+ default:
+ ConsolePrintf( PRIO_ERROR, "MNSL Event Callback notifies: UNKNOWN CODE\n" );
+ break;
+ }
+ if (NULL != wrapperCB && oldSyncState != isSynced)
+ {
+ wrapperCB->OnSyncStateChanged(isSynced);
+ }
+}
+
+void CISNetServiceWrapper::OnMessage( Msg_MostTel_t *pRx, CTransceiver *pTr )
+{
+ assert(NULL != pRx);
+ assert(pRx->tel.tel_len <= MAX_PAYLOAD_SIZE);
+ if (NULL == wrapperCB)
+ return;
+ CISMostMsg msg;
+ msg.IsValid = true;
+ msg.SourceAddress = pRx->source_addr;
+ msg.TargetAddress = pRx->destination_addr;
+ msg.FBlock = pRx->id.fblock_id;
+ msg.Func = pRx->id.function_id;
+ msg.Inst = pRx->id.instance_id;
+ msg.OpType = (CISOpType_t) pRx->id.op_type;
+ msg.PayloadLen = pRx->tel.tel_len;
+ memcpy(msg.Payload, pRx->tel.tel_data_ptr, msg.PayloadLen);
+ Trcv_RxReleaseMsg(pTr, pRx);
+ wrapperCB->OnReceivedMostMessage(&msg);
+}
+
+/*----------------------------------------
+ * Private helper functions and C wrapper:
+ *----------------------------------------
+ */
+static bool CheckMnswPointer(void *inst_ptr, const char *functionName)
+{
+ if( NULL == inst_ptr || MNSW_TESTPATTERN != ( ( CISNetServiceWrapper * )inst_ptr )->testPattern )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Parameter bug in %s"RESETCOLOR"\n", functionName );
+ assert(false);
+ return true;
+ }
+ return false;
+}
+static void Lld_CtrlStartC( Mns_Lld_Api_t *callbacks_ptr, void *ns_ptr, void *inst_ptr )
+{
+ if (CheckMnswPointer(inst_ptr, "Lld_CtrlStart")) return;
+ CISNetServiceWrapper *mnsw = ( CISNetServiceWrapper * )inst_ptr;
+ mnsw->pMnsInterface = callbacks_ptr;
+ mnsw->pMnsInst = ns_ptr;
+}
+static void Lld_CtrlStopC( void *inst_ptr )
+{
+ if (CheckMnswPointer(inst_ptr, "Lld_CtrlStop")) return;
+ CISNetServiceWrapper *mnsw = ( CISNetServiceWrapper * )inst_ptr;
+ mnsw->pMnsInterface = 0;
+ mnsw->pMnsInst = 0;
+}
+static void Lld_CtrlTxTransmitC( Mns_Lld_TxMsg_t *msg_ptr, void *inst_ptr )
+{
+ if (CheckMnswPointer(inst_ptr, "Lld_CtrlTxTransmit")) return;
+ CISNetServiceWrapper *mnsw = ( CISNetServiceWrapper * )inst_ptr;
+ mnsw->OnCtrlTxTransmit(msg_ptr);
+}
+static void Lld_CtrlRxMsgAvailableC( void *inst_ptr )
+{
+ //Unused
+}
+static uint16_t GetTickCountWordC()
+{
+ return GetTickCountWord();
+}
+static void OnMnslEventC( Mnsl_Event_t event_code, void *inst_ptr )
+{
+ if (CheckMnswPointer(inst_ptr, "OnMnslEvent")) return;
+ CISNetServiceWrapper *mnsw = ( CISNetServiceWrapper * )inst_ptr;
+ mnsw->OnMnslEvent(event_code);
+}
+static void OnMnslServiceC( void *inst_ptr )
+{
+ //Unused
+}
+static void *OnMnslAmsAllocMemC( void *inst_ptr, uint16_t mem_size, Mns_Ams_MemUsage_t type, void** custom_info_pptr )
+{
+ if( 0 == mem_size )
+ return NULL;
+ return calloc( mem_size, 1 );
+}
+static void OnMnslAmsFreeMemC( void *inst_ptr, void *mem_ptr, Mns_Ams_MemUsage_t type, void* custom_info_ptr )
+{
+ if( NULL != mem_ptr )
+ free( mem_ptr );
+}
+static void OnIcmRx( void *inst_ptr, Msg_MostTel_t *pRx )
+{
+ if (CheckMnswPointer(inst_ptr, "OnIcmRx")) return;
+ CISNetServiceWrapper *mnsw = ( CISNetServiceWrapper * )inst_ptr;
+ mnsw->OnMessage(pRx, mnsw->icm_inst_ptr);
+}
+static void OnRcmRx( void *inst_ptr, Msg_MostTel_t *pRx )
+{
+ if (CheckMnswPointer(inst_ptr, "OnRcmRx")) return;
+ CISNetServiceWrapper *mnsw = ( CISNetServiceWrapper * )inst_ptr;
+ mnsw->OnMessage(pRx, mnsw->rcm_inst_ptr);
+}
+static void OnMcmRx( void *inst_ptr, Msg_MostTel_t *pRx )
+{
+ if (CheckMnswPointer(inst_ptr, "OnMcmRx")) return;
+ CISNetServiceWrapper *mnsw = ( CISNetServiceWrapper * )inst_ptr;
+ mnsw->OnMessage(pRx, mnsw->mcm_inst_ptr);
+}
+
+static void OnTransmissionStatus(void *self, Msg_MostTel_t *tel_ptr, Mns_MsgTxStatus_t status)
+{
+ if (MNS_MSG_STAT_OK != status)
+ {
+ ConsolePrintf(PRIO_ERROR, RED"Transmission failed for addr=0x%X FBlock=0x%X " \
+ "Function=0x%X, error-code=0x%X"RESETCOLOR"\n", tel_ptr->destination_addr,
+ tel_ptr->id.fblock_id, tel_ptr->id.function_id, status);
+ }
+ Trcv_TxReleaseMsg(tel_ptr);
+}
+
+#define TRACE_BUFFER_SZ 200
+#include <stdarg.h>
+#include <stdio.h>
+void My_TraceInfo(uint8_t mns_inst_id, const char module_str[], const char entry_str[], uint16_t vargs_cnt, ...)
+{
+ char_t outbuf[TRACE_BUFFER_SZ];
+ va_list argptr;
+ uint16_t timestamp = GetTickCountWord();
+ va_start(argptr, vargs_cnt);
+ vsprintf(outbuf, entry_str, argptr);
+ va_end(argptr);
+ ConsolePrintf(PRIO_HIGH, YELLOW"[%u] | %u | Info | %s | %s"RESETCOLOR"\n", mns_inst_id, timestamp, module_str, outbuf);
+}
+
+void My_TraceError(uint8_t mns_inst_id, const char module_str[], const char entry_str[], uint16_t vargs_cnt, ...)
+{
+ char_t outbuf[TRACE_BUFFER_SZ];
+ va_list argptr;
+ uint16_t timestamp = GetTickCountWord();
+ va_start(argptr, vargs_cnt);
+ vsprintf(outbuf, entry_str, argptr);
+ va_end(argptr);
+ ConsolePrintf(PRIO_ERROR, RED"[%u] | %u | Error | %s | %s"RESETCOLOR"\n", mns_inst_id, timestamp, module_str, outbuf);
+}
diff --git a/Src/Network/IndustrialStack_MNS.h b/Src/Network/IndustrialStack_MNS.h
new file mode 100644
index 0000000..7cb28ee
--- /dev/null
+++ b/Src/Network/IndustrialStack_MNS.h
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CIndustrialStack class (NetService part).
+ */
+/*----------------------------------------------------------*/
+
+#ifndef INDUSTRIAL_STACK_MNS_H
+#define INDUSTRIAL_STACK_MNS_H
+
+#include <assert.h>
+#include "IndustrialStack_Types.h"
+#include "IndustrialStack_LLD.h"
+#include "mns_types_cfg.h"
+#include "mnsl.h"
+
+#define MNSW_TESTPATTERN ((uint32_t)0xA1B2C3D4)
+
+class IISNetServiceWrapperCB
+{
+public:
+ virtual void OnReceivedMostMessage(CISMostMsg *rcvMessage) = 0;
+ virtual void OnSyncStateChanged(bool isSynced) = 0;
+ virtual void OnControlReadEnd() = 0;
+};
+
+class CISNetServiceWrapper : public CIndustrialStackLldCB
+{
+public:
+ const uint32_t testPattern;
+ bool inicWriteError;
+ Mns_Lld_Api_t *pMnsInterface;
+ void *pMnsInst;
+ CTransceiver *icm_inst_ptr;
+ CTransceiver *rcm_inst_ptr;
+ CTransceiver *mcm_inst_ptr;
+private:
+ CMnsl mnsl;
+ Mns_Lld_Callbacks_t pLldCb;
+ bool isSynced;
+ IISNetServiceWrapperCB *wrapperCB;
+ CIndustrialStackLld *lld;
+
+public:
+ CISNetServiceWrapper(uint8_t deviceApi, int controlRxHandle, int controlTxHandle);
+ virtual ~CISNetServiceWrapper();
+ void ServiceMns();
+ void AddListener(IISNetServiceWrapperCB *rcvListener);
+
+ bool SendMostMessage(CISMostMsg *sndMessage);
+ void Unsynchronize();
+
+public:
+ //Will be called from LLD, do not call directly
+ virtual void OnReadThreadEnd(CIndustrialStackLld *lld);
+ //All this functions will be called by the C wrappers, do not call them directly
+ void OnCtrlTxTransmit( Mns_Lld_TxMsg_t *msg_ptr);
+ void OnMnslEvent( Mnsl_Event_t event_code );
+ void OnMessage( Msg_MostTel_t *pRx, CTransceiver *pTr );
+};
+
+#endif //INDUSTRIAL_STACK_MNS_H
diff --git a/Src/Network/IndustrialStack_Types.h b/Src/Network/IndustrialStack_Types.h
new file mode 100644
index 0000000..21bba51
--- /dev/null
+++ b/Src/Network/IndustrialStack_Types.h
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CIndustrialStack class (type defnitions and common classes).
+ */
+/*----------------------------------------------------------*/
+
+#ifndef INDUSTRIAL_STACK_TYPES_H
+#define INDUSTRIAL_STACK_TYPES_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include "SafeVector.h"
+typedef enum
+{
+ ISReturn_NoChange,
+ ISReturn_Success,
+ ISReturn_Failure,
+ ISReturn_Timeout
+} ISReturn_t;
+
+typedef enum
+{
+ CISOpType_INVALID = 0xFF,
+ CISOpType_SET = 0x0,
+ CISOpType_GET = 0x1,
+ CISOpType_SETGET = 0x2,
+ CISOpType_INC = 0x3,
+ CISOpType_DEC = 0x4,
+ CISOpType_GETINTERFACE = 0x5,
+ CISOpType_STATUS = 0xC,
+ CISOpType_INTERFACE = 0xE,
+ CISOpType_ERROR = 0xF,
+ CISOpType_START = 0x0,
+ CISOpType_ABORT = 0x1,
+ CISOpType_STARTRESULT = 0x2,
+ CISOpType_STARTRESULTACK = 0x6,
+ CISOpType_ABORTACK = 0x7,
+ CISOpType_STARTACK = 0x8,
+ CISOpType_ERRORACK = 0x9,
+ CISOpType_PROCESSINGACK = 0xA,
+ CISOpType_PROCESSING = 0xB,
+ CISOpType_RESULT = 0xC,
+ CISOpType_RESULTACK = 0xD,
+ CISOpType_REPORTS = 0x9
+} CISOpType_t;
+
+class CIndustrialStack;
+class IISElement;
+class IISElementCallback;
+class CISWaitElement;
+class CISMostMsg;
+class CSInternalEvent;
+class CISSendMostMsgElement;
+class CISDeviceQueue;
+class CIndustrialStackLldCB;
+class CV1_OnMostRx;
+class CV2_OnMostRx;
+class CV3_OnMostRx;
+
+class IISElement
+{
+private:
+ int32_t refCount;
+public:
+ const char *ElementName;
+ IISElementCallback *Callback;
+ IISElement() : refCount(1), ElementName("Not set"), Callback(NULL) { }
+ virtual ~IISElement() {}
+
+ virtual ISReturn_t Service(CIndustrialStack *iStack, uint32_t time) = 0;
+ virtual ISReturn_t OnMostMessage(CIndustrialStack *iStack, CISMostMsg *rcvMessage) = 0;
+
+ void AddReference()
+ {
+ ++refCount;
+ }
+
+ void RemoveReference()
+ {
+ if( 0 == --refCount )
+ delete this;
+ }
+};
+
+class CISMostMsg
+{
+#define MAX_PAYLOAD_SIZE 45
+public:
+ bool IsValid;
+ uint32_t SourceAddress;
+ uint32_t TargetAddress;
+ uint32_t FBlock;
+ uint32_t Func;
+ uint32_t Inst;
+ CISOpType_t OpType;
+ uint32_t PayloadLen;
+ uint8_t Payload[MAX_PAYLOAD_SIZE];
+
+ CISMostMsg() : IsValid(false), SourceAddress(0xFFFFFFFF), TargetAddress(0xFFFFFFFF),
+ FBlock(0xFFFFFFFF), Func(0xFFFFFFFF), Inst(0xFFFFFFFF),
+ OpType(CISOpType_INVALID), PayloadLen(0)
+ { }
+
+ void DeepCopy(CISMostMsg *msg)
+ {
+ IsValid = msg->IsValid;
+ SourceAddress = msg->SourceAddress;
+ TargetAddress = msg->TargetAddress;
+ FBlock = msg->FBlock;
+ Func = msg->Func;
+ Inst = msg->Inst;
+ OpType = msg->OpType;
+ PayloadLen = msg->PayloadLen;
+ memcpy(Payload, msg->Payload, PayloadLen);
+ }
+};
+
+class IISElementCallback
+{
+public:
+ virtual void ElementProcessed(CIndustrialStack *iStack, ISReturn_t result, IISElement *element) = 0;
+};
+
+class CISDeviceQueue
+{
+private:
+ uint16_t nodeAddress;
+public:
+ CSafeVector<IISElement *> elements;
+
+ CISDeviceQueue(uint16_t address) : nodeAddress(address) { }
+ uint16_t GetNodeAddress() { return nodeAddress; }
+};
+
+#endif //INDUSTRIAL_STACK_TYPES_H \ No newline at end of file
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" );
+}
diff --git a/Src/Network/Network.h b/Src/Network/Network.h
new file mode 100644
index 0000000..749e903
--- /dev/null
+++ b/Src/Network/Network.h
@@ -0,0 +1,498 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CNetworkListner class.
+ */
+/*----------------------------------------------------------*/
+#ifndef _NETWORK_H_
+#define _NETWORK_H_
+
+#include "SafeVector.h"
+#include "Types.h"
+#include "Thread.h"
+#include "MacAddr.h"
+#include "NetworkDevice.h"
+#include "NetworkDeviceListener.h"
+#include "VodXml.h"
+
+/*----------------------------------------------------------*/
+/*! \brief CNetworkListner class shall be derived from classes, which want them self to be registered as callback to the CNetwork class.
+ */
+/*----------------------------------------------------------*/
+class CNetworkListner
+{
+public:
+ /*----------------------------------------------------------*/
+ /*! \brief This callback method is called whenever there is a new channel information available.
+ * \note In order to be informed about this event, derive this class, implement this method and register the class with AddListener method of CNetwork class.
+ * \param mostInstance - The instance number of the MOST bus. If the server device has more then one physical MOST devices, each ring
+ * is identified by a unique id starting with 0 for the first MOST instance.
+ * \param available - true, if the network is fully usable. false, otherwise.
+ * \param maxPos - The amount of devices found in the network (inclusive master)
+ * \param packetBW - Amount of bytes reserved for Ethernet data (multiple with 48000 to get Byte/s)
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnNetworkState( uint8_t mostInstance, bool available, uint8_t maxPos, uint16_t packetBW );
+
+ /*----------------------------------------------------------*/
+ /*! \brief This callback method is called whenever there is a new channel information available.
+ * \note In order to be informed about this event, derive this class, implement this method and register the class with AddListener method of CNetwork class.
+ * \param macAddr - The MAC address identifying the device unique.
+ * \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 channelId - The channel identifier as specified in the XML file, given by "LoadConfig"-method of CNetwork class.
+ * \param mostInstance - The MOST ring instance, starting with 0 for the first MOST ring.
+ * \param dataType - The MOST data used by this channel.
+ * \param reservedBandwidth - The reserved MOST bandwidth in bytes for this channel.
+ * is identified by a unique id starting with 0 for the first MOST instance.
+ * \param isSourceDevice - true, if this device acts as source. false, if this device acts as sink.
+ * \param inSocketCreated - true, if the in-socket of the connection was created. false, there is no in-socket available at the moment.
+ * \param outSocketCreated - true, if the out-socket of the connection was created. false, there is no out-socket available at the moment.
+ * \param socketsConnected - true, if the in- and the out-socket are connected.
+ * \param splittedOffset - If this socket is a splitted / combined socket, this value holds the offset in byte. -1 if this is a normal socket.
+ * \param splittedMaxBandwidth - If this socket is a splitted / combined socket, this value holds the maximum bandwidth of all splitted sockets in byte. -1 if this is a normal socket.
+ * \param bufferSize - The amount of bytes reserved for this channel in Driver. If no buffers were allocated, this value is -1.
+ * \param packetsPerXactconst, This is USB specific. It describes how many sub-frames are concatenated into a single USB microframe.
+ * \param deviceName - The name of the Linux character device. May be NULL if the device is a remote device.
+ */
+ /*----------------------------------------------------------*/
+ 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 );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief This callback method is called whenever a channel has become unavailable.
+ * \note In order to be informed about this event, derive this class, implement this method and register the class with AddListener method of CNetwork class.
+ * \param macAddr - The MAC address identifying the device unique.
+ * \param channelId - The channel identifier as specified in the XML file, given by "LoadConfig"-method of CNetwork class.
+ * \param mostInstance - The instance number of the MOST bus. If the server device has more then one physical MOST devices, each ring
+ * is identified by a unique id starting with 0 for the first MOST instance.
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnChannelUnavailable( CMacAddr *macAddr, TChannelId channelId, uint8_t mostInstance );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief This callback method is called whenever a MOST control message was sent or received.
+ * \note In order to be informed about this event, derive this class, implement this method and register the class with AddListener method of CNetwork class.
+ * \note The user may interpret the data and sent a corresponding MOST control message via CNetwork::SendMostControlMessage.
+ * \param devInst - The MOST ring instance, starting with 0 for the first MOST ring.
+ * \param sourceAddr - The MOST source address (may be not accurate)
+ * \param targetAddr - The MOST target address
+ * \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.
+ */
+ /*----------------------------------------------------------*/
+ 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 );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when a Ring Break Diagnosis Result was received.
+ * \param devInst - The MOST ring instance, starting with 0 for the first MOST ring.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \praram result - The ring break diagnosis result
+ * \param position - Relative position to the ring break.
+ * \param status - Gives information about the activity state.
+ * \param id - The RBD identifier as configured in config string.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnRingBreakDiagnosisResultV3( uint8_t devInst, uint16_t nodeAddress, uint8_t result,
+ uint8_t position, uint8_t status, uint16_t id );
+};
+
+/*----------------------------------------------------------*/
+/*! \brief CNetwork represents the main controlling class, which opens and setup MOST connections.
+*/
+/*----------------------------------------------------------*/
+class CNetwork : public CNetworkDeviceListener, public CThread
+{
+
+private:
+ bool allowNetworkRun;
+ char searchPath[256];
+ CSafeVector<CNetworkListner *> allListeners;
+ static CSafeVector<CNetworkDevice *> allNetworkDevices;
+ CVodXml *vodXml;
+ sem_t vodXmlMutex;
+ uint32_t connectionBitMask;
+ bool promiscuous;
+ uint32_t retryCounter;
+ uint32_t retryExecTime;
+
+ CNetwork();
+
+ void DestroyAllResources( CNetworkDevice *device, uint16_t nodeAddress );
+
+ void CloseAllNetworkDevices();
+
+ void DestroyAllResources();
+
+ void FindNewNetworkDevices();
+
+ void TryToCreateRoute( uint32_t devInstance, bool mostIsTx, void *entry, void *terminal );
+
+ void TryToConnectSockets( uint32_t devInstance, uint16_t nodeAddr, uint32_t channelId );
+
+ void TryToCloseExistingMostConnection( void *inNode, uint32_t channelId, void *outNode, uint32_t outChannelId );
+
+ void RaiseAvailable( void *connection );
+
+ void RaiseUnavailable( void *connection );
+
+ CNetworkDevice *GetNetworkDevice( uint32_t devInstance );
+
+ CMacAddr *SetMacAddress( CNetworkDevice *device, uint32_t devInstance, uint16_t nodeAddress,
+ uint8_t inicApiVersion );
+
+ bool ConnectSourceToSink( void *mostTxNode, void *mostRxNode, uint32_t sourceChannelId, uint32_t sinkChannelId );
+
+ void RaiseUknownConnection( uint32_t devInstance, uint16_t nodeAddress, EPDataType_t dType );
+
+ void ShutdownMost( CNetworkDevice *device );
+
+ void ShutdownMostBecauseOfErrors( CNetworkDevice *device );
+
+ virtual void OnSync( void *source, bool isSynced );
+
+ virtual void 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 );
+
+ virtual void OnNetworkStartupV3( void *source, bool success );
+
+ virtual void OnNetworkShutdownV3( void *source, bool success );
+
+ virtual void OnMostDeviceType( void *source, bool success, uint16_t nodeAddress, uint16_t deviceType );
+
+ virtual void 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 );
+
+ virtual void 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 );
+
+ virtual void 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 );
+
+ virtual void OnConnectSocketsV1( void *source, bool success, uint16_t nodeAddr, uint16_t inSocketHandle,
+ uint16_t outSocketHandle, uint16_t connectionHandle, uint32_t tag );
+
+ virtual void OnDestroySocketV1( void *source, bool success, uint16_t nodeAddr, uint16_t handle, uint32_t tag );
+
+ virtual void OnDisconnectSocketsV1( void *source, bool success, uint16_t nodeAddr, uint16_t handle, uint32_t tag );
+
+ virtual void OnCreateI2SSocketV1( void *source, bool success, uint16_t nodeAddr, EPDirection_t epDir,
+ uint16_t blockWidthI2S, V1I2SPin_t pin, uint16_t socketHandle, uint32_t tag );
+
+ virtual void OnCreateUsbSocketV3( void *source, bool success, uint16_t nodeAddr, EPDataType_t epType,
+ EPDirection_t epDir, uint8_t endPointAddress, uint16_t socketHandle, uint32_t tag );
+
+ virtual void 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 );
+
+ virtual void 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 );
+
+ virtual void 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 );
+
+ virtual void 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 );
+
+ virtual void 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 );
+
+ virtual void 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 );
+
+ virtual void OnConnectSocketsV3( void *source, bool success, uint16_t nodeAddr, EPDataType_t epType,
+ uint16_t inSocketHandle, uint16_t outSocketHandle, uint16_t connectionHandle, uint32_t tag );
+
+ virtual void OnControlChannelReadEnd( void *source );
+
+ virtual void 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 );
+
+ virtual void OnRbdResultV3( void *source, uint16_t nodeAddress, uint8_t result, uint8_t position,
+ uint8_t status, uint16_t id );
+
+ virtual void 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 );
+
+ virtual void OnConfigureI2SPortV3( void *source, bool success, uint16_t nodeAddr, uint8_t portInstance,
+ V3I2SPortOption_t option, V3I2SClockMode_t mode, V3I2SDelayMode_t delay, uint32_t tag );
+
+ virtual void OnCreateI2SPortV3( void *source, bool success, uint16_t nodeAddr, uint8_t portInstance,
+ V3I2SPortSpeed_t clock, V3I2SAlignment_t align, uint32_t tag );
+
+ virtual void 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 );
+public:
+ /*----------------------------------------------------------*/
+ /*! \brief Destructor of CNetwork.
+ */
+ /*----------------------------------------------------------*/
+ virtual ~CNetwork();
+
+
+
+ //Singleton pattern, there can only be one manager
+ /*----------------------------------------------------------*/
+ /*! \brief Gets the singleton instance of CNetwork (Only one object).
+ * \return Pointer to the singleton object.
+ */
+ /*----------------------------------------------------------*/
+ static CNetwork *GetInstance( void );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Registers the given CNetworkListener to this component.
+ * If there are events, all registered listeners will be called back.
+ * \note Multiple listerners are supported.
+ * \param listener- Class derivating CNetworkListener base class. This class will be called back on events.
+ */
+ /*----------------------------------------------------------*/
+ void AddListener( CNetworkListner *listener );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Deregisters the given CNetworkListener from this component.
+ * The given object will no longer be called back.
+ * \param listener- Class derivating CNetworkListener base class. This class will not be called after this method call.
+ */
+ /*----------------------------------------------------------*/
+ void RemoveListener( CNetworkListner *listener );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Enables or Disables the promiscuous mode on MEP channel. If enabled, tools like Wireshark will capture every packet.
+ * \param enabled - true, promiscuous mode. false, perfect match filter with multicast and broadcast enabled.
+ */
+ /*----------------------------------------------------------*/
+ void SetPromiscuousMode( bool enabled );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Loads a XML file holding information about connections and devices.
+ * \param szConfigXml - string holding only the filename to the XML file.
+ * \note This method tries to extract the search path from the given string. Therefor it must start with '/'.
+ * \note The given string will be modified by this method. Don't use it anymore after wise!
+ * \return true, if successful, false otherwise
+ */
+ /*----------------------------------------------------------*/
+ bool LoadConfig( char *szConfigXml );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Loads a XML file holding information about connections and devices.
+ * \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 successful, false otherwise
+ */
+ /*----------------------------------------------------------*/
+ bool LoadConfig( const char *szConfigXml, const char *szSearchPath );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Checks if there are pending actions enqueued.
+ * \note This method blocks, until the result (true / false is reported by the subprocess).
+ * \return true, when there are pending actions in the queue. false, otherwise
+ */
+ /*----------------------------------------------------------*/
+ bool ActionsPending();
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Connects a source to sink according to the configuration of the XML file, provided by LoadConfig method.
+ * \param SourceMacAddr - The MAC address of the source device, reported by the OnChannelAvailable callback method.
+ * \param SourceChannelId - The channel identifier of the source as specified in the XML file and reported by
+ * the OnChannelAvailable callback method.
+ * \param SinkMacAddr - The MAC address of the sink device, reported by the OnChannelAvailable callback method.
+ * \param SourceChannelId - The channel identifier of the sink as specified in the XML file and reported by
+ * the OnChannelAvailable callback method.
+ * \return true, if succesful. false, otherwise
+ */
+ /*----------------------------------------------------------*/
+ bool ConnectSourceToSink( CMacAddr *SourceMacAddr, TChannelId SourceChannelId, CMacAddr *SinkMacAddr,
+ TChannelId SinkChannelId );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves the amount of connected INIC nodes.
+ * \return The amount of local connected INIC nodes.
+ */
+ /*----------------------------------------------------------*/
+ uint8_t GetAmountOfLocalNodes();
+
+
+ /*----------------------------------------------------------*/
+ /*! \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 );
+
+
+ /*----------------------------------------------------------*/
+ /*! \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 );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Executes a given XML script by it's filename and MOST target address
+ * \param mostInstance - The MOST ring instance, starting with 0 for the first MOST ring
+ * \param targetAddr - The MOST target address (0x100, 0x401, etc..)
+ * \param szFile - Path to the XML file (zero terminated string)
+ */
+ /*----------------------------------------------------------*/
+ bool ExecuteXmlScriptFromFile( TMostInstace mostInstance, uint32_t targetAddr, const char *szFile );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Executes a given XML script by it's filename, device identifier and device instance
+ * \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 szFile - Path to the XML file (zero terminated string)
+ */
+ /*----------------------------------------------------------*/
+ bool ExecuteXmlScriptFromFile( TMostInstace mostInstance, TDeviceId deviceId, uint8_t devInst,
+ const char *szFile );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Executes a given XML script directly by it's content stored in the memory and MOST target address
+ * \param mostInstance - The MOST ring instance, starting with 0 for the first MOST ring
+ * \param targetAddr - The MOST target address (0x100, 0x401, etc..)
+ * \param szBuffer - The Buffer containing the XML script
+ * \param nBufferLen - The length of the XML script stored in szBuffer
+ */
+ /*----------------------------------------------------------*/
+ bool ExecuteXmlScriptFromMemory( TMostInstace mostInstance, uint32_t targetAddr, const char *szBuffer,
+ uint32_t nBufferLen );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Executes a given XML script by it's filename, device identifier and device instance
+ * \param mostInstance - The MOST ring instance, starting with 0 for the first MOST ring
+ * \param targetAddr - The MOST target address (0x100, 0x401, etc..)
+ * \param szBuffer - The Buffer containing the XML script
+ * \param nBufferLen - The length of the XML script stored in szBuffer
+ */
+ /*----------------------------------------------------------*/
+ bool ExecuteXmlScriptFromMemory( TMostInstace mostInstance, TDeviceId deviceId, uint8_t devInst,
+ const char *szBuffer, uint32_t nBufferLen );
+
+ /*!
+ * \brief Storage class for channel related informations. This class will be returned by
+ * the CVodXml class.
+ */
+ typedef struct
+ {
+ /// Determines the device type as specified in the configuration XML file and found in the group address configuration.
+ uint32_t deviceType;
+
+ /// instance number of the device found in the network
+ uint32_t instance;
+
+ /// Determines the used channel id, as specified in the configuration XML file.
+ uint32_t channelId;
+ } Route_t;
+
+ /*----------------------------------------------------------*/
+ /*! \brief Sends the given Control Message out to the given MOST ring.
+ * \param pInRoute - Pointer to the route to search the counter part of.
+ * \param pOutRouteArray - Pointer to pointer, which then the result array will be stored, maybe NULL!
+ * \return The array length of pOutRouteArray, maybe 0!
+ * \note The pOutRouteArray must be freed by the user after usage!
+ */
+ /*----------------------------------------------------------*/
+ uint32_t GetCounterPartOfRoute( const Route_t *pInRoute, Route_t **pOutRouteArray );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves the stored result of the Ring Break Diagnosis
+ * \param mostInstance - The MOST ring instance, starting with 0 for the first MOST ring
+ * \param targetAddr - The MOST target address (0x100, 0x401, etc..)
+ * \return true, if successful, false otherwise
+ */
+ /*----------------------------------------------------------*/
+ bool GetRingBreakDiagnosisResult( TMostInstace mostInstance, uint32_t targetAddr );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Enables or disables all MOST rings.
+ * \note This is thought for debug reasons only. Normally this method must not be called.
+ * \param enabled - TRUE, all MOST rings will start up. FALSE, all MOST rings will shutdown.
+ */
+ /*----------------------------------------------------------*/
+ void EnableMost(bool enabled);
+
+ /*----------------------------------------------------------*/
+ /*! \brief Function of background thread.
+ * \note Never call this method. It is used by internal threads.
+ */
+ /*----------------------------------------------------------*/
+ void Run();
+
+};
+
+
+#endif
diff --git a/Src/Network/NetworkDevice.cpp b/Src/Network/NetworkDevice.cpp
new file mode 100644
index 0000000..5308215
--- /dev/null
+++ b/Src/Network/NetworkDevice.cpp
@@ -0,0 +1,903 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include "NetworkDevice.h"
+#include "DriverConfiguration.h"
+#include "Board.h"
+#include "ScriptXml.h"
+#include "IndustrialStack_ApiV1.h"
+#include "IndustrialStack_ApiV3.h"
+#include "IndustrialStack_ApiGeneric.h"
+
+CNetworkDevice::CNetworkDevice( uint8_t index, uint8_t api, bool master, uint32_t asyncBW, bool promiscuousMode ) :
+CThread( "CNetworkDevice", false ), promiscuous( promiscuousMode ), netState( NetworkState_Unknown ),
+ pInic( NULL ), pScriptMemoryArea( NULL ), isRunning( false ),
+ isActionPending( false ), deviceIndex( index ), deviceApi( api ),
+ isTimingMaster( master ), asyncBandwidth( asyncBW ),
+ controlEndpointRxHandle( -1 ), controlEndpointTxHandle( -1 ),
+ startV3autoForced( 0xFFFF ), startV3packetBW( 0xFFFF )
+{
+ responseToWaitFor[0] = '\0';
+ deviceNameControlRx[0] = '\0';
+ deviceNameControlTx[0] = '\0';
+
+ sem_init( &methodMutex, 0, 0 ); //Mutex, initialized to 0 => sem_wait will block
+}
+
+CNetworkDevice::~CNetworkDevice()
+{
+ Stop();
+ CloseMostControlChannel();
+ if (NULL != iStack)
+ {
+ delete iStack;
+ iStack = NULL;
+ }
+ if (NULL != v1Events)
+ {
+ delete v1Events;
+ v1Events = NULL;
+ }
+ if (NULL != v3Events)
+ {
+ delete v3Events;
+ v3Events = NULL;
+ }
+}
+
+bool CNetworkDevice::OpenDevice( const char *systemNameControlRx, const char *systemNameControlTx,
+ const char *linkNameControlRx, const char *linkNameControlTx )
+{
+ ConsolePrintf( PRIO_LOW, "SYS RX:%s\nSYS TX:%s\nLINK RX:%s\nLINK TX:%s\n", systemNameControlRx,
+ systemNameControlTx, linkNameControlRx, linkNameControlTx );
+
+ CloseMostChannel( systemNameControlRx );
+ CloseMostChannel( systemNameControlTx );
+
+ bool success = ConfigureMostChannel( systemNameControlRx, EP_Control, EPDIR_OUT, 32, 128 );
+
+ if( success )
+ {
+ success = ConfigureMostChannel( systemNameControlTx, EP_Control, EPDIR_IN, 32, 128 );
+ }
+
+ if( success )
+ {
+ success = LinkToCharacterDevice( linkNameControlRx, deviceNameControlRx );
+ }
+
+ if( success )
+ {
+ success = LinkToCharacterDevice( linkNameControlTx, deviceNameControlTx );
+ }
+
+ if( success )
+ {
+ if( OpenMostControlChannel() )
+ {
+ isRunning = true;
+ Start();
+ }
+ else
+ {
+ ConsolePrintf( PRIO_ERROR, RED"MOST control channel startup failed"RESETCOLOR"\n" );
+ }
+
+ }
+ else
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"NetworkDevice: Open device aborted, because of channel configuration issues"RESETCOLOR"\n" );
+ }
+ return success;
+}
+
+bool CNetworkDevice::OpenUsb( uint8_t controlRxEndpointAddress, uint8_t controlTxEndpointAddress )
+{
+ char systemNameControlRx[64];
+ char systemNameControlTx[64];
+ char linkNameControlRx[64];
+ char linkNameControlTx[64];
+ bool success = GetUsbDeviceNames( deviceIndex, controlRxEndpointAddress,
+ deviceNameControlRx, sizeof( deviceNameControlRx ), systemNameControlRx, sizeof( systemNameControlRx ),
+ linkNameControlRx, sizeof( linkNameControlRx ) );
+
+ if( success )
+ success = GetUsbDeviceNames( deviceIndex, controlTxEndpointAddress,
+ deviceNameControlTx, sizeof( deviceNameControlTx ), systemNameControlTx, sizeof( systemNameControlTx ),
+ linkNameControlTx, sizeof( linkNameControlTx ) );
+
+ if( success )
+ success = OpenDevice( systemNameControlRx, systemNameControlTx, linkNameControlRx, linkNameControlTx );
+
+ if( ! success )
+ ConsolePrintf( PRIO_ERROR, RED"NetworkDevice: Failed to open USB device"RESETCOLOR"\n" );
+
+ return success;
+}
+
+bool CNetworkDevice::OpenMlb( uint8_t controlRxChannelAddress, uint8_t controlTxChannelAddress )
+{
+ char systemNameControlRx[64];
+ char systemNameControlTx[64];
+ char linkNameControlRx[64];
+ char linkNameControlTx[64];
+ bool success = GetMlbDeviceNames( deviceIndex, controlRxChannelAddress,
+ deviceNameControlRx, sizeof( deviceNameControlRx ), systemNameControlRx, sizeof( systemNameControlRx ),
+ linkNameControlRx, sizeof( linkNameControlRx ) );
+
+ if( success )
+ success = GetMlbDeviceNames( deviceIndex, controlTxChannelAddress,
+ deviceNameControlTx, sizeof( deviceNameControlTx ), systemNameControlTx, sizeof( systemNameControlTx ),
+ linkNameControlTx, sizeof( linkNameControlTx ) );
+
+ if( success )
+ success = OpenDevice( systemNameControlRx, systemNameControlTx, linkNameControlRx, linkNameControlTx );
+
+ if( ! success )
+ ConsolePrintf( PRIO_ERROR, RED"NetworkDevice: Failed to open MLB device"RESETCOLOR"\n" );
+
+ return success;
+}
+
+bool CNetworkDevice::OpenI2C()
+{
+ char systemNameControlRx[64];
+ char systemNameControlTx[64];
+ char linkNameControlRx[64];
+ char linkNameControlTx[64];
+ bool success = GetI2CDeviceNames( deviceIndex, false, deviceNameControlRx, sizeof( deviceNameControlRx ),
+ systemNameControlRx, sizeof( systemNameControlRx ), linkNameControlRx, sizeof( linkNameControlRx ) );
+
+ if( success )
+ success = GetI2CDeviceNames( deviceIndex, true, deviceNameControlTx, sizeof( deviceNameControlTx ),
+ systemNameControlTx, sizeof( systemNameControlTx ), linkNameControlTx, sizeof( linkNameControlTx ) );
+
+ if( success )
+ success = OpenDevice( systemNameControlRx, systemNameControlTx, linkNameControlRx, linkNameControlTx );
+
+ if( ! success )
+ ConsolePrintf( PRIO_ERROR, RED"NetworkDevice: Failed to open I2C device"RESETCOLOR"\n" );
+
+ return success;
+}
+
+void CNetworkDevice::Close()
+{
+ int32_t timeoutVal = 10; //10 Seconds
+ while( timeoutVal-- > 0 )
+ {
+ if( iStack->ElementsPending() )
+ {
+ ConsolePrintf( PRIO_MEDIUM, "NetworkDevice: Closing delayed, Actions pending..\n" );
+ usleep( 1000000 );
+ }
+ else
+ {
+ break;
+ }
+ }
+ sem_post( &methodMutex );
+ isRunning = false;
+ Stop();
+ for( uint32_t timeout = 0; timeout < 100; timeout++ )
+ {
+ if( !IsThreadRunning() )
+ break;
+ usleep( 10000 );
+ }
+ ConsolePrintf( PRIO_LOW, "NetworkDevice: Closed..\n" );
+}
+
+uint8_t CNetworkDevice::GetDeviceApi()
+{
+ return deviceApi;
+}
+
+NetworkState_t CNetworkDevice::GetNetState()
+{
+ return netState;
+}
+
+void CNetworkDevice::SetNetstate( NetworkState_t newState )
+{
+ netState = newState;
+}
+
+ void CNetworkDevice::SetTimingMaster(bool tm)
+ {
+ isTimingMaster = tm;
+ }
+
+bool CNetworkDevice::IsTimingMaster()
+{
+ return isTimingMaster;
+}
+
+void CNetworkDevice::SetAsyncBandwidth(uint32_t bw)
+{
+ asyncBandwidth = bw;
+}
+
+uint32_t CNetworkDevice::GetAsyncBandwidth()
+{
+ return asyncBandwidth;
+}
+
+bool CNetworkDevice::ActionsPending()
+{
+ if( NULL == iStack || !isRunning )
+ return true;
+ return iStack->ElementsPending();
+}
+
+void CNetworkDevice::ClearAllPendingActions()
+{
+ if( NULL == iStack )
+ return;
+ iStack->ClearAllElements();
+}
+
+void CNetworkDevice::AddListener( CNetworkDeviceListener *listener )
+{
+ allListeners.PushBack( listener );
+}
+
+uint32_t CNetworkDevice::GetAmountOfListners()
+{
+ return allListeners.Size();
+}
+
+CNetworkDeviceListener *CNetworkDevice::GetListener( uint32_t instance )
+{
+ return allListeners[instance];
+}
+
+uint8_t CNetworkDevice::GetDeviceIndex()
+{
+ return deviceIndex;
+}
+
+void CNetworkDevice::ScriptPause( uint32_t timeInMillis )
+{
+ CISWaitElement *waitElement = new CISWaitElement();
+ waitElement->SetTimeout(timeInMillis);
+ iStack->EnqueueElement(0x1, waitElement);
+ waitElement->RemoveReference();
+}
+
+void CNetworkDevice::ExecuteMcmScript( uint16_t nodeAddress, CSciptXml *scriptXml )
+{
+ if( NULL == scriptXml )
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"ExecuteMcmScript failed to retrieve scripts from XML file"RESETCOLOR"\n" );
+ return;
+ }
+ CSafeVector<CScript *> allScripts;
+ if( scriptXml->GetScripts( allScripts ) )
+ {
+ for (uint32_t i = 0; i < allScripts.Size(); i++ )
+ {
+ CScript *script = allScripts[i];
+ if( NULL == script )
+ continue;
+ switch( script->scriptType )
+ {
+ case SCRIPT_MCM_SEND:
+ {
+ CGeneric_SendMostMessage *a = new CGeneric_SendMostMessage(
+ script->payload, script->payloadLength, nodeAddress,
+ script->fblockId, 0, script->functionId, script->opTypeRequest,
+ script->opTypeResponse);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+ break;
+ }
+ case SCRIPT_PAUSE:
+ {
+ CISWaitElement *waitElement = new CISWaitElement();
+ waitElement->SetTimeout(script->pauseInMillis);
+ iStack->EnqueueElement(nodeAddress, waitElement);
+ waitElement->RemoveReference();
+ break;
+ }
+ default:
+ ConsolePrintf( PRIO_ERROR,
+ YELLOW"ExecuteMcmScript ignoring unknown script type:%d"RESETCOLOR"\n",
+ script->scriptType );
+ break;
+ }
+ }
+ }
+ allScripts.RemoveAll(true);
+}
+
+void CNetworkDevice::ExecuteMcmScript( uint16_t nodeAddress, const char *pPathToScriptXml )
+{
+ if( NULL == pPathToScriptXml )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"ExecuteMcmScript (from file) was called with invalid parameter"RESETCOLOR"\n" );
+ return;
+ }
+ ConsolePrintf( PRIO_MEDIUM, "##### Executing MCM script from file: Address:%X '%s'\n", nodeAddress,
+ pPathToScriptXml );
+ CSciptXml *scriptXml = new CSciptXml( pPathToScriptXml );
+ ExecuteMcmScript( nodeAddress, scriptXml );
+}
+
+void CNetworkDevice::ExecuteMcmScript( uint16_t nodeAddress, const char *pStringBuffer, uint32_t bufferLength )
+{
+ if( NULL == pStringBuffer || 0 == bufferLength )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"ExecuteMcmScript (from memory) was called with invalid parameter"RESETCOLOR"\n" );
+ return;
+ }
+ ConsolePrintf( PRIO_MEDIUM, "##### Executing MCM script from memory: Address:%X buffer-len:\n", nodeAddress,
+ bufferLength );
+ CSciptXml *scriptXml = new CSciptXml( pStringBuffer, bufferLength );
+ ExecuteMcmScript( nodeAddress, scriptXml );
+}
+
+void CNetworkDevice::ToggleNotOk()
+{
+ CGeneric_SendConfigOk *a = new CGeneric_SendConfigOk(false);
+ iStack->EnqueueElement(0x3C8, a);
+ a->RemoveReference();
+
+ CGeneric_SendConfigOk *b = new CGeneric_SendConfigOk(true);
+ iStack->EnqueueElement(0x3C8, b);
+ b->RemoveReference();
+}
+
+void CNetworkDevice::GetMacAddress( uint16_t nodeAddress )
+{
+ CGeneric_GetMacAddress *a = new CGeneric_GetMacAddress(nodeAddress);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::GetGroupAddresses( uint8_t maxNodePos )
+{
+ for( uint32_t i = 0x400; maxNodePos != 0xFF && i < 0x400 + ( uint32_t )maxNodePos; i++ )
+ {
+ uint16_t n = ( i == 0x400 ? 1 : i );
+ CGeneric_GetGroupAddress *a = new CGeneric_GetGroupAddress(n);
+ iStack->EnqueueElement(n, a);
+ a->RemoveReference();
+ }
+}
+
+void CNetworkDevice::SetMostMacAddressV1( uint16_t nodeAddress, uint8_t macAddress1, uint8_t macAddress2,
+ uint8_t macAddress3, uint8_t macAddress4, uint8_t macAddress5, uint8_t macAddress6, bool persistent )
+{
+ CV1_ChangeEUI48 *a = new CV1_ChangeEUI48(this, nodeAddress, macAddress1, macAddress2,
+ macAddress3, macAddress4, macAddress5, macAddress6, persistent);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::StartMostV1( bool isTimingMaster, uint16_t packetBandWidth )
+{
+ CV1_NetworkStartup *a = new CV1_NetworkStartup(this, isTimingMaster, packetBandWidth);
+ iStack->EnqueueElement(0x1, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::MostNetworkShutdownV1()
+{
+ CISWaitForPendingElements *w = new CISWaitForPendingElements(0x1);
+ iStack->EnqueueElement(0x1, w);
+ w->RemoveReference();
+
+ CV1_NetworkShutdown *a = new CV1_NetworkShutdown(this);
+ iStack->EnqueueElement(0x1, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::OpenTsiV1( uint16_t nodeAddress, V1TsiPortInstance_t tsiPortId, V1TsiPortMode tsiPortMode )
+{
+ if (V1TsiPortInstanceNotSet == tsiPortId || V1TsiPortModeNotSet == tsiPortMode)
+ return;
+ CV1_TsiPortCreate *a = new CV1_TsiPortCreate(this, nodeAddress, tsiPortId, tsiPortMode);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::CreateTsiSocketV1( uint16_t nodeAddress, V1TsiPortInstance_t portInst,
+ EPDataType_t epType, EPDirection_t epDir,uint16_t blockWidthTsi, uint32_t tag )
+{
+ CV1_TsiSocketCreate *a = new CV1_TsiSocketCreate(this, nodeAddress, portInst,
+ epType, epDir, blockWidthTsi, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::OpenMlbV1( uint16_t nodeAddress, MlbPortSpeed_t mlbSpeed )
+{
+ if( MlbSpeedNotSet == mlbSpeed )
+ return;
+ CV1_MlbPortCreate *a = new CV1_MlbPortCreate(this, nodeAddress, mlbSpeed);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::CreateMlbSocketV1( uint16_t nodeAddress, EPDataType_t epType, EPDirection_t epDir,
+ uint16_t mlbChannelAddress, uint16_t blockWidthMlb, uint32_t tag )
+{
+ CV1_MlbSocketCreate *a = new CV1_MlbSocketCreate(this, nodeAddress, epType, epDir,
+ mlbChannelAddress, blockWidthMlb, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::CreateSplittedMlbSocketV1( uint16_t nodeAddress, EPDataType_t epType, EPDirection_t epDir,
+ uint16_t mlbChannelAddress, uint16_t blockWidthMlb, uint16_t splittedOffset, uint16_t blockWidthCombined,
+ uint32_t tag )
+{
+ CV1_SplittedMlbSocketCreate *a = new CV1_SplittedMlbSocketCreate(this, nodeAddress,
+ epType, epDir, mlbChannelAddress, blockWidthMlb, splittedOffset, blockWidthCombined, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::CreateMostSocketV1( uint16_t nodeAddress, EPDataType_t epType, EPDirection_t epDir,
+ uint16_t connectionLabel, uint16_t blockWidthMost, uint32_t tag )
+{
+ CV1_MostSocketCreate *a = new CV1_MostSocketCreate(this, nodeAddress,
+ epType, epDir, connectionLabel, blockWidthMost, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::ConnectSocketsV1( uint16_t nodeAddress, uint8_t inHandle, uint8_t outHandle, uint32_t tag )
+{
+ CV1_ConnectSockets *a = new CV1_ConnectSockets(this, nodeAddress,
+ inHandle, outHandle, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::DestroySocketV1( uint16_t nodeAddress, uint8_t handle, uint32_t tag )
+{
+ CV1_DestroySocket *a = new CV1_DestroySocket(this, nodeAddress, handle, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::DisconnectSocketsV1( uint16_t nodeAddress, uint8_t handle, uint32_t tag )
+{
+ CV1_DisconnectSockets *a = new CV1_DisconnectSockets(this, nodeAddress, handle, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::OpenStreamPortV1( uint16_t nodeAddress, V1I2SPortClkDriveMode_t portMode,
+ V1I2SStreamingPortMode_t streamPortMode, V1I2SStreamingDataFormat_t format, uint32_t tag )
+{
+ CV1_StreamPortOpen *a = new CV1_StreamPortOpen(this, nodeAddress, portMode, streamPortMode, format, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::CreateStreamSocketV1( uint16_t nodeAddress, EPDirection_t epDir, uint16_t blockWidthI2S,
+ V1I2SPin_t pin, uint32_t tag )
+{
+ CV1_StreamSocketCreate *a = new CV1_StreamSocketCreate(this, nodeAddress, epDir, blockWidthI2S, pin, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::CreateSplittedStreamSocketV1( uint16_t nodeAddress, EPDirection_t epDir, uint16_t blockWidthI2S,
+ uint16_t splittedOffset, uint16_t blockWidthCombined, V1I2SPin_t pin, uint32_t tag )
+{
+ CV1_SplittedStreamSocketCreate *a = new CV1_SplittedStreamSocketCreate(this,
+ nodeAddress, epDir, blockWidthI2S, splittedOffset, blockWidthCombined, pin, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::AttachV3()
+{
+ CV3_DeviceAttach *a = new CV3_DeviceAttach();
+ iStack->EnqueueElement(0x1, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::InicUnsychronizeV3()
+{
+ CISWaitForPendingElements *w = new CISWaitForPendingElements(0x1);
+ iStack->EnqueueElement(0x1, w);
+ w->RemoveReference();
+
+ CV3_Unsynchronize *a = new CV3_Unsynchronize();
+ iStack->EnqueueElement(0x1, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::DeviceSyncV3( uint16_t nodeAddress, bool sync )
+{
+ CV3_DeviceSync *a = new CV3_DeviceSync(nodeAddress, sync);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::MostNetworkStartupV3( uint16_t autoForcedNotAvailable, uint16_t packetBW )
+{
+ startV3autoForced = autoForcedNotAvailable;
+ startV3packetBW = packetBW;
+ CV3_NetworkStartup *a = new CV3_NetworkStartup(this, autoForcedNotAvailable, packetBW);
+ iStack->EnqueueElement(0x1, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::MostNetworkStartupV3()
+{
+ if( 0xFFFF == startV3packetBW )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Repeated MostNetworkStartupV3 was called"\
+ " without calling the overloaded MostNetworkStartupV3 with parameters"\
+ RESETCOLOR"\n" );
+ return;
+ }
+ CV3_NetworkStartup *a = new CV3_NetworkStartup(this, startV3autoForced, startV3packetBW);
+ iStack->EnqueueElement(0x1, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::MostNetworkShutdownV3()
+{
+ CISWaitForPendingElements *w = new CISWaitForPendingElements(0x1);
+ iStack->EnqueueElement(0x1, w);
+ w->RemoveReference();
+
+ CV3_NetworkShutdown *a = new CV3_NetworkShutdown(this);
+ iStack->EnqueueElement(0x1, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::SetMostMacAddressV3( uint16_t nodeAddress, uint8_t macAddress1, uint8_t macAddress2,
+ uint8_t macAddress3, uint8_t macAddress4, uint8_t macAddress5, uint8_t macAddress6 )
+{
+ CV3_MostNetworkConfiguration *a = new CV3_MostNetworkConfiguration(this, nodeAddress, macAddress1, macAddress2,
+ macAddress3, macAddress4, macAddress5, macAddress6, promiscuous);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::OpenMlbV3( uint16_t nodeAddress, MlbPortSpeed_t mlbSpeed )
+{
+ if( MlbSpeedNotSet == mlbSpeed )
+ return;
+ CV3_MlbPortCreate *a = new CV3_MlbPortCreate(this, nodeAddress, mlbSpeed);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::CreateUsbSocketV3( uint16_t nodeAddress, EPDataType_t epType, EPDirection_t epDir,
+ uint8_t endPointAddress, uint16_t packetsPerFrame, uint32_t tag )
+{
+ CV3_UsbSocketCreate *a = new CV3_UsbSocketCreate(this, nodeAddress, epType,
+ epDir, endPointAddress, packetsPerFrame, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::CreateSplittedUsbSocketV3( uint16_t nodeAddress, EPDataType_t epType, EPDirection_t epDir,
+ uint8_t endPointAddress, uint16_t packetsPerFrame, uint16_t bytesPerPacket, uint32_t tag )
+{
+ CV3_SplittedUsbSocketCreate *a = new CV3_SplittedUsbSocketCreate(this, nodeAddress,
+ epType, epDir, endPointAddress, packetsPerFrame, bytesPerPacket, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::CreateMlbSocketV3( uint16_t nodeAddress, uint16_t mlbPortHandle, EPDataType_t epType,
+ EPDirection_t epDir, uint16_t mlbChannelAddress, uint16_t blockwidthMlb, uint32_t tag )
+{
+ CV3_MlbSocketCreate *a = new CV3_MlbSocketCreate(this, nodeAddress, mlbPortHandle,
+ epType, epDir, mlbChannelAddress, blockwidthMlb, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::CreateSplittedMlbSocketV3( uint16_t nodeAddress, uint16_t mlbPortHandle, EPDataType_t epType,
+ EPDirection_t epDir, uint16_t mlbChannelAddress, uint16_t blockwidthMlb, uint16_t bytesPerPacket, uint32_t tag )
+{
+ CV3_SplittedMlbSocketCreate *a = new CV3_SplittedMlbSocketCreate(this, nodeAddress,
+ mlbPortHandle, epType, epDir, mlbChannelAddress, blockwidthMlb, bytesPerPacket, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::CreateMostSocketV3( uint16_t nodeAddress, EPDataType_t epType, EPDirection_t epDir,
+ uint16_t connectionLabel, uint16_t blockwidthMost, uint32_t tag )
+{
+ CV3_MostSocketCreate *a = new CV3_MostSocketCreate(this, nodeAddress, epType,
+ epDir, connectionLabel, blockwidthMost, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::ConnectSocketsV3( uint16_t nodeAddress, EPDataType_t epType, uint16_t inHandle,
+ uint16_t outHandle, uint16_t offset, uint32_t tag )
+{
+ CV3_ConnectSockets *a = new CV3_ConnectSockets(this, nodeAddress, epType,
+ inHandle, outHandle, offset, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::ResourceDestroyV3( uint16_t nodeAddress, uint8_t amountOfHandles, const uint16_t *pHandle,
+ uint32_t tag )
+{
+ CV3_ResourceDestroy *a = new CV3_ResourceDestroy(this, nodeAddress,
+ amountOfHandles, pHandle, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::ConfigureStreamPortV3( uint16_t nodeAddress, uint8_t portInstance, V3I2SPortOption_t option,
+ V3I2SClockMode_t mode, V3I2SDelayMode_t delay, uint32_t tag )
+{
+ CV3_StreamPortConfig *a = new CV3_StreamPortConfig(this, nodeAddress,
+ portInstance, option, mode, delay, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::CreateStreamPortV3( uint16_t nodeAddress, uint8_t portInstance, V3I2SPortSpeed_t clock,
+ V3I2SAlignment_t align, uint32_t tag )
+{
+ CV3_StreamPortCreate *a = new CV3_StreamPortCreate(this, nodeAddress,
+ portInstance, clock, align, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::CreateStreamSocketV3( uint16_t nodeAddress, uint8_t portInstance, EPDirection_t epDir,
+ uint16_t blockWidthI2S, V3I2SPin_t pin, uint32_t tag )
+{
+ CV3_StreamSocketCreate *a = new CV3_StreamSocketCreate(this, nodeAddress,
+ portInstance, epDir, blockWidthI2S, pin, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::CreateSplittedStreamSocketV3( uint16_t nodeAddress, uint8_t portInstance, EPDirection_t epDir,
+ uint16_t blockWidthI2S, V3I2SPin_t pin, uint16_t bytesPerPacket, uint32_t tag )
+{
+ CV3_SplittedStreamSocketCreate *a = new CV3_SplittedStreamSocketCreate(this, nodeAddress,
+ portInstance, epDir, blockWidthI2S, pin, bytesPerPacket, tag);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+void CNetworkDevice::GetRingBreakResultV3( uint16_t nodeAddress, uint32_t tag )
+{
+ CV3_GetRbdResult *a = new CV3_GetRbdResult(nodeAddress);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+bool CNetworkDevice::OpenMostControlChannel( void )
+{
+ bool success = false;
+ for (uint8_t i = 0; !success && i < 10; i++)
+ {
+ if (-1 == controlEndpointRxHandle)
+ controlEndpointRxHandle = open( deviceNameControlRx, O_RDONLY );
+ if (-1 == controlEndpointTxHandle)
+ controlEndpointTxHandle = open( deviceNameControlTx, O_WRONLY );
+ success = (-1 != controlEndpointRxHandle && -1 != controlEndpointTxHandle);
+ if (!success)
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Opened file handles failed TX:%d RX:%d, retrying.."RESETCOLOR"\n", controlEndpointTxHandle, controlEndpointRxHandle);
+ usleep(1000000);
+ }
+ }
+
+ if( success )
+ {
+ iStack = new CIndustrialStack(deviceApi, controlEndpointRxHandle, controlEndpointTxHandle);
+ v1Events = new CV1_OnMostRx(this);
+ v3Events = new CV3_OnMostRx(this);
+ iStack->AddInternalEventListener(this);
+ iStack->AddInternalEventListener(v1Events);
+ iStack->AddInternalEventListener(v3Events);
+ }
+ else
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Failure while opening MOST control channel" \
+ " ('%s' or '%s'), error='%s'"RESETCOLOR"\n"
+ , deviceNameControlRx, deviceNameControlTx, GetErrnoString() );
+ }
+ return success;
+}
+
+void CNetworkDevice::Run( void )
+{
+ iStack->ServiceStack(GetTickCount());
+ usleep( 1000 );
+}
+
+void CNetworkDevice::CloseMostControlChannel( void )
+{
+ close( controlEndpointTxHandle );
+ close( controlEndpointRxHandle );
+ if (NULL != iStack)
+ {
+ delete iStack;
+ iStack = NULL;
+ }
+}
+
+void CNetworkDevice::WaitForIpcResponse( const char *responseMessage )
+{
+ if( isRunning )
+ {
+ strncpy( ( char * )responseToWaitFor, responseMessage, sizeof( responseToWaitFor ) );
+ sem_wait( &methodMutex );
+ responseToWaitFor[0] = '\0';
+ }
+}
+
+bool CNetworkDevice::ConfigureUsbEndpoint( AimType_t aimType, uint8_t endpointAddress, EPDataType_t epType,
+ EPDirection_t epDir, char *deviceName, uint32_t deviceNameBufLen, uint32_t amountOfBuffers, uint32_t bufferSize,
+ uint32_t subbufferSize, uint32_t packetsPerTransaction )
+{
+ char systemName[64];
+ char linkName[64];
+ bool success = GetUsbDeviceNames( deviceIndex, endpointAddress, deviceName, deviceNameBufLen,
+ systemName, sizeof( systemName ), linkName, sizeof( linkName ) );
+ if( !success )
+ return success;
+ CloseMostChannel( systemName );
+ switch( epType )
+ {
+ case EP_Synchron:
+ success = ConfigureSyncChannel( systemName, subbufferSize, packetsPerTransaction );
+ if( success )
+ success = ConfigureMostChannel( systemName, epType, epDir, amountOfBuffers, bufferSize );
+ break;
+ case EP_Isochron:
+ success = ConfigureIsocChannel( systemName, subbufferSize, packetsPerTransaction );
+ if( success )
+ success = ConfigureMostChannel( systemName, epType, epDir, amountOfBuffers, bufferSize );
+ break;
+ default:
+ break;
+ }
+ if( success )
+ {
+ switch( aimType )
+ {
+ case AIM_AUDIO:
+ success = LinkToAudioDevice( linkName, subbufferSize );
+ break;
+ case AIM_V4L:
+ success = LinkToVideoForLinuxDevice( linkName );
+ break;
+ case AIM_CDEV:
+ default:
+ success = LinkToCharacterDevice( linkName, deviceName );
+ break;
+ }
+ }
+ return success;
+}
+
+bool CNetworkDevice::ConfigureUsbEndpoint( uint8_t endpointAddress, EPDataType_t epType, EPDirection_t epDir,
+ char *deviceName, uint32_t deviceNameBufLen, uint32_t amountOfBuffers, uint32_t bufferSize )
+{
+ return ConfigureUsbEndpoint( AIM_CDEV, endpointAddress, epType, epDir, deviceName, deviceNameBufLen,
+ amountOfBuffers, bufferSize, 0, 0 );
+}
+
+bool CNetworkDevice::ConfigureMlbChannel( AimType_t aimType, uint8_t mlbChannelAddress, EPDataType_t epType,
+ EPDirection_t epDir, char *deviceName, uint32_t deviceNameBufLen, uint32_t amountOfBuffers, uint32_t bufferSize,
+ uint32_t subbufferSize, uint32_t packetsPerTransaction )
+{
+ char systemName[64];
+ char linkName[64];
+ bool success = GetMlbDeviceNames( deviceIndex, mlbChannelAddress, deviceName, deviceNameBufLen,
+ systemName, sizeof( systemName ), linkName, sizeof( linkName ) );
+ if( !success )
+ return false;
+ CloseMostChannel( systemName );
+ switch( epType )
+ {
+ case EP_Synchron:
+ success = ConfigureSyncChannel( systemName, subbufferSize, packetsPerTransaction );
+ if( success )
+ success = ConfigureMostChannel( systemName, epType, epDir, amountOfBuffers, bufferSize );
+ if( success )
+ {
+ switch( aimType )
+ {
+ case AIM_AUDIO:
+ success = LinkToAudioDevice( linkName, subbufferSize );
+ break;
+ case AIM_CDEV:
+ default:
+ success = LinkToCharacterDevice( linkName, deviceName );
+ break;
+ }
+ }
+ break;
+ case EP_Isochron:
+ success = ConfigureIsocChannel( systemName, subbufferSize, packetsPerTransaction );
+ if( success )
+ success = ConfigureMostChannel( systemName, epType, epDir, amountOfBuffers, bufferSize );
+ if( success )
+ success = LinkToCharacterDevice( linkName, deviceName );
+ break;
+ default:
+ break;
+ }
+ return success;
+}
+
+bool CNetworkDevice::ConfigureMlbChannel( uint8_t mlbChannelAddress, EPDataType_t epType, EPDirection_t epDir,
+ char *deviceName, uint32_t deviceNameBufLen, uint32_t amountOfBuffers, uint32_t bufferSize )
+{
+ return ConfigureMlbChannel( AIM_CDEV, mlbChannelAddress, epType, epDir, deviceName, deviceNameBufLen,
+ amountOfBuffers, bufferSize, 0, 0 );
+}
+
+bool CNetworkDevice::SendMostControlMessage( uint8_t devInst, uint32_t targetAddr, uint32_t nFBlock, uint32_t nInst,
+ uint32_t nFunc, uint8_t nOpType, uint32_t nPayloadLen, const uint8_t *Payload )
+{
+ CGeneric_SendMostMessage *a = new CGeneric_SendMostMessage(Payload,
+ nPayloadLen, targetAddr, nFBlock, nInst, nFunc, nOpType, 0xFF);
+ iStack->EnqueueElement(targetAddr, a);
+ a->RemoveReference();
+ return true;
+}
+
+void CNetworkDevice::GetDeviceVersion( uint16_t nodeAddress )
+{
+ CV3_DeviceVersion *a = new CV3_DeviceVersion(this, nodeAddress, 0);
+ iStack->EnqueueElement(nodeAddress, a);
+ a->RemoveReference();
+}
+
+ISReturn_t CNetworkDevice::OnMostMessage(CIndustrialStack *iStack, CISMostMsg *r)
+{
+ if (NULL == r)
+ return ISReturn_NoChange;
+ for (uint32_t i = 0; i < allListeners.Size(); i++)
+ {
+ allListeners[i]->OnMostControlMessage(this, r->SourceAddress, r->TargetAddress,
+ r->FBlock, r->Inst, r->Func, r->OpType, r->PayloadLen, r->Payload);
+ }
+ return ISReturn_NoChange;
+}
+
diff --git a/Src/Network/NetworkDevice.h b/Src/Network/NetworkDevice.h
new file mode 100644
index 0000000..8a67556
--- /dev/null
+++ b/Src/Network/NetworkDevice.h
@@ -0,0 +1,862 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CNetworkDevice class.
+ */
+/*----------------------------------------------------------*/
+#ifndef _NETWORKDEVICE_H_
+#define _NETWORKDEVICE_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <semaphore.h>
+#include "SafeVector.h"
+#include "ScriptXml.h"
+#include "Types.h"
+#include "Thread.h"
+#include "NetworkDeviceListener.h"
+#include "IndustrialStack.h"
+#include "IndustrialStack_Types.h"
+
+typedef enum
+{
+ NetworkState_Unknown,
+ NetworkState_Unavailable,
+ NetworkState_Available,
+ NetworkState_ShutdownInProgress
+} NetworkState_t;
+
+/*----------------------------------------------------------*/
+/*! \brief This class represents an INIC instance.
+ * It will be multiple instanced, for each connected OS81118.
+ * It generates INIC requests and parses INIC responses.
+ */
+/*----------------------------------------------------------*/
+class CNetworkDevice : public CThread, public CSInternalEvent
+{
+private:
+ CIndustrialStack *iStack;
+ CV1_OnMostRx *v1Events;
+ CV3_OnMostRx *v3Events;
+ bool promiscuous;
+ NetworkState_t netState;
+ void *pInic;
+ void *pScriptMemoryArea;
+ bool isRunning;
+ bool isActionPending;
+ uint8_t deviceIndex;
+ uint8_t deviceApi;
+ bool isTimingMaster;
+ uint32_t asyncBandwidth;
+ sem_t methodMutex;
+ int controlEndpointRxHandle;
+ int controlEndpointTxHandle;
+ char *responseToWaitFor[64];
+ char deviceNameControlRx[64];
+ char deviceNameControlTx[64];
+ CSafeVector<CNetworkDeviceListener *> allListeners;
+
+ uint16_t startV3autoForced;
+ uint16_t startV3packetBW;
+
+ bool OpenDevice( const char *systemNameControlRx, const char *systemNameControlTx, const char *linkNameControlRx,
+ const char *linkNameControlTx );
+ bool OpenMostControlChannel( void );
+ void CloseMostControlChannel( void );
+ void WaitForIpcResponse( const char *responseMessage );
+ void ExecuteMcmScript( uint16_t nodeAddress, CSciptXml *scriptXml );
+public:
+ /*----------------------------------------------------------*/
+ /*! \brief Constructor of CNetworkDevice.
+ * \param deviceIndex - The index of the physical device instance of the server device.
+ * Starting at 0 for the first device instance.
+ * \param deviceApi - 1: OS81092, OS81110; 2: OS81118-C-Rev; 3:OS81118-D-Rev
+ * \param isTimingMaster - true, if this device shall act as timing master, otherwise it is timing slave
+ * \param asyncBandwidth - if set as timing master, how many bytes shall be reserved for the asynchronous channel
+ * \param promiscuousMode - true, promiscuous mode. false, perfect match filter with multicast and broadcast enabled. If enabled, tools like Wireshark will capture every packet.
+ */
+ /*----------------------------------------------------------*/
+ CNetworkDevice( uint8_t deviceIndex, uint8_t deviceApi, bool isTimingMaster, uint32_t asyncBandwidth,
+ bool promiscuousMode );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Destructor of CNetworkDevice.
+ */
+ /*----------------------------------------------------------*/
+ virtual ~CNetworkDevice();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Function of background thread.
+ * \note Do never call this method. It is used by internal threads.
+ */
+ /*----------------------------------------------------------*/
+ void Run();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Opens the USB connection to the INIC.
+ * \param controlRxEndpointAddress - The USB endpoint address of the RX direction.
+ * \param controlTxEndpointAddress - The USB endpoint address of the TX direction.
+ * \return true, if successful. false, otherwise.
+ */
+ /*----------------------------------------------------------*/
+ bool OpenUsb( uint8_t controlRxEndpointAddress, uint8_t controlTxEndpointAddress );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Opens the MLB connection to the INIC.
+ * \param controlRxChannelAddress - The MLB channel address of the RX direction.
+ * \param controlTxChannelAddress - The MLB channel address of the TX direction.
+ * \return true, if successful. false, otherwise.
+ */
+ /*----------------------------------------------------------*/
+ bool OpenMlb( uint8_t controlRxChannelAddress, uint8_t controlTxChannelAddress );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Opens the I2C connection to the INIC.
+ * \param inicApi - INIC API Version
+ * \return true, if successful. false, otherwise.
+ */
+ /*----------------------------------------------------------*/
+ bool OpenI2C();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Closes the USB connection to the INIC.
+ */
+ /*----------------------------------------------------------*/
+ void Close();
+
+ /*----------------------------------------------------------*/
+ /*! \brief Returns the used API of the INIC.
+ * \return INIC API Version 1: OS81092, OS81110; 2: OS81118-C-Rev; 3:OS81118-D-Rev
+ */
+ /*----------------------------------------------------------*/
+ uint8_t GetDeviceApi();
+
+ NetworkState_t GetNetState();
+ void SetNetstate( NetworkState_t newState );
+ void SetTimingMaster(bool tm);
+ bool IsTimingMaster();
+ void SetAsyncBandwidth(uint32_t bw);
+ uint32_t GetAsyncBandwidth();
+
+ /*----------------------------------------------------------*/
+ /*! \brief Determines if there are jobs currently in the working queue.
+ * \note This method will block until the result is queried from the worker process.
+ * \return true, if there are pending actions enqueued.
+ */
+ /*----------------------------------------------------------*/
+ bool ActionsPending();
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Remove all pending actions from the working queue.
+ */
+ /*----------------------------------------------------------*/
+ void ClearAllPendingActions();
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Configure the Linux character device driver to handle an USB connection.
+ * \note This overloaded function is used to configure synchronous channels.
+ * \param aimType - Specifies the type of used Linux Driver Application Interface Module.
+ * \param endpointAddress - The USB endpoint address.
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param deviceName - On successful configuration, this method stores the name of the character device into the given buffer.
+ * \param deviceNameBufLen - The length of the given buffer.
+ * \param amountOfBuffers - The amount of buffers used in the driver.
+ * \param bufferSize - The amount of bytes used in a single buffer.
+ * \param subbufferSize - The amount of bytes used for a single subbuffer. For isoc channel this maybe 188 or 196 byte.
+ * \param packetsPerTransaction - The amount of packets per transaction.
+ * \return true, if successful. false, otherwise.
+ */
+ /*----------------------------------------------------------*/
+ bool ConfigureUsbEndpoint( AimType_t aimType, uint8_t endpointAddress, EPDataType_t epType, EPDirection_t epDir,
+ char *deviceName, uint32_t deviceNameBufLen, uint32_t amountOfBuffers, uint32_t bufferSize,
+ uint32_t subbufferSize, uint32_t packetsPerTransaction );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Configure the Linux character device driver to handle an USB connection.
+ * \param endpointAddress - The USB endpoint address.
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param deviceName - On successful configuration, this method stores the name of the character device into the given buffer.
+ * \param deviceNameBufLen - The length of the given buffer.
+ * \param amountOfBuffers - The amount of buffers used in the driver.
+ * \param bufferSize - The amount of bytes used in a single buffer.
+ * \return true, if successful. false, otherwise.
+ */
+ /*----------------------------------------------------------*/
+ bool ConfigureUsbEndpoint( uint8_t endpointAddress, EPDataType_t epType, EPDirection_t epDir, char *deviceName,
+ uint32_t deviceNameBufLen, uint32_t amountOfBuffers, uint32_t bufferSize );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Configure the Linux character device driver to handle an MLB connection.
+ * \note This overloaded function is used to configure synchronous channels.
+ * \param aimType - Specifies the type of used Linux Driver Application Interface Module.
+ * \param mlbChannelAddress - The MLB channel address
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param deviceName - On successful configuration, this method stores the name of the character device into the given buffer.
+ * \param deviceNameBufLen - The length of the given buffer.
+ * \param amountOfBuffers - The amount of buffers used in the driver.
+ * \param bufferSize - The amount of bytes used in a single buffer.
+ * \param subbufferSize - The amount of bytes used for a single subbuffer. For isoc channel this maybe 188 or 196 byte.
+ * \param packetsPerTransaction - The amount of packets per transaction.
+ * \return true, if successful. false, otherwise.
+ */
+ /*----------------------------------------------------------*/
+ bool ConfigureMlbChannel( AimType_t aimType, uint8_t mlbChannelAddress, EPDataType_t epType, EPDirection_t epDir,
+ char *deviceName, uint32_t deviceNameBufLen, uint32_t amountOfBuffers, uint32_t bufferSize,
+ uint32_t subbufferSize, uint32_t packetsPerTransaction );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Configure the Linux character device driver to handle an MLB connection.
+ * \param mlbChannelAddress - The MLB channel address
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param deviceName - On successful configuration, this method stores the name of the character device into the given buffer.
+ * \param deviceNameBufLen - The length of the given buffer.
+ * \param amountOfBuffers - The amount of buffers used in the driver.
+ * \param bufferSize - The amount of bytes used in a single buffer.
+ * \return true, if successful. false, otherwise.
+ */
+ /*----------------------------------------------------------*/
+ bool ConfigureMlbChannel( uint8_t mlbChannelAddress, EPDataType_t epType, EPDirection_t epDir, char *deviceName,
+ uint32_t deviceNameBufLen, uint32_t amountOfBuffers, uint32_t bufferSize );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Adds a callback class, which derives CNetworkDeviceListener.
+ * This class will then be informed about any results and changes of MOST transactions.
+ * \note It is possible to register multiple listeners.
+ * \param listener - The class, which wants to be registered for MOST events.
+ */
+ /*----------------------------------------------------------*/
+ void AddListener( CNetworkDeviceListener *listener );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves the amount of registered listeners.
+ * \note Use this method in combination of GetListener()
+ * \return The amount of registered listeners.
+ */
+ /*----------------------------------------------------------*/
+ uint32_t GetAmountOfListners();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets a pointer to the class implementing the CNetworkDeviceListener interface.
+ * \note Use this method in combination of GetAmountOfListners()
+ * \return The pointer to the given instance of Listener.
+ */
+ /*----------------------------------------------------------*/
+ CNetworkDeviceListener *GetListener( uint32_t instance );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets the MOST instance index of the server device.
+ * \return The MOST instance index, starting at 0 for the first instance.
+ */
+ /*----------------------------------------------------------*/
+ uint8_t GetDeviceIndex();
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Wait let the scripting engine wait for the given amount of time.
+ * \param timeInMillis - Time value in milliseconds.
+ */
+ /*----------------------------------------------------------*/
+ void ScriptPause( uint32_t timeInMillis );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Execute a bunch of MCM send and receive actions, as descibed in the XML file.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param pPathToScriptXml - Path to the XML file.
+ */
+ /*----------------------------------------------------------*/
+ void ExecuteMcmScript( uint16_t nodeAddress, const char *pPathToScriptXml );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Execute a bunch of MCM send and receive actions, as descibed in the XML zero terminated string.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param pPathToScriptXml - Path to the XML file.
+ */
+ /*----------------------------------------------------------*/
+ void ExecuteMcmScript( uint16_t nodeAddress, const char *pStringBuffer, uint32_t bufferLength );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Sends a NetworkMaster.NOT_OK and NetworkMaster.OK, in order resolve address conflicts.
+ */
+ /*----------------------------------------------------------*/
+ void ToggleNotOk();
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves the GroupAddresses of all available MOST devices in this MOST instance.
+ * \note The result of this request is reported in the callback method OnMostDeviceType of the CNetworkDeviceListener class.
+ * Use AddListener to get the result.
+ */
+ /*----------------------------------------------------------*/
+ void GetGroupAddresses( uint8_t maxNodePos );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves the MOST MAC address for the given node address in this MOST instance.
+ * \note The result of this request is reported in the callback method OnMostMacAddress of the CNetworkDeviceListener class.
+ * Use AddListener to get the result.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ */
+ /*----------------------------------------------------------*/
+ void GetMacAddress( uint16_t nodeAddress );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Starts up the MOST on the local INIC of the server device.
+ * \param isTimingMaster - true, if the INIC shall act as a timing master. false, if the device shall act as a timing slave.
+ * \param packetBandWidth - The amount of Bytes, which are reserved for asynchronous data (MEP, MHP).
+ * \note This is an INIC API Version 1 command. Use it for e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ void StartMostV1( bool isTimingMaster, uint16_t packetBandWidth );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Performs a network shutdown sequence on the local INIC attached to the server device.
+ * \note This method will cause a chain reaction on the MOST network. All devices will switch of their output signal on MOST.
+ * \note This is an INIC API Version 1 command. Use it for e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ void MostNetworkShutdownV1();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Enables the usage of the MLB bus for the device on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param mlbSpeed - The used MLB speed.
+ * \note This is an INIC API Version 1 command. Use it for e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ void OpenMlbV1( uint16_t nodeAddress, MlbPortSpeed_t mlbSpeed );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Sets the MOST MAC address for the device on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param macAddress1 - The 1st byte of the MAC address.
+ * \param macAddress2 - The 2nd byte of the MAC address.
+ * \param macAddress3 - The 3rd byte of the MAC address.
+ * \param macAddress4 - The 4th byte of the MAC address.
+ * \param macAddress5 - The 5th byte of the MAC address.
+ * \param macAddress6 - The 6th byte of the MAC address.
+ * \param persistent - true, if the given MAC address shall be stored persistent into the INIC flash memory.
+ * \note This is an INIC API Version 1 command. Use it for e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ void SetMostMacAddressV1( uint16_t nodeAddress, uint8_t macAddress1, uint8_t macAddress2, uint8_t macAddress3,
+ uint8_t macAddress4, uint8_t macAddress5, uint8_t macAddress6, bool persistent );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Enables the usage of the MLB bus for the device on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param tsiPortId - The instance id of the used TSI port.
+ * \param tsiPortMode - The used mode for this TSI port.
+ * \note This is an INIC API Version 1 command. Use it for OS81110 only.
+ */
+ /*----------------------------------------------------------*/
+ void OpenTsiV1( uint16_t nodeAddress, V1TsiPortInstance_t tsiPortId, V1TsiPortMode tsiPortMode );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates a TSI socket on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param portInst - The port instance id of the TSI port.
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param blockWidthTsi -The block width in bytes to be allocated on the MLB bus.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 1 command. Use it for e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ void CreateTsiSocketV1( uint16_t nodeAddress, V1TsiPortInstance_t portInst,
+ EPDataType_t epType, EPDirection_t epDir,uint16_t blockWidthTsi, uint32_t tag );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates a MLB socket on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param mlbChannelAddress - The MLB channel address (even value).
+ * \param blockWidthMlb -The block width in bytes to be allocated on the MLB bus.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 1 command. Use it for e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ void CreateMlbSocketV1( uint16_t nodeAddress, EPDataType_t epType, EPDirection_t epDir, uint16_t mlbChannelAddress,
+ uint16_t blockWidthMlb, uint32_t tag );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates a MLB socket on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param mlbChannelAddress - The MLB channel address (even value).
+ * \param blockWidthMlb -The block width in bytes of this singular splitted socked.
+ * \param splittedOffset - Offset in between the splitted socket.
+ * \param blockWidthCombined - The block width in bytes of all splitted sockets combined.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 1 command. Use it for e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ void CreateSplittedMlbSocketV1( uint16_t nodeAddress, EPDataType_t epType, EPDirection_t epDir,
+ uint16_t mlbChannelAddress, uint16_t blockWidthMlb, uint16_t splittedOffset, uint16_t blockWidthCombined,
+ uint32_t tag );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates a MOST socket on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param connectionLabel - Only in case of if epDir is "EPDIR_IN": The connection label, which this socket will be bound.
+ * Otherwise, the value will be ignored.
+ * \param blockwidthMost - The block width in bytes to be allocated on the MOST bus.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 1 command. Use it for e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ void CreateMostSocketV1( uint16_t nodeAddress, EPDataType_t epType, EPDirection_t epDir, uint16_t connectionLabel,
+ uint16_t blockwidthMost, uint32_t tag );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param handle - The handle of socket (will be reported by the callback callback methods of the create socket methods).
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 1 command. Use it for e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ void DestroySocketV1( uint16_t nodeAddress, uint8_t handle, uint32_t tag );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param handle - The handle of socket (will be reported by the callback callback methods of the connect socket method).
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 1 command. Use it for e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ void DisconnectSocketsV1( uint16_t nodeAddress, uint8_t handle, uint32_t tag );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Connects two different sockets, which then is called a connection, on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param inHandle - The handle of the in-socket (will be reported by the callback callback methods of the create socket methods).
+ * \param outHandle - * The handle of out-socket (will be reported by the callback callback methods of the create socket methods).
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 1 command. Use it for e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ void ConnectSocketsV1( uint16_t nodeAddress, uint8_t inHandle, uint8_t outHandle, uint32_t tag );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Configures an I2S port on the given node address.
+ * \param nodeAddr -The device with this MOST node address raised this event.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ void OpenStreamPortV1( uint16_t nodeAddress, V1I2SPortClkDriveMode_t portMode,
+ V1I2SStreamingPortMode_t streamPortMode, V1I2SStreamingDataFormat_t format, uint32_t tag );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates an I2S socket on the given node address.
+ * \param nodeAddr -The device with this MOST node address raised this event.
+ * \param portInstance - The I2S port instance. 0 = Port A, 1 = Port B.
+ * \param epDir - he Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param blockWidthI2S - The block width in bytes allocated on the I2S bus.
+ * \param pin - The physical I2S data pin of the INIC.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ void CreateStreamSocketV1( uint16_t nodeAddress, EPDirection_t epDir, uint16_t blockWidthI2S, V1I2SPin_t pin,
+ uint32_t tag );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates an I2S socket on the given node address.
+ * \param nodeAddr -The device with this MOST node address raised this event.
+ * \param portInstance - The I2S port instance. 0 = Port A, 1 = Port B.
+ * \param epDir - he Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param blockWidthI2S - The block width in bytes allocated on the I2S bus.
+ * \param splittedOffset - Offset in between the splitted socket.
+ * \param blockWidthCombined - The block width in bytes of all splitted sockets combined.
+ * \param pin - The physical I2S data pin of the INIC.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ void CreateSplittedStreamSocketV1( uint16_t nodeAddress, EPDirection_t epDir, uint16_t blockWidthI2S,
+ uint16_t splittedOffset, uint16_t blockWidthCombined, V1I2SPin_t pin, uint32_t tag );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Attach to a local INIC on the server device.
+ * \note This command has to be called before any other commands to the local INIC.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void AttachV3();
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Destroyes any resource on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param sync - true, if the device shall be used afterwise. false, if the device is going to suspend (shutdown).
+ * \note In any case (regardless if sync is true or false), all ports, sockets and connects are going to be destroyed).
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void DeviceSyncV3( uint16_t nodeAddress, bool sync );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Performs a network startup sequence on the local INIC attached to the server device.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118-D Revision
+ */
+ /*----------------------------------------------------------*/
+ void MostNetworkStartupV3( uint16_t autoForcedNotAvailable, uint16_t packetBW );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Performs a network startup sequence on the local INIC attached to the server device, after MostNetworkStartupV3 with parameters had failed.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118-D Revision
+ * \note Call this method only if the MostNetworkStartupV3( uint16_t autoForcedNotAvailable, uint16_t packetBW ) had failed. This will be treated as retry.
+ */
+ /*----------------------------------------------------------*/
+ void MostNetworkStartupV3();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Performs a network shutdown sequence on the local INIC attached to the server device.
+ * \note This method will cause a chain reaction on the MOST network. All devices will switch of their output signal on MOST.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void MostNetworkShutdownV3();
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Closes the IPC connection to local attached INIC.
+ * \note This will also cleanup any used resource in the INIC.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void InicUnsychronizeV3();
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Sets the MOST MAC address for the device on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param macAddress1 - The 1st byte of the MAC address.
+ * \param macAddress2 - The 2nd byte of the MAC address.
+ * \param macAddress3 - The 3rd byte of the MAC address.
+ * \param macAddress4 - The 4th byte of the MAC address.
+ * \param macAddress5 - The 5th byte of the MAC address.
+ * \param macAddress6 - The 6th byte of the MAC address.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118-D Rev
+ */
+ /*----------------------------------------------------------*/
+ void SetMostMacAddressV3( uint16_t nodeAddress, uint8_t macAddress1, uint8_t macAddress2, uint8_t macAddress3,
+ uint8_t macAddress4, uint8_t macAddress5, uint8_t macAddress6 );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Enables the usage of the MLB bus for the device on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param mlbSpeed - The speed of the MLB bus.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void OpenMlbV3( uint16_t nodeAddress, MlbPortSpeed_t mlbSpeed );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates an USB socket on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param endPointAddress - The USB endpoint address.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \param packetsPerFrame - The amount of packets stored in a single USB frame (512 byte).
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void CreateUsbSocketV3( uint16_t nodeAddress, EPDataType_t epType, EPDirection_t epDir, uint8_t endPointAddress,
+ uint16_t packetsPerFrame, uint32_t tag );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates an splitted USB socket on the given node address to use with Combiner or Splitter.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param endPointAddress - The USB endpoint address.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \param packetsPerFrame - The amount of packets stored in a single USB frame (512 byte).
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void CreateSplittedUsbSocketV3( uint16_t nodeAddress, EPDataType_t epType, EPDirection_t epDir,
+ uint8_t endPointAddress, uint16_t packetsPerFrame, uint16_t bytesPerPacket, uint32_t tag );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates a MLB socket on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param mlbChannelAddress - The MLB channel address (even value).
+ * \param blockwidthMlb - The block width in bytes to be allocated on the MLB bus.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void CreateMlbSocketV3( uint16_t nodeAddress, uint16_t mlbPortHandle, EPDataType_t epType, EPDirection_t epDir,
+ uint16_t mlbChannelAddress, uint16_t blockwidthMlb, uint32_t tag );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates a splitted MLB socket on the given node address to use with Combiner or Splitter.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param mlbChannelAddress - The MLB channel address (even value).
+ * \param blockwidthMlb - The block width in bytes to be allocated on the MLB bus.
+ * \param bytesPerPacket - The total number of data bytes to be transfered each MOST frame.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void CreateSplittedMlbSocketV3( uint16_t nodeAddress, uint16_t mlbPortHandle, EPDataType_t epType,
+ EPDirection_t epDir, uint16_t mlbChannelAddress, uint16_t blockwidthMlb, uint16_t bytesPerPacket,
+ uint32_t tag );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates a MOST socket on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param epType - The data type, which then will be transmitted on this MOST channel.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param connectionLabel - Only in case of if epDir is "EPDIR_IN": The connection label, which this socket will be bound.
+ * Otherwise, the value will be ignored.
+ * \param blockwidthMost - The block width in bytes to be allocated on the MOST bus.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void CreateMostSocketV3( uint16_t nodeAddress, EPDataType_t epType, EPDirection_t epDir, uint16_t connectionLabel,
+ uint16_t blockwidthMost, uint32_t tag );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Connects two different sockets, which then is called a connection, on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param epType - The data type, which then will be transmitted on this connection.
+ * \param inHandle - The handle of the in-socket (will be reported by the callback callback methods of the create socket methods).
+ * \param outHandle - * The handle of out-socket (will be reported by the callback callback methods of the create socket methods).
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void ConnectSocketsV3( uint16_t nodeAddress, EPDataType_t epType, uint16_t inHandle, uint16_t outHandle,
+ uint16_t offset, uint32_t tag );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Destroyes up to three resources (Ports or connections) on the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \param amountOfHandles - The amount of resources to be destroyed. (value must be between 1 to 3).
+ * \param handle1 - The first resource to be destroyed.
+ * \param handle2 - The second resource to be destroyed.
+ * \param handle3 - The third resource to be destroyed.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void ResourceDestroyV3( uint16_t nodeAddress, uint8_t amountOfHandles, const uint16_t *pHandle, uint32_t tag );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Configures an I2S port on the given node address.
+ * \param nodeAddr -The device with this MOST node address raised this event.
+ * \param portInstance - The I2S port instance. 0 = Port A, 1 = Port B.
+ * \param option - The I2S port option.
+ * \param mode - The I2S clock mode.
+ * \param delay - The I2S delay mode.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void ConfigureStreamPortV3( uint16_t nodeAddress, uint8_t portInstance, V3I2SPortOption_t option,
+ V3I2SClockMode_t mode, V3I2SDelayMode_t delay, uint32_t tag );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates an I2S port on the given node address.
+ * \param nodeAddr -The device with this MOST node address raised this event.
+ * \param portInstance - The I2S port instance. 0 = Port A, 1 = Port B.
+ * \param clock - The I2S port speed in multiple of MOST base clock.
+ * \param align - The I2S data format alignment.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void CreateStreamPortV3( uint16_t nodeAddress, uint8_t portInstance, V3I2SPortSpeed_t clock,
+ V3I2SAlignment_t align, uint32_t tag );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates an I2S socket on the given node address.
+ * \param nodeAddr -The device with this MOST node address raised this event.
+ * \param portInstance - The I2S port instance. 0 = Port A, 1 = Port B.
+ * \param epDir - he Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param blockWidthI2S - The block width in bytes allocated on the I2S bus.
+ * \param pin - The physical I2S data pin of the INIC.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void CreateStreamSocketV3( uint16_t nodeAddress, uint8_t portInstance, EPDirection_t epDir, uint16_t blockWidthI2S,
+ V3I2SPin_t pin, uint32_t tag );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates an splitted I2S socket on the given node address to use with Combiner or Splitter.
+ * \param nodeAddr -The device with this MOST node address raised this event.
+ * \param portInstance - The I2S port instance. 0 = Port A, 1 = Port B.
+ * \param epDir - he Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param blockWidthI2S - The block width in bytes allocated on the I2S bus.
+ * \param pin - The physical I2S data pin of the INIC.
+ * \param bytesPerPacket - The total number of data bytes to be transfered each MOST frame.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void CreateSplittedStreamSocketV3( uint16_t nodeAddress, uint8_t portInstance, EPDirection_t epDir,
+ uint16_t blockWidthI2S, V3I2SPin_t pin, uint16_t bytesPerPacket, uint32_t tag );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates an I2S socket on the given node address.
+ * \param nodeAddr -The device with this MOST node address raised this event.
+ * \param tag - Any 32 bit value. This value will be unmodified passed back in the corresponding callback method.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void GetRingBreakResultV3( uint16_t nodeAddress, uint32_t tag );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Sends the given Control Message out to MOST ring.
+ * \param targetAddr - The MOST target address
+ * \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( uint8_t devInst, uint32_t targetAddr, uint32_t nFBlock, uint32_t nInst,
+ uint32_t nFunc, uint8_t nOpType, uint32_t nPayloadLen, const uint8_t *Payload );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets the device information for the given node address.
+ * \param nodeAddress - The MOST node address (e.g. 0x101).
+ * \note The corresponding callback to this request is OnDeviceVersion.
+ * \note This is an INIC API Version 3 command. Use it for e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ void GetDeviceVersion( uint16_t nodeAddress );
+
+ /* Callback from underlying layers */
+ virtual ISReturn_t OnMostMessage(CIndustrialStack *iStack, CISMostMsg *r);
+};
+
+#endif //_NETWORKDEVICE_H_
diff --git a/Src/Network/NetworkDeviceListener.cpp b/Src/Network/NetworkDeviceListener.cpp
new file mode 100644
index 0000000..be62d33
--- /dev/null
+++ b/Src/Network/NetworkDeviceListener.cpp
@@ -0,0 +1,306 @@
+/*
+ * 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 <stdio.h>
+#include <Board.h>
+#include "Console.h"
+#include "NetworkDeviceListener.h"
+
+void CNetworkDeviceListener::OnSync( void *source, bool isSynced )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnSync\n" );
+}
+
+void CNetworkDeviceListener::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 )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnNetworkState\n" );
+}
+
+void CNetworkDeviceListener::OnNetworkStartupV3( void *source, bool success )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnNetworkStartupV3, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::OnNetworkShutdownV3( void *source, bool success )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnNetworkShutdownV2, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::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( success )
+ {
+ ConsolePrintf( PRIO_LOW,
+ "BASE->OnMostMacAddress:nodeAddress:0x%X, MAC-Address:%02X-%02X-%02X-%02X-%02X-%02X)\n", nodeAddress,
+ macAddress1, macAddress2, macAddress3, macAddress4, macAddress5, macAddress6 );
+ }
+ else
+ {
+ ConsolePrintf( PRIO_ERROR,
+ RED"BASE->OnMostMacAddress reports failure for nodeAddress:0x%X"RESETCOLOR"\n", nodeAddress );
+ }
+}
+
+void CNetworkDeviceListener::OnMostDeviceType( void *source, bool success, uint16_t nodeAddress, uint16_t deviceType )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnMostDeviceType, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::OnInitCompleteV1( void *source )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnInitCompleteV1\n" );
+}
+
+void CNetworkDeviceListener::OnNetOnV1( void *source, bool isMaster )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnNetOnV1, mode=%s\n", ( isMaster ? "master" : "slave" ) );
+}
+
+void CNetworkDeviceListener::OnShutDownV1( void *source )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnShutDownV1\n" );
+}
+
+void CNetworkDeviceListener::OnNprV1( void *source, uint8_t npr )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnNprV1, NPR=%d\n", npr );
+}
+
+void CNetworkDeviceListener::OnUnlockV1( void *source )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnUnlockV1\n" );
+}
+
+void CNetworkDeviceListener::OnMprV1( void *source, uint8_t oldMpr, uint8_t newMpr )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnMprV1, old MPR=%d, new MPR:%d\n", oldMpr, newMpr );
+}
+
+void CNetworkDeviceListener::OnOpenTsiV1( void *source, bool success, uint16_t nodeAddress )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnOpenTsiV1, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::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 )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnCreateTsiSocketV1, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::OnOpenMlbV1( void *source, bool success, uint16_t nodeAddress )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnOpenMlbV1, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::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 )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnCreateMlbSocketV1, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::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 )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnCreateMostSocketV1, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::OnConnectSocketsV1( void *source, bool success, uint16_t nodeAddr,
+ uint16_t inSocketHandle, uint16_t outSocketHandle, uint16_t connectionHandle, uint32_t tag )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnConnectSocketsV1, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::OnDestroySocketV1( void *source, bool success, uint16_t nodeAddr, uint16_t handle,
+ uint32_t tag )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnDestroySocketV1, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::OnDisconnectSocketsV1( void *source, bool success, uint16_t nodeAddr, uint16_t handle,
+ uint32_t tag )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnDisconnectSocketsV1, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::OnOpenI2SPortV1( void *source, bool success, uint16_t nodeAddress,
+ V1I2SPortClkDriveMode_t portMode, V1I2SStreamingDataFormat_t format, uint32_t tag )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnOpenI2SPortV1, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::OnCreateI2SSocketV1( void *source, bool success, uint16_t nodeAddr, EPDirection_t epDir,
+ uint16_t blockWidthI2S, V1I2SPin_t pin, uint16_t socketHandle, uint32_t tag )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnCreateI2SSocketV1, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::OnOpenMlbV3( void *source, bool success, uint16_t nodeAddress, uint16_t mlbPortHandle )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnOpenMlbV2, success=%s, Handle:%X\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ), mlbPortHandle );
+}
+
+void CNetworkDeviceListener::OnCreateUsbSocketV3( void *source, bool success, uint16_t nodeAddr, EPDataType_t epType,
+ EPDirection_t epDir, uint8_t endPointAddress, uint16_t socketHandle, uint32_t tag )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnCreateUsbSocketV2, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::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 )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnCreateSplittedUsbSocketV2, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::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 )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnCreateMlbSocketV2, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::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 splittertHandle, uint32_t tag )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnCreateSplittedMlbSocketV2, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::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 )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnCreateMostSocketV2, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::OnConnectSocketsV3( void *source, bool success, uint16_t nodeAddr, EPDataType_t epType,
+ uint16_t inSocketHandle, uint16_t outSocketHandle, uint16_t connectionHandle, uint32_t tag )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnConnectSocketsV2, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+
+void CNetworkDeviceListener::OnResourceDestroyV3( void *source, bool success, uint16_t nodeAddress,
+ uint8_t amountOfHandles, const uint16_t *pHandle, uint32_t tag )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnResourceDestroyV2, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::OnConfigureI2SPortV3( void *source, bool success, uint16_t nodeAddr, uint8_t portInstance,
+ V3I2SPortOption_t option, V3I2SClockMode_t mode, V3I2SDelayMode_t delay, uint32_t tag )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnConfigureI2SPortV2, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::OnCreateI2SPortV3( void *source, bool success, uint16_t nodeAddr, uint8_t portInstance,
+ V3I2SPortSpeed_t clock, V3I2SAlignment_t align, uint32_t tag )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnCreateI2SPortV2, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::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 )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnCreateI2SSocketV2, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::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 )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->CNetworkDeviceListener::OnCreateSplittedI2SSocketV2, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
+
+void CNetworkDeviceListener::OnRbdResultV3( void *source, uint16_t nodeAddress, uint8_t result, uint8_t position,
+ uint8_t status, uint16_t id )
+{
+ ConsolePrintfStart( PRIO_HIGH, YELLOW"BASE->OnRbdResultV3: Diagnosis Result from node=0x%X, result=0x%X (",
+ nodeAddress, result );
+ switch( result )
+ {
+ case 0:
+ ConsolePrintfContinue( "NoError" );
+ break;
+ case 1:
+ ConsolePrintfContinue( "PosDetected" );
+ break;
+ case 2:
+ ConsolePrintfContinue( "DiagFailed" );
+ break;
+ case 3:
+ ConsolePrintfContinue( "Pos0WeakSig" );
+ break;
+ case 0xFF:
+ ConsolePrintfContinue( "No result" );
+ break;
+ default:
+ ConsolePrintfContinue( "UNKNOWN" );
+ break;
+ }
+ ConsolePrintfExit( ") Position: %d"RESETCOLOR"\n", position );
+}
+
+void CNetworkDeviceListener::OnControlChannelReadEnd( void *source )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->OnControlChannelReadEnd\n" );
+}
+
+void CNetworkDeviceListener::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 )
+{
+ ConsolePrintf( PRIO_LOW, "Base->OnMostControlMessage\n" );
+}
+
+void CNetworkDeviceListener::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 )
+{
+ ConsolePrintf( PRIO_LOW, "BASE->OnDeviceVersion::OnDeviceVersion, success=%s\n",
+ ( success ? GREEN"yes"RESETCOLOR : RED"no"RESETCOLOR ) );
+}
diff --git a/Src/Network/NetworkDeviceListener.h b/Src/Network/NetworkDeviceListener.h
new file mode 100644
index 0000000..719bc5f
--- /dev/null
+++ b/Src/Network/NetworkDeviceListener.h
@@ -0,0 +1,568 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CNetworkDeviceListener class.
+ */
+/*----------------------------------------------------------*/
+#ifndef _NETWORKDEVICELISTENER_H_
+#define _NETWORKDEVICELISTENER_H_
+
+#include <stdint.h>
+#include "Types.h"
+
+/*----------------------------------------------------------*/
+/*! \brief This class defines callbacks methods which will be called by CNetworkDevice to any
+ * registered listener. Also this class implements empty implementation of each method.
+ * So the integrator has only to override methods, he is interessted in.
+ */
+/*----------------------------------------------------------*/
+class CNetworkDeviceListener
+{
+public:
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a sync event has been detected on the server network device.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnSync( void *source, bool isSynced );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a Network State event has been detected on the server network device.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param mpValChanged - true, there was a change in the Maximum Position Information. false, no change.
+ * \param systemNotOk - true, system state changes to NotOk. false, no change.
+ * \param mostAvailable - true, the MOST network is available. false, The MOST network is not available for sending control/packet data.
+ * \param availableSubState - 0=Regular, 2=Diagnosis, 4=RxOnBlocked, 6=ForcedNA, 0x10=Unstable, 0x11=Stable
+ * \param availableTransition - 0=Command, 1=RxActivity, 2=DiagnosisReady, 0x10=Normal, 0x11=SuddenSignalOff, 0x12=CriticalUnlock
+ * 0x13=ErrorSystem, 0xFF=NoTransition
+ * \param nodeAddress - The assigned MOST node address.
+ * \param nodePos - The position in the MOST ring.
+ * \param maxPos - The maximum amount of devices in the MOST ring.
+ * \param packetBW - The amount of bytes reserved for packet channel (MEP/MHP)
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void 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 );
+
+
+
+ virtual void OnInitCompleteV1( void *source );
+ virtual void OnUnlockV1( void *source );
+ virtual void OnNetOnV1( void *source, bool isMaster );
+ virtual void OnShutDownV1( void *source );
+ virtual void OnNprV1( void *source, uint8_t npr );
+ virtual void OnMprV1( void *source, uint8_t oldMpr, uint8_t newMpr );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever the MOST had been tried to start.
+ * \param success - true, when the operation was successful.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118 D-Rev
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnNetworkStartupV3( void *source, bool success );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever the MOST had been tried to shutdown.
+ * \param success - true, when the operation was successful.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118 D-Rev
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnNetworkShutdownV3( void *source, bool success );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a MAC address has been changed in the network.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddress - The device with this MOST node address raised this event.
+ * \param macAddress1 - The 1st byte of the MAC address.
+ * \param macAddress2 - The 2nd byte of the MAC address.
+ * \param macAddress3 - The 3rd byte of the MAC address.
+ * \param macAddress4 - The 4th byte of the MAC address.
+ * \param macAddress5 - The 5th byte of the MAC address.
+ * \param macAddress6 - The 6th byte of the MAC address.
+ * \note This is event will be raised by all INIC APIS (V1 & V2).
+ */
+ /*----------------------------------------------------------*/
+ virtual void 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 );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a Device type has been detected.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param nodeAddress - The device with this MOST node address raised this event.
+ * \param deviceType - Identifier which sorts the MOST device to a specific function group.
+ * \note In this implementation the Device Type is simply derived from the Group Address set in the INIC config string!
+ * \note This is event will be raised by all INIC APIS (V1 & V2).
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnMostDeviceType( void *source, bool success, uint16_t nodeAddress, uint16_t deviceType );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever the TSI bus was opened.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddress - The device with this MOST node address raised this event.
+ * \note This is an INIC API Version 1 event. It is raised from e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnOpenTsiV1( void *source, bool success, uint16_t nodeAddress );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a TSI socket was created.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \param tsiPortInst - The use TSI port.
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param blockWidthMlb - The block width in bytes allocated on the MLB bus.
+ * \param mlbChannelAddress - The MLB channel address (even value).
+ * \param socketHandle - Unique handle for this socket. Use this for creating connections or closing this socket again.
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 1 event. It is raised from e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ virtual void 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 );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever the MLB bus was opened.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddress - The device with this MOST node address raised this event.
+ * \note This is an INIC API Version 1 event. It is raised from e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnOpenMlbV1( void *source, bool success, uint16_t nodeAddress );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a MLB socket was created.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param blockWidthMlb - The block width in bytes allocated on the MLB bus.
+ * \param mlbChannelAddress - The MLB channel address (even value).
+ * \param socketHandle - Unique handle for this socket. Use this for creating connections or closing this socket again.
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 1 event. It is raised from e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ virtual void 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 );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a MOST socket was created.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param blockwidthMost - The block width in bytes allocated on the MOST bus.
+ * \param connectionLabel - The MOST connection label, which this socket will be bound.
+ * \param socketHandle - Unique handle for this socket. Use this for creating connections or closing this socket again.
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 1 event. It is raised from e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ virtual void 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 );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever two MOST sockets where connected.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \param inSocketHandle - The user given IN-handle.
+ * \param outSocketHandle - The user given OUT-handle.
+ * \param connectionHandle - Unique handle for this connection. Use this for disconnecting this connection again.
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 1 event. It is raised from e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnConnectSocketsV1( void *source, bool success, uint16_t nodeAddr, uint16_t inSocketHandle,
+ uint16_t outSocketHandle, uint16_t connectionHandle, uint32_t tag );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a MOST socket was deestroyed.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddress - The device with this MOST node address raised this event.
+ * \param handle - The unique handle for this socket. After this call, the handle is invalid.
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 1 event. It is raised from e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnDestroySocketV1( void *source, bool success, uint16_t nodeAddr, uint16_t handle, uint32_t tag );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a MOST connection was disconnected.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddress - The device with this MOST node address raised this event.
+ * \param handle - The unique handle for this connection. After this call, the handle is invalid.
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 1 event. It is raised from e.g. OS81110
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnDisconnectSocketsV1( void *source, bool success, uint16_t nodeAddr, uint16_t handle, uint32_t tag );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a I2S port has been configured.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnOpenI2SPortV1( void *source, bool success, uint16_t nodeAddress, V1I2SPortClkDriveMode_t portMode,
+ V1I2SStreamingDataFormat_t format, uint32_t tag );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a I2S socket has been created.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \param portInstance - The I2S port instance. 0 = Port A, 1 = Port B.
+ * \param epDir - he Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param blockWidthI2S - The block width in bytes allocated on the I2S bus.
+ * \param pin - The physical I2S data pin of the INIC.
+ * \param socketHandle - Unique handle for this socket. Use this for creating connections or destroying this socket again.
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnCreateI2SSocketV1( void *source, bool success, uint16_t nodeAddr, EPDirection_t epDir,
+ uint16_t blockWidthI2S, V1I2SPin_t pin, uint16_t socketHandle, uint32_t tag );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever the MLB bus was opened.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddress - The device with this MOST node address raised this event.
+ * \param mlbPortHandle - The device with this MOST node address raised this event.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnOpenMlbV3( void *source, bool success, uint16_t nodeAddress, uint16_t mlbPortHandle );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a USB socket was created.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param endPointAddress - The USB endpoint address, which is now usable.
+ * \param socketHandle - Unique handle for this socket. Use this for creating connections or closing this socket again.
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnCreateUsbSocketV3( void *source, bool success, uint16_t nodeAddr, EPDataType_t epType,
+ EPDirection_t epDir, uint8_t endPointAddress, uint16_t socketHandle, uint32_t tag );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a USB socket was created, which uses a Splitter or a Combiner.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param endPointAddress - The USB endpoint address, which is now usable.
+ * \param usbHandle - Unique handle for this USB socket. Do not use this for creating connections!
+ * \param splitterHandle - Unique handle for this Splitter socket. Use this for creating connections or closing this socket again!
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void 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 );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a MLB socket was created.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param blockWidthMlb - The block width in bytes allocated on the MLB bus.
+ * \param mlbChannelAddress - The MLB channel address (even value).
+ * \param socketHandle - Unique handle for this socket. Use this for creating connections or closing this socket again.
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void 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 );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a MLB socket was created, which uses a Splitter or a Combiner.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param blockWidthMlb - The block width in bytes allocated on the MLB bus.
+ * \param mlbChannelAddress - The MLB channel address (even value).
+ * \param mlbSocketHandle - Unique handle for this socket. Use this for creating connections or closing this socket again.
+ * \param splitterHandle - Unique handle for this Splitter socket. Use this for creating connections or closing this socket again!
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void 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 );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a MOST socket was created.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \param epType - The data type, which then will be transmitted on this endpoint.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param blockwidthMost - The block width in bytes allocated on the MOST bus.
+ * \param connectionLabel - The MOST connection label, which this socket will be bound.
+ * \param socketHandle - Unique handle for this socket. Use this for creating connections or destroying this socket again.
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void 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 );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever two MOST sockets where connected.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \param epType - The data type, which then will be transmitted on this connection.
+ * \param inSocketHandle - The user given IN-handle.
+ * \param outSocketHandle - The user given OUT-handle.
+ * \param connectionHandle - Unique handle for this connection. Use this for destroying this connection again.
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnConnectSocketsV3( void *source, bool success, uint16_t nodeAddr, EPDataType_t epType,
+ uint16_t inSocketHandle, uint16_t outSocketHandle, uint16_t connectionHandle, uint32_t tag );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever MOST resources where destroyed.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \param amountOfHandles - The amount of resources to be destroyed. (value will be between 1 to 3).
+ * \param pHandle - Pointer to the resource list
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnResourceDestroyV3( void *source, bool success, uint16_t nodeAddr, uint8_t amountOfHandles,
+ const uint16_t *pHandle, uint32_t tag );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a I2S port has been configured.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \param portInstance - The I2S port instance. 0 = Port A, 1 = Port B.
+ * \param option - The I2S port option.
+ * \param mode - The I2S clock mode.
+ * \param delay - The I2S delay mode.
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnConfigureI2SPortV3( void *source, bool success, uint16_t nodeAddr, uint8_t portInstance,
+ V3I2SPortOption_t option, V3I2SClockMode_t mode, V3I2SDelayMode_t delay, uint32_t tag );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a I2S port has been created.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \param portInstance - The I2S port instance. 0 = Port A, 1 = Port B.
+ * \param clock - The I2S port speed in multiple of MOST base clock.
+ * \param align - The I2S data format alignment.
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnCreateI2SPortV3( void *source, bool success, uint16_t nodeAddr, uint8_t portInstance,
+ V3I2SPortSpeed_t clock, V3I2SAlignment_t align, uint32_t tag );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a I2S socket has been created.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \param portInstance - The I2S port instance. 0 = Port A, 1 = Port B.
+ * \param epDir - he Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param blockWidthI2S - The block width in bytes allocated on the I2S bus.
+ * \param pin - The physical I2S data pin of the INIC.
+ * \param socketHandle - Unique handle for this socket. Use this for creating connections or destroying this socket again.
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void 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 );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when ever a I2S socket has been created, which uses a Splitter or a Combiner.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \param portInstance - The I2S port instance. 0 = Port A, 1 = Port B.
+ * \param epDir - The Direction of the stream. (EPDIR_IN == Data from the INIC to the EHC, EPDIR_OUT == Data from the EHC to the INIC)
+ * \param blockWidthI2S - The block width in bytes allocated on the I2S bus.
+ * \param pin - The physical I2S data pin of the INIC.
+ * \param i2sSocketHandle - Unique handle for this socket. Use this for creating connections or destroying this socket again.
+ * \param splitterHandle - Unique handle for this Splitter socket. Use this for creating connections or closing this socket again!
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void 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 );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when a Ring Break Diagnosis Result was received.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param nodeAddr - The device with this MOST node address raised this event.
+ * \praram result - The ring break diagnosis result
+ * \param position - Relative position to the ring break.
+ * \param status - Gives information about the activity state.
+ * \param id - The RBD identifier as configured in config string.
+ * \note This is an INIC API Version 3 event. It is raised from e.g. OS81118
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnRbdResultV3( void *source, uint16_t nodeAddress, uint8_t result, uint8_t position,
+ uint8_t status, uint16_t id );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Callback, when the MOST control channel receive thread has ended.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ */
+ /*----------------------------------------------------------*/
+ virtual void OnControlChannelReadEnd( void *source );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief This callback method is called whenever a MOST control message was sent or received.
+ * \note In order to be informed about this event, derive this class, implement this method and register the class with AddListener method of CNetwork class.
+ * \note The user may interpret the data and sent a corresponding MOST control message via CNetwork::SendMostControlMessage.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param sourceAddr - The MOST source address (may be not accurate)
+ * \param targetAddr - The MOST target address
+ * \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.
+ *
+ */
+ /*----------------------------------------------------------*/
+ virtual void 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 );
+
+ /*----------------------------------------------------------*/
+ /*! \brief This callback method is as result of the DeviceVersion query.
+ * \param source - Cast this pointer to (CNetworkDevice*), it points to server network device, which received this event.
+ * \param success - true, when the operation was successful.
+ * \param sourceAddr - The device with this MOST node address raised this event.
+ * \param productId - Unique identifier that represents the product name.
+ * \param fwVersion - INIC firmware version: Byte[3] Major, Byte[2] Minor, Byte[1] Release.
+ * \param buildVersion - Build version of the firmware.
+ * \param hwVersion - Chip revision number.
+ * \param diagnosisId - Unique diagnosis identifier of the device.
+ * \param tag - Any 32 bit value. This value was passed to the corresponding function call of the CNetworkDevice class.
+ */
+ /*----------------------------------------------------------*/
+ virtual void 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 );
+
+};
+
+#endif //_NETWORKDEVICELISTENER_H_
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
diff --git a/Src/Network/Network_Private.cpp b/Src/Network/Network_Private.cpp
new file mode 100644
index 0000000..2aaef6e
--- /dev/null
+++ b/Src/Network/Network_Private.cpp
@@ -0,0 +1,695 @@
+/*
+ * 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()
+#define MAX_MOST_DEVICES 4
+
+void CNetwork::DestroyAllResources( CNetworkDevice *device, uint16_t nodeAddress )
+{
+ if( NULL == device )
+ return;
+
+ CNodeEntry *node = CNodeEntry::GetNodeEntry( device->GetDeviceIndex(), nodeAddress );
+ if( NULL == node )
+ return;
+
+ sem_wait( &vodXmlMutex );
+ uint32_t apiVer = vodXml->GetDeviceApi( node->deviceType );
+ sem_post( &vodXmlMutex );
+ if( 1 == apiVer )
+ {
+ for( int i = 0; i < node->GetAmountOfConnections(); i++ )
+ {
+ CNodeConnectionEntry *connection = node->GetConnectionByIndex( i );
+ if( NULL == connection || NULL == connection->channelConfig )
+ continue;
+
+ uint32_t inHandle = connection->inHandle;
+ uint32_t outHandle = connection->outHandle;
+ uint32_t conHandle = connection->connectHandle;
+ NodeConnectionState_t inState = connection->inSocketState;
+ NodeConnectionState_t outState = connection->outSocketState;
+ NodeConnectionState_t conState = connection->connectedSocketState;
+ uint32_t channelId = connection->channelConfig->channelId;
+ connection->deviceName[0] = '\0';
+ connection->mostConnectionLabel = 0xFFFFFFFF;
+ connection->inHandle = 0xFFFFFFFF;
+ connection->outHandle = 0xFFFFFFFF;
+ connection->connectHandle = 0xFFFFFFFF;
+ connection->inSocketState = NodeConnection_NotUsed;
+ connection->outSocketState = NodeConnection_NotUsed;
+ connection->connectedSocketState = NodeConnection_NotUsed;
+ if( NodeConnection_NotUsed != conState && 0xFFFFFFFF != conHandle )
+ {
+ device->DisconnectSocketsV1( nodeAddress, conHandle, channelId );
+ }
+ if( NodeConnection_NotUsed != inState && 0xFFFFFFFF != inHandle )
+ {
+ device->DestroySocketV1( nodeAddress, inHandle, channelId );
+ }
+ if( NodeConnection_NotUsed != outState && 0xFFFFFFFF != outHandle )
+ {
+ device->DestroySocketV1( nodeAddress, outHandle, channelId );
+ }
+ RaiseUnavailable( connection );
+ }
+ }
+ else if( 2 == apiVer || 3 == apiVer )
+ {
+ uint8_t amount;
+#define MAX_DESTROY_ELEMENTS 10
+ uint16_t handles[MAX_DESTROY_ELEMENTS];
+
+ //Start to destroy the connections first:
+ do
+ {
+ amount = 0;
+ for( int i = 0; amount < MAX_DESTROY_ELEMENTS && i < node->GetAmountOfConnections(); i++ )
+ {
+ CNodeConnectionEntry *connection = node->GetConnectionByIndex( i );
+ if( NULL == connection || NULL == connection->channelConfig )
+ continue;
+ if( NodeConnection_NotUsed != connection->connectedSocketState )
+ {
+ handles[amount++] = connection->connectHandle;
+ connection->connectHandle = 0xFFFFFFFF;
+ connection->connectedSocketState = NodeConnection_NotUsed;
+ }
+ }
+ if( amount != 0 )
+ {
+ device->ResourceDestroyV3( nodeAddress, amount, handles, 0 );
+ }
+ }
+ while( amount != 0 );
+
+ do
+ {
+ amount = 0;
+ //Continue to destroy the In and Out sockets:
+ for( int i = 0; amount < MAX_DESTROY_ELEMENTS && i < node->GetAmountOfConnections(); i++ )
+ {
+ CNodeConnectionEntry *connection = node->GetConnectionByIndex( i );
+ if( NULL == connection || NULL == connection->channelConfig )
+ continue;
+ if( ( NodeConnection_NotUsed != connection->inSocketState )
+ && ( 0xFFFFFFFF != connection->inHandle ) )
+ {
+ handles[amount++] = connection->inHandle;
+ for( int j = 0; j < node->GetAmountOfConnections(); j++ )
+ {
+ if( i == j )
+ continue;
+ CNodeConnectionEntry *otherConn = node->GetConnectionByIndex( j );
+ if( ( otherConn != NULL ) && ( otherConn->inHandle == connection->inHandle ) )
+ {
+ otherConn->inHandle = 0xFFFFFFFF;
+ otherConn->inSocketState = NodeConnection_NotUsed;
+ }
+ }
+ connection->inHandle = 0xFFFFFFFF;
+ connection->inSocketState = NodeConnection_NotUsed;
+ }
+ if( amount < MAX_DESTROY_ELEMENTS &&
+ ( NodeConnection_NotUsed != connection->outSocketState )
+ && ( 0xFFFFFFFF != connection->outHandle ) )
+ {
+ handles[amount++] = connection->outHandle;
+ for( int j = 0; j < node->GetAmountOfConnections(); j++ )
+ {
+ if( i == j )
+ continue;
+ CNodeConnectionEntry *otherConn = node->GetConnectionByIndex( j );
+ if( ( otherConn != NULL ) && ( otherConn->outHandle == connection->outHandle ) )
+ {
+ otherConn->outHandle = 0xFFFFFFFF;
+ otherConn->outSocketState = NodeConnection_NotUsed;
+ }
+ }
+ connection->outHandle = 0xFFFFFFFF;
+ connection->outSocketState = NodeConnection_NotUsed;
+ RaiseUnavailable( connection );
+ }
+
+ }
+ if( amount != 0 )
+ {
+ device->ResourceDestroyV3( nodeAddress, amount, handles, 0 );
+ }
+ }
+ while( amount != 0 );
+
+ //Last step destroy Splitter / Combiner input / output
+ do
+ {
+ amount = 0;
+ for( int i = 0; i < node->GetAmountOfConnections(); i++ )
+ {
+ CNodeConnectionEntry *connection = node->GetConnectionByIndex( i );
+ if( NULL == connection || NULL == connection->channelConfig )
+ continue;
+ if( 0xFFFFFFFF != connection->splittedSourceHandle )
+ {
+ handles[amount++] = connection->splittedSourceHandle;
+ for( int j = 0; j < node->GetAmountOfConnections(); j++ )
+ {
+ if( i == j )
+ continue;
+ CNodeConnectionEntry *otherConn = node->GetConnectionByIndex( j );
+ if( ( otherConn != NULL ) && ( otherConn->splittedSourceHandle == connection->
+ splittedSourceHandle ) )
+ {
+ otherConn->splittedSourceHandle = 0xFFFFFFFF;
+ }
+ }
+ connection->splittedSourceHandle = 0xFFFFFFFF;
+ }
+ }
+ if( amount != 0 )
+ {
+ device->ResourceDestroyV3( nodeAddress, amount, handles, 0 );
+ }
+ }
+ while( amount != 0 );
+ }
+}
+
+void CNetwork::DestroyAllResources()
+{
+ CNetworkDevice *device;
+ uint16_t nodeAmount = CNodeEntry::GetAmountOfNodeEntries();
+ for( int i = 0; i < nodeAmount; i++ )
+ {
+ CNodeEntry *node = CNodeEntry::GetNodeEntry( i );
+ if( NULL == node )
+ continue;
+ CNetworkDevice *device = GetNetworkDevice( node->deviceInstance );
+ uint16_t nodeAddress = node->nodeAddress;
+ DestroyAllResources( device, nodeAddress );
+ }
+ for( uint32_t i = 0; i < allNetworkDevices.Size(); i++ )
+ {
+ device = allNetworkDevices[i];
+ if( NULL != device )
+ {
+ sem_wait( &vodXmlMutex );
+ if( NULL != vodXml )
+ {
+ sem_post( &vodXmlMutex );
+ if( device->IsTimingMaster() )
+ {
+ ConsolePrintf( PRIO_MEDIUM, "DestroyAllResources, Performing MOST Shutdown index: %d\n",
+ device->GetDeviceIndex() );
+ device->ToggleNotOk();
+ device->SetNetstate( NetworkState_ShutdownInProgress );
+ device->MostNetworkShutdownV3();
+ }
+ }
+ else
+ sem_post( &vodXmlMutex );
+ }
+ }
+ PRINT_ALL_INFOS();
+}
+
+void CNetwork::CloseAllNetworkDevices()
+{
+ DestroyAllResources();
+ CNetworkDevice *device;
+ for( uint32_t i = 0; i < allNetworkDevices.Size(); i++ )
+ {
+ device = allNetworkDevices[i];
+ if( NULL != device )
+ {
+ ConsolePrintf( PRIO_MEDIUM, "CloseAllNetworkDevices, Closing device index: %d\n",
+ device->GetDeviceIndex() );
+ device->Close();
+ }
+ }
+ allNetworkDevices.RemoveAll(true);
+ connectionBitMask = 0;
+}
+
+void CNetwork::FindNewNetworkDevices()
+{
+ sem_wait( &vodXmlMutex );
+ if( NULL == vodXml )
+ {
+ sem_post( &vodXmlMutex );
+ return;
+ }
+ bool success = false;
+ bool infoQueried = false;
+ uint8_t *controlRxAddress = NULL;
+ uint8_t *controlTxAddress = NULL;
+ uint32_t *apiVersion = NULL;
+ SocketPort_t *hwPort = NULL;
+ bool *isTimingMaster = NULL;
+ uint32_t *asyncBW = NULL;
+ uint8_t serverNum = 0;
+ for( uint8_t devInstance = 0; devInstance < MAX_MOST_DEVICES; devInstance++ )
+ {
+ if( 0 != ( connectionBitMask & ( 1 << devInstance ) ) )
+ continue;
+
+ if( !infoQueried )
+ infoQueried = vodXml->GetLocalInicConfigurations( &controlRxAddress, &controlTxAddress, &apiVersion,
+ &hwPort, &isTimingMaster, &asyncBW, &serverNum );
+
+ if( !infoQueried )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Can not parse XML file to configure server device"RESETCOLOR"\n" );
+ sem_post( &vodXmlMutex );
+ return;
+ }
+ for( uint8_t conIndex = 0; conIndex < serverNum; conIndex++ )
+ {
+ if( ( ( PORT_MLB == hwPort[conIndex] ) && ExistsMlbDeviceInstance( devInstance ) )
+ || ( ( PORT_USB == hwPort[conIndex] ) && ExistsUsbDeviceInstance( devInstance ) ) )
+ {
+ connectionBitMask += ( 1 << devInstance );
+ ConsolePrintf( PRIO_MEDIUM, "=======Server %d device uses %s, INIC API V%d=======\n",
+ devInstance, ( PORT_USB == hwPort[conIndex] ? "USB" : PORT_MLB == hwPort[conIndex] ? "MLB" :
+ "UNKNOWN" ), apiVersion[conIndex] );
+ ConsolePrintf( PRIO_MEDIUM, "Opening device instance %d\n", devInstance );
+ CNetworkDevice *newDevice = new CNetworkDevice( devInstance,
+ apiVersion[conIndex], isTimingMaster[conIndex], asyncBW[conIndex], promiscuous );
+ switch( hwPort[conIndex] )
+ {
+ case PORT_USB:
+ success = newDevice->OpenUsb( controlRxAddress[conIndex], controlTxAddress[conIndex] );
+ break;
+ case PORT_MLB:
+ success = newDevice->OpenMlb( controlRxAddress[conIndex], controlTxAddress[conIndex] );
+ break;
+ default:
+ success = false;
+ break;
+ }
+ if( success )
+ {
+ allNetworkDevices.PushBack( newDevice );
+ newDevice->AddListener( this );
+ }
+ else
+ {
+ if( ( PORT_USB == hwPort[conIndex] ) && ( apiVersion[conIndex] < 3 ) )
+ ConsolePrintf( PRIO_ERROR, RED"Failed to open device instance %d"\
+ RESETCOLOR"\n", devInstance );
+ delete newDevice;
+ }
+ }
+ }
+ }
+ if( NULL != controlRxAddress )
+ free( controlRxAddress );
+ if( NULL != controlTxAddress )
+ free( controlTxAddress );
+ if( NULL != apiVersion )
+ free( apiVersion );
+ if( NULL != hwPort )
+ free( hwPort );
+ sem_post( &vodXmlMutex );
+}
+
+void CNetwork::TryToCreateRoute( uint32_t devInstance, bool mostIsTx, void *e, void *t )
+{
+ if( NULL == e || NULL == t )
+ return;
+ CNodeEntry *entry = ( CNodeEntry * )e;
+ CRouteTerminal *terminal = ( CRouteTerminal * )t;
+ CSafeVector<CRouteTerminal *> connectedTerminals;
+
+ sem_wait( &vodXmlMutex );
+ bool found = vodXml->GetRouteTerminals( terminal, connectedTerminals );
+ sem_post( &vodXmlMutex );
+ if( !found )
+ return;
+ CNodeEntry *oppositeEntry = NULL;
+ for( uint32_t i = 0; i < connectedTerminals.Size(); i++ )
+ {
+ if( NULL != ( oppositeEntry = CNodeEntry::GetNodeEntry( devInstance, connectedTerminals[i]->deviceType,
+ connectedTerminals[i]->instance ) ) )
+ {
+ if( mostIsTx )
+ ConnectSourceToSink( entry, oppositeEntry, terminal->channelId, connectedTerminals[i]->channelId );
+ else
+ ConnectSourceToSink( oppositeEntry, entry, connectedTerminals[i]->channelId, terminal->channelId );
+ }
+ delete connectedTerminals[i];
+ }
+}
+
+void CNetwork::TryToConnectSockets( uint32_t devInstance, uint16_t nodeAddr, uint32_t channelId )
+{
+ CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddr );
+ if( NULL != entry )
+ {
+ CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( channelId, true );
+ CNetworkDevice *device = GetNetworkDevice( devInstance );
+ CChannelConfiguration *config = connection->channelConfig;
+ sem_wait( &vodXmlMutex );
+ uint32_t deviceApi = vodXml->GetDeviceApi( connection->channelConfig->deviceType );
+ sem_post( &vodXmlMutex );
+ if( ( NULL != connection ) && ( NULL != device ) && ( NULL != config ) )
+ {
+ CRouteTerminal terminal;
+ terminal.channelId = channelId;
+ terminal.deviceType = entry->deviceType;
+ terminal.instance = CNodeEntry::GetTerminalInstance( devInstance, nodeAddr, entry->deviceType );
+
+ if( ( NodeConnection_Used == connection->inSocketState )
+ && ( NodeConnection_Used == connection->outSocketState )
+ && ( NodeConnection_NotUsed == connection->connectedSocketState ) )
+ {
+ if( deviceApi > 3 )
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"TryToConnectSockets found unknown device API version: %d"RESETCOLOR"\n",
+ deviceApi );
+ return;
+ }
+ connection->connectedSocketState = NodeConnection_Pending_Up;
+ if( 1 == deviceApi )
+ {
+ device->ConnectSocketsV1( nodeAddr, connection->inHandle, connection->outHandle, channelId );
+ }
+ else if( ( 2 == deviceApi ) || ( 3 == deviceApi ) )
+ {
+ uint32_t offset = config->inSocket.splittedOffset;
+ if( 0xFFFFFFFF == offset )
+ {
+ offset = config->outSocket.splittedOffset;
+ if( 0xFFFFFFFF == offset )
+ offset = 0;
+ }
+ device->ConnectSocketsV3( nodeAddr, config->outSocket.type, connection->inHandle,
+ connection->outHandle, offset, channelId );
+ }
+ TryToCreateRoute( devInstance, true, entry, &terminal );
+ }
+ else if( ( NodeConnection_NotUsed == connection->inSocketState )
+ && ( NodeConnection_Used == connection->outSocketState )
+ && ( PORT_MOST == config->inSocket.port ) )
+ {
+ TryToCreateRoute( devInstance, false, entry, &terminal );
+ }
+ }
+ }
+ PRINT_ALL_INFOS();
+}
+
+void CNetwork::TryToCloseExistingMostConnection( void *inNode, uint32_t inChannelId, void *outNode,
+ uint32_t outChannelId )
+{
+ if( ( NULL == inNode ) || ( NULL == outNode ) )
+ return;
+
+ for( uint8_t i = 0; i < 2; i++ )
+ {
+ CNodeConnectionEntry *closeEntry = NULL;
+ switch( i )
+ {
+ case 0:
+ closeEntry = ( ( CNodeEntry * )outNode )->GetConnectionByChannelId( outChannelId, false );
+ break;
+ case 1:
+ closeEntry = ( ( CNodeEntry * )inNode )->GetConflictingConnection( inChannelId,
+ ( ( CNodeEntry * )outNode ) );
+ break;
+ }
+ if( NULL == closeEntry || NULL == closeEntry->channelConfig
+ || NULL == closeEntry->parentNode )
+ continue;
+
+ if( ( NodeConnection_Used == closeEntry->inSocketState ) &&
+ ( NodeConnection_Used == closeEntry->connectedSocketState ) &&
+ ( PORT_MOST == closeEntry->channelConfig->inSocket.port ) )
+ {
+ uint8_t oppInst = closeEntry->parentNode->deviceInstance;
+ CNetworkDevice *oppDevice = GetNetworkDevice( oppInst );
+ if( NULL != oppDevice )
+ {
+ uint16_t oppNodeAddress = closeEntry->parentNode->nodeAddress;
+ uint32_t oppApiVer = closeEntry->parentNode->deviceType;
+ uint32_t oppConHandle = closeEntry->connectHandle;
+ uint32_t oppInHandle = closeEntry->inHandle;
+ uint32_t oppChannelId = closeEntry->channelId;
+
+ closeEntry->connectedSocketState = NodeConnection_Pending_Down;
+ closeEntry->inSocketState = NodeConnection_Pending_Down;
+
+ if( 1 == oppApiVer )
+ {
+ oppDevice->DisconnectSocketsV1( oppNodeAddress, oppConHandle, oppChannelId );
+ oppDevice->DestroySocketV1( oppNodeAddress, oppInHandle, oppChannelId );
+ }
+ else if( 2 == oppApiVer || 3 == oppApiVer )
+ {
+ uint16_t a[2];
+ a[0] = oppConHandle;
+ a[1] = oppInHandle;
+ oppDevice->ResourceDestroyV3( oppNodeAddress, 2, a, oppChannelId );
+ }
+ }
+ }
+ }
+ PRINT_ALL_INFOS();
+}
+
+void CNetwork::RaiseAvailable( void *con )
+{
+ CNodeConnectionEntry *connection = ( CNodeConnectionEntry * )con;
+ if( ( NULL != connection )
+ && ( NULL != connection->parentNode )
+ && ( NULL != connection->channelConfig )
+ )
+ {
+ uint32_t blockWidth = connection->channelConfig->outSocket.blockWidth;
+ if( 0xFFFFFFFF == blockWidth )
+ blockWidth = connection->channelConfig->inSocket.blockWidth;
+
+ uint16_t xact = 0;
+ if ( PORT_USB == connection->channelConfig->inSocket.port )
+ xact = connection->channelConfig->inSocket.packetsPerTransaction;
+ else if ( PORT_USB == connection->channelConfig->outSocket.port )
+ xact = connection->channelConfig->outSocket.packetsPerTransaction;
+
+ uint32_t devInst = CNodeEntry::GetTerminalInstance( connection->parentNode->deviceInstance,
+ connection->parentNode->nodeAddress, connection->parentNode->deviceType );
+ for( uint32_t i = 0; i < allListeners.Size(); i++ )
+ {
+ int offset = -1;
+ int maxBW = -1;
+ if( 0xFFFFFFFF != connection->channelConfig->inSocket.splittedOffset )
+ {
+ offset = connection->channelConfig->inSocket.splittedOffset;
+ maxBW = connection->channelConfig->inSocket.subbufferSize;
+ }
+ else if( 0xFFFFFFFF != connection->channelConfig->outSocket.splittedOffset )
+ {
+ offset = connection->channelConfig->outSocket.splittedOffset;
+ maxBW = connection->channelConfig->outSocket.subbufferSize;
+ }
+ allListeners[i]->OnChannelAvailable( connection->parentNode->macAddress,
+ connection->parentNode->deviceType, devInst, connection->channelId,
+ connection->parentNode->deviceInstance, connection->channelConfig->outSocket.type,
+ blockWidth, ( PORT_MOST == connection->channelConfig->outSocket.port ), ( NodeConnection_Used ==
+ connection->inSocketState ), ( NodeConnection_Used == connection->outSocketState ),
+ ( NodeConnection_Used == connection->connectedSocketState ), connection->bufferSize,
+ connection->mostConnectionLabel, offset, maxBW, xact, connection->deviceName );
+ }
+ }
+}
+
+void CNetwork::RaiseUnavailable( void *con )
+{
+ CNodeConnectionEntry *connection = ( CNodeConnectionEntry * )con;
+ if( ( NULL != connection )
+ && ( NULL != connection->parentNode )
+ && ( NULL != connection->channelConfig )
+ && ( NULL != connection->parentNode->macAddress )
+ )
+ {
+ for( uint32_t i = 0; i < allListeners.Size(); i++ )
+ {
+ allListeners[i]->OnChannelUnavailable( connection->parentNode->macAddress, connection->channelId,
+ connection->parentNode->deviceInstance );
+ }
+ }
+}
+
+CNetworkDevice *CNetwork::GetNetworkDevice( uint32_t devInstance )
+{
+ CNetworkDevice *device = NULL;
+ for( uint32_t i = 0; i < allNetworkDevices.Size(); i++ )
+ {
+ if( devInstance == allNetworkDevices[i]->GetDeviceIndex() )
+ {
+ device = allNetworkDevices[i];
+ break;
+ }
+ }
+ return device;
+}
+
+CMacAddr *CNetwork::SetMacAddress( CNetworkDevice *device, uint32_t devInstance, uint16_t nodeAddress,
+ uint8_t inicApiVersion )
+{
+ if( NULL == device )
+ return NULL;
+ CMacAddr *mac = new CMacAddr( devInstance, nodeAddress );
+ if( NULL == mac )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"Failed to instance CMacAddr object"RESETCOLOR"\n" );
+ return NULL;
+ }
+ ConsolePrintf( PRIO_MEDIUM,
+ "Creating local MAC for deviceInstance:%d: nodeAddress:0x%X, MAC-Address:%02X-%02X-%02X-%02X-%02X-%02X)\n",
+ devInstance, nodeAddress, ( *mac )[0], ( *mac )[1], ( *mac )[2], ( *mac )[3], ( *mac )[4], ( *mac )[5] );
+
+ switch( inicApiVersion )
+ {
+ case 1:
+ device->SetMostMacAddressV1( nodeAddress, ( *mac )[0], ( *mac )[1], ( *mac )[2], ( *mac )[3], ( *mac )[4],
+ ( *mac )[5], false );
+ break;
+ case 2:
+ device->SetMostMacAddressV3( nodeAddress, ( *mac )[0], ( *mac )[1], ( *mac )[2], ( *mac )[3], ( *mac )[4],
+ ( *mac )[5] );
+ break;
+ case 3:
+ device->SetMostMacAddressV3( nodeAddress, ( *mac )[0], ( *mac )[1], ( *mac )[2], ( *mac )[3], ( *mac )[4],
+ ( *mac )[5] );
+ break;
+ default:
+ ConsolePrintf(
+ PRIO_ERROR, RED"Can not set local MAC, because device API version (%d) is unknown"RESETCOLOR"\n",
+ inicApiVersion );
+ delete mac;
+ mac = NULL;
+ break;
+ }
+ return mac;
+}
+
+bool CNetwork::ConnectSourceToSink( void *mostTxNode, void *mostRxNode, uint32_t sourceChannelId,
+ uint32_t sinkChannelId )
+{
+ bool success = false;
+ PRINT_ALL_INFOS();
+ if( ( NULL != mostTxNode ) && ( NULL != mostRxNode ) )
+ {
+ CNodeEntry *txNode = ( CNodeEntry * )mostTxNode;
+ CNodeEntry *rxNode = ( CNodeEntry * )mostRxNode;
+ CNodeConnectionEntry *inConnection = txNode->GetConnectionByChannelId( sourceChannelId, false );
+ CNodeConnectionEntry *outConnection = rxNode->GetConnectionByChannelId( sinkChannelId, false );
+ CNetworkDevice *outDevice = GetNetworkDevice( rxNode->deviceInstance );
+ if( ( NULL != inConnection ) && ( NULL != outConnection ) && ( NULL != outDevice )
+ && ( NULL != outConnection->channelConfig ) && ( 0xFFFFFFFF != inConnection->mostConnectionLabel ) )
+ {
+ if( ( NodeConnection_Used == inConnection->outSocketState )
+ && ( NodeConnection_NotUsed == outConnection->inSocketState ) )
+ {
+ uint32_t connectionLabel = inConnection->mostConnectionLabel;
+ sem_wait( &vodXmlMutex );
+ uint32_t inApiVer = vodXml->GetDeviceApi( txNode->deviceType );
+ uint32_t outApiVer = vodXml->GetDeviceApi( rxNode->deviceType );
+ sem_post( &vodXmlMutex );
+ ConsolePrintf( PRIO_MEDIUM,
+ BLUE"CNetwork::ConnectSourceToSink Connection Label:0x%X, IN-API-Ver:%d, OUT-API-Ver:%d, devIndex:%d, address:0x%X"RESETCOLOR"\n",
+ connectionLabel, inApiVer, outApiVer, rxNode->deviceInstance,
+ rxNode->nodeAddress );
+ TryToCloseExistingMostConnection( txNode, sourceChannelId, rxNode, sinkChannelId );
+ if( 1 == outApiVer )
+ {
+ outDevice->CreateMostSocketV1( rxNode->nodeAddress, outConnection->channelConfig->inSocket.type,
+ EPDIR_IN, connectionLabel, outConnection->channelConfig->inSocket.blockWidth, sinkChannelId );
+ success = true;
+ }
+ else if( 2 == outApiVer || 3 == outApiVer )
+ {
+ outDevice->CreateMostSocketV3( rxNode->nodeAddress, outConnection->channelConfig->inSocket.type,
+ EPDIR_IN, connectionLabel, outConnection->channelConfig->inSocket.blockWidth, sinkChannelId );
+ success = true;
+ }
+ if( success )
+ {
+ outConnection->inSocketState = NodeConnection_Pending_Up;
+ outConnection->mostConnectionLabel = connectionLabel;
+ }
+ }
+ }
+ }
+ else
+ {
+ ConsolePrintf(
+ PRIO_ERROR, RED"CNetwork::SetSinkToChannel failed to resolve given MAC addresses"RESETCOLOR"\n" );
+ }
+ PRINT_ALL_INFOS();
+ return success;
+}
+
+void CNetwork::RaiseUknownConnection( uint32_t devInstance, uint16_t nodeAddress, EPDataType_t dType )
+{
+ CNodeEntry *entry = CNodeEntry::GetNodeEntry( devInstance, nodeAddress );
+ CNodeConnectionEntry *connection = entry->GetConnectionByChannelId( 0xFF, true );
+ entry->macAddress = new CMacAddr( devInstance, nodeAddress );
+ connection->channelConfig = new CChannelConfiguration();
+ connection->channelConfig->inSocket.type = dType;
+ connection->channelConfig->outSocket.type = dType;
+ RaiseAvailable( connection );
+}
+
+void CNetwork::ShutdownMost( CNetworkDevice *device )
+{
+ if( NULL == device )
+ return;
+ device->ClearAllPendingActions();
+ device->SetNetstate( NetworkState_ShutdownInProgress );
+ device->MostNetworkShutdownV3();
+}
+
+void CNetwork::ShutdownMostBecauseOfErrors( CNetworkDevice *device )
+{
+ if (retryCounter < 5)
+ {
+ retryExecTime = GetTickCount();
+ retryCounter++;
+ ConsolePrintf(
+ PRIO_ERROR, RED"Restart MOST because of resources allocation /"\
+ " configuration problems, retry count=%d"RESETCOLOR"\n", retryCounter );
+ ShutdownMost( device );
+ }
+} \ No newline at end of file
diff --git a/Src/Network/NodeDatabase.cpp b/Src/Network/NodeDatabase.cpp
new file mode 100644
index 0000000..d53d2d1
--- /dev/null
+++ b/Src/Network/NodeDatabase.cpp
@@ -0,0 +1,287 @@
+/*
+ * 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 <stdio.h>
+#include <stddef.h>
+#include "Console.h"
+#include "NodeDatabase.h"
+
+CSafeVector<CNodeEntry *> CNodeEntry::allNodes;
+
+CNodeConnectionEntry::CNodeConnectionEntry( CNodeEntry *parent ) : parentNode( parent ), channelConfig( NULL ),
+ channelId( 0xFFFFFFFF ), inHandle( 0xFFFFFFFF ),
+ outHandle( 0xFFFFFFFF ),
+ connectHandle( 0xFFFFFFFF ),
+ splittedSourceHandle( 0xFFFFFFFF ),
+ mostConnectionLabel( 0xFFFFFFFF ),
+ inSocketState( NodeConnection_NotUsed ),
+ outSocketState( NodeConnection_NotUsed ),
+ connectedSocketState( NodeConnection_NotUsed ),
+ bufferSize( -1 )
+{
+ memset( deviceName, 0, sizeof( deviceName ) );
+};
+
+CNodeConnectionEntry::~CNodeConnectionEntry()
+{
+ if( NULL != channelConfig )
+ {
+ delete channelConfig;
+ channelConfig = NULL;
+ }
+}
+
+CNodeEntry::CNodeEntry() : deviceInstance( 0xFF ), nodeAddress( 0xFFFF ), deviceType( 0xFFFF ), macAddress( NULL ),
+ isTsiPortOpened(false), isMlbPortOpened( false ), isUsbPortOpened( false ), isI2SPortOpened( false )
+{
+}
+
+CNodeEntry::~CNodeEntry()
+{
+ if( NULL != macAddress )
+ delete macAddress;
+}
+
+uint16_t CNodeEntry::GetAmountOfNodeEntries()
+{
+ return allNodes.Size();
+}
+
+CNodeEntry *CNodeEntry::GetNodeEntry( uint16_t index )
+{
+ return allNodes[index];
+}
+
+CNodeEntry *CNodeEntry::GetNodeEntry( uint8_t deviceInstance, uint16_t nodeAddress )
+{
+ CNodeEntry *entry = NULL;
+ for( uint32_t i = 0; i < allNodes.Size(); i++ )
+ {
+ if( ( allNodes[i]->deviceInstance == deviceInstance )
+ && ( allNodes[i]->nodeAddress == nodeAddress ) )
+ {
+ entry = allNodes[i];
+ break;
+ }
+ }
+ if( NULL == entry )
+ {
+ entry = new CNodeEntry();
+ entry->deviceInstance = deviceInstance;
+ entry->nodeAddress = nodeAddress;
+ allNodes.PushBack( entry );
+ }
+ return entry;
+}
+
+CNodeEntry *CNodeEntry::GetNodeEntry( CMacAddr *macAddress )
+{
+ if( NULL == macAddress )
+ return NULL;
+ CNodeEntry *entry = NULL;
+ for( uint32_t i = 0; i < allNodes.Size(); i++ )
+ {
+ CNodeEntry *node = allNodes[i];
+ if( ( NULL != node->macAddress ) && ( *node->macAddress == *macAddress ) )
+ {
+ entry = node;
+ break;
+ }
+ }
+ return entry;
+}
+
+CNodeEntry *CNodeEntry::GetNodeEntry( uint8_t deviceInstance, uint32_t deviceType, uint32_t terminalInstance )
+{
+ uint32_t inst = 0;
+ CNodeEntry *entry = NULL;
+ for( uint32_t i = 0; i < allNodes.Size(); i++ )
+ {
+ CNodeEntry *node = allNodes[i];
+ if( ( allNodes[i]->deviceInstance == deviceInstance )
+ && ( allNodes[i]->deviceType == deviceType ) )
+ {
+ if( inst == terminalInstance )
+ {
+ entry = node;
+ break;
+ }
+ else
+ {
+ ++inst;
+ }
+ }
+ }
+ return entry;
+}
+
+uint32_t CNodeEntry::GetTerminalInstance( uint8_t deviceInstance, uint16_t nodeAddress, uint32_t deviceType )
+{
+ uint32_t terminalInst = 0;
+ for( uint32_t i = 0; i < allNodes.Size(); i++ )
+ {
+ if( ( allNodes[i]->deviceInstance == deviceInstance )
+ && ( allNodes[i]->deviceType == deviceType ) )
+ {
+ if( ( allNodes[i]->nodeAddress == nodeAddress ) )
+ break;
+ else
+ ++terminalInst;
+ }
+ }
+ return terminalInst;
+}
+
+void CNodeEntry::DeleteAllNodeEntries()
+{
+ allNodes.RemoveAll(true);
+}
+
+void CNodeEntry::DeleteNodeEntry( uint16_t index )
+{
+ CNodeEntry *ent = allNodes[index];
+ if( NULL == ent )
+ return;
+
+ allNodes.Remove(ent);
+ delete ent;
+}
+
+const char *CNodeEntry::GetConnectionStateString( NodeConnectionState_t conState )
+{
+ switch( conState )
+ {
+ case NodeConnection_NotUsed:
+ return "Idle";
+ case NodeConnection_Pending_Up:
+ return "Pending-Up";
+ case NodeConnection_Pending_Down:
+ return "Pending-Down";
+ case NodeConnection_Used:
+ return "Established";
+ default:
+ return "Unknown State";
+ }
+}
+
+void CNodeEntry::PrintAllInformations()
+{
+ ConsolePrintfStart( PRIO_LOW, "==================================================================\n" );
+ for( uint32_t i = 0; i < allNodes.Size(); i++ )
+ {
+ CNodeEntry *entry = allNodes[i];
+ ;
+ if( NULL != entry )
+ {
+ ConsolePrintfContinue( "Inst:%d, NodeAddr:0x%X, DevType:0x%X, MAC:%s, open:%d\n", entry->deviceInstance,
+ entry->nodeAddress, entry->deviceType, ( NULL != entry->macAddress ? entry->macAddress->ToString() :
+ "None" ), ( entry->isUsbPortOpened || entry->isMlbPortOpened ) );
+ for( uint32_t j = 0; j < entry->GetAmountOfConnections(); j++ )
+ {
+ CNodeConnectionEntry *con = entry->GetConnectionByIndex( j );
+ ConsolePrintfContinue(
+ "Id:%d, inHandle:0x%X, outHandle:0x%X, conHandle:0x%X, conLabel:0x%X, inState:%s, outState:%s, conState:%s, bufferSize:%d, name:%s\n", con->channelId, con->inHandle, con->outHandle, con->connectHandle, con->mostConnectionLabel, GetConnectionStateString( con->inSocketState ), GetConnectionStateString( con->outSocketState ), GetConnectionStateString( con->connectedSocketState ), con->bufferSize, con->deviceName );
+ }
+ }
+ if( i < allNodes.Size() - 1 )
+ ConsolePrintfContinue( "------------------------------------------------------------------\n" );
+ }
+ ConsolePrintfExit( "==================================================================\n" );
+}
+
+uint16_t CNodeEntry::GetAmountOfConnections()
+{
+ return allConnections.Size();
+}
+
+CNodeConnectionEntry *CNodeEntry::GetConnectionByIndex( uint16_t index )
+{
+ return allConnections[index];
+}
+
+CNodeConnectionEntry *CNodeEntry::GetConnectionByChannelId( uint32_t channelId, bool createNewIfUnknown )
+{
+ CNodeConnectionEntry *entry = NULL;
+ for( uint32_t i = 0; i < allConnections.Size(); i++ )
+ {
+ if( allConnections[i]->channelId == channelId )
+ {
+ entry = allConnections[i];
+ break;
+ }
+ }
+ if( createNewIfUnknown && NULL == entry )
+ {
+ entry = new CNodeConnectionEntry( this );
+ entry->channelId = channelId;
+ allConnections.PushBack( entry );
+ }
+ return entry;
+}
+
+CNodeConnectionEntry *CNodeEntry::GetConflictingConnection( uint32_t channelId, CNodeEntry *opposite )
+{
+ if( NULL == opposite )
+ return NULL;
+ if( opposite->deviceInstance != deviceInstance )
+ return NULL;
+ CNodeConnectionEntry *entry = NULL;
+ uint32_t connectionLabel = 0xFFFFFFFF;
+ for( uint32_t i = 0; i < allConnections.Size(); i++ )
+ {
+ if( allConnections[i]->channelId == channelId )
+ {
+ connectionLabel = allConnections[i]->mostConnectionLabel;
+ break;
+ }
+ }
+ if( 0xFFFFFFFF != connectionLabel )
+ {
+ for( uint32_t i = 0; i < opposite->allConnections.Size(); i++ )
+ {
+ if( opposite->allConnections[i]->mostConnectionLabel == connectionLabel )
+ {
+ entry = opposite->allConnections[i];
+ break;
+ }
+ }
+ }
+ return entry;
+}
+
+void CNodeEntry::DeleteConnection( uint32_t channelId )
+{
+ uint32_t index = 0xFFFFFFFF;
+ for( uint32_t i = 0; i < allConnections.Size(); i++ )
+ {
+ if( allConnections[i]->channelId == channelId )
+ {
+ index = i;
+ }
+ }
+ if( index >= allNodes.Size() )
+ return;
+ CNodeConnectionEntry *ent = allConnections[index];
+ allConnections.Remove(ent);
+ delete ent;
+}
diff --git a/Src/Network/NodeDatabase.h b/Src/Network/NodeDatabase.h
new file mode 100644
index 0000000..16eb863
--- /dev/null
+++ b/Src/Network/NodeDatabase.h
@@ -0,0 +1,379 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CNodeEntry and the CNodeConnectionEntry class.
+ */
+/*----------------------------------------------------------*/
+#ifndef NODEDATABASE_H
+#define NODEDATABASE_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "SafeVector.h"
+#include "VodXml.h"
+#include "MacAddr.h"
+
+class CNodeEntry;
+class CNodeConnectionEntry;
+
+/*----------------------------------------------------------*/
+/*! \brief Enumeration describing the state of a Node socket
+ */
+/*----------------------------------------------------------*/
+typedef enum NodeConnectionState_tag
+{
+ NodeConnection_NotUsed,
+ NodeConnection_Pending_Up,
+ NodeConnection_Pending_Down,
+ NodeConnection_Used
+} NodeConnectionState_t;
+
+/*----------------------------------------------------------*/
+/*! \brief Storage class holding informations of a specific MOST connection (Ports)
+ */
+/*----------------------------------------------------------*/
+class CNodeConnectionEntry
+{
+public:
+ /*----------------------------------------------------------*/
+ /*! \brief Pointer to the device, which this connection belongs to.
+ */
+ /*----------------------------------------------------------*/
+ CNodeEntry *parentNode;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Pointer to the XML generated configuration, holding the user specific part of this connection.
+ */
+ /*----------------------------------------------------------*/
+ CChannelConfiguration *channelConfig;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Identifier determinating the connection based on the XML configuration.
+ */
+ /*----------------------------------------------------------*/
+ uint32_t channelId;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief In-Handle provided from INIC when the In-Socket was created
+ */
+ /*----------------------------------------------------------*/
+ uint32_t inHandle;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Out-Handle provided from INIC when the Out-Socket was created
+ */
+ /*----------------------------------------------------------*/
+ uint32_t outHandle;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Connection-Handle provided from INIC when the In- and the Out-Socket were connected.
+ */
+ /*----------------------------------------------------------*/
+ uint32_t connectHandle;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief If this connection uses combiner or splitter, this handle points to the source / sink of the splitter / combiner.
+ * \note The idea of storing this handle, is only for cleanup purposes.
+ * \warning Do not use this handle for creating connections.
+ */
+ /*----------------------------------------------------------*/
+ uint32_t splittedSourceHandle;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Connection-Handle provided from INIC when the MOST-Socket was created.
+ */
+ /*----------------------------------------------------------*/
+ uint32_t mostConnectionLabel;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief The state of the In-Socket
+ */
+ /*----------------------------------------------------------*/
+ NodeConnectionState_t inSocketState;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief The state of the Out-Socket
+ */
+ /*----------------------------------------------------------*/
+ NodeConnectionState_t outSocketState;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief The connection state between In-Socket and Out-Socket
+ */
+ /*----------------------------------------------------------*/
+ NodeConnectionState_t connectedSocketState;
+
+ /*----------------------------------------------------------*/
+ /*! \brief The used buffer size for this connection.
+ * \note bufferSize is -1 in case, there were no buffers configured.
+ */
+ /*----------------------------------------------------------*/
+ int32_t bufferSize;
+
+ /*----------------------------------------------------------*/
+ /*! \brief The Linux character device name, when this connection belongs to a local connection. May be strlen of 0.
+ */
+ /*----------------------------------------------------------*/
+ char deviceName[64];
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Constructor of CNodeConnectionEntry.
+ * \param Pointer to the device this connection belongs to.
+ */
+ /*----------------------------------------------------------*/
+ CNodeConnectionEntry( CNodeEntry *parentNode );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Destructor of CNodeConnectionEntry.
+ */
+ /*----------------------------------------------------------*/
+ ~CNodeConnectionEntry();
+};
+
+/*----------------------------------------------------------*/
+/*! \brief Storage class holding information of a specific MOST device
+ */
+/*----------------------------------------------------------*/
+class CNodeEntry
+{
+private:
+ static CSafeVector<CNodeEntry *> allNodes;
+ CSafeVector<CNodeConnectionEntry *> allConnections;
+
+ CNodeEntry();
+ static const char *GetConnectionStateString( NodeConnectionState_t state );
+public:
+ ~CNodeEntry();
+
+ /*----------------------------------------------------------*/
+ /*! \brief MOST instance. 0 for the first instance. If the server has multiple MOST devices, this value will be increased.
+ */
+ /*----------------------------------------------------------*/
+ uint8_t deviceInstance;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief The unique address of the MOST device.
+ */
+ /*----------------------------------------------------------*/
+ uint16_t nodeAddress;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief The type of the device (derived from the group address), as described in the XML configuration.
+ */
+ /*----------------------------------------------------------*/
+ uint16_t deviceType;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief The unique MAC address of the device.
+ */
+ /*----------------------------------------------------------*/
+ CMacAddr *macAddress;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Determines if the TSI port is opened.
+ * \return true, if the port is opened. false
+ */
+ /*----------------------------------------------------------*/
+ bool isTsiPortOpened;
+
+ /*----------------------------------------------------------*/
+ /*! \brief Determines if the MLB port is opened.
+ * \return true, if the port is opened. false
+ */
+ /*----------------------------------------------------------*/
+ bool isMlbPortOpened;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Determines if the USB port is opened.
+ * \return true, if the port is opened. false
+ */
+ /*----------------------------------------------------------*/
+ bool isUsbPortOpened;
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Determines if the USB port A is opened.
+ * \return true, if the port is opened. false
+ */
+ /*----------------------------------------------------------*/
+ bool isI2SPortOpened;
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets the amount of available MOST devices.
+ * \return The number of MOST devices.
+ */
+ /*----------------------------------------------------------*/
+ static uint16_t GetAmountOfNodeEntries();
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets an instance of CNodeEntry by the given instance index
+ * \param index - starting at 0 for the first instance. "GetAmountOfNodeEntries() - 1" for the last instance.
+ * \return The requested instance, when successful. Otherwise NULL pointer.
+ */
+ /*----------------------------------------------------------*/
+ static CNodeEntry *GetNodeEntry( uint16_t index );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets an instance of CNodeEntry by the given MOST instance and the unique node address of the device.
+ * \param deviceInstance - MOST instance id, starting at 0 for the first MOST ring. When the server have multiple MOST devices,
+ * This value may be above 0.
+ * \param nodeAddress - The MOST node address of the specific device (0x100 e.g.).
+ * \return The requested instance, when successful. Otherwise NULL pointer.
+ */
+ /*----------------------------------------------------------*/
+ static CNodeEntry *GetNodeEntry( uint8_t deviceInstance, uint16_t nodeAddress );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets an instance of CNodeEntry by the given unique MAC address of the device.
+ * \param macAddress - Unique MAC address of the device
+ * \return The requested instance, when successful. Otherwise NULL pointer.
+ */
+ /*----------------------------------------------------------*/
+ static CNodeEntry *GetNodeEntry( CMacAddr *macAddress );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets an instance of CNodeEntry by the given device type and terminal instance
+ * \param deviceInstance - MOST instance id, starting at 0 for the first MOST ring. When the server have multiple MOST devices,
+ * This value may be above 0.
+ * \param deviceType - The type of the device (derived from the group address), as described in the XML configuration.
+ * \param terminalInstance - The instance of the terminal, starting at 0 for the first terminal.
+ *
+ * \return The requested instance, when successful. Otherwise NULL pointer.
+ */
+ /*----------------------------------------------------------*/
+ static CNodeEntry *GetNodeEntry( uint8_t deviceInstance, uint32_t deviceType, uint32_t terminalInstance );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets the terminal instance number for the given device type.
+ * \param deviceInstance - MOST instance id, starting at 0 for the first MOST ring. When the server have multiple MOST devices,
+ * This value may be above 0.
+ * \param nodeAddress - The MOST node address of the specific device (0x100 e.g.).
+ * \param deviceType - The type of the device (derived from the group address), as described in the XML configuration.
+ *
+ * \return The requested instance, when successful. Otherwise NULL pointer.
+ */
+ /*----------------------------------------------------------*/
+ static uint32_t GetTerminalInstance( uint8_t deviceInstance, uint16_t nodeAddress, uint32_t deviceType );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Deleting all informations of any device.
+ */
+ /*----------------------------------------------------------*/
+ static void DeleteAllNodeEntries();
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Deleting all informations of a specific device.
+ * \param index - starting at 0 for the first instance. "GetAmountOfNodeEntries() - 1" for the last instance.
+ */
+ /*----------------------------------------------------------*/
+ static void DeleteNodeEntry( uint16_t index );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Dumps out all information of all devices to stdout
+ */
+ /*----------------------------------------------------------*/
+ static void PrintAllInformations();
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets the amount of connection for the current instance of MOST device.
+ * \return The amount of connections.
+ */
+ /*----------------------------------------------------------*/
+ uint16_t GetAmountOfConnections();
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets an instance of CNodeConnectionEntry by the given instance index.
+ * \param index - starting at 0 for the first instance. "GetAmountOfConnections() - 1" for the last instance.
+ * \return The requested instance, when successful. Otherwise NULL pointer.
+ */
+ /*----------------------------------------------------------*/
+ CNodeConnectionEntry *GetConnectionByIndex( uint16_t index );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets an instance of CNodeConnectionEntry by the given channel identifier.
+ * \param channelId - The channel identifier as specified in the XML file.
+ * \param createNewIfUnknown - TRUE, if this function shall create a new entry, when there is no existing object.
+ * \return The requested instance, when successful. Otherwise NULL pointer.
+ */
+ /*----------------------------------------------------------*/
+ CNodeConnectionEntry *GetConnectionByChannelId( uint32_t channelId, bool createNewIfUnknown );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves a conflicting connection by the given parameters.#
+ * This method checks if the in and out configurations are unique for one device.
+ * \param channelId - The channel identifier as specified in the XML file.
+ * \param opposite - The other side to be connected to.
+ * \return The instance, which causes an conflict. If there is no conflict, a NULL pointer will be returned.
+ */
+ /*----------------------------------------------------------*/
+ CNodeConnectionEntry *GetConflictingConnection( uint32_t channelId, CNodeEntry *opposite );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Delets all informations of the given channel identifier.
+ * \param channelId - The channel identifier as specified in the XML file.
+ */
+ /*----------------------------------------------------------*/
+ void DeleteConnection( uint32_t channelId );
+};
+
+#endif //NODEDATABASE_H
diff --git a/Src/Network/base/.svn/dir-prop-base b/Src/Network/base/.svn/dir-prop-base
new file mode 100644
index 0000000..c4fbe3b
--- /dev/null
+++ b/Src/Network/base/.svn/dir-prop-base
@@ -0,0 +1,14 @@
+K 16
+bugtraq:logregex
+V 67
+(?:[Bb]ugs?|[Ii]ssues?|[Rr]eports?)+\s+#(?:(?:\d+)[#,\.\s]*)+
+(\d+)
+K 15
+bugtraq:message
+V 21
+Mantis issue #%BUGID%
+K 11
+bugtraq:url
+V 33
+http://mantis/view.php?id=%BUGID%
+END
diff --git a/Src/Network/base/.svn/entries b/Src/Network/base/.svn/entries
new file mode 100644
index 0000000..eba0b2c
--- /dev/null
+++ b/Src/Network/base/.svn/entries
@@ -0,0 +1,164 @@
+10
+
+dir
+6611
+svn://kar-vm-svn01.mchp-main.com/svn/AppsTeam/Samples/iMX6+OS81118/Industrial/VideoOnDemand/tags/V3.0.4/source/Examples/NetworkManager/Server/Src/Network/base
+svn://kar-vm-svn01.mchp-main.com/svn/AppsTeam
+
+
+
+2016-03-08T10:11:00.246092Z
+5263
+tkummermehr
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+c50209ca-6af6-4c1a-9d47-4b11eae79d1c
+
+Board.c
+file
+
+
+
+
+2016-11-29T13:32:01.206172Z
+002b1b0937a1a1653ff724364be62050
+2016-03-08T10:11:00.246092Z
+5263
+tkummermehr
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1685
+
+DriverConfiguration.h
+file
+
+
+
+
+2016-11-29T13:32:01.206172Z
+05273e72ca5b7af8c2f55a35fcdaa5a0
+2015-12-17T09:32:42.832988Z
+5040
+ashvetsov
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+11839
+
+Board.h
+file
+
+
+
+
+2016-11-29T13:32:01.206172Z
+40cb461e8d0039b063b790d626d37f1a
+2016-03-08T10:11:00.246092Z
+5263
+tkummermehr
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1799
+
+DriverConfiguration.c
+file
+
+
+
+
+2016-11-29T13:32:01.202172Z
+b8e55c1b0e2437a8513afd32ae4f5446
+2015-12-17T09:32:42.832988Z
+5040
+ashvetsov
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+18468
+
diff --git a/Src/Network/base/.svn/prop-base/DriverConfiguration.c.svn-base b/Src/Network/base/.svn/prop-base/DriverConfiguration.c.svn-base
new file mode 100644
index 0000000..3160658
--- /dev/null
+++ b/Src/Network/base/.svn/prop-base/DriverConfiguration.c.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mergeinfo
+V 0
+
+END
diff --git a/Src/Network/base/.svn/prop-base/DriverConfiguration.h.svn-base b/Src/Network/base/.svn/prop-base/DriverConfiguration.h.svn-base
new file mode 100644
index 0000000..3160658
--- /dev/null
+++ b/Src/Network/base/.svn/prop-base/DriverConfiguration.h.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mergeinfo
+V 0
+
+END
diff --git a/Src/Network/base/.svn/text-base/Board.c.svn-base b/Src/Network/base/.svn/text-base/Board.c.svn-base
new file mode 100644
index 0000000..50daf0c
--- /dev/null
+++ b/Src/Network/base/.svn/text-base/Board.c.svn-base
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file */
+/*! \brief Base Board initialisation */
+/*----------------------------------------------------------*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include "Board.h"
+#include "Console.h"
+
+uint32_t GetTickCount( void )
+{
+ struct timespec currentTime;
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &currentTime))
+ {
+ ConsolePrintf( PRIO_ERROR, RED"GetTickCount failed!!"RESETCOLOR"\n" );
+ return 0;
+ }
+ return ( currentTime.tv_sec * 1000 ) + ( currentTime.tv_nsec / 1000000 );
+}
+
+uint16_t GetTickCountWord()
+{
+ return ( uint16_t )( GetTickCount() & UINT16_MAX );
+}
diff --git a/Src/Network/base/.svn/text-base/Board.h.svn-base b/Src/Network/base/.svn/text-base/Board.h.svn-base
new file mode 100644
index 0000000..585a862
--- /dev/null
+++ b/Src/Network/base/.svn/text-base/Board.h.svn-base
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This component abstracts platform specific functionalities.
+ */
+/*----------------------------------------------------------*/
+#ifndef _BOARD_H_
+#define _BOARD_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+ /*----------------------------------------------------------*/
+ /*! \brief reads the ms tick counter.
+ *
+ * \return value of the ms counter.
+ */
+ /*----------------------------------------------------------*/
+ uint32_t GetTickCount( void );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief reads the ms tick counter
+ *
+ * \return value of the ms counter as word
+ */
+ /*----------------------------------------------------------*/
+ uint16_t GetTickCountWord( void );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _BOARD_H_
diff --git a/Src/Network/base/.svn/text-base/DriverConfiguration.c.svn-base b/Src/Network/base/.svn/text-base/DriverConfiguration.c.svn-base
new file mode 100644
index 0000000..7a98d25
--- /dev/null
+++ b/Src/Network/base/.svn/text-base/DriverConfiguration.c.svn-base
@@ -0,0 +1,608 @@
+/*
+ * 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 <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include "DriverConfiguration.h"
+#include "Console.h"
+
+static bool WriteCharactersToFile( const char *pFileName, const char *pString )
+{
+ bool success = false;
+ FILE *fh = fopen( pFileName, "a" );
+ if( NULL != fh )
+ {
+ int result = fputs( pString, fh );
+ if( result >= 0 )
+ fputc( '\n', fh );
+ if( result >= 0 )
+ success = true;
+ fclose( fh );
+ }
+ if( success )
+ ConsolePrintf( PRIO_MEDIUM, "*** configured device: '%s = %s', success:%d\n", pFileName, pString, success );
+ else
+ ConsolePrintf( PRIO_ERROR, RED"DriverConfiguration.WriteCharactersToFile failed for file '%s', errno:'%s'"RESETCOLOR"\n",
+ pFileName, GetErrnoString() );
+ return success;
+}
+
+static bool WriteIntegerToFile( const char *pFileName, int intValue )
+{
+ char tempBuffer[16];
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%d", intValue );
+ return WriteCharactersToFile( pFileName, tempBuffer );
+}
+
+static bool ReadFromFile( const char *pFileName, char *pString, uint16_t bufferLen )
+{
+ bool success = false;
+ if( NULL == pString || 0 == bufferLen )
+ return success;
+ FILE *fh = fopen( pFileName, "r" );
+ if( NULL != fh )
+ {
+ success = ( NULL != fgets( pString, bufferLen, fh ) );
+ fclose( fh );
+ }
+ if( !success )
+ ConsolePrintf( PRIO_ERROR, RED"DriverConfiguration.ReadFromFile failed for file '%s', errno:'%s'"RESETCOLOR"\n",
+ pFileName, GetErrnoString() );
+ return success;
+}
+
+static bool ExistsDevice( const char *pDeviceName )
+{
+ struct stat buffer;
+ return ( stat( pDeviceName, &buffer ) == 0 );
+}
+
+static bool WaitForDevice( const char *pDeviceName )
+{
+ int timeout;
+ bool deviceExists = false;
+ for( timeout = 0; timeout < 40; timeout++ )
+ {
+ deviceExists = ExistsDevice( pDeviceName );
+ if( deviceExists )
+ {
+ break;
+ }
+ else
+ {
+ usleep( 2500 );
+ }
+ }
+ if( !deviceExists )
+ ConsolePrintf( PRIO_ERROR, RED"Waiting for device '%s' to appear, timed out"RESETCOLOR"\n",
+ pDeviceName );
+ return deviceExists;
+}
+
+static bool GetDeviceDescription( uint8_t deviceInstance, char *deviceString, uint32_t stringLen )
+{
+ bool descriptionFound = false;
+ char descriptionPath[64];
+ char descriptionValue[32];
+
+ if( NULL == deviceString )
+ return descriptionFound;
+
+ snprintf( descriptionPath, sizeof( descriptionPath ),
+ "/sys/devices/virtual/most/mostcore/devices/mdev%d/description", deviceInstance );
+
+ if( !ExistsDevice( descriptionPath ) )
+ return descriptionFound;
+
+ descriptionFound = ReadFromFile( descriptionPath, descriptionValue, sizeof( descriptionValue ) );
+ if( descriptionFound )
+ {
+ strncpy( deviceString, descriptionValue, stringLen );
+ }
+ return descriptionFound;
+}
+
+static bool ExistsDeviceWithType( uint8_t deviceInstance, const char *deviceString, uint32_t stringLen )
+{
+ bool deviceFound = false;
+ char interfacePath[64];
+ char interfaceValue[32];
+
+ if( NULL == deviceString )
+ return deviceFound;
+
+ snprintf( interfacePath, sizeof( interfacePath ), "/sys/devices/virtual/most/mostcore/devices/mdev%d/interface",
+ deviceInstance );
+
+ if( !ExistsDevice( interfacePath ) )
+ return deviceFound;
+
+ deviceFound = ReadFromFile( interfacePath, interfaceValue, sizeof( interfaceValue ) );
+ if( deviceFound )
+ {
+ deviceFound = ( 0 == strncmp( interfaceValue, deviceString, stringLen ) );
+ }
+ return deviceFound;
+}
+
+static bool GetAlsaConfiguration( uint16_t subBufferSize, uint8_t *amountOfChannels, uint8_t *bitDepth )
+{
+ if( NULL == amountOfChannels || NULL == bitDepth )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"GetAlsaConfiguration was called with invalid parameters"RESETCOLOR"\n" );
+ return false;
+ }
+ switch( subBufferSize )
+ {
+ case 2:
+ *amountOfChannels = 1;
+ *bitDepth = 16;
+ break;
+ case 4:
+ *amountOfChannels = 2;
+ *bitDepth = 16;
+ break;
+ case 6:
+ *amountOfChannels = 2;
+ *bitDepth = 24;
+ break;
+ case 8:
+ *amountOfChannels = 2;
+ *bitDepth = 32;
+ break;
+ case 12:
+ *amountOfChannels = 6;
+ *bitDepth = 16;
+ break;
+ case 18:
+ *amountOfChannels = 6;
+ *bitDepth = 24;
+ break;
+ case 16:
+ *amountOfChannels = 8;
+ *bitDepth = 16;
+ break;
+ case 24:
+ *amountOfChannels = 8;
+ *bitDepth = 24;
+ break;
+ default:
+ ConsolePrintf( PRIO_ERROR, RED"Configure ALSA device was called"\
+ " with unknown sub-buffer size: %d"RESETCOLOR"\n", subBufferSize );
+ return false;
+ }
+ return true;
+}
+
+bool ExistsUsbDeviceInstance( uint8_t deviceInstance )
+{
+ uint32_t i;
+ bool found = false;
+ uint8_t curDevInst = 0;
+ char lastDescr[64];
+ lastDescr[0] = '\0';
+ for( i = 0; i < 12; i++ )
+ {
+ uint32_t curDescrLen;
+ char curDescr[64];
+ if( !ExistsDeviceWithType( i, "usb", 3 ) )
+ continue;
+
+ if( !GetDeviceDescription( i, curDescr, sizeof( curDescr ) ) )
+ continue;
+
+ curDescrLen = strnlen( curDescr, sizeof( curDescr ) );
+ if( curDescrLen <= 2 )
+ continue;
+
+ //Cut away the last two characters, as they are different for the 3 interfaces of INIC
+ curDescrLen -= 2;
+
+ if( 0 == strncmp( curDescr, lastDescr, curDescrLen ) )
+ continue;
+
+ strncpy( lastDescr, curDescr, curDescrLen );
+ lastDescr[curDescrLen] = '\0';
+
+ if( curDevInst++ != deviceInstance )
+ continue;
+
+ found = true;
+ break;
+ }
+ return found;
+}
+
+bool ExistsMlbDeviceInstance( uint8_t deviceInstance )
+{
+ return ExistsDeviceWithType( deviceInstance, "mlb", 3 );
+}
+
+bool ExistsI2CDeviceInstance( uint8_t deviceInstance )
+{
+ return ExistsDeviceWithType( deviceInstance, "i2c", 3 );
+}
+
+bool GetUsbDeviceNames( uint8_t deviceInstance, uint8_t endpointAddress, char *deviceName, uint16_t deviceNameLength,
+ char *systemName, uint16_t systemNameLength, char *linkName, uint16_t linkNameLength )
+{
+ uint32_t i;
+ bool systemFound = false;
+ uint8_t curDevInst = 0;
+ char lastDescr[64];
+ lastDescr[0] = '\0';
+ char endpointBuffer[16];
+ char systemSourceDir[64];
+ DIR *d;
+ struct dirent *dir;
+
+ if( NULL == deviceName || NULL == systemName || NULL == linkName )
+ return false;
+
+ deviceName[0] = '\0';
+ systemName[0] = '\0';
+
+ for( i = 0; !systemFound && i < 12; i++ )
+ {
+ uint32_t curDescrLen;
+ char curDescr[64];
+ if( !ExistsDeviceWithType( i, "usb", 3 ) )
+ continue;
+
+ if( !GetDeviceDescription( i, curDescr, sizeof( curDescr ) ) )
+ continue;
+
+ curDescrLen = strnlen( curDescr, sizeof( curDescr ) );
+ if( curDescrLen <= 2 )
+ continue;
+
+ //Cut away the last two characters, as they are different for the 3 interfaces of INIC
+ curDescrLen -= 2;
+
+ if( ( '\0' != lastDescr[0] )
+ && ( 0 != strncmp( curDescr, lastDescr, curDescrLen ) ) )
+ {
+ ++curDevInst;
+ }
+
+ strncpy( lastDescr, curDescr, curDescrLen );
+ lastDescr[curDescrLen] = '\0';
+
+ if( curDevInst < deviceInstance )
+ continue;
+ else if( curDevInst > deviceInstance )
+ break;
+
+ snprintf( endpointBuffer, sizeof( endpointBuffer ), "ep%02x", endpointAddress );
+ snprintf( systemSourceDir, sizeof( systemSourceDir ), "/sys/devices/virtual/most/mostcore/devices/mdev%d", i );
+ d = opendir( systemSourceDir );
+ if( d )
+ {
+ while( ( dir = readdir( d ) ) != NULL )
+ {
+ if( strstr( dir->d_name, endpointBuffer ) )
+ {
+ snprintf( systemName, systemNameLength, "%s/%s", systemSourceDir, dir->d_name );
+ snprintf( deviceName, deviceNameLength, "/dev/mdev%d-%s", deviceInstance, dir->d_name );
+ snprintf( linkName, linkNameLength, "mdev%d:%s:mdev%d-%s", i, dir->d_name, deviceInstance,
+ dir->d_name );
+ systemFound = true;
+ break;
+ }
+ }
+ closedir( d );
+ }
+ }
+ return systemFound;
+}
+
+bool GetMlbDeviceNames( uint8_t deviceInstance, uint8_t mlbChannelAddress, char *deviceName, uint16_t deviceNameLength,
+ char *systemName, uint16_t systemNameLength, char *linkName, uint16_t linkNameLength )
+{
+ bool systemFound = false;
+ char channelBuffer[16];
+ char systemSourceDir[64];
+ DIR *d;
+ struct dirent *dir;
+
+ if( NULL == deviceName || NULL == systemName || NULL == linkName )
+ return false;
+
+ deviceName[0] = '\0';
+ systemName[0] = '\0';
+
+ snprintf( channelBuffer, sizeof( channelBuffer ), "ca%d", mlbChannelAddress );
+ snprintf( systemSourceDir, sizeof( systemSourceDir ), "/sys/devices/virtual/most/mostcore/devices/mdev%d",
+ deviceInstance );
+ d = opendir( systemSourceDir );
+ if( d )
+ {
+ while( ( dir = readdir( d ) ) != NULL )
+ {
+ if( strstr( dir->d_name, channelBuffer ) )
+ {
+ snprintf( systemName, systemNameLength, "%s/%s", systemSourceDir, dir->d_name );
+ snprintf( deviceName, deviceNameLength, "/dev/mdev%d-%s", deviceInstance, dir->d_name );
+ snprintf( linkName, linkNameLength, "mdev%d:%s:mdev%d-%s", deviceInstance, dir->d_name, deviceInstance,
+ dir->d_name );
+ systemFound = true;
+ break;
+ }
+ }
+ closedir( d );
+ }
+ return systemFound;
+}
+
+bool GetI2CDeviceNames( uint8_t deviceInstance, bool isTx, char *deviceName, uint16_t deviceNameLength,
+ char *systemName, uint16_t systemNameLength, char *linkName, uint16_t linkNameLength )
+{
+ bool systemFound = false;
+ char systemSourceDir[64];
+ DIR *d;
+ struct dirent *dir;
+
+ if( NULL == deviceName || NULL == systemName || NULL == linkName )
+ return false;
+
+ deviceName[0] = '\0';
+ systemName[0] = '\0';
+
+ snprintf( systemSourceDir, sizeof( systemSourceDir ), "/sys/devices/virtual/most/mostcore/devices/mdev%d",
+ deviceInstance );
+ d = opendir( systemSourceDir );
+ if( d )
+ {
+ while( ( dir = readdir( d ) ) != NULL )
+ {
+ if( strstr( dir->d_name, ( isTx ? "tx" : "rx" ) ) )
+ {
+ snprintf( systemName, systemNameLength, "%s/%s", systemSourceDir, dir->d_name );
+ snprintf( deviceName, deviceNameLength, "/dev/mdev%d-%s", deviceInstance, dir->d_name );
+ snprintf( linkName, linkNameLength, "mdev%d:%s:mdev%d-%s", deviceInstance, dir->d_name, deviceInstance,
+ dir->d_name );
+ systemFound = true;
+ break;
+ }
+ }
+ closedir( d );
+ }
+ return systemFound;
+}
+
+bool CloseMostChannel( const char *device )
+{
+ return true;
+}
+
+bool ConfigureMostChannel( const char *device, EPDataType_t mostType, EPDirection_t direction, uint32_t numBuf,
+ uint32_t bufSize )
+{
+ static const char *controlType = "control";
+ static const char *asyncType = "async";
+ static const char *syncType = "sync";
+ static const char *isocType = "isoc_avp";
+ static const char *rxDirection = "dir_rx";
+ static const char *txDirection = "dir_tx";
+ bool success = true;
+ char tempBuffer[128];
+ const char *typeString = NULL;
+ const char *directionString = NULL;
+
+ switch( mostType )
+ {
+ case EP_Control:
+ typeString = controlType;
+ break;
+ case EP_Asynchron:
+ typeString = asyncType;
+ break;
+ case EP_Synchron:
+ typeString = syncType;
+ break;
+ case EP_Isochron:
+ typeString = isocType;
+ break;
+ default:
+ return false;
+ }
+
+ switch( direction )
+ {
+ case EPDIR_IN:
+ directionString = txDirection;
+ break;
+ case EPDIR_OUT:
+ directionString = rxDirection;
+ break;
+ default:
+ return false;
+ }
+
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_datatype", device ); /// Setting data type
+ success = WriteCharactersToFile( tempBuffer, typeString );
+ if( success )
+ {
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_direction", device ); /// Setting direction
+ success = WriteCharactersToFile( tempBuffer, directionString );
+ }
+ if( success )
+ {
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_number_of_buffers", device ); /// Setting amount of buffers
+ success = WriteIntegerToFile( tempBuffer, numBuf );
+ }
+ if( success )
+ {
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_buffer_size", device ); /// Setting amount of buffers
+ success = WriteIntegerToFile( tempBuffer, bufSize );
+ }
+ return success;
+}
+
+bool ConfigureIsocChannel( const char *device, uint32_t subbufferSize, uint32_t packetsPerTransaction )
+{
+ char tempBuffer[128];
+ bool success;
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_subbuffer_size", device ); /// Setting the subbuffer size in bytes
+ success = WriteIntegerToFile( tempBuffer, subbufferSize );
+
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_packets_per_xact", device ); /// Setting the packets per transaction
+ success = WriteIntegerToFile( tempBuffer, ( packetsPerTransaction & 0xFF ) );
+ return success;
+}
+
+bool ConfigureSyncChannel( const char *device, uint32_t syncBlockWidth, uint32_t amounOfSyncFrames )
+{
+ char tempBuffer[128];
+ bool success;
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_packets_per_xact", device ); /// Setting the amount of frames in one USB frame
+ success = WriteIntegerToFile( tempBuffer, amounOfSyncFrames );
+
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_subbuffer_size", device ); /// Setting the blockwidth of a single frame
+ success = WriteIntegerToFile( tempBuffer, syncBlockWidth );
+ return success;
+}
+
+bool LinkToCharacterDevice( const char *linkName, const char *deviceName )
+{
+ bool success =
+ WriteCharactersToFile( "/sys/devices/virtual/most/mostcore/aims/cdev/add_link", linkName );
+ if( success )
+ {
+ success = WaitForDevice( deviceName );
+ }
+ if( success )
+ {
+ chmod( deviceName, ( S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH ) );
+ }
+ return success;
+}
+
+bool LinkToAudioDevice( const char *linkName, uint16_t subBufferSize )
+{
+ char tempBuffer[128];
+ uint8_t amountOfChannels;
+ uint8_t bitDepth;
+ if( !GetAlsaConfiguration( subBufferSize, &amountOfChannels, &bitDepth ) )
+ return false;
+
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s.%dx%d", linkName, amountOfChannels, bitDepth ); /// Add the channel information behind the Link Name
+
+ //Be compatible to all versions of MOST Linux Driver. The name was changed of Sound AIM.
+ bool success =
+ WriteCharactersToFile( "/sys/devices/virtual/most/mostcore/aims/sound/add_link", tempBuffer );
+ if( !success )
+ success =
+ WriteCharactersToFile( "/sys/devices/virtual/most/mostcore/aims/audio/add_link", tempBuffer );
+ return success;
+}
+
+bool LinkToVideoForLinuxDevice( const char *linkName )
+{
+ bool success =
+ WriteCharactersToFile( "/sys/devices/virtual/most/mostcore/aims/v4l/add_link", linkName );
+ return success;
+}
+
+const char *GetErrnoString()
+{
+ switch( errno )
+ {
+ case 0:
+ return "Nothing stored in errno";
+ case 1:
+ return "Operation not permitted";
+ case 2:
+ return "No such file or directory";
+ case 3:
+ return "No such process";
+ case 4:
+ return "Interrupted system call";
+ case 5:
+ return "I/O error";
+ case 6:
+ return "No such device or address";
+ case 7:
+ return "Argument list too long";
+ case 8:
+ return "Exec format error";
+ case 9:
+ return "Bad file number";
+ case 10:
+ return "No child processes";
+ case 11:
+ return "Try again";
+ case 12:
+ return "Out of memory";
+ case 13:
+ return "Permission denied";
+ case 14:
+ return "Bad address";
+ case 15:
+ return "Block device required";
+ case 16:
+ return "Device or resource busy";
+ case 17:
+ return "File exists";
+ case 18:
+ return "Cross-device link";
+ case 19:
+ return "No such device";
+ case 20:
+ return "Not a directory";
+ case 21:
+ return "Is a directory";
+ case 22:
+ return "Invalid argument";
+ case 23:
+ return "File table overflow";
+ case 24:
+ return "Too many open files";
+ case 25:
+ return "Not a typewriter";
+ case 26:
+ return "Text file busy";
+ case 27:
+ return "File too large";
+ case 28:
+ return "No space left on device";
+ case 29:
+ return "Illegal seek";
+ case 30:
+ return "Read-only file system";
+ case 31:
+ return "Too many links";
+ case 32:
+ return "Broken pipe";
+ case 33:
+ return "Math argument out of domain of func";
+ case 34:
+ return "Math result not representable";
+ default:
+ break;
+ }
+ return "Unknown";
+}
diff --git a/Src/Network/base/.svn/text-base/DriverConfiguration.h.svn-base b/Src/Network/base/.svn/text-base/DriverConfiguration.h.svn-base
new file mode 100644
index 0000000..b2fd44a
--- /dev/null
+++ b/Src/Network/base/.svn/text-base/DriverConfiguration.h.svn-base
@@ -0,0 +1,239 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This component provides helper tools to deal with USB endpoints.
+ */
+/*----------------------------------------------------------*/
+#ifndef DRIVERCONFIGURATION_H
+#define DRIVERCONFIGURATION_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "Types.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------*/
+ /*! \brief Checks if the given USB device instance exists.
+ *
+ * \param deviceInstance - The device instance of the USB INIC, starting at 0 for the first instance.
+ *
+ * \return true: Device exists.
+ * \return false: Device does not exist.
+ */
+ /*----------------------------------------------------------*/
+ bool ExistsUsbDeviceInstance( uint8_t deviceInstance );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Checks if the given MLB device instance exists.
+ *
+ * \param deviceInstance - The device instance of the MLB INIC, starting at 0 for the first instance.
+ *
+ * \return true: Device exists.
+ * \return false: Device does not exist.
+ */
+ /*----------------------------------------------------------*/
+ bool ExistsMlbDeviceInstance( uint8_t deviceInstance );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Checks if the given I2C device instance exists.
+ *
+ * \param deviceInstance - The device instance of the I2C INIC, starting at 0 for the first instance.
+ *
+ * \return true: Device exists.
+ * \return false: Device does not exist.
+ */
+ /*----------------------------------------------------------*/
+ bool ExistsI2CDeviceInstance( uint8_t deviceInstance );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retreives the Linux character device names for the given USB device instance and the endpoint address.
+ *
+ * \note If the given buffer is too small to hold the whole path, the string is truncated and not useable!
+ *
+ * \param deviceInstance - The device instance of the USB INIC, starting at 0 for the first instance.
+ * \param endpointAddress - The USB endpoint address, RX endpoints starting with upper bit set (0x8X).
+ * \param deviceName - [in,out] Given buffer will be filled with device name (starting with /dev/).
+ * \param deviceNameLength - The length of the given deviceName buffer in bytes.
+ * \param systemName - [in,out] Given buffer will be filled with system name (starting with /sys/).
+ * \param systemNameLength - The length of the given systemName buffer in bytes.
+ * \param linkName - [in,out] Given buffer will be filled with the string needed to register this device to an AIM
+ * \param linkNameLength - The length of the given linkName buffer in bytes.
+ *
+ * \return true: Operation was successful.
+ * \return false: Operation failed, device or endpoint does not exist.
+ */
+ /*----------------------------------------------------------*/
+ bool GetUsbDeviceNames( uint8_t deviceInstance, uint8_t endpointAddress, char *deviceName,
+ uint16_t deviceNameLength, char *systemName, uint16_t systemNameLength, char *linkName,
+ uint16_t linkNameLength );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retreives the Linux character device names for the given MLB device instance and the endpoint address.
+ *
+ * \note If the given buffer is too small to hold the whole path, the string is truncated and not useable!
+ *
+ * \param deviceInstance - The device instance of the USB INIC, starting at 0 for the first instance.
+ * \param mlbChannelAddress - The MLB channel address
+ * \param deviceName - [in,out] Given buffer will be filled with device name (starting with /dev/).
+ * \param deviceNameLength - The length of the given deviceName buffer in bytes.
+ * \param systemName - [in,out] Given buffer will be filled with system name (starting with /sys/).
+ * \param systemNameLength - The length of the given systemName buffer in bytes.
+ * \param linkName - [in,out] Given buffer will be filled with the string needed to register this device to an AIM
+ * \param linkNameLength - The length of the given linkName buffer in bytes.
+ *
+ * \return true: Operation was successful.
+ * \return false: Operation failed, device or endpoint does not exist.
+ */
+ /*----------------------------------------------------------*/
+ bool GetMlbDeviceNames( uint8_t deviceInstance, uint8_t mlbChannelAddress, char *deviceName,
+ uint16_t deviceNameLength, char *systemName, uint16_t systemNameLength, char *linkName,
+ uint16_t linkNameLength );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retreives the Linux character device names for the given I2C device instance and the endpoint address.
+ *
+ * \note If the given buffer is too small to hold the whole path, the string is truncated and not useable!
+ *
+ * \param deviceInstance - The device instance of the I2C INIC, starting at 0 for the first instance.
+ * \param isTx - true, if the names for transmission path should be retrieved, otherwise for the reception path.
+ * \param deviceName - [in,out] Given buffer will be filled with device name (starting with /dev/).
+ * \param deviceNameLength - The length of the given deviceName buffer in bytes.
+ * \param systemName - [in,out] Given buffer will be filled with system name (starting with /sys/).
+ * \param systemNameLength - The length of the given systemName buffer in bytes.
+ * \param linkName - [in,out] Given buffer will be filled with the string needed to register this device to an AIM
+ * \param linkNameLength - The length of the given linkName buffer in bytes.
+ *
+ * \return true: Operation was successful.
+ * \return false: Operation failed, device or endpoint does not exist.
+ */
+ /*----------------------------------------------------------*/
+ bool GetI2CDeviceNames( uint8_t deviceInstance, bool isTx, char *deviceName, uint16_t deviceNameLength,
+ char *systemName, uint16_t systemNameLength, char *linkName, uint16_t linkNameLength );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Closes the MOST channel.
+ *
+ * \param device - The system path to configure the MOST device (starting with "/sys/").
+ *
+ * \return True if no error
+ */
+ /*----------------------------------------------------------*/
+ bool CloseMostChannel( const char *device );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Configures the MOST channel.
+ *
+ * \param device - The system path to configure the MOST device (starting with "/sys/").
+ * \param mostType - The MOST data type (control, asynchron, synchron, isochron).
+ * \param direction - The direction of the stream (directionRX, directionTX).
+ * \param numBuf - The amount of buffers.
+ * \param bufSize - The size of each buffer in bytes.
+ *
+ * \return True if no error
+ */
+ /*----------------------------------------------------------*/
+ bool ConfigureMostChannel( const char *device, EPDataType_t mostType, EPDirection_t direction, uint32_t numBuf,
+ uint32_t bufSize );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Configures the isochronous channel of a device.
+ * \note This function has to be called before ConfigureMostChannel!
+ *
+ * \param device - The system path to configure the MOST device (starting with "/sys/").
+ * \param subbufferSize - The amount of bytes for a single subbuffer (eg. 188 or 196 bytes).
+ * \param packetsPerTransaction - The amount of ischronous packets per transaction.
+ *
+ * \return True if no error
+ */
+ /*----------------------------------------------------------*/
+ bool ConfigureIsocChannel( const char *device, uint32_t subbufferSize, uint32_t packetsPerTransaction );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Configures the Synchronous channel of a device.
+ * \note This function has to be called before ConfigureMostChannel!
+ *
+ * \param device - The system path to configure the MOST device (starting with "/sys/").
+ * \param syncBlockWidth - The bandwidth of a single synchronous frame. Ignored if not sync channel.
+ * \param amounOfSyncFrames - The amount of synchronous frames per USB packet. Ignored if not sync channel.
+ *
+ * \return True if no error
+ */
+ /*----------------------------------------------------------*/
+ bool ConfigureSyncChannel( const char *device, uint32_t syncBlockWidth, uint32_t amounOfSyncFrames );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates a character device for the given device's link name.
+ *
+ * \param linkName - [in] Link name, which is needed to register this device to an AIM.
+ * \param deviceName - [in,out] Device name (starting with /dev/).
+ *
+ * \return True if no error
+ */
+ /*----------------------------------------------------------*/
+ bool LinkToCharacterDevice( const char *linkName, const char *deviceName );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates a audio device (ALSA) for the given device's link name.
+ *
+ * \param linkName - [in] Link name, which is needed to register this device to an AIM.
+ * \param subBufferSize - [in] The amount of bytes for all channels of this connection on the MOST.
+ *
+ * \return True if no error
+ */
+ /*----------------------------------------------------------*/
+ bool LinkToAudioDevice( const char *linkName, uint16_t subBufferSize );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates a Video for Linux device (V4L) for the given device's link name.
+ *
+ * \param linkName - [in] Link name, which is needed to register this device to an AIM.
+ *
+ * \return True if no error
+ */
+ /*----------------------------------------------------------*/
+ bool LinkToVideoForLinuxDevice( const char *linkName );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Parsed the global errno variable and generate a human readable error description out of it.
+ *
+ * \return Zero terminated error description string.
+ */
+ /*----------------------------------------------------------*/
+ const char *GetErrnoString();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //DRIVERCONFIGURATION_H
diff --git a/Src/Network/base/Board.c b/Src/Network/base/Board.c
new file mode 100644
index 0000000..50daf0c
--- /dev/null
+++ b/Src/Network/base/Board.c
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file */
+/*! \brief Base Board initialisation */
+/*----------------------------------------------------------*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include "Board.h"
+#include "Console.h"
+
+uint32_t GetTickCount( void )
+{
+ struct timespec currentTime;
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &currentTime))
+ {
+ ConsolePrintf( PRIO_ERROR, RED"GetTickCount failed!!"RESETCOLOR"\n" );
+ return 0;
+ }
+ return ( currentTime.tv_sec * 1000 ) + ( currentTime.tv_nsec / 1000000 );
+}
+
+uint16_t GetTickCountWord()
+{
+ return ( uint16_t )( GetTickCount() & UINT16_MAX );
+}
diff --git a/Src/Network/base/Board.h b/Src/Network/base/Board.h
new file mode 100644
index 0000000..585a862
--- /dev/null
+++ b/Src/Network/base/Board.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This component abstracts platform specific functionalities.
+ */
+/*----------------------------------------------------------*/
+#ifndef _BOARD_H_
+#define _BOARD_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+ /*----------------------------------------------------------*/
+ /*! \brief reads the ms tick counter.
+ *
+ * \return value of the ms counter.
+ */
+ /*----------------------------------------------------------*/
+ uint32_t GetTickCount( void );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief reads the ms tick counter
+ *
+ * \return value of the ms counter as word
+ */
+ /*----------------------------------------------------------*/
+ uint16_t GetTickCountWord( void );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _BOARD_H_
diff --git a/Src/Network/base/DriverConfiguration.c b/Src/Network/base/DriverConfiguration.c
new file mode 100644
index 0000000..7a98d25
--- /dev/null
+++ b/Src/Network/base/DriverConfiguration.c
@@ -0,0 +1,608 @@
+/*
+ * 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 <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include "DriverConfiguration.h"
+#include "Console.h"
+
+static bool WriteCharactersToFile( const char *pFileName, const char *pString )
+{
+ bool success = false;
+ FILE *fh = fopen( pFileName, "a" );
+ if( NULL != fh )
+ {
+ int result = fputs( pString, fh );
+ if( result >= 0 )
+ fputc( '\n', fh );
+ if( result >= 0 )
+ success = true;
+ fclose( fh );
+ }
+ if( success )
+ ConsolePrintf( PRIO_MEDIUM, "*** configured device: '%s = %s', success:%d\n", pFileName, pString, success );
+ else
+ ConsolePrintf( PRIO_ERROR, RED"DriverConfiguration.WriteCharactersToFile failed for file '%s', errno:'%s'"RESETCOLOR"\n",
+ pFileName, GetErrnoString() );
+ return success;
+}
+
+static bool WriteIntegerToFile( const char *pFileName, int intValue )
+{
+ char tempBuffer[16];
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%d", intValue );
+ return WriteCharactersToFile( pFileName, tempBuffer );
+}
+
+static bool ReadFromFile( const char *pFileName, char *pString, uint16_t bufferLen )
+{
+ bool success = false;
+ if( NULL == pString || 0 == bufferLen )
+ return success;
+ FILE *fh = fopen( pFileName, "r" );
+ if( NULL != fh )
+ {
+ success = ( NULL != fgets( pString, bufferLen, fh ) );
+ fclose( fh );
+ }
+ if( !success )
+ ConsolePrintf( PRIO_ERROR, RED"DriverConfiguration.ReadFromFile failed for file '%s', errno:'%s'"RESETCOLOR"\n",
+ pFileName, GetErrnoString() );
+ return success;
+}
+
+static bool ExistsDevice( const char *pDeviceName )
+{
+ struct stat buffer;
+ return ( stat( pDeviceName, &buffer ) == 0 );
+}
+
+static bool WaitForDevice( const char *pDeviceName )
+{
+ int timeout;
+ bool deviceExists = false;
+ for( timeout = 0; timeout < 40; timeout++ )
+ {
+ deviceExists = ExistsDevice( pDeviceName );
+ if( deviceExists )
+ {
+ break;
+ }
+ else
+ {
+ usleep( 2500 );
+ }
+ }
+ if( !deviceExists )
+ ConsolePrintf( PRIO_ERROR, RED"Waiting for device '%s' to appear, timed out"RESETCOLOR"\n",
+ pDeviceName );
+ return deviceExists;
+}
+
+static bool GetDeviceDescription( uint8_t deviceInstance, char *deviceString, uint32_t stringLen )
+{
+ bool descriptionFound = false;
+ char descriptionPath[64];
+ char descriptionValue[32];
+
+ if( NULL == deviceString )
+ return descriptionFound;
+
+ snprintf( descriptionPath, sizeof( descriptionPath ),
+ "/sys/devices/virtual/most/mostcore/devices/mdev%d/description", deviceInstance );
+
+ if( !ExistsDevice( descriptionPath ) )
+ return descriptionFound;
+
+ descriptionFound = ReadFromFile( descriptionPath, descriptionValue, sizeof( descriptionValue ) );
+ if( descriptionFound )
+ {
+ strncpy( deviceString, descriptionValue, stringLen );
+ }
+ return descriptionFound;
+}
+
+static bool ExistsDeviceWithType( uint8_t deviceInstance, const char *deviceString, uint32_t stringLen )
+{
+ bool deviceFound = false;
+ char interfacePath[64];
+ char interfaceValue[32];
+
+ if( NULL == deviceString )
+ return deviceFound;
+
+ snprintf( interfacePath, sizeof( interfacePath ), "/sys/devices/virtual/most/mostcore/devices/mdev%d/interface",
+ deviceInstance );
+
+ if( !ExistsDevice( interfacePath ) )
+ return deviceFound;
+
+ deviceFound = ReadFromFile( interfacePath, interfaceValue, sizeof( interfaceValue ) );
+ if( deviceFound )
+ {
+ deviceFound = ( 0 == strncmp( interfaceValue, deviceString, stringLen ) );
+ }
+ return deviceFound;
+}
+
+static bool GetAlsaConfiguration( uint16_t subBufferSize, uint8_t *amountOfChannels, uint8_t *bitDepth )
+{
+ if( NULL == amountOfChannels || NULL == bitDepth )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"GetAlsaConfiguration was called with invalid parameters"RESETCOLOR"\n" );
+ return false;
+ }
+ switch( subBufferSize )
+ {
+ case 2:
+ *amountOfChannels = 1;
+ *bitDepth = 16;
+ break;
+ case 4:
+ *amountOfChannels = 2;
+ *bitDepth = 16;
+ break;
+ case 6:
+ *amountOfChannels = 2;
+ *bitDepth = 24;
+ break;
+ case 8:
+ *amountOfChannels = 2;
+ *bitDepth = 32;
+ break;
+ case 12:
+ *amountOfChannels = 6;
+ *bitDepth = 16;
+ break;
+ case 18:
+ *amountOfChannels = 6;
+ *bitDepth = 24;
+ break;
+ case 16:
+ *amountOfChannels = 8;
+ *bitDepth = 16;
+ break;
+ case 24:
+ *amountOfChannels = 8;
+ *bitDepth = 24;
+ break;
+ default:
+ ConsolePrintf( PRIO_ERROR, RED"Configure ALSA device was called"\
+ " with unknown sub-buffer size: %d"RESETCOLOR"\n", subBufferSize );
+ return false;
+ }
+ return true;
+}
+
+bool ExistsUsbDeviceInstance( uint8_t deviceInstance )
+{
+ uint32_t i;
+ bool found = false;
+ uint8_t curDevInst = 0;
+ char lastDescr[64];
+ lastDescr[0] = '\0';
+ for( i = 0; i < 12; i++ )
+ {
+ uint32_t curDescrLen;
+ char curDescr[64];
+ if( !ExistsDeviceWithType( i, "usb", 3 ) )
+ continue;
+
+ if( !GetDeviceDescription( i, curDescr, sizeof( curDescr ) ) )
+ continue;
+
+ curDescrLen = strnlen( curDescr, sizeof( curDescr ) );
+ if( curDescrLen <= 2 )
+ continue;
+
+ //Cut away the last two characters, as they are different for the 3 interfaces of INIC
+ curDescrLen -= 2;
+
+ if( 0 == strncmp( curDescr, lastDescr, curDescrLen ) )
+ continue;
+
+ strncpy( lastDescr, curDescr, curDescrLen );
+ lastDescr[curDescrLen] = '\0';
+
+ if( curDevInst++ != deviceInstance )
+ continue;
+
+ found = true;
+ break;
+ }
+ return found;
+}
+
+bool ExistsMlbDeviceInstance( uint8_t deviceInstance )
+{
+ return ExistsDeviceWithType( deviceInstance, "mlb", 3 );
+}
+
+bool ExistsI2CDeviceInstance( uint8_t deviceInstance )
+{
+ return ExistsDeviceWithType( deviceInstance, "i2c", 3 );
+}
+
+bool GetUsbDeviceNames( uint8_t deviceInstance, uint8_t endpointAddress, char *deviceName, uint16_t deviceNameLength,
+ char *systemName, uint16_t systemNameLength, char *linkName, uint16_t linkNameLength )
+{
+ uint32_t i;
+ bool systemFound = false;
+ uint8_t curDevInst = 0;
+ char lastDescr[64];
+ lastDescr[0] = '\0';
+ char endpointBuffer[16];
+ char systemSourceDir[64];
+ DIR *d;
+ struct dirent *dir;
+
+ if( NULL == deviceName || NULL == systemName || NULL == linkName )
+ return false;
+
+ deviceName[0] = '\0';
+ systemName[0] = '\0';
+
+ for( i = 0; !systemFound && i < 12; i++ )
+ {
+ uint32_t curDescrLen;
+ char curDescr[64];
+ if( !ExistsDeviceWithType( i, "usb", 3 ) )
+ continue;
+
+ if( !GetDeviceDescription( i, curDescr, sizeof( curDescr ) ) )
+ continue;
+
+ curDescrLen = strnlen( curDescr, sizeof( curDescr ) );
+ if( curDescrLen <= 2 )
+ continue;
+
+ //Cut away the last two characters, as they are different for the 3 interfaces of INIC
+ curDescrLen -= 2;
+
+ if( ( '\0' != lastDescr[0] )
+ && ( 0 != strncmp( curDescr, lastDescr, curDescrLen ) ) )
+ {
+ ++curDevInst;
+ }
+
+ strncpy( lastDescr, curDescr, curDescrLen );
+ lastDescr[curDescrLen] = '\0';
+
+ if( curDevInst < deviceInstance )
+ continue;
+ else if( curDevInst > deviceInstance )
+ break;
+
+ snprintf( endpointBuffer, sizeof( endpointBuffer ), "ep%02x", endpointAddress );
+ snprintf( systemSourceDir, sizeof( systemSourceDir ), "/sys/devices/virtual/most/mostcore/devices/mdev%d", i );
+ d = opendir( systemSourceDir );
+ if( d )
+ {
+ while( ( dir = readdir( d ) ) != NULL )
+ {
+ if( strstr( dir->d_name, endpointBuffer ) )
+ {
+ snprintf( systemName, systemNameLength, "%s/%s", systemSourceDir, dir->d_name );
+ snprintf( deviceName, deviceNameLength, "/dev/mdev%d-%s", deviceInstance, dir->d_name );
+ snprintf( linkName, linkNameLength, "mdev%d:%s:mdev%d-%s", i, dir->d_name, deviceInstance,
+ dir->d_name );
+ systemFound = true;
+ break;
+ }
+ }
+ closedir( d );
+ }
+ }
+ return systemFound;
+}
+
+bool GetMlbDeviceNames( uint8_t deviceInstance, uint8_t mlbChannelAddress, char *deviceName, uint16_t deviceNameLength,
+ char *systemName, uint16_t systemNameLength, char *linkName, uint16_t linkNameLength )
+{
+ bool systemFound = false;
+ char channelBuffer[16];
+ char systemSourceDir[64];
+ DIR *d;
+ struct dirent *dir;
+
+ if( NULL == deviceName || NULL == systemName || NULL == linkName )
+ return false;
+
+ deviceName[0] = '\0';
+ systemName[0] = '\0';
+
+ snprintf( channelBuffer, sizeof( channelBuffer ), "ca%d", mlbChannelAddress );
+ snprintf( systemSourceDir, sizeof( systemSourceDir ), "/sys/devices/virtual/most/mostcore/devices/mdev%d",
+ deviceInstance );
+ d = opendir( systemSourceDir );
+ if( d )
+ {
+ while( ( dir = readdir( d ) ) != NULL )
+ {
+ if( strstr( dir->d_name, channelBuffer ) )
+ {
+ snprintf( systemName, systemNameLength, "%s/%s", systemSourceDir, dir->d_name );
+ snprintf( deviceName, deviceNameLength, "/dev/mdev%d-%s", deviceInstance, dir->d_name );
+ snprintf( linkName, linkNameLength, "mdev%d:%s:mdev%d-%s", deviceInstance, dir->d_name, deviceInstance,
+ dir->d_name );
+ systemFound = true;
+ break;
+ }
+ }
+ closedir( d );
+ }
+ return systemFound;
+}
+
+bool GetI2CDeviceNames( uint8_t deviceInstance, bool isTx, char *deviceName, uint16_t deviceNameLength,
+ char *systemName, uint16_t systemNameLength, char *linkName, uint16_t linkNameLength )
+{
+ bool systemFound = false;
+ char systemSourceDir[64];
+ DIR *d;
+ struct dirent *dir;
+
+ if( NULL == deviceName || NULL == systemName || NULL == linkName )
+ return false;
+
+ deviceName[0] = '\0';
+ systemName[0] = '\0';
+
+ snprintf( systemSourceDir, sizeof( systemSourceDir ), "/sys/devices/virtual/most/mostcore/devices/mdev%d",
+ deviceInstance );
+ d = opendir( systemSourceDir );
+ if( d )
+ {
+ while( ( dir = readdir( d ) ) != NULL )
+ {
+ if( strstr( dir->d_name, ( isTx ? "tx" : "rx" ) ) )
+ {
+ snprintf( systemName, systemNameLength, "%s/%s", systemSourceDir, dir->d_name );
+ snprintf( deviceName, deviceNameLength, "/dev/mdev%d-%s", deviceInstance, dir->d_name );
+ snprintf( linkName, linkNameLength, "mdev%d:%s:mdev%d-%s", deviceInstance, dir->d_name, deviceInstance,
+ dir->d_name );
+ systemFound = true;
+ break;
+ }
+ }
+ closedir( d );
+ }
+ return systemFound;
+}
+
+bool CloseMostChannel( const char *device )
+{
+ return true;
+}
+
+bool ConfigureMostChannel( const char *device, EPDataType_t mostType, EPDirection_t direction, uint32_t numBuf,
+ uint32_t bufSize )
+{
+ static const char *controlType = "control";
+ static const char *asyncType = "async";
+ static const char *syncType = "sync";
+ static const char *isocType = "isoc_avp";
+ static const char *rxDirection = "dir_rx";
+ static const char *txDirection = "dir_tx";
+ bool success = true;
+ char tempBuffer[128];
+ const char *typeString = NULL;
+ const char *directionString = NULL;
+
+ switch( mostType )
+ {
+ case EP_Control:
+ typeString = controlType;
+ break;
+ case EP_Asynchron:
+ typeString = asyncType;
+ break;
+ case EP_Synchron:
+ typeString = syncType;
+ break;
+ case EP_Isochron:
+ typeString = isocType;
+ break;
+ default:
+ return false;
+ }
+
+ switch( direction )
+ {
+ case EPDIR_IN:
+ directionString = txDirection;
+ break;
+ case EPDIR_OUT:
+ directionString = rxDirection;
+ break;
+ default:
+ return false;
+ }
+
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_datatype", device ); /// Setting data type
+ success = WriteCharactersToFile( tempBuffer, typeString );
+ if( success )
+ {
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_direction", device ); /// Setting direction
+ success = WriteCharactersToFile( tempBuffer, directionString );
+ }
+ if( success )
+ {
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_number_of_buffers", device ); /// Setting amount of buffers
+ success = WriteIntegerToFile( tempBuffer, numBuf );
+ }
+ if( success )
+ {
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_buffer_size", device ); /// Setting amount of buffers
+ success = WriteIntegerToFile( tempBuffer, bufSize );
+ }
+ return success;
+}
+
+bool ConfigureIsocChannel( const char *device, uint32_t subbufferSize, uint32_t packetsPerTransaction )
+{
+ char tempBuffer[128];
+ bool success;
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_subbuffer_size", device ); /// Setting the subbuffer size in bytes
+ success = WriteIntegerToFile( tempBuffer, subbufferSize );
+
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_packets_per_xact", device ); /// Setting the packets per transaction
+ success = WriteIntegerToFile( tempBuffer, ( packetsPerTransaction & 0xFF ) );
+ return success;
+}
+
+bool ConfigureSyncChannel( const char *device, uint32_t syncBlockWidth, uint32_t amounOfSyncFrames )
+{
+ char tempBuffer[128];
+ bool success;
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_packets_per_xact", device ); /// Setting the amount of frames in one USB frame
+ success = WriteIntegerToFile( tempBuffer, amounOfSyncFrames );
+
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_subbuffer_size", device ); /// Setting the blockwidth of a single frame
+ success = WriteIntegerToFile( tempBuffer, syncBlockWidth );
+ return success;
+}
+
+bool LinkToCharacterDevice( const char *linkName, const char *deviceName )
+{
+ bool success =
+ WriteCharactersToFile( "/sys/devices/virtual/most/mostcore/aims/cdev/add_link", linkName );
+ if( success )
+ {
+ success = WaitForDevice( deviceName );
+ }
+ if( success )
+ {
+ chmod( deviceName, ( S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH ) );
+ }
+ return success;
+}
+
+bool LinkToAudioDevice( const char *linkName, uint16_t subBufferSize )
+{
+ char tempBuffer[128];
+ uint8_t amountOfChannels;
+ uint8_t bitDepth;
+ if( !GetAlsaConfiguration( subBufferSize, &amountOfChannels, &bitDepth ) )
+ return false;
+
+ snprintf( tempBuffer, sizeof( tempBuffer ), "%s.%dx%d", linkName, amountOfChannels, bitDepth ); /// Add the channel information behind the Link Name
+
+ //Be compatible to all versions of MOST Linux Driver. The name was changed of Sound AIM.
+ bool success =
+ WriteCharactersToFile( "/sys/devices/virtual/most/mostcore/aims/sound/add_link", tempBuffer );
+ if( !success )
+ success =
+ WriteCharactersToFile( "/sys/devices/virtual/most/mostcore/aims/audio/add_link", tempBuffer );
+ return success;
+}
+
+bool LinkToVideoForLinuxDevice( const char *linkName )
+{
+ bool success =
+ WriteCharactersToFile( "/sys/devices/virtual/most/mostcore/aims/v4l/add_link", linkName );
+ return success;
+}
+
+const char *GetErrnoString()
+{
+ switch( errno )
+ {
+ case 0:
+ return "Nothing stored in errno";
+ case 1:
+ return "Operation not permitted";
+ case 2:
+ return "No such file or directory";
+ case 3:
+ return "No such process";
+ case 4:
+ return "Interrupted system call";
+ case 5:
+ return "I/O error";
+ case 6:
+ return "No such device or address";
+ case 7:
+ return "Argument list too long";
+ case 8:
+ return "Exec format error";
+ case 9:
+ return "Bad file number";
+ case 10:
+ return "No child processes";
+ case 11:
+ return "Try again";
+ case 12:
+ return "Out of memory";
+ case 13:
+ return "Permission denied";
+ case 14:
+ return "Bad address";
+ case 15:
+ return "Block device required";
+ case 16:
+ return "Device or resource busy";
+ case 17:
+ return "File exists";
+ case 18:
+ return "Cross-device link";
+ case 19:
+ return "No such device";
+ case 20:
+ return "Not a directory";
+ case 21:
+ return "Is a directory";
+ case 22:
+ return "Invalid argument";
+ case 23:
+ return "File table overflow";
+ case 24:
+ return "Too many open files";
+ case 25:
+ return "Not a typewriter";
+ case 26:
+ return "Text file busy";
+ case 27:
+ return "File too large";
+ case 28:
+ return "No space left on device";
+ case 29:
+ return "Illegal seek";
+ case 30:
+ return "Read-only file system";
+ case 31:
+ return "Too many links";
+ case 32:
+ return "Broken pipe";
+ case 33:
+ return "Math argument out of domain of func";
+ case 34:
+ return "Math result not representable";
+ default:
+ break;
+ }
+ return "Unknown";
+}
diff --git a/Src/Network/base/DriverConfiguration.h b/Src/Network/base/DriverConfiguration.h
new file mode 100644
index 0000000..b2fd44a
--- /dev/null
+++ b/Src/Network/base/DriverConfiguration.h
@@ -0,0 +1,239 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This component provides helper tools to deal with USB endpoints.
+ */
+/*----------------------------------------------------------*/
+#ifndef DRIVERCONFIGURATION_H
+#define DRIVERCONFIGURATION_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "Types.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------*/
+ /*! \brief Checks if the given USB device instance exists.
+ *
+ * \param deviceInstance - The device instance of the USB INIC, starting at 0 for the first instance.
+ *
+ * \return true: Device exists.
+ * \return false: Device does not exist.
+ */
+ /*----------------------------------------------------------*/
+ bool ExistsUsbDeviceInstance( uint8_t deviceInstance );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Checks if the given MLB device instance exists.
+ *
+ * \param deviceInstance - The device instance of the MLB INIC, starting at 0 for the first instance.
+ *
+ * \return true: Device exists.
+ * \return false: Device does not exist.
+ */
+ /*----------------------------------------------------------*/
+ bool ExistsMlbDeviceInstance( uint8_t deviceInstance );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Checks if the given I2C device instance exists.
+ *
+ * \param deviceInstance - The device instance of the I2C INIC, starting at 0 for the first instance.
+ *
+ * \return true: Device exists.
+ * \return false: Device does not exist.
+ */
+ /*----------------------------------------------------------*/
+ bool ExistsI2CDeviceInstance( uint8_t deviceInstance );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retreives the Linux character device names for the given USB device instance and the endpoint address.
+ *
+ * \note If the given buffer is too small to hold the whole path, the string is truncated and not useable!
+ *
+ * \param deviceInstance - The device instance of the USB INIC, starting at 0 for the first instance.
+ * \param endpointAddress - The USB endpoint address, RX endpoints starting with upper bit set (0x8X).
+ * \param deviceName - [in,out] Given buffer will be filled with device name (starting with /dev/).
+ * \param deviceNameLength - The length of the given deviceName buffer in bytes.
+ * \param systemName - [in,out] Given buffer will be filled with system name (starting with /sys/).
+ * \param systemNameLength - The length of the given systemName buffer in bytes.
+ * \param linkName - [in,out] Given buffer will be filled with the string needed to register this device to an AIM
+ * \param linkNameLength - The length of the given linkName buffer in bytes.
+ *
+ * \return true: Operation was successful.
+ * \return false: Operation failed, device or endpoint does not exist.
+ */
+ /*----------------------------------------------------------*/
+ bool GetUsbDeviceNames( uint8_t deviceInstance, uint8_t endpointAddress, char *deviceName,
+ uint16_t deviceNameLength, char *systemName, uint16_t systemNameLength, char *linkName,
+ uint16_t linkNameLength );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retreives the Linux character device names for the given MLB device instance and the endpoint address.
+ *
+ * \note If the given buffer is too small to hold the whole path, the string is truncated and not useable!
+ *
+ * \param deviceInstance - The device instance of the USB INIC, starting at 0 for the first instance.
+ * \param mlbChannelAddress - The MLB channel address
+ * \param deviceName - [in,out] Given buffer will be filled with device name (starting with /dev/).
+ * \param deviceNameLength - The length of the given deviceName buffer in bytes.
+ * \param systemName - [in,out] Given buffer will be filled with system name (starting with /sys/).
+ * \param systemNameLength - The length of the given systemName buffer in bytes.
+ * \param linkName - [in,out] Given buffer will be filled with the string needed to register this device to an AIM
+ * \param linkNameLength - The length of the given linkName buffer in bytes.
+ *
+ * \return true: Operation was successful.
+ * \return false: Operation failed, device or endpoint does not exist.
+ */
+ /*----------------------------------------------------------*/
+ bool GetMlbDeviceNames( uint8_t deviceInstance, uint8_t mlbChannelAddress, char *deviceName,
+ uint16_t deviceNameLength, char *systemName, uint16_t systemNameLength, char *linkName,
+ uint16_t linkNameLength );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retreives the Linux character device names for the given I2C device instance and the endpoint address.
+ *
+ * \note If the given buffer is too small to hold the whole path, the string is truncated and not useable!
+ *
+ * \param deviceInstance - The device instance of the I2C INIC, starting at 0 for the first instance.
+ * \param isTx - true, if the names for transmission path should be retrieved, otherwise for the reception path.
+ * \param deviceName - [in,out] Given buffer will be filled with device name (starting with /dev/).
+ * \param deviceNameLength - The length of the given deviceName buffer in bytes.
+ * \param systemName - [in,out] Given buffer will be filled with system name (starting with /sys/).
+ * \param systemNameLength - The length of the given systemName buffer in bytes.
+ * \param linkName - [in,out] Given buffer will be filled with the string needed to register this device to an AIM
+ * \param linkNameLength - The length of the given linkName buffer in bytes.
+ *
+ * \return true: Operation was successful.
+ * \return false: Operation failed, device or endpoint does not exist.
+ */
+ /*----------------------------------------------------------*/
+ bool GetI2CDeviceNames( uint8_t deviceInstance, bool isTx, char *deviceName, uint16_t deviceNameLength,
+ char *systemName, uint16_t systemNameLength, char *linkName, uint16_t linkNameLength );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Closes the MOST channel.
+ *
+ * \param device - The system path to configure the MOST device (starting with "/sys/").
+ *
+ * \return True if no error
+ */
+ /*----------------------------------------------------------*/
+ bool CloseMostChannel( const char *device );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Configures the MOST channel.
+ *
+ * \param device - The system path to configure the MOST device (starting with "/sys/").
+ * \param mostType - The MOST data type (control, asynchron, synchron, isochron).
+ * \param direction - The direction of the stream (directionRX, directionTX).
+ * \param numBuf - The amount of buffers.
+ * \param bufSize - The size of each buffer in bytes.
+ *
+ * \return True if no error
+ */
+ /*----------------------------------------------------------*/
+ bool ConfigureMostChannel( const char *device, EPDataType_t mostType, EPDirection_t direction, uint32_t numBuf,
+ uint32_t bufSize );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Configures the isochronous channel of a device.
+ * \note This function has to be called before ConfigureMostChannel!
+ *
+ * \param device - The system path to configure the MOST device (starting with "/sys/").
+ * \param subbufferSize - The amount of bytes for a single subbuffer (eg. 188 or 196 bytes).
+ * \param packetsPerTransaction - The amount of ischronous packets per transaction.
+ *
+ * \return True if no error
+ */
+ /*----------------------------------------------------------*/
+ bool ConfigureIsocChannel( const char *device, uint32_t subbufferSize, uint32_t packetsPerTransaction );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Configures the Synchronous channel of a device.
+ * \note This function has to be called before ConfigureMostChannel!
+ *
+ * \param device - The system path to configure the MOST device (starting with "/sys/").
+ * \param syncBlockWidth - The bandwidth of a single synchronous frame. Ignored if not sync channel.
+ * \param amounOfSyncFrames - The amount of synchronous frames per USB packet. Ignored if not sync channel.
+ *
+ * \return True if no error
+ */
+ /*----------------------------------------------------------*/
+ bool ConfigureSyncChannel( const char *device, uint32_t syncBlockWidth, uint32_t amounOfSyncFrames );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates a character device for the given device's link name.
+ *
+ * \param linkName - [in] Link name, which is needed to register this device to an AIM.
+ * \param deviceName - [in,out] Device name (starting with /dev/).
+ *
+ * \return True if no error
+ */
+ /*----------------------------------------------------------*/
+ bool LinkToCharacterDevice( const char *linkName, const char *deviceName );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates a audio device (ALSA) for the given device's link name.
+ *
+ * \param linkName - [in] Link name, which is needed to register this device to an AIM.
+ * \param subBufferSize - [in] The amount of bytes for all channels of this connection on the MOST.
+ *
+ * \return True if no error
+ */
+ /*----------------------------------------------------------*/
+ bool LinkToAudioDevice( const char *linkName, uint16_t subBufferSize );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Creates a Video for Linux device (V4L) for the given device's link name.
+ *
+ * \param linkName - [in] Link name, which is needed to register this device to an AIM.
+ *
+ * \return True if no error
+ */
+ /*----------------------------------------------------------*/
+ bool LinkToVideoForLinuxDevice( const char *linkName );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Parsed the global errno variable and generate a human readable error description out of it.
+ *
+ * \return Zero terminated error description string.
+ */
+ /*----------------------------------------------------------*/
+ const char *GetErrnoString();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //DRIVERCONFIGURATION_H
diff --git a/Src/SafeVector.h b/Src/SafeVector.h
new file mode 100644
index 0000000..97a4882
--- /dev/null
+++ b/Src/SafeVector.h
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CSafeVector class.
+ */
+/*----------------------------------------------------------*/
+
+#ifndef SAFE_VECTOR_H
+#define SAFE_VECTOR_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <semaphore.h>
+#include <vector>
+#include "SafeVector.h"
+
+using namespace std;
+
+/*----------------------------------------------------------*/
+/*! \brief Thread safe vector class.
+ */
+/*----------------------------------------------------------*/
+template<typename T>
+class CSafeVector
+{
+private:
+ bool initialized;
+ std::vector<T> vec;
+ sem_t sem;
+public:
+ /*----------------------------------------------------------*/
+ /*! \brief Default constructor of CSafeVector.
+ */
+ /*----------------------------------------------------------*/
+ CSafeVector() : initialized(false)
+ {
+ sem_init( &sem, 0, 1 ); //Mutex, initialized to 1 => sem_wait will block at 2nd call
+ }
+
+ /*----------------------------------------------------------*/
+ /*! \brief Default destructor of CSafeVector.
+ */
+ /*----------------------------------------------------------*/
+ ~CSafeVector()
+ {
+ vec.empty();
+ sem_destroy( &sem);
+ }
+
+ /*----------------------------------------------------------*/
+ /*! \brief Stores the given object into the last postion of the vector.
+ */
+ /*----------------------------------------------------------*/
+ void PushBack(T obj)
+ {
+ if( NULL == obj )
+ return;
+ sem_wait( &sem );
+ vec.push_back( obj );
+ initialized = true;
+ sem_post( &sem );
+ }
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets the first element from the vector and dequeue it.
+ * \return The first object if exists, otherwise NULL,
+ */
+ /*----------------------------------------------------------*/
+ T PopFront()
+ {
+ T obj = NULL;
+ sem_wait( &sem );
+ if (vec.size() >= 1)
+ {
+ obj = vec[0];
+ vec.erase( vec.begin() );
+ }
+ sem_post( &sem );
+ return obj;
+ }
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets the first element from the vector and dequeue it.
+ * \return The first object if exists, otherwise NULL,
+ */
+ /*----------------------------------------------------------*/
+ T operator[](uint32_t p)
+ {
+ if( !initialized )
+ return NULL;
+ T obj = NULL;
+ sem_wait( &sem );
+ uint32_t s = vec.size();
+ if (0 != s && p < s)
+ {
+ obj = vec[p];
+ }
+ sem_post( &sem );
+ return obj;
+ }
+
+ /*----------------------------------------------------------*/
+ /*! \brief Gets the amount of objects stored in the vector.
+ * \return The amount of objects available.
+ */
+ /*----------------------------------------------------------*/
+ uint32_t Size()
+ {
+ uint32_t s;
+ if( !initialized )
+ return 0;
+
+ sem_wait( &sem );
+ s = vec.size();
+ sem_post( &sem );
+ return s;
+ }
+
+ /*----------------------------------------------------------*/
+ /*! \brief Safley removes the given object from the vector.
+ * \note If not found, it will be silently ignored.
+ * \note The memory of the object will NOT be freed!
+ */
+ /*----------------------------------------------------------*/
+ void Remove(T obj)
+ {
+ int32_t deleteIndex = -1;
+ if( !initialized || NULL == obj )
+ return;
+
+ sem_wait( &sem );
+ for( uint32_t i = 0; i < vec.size(); i++ )
+ {
+ if( obj == vec[i] )
+ {
+ deleteIndex = i;
+ break;
+ }
+ }
+ if( -1 != deleteIndex )
+ {
+ vec.erase( vec.begin() + deleteIndex );
+ }
+ sem_post( &sem );
+ }
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Safley removes the given object from the vector.
+ * \note If not found, it will be silently ignored.
+ * \param destroy - if set to true, the memory will be freed for each deleted object.
+ */
+ /*----------------------------------------------------------*/
+ void RemoveAll(bool destroy)
+ {
+ if( !initialized )
+ return;
+ sem_wait( &sem );
+ for( uint32_t i = 0; destroy && i < vec.size(); i++ )
+ {
+ T obj = vec[i];
+ delete obj;
+ }
+ vec.clear();
+ sem_post( &sem );
+ }
+};
+
+#endif //SAFE_VECTOR_H \ No newline at end of file
diff --git a/Src/ScriptXml.cpp b/Src/ScriptXml.cpp
new file mode 100644
index 0000000..94c7ae3
--- /dev/null
+++ b/Src/ScriptXml.cpp
@@ -0,0 +1,200 @@
+/*
+ * 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 "SafeVector.h"
+#include "Console.h"
+#include "ScriptXml.h"
+
+#define TAG_SCRIPT ((xmlChar *)"script")
+#define TAG_ACTION ((xmlChar *)"action")
+#define TAG_NAME ((xmlChar *)"name")
+#define TAG_TYPE ((xmlChar *)"type")
+#define TAG_FBLOCK_ID_HEX ((xmlChar *)"fblock_id_hex")
+#define TAG_FUNCTION_ID_HEX ((xmlChar *)"function_id_hex")
+#define TAG_OP_TYPE_REQUEST_HEX ((xmlChar *)"op_type_request_hex")
+#define TAG_OP_TYPE_RESPONSE_HEX ((xmlChar *)"op_type_response_hex")
+#define TAG_PAYLOAD_HEX ((xmlChar *)"payload_hex")
+#define TAG_PAUSE_MS ((xmlChar *)"pause_ms")
+
+#define VAL_SEND_MCM ((char*)"SEND_MCM")
+#define VAL_PAUSE ((char*)"PAUSE")
+
+#define XML_STRCMP(x,y) (strcmp(reinterpret_cast< const char* >(x), reinterpret_cast< const char* >(y)) == 0)
+
+CSciptXml::CSciptXml( const char *szFile ) : CXml( szFile )
+{
+
+}
+
+CSciptXml::CSciptXml( const char *szBuffer, uint32_t nBufferLen ) : CXml( szBuffer, nBufferLen )
+{
+
+}
+
+bool CSciptXml::GetScripts( CSafeVector<CScript *> &allChannels )
+{
+ xmlChar szTmp[XML_DEFAULT_VALUE_LEN];
+ bool success = false;
+ CXml Xml( *( ( CXml * )this ) );
+ success = Xml.SetToTopNode();
+
+ while( success && Xml.FindNode( TAG_ACTION ) )
+ {
+ ConsolePrintf( PRIO_LOW, BLUE"--NEW ACTION--"RESETCOLOR"\n" );
+ CScript *script = new CScript();
+ if( NULL == script )
+ break;
+
+ szTmp[0] = '\0';
+ success &= Xml.GetChildValue( TAG_NAME, szTmp, XML_DEFAULT_VALUE_LEN );
+ if( success )
+ {
+ ConsolePrintf( PRIO_LOW, BLUE"Name: '%s'"RESETCOLOR"\n", szTmp );
+ int nameLen = sizeof( xmlChar ) * ( xmlStrlen( szTmp ) + 1 );
+ if( nameLen >= MAX_SCRIPT_NAME_LENGTH )
+ nameLen = MAX_SCRIPT_NAME_LENGTH - 1;
+ memcpy( script->scriptName, szTmp, nameLen );
+ script->scriptName[nameLen] = '\0'; //Terminate string in any case
+ }
+
+ szTmp[0] = '\0';
+ success &= Xml.GetChildValue( TAG_TYPE, szTmp );
+ if( success )
+ {
+ ConsolePrintf( PRIO_LOW, BLUE"Type: %s"RESETCOLOR"\n", szTmp );
+ if( XML_STRCMP(szTmp, VAL_SEND_MCM) )
+ {
+ script->scriptType = SCRIPT_MCM_SEND;
+ }
+ else if( XML_STRCMP(szTmp, VAL_PAUSE) )
+ {
+ script->scriptType = SCRIPT_PAUSE;
+ }
+ else
+ {
+ //Be tolerant to new types
+ ConsolePrintf( PRIO_ERROR, YELLOW"CSciptXml: Ignoring unknown TYPE:'%s'"RESETCOLOR"\n", szTmp );
+ delete script;
+ Xml.FindNextNode();
+ continue;
+ }
+ }
+
+ if( SCRIPT_MCM_SEND == script->scriptType )
+ {
+ szTmp[0] = '\0';
+ success &= Xml.GetChildValue( TAG_FBLOCK_ID_HEX, szTmp, XML_DEFAULT_VALUE_LEN );
+ if( success )
+ {
+ script->fblockId = ConvertToInt( szTmp );
+ ConsolePrintf( PRIO_LOW, BLUE"FBlock-ID: '%s=%d'"RESETCOLOR"\n", szTmp, script->fblockId );
+ }
+
+ szTmp[0] = '\0';
+ success &= Xml.GetChildValue( TAG_FUNCTION_ID_HEX, szTmp, XML_DEFAULT_VALUE_LEN );
+ if( success )
+ {
+ script->functionId = ConvertToInt( szTmp );
+ ConsolePrintf( PRIO_LOW, BLUE"Function-ID: '%s=%d'"RESETCOLOR"\n", szTmp, script->functionId );
+ }
+
+ szTmp[0] = '\0';
+ success &= Xml.GetChildValue( TAG_OP_TYPE_REQUEST_HEX, szTmp,
+ XML_DEFAULT_VALUE_LEN );
+ if( success )
+ {
+ script->opTypeRequest = ConvertToInt( szTmp );
+ ConsolePrintf( PRIO_LOW, BLUE"OP-Type Request: '%s=%d'"RESETCOLOR"\n", szTmp, script->opTypeRequest );
+ }
+
+ szTmp[0] = '\0';
+ if( Xml.GetChildValue( TAG_OP_TYPE_RESPONSE_HEX, szTmp,
+ XML_DEFAULT_VALUE_LEN ) )
+ {
+ script->opTypeResponse = ConvertToInt( szTmp );
+ ConsolePrintf( PRIO_LOW, BLUE"OP-Type Response: '%s=%d'"RESETCOLOR"\n", szTmp,
+ script->opTypeResponse );
+ }
+ else
+ {
+ script->opTypeResponse = 0xFF;
+ ConsolePrintf( PRIO_LOW, BLUE"OP-Type Response was not defined"RESETCOLOR"\n" );
+ }
+
+ szTmp[0] = '\0';
+ //Payload is optional
+ if( Xml.GetChildValue( TAG_PAYLOAD_HEX, szTmp, XML_DEFAULT_VALUE_LEN ) )
+ {
+ ConsolePrintf( PRIO_LOW, BLUE"Payload: '%s'"RESETCOLOR"\n", szTmp );
+ StorePayload( szTmp, script );
+ }
+ }
+ else if( SCRIPT_PAUSE == script->scriptType )
+ {
+ szTmp[0] = '\0';
+ success &= Xml.GetChildValue( TAG_PAUSE_MS, szTmp, XML_DEFAULT_VALUE_LEN );
+ if( success )
+ {
+ script->pauseInMillis = strtol( ( char * )szTmp, NULL, 10 );
+ ConsolePrintf( PRIO_LOW, BLUE"FBlock-ID: '%s=%d'"RESETCOLOR"\n", szTmp, script->fblockId );
+ }
+ }
+ if( success )
+ {
+ allChannels.PushBack( script );
+ }
+ else
+ {
+ delete script;
+ }
+ Xml.FindNextNode();
+ }
+ return success;
+}
+
+void CSciptXml::StorePayload( xmlChar *xString, CScript *script )
+{
+ char *cString = ( char * )xString; //Convertion may be needed..
+ script->payloadLength = 0;
+ for( uint32_t i = 0; i < strlen( cString ); i++ )
+ {
+ if( cString[i] >= 65 && cString[i] <= 90 )
+ {
+ //convert upper case to lower case
+ cString[i] += 32;
+ }
+ }
+ char *tkPtr;
+ char *token = strtok_r( cString, " ,.-", &tkPtr );
+ while( NULL != token )
+ {
+ if( script->payloadLength >= MAX_PAYLOAD_LENGTH )
+ {
+ ConsolePrintf( PRIO_ERROR,
+ "CSciptXml::ConvertToByteArray, MAX_PAYLOAD_LENGTH is defined too low. Please increase value!" );
+ break;
+ }
+ script->payload[script->payloadLength++] = strtol( token, NULL, 16 );
+ token = strtok_r( NULL, " ,.-", &tkPtr );
+ }
+}
diff --git a/Src/ScriptXml.h b/Src/ScriptXml.h
new file mode 100644
index 0000000..093c4ae
--- /dev/null
+++ b/Src/ScriptXml.h
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CSciptXml class.
+ */
+/*----------------------------------------------------------*/
+#ifndef _SCRIPTXML_H_
+#define _SCRIPTXML_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <Types.h>
+#include "Xml.h"
+
+#define MAX_SCRIPT_NAME_LENGTH 64
+#define MAX_PAYLOAD_LENGTH 64
+
+typedef enum ScriptType_tag
+{
+ SCRIPT_UNKNOWN,
+ SCRIPT_MCM_SEND,
+ SCRIPT_PAUSE
+} ScriptType_t;
+
+/*----------------------------------------------------------*/
+/*!
+ * \brief Storage class to store the scripting informations. This class will be returned by
+ * the CSciptXml class.
+ */
+/*----------------------------------------------------------*/
+class CScript
+{
+public:
+ ScriptType_t scriptType;
+ char scriptName[MAX_SCRIPT_NAME_LENGTH];
+ uint8_t fblockId;
+ uint16_t functionId;
+ uint8_t opTypeRequest;
+ uint8_t opTypeResponse;
+ uint8_t payload[MAX_PAYLOAD_LENGTH];
+ uint32_t payloadLength;
+ uint32_t pauseInMillis;
+
+ CScript() : scriptType( SCRIPT_UNKNOWN ), fblockId( 0xFF ), functionId( 0xFFFF ), opTypeRequest( 0xFF ),
+ opTypeResponse( 0xFF ), payloadLength( 0 ), pauseInMillis( 0 )
+ {
+ scriptName[0] = '\0';
+ }
+};
+
+/*----------------------------------------------------------*/
+/*!
+ * \brief Class to read XML for the NetworkManager scripting use case.
+ */
+/*----------------------------------------------------------*/
+class CSciptXml : public CXml
+{
+private:
+ void StorePayload( xmlChar *xString, CScript *script );
+public:
+ CSciptXml( const char *szFile );
+ CSciptXml( const char *szBuffer, uint32_t nBufferLen );
+ bool GetScripts( CSafeVector<CScript *> &allChannels );
+};
+
+#endif //_SCRIPTXML_H_
diff --git a/Src/Thread.cpp b/Src/Thread.cpp
new file mode 100644
index 0000000..b6bb01e
--- /dev/null
+++ b/Src/Thread.cpp
@@ -0,0 +1,129 @@
+/*
+ * 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 "Thread.h"
+#include <string.h>
+#include "Console.h"
+
+CThread::CThread( const char *threadName, bool maxPrio ) : m_hThread( THREAD_STATE_DONE )
+{
+ strncpy( m_threadName, threadName, sizeof( m_threadName ) );
+ m_maxPrio = maxPrio;
+#ifdef THREAD_DEBUG
+ ConsolePrintf(PRIO_LOW, "===== Thread '%s' has been created =====\n", m_threadName);
+#endif
+}
+
+CThread::~CThread()
+{
+ Stop();
+ usleep( 10000 );
+ while( IsThreadRunning() )
+ {
+ ConsolePrintf( PRIO_LOW, "===== Thread '%s' is still running =====\n", m_threadName );
+ usleep( 1000000 );
+ }
+}
+
+void *CThread::RunInst( void *pInst )
+{
+ CThread *thread = ( CThread * )pInst;
+ if( NULL == thread )
+ return 0;
+
+ /* set thread priority: */
+ if( thread->m_maxPrio )
+ {
+ int ret;
+ pthread_t this_thread = pthread_self();
+ struct sched_param params;
+ params.sched_priority = sched_get_priority_max( SCHED_FIFO );
+ ret = pthread_setschedparam( this_thread, SCHED_FIFO, &params );
+ if( ret != 0 )
+ {
+ ConsolePrintf( PRIO_ERROR, "Thread %s: pthread_setschedparam(SCHED_FIFO) failed\n", thread->m_threadName );
+ }
+ // Now verify the change in thread priority
+ int policy = 0;
+ ret = pthread_getschedparam( this_thread, &policy, &params );
+ if( ret != 0 )
+ {
+ ConsolePrintf( PRIO_ERROR, "Thread %s: pthread_getschedparam() failed\n", thread->m_threadName );
+ }
+ if( policy != SCHED_FIFO )
+ {
+ ConsolePrintf( PRIO_ERROR, "Thread %s: Scheduling is NOT SCHED_FIFO!\n", thread->m_threadName );
+ }
+ else
+ {
+ ConsolePrintf( PRIO_LOW, "Thread %s: SCHED_FIFO OK\n", thread->m_threadName );
+ }
+ ConsolePrintf( PRIO_LOW, "Thread %s: Thread priority is %d\n", thread->m_threadName, params.sched_priority );
+ }
+
+ while( THREAD_STATE_STOPPING !=
+ thread->m_hThread )
+ { // until thread is marked for termination
+#ifdef THREAD_DEBUG
+ ConsolePrintf(PRIO_LOW, "+++++ Thread '%s' run before Run +++++\n", thread->m_threadName);
+#endif
+ ( ( CThread * )pInst )->Run();
+#ifdef THREAD_DEBUG
+ ConsolePrintf(PRIO_LOW, "----- Thread '%s' run after Run -----\n", thread->m_threadName);
+#endif
+ }
+
+ ( ( CThread * )pInst )->m_hThread = THREAD_STATE_DONE; // mark thread as done
+
+ return 0;
+}
+
+void CThread::Start()
+{
+ if( THREAD_STATE_DONE != m_hThread )
+ return;
+
+ struct sched_param param;
+ pthread_attr_t tattr;
+ pthread_attr_init( &tattr );
+ pthread_attr_getschedparam( &tattr, &param );
+ pthread_attr_setschedpolicy( &tattr, SCHED_RR );
+ if( m_maxPrio )
+ {
+ param.sched_priority = sched_get_priority_max( SCHED_RR );
+ pthread_attr_setschedparam( &tattr, &param );
+ // note: this doesn't seem to work, so we're setting prio in RunInst() now
+ }
+ pthread_create( &m_hThread, &tattr, CThread::RunInst, ( void * )this );
+}
+
+void CThread::Stop()
+{
+ if( m_hThread )
+ m_hThread = THREAD_STATE_STOPPING;
+}
+
+bool CThread::IsThreadRunning()
+{
+ return ( THREAD_STATE_DONE != m_hThread );
+}
diff --git a/Src/Thread.h b/Src/Thread.h
new file mode 100644
index 0000000..01f6500
--- /dev/null
+++ b/Src/Thread.h
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CThread class.
+ */
+/*----------------------------------------------------------*/
+#ifndef THREAD_H
+#define THREAD_H
+
+#include <pthread.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdio.h>
+
+//#define THREAD_DEBUG
+#define THREAD_STATE_DONE 0
+#define THREAD_STATE_STOPPING (pthread_t)-1
+
+/*----------------------------------------------------------*/
+/*! \brief Helper class to deal with Threads.
+ */
+/*----------------------------------------------------------*/
+class CThread
+{
+ pthread_t m_hThread;
+ char m_threadName[32];
+ bool m_maxPrio;
+
+public:
+ CThread( const char *threadName, bool maxPrio );
+ virtual ~CThread();
+
+ /*----------------------------------------------------------*/
+ /*! \brief Starts the thread execution.
+ */
+ /*----------------------------------------------------------*/
+ void Start();
+
+ /*----------------------------------------------------------*/
+ /*! \brief Stops the thread execution.
+ */
+ /*----------------------------------------------------------*/
+ void Stop();
+
+ /*----------------------------------------------------------*/
+ /*! \brief Determines if the thread is running.
+ * \return true, if the thread is running. false, if the thread is stopped.
+ */
+ /*----------------------------------------------------------*/
+ bool IsThreadRunning();
+
+ /*----------------------------------------------------------*/
+ /*! \brief This method must be overridden the deriving class.
+ * This method will then run in an own thread.
+ * This method will be infinitely called, as long as the CThread object is marked to run.
+ */
+ /*----------------------------------------------------------*/
+ virtual void Run() = 0;
+
+private:
+ static void *RunInst( void *pInst );
+
+};
+
+#endif
+
diff --git a/Src/Types.h b/Src/Types.h
new file mode 100644
index 0000000..13ab01b
--- /dev/null
+++ b/Src/Types.h
@@ -0,0 +1,230 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the EPDataType_t, EPDirection_t, MlbPortSpeed_t, V1I2SPortClkDriveMode_t, V1I2SStreamingDataFormat_t,
+ * V1I2SPin_t, V3I2SPortOption_t, V3I2SClockMode_t, V3I2SDelayMode_t, V3I2SPortSpeed_t, V3I2SAlignment_t, V3I2SPin_t type definition.
+ */
+/*----------------------------------------------------------*/
+#ifndef _TYPES_H_
+#define _TYPES_H_
+
+#include <inttypes.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include "Console.h"
+
+#define LOG(x) ConsolePrintf(PRIO_ERROR, RED"! %s, %u, %s"RESETCOLOR"\n",x,__LINE__,__FILE__)
+
+#define SCM_IN 0x00
+#define SCM_OUT 0x01
+
+typedef uint32_t TChannelId;
+typedef uint16_t TDeviceId;
+typedef uint8_t TNodePos;
+typedef uint16_t TNodeAddr;
+typedef uint32_t TBlockwidth;
+typedef uint8_t TMostInstace;
+typedef uint16_t TPos; ///Value is in per mile. (0..1000)
+
+typedef enum AimType_tag
+{
+ AIM_UNKNOWN,
+ AIM_CDEV,
+ AIM_AUDIO,
+ AIM_V4L
+} AimType_t;
+
+///Data type enum values are matched to INIC API V1 & V2
+typedef enum
+{
+ EP_Synchron = 0x00,
+ EP_Asynchron = 0x01,
+ EP_Control = 0x02,
+ EP_Isochron = 0x03,
+ EP_Unused = 0xFE,
+ EP_Unknown = 0xFF
+} EPDataType_t;
+
+///Direction type enum values are matched to INIC API V1 & V2
+typedef enum
+{
+ EPDIR_IN = 0x00,
+ EPDIR_OUT = 0x01,
+ EPDIR_Unknown = 0xFF
+} EPDirection_t;
+
+///INIC API V1 and V2: MLB Port speed in mulitple of MOST base clock (FS)
+typedef enum
+{
+ MlbSpeed256FS = 0,
+ MlbSpeed512FS = 1,
+ MlbSpeed1024FS = 2,
+ MlbSpeed2048FS = 3,
+ MlbSpeed3072FS = 4,
+ MlbSpeed4096FS = 5,
+ MlbSpeed6144FS = 6,
+ MlbSpeed8192FS = 7,
+ MlbSpeedNotSet = 0xFF
+} MlbPortSpeed_t;
+
+///TSI Port ID
+typedef enum
+{
+ V1TsiPortInstance0 = 0x5,
+ V1TsiPortInstance1 = 0x25,
+ V1TsiPortInstanceNotSet = 0xFF
+} V1TsiPortInstance_t;
+
+///TSI Port Mode
+typedef enum
+{
+ V1TsiPortModeSlave = 0x0,
+ V1TsiPortModeMaster = 0x1,
+ V1TsiPortModeNotSet = 0xFF
+} V1TsiPortMode;
+
+///I2S Port drive mode
+typedef enum
+{
+ V1I2sClockModeOutput = 0,
+ V1I2sClockModeInput = 1,
+ V1I2sClockModeIsocOutput = 2,
+ V1I2sClockModeIsocInput = 3,
+ V1I2sClockModeUnknown = 0xFE,
+} V1I2SPortClkDriveMode_t;
+
+///I2S Streaming Port mode
+typedef enum
+{
+ V1I2sStreamingPortInOut = 0,
+ V1I2sStreamingPortDualIn = 1,
+ V1I2sStreamingPortDualOut = 2,
+ V1I2sStreamingPortFullStream = 3,
+ V1I2sStreamingPortUnknown = 0xFE,
+ V1I2sStreamingPortWildcard = 0xFF ///Only valid for OS81110
+} V1I2SStreamingPortMode_t;
+
+///I2S Port streaming data format
+typedef enum
+{
+ V1I2sDelay64Fs16Bit = 0x00,
+ V1I2sDelay64Fs24Bit = 0x01,
+ V1I2sDelay64FsSeq = 0x04,
+ V1I2sDelay128FsSeq = 0x05,
+ V1I2sDelay256FsSeq = 0x06,
+ V1I2sRight64Fs16Bit = 0x07,
+ V1I2sRight64Fs24Bit = 0x08,
+ V1I2sSeq64Fs = 0x0B,
+ V1I2sSeq128Fs = 0x0C,
+ V1I2sSeq256Fs = 0x0D,
+ V1I2sLeft64Fs16Bit = 0x0E,
+ V1I2sLeft64Fs24Bit = 0x0F,
+ V1I2sDelay512FsSeq = 0x17,
+ V1I2sSeq512Fs = 0x18,
+ V1I2sDataFormatUnknown = 0xFE,
+} V1I2SStreamingDataFormat_t;
+
+///I2S Stream Pin ID
+typedef enum
+{
+ V1I2sSR0Pin = 0x00,
+ V1I2sSX0Pin = 0x01,
+ V1I2sSR1Pin = 0x02,
+ V1I2sSX1Pin = 0x03,
+ V1I2sSR2Pin = 0x04,
+ V1I2sSX2Pin = 0x05,
+ V1I2sSR3Pin = 0x06,
+ V1I2sSX3Pin = 0x07,
+ V1I2sFSYSCKPins = 0x10,
+ V1I2sInvalidPin = 0xFE,
+} V1I2SPin_t;
+
+///I2S Port option
+typedef enum
+{
+ V3I2SOptionInOut = 0,
+ V3I2SOptionDualIn = 1,
+ V3I2SOptionDualOut = 2,
+ V3I2SOptionUnknown = 0xFE
+} V3I2SPortOption_t;
+
+///I2S Clock mode
+typedef enum
+{
+ V3I2SClockModeOutput = 0,
+ V3I2SClockModeInput = 1,
+ V3I2SClockModeWildcard = 0xFF,
+ V3I2SClockModeUnknown = 0xFE
+} V3I2SClockMode_t;
+
+///I2S Delay option
+typedef enum
+{
+ V3I2SDelayOff = 0,
+ V3I2SDelayEnabled = 1,
+ V3I2SDelayWildcard = 0xFF,
+ V3I2SDelayUnknown = 0xFE
+} V3I2SDelayMode_t;
+
+///I2S Port speed in mulitple of MOST base clock (FS)
+typedef enum
+{
+ V3I2SSpeed64FS = 3,
+ V3I2SSpeed128FS = 4,
+ V3I2SSpeed256FS = 5,
+ V3I2SSpeed512FS = 6,
+ V3I2SSpeedWildcard = 0xFF,
+ V3I2SSpeedUnknown = 0xFE
+} V3I2SPortSpeed_t;
+
+///I2S Data Alignment
+typedef enum
+{
+ V3I2SAlignLeft16 = 0,
+ V3I2SAlignLeft24 = 1,
+ V3I2SAlignRight16 = 2,
+ V3I2SAlignRight24 = 3,
+ V3I2SAlignSeq = 4,
+ V3I2SAlignUnknown = 0xFE
+} V3I2SAlignment_t;
+
+///I2S Stream Pin ID
+typedef enum
+{
+ V3I2SSRXA0 = 0x0,
+ V3I2SSRXA1 = 0x1,
+ V3I2SSRXB0 = 0x10,
+ V3I2SSRXB1 = 0x11,
+ V3I2SInvalidPin = 0xFE
+} V3I2SPin_t;
+
+#endif
diff --git a/Src/VodXml.cpp b/Src/VodXml.cpp
new file mode 100644
index 0000000..edf27c5
--- /dev/null
+++ b/Src/VodXml.cpp
@@ -0,0 +1,1112 @@
+/*
+ * 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 "SafeVector.h"
+#include "Console.h"
+#include "VodXml.h"
+
+#define TAG_ADDRESS ((xmlChar *)"channel_addr")
+#define TAG_ADDRESS_HEX ((xmlChar *)"channel_addr_hex")
+#define TAG_ASYNC_BANDWIDTH ((xmlChar *)"async_bandwidth")
+#define TAG_BLOCKWIDTH ((xmlChar *)"blockwidth")
+#define TAG_OFFSET ((xmlChar *)"offset")
+#define TAG_BUFFER_SIZE ((xmlChar *)"buffer_size")
+#define TAG_CHANNEL ((xmlChar *)"channel")
+#define TAG_CHANNEL_ID ((xmlChar *)"channel_id")
+#define TAG_DATA_TYPE ((xmlChar *)"data_type")
+#define TAG_AIM_TYPE ((xmlChar *)"aim_type")
+#define TAG_DEVICE ((xmlChar *)"device")
+#define TAG_DEVICE_API_VERSION ((xmlChar *)"device_api_ver")
+#define TAG_DEVICE_MLB_SPEED ((xmlChar *)"open_mlb_port_speed")
+#define TAG_DEVICE_TYPE ((xmlChar *)"device_type")
+#define TAG_DEVICE_TYPE_HEX ((xmlChar *)"device_type_hex")
+#define TAG_DIR ((xmlChar *)"dir")
+#define TAG_ENDPOINT ((xmlChar *)"endpoint")
+#define TAG_TSI_PORT_ID ((xmlChar *)"tsi_port_id")
+#define TAG_TSI_PORT_MODE ((xmlChar *)"tsi_port_mode")
+#define TAG_I2S_V1_CLKDRIVEMODE ((xmlChar *)"i2s_v1_clock_drive_mode")
+#define TAG_I2S_V1_OPTION ((xmlChar *)"i2s_v1_option")
+#define TAG_I2S_V1_DATAFORMAT ((xmlChar *)"i2s_v1_data_format")
+#define TAG_I2S_V1_PIN ((xmlChar *)"i2s_v1_pin")
+#define TAG_I2S_OPTION ((xmlChar *)"i2s_option")
+#define TAG_I2S_CLOCK_DIR ((xmlChar *)"i2s_clock_dir")
+#define TAG_I2S_CLOCK_DELAY ((xmlChar *)"i2s_clock_delay")
+#define TAG_I2S_FS_SPEED ((xmlChar *)"i2s_fs_speed")
+#define TAG_I2S_ALIGN ((xmlChar *)"i2s_align")
+#define TAG_I2S_PIN ((xmlChar *)"i2s_pin")
+#define TAG_INSTANCE ((xmlChar *)"instance")
+#define TAG_LOCAL_CONNECTION ((xmlChar *)"local_connection")
+#define TAG_NETWORK_CONFIG ((xmlChar *)"network_config")
+#define TAG_NETWORK_MANAGER ((xmlChar *)"network_manager")
+#define TAG_NUMBER_OF_BUFFERS ((xmlChar *)"number_of_buffers")
+#define TAG_PACKETS_XACT ((xmlChar *)"packets_per_xact")
+#define TAG_PACKETS_XACT_HEX ((xmlChar *)"packets_per_xact_hex")
+#define TAG_PORT_ID ((xmlChar *)"port_id")
+#define TAG_ROUTE ((xmlChar *)"route")
+#define TAG_SCRIPT ((xmlChar *)"script")
+#define TAG_SOCKET ((xmlChar *)"socket")
+#define TAG_SUBBUFFER_SIZE ((xmlChar *)"subbuffer_size")
+#define TAG_TERMINAL ((xmlChar *)"terminal")
+#define TAG_TIMING_MASTER ((xmlChar *)"timing_master")
+
+#define VAL_AIM_TYPE_CDEV ((char*)"CDEV")
+#define VAL_AIM_TYPE_AUDIO ((char*)"AUDIO")
+#define VAL_AIM_TYPE_V4L ((char*)"V4L")
+
+#define VAL_PORT_MLB ((char*)"MLB")
+#define VAL_PORT_TSI ((char*)"TSI")
+#define VAL_PORT_I2S ((char*)"I2S")
+#define VAL_PORT_I2C ((char*)"I2C")
+#define VAL_PORT_USB ((char*)"USB")
+#define VAL_PORT_PCIE ((char*)"PCIE")
+#define VAL_PORT_MOST ((char*)"MOST")
+
+#define VAL_DATATYPE_SYNC ((char*)"SYNC")
+#define VAL_DATATYPE_ISOC ((char*)"ISOC")
+#define VAL_DATATYPE_ASYNC ((char*)"ASYNC")
+#define VAL_DATATYPE_CTRL ((char*)"CTRL")
+
+#define VAL_DIR_IN ((char*)"IN")
+#define VAL_DIR_OUT ((char*)"OUT")
+
+#define VAL_TSI_V1_PORT_0 ((char*)"TSI_PORT0")
+#define VAL_TSI_V1_PORT_1 ((char*)"TSI_PORT1")
+
+#define VAL_TSI_V1_SLAVE ((char*)"TSI_SLAVE")
+#define VAL_TSI_V1_MASTER ((char*)"TSI_MASTER")
+
+#define VAL_I2S_V1_CLK_OUTPUT ((char*)"Output")
+#define VAL_I2S_V1_CLK_INPUT ((char*)"Input")
+#define VAL_I2S_V1_CLK_ISOCOUT ((char*)"IsocOutput")
+#define VAL_I2S_V1_CLK_ISOCIN ((char*)"IsocInput")
+
+#define VAL_I2S_V1_OPTION_INOUT ((char*)"InOut")
+#define VAL_I2S_V1_OPTION_DUALIN ((char*)"DualIn")
+#define VAL_I2S_V1_OPTION_DUALOUT ((char*)"DualOut")
+#define VAL_I2S_V1_OPTION_FULL ((char*)"FullStream")
+#define VAL_I2S_V1_OPTION_WILDCARD ((char*)"Wildcard")
+
+#define VAL_I2S_V1_FMT_D64Fs16 ((char*)"Delay64Fs16Bit")
+#define VAL_I2S_V1_FMT_D64Fs24 ((char*)"Delay64Fs24Bit")
+#define VAL_I2S_V1_FMT_D64FsSeq ((char*)"Delay64FsSeq")
+#define VAL_I2S_V1_FMT_D128FsSeq ((char*)"Delay128FsSeq")
+#define VAL_I2S_V1_FMT_D256FsSeq ((char*)"Delay256FsSeq")
+#define VAL_I2S_V1_FMT_R64Fs16 ((char*)"Right64Fs16Bit")
+#define VAL_I2S_V1_FMT_R64Fs24 ((char*)"Right64Fs24Bit")
+#define VAL_I2S_V1_FMT_Seq64Fs ((char*)"Seq64Fs")
+#define VAL_I2S_V1_FMT_Seq128Fs ((char*)"Seq128Fs")
+#define VAL_I2S_V1_FMT_Seq256Fs ((char*)"Seq256Fs")
+#define VAL_I2S_V1_FMT_L64Fs16 ((char*)"Left64Fs16Bit")
+#define VAL_I2S_V1_FMT_L64Fs24 ((char*)"Left64Fs24Bit")
+#define VAL_I2S_V1_FMT_D512FsSeq ((char*)"Delay512FsSeq")
+#define VAL_I2S_V1_FMT_Seq512Fs ((char*)"Seq512Fs")
+
+#define VAL_I2S_V1_PIN_SR0 ((char*)"SR0Pin")
+#define VAL_I2S_V1_PIN_SX0 ((char*)"SX0Pin")
+#define VAL_I2S_V1_PIN_SR1 ((char*)"SR1Pin")
+#define VAL_I2S_V1_PIN_SX1 ((char*)"SX1Pin")
+#define VAL_I2S_V1_PIN_SR2 ((char*)"SR2Pin")
+#define VAL_I2S_V1_PIN_SX2 ((char*)"SX2Pin")
+#define VAL_I2S_V1_PIN_SR3 ((char*)"SR3Pin")
+#define VAL_I2S_V1_PIN_SX3 ((char*)"SX3Pin")
+#define VAL_I2S_V1_PIN_FSY_SCK ((char*)"FSY_SCK_Pins")
+
+#define VAL_I2S_OPTION_INOUT ((char*)"InOut")
+#define VAL_I2S_OPTION_DUALIN ((char*)"DualIn")
+#define VAL_I2S_OPTION_DUALOUT ((char*)"DualOut")
+#define VAL_I2S_OPTION_WILDCARD ((char*)"Wildcard")
+
+#define VAL_I2S_CLOCK_OUTPUT ((char*)"Output")
+#define VAL_I2S_CLOCK_INPUT ((char*)"Input")
+#define VAL_I2S_CLOCK_WILDCARD ((char*)"Wildcard")
+
+#define VAL_I2S_ALIGNMENT_L16 ((char*)"Left16")
+#define VAL_I2S_ALIGNMENT_L24 ((char*)"Left24")
+#define VAL_I2S_ALIGNMENT_R16 ((char*)"Right16")
+#define VAL_I2S_ALIGNMENT_R24 ((char*)"Right24")
+#define VAL_I2S_SEQUENTIAL ((char*)"Seq")
+
+#define VAL_I2S_PIN_SRXA0 ((char*)"SRXA0")
+#define VAL_I2S_PIN_SRXA1 ((char*)"SRXA1")
+#define VAL_I2S_PIN_SRXB0 ((char*)"SRXB0")
+#define VAL_I2S_PIN_SRXB1 ((char*)"SRXB1")
+
+#define UNKNOWN_ENDPOINT_ADDR 0xFF
+
+#define XML_STRCMP(x,y) (strcmp(reinterpret_cast< const char* >(x), reinterpret_cast< const char* >(y)) == 0)
+
+CVodXml::CVodXml( const char *szFile ) : CXml( szFile )
+{
+
+}
+
+bool CVodXml::GetLocalInicConfigurations( uint8_t *rxEndpoint, uint8_t *txEndpoint )
+{
+ if( NULL == rxEndpoint || NULL == txEndpoint )
+ return false;
+ *rxEndpoint = UNKNOWN_ENDPOINT_ADDR;
+ *txEndpoint = UNKNOWN_ENDPOINT_ADDR;
+ CXml rootXml( *( ( CXml * )this ) );
+ bool success = rootXml.SetToTopNode();
+ if( success && rootXml.FindNode( TAG_NETWORK_MANAGER ) )
+ {
+ CXml xmlNWM( rootXml );
+ success = xmlNWM.FindFirstChildNode();
+ while( success && xmlNWM.FindNode( TAG_ENDPOINT ) )
+ {
+ ConsolePrintf( PRIO_LOW, "NETWORK_MANAGER\r\n" );
+ xmlChar interface[XML_DEFAULT_VALUE_LEN];
+ if( xmlNWM.GetChildValue( TAG_PORT_ID, interface ) )
+ {
+ if( XML_STRCMP(interface, VAL_PORT_I2C) )
+ {
+ ConsolePrintf( PRIO_LOW,
+ "GetLocalInicConfigurations found I2C, returning without channel addresses\r\n" );
+ return true;
+ }
+ }
+ xmlChar dataType[XML_DEFAULT_VALUE_LEN];
+ xmlChar direction[XML_DEFAULT_VALUE_LEN];
+ dataType[0] = '\0';
+ direction[0] = '\0';
+ int epAddress;
+ success &= xmlNWM.GetChildValue( TAG_DATA_TYPE, dataType );
+ ConsolePrintf( PRIO_LOW, " Type:%s\r\n", dataType );
+ success &= xmlNWM.GetChildValue( TAG_DIR, direction );
+ ConsolePrintf( PRIO_LOW, " Direction:%s\r\n", direction );
+ if( !xmlNWM.GetChildValueInt( TAG_ADDRESS, epAddress ) )
+ {
+ xmlChar szTmp[XML_DEFAULT_VALUE_LEN];
+ if( xmlNWM.GetChildValue( TAG_ADDRESS_HEX, szTmp, XML_DEFAULT_VALUE_LEN ) )
+ epAddress = ConvertToInt( szTmp );
+ }
+ ConsolePrintf( PRIO_LOW, " Address:%d\r\n", epAddress );
+
+ if( success )
+ {
+ if( XML_STRCMP(dataType, VAL_DATATYPE_CTRL) )
+ {
+ if( XML_STRCMP(direction, VAL_DIR_IN) )
+ {
+ *rxEndpoint = epAddress;
+ }
+ else if( XML_STRCMP(direction, VAL_DIR_OUT) )
+ {
+ *txEndpoint = epAddress;
+ }
+ }
+ }
+ else
+ {
+ ConsolePrintf( PRIO_ERROR, "Failed to retrieve Endpoint config\n" );
+ }
+ xmlNWM.FindNextNode();
+ }
+ }
+ return success && ( 0xFF != *rxEndpoint ) && ( 0xFF != *txEndpoint );
+}
+
+bool CVodXml::GetMostParameters(bool *isTimingMaster, uint32_t *asyncBandwidth)
+{
+ if( NULL == isTimingMaster || NULL == asyncBandwidth )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"GetMostParameters was"\
+ " called with wrong parameters"RESETCOLOR"\n" );
+ return false;
+ }
+ uint8_t serverNum = 0;
+ CXml xmlNWM( *( ( CXml * )this ) );
+ bool success = xmlNWM.SetToTopNode();
+ if( success && xmlNWM.FindNode( TAG_NETWORK_MANAGER ) )
+ {
+ success = xmlNWM.FindFirstChildNode();
+ while( success && xmlNWM.FindNode( TAG_LOCAL_CONNECTION ) )
+ {
+ serverNum += 1;
+ xmlNWM.FindNextNode();
+ }
+ }
+ //Be compatible to old XML API
+ if( !success || 0 == serverNum )
+ {
+ success = GetNetworkConfiguration( isTimingMaster, asyncBandwidth );
+ return success;
+ }
+
+ if( success )
+ success = xmlNWM.SetToTopNode();
+ if( success )
+ success = xmlNWM.FindNode( TAG_NETWORK_MANAGER );
+ if( success )
+ success = xmlNWM.FindFirstChildNode();
+
+ if( success && xmlNWM.FindNode( TAG_LOCAL_CONNECTION ) )
+ {
+ CXml xmlLC( xmlNWM );
+ int bw;
+ int tm = true;
+ success &= xmlNWM.GetChildValueInt( TAG_TIMING_MASTER, tm );
+ if (success)
+ {
+ ConsolePrintf( PRIO_LOW, " Timing Master:%d\r\n", tm );
+ success &= xmlNWM.GetChildValueInt( TAG_ASYNC_BANDWIDTH, bw );
+ if (success)
+ {
+ *isTimingMaster = tm;
+ *asyncBandwidth = bw;
+ ConsolePrintf( PRIO_LOW, "Asynchronous Bandwidth:%d\r\n", bw );
+ }
+ }
+ }
+ return success;
+}
+
+bool CVodXml::GetLocalInicConfigurations( uint8_t *rxEndpoint[], uint8_t *txEndpoint[], uint32_t *apiVersion[],
+ SocketPort_t *hwPort[], bool *isTimingMaster[], uint32_t *asyncBandwidth[], uint8_t *serverNum )
+{
+ if( NULL == rxEndpoint || NULL == txEndpoint || NULL == serverNum ||
+ NULL == apiVersion || NULL == hwPort || NULL == isTimingMaster ||
+ NULL == asyncBandwidth )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"GetLocalInicConfigurations was"\
+ " called with wrong parameters"RESETCOLOR"\n" );
+ return false;
+ }
+ *rxEndpoint = NULL;
+ *txEndpoint = NULL;
+ *apiVersion = NULL;
+ *hwPort = NULL;
+ *isTimingMaster = NULL;
+ *asyncBandwidth = NULL;
+ *serverNum = 0;
+ CXml xmlNWM( *( ( CXml * )this ) );
+ bool success = xmlNWM.SetToTopNode();
+ if( success && xmlNWM.FindNode( TAG_NETWORK_MANAGER ) )
+ {
+ success = xmlNWM.FindFirstChildNode();
+ while( success && xmlNWM.FindNode( TAG_LOCAL_CONNECTION ) )
+ {
+ *serverNum = *serverNum + 1;
+ xmlNWM.FindNextNode();
+ }
+ }
+ //Be compatible to old XML API
+ if( !success || 0 == *serverNum )
+ {
+ uint8_t rxEP;
+ uint8_t txEP;
+ bool tm;
+ uint32_t bw;
+ success = GetLocalInicConfigurations( &rxEP, &txEP );
+ if( success )
+ success = GetNetworkConfiguration( &tm, &bw );
+
+ if( success )
+ {
+ *rxEndpoint = ( uint8_t * )calloc( 1, sizeof( uint8_t ) );
+ *txEndpoint = ( uint8_t * )calloc( 1, sizeof( uint8_t ) );
+ *apiVersion = ( uint32_t * )calloc( 1, sizeof( uint32_t ) );
+ *hwPort = ( SocketPort_t * )calloc( 1, sizeof( SocketPort_t ) );
+ *isTimingMaster = ( bool * )calloc( 1, sizeof( bool ) );
+ *asyncBandwidth = ( uint32_t * )calloc( 1, sizeof( uint32_t ) );
+ ( *rxEndpoint )[0] = rxEP;
+ ( *txEndpoint )[0] = txEP;
+ ( *apiVersion )[0] = GetServerDeviceApi();
+ ( *hwPort )[0] = GetServerHardwareInterface();
+ ( *isTimingMaster )[0] = tm;
+ ( *asyncBandwidth )[0] = bw;
+ *serverNum = 1;
+ }
+ return success;
+ }
+ //New method to get multiple instances of local configurations
+ *rxEndpoint = ( uint8_t * )calloc( *serverNum, sizeof( uint8_t ) );
+ *txEndpoint = ( uint8_t * )calloc( *serverNum, sizeof( uint8_t ) );
+ *apiVersion = ( uint32_t * )calloc( *serverNum, sizeof( uint32_t ) );
+ *hwPort = ( SocketPort_t * )calloc( *serverNum, sizeof( SocketPort_t ) );
+ *isTimingMaster = ( bool * )calloc( *serverNum, sizeof( bool ) );
+ *asyncBandwidth = ( uint32_t * )calloc( *serverNum, sizeof( uint32_t ) );
+
+ if( success )
+ success = xmlNWM.SetToTopNode();
+ if( success )
+ success = xmlNWM.FindNode( TAG_NETWORK_MANAGER );
+ if( success )
+ success = xmlNWM.FindFirstChildNode();
+
+ uint8_t currentCon = 0;
+ while( success && xmlNWM.FindNode( TAG_LOCAL_CONNECTION ) && currentCon < *serverNum )
+ {
+ int apiVer = -1;
+ CXml xmlLC( xmlNWM );
+ if( xmlLC.GetChildValueInt( TAG_DEVICE_API_VERSION, apiVer ) )
+ {
+ ( *apiVersion )[currentCon] = ( uint32_t )apiVer;
+ ConsolePrintf( PRIO_LOW, "[Con:%d] API Version: %d\r\n", currentCon, apiVer );
+ }
+ ( *hwPort )[currentCon] = PORT_UNKNOWN;
+ xmlChar interface[XML_DEFAULT_VALUE_LEN];
+ if( xmlLC.GetChildValue( TAG_PORT_ID, interface ) )
+ {
+ ConsolePrintf( PRIO_LOW, "[Con:%d] HW Type: %s\r\n", currentCon, interface );
+
+ if( XML_STRCMP(interface, VAL_PORT_MLB) )
+ ( *hwPort )[currentCon] = PORT_MLB;
+ else if( XML_STRCMP(interface, VAL_PORT_TSI) )
+ ( *hwPort )[currentCon] = PORT_TSI;
+ else if( XML_STRCMP(interface, VAL_PORT_USB) )
+ ( *hwPort )[currentCon] = PORT_USB;
+ else if( XML_STRCMP(interface, VAL_PORT_I2C) )
+ ( *hwPort )[currentCon] = PORT_I2C;
+ }
+ int isMaster = true;
+ int bw = 40;
+ success &= xmlNWM.GetChildValueInt( TAG_TIMING_MASTER, isMaster );
+ ConsolePrintf( PRIO_LOW, "[Con:%d] Timing Master:%d\r\n", currentCon, isMaster );
+ success &= xmlNWM.GetChildValueInt( TAG_ASYNC_BANDWIDTH, bw );
+ ConsolePrintf( PRIO_LOW, "[Con:%d] Asynchronous Bandwidth:%d\r\n", currentCon, bw );
+ ( *isTimingMaster )[currentCon] = isMaster;
+ ( *asyncBandwidth )[currentCon] = bw;
+ success = xmlLC.FindFirstChildNode();
+ while( success && xmlLC.FindNode( TAG_ENDPOINT ) )
+ {
+ xmlChar dataType[XML_DEFAULT_VALUE_LEN];
+ xmlChar direction[XML_DEFAULT_VALUE_LEN];
+ dataType[0] = '\0';
+ direction[0] = '\0';
+ int epAddress;
+ success &= xmlLC.GetChildValue( TAG_DATA_TYPE, dataType );
+ ConsolePrintf( PRIO_LOW, "[Con:%d] Type:%s\r\n", currentCon, dataType );
+ success &= xmlLC.GetChildValue( TAG_DIR, direction );
+ ConsolePrintf( PRIO_LOW, "[Con:%d] Direction:%s\r\n", currentCon, direction );
+ if( !xmlLC.GetChildValueInt( TAG_ADDRESS, epAddress ) )
+ {
+ xmlChar szTmp[XML_DEFAULT_VALUE_LEN];
+ if( xmlLC.GetChildValue( TAG_ADDRESS_HEX, szTmp, XML_DEFAULT_VALUE_LEN ) )
+ epAddress = ConvertToInt( szTmp );
+ }
+ ConsolePrintf( PRIO_LOW, "[Con:%d] Address:%d\r\n", currentCon, epAddress );
+
+ if( success )
+ {
+ if( XML_STRCMP(dataType, VAL_DATATYPE_CTRL) )
+ {
+ if( XML_STRCMP(direction, VAL_DIR_IN) )
+ {
+ ( *rxEndpoint )[currentCon] = epAddress;
+ }
+ else if( XML_STRCMP(direction, VAL_DIR_OUT) )
+ {
+ ( *txEndpoint )[currentCon] = epAddress;
+ }
+ }
+ }
+ else
+ {
+ ConsolePrintf( PRIO_ERROR, "Failed to retrieve Endpoint config\n" );
+ }
+ xmlLC.FindNextNode();
+ }
+ currentCon++;
+ xmlNWM.FindNextNode();
+ }
+ return success;
+}
+
+SocketPort_t CVodXml::GetServerHardwareInterface()
+{
+ //Be compatible to old configurations, which had no interface declaration
+ SocketPort_t hwInterface = PORT_USB;
+ CXml rootXml( *( ( CXml * )this ) );
+ bool success = rootXml.SetToTopNode();
+ if( success && rootXml.FindNode( TAG_NETWORK_MANAGER ) )
+ {
+ CXml xmlNWM( rootXml );
+ success = xmlNWM.FindFirstChildNode();
+ if( success && xmlNWM.FindNode( TAG_ENDPOINT ) )
+ {
+ xmlChar interface[XML_DEFAULT_VALUE_LEN];
+
+ if( xmlNWM.GetChildValue( TAG_PORT_ID, interface ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - Port ID : %s\r\n", interface );
+ if( XML_STRCMP(interface, VAL_PORT_MLB) )
+ hwInterface = PORT_MLB;
+ else if( XML_STRCMP(interface, VAL_PORT_USB) )
+ hwInterface = PORT_USB;
+ else if( XML_STRCMP(interface, VAL_PORT_I2C) )
+ hwInterface = PORT_I2C;
+ }
+ }
+ }
+ return hwInterface;
+}
+
+uint32_t CVodXml::GetServerDeviceApi()
+{
+ //Be compatible to old configurations, which had no API declaration
+ uint32_t deviceApi = 2;
+ CXml rootXml( *( ( CXml * )this ) );
+ bool success = rootXml.SetToTopNode();
+ if( success && rootXml.FindNode( TAG_NETWORK_MANAGER ) )
+ {
+ CXml xmlNWM( rootXml );
+ success = xmlNWM.FindFirstChildNode();
+ if( success && xmlNWM.FindNode( TAG_ENDPOINT ) )
+ {
+ ConsolePrintf( PRIO_LOW, "NETWORK_MANAGER\r\n" );
+ int apiVer;
+ if( xmlNWM.GetChildValueInt( TAG_DEVICE_API_VERSION, apiVer ) )
+ {
+ deviceApi = apiVer;
+ ConsolePrintf( PRIO_LOW, " - Device API Version: %d\r\n", apiVer );
+ }
+ }
+ }
+ return deviceApi;
+}
+
+uint32_t CVodXml::GetDeviceApi( uint32_t deviceType )
+{
+ uint32_t deviceApi = 0xFFFFFFFF;
+ bool success = true;
+ CXml Xml( *( ( CXml * )this ) );
+ success = Xml.SetToTopNode();
+ success &= Xml.FindNode( TAG_NETWORK_MANAGER );
+ success &= Xml.FindFirstChildNode();
+
+ while( success && Xml.FindNode( TAG_DEVICE ) )
+ {
+ int xmlDeviceType = -1;
+ int xmlDeviceApiVer = -1;
+ if( !Xml.GetChildValueInt( TAG_DEVICE_TYPE, xmlDeviceType ) )
+ {
+ xmlChar szTmp[XML_DEFAULT_VALUE_LEN];
+ if( Xml.GetChildValue( TAG_DEVICE_TYPE_HEX, szTmp, XML_DEFAULT_VALUE_LEN ) )
+ xmlDeviceType = ConvertToInt( szTmp );
+ }
+ if( ( uint32_t )xmlDeviceType == deviceType )
+ {
+ success &= Xml.GetChildValueInt( TAG_DEVICE_API_VERSION, xmlDeviceApiVer );
+ if( success )
+ {
+ ConsolePrintf( PRIO_LOW, "Device API Version %d for device type: 0x%X\r\n", xmlDeviceApiVer,
+ xmlDeviceType );
+ deviceApi = xmlDeviceApiVer;
+ break;
+ }
+ }
+ Xml.FindNextNode();
+ }
+ return deviceApi;
+}
+
+MlbPortSpeed_t CVodXml::GetDeviceMlbPortSpeed( uint32_t deviceType )
+{
+ MlbPortSpeed_t mlbSpeed = MlbSpeedNotSet;
+ bool success = true;
+ CXml Xml( *( ( CXml * )this ) );
+ success = Xml.SetToTopNode();
+ success &= Xml.FindNode( TAG_NETWORK_MANAGER );
+ success &= Xml.FindFirstChildNode();
+
+ while( success && Xml.FindNode( TAG_DEVICE ) )
+ {
+ int xmlDeviceType;
+ int xmlDeviceMlbPortSpeed = -1;
+ if( !Xml.GetChildValueInt( TAG_DEVICE_TYPE, xmlDeviceType ) )
+ {
+ xmlChar szTmp[XML_DEFAULT_VALUE_LEN];
+ if( Xml.GetChildValue( TAG_DEVICE_TYPE_HEX, szTmp, XML_DEFAULT_VALUE_LEN ) )
+ xmlDeviceType = ConvertToInt( szTmp );
+ }
+ ConsolePrintf( PRIO_LOW, "DeviceType: %d\r\n", xmlDeviceType );
+ if( ( uint32_t )xmlDeviceType == deviceType )
+ {
+ success &= Xml.GetChildValueInt( TAG_DEVICE_MLB_SPEED, xmlDeviceMlbPortSpeed );
+ if( success )
+ {
+ ConsolePrintf( PRIO_LOW, "Device MLB speed %d for device type: 0x%X\r\n", xmlDeviceMlbPortSpeed,
+ xmlDeviceType );
+ switch( xmlDeviceMlbPortSpeed )
+ {
+ case 256:
+ mlbSpeed = MlbSpeed256FS;
+ break;
+ case 512:
+ mlbSpeed = MlbSpeed512FS;
+ break;
+ case 1024:
+ mlbSpeed = MlbSpeed1024FS;
+ break;
+ case 2048:
+ mlbSpeed = MlbSpeed2048FS;
+ break;
+ case 3072:
+ mlbSpeed = MlbSpeed3072FS;
+ break;
+ case 4096:
+ mlbSpeed = MlbSpeed4096FS;
+ break;
+ case 6144:
+ mlbSpeed = MlbSpeed6144FS;
+ break;
+ case 8192:
+ mlbSpeed = MlbSpeed8192FS;
+ break;
+ default:
+ mlbSpeed = MlbSpeedNotSet;
+ break;
+ }
+ break;
+ }
+ }
+ Xml.FindNextNode();
+ }
+ return mlbSpeed;
+}
+
+bool CVodXml::GetNetworkConfiguration( bool *isTimingMaster, uint32_t *asyncBandwidth )
+{
+ if( NULL == isTimingMaster || NULL == asyncBandwidth )
+ return false;
+ *isTimingMaster = true;
+ *asyncBandwidth = 40;
+ CXml rootXml( *( ( CXml * )this ) );
+ bool success = rootXml.SetToTopNode();
+ if( success && rootXml.FindNode( TAG_NETWORK_MANAGER ) )
+ {
+ CXml xmlNWM( rootXml );
+ success = xmlNWM.FindFirstChildNode();
+ while( success && xmlNWM.FindNode( TAG_NETWORK_CONFIG ) )
+ {
+ ConsolePrintf( PRIO_LOW, "NETWORK_MANAGER\r\n" );
+ int isMaster;
+ int bw;
+ success &= xmlNWM.GetChildValueInt( TAG_TIMING_MASTER, isMaster );
+ ConsolePrintf( PRIO_LOW, " Is Timing Master:%d\r\n", isMaster );
+ success &= xmlNWM.GetChildValueInt( TAG_ASYNC_BANDWIDTH, bw );
+ ConsolePrintf( PRIO_LOW, " Asynchronous Bandwidth:%d\r\n", bw );
+ if( success )
+ {
+ *isTimingMaster = isMaster;
+ *asyncBandwidth = bw;
+ break;
+ }
+ else
+ {
+ ConsolePrintf( PRIO_ERROR, "Failed to retrieve Network config\n" );
+ }
+ xmlNWM.FindNextNode();
+ }
+ }
+ return success;
+}
+
+
+bool CVodXml::GetChannelConfigurations( uint32_t deviceType, CSafeVector<CChannelConfiguration *> &allChannels )
+{
+ bool success = false;
+ bool found = false;
+ CXml Xml( *( ( CXml * )this ) );
+ success = Xml.SetToTopNode();
+ success &= Xml.FindNode( TAG_NETWORK_MANAGER );
+ success &= Xml.FindFirstChildNode();
+
+ while( !found && Xml.FindNode( TAG_DEVICE ) )
+ {
+ int xmlDeviceType = -1;
+ char *externalScript = NULL;
+ xmlChar szTmp[XML_DEFAULT_VALUE_LEN];
+ if( !Xml.GetChildValueInt( TAG_DEVICE_TYPE, xmlDeviceType ) )
+ {
+ xmlChar szTmp[XML_DEFAULT_VALUE_LEN];
+ if( Xml.GetChildValue( TAG_DEVICE_TYPE_HEX, szTmp, XML_DEFAULT_VALUE_LEN ) )
+ xmlDeviceType = ConvertToInt( szTmp );
+ }
+ if( ( uint32_t )xmlDeviceType != deviceType )
+ {
+ Xml.FindNextNode();
+ continue;
+ }
+ ConsolePrintf( PRIO_LOW, "DeviceType: %d (0x%X)\r\n", xmlDeviceType, xmlDeviceType );
+ szTmp[0] = '\0';
+ if( Xml.GetChildValue( TAG_SCRIPT, szTmp ) )
+ {
+ int scriptLen = xmlStrlen( szTmp );
+ externalScript = ( char * )malloc( scriptLen + 1 );
+ if( NULL != externalScript )
+ {
+ memcpy( externalScript, szTmp, scriptLen );
+ externalScript[scriptLen] = '\0';
+ }
+ ConsolePrintf( PRIO_LOW, "External script:'%s'\r\n", externalScript );
+ }
+ found = true;
+ CXml Channel( Xml );
+ success = Channel.FindFirstChildNode();
+
+ while( success && Channel.FindNode( TAG_CHANNEL ) )
+ {
+ int channelId;
+ success &= Channel.GetChildValueInt( TAG_CHANNEL_ID, channelId );
+ if( success )
+ {
+ ConsolePrintf( PRIO_LOW, " Channel: %u\r\n", channelId );
+ CChannelConfiguration *channelConfig = new CChannelConfiguration();
+ allChannels.PushBack( channelConfig );
+ channelConfig->deviceType = xmlDeviceType;
+ channelConfig->channelId = channelId;
+ channelConfig->externalScipt = externalScript;
+ CXml Socket( Channel );
+ success = Socket.FindFirstChildNode();
+ while( Socket.FindNode( TAG_SOCKET ) )
+ {
+ ConsolePrintf( PRIO_LOW, " Socket:\r\n" );
+ int nTmp;
+ CSocketConfiguration *sockConfig = NULL;
+ szTmp[0] = '\0';
+ if( Socket.GetChildValue( TAG_DIR, szTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - Direction : %s\r\n", szTmp );
+ if( XML_STRCMP(szTmp, VAL_DIR_IN) )
+ sockConfig = &channelConfig->inSocket;
+ else if( XML_STRCMP(szTmp, VAL_DIR_OUT) )
+ sockConfig = &channelConfig->outSocket;
+ }
+ if( NULL == sockConfig )
+ {
+ ConsolePrintf( PRIO_ERROR, RED"VodXml can not detect socket direction"RESETCOLOR"\n" );
+ return false; //unknown target socket
+ }
+
+ szTmp[0] = '\0';
+ if( Socket.GetChildValue( TAG_PORT_ID, szTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - Port ID : %s\r\n", szTmp );
+ if( XML_STRCMP(szTmp, VAL_PORT_MLB) )
+ sockConfig->port = PORT_MLB;
+ else if( XML_STRCMP(szTmp, VAL_PORT_TSI) )
+ sockConfig->port = PORT_TSI;
+ else if( XML_STRCMP(szTmp, VAL_PORT_I2S) )
+ sockConfig->port = PORT_I2S;
+ else if( XML_STRCMP(szTmp, VAL_PORT_USB) )
+ sockConfig->port = PORT_USB;
+ else if( XML_STRCMP(szTmp, VAL_PORT_PCIE) )
+ sockConfig->port = PORT_PCIE;
+ else if( XML_STRCMP(szTmp, VAL_PORT_MOST) )
+ sockConfig->port = PORT_MOST;
+ else
+ sockConfig->port = PORT_UNKNOWN;
+ }
+
+ szTmp[0] = '\0';
+ if( Socket.GetChildValue( TAG_DATA_TYPE, szTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - Data Type : %s\r\n", szTmp );
+ if( XML_STRCMP(szTmp, VAL_DATATYPE_SYNC) )
+ sockConfig->type = EP_Synchron;
+ else if( XML_STRCMP(szTmp, VAL_DATATYPE_ISOC) )
+ sockConfig->type = EP_Isochron;
+ else if( XML_STRCMP(szTmp, VAL_DATATYPE_ASYNC) )
+ sockConfig->type = EP_Asynchron;
+ else if( XML_STRCMP(szTmp, VAL_DATATYPE_CTRL) )
+ sockConfig->type = EP_Control;
+ else
+ sockConfig->type = EP_Unknown;
+ }
+
+ if( Socket.GetChildValueInt( TAG_OFFSET, nTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - Splitted Offset: %d\r\n", nTmp );
+ sockConfig->splittedOffset = nTmp;
+ }
+
+ if( Socket.GetChildValueInt( TAG_BLOCKWIDTH, nTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - Blockwidth: %d\r\n", nTmp );
+ sockConfig->blockWidth = nTmp;
+ }
+
+ if( Socket.GetChildValueInt( TAG_ADDRESS, nTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - Channel Address: 0x%X\r\n", nTmp );
+ sockConfig->address = nTmp;
+ }
+ else if( Socket.GetChildValue( TAG_ADDRESS_HEX, szTmp, XML_DEFAULT_VALUE_LEN ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - Channel Address (hex): 0x%X\r\n", nTmp );
+ sockConfig->address = ConvertToInt( szTmp );
+ }
+
+ if( Socket.GetChildValueInt( TAG_NUMBER_OF_BUFFERS, nTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - Number of Buffers: %d\r\n", nTmp );
+ sockConfig->amountOfBuffers = nTmp;
+ }
+
+ if( Socket.GetChildValueInt( TAG_BUFFER_SIZE, nTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - Buffer Size: %d\r\n", nTmp );
+ sockConfig->bufferSize = nTmp;
+ }
+
+ if( Socket.GetChildValueInt( TAG_PACKETS_XACT, nTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - Packets per Transaction: %d\r\n", nTmp );
+ sockConfig->packetsPerTransaction = nTmp;
+ }
+ else
+ {
+ if( Socket.GetChildValue( TAG_PACKETS_XACT_HEX, szTmp, XML_DEFAULT_VALUE_LEN ) )
+ {
+ sockConfig->packetsPerTransaction = ConvertToInt( szTmp );
+ ConsolePrintf( PRIO_LOW, " - Packets per Transaction: 0x%X\r\n", sockConfig->packetsPerTransaction );
+ }
+ }
+
+ if( Socket.GetChildValueInt( TAG_SUBBUFFER_SIZE, nTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - Subbuffer Size: %d\r\n", nTmp );
+ sockConfig->subbufferSize = nTmp;
+ }
+
+ if( Socket.GetChildValue( TAG_AIM_TYPE, szTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - TAG_AIM_TYPE : %s\r\n", szTmp );
+ if( XML_STRCMP(szTmp, VAL_AIM_TYPE_CDEV) )
+ sockConfig->aimType = AIM_CDEV;
+ else if( XML_STRCMP(szTmp, VAL_AIM_TYPE_AUDIO) )
+ sockConfig->aimType = AIM_AUDIO;
+ else if( XML_STRCMP(szTmp, VAL_AIM_TYPE_V4L) )
+ sockConfig->aimType = AIM_V4L;
+ else
+ sockConfig->aimType = AIM_UNKNOWN;
+ }
+
+ if( PORT_TSI == sockConfig->port )
+ {
+ if( Socket.GetChildValue( TAG_TSI_PORT_ID, szTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - TSI Port ID : %s\r\n", szTmp );
+ if( XML_STRCMP(szTmp, VAL_TSI_V1_PORT_0) )
+ sockConfig->tsiConfig.tsiPortInstance = V1TsiPortInstance0;
+ else if( XML_STRCMP(szTmp, VAL_TSI_V1_PORT_1) )
+ sockConfig->tsiConfig.tsiPortInstance = V1TsiPortInstance1;
+ }
+ if( Socket.GetChildValue( TAG_TSI_PORT_MODE, szTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - TSI Port Mode : %s\r\n", szTmp );
+ if( XML_STRCMP(szTmp, VAL_TSI_V1_SLAVE) )
+ sockConfig->tsiConfig.tsiPortMode = V1TsiPortModeSlave;
+ else if( XML_STRCMP(szTmp, VAL_TSI_V1_MASTER) )
+ sockConfig->tsiConfig.tsiPortMode = V1TsiPortModeMaster;
+ }
+ }
+ else if( PORT_I2S == sockConfig->port )
+ {
+ sockConfig->i2sConfig.portClkDriveModeV1 = V1I2sClockModeUnknown;
+ sockConfig->i2sConfig.portOptionV1 = V1I2sStreamingPortWildcard; //Be backward compatible
+ sockConfig->i2sConfig.streamingDataFormatV1 = V1I2sDataFormatUnknown;
+ sockConfig->i2sConfig.pinV1 = V1I2sInvalidPin;
+ sockConfig->i2sConfig.portOption = V3I2SOptionUnknown;
+ sockConfig->i2sConfig.clockMode = V3I2SClockModeUnknown;
+ sockConfig->i2sConfig.delayMode = V3I2SDelayUnknown;
+ sockConfig->i2sConfig.portSpeed = V3I2SSpeedUnknown;
+ sockConfig->i2sConfig.alignment = V3I2SAlignUnknown;
+ sockConfig->i2sConfig.pin = V3I2SInvalidPin;
+ szTmp[0] = '\0';
+ if( Socket.GetChildValue( TAG_I2S_V1_CLKDRIVEMODE, szTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - I2S V1 clock drive mode : %s\r\n", szTmp );
+ if( XML_STRCMP(szTmp, VAL_I2S_V1_CLK_OUTPUT) )
+ sockConfig->i2sConfig.portClkDriveModeV1 = V1I2sClockModeOutput;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_CLK_INPUT) )
+ sockConfig->i2sConfig.portClkDriveModeV1 = V1I2sClockModeInput;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_CLK_ISOCOUT) )
+ sockConfig->i2sConfig.portClkDriveModeV1 = V1I2sClockModeIsocOutput;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_CLK_ISOCIN) )
+ sockConfig->i2sConfig.portClkDriveModeV1 = V1I2sClockModeIsocInput;
+ }
+
+ if( Socket.GetChildValue( TAG_I2S_V1_OPTION, szTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - I2S V1 port option : %s\r\n", szTmp );
+ if( XML_STRCMP(szTmp, VAL_I2S_V1_OPTION_INOUT ) )
+ sockConfig->i2sConfig.portOptionV1 = V1I2sStreamingPortInOut;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_OPTION_DUALIN ) )
+ sockConfig->i2sConfig.portOptionV1 = V1I2sStreamingPortDualIn;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_OPTION_DUALOUT ) )
+ sockConfig->i2sConfig.portOptionV1 = V1I2sStreamingPortDualOut;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_OPTION_FULL ) )
+ sockConfig->i2sConfig.portOptionV1 = V1I2sStreamingPortFullStream;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_OPTION_WILDCARD ) )
+ sockConfig->i2sConfig.portOptionV1 = V1I2sStreamingPortWildcard;
+ }
+
+ szTmp[0] = '\0';
+ if( Socket.GetChildValue( TAG_I2S_V1_DATAFORMAT, szTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - I2S V1 data format : %s\r\n", szTmp );
+ if( XML_STRCMP(szTmp, VAL_I2S_V1_FMT_D64Fs16) )
+ sockConfig->i2sConfig.streamingDataFormatV1 = V1I2sDelay64Fs16Bit;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_FMT_D64Fs24) )
+ sockConfig->i2sConfig.streamingDataFormatV1 = V1I2sDelay64Fs24Bit;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_FMT_D64FsSeq) )
+ sockConfig->i2sConfig.streamingDataFormatV1 = V1I2sDelay64FsSeq;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_FMT_D128FsSeq) )
+ sockConfig->i2sConfig.streamingDataFormatV1 = V1I2sDelay128FsSeq;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_FMT_D256FsSeq) )
+ sockConfig->i2sConfig.streamingDataFormatV1 = V1I2sDelay256FsSeq;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_FMT_R64Fs16) )
+ sockConfig->i2sConfig.streamingDataFormatV1 = V1I2sRight64Fs16Bit;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_FMT_R64Fs24) )
+ sockConfig->i2sConfig.streamingDataFormatV1 = V1I2sRight64Fs24Bit;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_FMT_Seq64Fs) )
+ sockConfig->i2sConfig.streamingDataFormatV1 = V1I2sSeq64Fs;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_FMT_Seq128Fs) )
+ sockConfig->i2sConfig.streamingDataFormatV1 = V1I2sSeq128Fs;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_FMT_Seq256Fs) )
+ sockConfig->i2sConfig.streamingDataFormatV1 = V1I2sSeq256Fs;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_FMT_L64Fs16) )
+ sockConfig->i2sConfig.streamingDataFormatV1 = V1I2sLeft64Fs16Bit;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_FMT_L64Fs24) )
+ sockConfig->i2sConfig.streamingDataFormatV1 = V1I2sLeft64Fs24Bit;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_FMT_D512FsSeq) )
+ sockConfig->i2sConfig.streamingDataFormatV1 = V1I2sDelay512FsSeq;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_FMT_Seq512Fs) )
+ sockConfig->i2sConfig.streamingDataFormatV1 = V1I2sSeq512Fs;
+ }
+
+ szTmp[0] = '\0';
+ if( Socket.GetChildValue( TAG_I2S_V1_PIN, szTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - I2S V1 pin : %s\r\n", szTmp );
+ if( XML_STRCMP(szTmp, VAL_I2S_V1_PIN_SR0) )
+ sockConfig->i2sConfig.pinV1 = V1I2sSR0Pin;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_PIN_SX0) )
+ sockConfig->i2sConfig.pinV1 = V1I2sSX0Pin;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_PIN_SR1) )
+ sockConfig->i2sConfig.pinV1 = V1I2sSR1Pin;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_PIN_SX1) )
+ sockConfig->i2sConfig.pinV1 = V1I2sSX1Pin;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_PIN_SR2) )
+ sockConfig->i2sConfig.pinV1 = V1I2sSR2Pin;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_PIN_SX2) )
+ sockConfig->i2sConfig.pinV1 = V1I2sSX2Pin;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_PIN_SR3) )
+ sockConfig->i2sConfig.pinV1 = V1I2sSR3Pin;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_PIN_SX3) )
+ sockConfig->i2sConfig.pinV1 = V1I2sSX3Pin;
+ else if( XML_STRCMP(szTmp, VAL_I2S_V1_PIN_FSY_SCK) )
+ sockConfig->i2sConfig.pinV1 = V1I2sFSYSCKPins;
+ }
+
+
+ szTmp[0] = '\0';
+ if( Socket.GetChildValue( TAG_I2S_OPTION, szTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - I2S OPTION : %s\r\n", szTmp );
+ if( XML_STRCMP(szTmp, VAL_I2S_OPTION_INOUT) )
+ sockConfig->i2sConfig.portOption = V3I2SOptionInOut;
+ else if( XML_STRCMP(szTmp, VAL_I2S_OPTION_DUALIN) )
+ sockConfig->i2sConfig.portOption = V3I2SOptionDualIn;
+ else if( XML_STRCMP(szTmp, VAL_I2S_OPTION_DUALOUT) )
+ sockConfig->i2sConfig.portOption = V3I2SOptionDualOut;
+ }
+
+ szTmp[0] = '\0';
+ if( Socket.GetChildValue( TAG_I2S_CLOCK_DIR, szTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - I2S clock direction : %s\r\n", szTmp );
+ if( XML_STRCMP(szTmp, VAL_I2S_CLOCK_OUTPUT) )
+ sockConfig->i2sConfig.clockMode = V3I2SClockModeOutput;
+ else if( XML_STRCMP(szTmp, VAL_I2S_CLOCK_INPUT) )
+ sockConfig->i2sConfig.clockMode = V3I2SClockModeInput;
+ else if( XML_STRCMP(szTmp, VAL_I2S_OPTION_WILDCARD) )
+ sockConfig->i2sConfig.clockMode = V3I2SClockModeWildcard;
+ }
+
+ if( Socket.GetChildValueInt( TAG_I2S_CLOCK_DELAY, nTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - I2S clock delay: %d\r\n", nTmp );
+ if( 0 == nTmp )
+ sockConfig->i2sConfig.delayMode = V3I2SDelayOff;
+ else if( 1 == nTmp )
+ sockConfig->i2sConfig.delayMode = V3I2SDelayEnabled;
+ else if( 2 == nTmp )
+ sockConfig->i2sConfig.delayMode = V3I2SDelayWildcard;
+ }
+
+ if( Socket.GetChildValueInt( TAG_I2S_FS_SPEED, nTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - I2S FS speed: %d\r\n", nTmp );
+ switch( nTmp )
+ {
+ case 64:
+ sockConfig->i2sConfig.portSpeed = V3I2SSpeed64FS;
+ break;
+ case 128:
+ sockConfig->i2sConfig.portSpeed = V3I2SSpeed128FS;
+ break;
+ case 256:
+ sockConfig->i2sConfig.portSpeed = V3I2SSpeed256FS;
+ break;
+ case 512:
+ sockConfig->i2sConfig.portSpeed = V3I2SSpeed512FS;
+ break;
+ case 0:
+ sockConfig->i2sConfig.portSpeed = V3I2SSpeedWildcard;
+ break;
+ }
+ }
+
+ szTmp[0] = '\0';
+ if( Socket.GetChildValue( TAG_I2S_ALIGN, szTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - I2S alignment : %s\r\n", szTmp );
+ if( XML_STRCMP(szTmp, VAL_I2S_ALIGNMENT_L16) )
+ sockConfig->i2sConfig.alignment = V3I2SAlignLeft16;
+ else if( XML_STRCMP(szTmp, VAL_I2S_ALIGNMENT_L24) )
+ sockConfig->i2sConfig.alignment = V3I2SAlignLeft24;
+ else if( XML_STRCMP(szTmp, VAL_I2S_ALIGNMENT_R16) )
+ sockConfig->i2sConfig.alignment = V3I2SAlignRight16;
+ else if( XML_STRCMP(szTmp, VAL_I2S_ALIGNMENT_R24) )
+ sockConfig->i2sConfig.alignment = V3I2SAlignRight24;
+ else if( XML_STRCMP(szTmp, VAL_I2S_SEQUENTIAL) )
+ sockConfig->i2sConfig.alignment = V3I2SAlignSeq;
+ }
+
+ szTmp[0] = '\0';
+ if( Socket.GetChildValue( TAG_I2S_PIN, szTmp ) )
+ {
+ ConsolePrintf( PRIO_LOW, " - I2S Pin : %s\r\n", szTmp );
+ if( XML_STRCMP(szTmp, VAL_I2S_PIN_SRXA0) )
+ sockConfig->i2sConfig.pin = V3I2SSRXA0;
+ else if( XML_STRCMP(szTmp, VAL_I2S_PIN_SRXA1) )
+ sockConfig->i2sConfig.pin = V3I2SSRXA1;
+ else if( XML_STRCMP(szTmp, VAL_I2S_PIN_SRXB0) )
+ sockConfig->i2sConfig.pin = V3I2SSRXB0;
+ else if( XML_STRCMP(szTmp, VAL_I2S_PIN_SRXB1) )
+ sockConfig->i2sConfig.pin = V3I2SSRXB1;
+ }
+ }
+
+ Socket.FindNextNode();
+ }
+ }
+ Channel.FindNextNode();
+ }
+ Xml.FindNextNode();
+ }
+ return success && found;
+}
+
+bool CVodXml::GetRouteTerminals( CRouteTerminal *routeTerminal, CSafeVector<CRouteTerminal *> &allRouteTerminals )
+{
+ bool success = false;
+ bool found = false;
+ CXml Xml( *( ( CXml * )this ) );
+ success = Xml.SetToTopNode();
+ success &= Xml.FindNode( TAG_NETWORK_MANAGER );
+ success &= Xml.FindFirstChildNode();
+
+ while( success && Xml.FindNode( TAG_ROUTE ) )
+ {
+ CXml t1( Xml );
+ t1.FindFirstChildNode();
+
+ int deviceType = -1;
+ int instance = -1;
+ int channelId = -1;
+
+ while( t1.FindNode( TAG_TERMINAL ) &&
+ t1.GetChildValueInt( TAG_CHANNEL_ID, channelId ) &&
+ t1.GetChildValueInt( TAG_INSTANCE, instance ) )
+ {
+ if( !t1.GetChildValueInt( TAG_DEVICE_TYPE, deviceType ) )
+ {
+ xmlChar szTmp[XML_DEFAULT_VALUE_LEN];
+ if( t1.GetChildValue( TAG_DEVICE_TYPE_HEX, szTmp, XML_DEFAULT_VALUE_LEN ) )
+ deviceType = ConvertToInt( szTmp );
+ }
+ if( routeTerminal->deviceType != ( uint32_t )deviceType ||
+ routeTerminal->channelId != ( uint32_t )channelId ||
+ routeTerminal->instance != ( uint32_t )instance )
+ {
+ t1.FindNextNode();
+ continue;
+ }
+
+ CXml t2( Xml );
+ t2.FindFirstChildNode();
+
+ while( t2.FindNode( TAG_TERMINAL ) )
+ {
+ deviceType = -1;
+ if( !t2.GetChildValueInt( TAG_DEVICE_TYPE, deviceType ) )
+ {
+ xmlChar szTmp[XML_DEFAULT_VALUE_LEN];
+ if( t2.GetChildValue( TAG_DEVICE_TYPE_HEX, szTmp, XML_DEFAULT_VALUE_LEN ) )
+ deviceType = ConvertToInt( szTmp );
+ }
+ if( !t2.GetChildValueInt( TAG_CHANNEL_ID, channelId ) ||
+ !t2.GetChildValueInt( TAG_INSTANCE, instance ) ||
+ ( routeTerminal->deviceType == ( uint32_t )deviceType &&
+ routeTerminal->channelId == ( uint32_t )channelId &&
+ routeTerminal->instance == ( uint32_t )instance ) )
+ {
+ t2.FindNextNode();
+ continue;
+ }
+ bool alreadyStored = false;
+ for( uint32_t i = 0; found && i < allRouteTerminals.Size(); i++ )
+ {
+ if( allRouteTerminals[i]->deviceType == ( uint32_t )deviceType &&
+ allRouteTerminals[i]->channelId == ( uint32_t )channelId &&
+ allRouteTerminals[i]->instance == ( uint32_t )instance )
+ {
+ alreadyStored = true;
+ break;
+ }
+ }
+ if( !alreadyStored )
+ {
+ CRouteTerminal *terminal = new CRouteTerminal();
+ if( NULL != terminal )
+ {
+ terminal->deviceType = deviceType;
+ terminal->channelId = channelId;
+ terminal->instance = instance;
+ allRouteTerminals.PushBack( terminal );
+ found = true;
+ }
+ }
+ t2.FindNextNode();
+ }
+ t1.FindNextNode();
+ }
+ Xml.FindNextNode();
+ }
+ return success && found;
+}
diff --git a/Src/VodXml.h b/Src/VodXml.h
new file mode 100644
index 0000000..e02fe66
--- /dev/null
+++ b/Src/VodXml.h
@@ -0,0 +1,361 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CVodXml, CChannelConfiguration and the CSocketConfiguration classes.
+ */
+/*----------------------------------------------------------*/
+#ifndef _VODXML_H_
+#define _VODXML_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <Types.h>
+#include "Xml.h"
+
+typedef enum SocketPort_tag
+{
+ PORT_UNKNOWN,
+ PORT_I2C,
+ PORT_I2S,
+ PORT_PCIE,
+ PORT_MLB,
+ PORT_MOST,
+ PORT_TSI,
+ PORT_USB
+} SocketPort_t;
+
+/*----------------------------------------------------------*/
+/*!
+ * \brief Storage class to store I2S related informations
+ */
+
+/*----------------------------------------------------------*/
+class CI2SConfiguration
+{
+public:
+ ///I2S Clock drive mode
+ V1I2SPortClkDriveMode_t portClkDriveModeV1;
+
+ ///I2S Streaming port mode
+ V1I2SStreamingPortMode_t portOptionV1;
+
+ ///I2S Streaming data format
+ V1I2SStreamingDataFormat_t streamingDataFormatV1;
+
+ ///I2S Stream Pin ID
+ V1I2SPin_t pinV1;
+
+ ///I2S Port option
+ V3I2SPortOption_t portOption;
+
+ ///I2S Clock mode
+ V3I2SClockMode_t clockMode;
+
+ ///I2S Delay option
+ V3I2SDelayMode_t delayMode;
+
+ ///I2S Port speed in mulitple of MOST base clock (FS)
+ V3I2SPortSpeed_t portSpeed;
+
+ ///I2S Data Alignment
+ V3I2SAlignment_t alignment;
+
+ ///I2S Stream Pin ID
+ V3I2SPin_t pin;
+
+ CI2SConfiguration() : portClkDriveModeV1( V1I2sClockModeUnknown ),
+ streamingDataFormatV1( V1I2sDataFormatUnknown ), pinV1( V1I2sInvalidPin ),
+ portOption( V3I2SOptionUnknown ), clockMode( V3I2SClockModeUnknown ),
+ delayMode( V3I2SDelayUnknown ), portSpeed( V3I2SSpeedUnknown ),
+ alignment( V3I2SAlignUnknown ), pin( V3I2SInvalidPin )
+ {
+ }
+};
+
+/*----------------------------------------------------------*/
+/*!
+ * \brief Storage class to store TSI related informations (only available on OS81110)
+ */
+
+/*----------------------------------------------------------*/
+class CTsiConfigurationV1
+{
+public:
+ ///TSI port instance
+ V1TsiPortInstance_t tsiPortInstance;
+
+ ///I2S Streaming port mode
+ V1TsiPortMode tsiPortMode;
+
+ CTsiConfigurationV1() : tsiPortInstance(V1TsiPortInstanceNotSet), tsiPortMode(V1TsiPortModeNotSet)
+ {
+ }
+};
+
+/*----------------------------------------------------------*/
+/*!
+ * \brief Storage class to store all socket related informations. This class will be used inside
+ * the CChannelConfiguration class.
+ */
+
+/*----------------------------------------------------------*/
+class CSocketConfiguration
+{
+public:
+ ///Determines the type of used Application Interface Module (Linux Driver API)
+ AimType_t aimType;
+
+ /// Determines the used INIC port
+ SocketPort_t port;
+
+ /// Determines the used MOST data type
+ EPDataType_t type;
+
+ /// Determines the offset of current socket is splitted in case of usage of Splitter or Combiner
+ /// The value in case Splitter or Combiner are not used, this value is 0xFFFFFFFF.
+ uint32_t splittedOffset;
+
+ /// Determines the used amount of bytes used for this configuration
+ uint32_t blockWidth;
+
+ /// Determines the used address. This value is generic and has to be interpreted for the used INIC port.
+ uint32_t address;
+
+ /// (optional) Determines the amount of buffers used in the driver.
+ uint32_t amountOfBuffers;
+
+ /// (optional) Determines the size of a single buffer used in the driver.
+ uint32_t bufferSize;
+
+ /// (optional) Determines the amount of transmitted packets inside of one USB frame.
+ uint32_t packetsPerTransaction;
+
+ /// (optional) Determines the width of a subbuffer.
+ uint32_t subbufferSize;
+
+ /// (optional) In case of I2C port, this class holds the corresponding informations
+ CI2SConfiguration i2sConfig;
+
+ /// (optional) In case of TSI port, this class holds the corresponding informations
+ CTsiConfigurationV1 tsiConfig;
+
+ CSocketConfiguration() : aimType( AIM_UNKNOWN ), port( PORT_UNKNOWN ), type( EP_Unknown ),
+ splittedOffset( 0xFFFFFFFF ), blockWidth( 0xFFFFFFFF ), address( 0xFFFFFFFF ),
+ amountOfBuffers( 32 ), bufferSize( 8192 ), packetsPerTransaction( 2 ),
+ subbufferSize( 188 )
+ {
+ }
+};
+
+/*----------------------------------------------------------*/
+/*!
+ * \brief Storage class to store all channel related informations. This class will be returned by
+ * the CVodXml class.
+ */
+
+/*----------------------------------------------------------*/
+class CChannelConfiguration
+{
+public:
+ /// Determines the device type as specified in the configuration XML file and found in the group address configuration.
+ uint32_t deviceType;
+
+ /// Determines the used channel id, as specified in the configuration XML file.
+ uint32_t channelId;
+
+ /// Points to the input socket configuration, which will be represented by the CSocketConfiguration class.
+ CSocketConfiguration inSocket;
+
+ /// Points to the output socket configuration, which will be represented by the CSocketConfiguration class.
+ CSocketConfiguration outSocket;
+
+ /// Points to an external scripting file, to perform additional configuration actions. May be NULL.
+ char *externalScipt;
+
+ CChannelConfiguration() : deviceType( 0xFFFFFFFF ), channelId( 0xFFFFFFFF ), externalScipt( NULL )
+ {
+ }
+
+ ~CChannelConfiguration()
+ {
+ if( NULL != externalScipt )
+ {
+ free( externalScipt );
+ externalScipt = NULL;
+ }
+ }
+};
+
+
+/*----------------------------------------------------------*/
+/*!
+ * \brief Storage class for channel related informations. This class will be returned by
+ * the CVodXml class.
+ */
+
+/*----------------------------------------------------------*/
+class CRouteTerminal
+{
+public:
+ /// Determines the device type as specified in the configuration XML file and found in the group address configuration.
+ uint32_t deviceType;
+
+ /// instance number of the device found in the network
+ uint32_t instance;
+
+ /// Determines the used channel id, as specified in the configuration XML file.
+ uint32_t channelId;
+};
+
+
+
+
+/*----------------------------------------------------------*/
+/*!
+ * \brief Class to read XML for the Video On Demand use case.
+ */
+
+/*----------------------------------------------------------*/
+class CVodXml : public CXml
+{
+private:
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves the control channel addresses used by the sever
+ *
+ * \param rxEndpoint RX address will be written to this address (1 Byte)
+ * \param txEndpoint TX address will be written to this address (1 Byte)
+ * \return true, if successful
+ */
+ /*----------------------------------------------------------*/
+ bool GetLocalInicConfigurations( uint8_t *rxEndpoint, uint8_t *txEndpoint );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves the used physical interface used by the server for the MOST control channel.
+ *
+ * \return Enumeration holding the physical interface.
+ */
+ /*----------------------------------------------------------*/
+ SocketPort_t GetServerHardwareInterface();
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves the Port Message Protocol Version used by the server INIC.
+ *
+ * \return 1 for INIC API V1, 2 for INIC API V2.
+ */
+ /*----------------------------------------------------------*/
+ uint32_t GetServerDeviceApi();
+
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves the MOST parameters for the server attached INIC
+ *
+ * \param isTimingMaster true will be written to this address, when INIC shall act as timing master. false, otherwise.
+ * \param asyncBandwidth The amount of bytes usable for asynchronous data will be written to this address.
+ * \return true, if successful
+ */
+ /*----------------------------------------------------------*/
+ bool GetNetworkConfiguration( bool *isTimingMaster, uint32_t *asyncBandwidth );
+
+public:
+ /*----------------------------------------------------------*/
+ /*! \brief Constructor of CVodXml.
+ *
+ * \param szFile Path to configuration XML file.
+ */
+ /*----------------------------------------------------------*/
+ CVodXml( const char *szFile );
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves all instances of the control channel addresses used by the sever
+ *
+ * \param rxEndpoint RX address array will be written to this address (1 Byte)
+ * \param txEndpoint TX address array will be written to this address (1 Byte)
+ * \param serverNum The amount of found configurations will be written to this address.
+ * \note The user has to free the arrays rxEndpoint and txEndpoint after usage.
+ * \return true, if successful
+ */
+ /*----------------------------------------------------------*/
+ bool GetLocalInicConfigurations( uint8_t *rxEndpoint[], uint8_t *txEndpoint[], uint32_t *apiVersion[],
+ SocketPort_t *hwPort[], bool *isTimingMaster[], uint32_t *asyncBandwidth[], uint8_t *serverNum );
+
+
+ bool GetMostParameters(bool *isTimingMaster, uint32_t *asyncBandwidth);
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves the Port Message Protocol Version used by the given device type.
+ *
+ * \return 1 for INIC API V1, 2 for INIC API V2.
+ */
+ /*----------------------------------------------------------*/
+ uint32_t GetDeviceApi( uint32_t deviceType );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves the used MLB Port speed, if used.
+ *
+ * \return The configured MLB port speed.
+ */
+ /*----------------------------------------------------------*/
+ MlbPortSpeed_t GetDeviceMlbPortSpeed( uint32_t deviceType );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves the MOST channel configurations for the given device type.
+ *
+ * \param deviceType The device type to search for.
+ * \param allChannels A list with all channel configurations will be written into the given vector.
+ * \return true, if successful
+ */
+ /*----------------------------------------------------------*/
+ bool GetChannelConfigurations( uint32_t deviceType, CSafeVector<CChannelConfiguration *> &allChannels );
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief Retrieves the counter route terminals found in routes
+ *
+ * \param routeTerminal - Route terminal, a counter terminal is searched for
+ * \return true, if successful
+ */
+ /*----------------------------------------------------------*/
+ bool GetRouteTerminals( CRouteTerminal *routeTerminal, CSafeVector<CRouteTerminal *> &allRouteTerminals );
+
+
+
+};
+
+#endif //_VODXML_H_
diff --git a/Src/Xml.cpp b/Src/Xml.cpp
new file mode 100644
index 0000000..44a814e
--- /dev/null
+++ b/Src/Xml.cpp
@@ -0,0 +1,251 @@
+/*
+ * 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 "Types.h"
+#include "Xml.h"
+
+#define CHILD(x) ( (x) ? (x)->xmlChildrenNode : NULL )
+
+
+
+
+CXml::CXml( const char *szFile )
+{
+ m_Doc = xmlReadFile( szFile, NULL, 0 );
+
+ if( NULL == m_Doc )
+ LOG("unable to open XML file\n");
+ else
+ m_bDocOpened = true;
+}
+
+
+
+CXml::CXml( const char *szBuffer, uint32_t nBufferLen )
+{
+ if( NULL == szBuffer || strlen( szBuffer ) >= nBufferLen )
+ {
+ LOG("Parameter error in constructor of memory driven CXml\n");
+ }
+ m_Doc = xmlReadMemory( szBuffer, strlen( szBuffer ), "config.xml", NULL, 0 );
+
+ if( NULL == m_Doc )
+ LOG("unable to open XML buffer\n");
+ else
+ m_bDocOpened = true;
+}
+
+
+
+
+CXml::CXml( CXml &Node ) : m_Doc( Node.m_Doc ), m_Node( Node.m_Node ), m_bDocOpened( false )
+{
+}
+
+
+
+
+
+CXml::~CXml()
+{
+ if( m_bDocOpened )
+ xmlFreeDoc( m_Doc );
+}
+
+
+
+
+
+bool CXml::SetToTopNode()
+{
+ m_Node = xmlDocGetRootElement( m_Doc );
+ m_Node = CHILD(m_Node);
+
+ return ( NULL != m_Node );
+}
+
+
+
+
+
+bool CXml::FindFirstChildNode()
+{
+ m_Node = CHILD(m_Node);
+ return ( NULL != m_Node );
+}
+
+
+
+
+
+bool CXml::FindNextNode()
+{
+ if( NULL == m_Node )
+ return false;
+
+ m_Node = m_Node->next;
+
+ return NULL != m_Node;
+}
+
+
+
+
+
+bool CXml::FindNode( const xmlChar *szTag )
+{
+ if( NULL == m_Node || NULL == szTag )
+ {
+ m_Node = NULL;
+ return false;
+ }
+
+ while( m_Node && xmlStrcmp( m_Node->name, szTag ) ) // search in all nodes
+ m_Node = m_Node->next;
+
+ return ( NULL != m_Node );
+}
+
+
+
+
+
+bool CXml::GetChildValue( const xmlChar *szTag, xmlChar *szValue, int nMaxLen )
+{
+ xmlNode *nodeMem = m_Node;
+ FindFirstChildNode();
+ FindNode( szTag );
+
+ if( NULL == m_Node )
+ {
+ m_Node = nodeMem;
+ return false;
+ }
+
+ xmlChar *szTmp = xmlNodeListGetString( m_Doc, m_Node->xmlChildrenNode, 1 );
+ m_Node = nodeMem;
+
+ if( NULL == szTmp )
+ return false;
+
+ if( xmlStrlen( szTmp ) >= nMaxLen )
+ {
+ xmlFree( szTmp );
+ return false;
+ }
+
+ memcpy( szValue, szTmp, sizeof( xmlChar ) * ( xmlStrlen( szTmp ) + 1 ) );
+ xmlFree( szTmp );
+
+ return true;
+}
+
+
+
+
+
+bool CXml::GetChildValueInt( const xmlChar *szTag, int &nValue )
+{
+ xmlNode *nodeMem = m_Node;
+ FindFirstChildNode();
+ FindNode( szTag );
+ xmlNode *node = m_Node;
+ m_Node = nodeMem;
+
+ if( NULL == node )
+ {
+ return false;
+ }
+
+ xmlChar *szVal = xmlNodeListGetString( m_Doc, node->xmlChildrenNode, 1 );
+
+ if( NULL == szVal )
+ return false;
+
+ nValue = (szVal[0] == '0' && (szVal[1] =='x' || szVal[1] =='X')) ?
+ strtol( ( char * )szVal + 2, NULL, 16 ) :
+ atoi( ( char * )szVal );
+
+ xmlFree( szVal );
+
+ return true;
+}
+
+
+
+
+
+bool CXml::FindNodeWithValue( const xmlChar *szNodeTag, const xmlChar *szValueTag, const xmlChar *szValue )
+{
+ while( FindNode( szNodeTag ) )
+ { // search node fitting to NodeTag
+ xmlChar *szCmp = NULL;
+
+ if( GetChildValue( szValueTag, szCmp ) )
+ { // get nodes value fitting to ValueTag
+ int nCmp = xmlStrcmp( szValue, szCmp ); // value fitting to compare value
+ xmlFree( szCmp );
+
+ if( 0 == nCmp ) // search completed?
+ break;
+ }
+
+ m_Node = m_Node->next; // continue with next node
+ }
+
+ return ( NULL != m_Node );
+}
+
+
+
+
+
+bool CXml::FindNodeWithValueInt( const xmlChar *szNodeTag, const xmlChar *szValueTag, int nValue )
+{
+ int nCmp;
+
+ while( FindNode( szNodeTag ) &&
+ GetChildValueInt( szValueTag, nCmp ) &&
+ nValue != nCmp )
+ {
+ FindNextNode();
+ }
+
+ return NULL !=
+ m_Node; // return found node or NULL;
+}
+
+
+int CXml::ConvertToInt( xmlChar *xString )
+{
+ char *cString = ( char * )xString; //Convertion may be needed..
+ for( uint32_t i = 0; i < strlen( cString ); i++ )
+ {
+ if( cString[i] >= 65 && cString[i] <= 90 )
+ {
+ //convert upper case to lower case
+ cString[i] += 32;
+ }
+ }
+ return strtol( cString, NULL, 16 );
+}
diff --git a/Src/Xml.h b/Src/Xml.h
new file mode 100644
index 0000000..477a086
--- /dev/null
+++ b/Src/Xml.h
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CXml class.
+ */
+/*----------------------------------------------------------*/
+#ifndef _XML_H_
+#define _XML_H_
+
+#include "Types.h"
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+
+
+#define XML_DEFAULT_VALUE_LEN 255
+
+/*----------------------------------------------------------*/
+/*! \brief Generic class to read XML files. It does not implement a concrete use case.
+ */
+/*----------------------------------------------------------*/
+class CXml
+{
+ xmlDoc *m_Doc;
+ xmlNode *m_Node;
+ bool m_bDocOpened;
+protected:
+ static int ConvertToInt( xmlChar *xString );
+
+public:
+ /*----------------------------------------------------------*/
+ /*! \brief construct a XML document from a file name
+ */
+ /*----------------------------------------------------------*/
+ CXml( const char *szFile );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief construct a XML document from a zero terminated string in the memory.
+ */
+ /*----------------------------------------------------------*/
+ CXml( const char *szBuffer, uint32_t nBufferLen );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief construct a XML document from a given node
+ */
+ /*----------------------------------------------------------*/
+ CXml( CXml &Node );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief construct a XML document from a file name
+ */
+ /*----------------------------------------------------------*/
+ ~CXml();
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief gets top node inside root of XML document
+ *
+ * \return true, if successful
+ */
+ /*----------------------------------------------------------*/
+ bool SetToTopNode();
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief find first child node
+ *
+ * \return true, if child node was found
+ */
+ /*----------------------------------------------------------*/
+ bool FindFirstChildNode();
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief find next node on same level
+ *
+ * \return true, if node was found
+ */
+ /*----------------------------------------------------------*/
+ bool FindNextNode();
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief find a XML node with a given tag
+ *
+ * \param szTag - tag looking for
+ *
+ * \return XML node
+ */
+ /*----------------------------------------------------------*/
+ bool FindNode( const xmlChar *szTag );
+
+
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief searches a node, which has a child node with a
+ * given value
+ *
+ * \param szNodeTag - tag of nodes which are included in search
+ * \param szValueTag - tag of value inside node
+ * \param szValue - value looked for
+ *
+ * \return XML true if found
+ */
+ /*----------------------------------------------------------*/
+ bool FindNodeWithValue( const xmlChar *szNodeTag, const xmlChar *szValueTag, const xmlChar *szValue );
+
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief searches node, which has a child node with a
+ * given integer value
+ *
+ * \param szNodeTag - tag of nodes which are included in search
+ * \param szValueTag - tag of value inside node
+ * \param szValue - value looked for
+ *
+ * \return true if found
+ */
+ /*----------------------------------------------------------*/
+ bool FindNodeWithValueInt( const xmlChar *szNodeTag, const xmlChar *szValueTag, int nValue );
+
+ /*----------------------------------------------------------*/
+ /*! \brief get node's child value as string
+ *
+ * \param szTag - tag of the value inside the node
+ *
+ * \return value as string if found, otherwise NULL
+ */
+ /*----------------------------------------------------------*/
+ bool GetChildValue( const xmlChar *szTag, xmlChar *szValue, int nMaxLen = XML_DEFAULT_VALUE_LEN );
+
+
+ /*----------------------------------------------------------*/
+ /*! \brief get node's child value as int
+ *
+ * \param szTag - tag of the value inside the node
+ * \param nErr - value returned in case of an error
+ *
+ * \return value as int
+ */
+ /*----------------------------------------------------------*/
+ bool GetChildValueInt( const xmlChar *szTag, int &nValue );
+};
+
+#endif