/* * 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 . * * You may also obtain this software under a propriety license from Microchip. * Please contact Microchip for further information. * */ #include #include #include #include #include #include #include #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 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; }