connectivitylayer/isce/isirouter_dll/src/isicltransceiver.cpp
changeset 9 8486d82aef45
parent 7 fa67e03b87df
--- a/connectivitylayer/isce/isirouter_dll/src/isicltransceiver.cpp	Wed Apr 21 14:29:55 2010 +0300
+++ b/connectivitylayer/isce/isirouter_dll/src/isicltransceiver.cpp	Tue Oct 19 13:16:20 2010 +0300
@@ -17,151 +17,449 @@
 
 
 
-#include <kernel.h>               // For Kern
-#include "isirouter.h"            // For DISIRouter
-#include "isiroutertrace.h"       // For C_TRACE, ASSERT_RESET.. and fault codes
-#include "misirouterlinkif.h"     // For MISIRouterLinkIf
-#include "isihelpers.h"           // For GET_SENDER_DEV...
-#include "memapi.h"               // For MemApi
-#include <trxdefs.h>              // For ETrxTest...
-#include "isicltransceiver.h"     // For DISICLTransceiver
-#include <nsisi.h>                // For PN_NAMESERVICE... TODO:Remove this
+#include <kernel.h>                 // For Kern
+#include <pn_const.h>               // For PN_OBJ_ROUTING_REQ
+#include <phonetisi.h>              // For ISI_HEADER_OFFSET_...
+#include <commisi.h>                // For COMMON_ISA_...
 
-#define PN_MEDIA_TEST 0xBB //not real
-//#define PN_DEV_MODEM 0x12
-#define PN_DEV_DUMMYIST 0x13
-#define PN_DEV_OWN 0x6C
-
-// CONSTS
-DISICLTransceiver* DISICLTransceiver::iThisPtr = NULL;
-
+#include "isirouter.h"              // For DISIRouter
+#include "isiroutertrace.h"         // For C_TRACE, ASSERT_RESET.. and fault codes
+#include "misirouterlinkif.h"       // For MISIRouterLinkIf
+#include "isihelpers.h"             // For GET_SENDER_DEV...
+#include "memapi.h"                 // For MemApi
+#include <trxdefs.h>                // For ETrxTest...
+#include "isicltransceiver.h"       // For DISICLTransceiver
+#include <nsisi.h>                  // For PN_NAMESERVICE...
+#include "isirouterservice.h"       // For DIsiRouterService
+#include "isimsgqueue.h"            // For DISIMsgQueue
+#include "iscnokiadefinitions.h"    // For EIscNokiaUsbPhonetLink
+#ifdef USE_MEDIAAPI  
+#include <pn_isimedia_const.h>      // For PN_DEV_PC 
+#endif /* USE_MEDIAAPI */
 
 // Faults
 enum TISICLTransceiverFaults
     {
     EISICLTransceiverMemAllocFailure = 0x01,
     EISICLTransceiverMemAllocFailure1,
+    EISICLTransceiverMemAllocFailure2,
+    EISICLTransceiverMemAllocFailure3,
+    EISICLTransceiverMemAllocFailure4,
+    EISICLTransceiverMemAllocFailure5,
+    EISICLTransceiverMemAllocFailure6,
+    EISICLTransceiverMemAllocFailure7,
+    EISICLTransceiverMemAllocFailure8,
+#ifdef USE_MEDIAAPI 	
+    EISICLTransceiverMemAllocFailure9,
+    EISICLTransceiverMemAllocFailure10,  
+#endif /* USE_MEDIAAPI */  
     EISICLTransceiverNotSupportedMedia,
     EISICLTransceiverOverTheLimits,
     EISICLTransceiverNULLPtr,
+    EISICLTransceiverNULLPtr2,
+    EISICLTransceiverNULLPtr3,
+    EISICLTransceiverNULLPtr4,
+    EISICLTransceiverNULLPtr5,
+    EISICLTransceiverNULLPtr6,
+    EISICLTransceiverNULLPtr7,
     EISICLTransceiverNotSupportedDevice,
+    EISICLTransceiverDeviceConnection,
+    EISICLTransceiverCommIsaEntityNotReachableResp,
+    EISICLTransceiverNotThreadContext,
+    EISICLTransceiverMutexCreateFailed,
+    EISICLTransceiverMutexWaitFailed,
+    EISICLTransceiverMutexWaitFailed2,
     };
 
