diff options
Diffstat (limited to 'Src/Network/NetworkDevice.cpp')
-rw-r--r-- | Src/Network/NetworkDevice.cpp | 903 |
1 files changed, 903 insertions, 0 deletions
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; +} + |