-DISICLTransceiver::DISICLTransceiver( DISIRouter* aPtr )
-    : iRouter( aPtr )
+// Constants
+const TInt KDfcPriority( 5 );
+
+DMutex* DISICLTransceiver::iDynamicDeviceTableMutex = NULL;
+_LIT8( KISICLTransceiverMutex, "ISICLTransceiverMutex" );
+
+DISICLTransceiver::DISICLTransceiver(
+        DISIRouter& aRouter,
+        TDfcQue* aThreadPtr
+        )
+    : iShRouter( aRouter )
     {
     C_TRACE( ( _T( "DISICLTransceiver::DISICLTransceiver>" ) ) );
-    iLinksArray = new MISIRouterLinkIf*[ EISIAmountOfMedias ];
-    ASSERT_RESET_ALWAYS( iLinksArray, ( EISICLTransceiverMemAllocFailure | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
-    // Initialize links
-    for( TInt i( 0 ); i < EISIAmountOfMedias; i++ )
-        {
-        iLinksArray[ i ] = NULL;
-        }
-    //TODO add real media and trx when known
-    iLinksArray[ EISIMediaTest ] = MISIRouterLinkIf::CreateLinkF( this, PN_MEDIA_TEST, ETrxTest );
+    ASSERT_RESET_ALWAYS( aThreadPtr, ( EISICLTransceiverNULLPtr7 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+    iShStateChangedDfc = new TDfc( StateChangedDfc, this, aThreadPtr, KDfcPriority );
+    ASSERT_RESET_ALWAYS( iShStateChangedDfc, ( EISICLTransceiverMemAllocFailure6 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+    
+    iRxQueueDfc = new TDfc( RxQueueDfc, this, aThreadPtr, KDfcPriority );
+    ASSERT_RESET_ALWAYS( iShStateChangedDfc, ( EISICLTransceiverMemAllocFailure8 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+            
+    DISIDevice* dev = new DISIDevice( PN_DEV_MODEM,
+                                      MISIRouterLinkIf::CreateLinkF( this, PN_MEDIA_MODEM_HOST_IF, ETrxSharedMemory)
+                                      );
+    ASSERT_RESET_ALWAYS( dev, ( EISICLTransceiverMemAllocFailure3 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+    iShDevices.Append( dev );
+#ifdef USE_MEDIAAPI 
+    DISIDevice* dev2 = new DISIDevice( PN_DEV_PC,  // append to dynamic table if needed
+                                       MISIRouterLinkIf::CreateLinkF( this, PN_MEDIA_USB, ETrxUSB )
+                                      );
+    ASSERT_RESET_ALWAYS( dev2, ( EISICLTransceiverMemAllocFailure9 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+    iShDevices.Append( dev2 );
+    
+    DISIDevice* dev4 = new DISIDevice( PN_DEV_PC,  // append to dynamic table if needed
+                                       MISIRouterLinkIf::CreateLinkF( this, PN_MEDIA_BT, ETrxBT )
+                                      );
+    ASSERT_RESET_ALWAYS( dev4, ( EISICLTransceiverMemAllocFailure10 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+    iShDevices.Append( dev4 );
+ #endif /* USE_MEDIAAPI */
+	  DISIDevice* dev3 = new DISIDevice( PN_DEV_DUMMYIST,
+                                       MISIRouterLinkIf::CreateLinkF( this, PN_MEDIA_TEST, ETrxTest )
+                                      );                                      
+    ASSERT_RESET_ALWAYS( dev3, ( EISICLTransceiverMemAllocFailure5 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+    iShDevices.Append( dev3 );
+
+    iRouterService = new DIsiRouterService( *this );
+    ASSERT_RESET_ALWAYS( iRouterService, ( EISICLTransceiverMemAllocFailure2 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+    
+    iRxQueue = new DISIMsgQueue( KISIMainRxQueueSize );
+    ASSERT_RESET_ALWAYS( iRxQueue, ( EISICLTransceiverMemAllocFailure7 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+    
+    TInt err( Kern::MutexCreate( iDynamicDeviceTableMutex, KISICLTransceiverMutex, KMutexOrdGeneral0 ) );
+    ASSERT_RESET_ALWAYS( ( KErrNone == err ), ( EISICLTransceiverMutexCreateFailed | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+#ifdef USE_MEDIAAPI 
+    iDevPcLastSendTrxId = EAmountOfTrxs;  //put a maxvalue	
+    iDevPcLastActiveTrxId = EAmountOfTrxs;  //put a maxvalue
+#endif /* USE_MEDIAAPI */
     C_TRACE( ( _T( "DISICLTransceiver::DISICLTransceiver<" ) ) );
     }
 
 DISICLTransceiver::~DISICLTransceiver()
     {
     C_TRACE( ( _T( "DISICLTransceiver::~DISICLTransceiver>" ) ) );
-    for( TUint8 i( 0 ); i < EISIAmountOfMedias; i++ )
+    
+    iShDevices.ResetAndDestroy();
+    
+    if ( iRouterService )
+        {            
+        delete iRouterService;
+        iRouterService = NULL;
+        }
+        
+    if ( iShStateChangedDfc )
+        { 
+        iShStateChangedDfc->Cancel();
+        delete iShStateChangedDfc;
+        iShStateChangedDfc = NULL;
+        }
+    
+    if( iRxQueue )
         {
-        MISIRouterLinkIf* tmp = iLinksArray[ i ];
-        if( tmp )
+        C_TRACE( ( _T( "DISICLTransceiver::ResetQueues 0x%x iRxQueue 0x%x" ), this, iRxQueue ) );
+        while( iRxQueue->Count() )
             {
-            tmp->Release();
-            tmp = NULL;
-            iLinksArray[ i ] = NULL;
+            MemApi::DeallocBlock( iRxQueue->Get() );
             }
         }
-    delete []iLinksArray;
+        
+    if( iRxQueueDfc )
+        {
+        C_TRACE( ( _T( "DISIUserChannel::~DISIUserChannel 0x%x iRxQueueDfc 0x%x" ), this, iRxQueueDfc ) );
+        iRxQueueDfc->Cancel();
+        delete iRxQueueDfc;
+        iRxQueueDfc = NULL;
+        }
+
     C_TRACE( ( _T( "DISICLTransceiver::~DISICLTransceiver<" ) ) );
+
+    }
+
+TInt DISICLTransceiver::SendCommIsaEntityNotReachableResp(
+        TDes8& aNotDeliveredMessage
+        )
+    {
+    C_TRACE( ( _T( "DISICLTransceiver::SendCommIsaEntityNotReachableResp 0x%x>" ), &aNotDeliveredMessage ) );
+    const TUint8* notDeliveredMsgPtr( aNotDeliveredMessage.Ptr() );
+    TInt error = KErrAlreadyExists;
+    // Avoid COMM_ISA_ENTITY_NOT_REACHABLE_RESP loop.
+    if( ( notDeliveredMsgPtr[ ISI_HEADER_OFFSET_MESSAGEID ] == COMMON_MESSAGE ) &&
+        ( ( notDeliveredMsgPtr[ ISI_HEADER_OFFSET_SUBMESSAGEID ] == COMM_ISA_ENTITY_NOT_REACHABLE_RESP ) || 
+          ( notDeliveredMsgPtr[ ISI_HEADER_OFFSET_SUBMESSAGEID ] == COMM_SERVICE_NOT_IDENTIFIED_RESP ) ) )
+        {
+        C_TRACE( ( _T( "DISICLTransceiver Not sending another CommIsaEntityNotReachableResp 0x%x 0x%x" ), &aNotDeliveredMessage, notDeliveredMsgPtr[ ISI_HEADER_OFFSET_SUBMESSAGEID ] ) );
+        }
+    else
+        {
+        // Follows COMM specification: 000.031
+        TUint8 length( ISI_HEADER_SIZE + SIZE_COMMON_MESSAGE_COMM_ISA_ENTITY_NOT_REACHABLE_RESP );
+        TDes8& respMsg = MemApi::AllocBlock( length );
+        ASSERT_RESET_ALWAYS( length > ISI_HEADER_OFFSET_MESSAGEID, ( EISICLTransceiverOverTheLimits | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+        TUint8* respMsgPtr = const_cast<TUint8*>( respMsg.Ptr() );
+        // We start to append from transaction id.
+        respMsg.SetLength( ISI_HEADER_OFFSET_TRANSID );
+        // Get the header until messageid from prev. message.
+        // Just turn receiver and sender device and object vice versa.
+        respMsgPtr[ ISI_HEADER_OFFSET_MEDIA ] = notDeliveredMsgPtr[ ISI_HEADER_OFFSET_MEDIA ];
+        SET_RECEIVER_DEV( respMsgPtr, GET_SENDER_DEV( aNotDeliveredMessage ) );
+        SET_SENDER_DEV  ( respMsgPtr, GET_RECEIVER_DEV( aNotDeliveredMessage ) );
+        respMsgPtr[ ISI_HEADER_OFFSET_RESOURCEID ] = notDeliveredMsgPtr[ ISI_HEADER_OFFSET_RESOURCEID ];
+        SET_LENGTH( respMsgPtr, ( length - PN_HEADER_SIZE ) );
+        SET_RECEIVER_OBJ( respMsgPtr, GET_SENDER_OBJ( aNotDeliveredMessage ) );
+        SET_SENDER_OBJ( respMsgPtr, GET_RECEIVER_OBJ( aNotDeliveredMessage ) );
+        // Set from undelivered message
+        respMsg.Append( notDeliveredMsgPtr[ ISI_HEADER_OFFSET_TRANSID ] );
+        // Message Identifier
+        respMsg.Append( COMMON_MESSAGE );
+        // Sub message Identifier.
+        respMsg.Append( COMM_ISA_ENTITY_NOT_REACHABLE_RESP );
+        // Not Delivered Message from original message.
+        respMsg.Append( notDeliveredMsgPtr[ ISI_HEADER_OFFSET_MESSAGEID ] );
+        // Status
+        respMsg.Append( COMM_ISA_ENTITY_NOT_AVAILABLE );//  different status in a case of device not existing
+        // Filler
+        const TUint8 KFiller( 0x00 );
+        respMsg.Append( KFiller );
+        // Filler
+        respMsg.Append( KFiller );
+        // Filler
+        respMsg.Append( KFiller );
+        error = RouteISIMessage( respMsg, EFalse );
+        // Programming error in this function if below assert is raised
+        ASSERT_RESET_ALWAYS( KErrNone == error, ( EISICLTransceiverCommIsaEntityNotReachableResp | EDISICLTransceiverTraceId << KClassIdentifierShift ) );        
+        }
+    MemApi::DeallocBlock( aNotDeliveredMessage );
+    C_TRACE( ( _T( "DISICLTransceiver::SendCommIsaEntityNotReachableResp 0x%x<" ), &aNotDeliveredMessage ) );
+    return error;
+
     }
 
-TInt DISICLTransceiver::SendCommIsaEntityNotReachableResp( TDes8& aMessage )
+// This is called in 1...N thread contextes
+void DISICLTransceiver::ReceiveISIMessage(
+        const TDesC8& aMessage,
+        const TUint8 aTrxId
+        )
     {
-    C_TRACE( ( _T( "DISICLTransceiver::SendCommIsaEntityNotReachableResp 0x%x>" ), &aMessage ) );
-    const TUint8* msgTmpPtr( aMessage.Ptr() );
-    TInt error = KErrAlreadyExists;
+    C_TRACE( ( _T( "DISICLTransceiver::ReceiveMsg 0x%x 0x%x 0x%x>" ), this, &aMessage, aTrxId ) );
+    // Can only be called from thread context.
+    ASSERT_THREAD_CONTEXT_ALWAYS( ( EISICLTransceiverNotThreadContext | EDISIUserChannelTraceId << KClassIdentifierShift ) );
+    
+    TUint8 txDevId = GET_SENDER_DEV( aMessage.Ptr() );    
+    if ( DynamicDevice( txDevId ) )
+        {
+        TUint8 staticDevId(0);
+        const TInt count( iShDevices.Count() );        
+        TInt index(0);
+        TBool staticDeviceFound(EFalse);
+        MISIRouterLinkIf* Link = NULL;
+        while( !staticDeviceFound && ( index < count ) )
+            {
+            C_TRACE( ( _T( "DISICLTransceiver::ReceiveMsg find static device for trx 0x%x index %d" ), aTrxId, index ) );
+            DISIDevice* tmpDevice = iShDevices[ index ];
+            ASSERT_RESET_ALWAYS( tmpDevice, ( EISICLTransceiverNULLPtr4 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+            tmpDevice->LockDeviceFM();
+            Link = tmpDevice->GetLink();
+            if( Link->GetTrxId() == aTrxId )
+                {                
+                staticDevId = tmpDevice->GetDeviceIdentifier();
+                tmpDevice->FreeDeviceFM();
+                C_TRACE( ( _T( "DISICLTransceiver::ReceiveMsg static device 0x%x trx 0x%x" ), this, &aMessage, aTrxId ) );
+                staticDeviceFound = ETrue;
+                }
+            else
+                {
+                tmpDevice->FreeDeviceFM();
+                }
+            index++;
+            } 
+#ifdef USE_MEDIAAPI 		 
+        if ( PN_DEV_PC == GET_SENDER_DEV( aMessage.Ptr() ))
+            {
+            C_TRACE( ( _T( "DISICLTransceiver::ReceiveMsg 0x%x 0x%x trx id = %d<" ), this, &aMessage, (Link->GetTrxId())  ) ); 
+            iDevPcLastActiveTrxId = iDevPcLastSendTrxId;                  	
+            iDevPcLastSendTrxId =	Link->GetTrxId();                       	    
+            }		     
+#endif /* USE_MEDIAAPI */  			
+        UpdateDynamicDeviceTable( txDevId, staticDevId );
+        }
+    // else static device. No need to save trxId
 
-    // To avoid COMM_ISA_ENTITY_NOT_REACHABLE_RESP loop
-    if( msgTmpPtr[ ISI_HEADER_OFFSET_MESSAGEID ] != COMMON_MESSAGE &&
-        msgTmpPtr[ ISI_HEADER_OFFSET_SUBMESSAGEID ] != COMM_ISA_ENTITY_NOT_REACHABLE_RESP )
+    iRxQueue->Add( aMessage );
+    iRxQueueDfc->Enque();
+    C_TRACE( ( _T( "DISICLTransceiver::ReceiveMsg 0x%x 0x%x 0x%x<" ), this, &aMessage, aTrxId ) );
+    }
+
+void DISICLTransceiver::RxQueueDfc(
+        TAny* aPtr  // Pointer to this object.
+        )
+    {
+    C_TRACE( ( _T( "DISICLTransceiver::RxQueueDfc ->" ) ) );
+    
+    DISICLTransceiver& tmp = *reinterpret_cast<DISICLTransceiver*>( aPtr );
+    if( tmp.iRxQueue->Count() > 0 )
+        {
+        TDes8& msg( tmp.iRxQueue->Get() );
+        
+        tmp.RouteISIMessage( msg, EFalse );
+        // Check here too to avoid unnecessary dfc queuing.
+        if( tmp.iRxQueue->Count() > 0 )
+            {
+            C_TRACE( ( _T( "DISICLTransceiver::RxQueueDfc enque RxQueueDfc" ) ) );
+            tmp.iRxQueueDfc->Enque();
+            }
+        }
+    C_TRACE( ( _T( "DISICLTransceiver::RxQueueDfc <-" ) ) );
+    }
+    
+
+TInt DISICLTransceiver::RouteISIMessage(
+        TDes8& aMessage,
+        TBool aDynamicSenderCheckNeeded
+        )
+    {
+    C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage 0x%x 0x%x> len %d" ), &aMessage, aDynamicSenderCheckNeeded, aMessage.Length() ) );
+    const TUint8* msgPtr = aMessage.Ptr();
+    ISIMESSAGE_TRACE( aMessage );
+    TInt error( ValidateISIMessage( aMessage ) );
+    if( KErrNone != error )
+        {
+        TRACE_ASSERT_ALWAYS;
+        C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage invalid message 0x%x" ), &aMessage ) );
+        MemApi::DeallocBlock( aMessage );
+        }
+    else
         {
-        // Make channel opening request followinfg COMM specification: 000.026
-        // Length is sixteen bytes.
-		    TUint8 length( 16 );
-		    TDes8& tempPtr = MemApi::AllocBlock( ISI_HEADER_SIZE + SIZE_COMMON_MESSAGE_COMM_ISA_ENTITY_NOT_REACHABLE_RESP );
-		    ASSERT_RESET_ALWAYS( &tempPtr, ( EISICLTransceiverMemAllocFailure1 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
-  	    ASSERT_RESET_ALWAYS( ISI_HEADER_SIZE + SIZE_COMMON_MESSAGE_COMM_ISA_ENTITY_NOT_REACHABLE_RESP > ISI_HEADER_OFFSET_MESSAGEID, ( EISICLTransceiverOverTheLimits | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
-  	    TUint8* ptr = const_cast<TUint8*>( tempPtr.Ptr() );
-  	    // We start to append from transaction id.
-  	    tempPtr.SetLength( ISI_HEADER_OFFSET_TRANSID );
-  	    // Get the header until messageid from prev. message.
-		    // Just turn receiver and sender device and object vice versa.
-		    ptr[ ISI_HEADER_OFFSET_MEDIA ] = msgTmpPtr[ ISI_HEADER_OFFSET_MEDIA ];
-		    SET_RECEIVER_DEV( ptr, GET_SENDER_DEV( aMessage ) );
-		    SET_SENDER_DEV  ( ptr, GET_RECEIVER_DEV( aMessage ) );
-		    ptr[ ISI_HEADER_OFFSET_RESOURCEID ] = msgTmpPtr[ ISI_HEADER_OFFSET_RESOURCEID ];
-		    SET_LENGTH( ptr, length - PN_HEADER_SIZE );
-		    SET_RECEIVER_OBJ( ptr, GET_SENDER_OBJ( aMessage ) );
-		    SET_SENDER_OBJ( ptr, GET_RECEIVER_OBJ( aMessage ) );
-		    // Transactionid. Set to 0x01 since this is the first.
-		    tempPtr.Append( msgTmpPtr[ ISI_HEADER_OFFSET_TRANSID ] );
-		    // Message ID
-		    tempPtr.Append( ISI_HEADER_OFFSET_MESSAGEID );
-		    // Sub message ID.
-		    tempPtr.Append( COMM_ISA_ENTITY_NOT_REACHABLE_RESP );
-		    // Not Delivered Message from original req.
-		    tempPtr.Append( msgTmpPtr[ ISI_HEADER_OFFSET_MESSAGEID ] );
-		    // Status - COMM_ISA_ENTITY_NOT_AVAILABLE
-		    tempPtr.Append( 0x00 );
-		    // Filler
-		    tempPtr.Append( 0x00 );
-		    // Filler
-		    tempPtr.Append( 0x00 );
-		    // Filler
-            tempPtr.Append( 0x00 );
-            error = RouteISIMessage( tempPtr );
-   		    }
-		else
-		    {
-		    C_TRACE( ( _T( "DISICLTransceiver Not sending another CommIsaEntityNotReachableResp" ) ) );
-		    }
-    C_TRACE( ( _T( "DISICLTransceiver::SendCommIsaEntityNotReachableResp 0x%x<" ), &aMessage ) );
+        TBool sendOk( EFalse );
+        if ( aDynamicSenderCheckNeeded )// Save dynamic device ids from PN_DEV_OWN
+            {
+            C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage from ISI Router" ) ) );
+            TUint8 txDeviceIdentifier = GET_SENDER_DEV( aMessage );
+            if ( DynamicDevice( txDeviceIdentifier ) )
+                {
+                C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage from ISI Router Dynamic Dev" ) ) );                
+                UpdateDynamicDeviceTable( txDeviceIdentifier, PN_DEV_OWN );
+#ifndef USE_MEDIAAPI 				
+                ASSERT_RESET_ALWAYS( txDeviceIdentifier == PN_DEV_PC, 0xdeaddead );// only supported PN_DEV_PC with EIscNokiaUsbPhonetLink
+#endif /* USE_MEDIAAPI */  					
+                }
+            }
+
+        TUint8 rxDeviceIdentifier = GET_RECEIVER_DEV( aMessage );
+        C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage rxDeviceIdentifier 0x%x" ), rxDeviceIdentifier ) );
+        
+        if ( DynamicDevice( rxDeviceIdentifier ) )
+            {            
+            DynamicToStaticDevice( rxDeviceIdentifier );            
+            C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage rxDeviceIdentifier after 0x%x" ), rxDeviceIdentifier ) );
+            }
+
+
+        if( rxDeviceIdentifier == PN_DEV_OWN )
+            {
+            C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage PN_DEV_OWN 0x%x" ), &aMessage ) );
+            TUint16 objId(0xffff);
+#ifndef USE_MEDIAAPI 
+            if ( GET_RECEIVER_DEV( aMessage ) == PN_DEV_PC )
+                {
+                C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage to PN_DEV_PC in PN_DEV_OWN" )) );
+                objId = EIscNokiaUsbPhonetLink;
+                }
+            else
+                {
+                objId = GET_RECEIVER_OBJ( aMessage );
+                }
+#endif /* USE_MEDIAAPI */  					
+#ifdef USE_MEDIAAPI 
+            objId = GET_RECEIVER_OBJ( aMessage );
+#endif /* USE_MEDIAAPI */  				
+            sendOk = iShRouter.Receive( aMessage, objId );
+            C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage PN_DEV_OWN 0x%x ok %d" ), &aMessage, sendOk ) );
+            }        
+        else
+            {
+            C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage Not PN_DEV_OWN 0x%x" ), &aMessage ) );
+            MISIRouterLinkIf* link = NULL;
+
+
+            const TInt count( iShDevices.Count() );
+            for( TInt index( 0 ); index < count; index++ )
+                {
+                DISIDevice* tmpDevice = iShDevices[ index ];
+                ASSERT_RESET_ALWAYS( tmpDevice, ( EISICLTransceiverNULLPtr4 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+                tmpDevice->LockDeviceFM();
+                if( tmpDevice->GetDeviceIdentifier() == rxDeviceIdentifier ) 
+                    {
+                    link = tmpDevice->GetLink();
+                    tmpDevice->FreeDeviceFM();
+#ifndef USE_MEDIAAPI 					
+                    sendOk = link->Send( aMessage );
+                    break;
+#endif /* USE_MEDIAAPI */  	
+#ifdef USE_MEDIAAPI 						
+                    if ( GET_RECEIVER_DEV( aMessage ) == PN_DEV_PC )
+                        {
+                        C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage PN_DEV_PC %d, %d" ), link->GetTrxId(), iDevPcLastSendTrxId ) ); 	
+                        if(iDevPcLastSendTrxId < EAmountOfTrxs)
+                            {	
+                            if ( link->GetTrxId() ==	iDevPcLastSendTrxId )
+                                {
+                                if (link->StateConnected())
+                                    {
+                                    C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage PN_DEV_PC %d, Msg mediaid 0x%x" ), link->GetTrxId(), msgPtr[ ISI_HEADER_OFFSET_MEDIA ] ) ); 
+                                    sendOk = link->Send( aMessage );
+                                    break;
+                                    }
+                                }
+                            }    
+                        else
+                            {
+                            break;	
+                            }		   	
+		                 }
+                    else
+                    	{    			
+                        sendOk = link->Send( aMessage );
+                        break;
+                        }
+#endif /* USE_MEDIAAPI */  							
+                    }    
+                else
+                    {
+                    tmpDevice->FreeDeviceFM();
+                    }
+                }
+            C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage Not PN_DEV_OWN ok %d" ), &aMessage, sendOk ) );
+            }
+        if( !sendOk )
+            {
+            TRACE_ASSERT_ALWAYS;
+            error = SendCommIsaEntityNotReachableResp( aMessage );
+            }
+        }
+    C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage 0x%x<" ), &aMessage ) );
     return error;
     }
 
-TInt DISICLTransceiver::RouteISIMessage( TDes8& aMessage )
+void DISICLTransceiver::GetDeviceConnectionStates(
+        RArray<TUint8>& aDeviceIdentifierList,
+        const TBool aConnectedDevice
+        )
     {
-	 C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage 0x%x>" ), &aMessage ) );
-	TInt error( ValidateISIMessage( aMessage ) );
-    TBool sendOk( EFalse );
-    if(GET_RECEIVER_DEV( aMessage ) == PN_DEV_OWN )
-        {
-        C_TRACE( ( _T( "DISIRouter msg to PN_DEV_APE" ) ) );
-        sendOk = iRouter->Receive( aMessage, GET_RECEIVER_OBJ( aMessage ) );
-        C_TRACE( ( _T( "DISIRouter router sendOk %d" ), sendOk ) );
-        }
-    else
+    C_TRACE( ( _T( "DISICLTransceiver::GetDeviceConnectionStates 0x%x 0x%x>" ), &aDeviceIdentifierList, aConnectedDevice ) );
+
+    const TInt count( iShDevices.Count() );
+    for( TInt index( 0 ); index < count; index++ )
         {
-         C_TRACE( ( _T( "DISIRouter msg to other device" ) ) );
-         TUint8 linkId = MapDeviceToMedia( GET_RECEIVER_DEV( aMessage ) );
-	       ASSERT_RESET_ALWAYS( linkId < EISIAmountOfMedias, ( EISICLTransceiverNotSupportedMedia | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
-         MISIRouterLinkIf* link = iLinksArray[ linkId ];
-         ASSERT_RESET_ALWAYS( link, ( EISICLTransceiverNULLPtr | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
-         sendOk = link->Send( aMessage );
-         C_TRACE( ( _T( "DISIRouter link sendOk %d" ), sendOk ) );
-         }   
-    if( !sendOk )
-        {
-        SendCommIsaEntityNotReachableResp( aMessage );
-        MemApi::DeallocBlock( aMessage );
+        DISIDevice* tmpDevice = iShDevices[ index ];
+        ASSERT_RESET_ALWAYS( tmpDevice, ( EISICLTransceiverNULLPtr3 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+        tmpDevice->LockDeviceFM();
+        if( tmpDevice->GetDeviceState() == aConnectedDevice )
+            {
+            const TUint8 deviceIdentifier( tmpDevice->GetDeviceIdentifier() );
+            tmpDevice->FreeDeviceFM();
+            aDeviceIdentifierList.Append( deviceIdentifier );
+            }
+        else
+            {
+            tmpDevice->FreeDeviceFM();
+            }
         }
-	  C_TRACE( ( _T( "DISICLTransceiver::RouteISIMessage 0x%x<" ), &aMessage ) );
-    return error;
+    C_TRACE( ( _T( "DISICLTransceiver::GetDeviceConnectionStates 0x%x 0x%x<" ), &aDeviceIdentifierList, aConnectedDevice ) );
     }
 
 // KErrBadDescriptor, if message length too small
@@ -171,6 +469,7 @@
         TDes8& aMessage
         )
     {
+
     C_TRACE( ( _T( "DISICLTransceiver::ValidateISIMessage 0x%x>" ), &aMessage ) );
     const TUint16 descLength( aMessage.Length() );
     TInt msgOk( KErrNone );
@@ -188,40 +487,217 @@
     // If the ISI message length with PN_HEADER_SIZE is less or equal than ISI_HEADER_OFFSET_MESSAGEID.
     msgOk = ( ( msgOk == KErrNone && isiMsgLength <= ISI_HEADER_OFFSET_MESSAGEID ) ? KErrUnderflow : msgOk );
     TRACE_ASSERT_INFO( msgOk == KErrNone, msgOk );
-    TRACE_ASSERT_INFO( msgOk == KErrNone, msgOk );
     TRACE_ASSERT_INFO( msgOk == KErrNone, isiMsgLength );
     TRACE_ASSERT_INFO( msgOk == KErrNone, descLength );
-    TRACE_ASSERT_INFO( msgOk == KErrNone, msgOk );
     C_TRACE( ( _T( "DISICLTransceiver::ValidateISIMessage %d<" ), msgOk ) );
     return msgOk;
     }
 
-TUint8 DISICLTransceiver::MapDeviceToMedia(
-        const TUint8 aDevice
+// NOTE!! Called with FM held. Not allowed to block or nothing. Not even print traces!
+// Called in N Thread context
+void DISICLTransceiver::StateChanged(
+        // None
+        )
+    {
+
+    iShStateChangedDfc->Enque();
+
+    }
+
+void DISICLTransceiver::StateChangedDfc(
+        TAny* aPtr
+        )
+    {
+    C_TRACE( ( _T( "DISICLTransceiver::StateChangedDfc>" ) ) );
+    DISICLTransceiver* self = reinterpret_cast<DISICLTransceiver*>( aPtr );
+    ASSERT_RESET_ALWAYS( self, ( EISICLTransceiverNULLPtr5 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+    self->ReadStateChanges();
+    C_TRACE( ( _T( "DISICLTransceiver::StateChangedDfc<" ) ) );
+    }
+
+void DISICLTransceiver::ReadStateChanges(
+        // None
         )
     {
-    C_TRACE( ( _T( "DISICLTransceiver::MapDeviceToMedia aDevice %d>" ), aDevice ) );
-    TUint8 media( KErrNone );
-    switch( aDevice )
+
+    C_TRACE( ( _T( "DISICLTransceiver::ReadStateChanges>" ) ) );
+
+    const TInt count( iShDevices.Count() );
+    for( TInt index( 0 ); index < count; index++ )
         {
-        case PN_DEV_MODEM:
+        DISIDevice* tmpDevice = iShDevices[ index ];
+        ASSERT_RESET_ALWAYS( tmpDevice, ( EISICLTransceiverNULLPtr6 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+        tmpDevice->LockDeviceFM();
+        const TBool connected = tmpDevice->GetDeviceState();//  tee paremmaksi
+	
+#ifdef USE_MEDIAAPI 		
+        MISIRouterLinkIf* link = NULL;     
+        link = tmpDevice->GetLink();
+#endif /* USE_MEDIAAPI */                       	
+        if( connected != tmpDevice->GetDeviceOldState() )
             {
-            media = EISIMediaSharedMemory;
+            tmpDevice->SetDeviceOldState( connected );
+            const TUint8 deviceIdentifier = tmpDevice->GetDeviceIdentifier();
+            tmpDevice->FreeDeviceFM();
+#ifdef USE_MEDIAAPI 
+            C_TRACE( ( _T( "DISICLTransceiver::ReadStateChanges trxid 0x%x state changed>" ),link->GetTrxId() ) );   
+            if( (link->GetTrxId() == iDevPcLastSendTrxId) && (!connected) )
+                {
+                C_TRACE( ( _T( "DISICLTransceiver::ReadStateChanges trxid 0x%x disconneted>" ),link->GetTrxId() ) );   	
+         	      iDevPcLastSendTrxId = iDevPcLastActiveTrxId;
+         	      iDevPcLastActiveTrxId = EAmountOfTrxs;  //put a maxvalue	
+                } 
+#endif /* USE_MEDIAAPI */   					 
+            iRouterService->SendDeviceConnectionStateChangedInd( connected, deviceIdentifier );
+            }
+        else
+            {
+            tmpDevice->FreeDeviceFM();
+            }
+        }
+    C_TRACE( ( _T( "DISICLTransceiver::ReadStateChanges<" ) ) );
+    }
+
+TBool DISICLTransceiver::DynamicDevice( const TUint8 aDevId )
+    {
+    C_TRACE( ( _T( "DISICLTransceiver::DynamicDevice 0x%x>" ), aDevId ) );
+    TBool dynamicDevice(EFalse);
+    switch( aDevId )
+        {        
+        case PN_DEV_MODEM:
+        case PN_DEV_DUMMYIST:
+        case PN_DEV_OWN:
+            {
+            //already set as EFalse
             break;
             }
-        case PN_DEV_DUMMYIST:
-            {
-            media = EISIMediaTest;
-            break;
-            }
-        // Not supported device
         default:
             {
-           	ASSERT_RESET_ALWAYS( 0, ( EISICLTransceiverNotSupportedDevice | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+            dynamicDevice = ETrue;
             break;
             }
         }
-    C_TRACE( ( _T( "DISICLTransceiver::MapDeviceToMedia media %d<" ), media ) );
-    return media;
+    C_TRACE( ( _T( "DISICLTransceiver::DynamicDevice 0x%x<" ), dynamicDevice ) );
+    return dynamicDevice;
+    }
+    
+void DISICLTransceiver::UpdateDynamicDeviceTable( const TUint8 aDynamicDevId, const TUint8 aStaticDevId )
+    {
+    C_TRACE( ( _T( "DISICLTransceiver::UpdateDynamicDeviceTable 0x%x 0x%x>" ), aDynamicDevId, aStaticDevId) );
+    TBool deviceExist(EFalse);
+    TInt count(iDynamicDeviceTable.Count());
+    TInt err( Kern::MutexWait( *iDynamicDeviceTableMutex ) );
+    ASSERT_RESET_ALWAYS( ( err == KErrNone ), ( EISICLTransceiverMutexWaitFailed2 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+    for( TUint8 i = 0; i < count; i++ )
+        {
+        C_TRACE( ( _T( "DISICLTransceiver::UpdateDynamicDeviceTable find dynamic device %d" ), i) );
+        if( iDynamicDeviceTable[ i ]->iDynamicDevId == aDynamicDevId )
+            {                    
+            C_TRACE( ( _T( "DISICLTransceiver::UpdateDynamicDeviceTable dyn dev exist i = %d aDynamicDevId 0x%x staticDevId 0x%x previous 0x%x" ), i, iDynamicDeviceTable[ i ]->iDynamicDevId, aStaticDevId, iDynamicDeviceTable[ i ]->iStaticDevId ) );
+            iDynamicDeviceTable[ i ]->iStaticDevId = aStaticDevId;
+            deviceExist = ETrue;
+            break;
+            }
+        }
+        
+    if ( !deviceExist )
+        {
+        C_TRACE( ( _T( "DISICLTransceiver::UpdateDynamicDeviceTable new dynamic device added 0x%x 0x%x" ), aDynamicDevId, aStaticDevId ) );
+        iDynamicDeviceTable.Append( new TDynamicDevice( aDynamicDevId, aStaticDevId ) );
+        }
+    Kern::MutexSignal( *iDynamicDeviceTableMutex );
+    C_TRACE( ( _T( "DISICLTransceiver::UpdateDynamicDeviceTable 0x%x 0x%x<" ), aDynamicDevId, aStaticDevId) );
     }
 
+void DISICLTransceiver::DynamicToStaticDevice( TUint8& aRxDev )
+    {
+    C_TRACE( ( _T( "DISICLTransceiver::DynamicToStaticDevice aRxDev>" ), &aRxDev ) );
+    TInt err( Kern::MutexWait( *iDynamicDeviceTableMutex ) );
+    ASSERT_RESET_ALWAYS( ( err == KErrNone ), ( EISICLTransceiverMutexWaitFailed | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+    for( TUint8 i = 0; i < iDynamicDeviceTable.Count(); i++ )
+        {
+        if( iDynamicDeviceTable[ i ]->iDynamicDevId == aRxDev )
+            {                    
+            C_TRACE( ( _T( "DISICLTransceiver::DynamicToStaticDevice dyn dev exist i = %d iDynamicDevId 0x%x iStaticDevId 0x%x" ), i, iDynamicDeviceTable[ i ]->iDynamicDevId, iDynamicDeviceTable[ i ]->iStaticDevId) );
+            aRxDev = iDynamicDeviceTable[ i ]->iStaticDevId;
+            break;
+            }
+        }
+    Kern::MutexSignal( *iDynamicDeviceTableMutex );
+    C_TRACE( ( _T( "DISICLTransceiver::DynamicToStaticDevice aRxDev<" ), &aRxDev ) );
+    }
+        
+
+DISICLTransceiver::DISIDevice::DISIDevice(
+        const TUint8 aDeviceIdentifier,
+        MISIRouterLinkIf* aLink
+        )
+    {
+    C_TRACE( ( _T( "DISICLTransceiver::DISIDevice::DISIDevice 0x%x 0x%x 0x%x>" ), aDeviceIdentifier, aLink ) );
+    iShDeviceIdentifier = aDeviceIdentifier;
+    iShOldDeviceConnectedState = EFalse;
+    ASSERT_RESET_ALWAYS( aLink, ( EISICLTransceiverNULLPtr2 | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
+    iShLink = aLink;
+    iShDeviceMutex = new NFastMutex();
+    ASSERT_RESET_ALWAYS( iShDeviceMutex, EISICLTransceiverNULLPtr6 | EDISICLTransceiverTraceId << KClassIdentifierShift );
+    C_TRACE( ( _T( "DISICLTransceiver::DISIDevice::DISIDevice<" ) ) );
+    }
+
+DISICLTransceiver::DISIDevice::~DISIDevice()
+    {
+    C_TRACE( ( _T( "DISICLTransceiver::DISIDevice::~DISIDevice>" ) ) );
+    iShLink->Release();
+    iShLink = NULL;
+    // If not exists faulted already.
+    delete iShDeviceMutex;
+    iShDeviceMutex = NULL;
+    C_TRACE( ( _T( "DISICLTransceiver::DISIDevice::~DISIDevice<" ) ) );
+    }
+
+MISIRouterLinkIf* DISICLTransceiver::DISIDevice::GetLink()
+    {
+//    C_TRACE( ( _T( "DISICLTransceiver::DISIDevice::GetLink<> 0x%x" ), iShLink ) );
+    return iShLink;
+    }
+
+TUint8 DISICLTransceiver::DISIDevice::GetDeviceIdentifier()
+    {
+//    C_TRACE( ( _T( "DISICLTransceiver::DISIDevice::GetDeviceIdentifier<> 0x%x" ), iShDeviceIdentifier ) );
+    return iShDeviceIdentifier;
+    }
+
+TBool DISICLTransceiver::DISIDevice::GetDeviceState()
+    {
+//    C_TRACE( ( _T( "DISICLTransceiver::DISIDevice::GetDeviceState<>" ) ) );
+    return iShLink->StateConnected();
+    }
+
+TBool DISICLTransceiver::DISIDevice::GetDeviceOldState()
+    {
+//    C_TRACE( ( _T( "DISICLTransceiver::DISIDevice::GetDeviceOldState<> 0x%x" ), iShOldDeviceConnectedState ) );
+    return iShOldDeviceConnectedState;
+    }
+
+void DISICLTransceiver::DISIDevice::SetDeviceOldState(
+        TBool aConnected
+        )
+   {
+//   C_TRACE( ( _T( "DISICLTransceiver::DISIDevice::SetDeviceOldState<> 0x%x 0x%x" ), iShOldDeviceConnectedState, aConnected ) );
+   iShOldDeviceConnectedState = aConnected;    
+   }
+
+void DISICLTransceiver::DISIDevice::LockDeviceFM(
+        // None
+        )
+    {
+    C_TRACE( ( _T( "DISICLTransceiver::DISIDevice::LockDeviceFM<>" ) ) );    
+    NKern::FMWait( iShDeviceMutex );
+    }
+
+void DISICLTransceiver::DISIDevice::FreeDeviceFM(
+        // None
+        )
+    {
+    NKern::FMSignal( iShDeviceMutex );
+    C_TRACE( ( _T( "DISICLTransceiver::DISIDevice::FreeDeviceFM<>" ) ) );    
+    }