systemswstubs/examplecommonisc/IscDriver/src/IscChannel.cpp
changeset 0 0ce1b5ce9557
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/systemswstubs/examplecommonisc/IscDriver/src/IscChannel.cpp	Thu Jan 14 07:14:53 2010 +0200
@@ -0,0 +1,1800 @@
+/*
+* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  An example implementation for ISC Driver Reference
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <kern_priv.h>
+#include <IscDataTransmissionBase.h>
+#include "IscChannel.h"
+#include "IscDevice.h"
+#include "IscChannelContainer.h"
+#include "IscQueue.h"
+#include "IscTrace.h"
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES  
+
+// CONSTANTS
+_LIT( KIscDriver, "IscDriver" );
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+const TInt KIscInitializeDfcPriority( 1 );
+const TInt KOneParam( 1 );
+const TInt KTwoParams( 2 );
+const TInt KThreeParams( 3 );
+const TInt KFirstParam( 0 );
+const TInt KSecondParam( 1 );
+const TInt KThirdParam( 2 );
+const TInt KMultiplyByOne( KSecondParam );
+const TInt KMultiplyByThree( KThreeParams );
+const TInt KDivideByFour( 4 );
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// FORWARD DECLARATIONS
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+
+// -----------------------------------------------------------------------------
+// DIscChannel::DIscChannel
+// C++ default constructor.
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C DIscChannel::DIscChannel( DLogicalDevice* aDevice ) 
+    : iInitializeDfc( NULL ),
+    iDataTransmissionIniData( NULL ),
+    iMultiplexerIniData( NULL ),
+    iMultiplexerBuffer( NULL ),
+    iDataTransmissionBuffer( NULL ),
+    iIscDevice( NULL ),
+    iIscConnectionStatusPtr( NULL ),
+    iIscFlowControlStatusPtr( NULL ),
+    iReceiveBufPtr( NULL ),
+    iDataReceiveBufPtr( NULL ),
+    iNeededBufLen( NULL ),
+    iNeededDataBufLen( NULL ),
+    iChannelNumber( 0 ),
+    iChannelOpen( EFalse ),
+    iFrameRx( NULL ),
+    iFrameRxQueue( NULL ),    
+    iDataFrameRx( NULL ),
+    iDataFrameRxQueue( NULL ),
+    iULFlowControlStatus( EIscFlowControlOff ),
+    iDLFlowControlStatus( EIscFlowControlOff ),
+    iLastNotifiedULFlowstatus( EIscFlowControlOff ),
+    iIscChannelHighWaterMark( 0 ),
+    iIscChannelLowWaterMark( 0 ),
+    iOverFlow( EFalse ),
+    iClientPanic( EFalse ),
+    iDataTransmissionErrorCode( KErrNone )
+    {
+    
+    iIscDevice = ( DIscDevice * )aDevice;
+    for ( TInt i( KErrNone ); i < EIscAsyncLast; i++ )
+        {
+        iIscRequests[i] = NULL;
+        }
+    iThread = &Kern::CurrentThread();   
+    TInt r = iThread->Open();
+    TRACE_ASSERT( r == KErrNone );
+
+    }
+
+
+// -----------------------------------------------------------------------------
+// DIscChannel::~DIscChannel
+// Destructor
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+DIscChannel::~DIscChannel()
+    {
+    C_TRACE( ( _T( "DIscChannel::~DIscChannel()" ) ) );
+    
+    if ( iChannelNumber < KIscNumberOfUnits )
+        {
+        IscChannelContainer::RemoveChannel( this );
+        }
+    else 
+        {
+        C_TRACE( ( _T( "DIscChannel::~DIscChannel() re-open" ) ) );
+        }
+
+    ChannelDestruction();    
+    Kern::SafeClose( ( DObject*& )iThread, NULL );
+    C_TRACE( ( _T( "DIscChannel::~DIscChannel() SafeClose called" ) ) );
+
+    }
+
+// -----------------------------------------------------------------------------
+// DIscChannel::ChannelDestruction
+// Destructor
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void DIscChannel::ChannelDestruction()
+    {
+    C_TRACE( ( _T( "DIscChannel::ChannelDestruction() iChannelNumber (0x%x)" ),iChannelNumber ) );
+
+    // call DIscMultiplexerBase::CloseDLC and DLFlowControlNotify in case the channel has not been
+    // properly closed ( e.g. client thread panic etc. )
+    if ( iChannelOpen )
+        {
+        iIscDevice->CancelSending( iChannelNumber, this );// Delete pending send frames
+        iIscDevice->iIscMultiplexerInterface->CloseDLC( iChannelNumber, this );
+        iIscDevice->DLFlowControlNotify( EIscFlowControlOff, iChannelNumber, this );
+        }
+
+    if ( iFrameRxQueue )
+        {
+        while ( !iFrameRxQueue->Empty() )
+            {
+            TDes8* tempPtr = ( TDes8* ) iFrameRxQueue->GetFirst();
+            iFrameRxQueue->DeleteFirst();
+            iIscDevice->ReleaseMemoryBlock( tempPtr );
+            }
+        delete iFrameRxQueue;
+        iFrameRxQueue = NULL;
+        }
+
+    if ( iFrameRx )
+            {
+            delete [] iFrameRx;
+            iFrameRx = NULL;
+            }
+
+    if ( iDataFrameRxQueue )
+        {
+        while ( !iDataFrameRxQueue->Empty() )
+            {
+            TDes8* tempPtr = ( TDes8* ) iDataFrameRxQueue->GetFirst();
+            iDataFrameRxQueue->DeleteFirst();
+            iIscDevice->ReleaseMemoryBlock( tempPtr );        
+            }
+        delete iDataFrameRxQueue;
+        iDataFrameRxQueue = NULL;        
+        }
+
+    if ( iDataFrameRx )
+            {
+            delete [] iDataFrameRx;
+            iDataFrameRx = NULL;
+            }
+    
+    if ( iInitializeDfc )
+        {        
+        delete iInitializeDfc;
+        iInitializeDfc = NULL;
+        }    
+
+    if ( iDataTransmissionIniData )
+        {
+        Kern::Free( iDataTransmissionBuffer );
+        delete iDataTransmissionIniData;
+        iDataTransmissionIniData = NULL;
+        }
+
+    if ( iMultiplexerIniData )
+        {
+        Kern::Free( iMultiplexerBuffer );
+        delete iMultiplexerIniData;
+        iMultiplexerIniData = NULL;
+        }
+
+    C_TRACE( ( _T( "DIscChannel::ChannelDestruction - return void" ) ) );
+    }
+
+// -----------------------------------------------------------------------------
+// DIscChannel::HandleMsg
+// Message handling ( kernel server context ).
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void DIscChannel::HandleMsg( 
+    TMessageBase* aMsg )
+    {
+    C_TRACE( ( _T( "DIscChannel::HandleMsg(0x%x)" ), aMsg ) );
+    TThreadMessage& m=*( TThreadMessage* )aMsg;
+    TInt id( m.iValue );
+
+    if ( id==( TInt )ECloseMsg )
+        {
+        C_TRACE( ( _T( "DIscChannel::HandleMsg ECloseMsg" ) ) );
+        m.Complete( KErrNone,EFalse );
+        return;
+        }
+
+    else if ( id==KMaxTInt )
+        {
+        // DoCancel
+        // Should not come here ever
+        ASSERT_RESET_ALWAYS( 0,"IscDriver",EIscNotAllowedCallToDoCancel );
+        }
+
+    else if ( id<0 )
+        {
+        // DoRequest
+        // should not come here ever
+        ASSERT_RESET_ALWAYS( 0,"IscDriver",EIscNotAllowedCallToDoRequest );
+        }
+    
+    else
+        {
+        // DoControl
+        TUint32 a1[ KThreeParams ];
+        TInt r( KErrNone );
+        if ( id != EIscSyncClose )
+            {
+            TInt amountOfParams( KErrNone );
+            switch( id )
+                {
+                case EIscAsyncInitializeModemInterface:
+                case EIscAsyncOpen:
+                    amountOfParams = KThreeParams;
+                    break;
+                default:
+                    ASSERT_RESET_ALWAYS( 0, "NokiaISCDriver", EIscUnknownCommand );
+                break;
+                }
+            r = Kern::ThreadRawRead( iThread, ( TAny* )m.Ptr0(), a1,
+                                     amountOfParams * sizeof( TAny* ) );
+            TRACE_ASSERT( r == KErrNone );
+            }
+        if( r == KErrNone )
+            {
+            r=HandleRequest( id,a1,m.Ptr1() );
+            }
+
+        m.Complete( r,ETrue );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// DIscChannel::Request
+// Message handling ( user thread context ).
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+#ifndef COMPONENT_TRACE_FLAG
+TInt DIscChannel::Request( TInt aReqNo, TAny* a1, TAny* )
+#else 
+TInt DIscChannel::Request( TInt aReqNo, TAny* a1, TAny* a2)
+#endif
+    {
+    C_TRACE( ( _T( "DIscChannel::Request(0x%x, 0x%x, 0x%x)" ), aReqNo, a1, a2 ) );
+
+    TInt r( KErrNotFound );
+
+    if ( aReqNo<( TInt )EMinRequestId )
+        C_TRACE( ( _T( "DIscChannel::Request ERROR: False aReqNo %d" ), aReqNo ) );
+    
+    if ( aReqNo >= 0 && aReqNo < EIscAsyncLastKernelServerContext ||
+         aReqNo >= EIscAsyncLast && aReqNo < EIscSyncLastKernelServerContext )
+        {
+        TThreadMessage& m=Kern::Message();
+        m.iValue=aReqNo;
+        m.iArg[ KFirstParam ]=a1;
+        m.iArg[ KSecondParam ]=NULL;
+        r = m.SendReceive( &iMsgQ );
+        }
+    else
+        {
+        TInt ulen( KErrNotFound );
+        switch ( aReqNo )
+            {
+            case EIscCancelAsyncInitialize:
+            case EIscCancelAsyncReceive:
+            case EIscCancelAsyncDataReceive:
+            case EIscSyncGetConnectionStatus:
+            case EIscCancelAsyncNotifyConnection:
+            case EIscSyncGetFlowControlStatus:
+            case EIscCancelAsyncNotifyFlowControl:
+            case EIscSyncGetMaximunDataSize:
+            case EIscCancelAsyncCustomOperation1:
+            case EIscCancelAsyncCustomOperation2:
+            case EIscCancelAsyncCustomOperation3:
+            case EIscCancelAsyncCustomOperation4:
+            case EIscCancelAsyncCustomOperation5:
+            case EIscCancelAsyncOpen:
+            case EIscSyncResetBuffers:
+            case EIscCancelAsyncSend:
+            case EIscCancelAsyncDataSend:
+                {
+                ulen = KErrNone;
+                break;
+                }
+            case EIscSyncSend:
+            case EIscSyncDataSend:
+            case EIscSyncCustomOperation1:
+            case EIscSyncCustomOperation2:
+            case EIscSyncCustomOperation3:
+            case EIscSyncCustomOperation4:
+            case EIscSyncCustomOperation5:
+            case EIscAsyncClose:
+                {
+                ulen = KOneParam;
+                break;
+                }
+            case EIscAsyncSend:
+            case EIscAsyncDataSend:
+            case EIscSyncGetChannelInfo:
+            case EIscAsyncNotifyConnectionStatus:
+            case EIscAsyncNotifyFlowControlStatus:
+            case EIscAsyncCustomOperation1:
+            case EIscAsyncCustomOperation2:
+            case EIscAsyncCustomOperation3:
+            case EIscAsyncCustomOperation4:
+            case EIscAsyncCustomOperation5:
+                {
+                ulen = KTwoParams;
+                break;
+                }
+            case EIscAsyncReceive:
+            case EIscAsyncDataReceive:
+                {
+                ulen = KThreeParams;
+                break;
+                }
+            default:
+                {
+                TRACE_ASSERT_ALWAYS;
+                }
+            }
+        ASSERT_RESET_ALWAYS( KErrNotFound != ulen, "ISCDriver", EIscUnknownCommand );
+        // Maximum number of elements is three!!!
+        TAny* kptr[ KThreeParams ] = { KErrNone }; 
+        if( ulen > KErrNone )
+            {
+            C_TRACE( ( _T( "DIscChannel::Request ISC kumemget32" ) ) );
+            kumemget32( kptr , a1, ( sizeof( TAny* ) ) * ulen ); 
+            }
+        r = HandleRequest( aReqNo, kptr, NULL );
+        }
+    C_TRACE( ( _T( "DIscChannel::Request ISC return %d CH 0x%x" ), r, iChannelNumber ) );
+    return r;        
+
+    }
+
+// -----------------------------------------------------------------------------
+// DIscChannel::DoControl
+// Handles requests.
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+TInt DIscChannel::HandleRequest( 
+    TInt aFunction, 
+    TAny* a1, 
+    TAny* /*a2*/ )
+    {
+    C_TRACE( ( _T( "DIscChannel::DoControl(0x%x, 0x%x) iChannelNumber 0x%x channelPtr 0x%x" ), aFunction, a1, iChannelNumber, this ) );
+
+    TInt error( KErrNone );
+    
+#ifdef _DEBUG
+    // Check if control frame buffer overflow -> panic
+    if ( iClientPanic )
+        {
+        C_TRACE( ( _T( "DIscChannel::DoControl() BUFFER OVERFLOW: PANIC CLIENT 0x%x" ), iChannelNumber ) );
+        TRACE_ASSERT_ALWAYS;
+        // This panic the user thread only.
+		Kern::ThreadKill( iThread, EExitPanic, EIscControlBufferOverflow, KIscDriver );
+        }
+#endif // _DEBUG
+
+    // Handle asynchronous requests
+    if ( aFunction >= EIscAsyncInitializeModemInterface &&
+         aFunction < EIscAsyncLast )
+        {
+        // if request is already active
+        if ( iIscRequests[aFunction] )
+            {
+            TUint32* tablePtr = ( TUint32* )a1;
+            TRequestStatus* requestStatus = ( TRequestStatus* )( tablePtr[ KFirstParam ] );
+            Kern::RequestComplete( iThread, requestStatus, KErrAlreadyExists );
+            }
+        else
+            {
+            HandleAsyncRequest( aFunction, a1 );
+            }
+        }
+    // Handle synchronous requests.
+    else if ( aFunction >= EIscAsyncLast &&
+              aFunction < EIscSyncLast )
+        {
+        error = HandleSyncRequest( aFunction, a1 );
+        }
+    // Handle cancellation requests.
+    else if ( aFunction >= EIscSyncLast &&
+              aFunction < EIscCancelLast )
+        {
+        error = HandleCancelRequest( aFunction, a1 );
+        }
+    // Undefined request, panic current thread. 
+    else
+        {
+        // This panic the user thread only.
+		Kern::ThreadKill( iThread, EExitPanic, EIscControlBufferOverflow, KIscDriver );
+        }
+        
+    C_TRACE( ( _T( "DIscChannel::DoControl - return %d" ), error ) );
+
+    return error;
+    }
+
+   
+// -----------------------------------------------------------------------------
+// DIscChannel::HandleAsyncRequests
+// Handles asynchronous client requests
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void DIscChannel::HandleAsyncRequest( 
+    TInt aFunction, 
+    TAny* a1 )
+    {
+    C_TRACE( ( _T( "DIscChannel::HandleAsyncRequest(0x%x, 0x%x) channelPtr 0x%x" ), aFunction, a1, this ) );
+
+    TUint32* tablePtr = ( TUint32* )a1;
+
+    switch ( aFunction )
+        {
+        case EIscAsyncInitializeModemInterface:
+            {    
+            TInt r = KErrNotFound;
+            iIscRequests[EIscAsyncInitializeModemInterface] = ( TRequestStatus* )( tablePtr[ KFirstParam ] );
+           
+            iInitializeDfc = new TDfc( InitializeComplete, this, Kern::DfcQue0(), KIscInitializeDfcPriority );            
+            ASSERT_RESET_ALWAYS( iInitializeDfc, "IscDriver",EIscMemoryAllocationFailure );
+
+            // Get Data Transmission Driver initialization string
+            TDesC8* tempPtr = ( TDesC8* )tablePtr[ KThirdParam ];
+            iDataTransmissionBuffer = ( TUint8* )Kern::Alloc( KIscIniLineLength );
+            ASSERT_RESET_ALWAYS( iDataTransmissionBuffer, "IscDriver",EIscMemoryAllocationFailure );
+
+            iDataTransmissionIniData = new ( TPtr8 )( iDataTransmissionBuffer, KIscIniLineLength );
+            ASSERT_RESET_ALWAYS( iDataTransmissionIniData, "IscDriver",EIscMemoryAllocationFailure );
+
+            r = Kern::ThreadDesRead( iThread, tempPtr, *iDataTransmissionIniData, 0, KChunkShiftBy0 );
+            ASSERT_RESET_ALWAYS( r == KErrNone, "IscDriver",EIscMemoryAllocationFailure );
+
+            // Get Multiplexer initialization string
+            tempPtr = ( TDesC8* )tablePtr[1];
+            iMultiplexerBuffer = ( TUint8* )Kern::Alloc( KIscIniLineLength );
+            ASSERT_RESET_ALWAYS( iMultiplexerBuffer, "IscDriver",EIscMemoryAllocationFailure );
+
+            iMultiplexerIniData = new ( TPtr8 )( iMultiplexerBuffer, KIscIniLineLength );
+            ASSERT_RESET_ALWAYS( iDataTransmissionIniData, "IscDriver",EIscMemoryAllocationFailure );
+
+            r = Kern::ThreadDesRead( iThread, tempPtr, *iMultiplexerIniData, 0, KChunkShiftBy0 );
+            ASSERT_RESET_ALWAYS( r == KErrNone, "IscDriver",EIscMemoryAllocationFailure );
+
+            // If buffer configuration is given from isc_config.ini as multiplexer configuration string, multiplexer 
+            // needs configuration before datatransmissin driver is initialized
+            iIscDevice->iIscMultiplexerInterface->SetInitializationParameters( *iMultiplexerIniData );
+
+            // Allocate buffers and receive queues
+            iIscDevice->Initialize();
+
+            iIscDevice->iIscDataTransmissionInterface->InitializeDataTransmission( *iDataTransmissionIniData, 
+                                                                                   iInitializeDfc,
+                                                                                   iDataTransmissionErrorCode );            
+            break;
+            }
+            
+        case EIscAsyncOpen:
+            {
+            iIscRequests[EIscAsyncOpen] = ( TRequestStatus* )( tablePtr[ KFirstParam ] );
+            if ( iIscDevice->ConnectionStatus() == EIscConnectionOk )
+                {
+                TDesC8* openInfo = ( TDesC8* )tablePtr[ KThirdParam ];
+                // Channel info parameter has to be copied from user side in Epoc Kernel Architecture 2
+                TInt length = Kern::ThreadGetDesLength( iThread, ( TDesC8* )tablePtr[ KThirdParam ] );
+                TUint8* buffer = NULL;
+                TPtr8* bufferPtr = NULL;
+                if ( length > KErrNone )
+                    {
+                    C_TRACE( ( _T( "DIscChannel::HandleAsyncRequest EIscAsyncOpen channel info got" ) ) );
+                    buffer = ( TUint8* )Kern::Alloc( length );
+                    bufferPtr = new ( TPtr8 )( buffer, length );
+                    TInt r = Kern::ThreadDesRead( iThread, openInfo, *bufferPtr, 0, KChunkShiftBy0 );
+                    ASSERT_RESET_ALWAYS( r == KErrNone, "IscDriver",EIscMemoryAllocationFailure );
+                    openInfo = ( TDesC8* )bufferPtr;
+                    }
+                iIscDevice->iIscMultiplexerInterface->OpenDLC( ( TUint16 )tablePtr[ KSecondParam ], 
+                                                               openInfo,
+                                                               this );
+
+                if ( buffer )
+                    Kern::Free( buffer );
+                if ( bufferPtr )
+                    {
+                    delete bufferPtr;
+                    bufferPtr = NULL;
+                    }
+                }
+            else
+                {
+                CompleteRequest( aFunction, KErrNotReady );
+                }
+            break;
+            }
+        case EIscAsyncSend:
+            {
+            iIscRequests[EIscAsyncSend] = ( TRequestStatus* )( tablePtr[ KFirstParam ] );
+            if ( iIscDevice->ConnectionStatus() == EIscConnectionOk
+                && iULFlowControlStatus == EIscFlowControlOff )
+                {
+                TDesC8* ptr = ( TDesC8* ) tablePtr[ KSecondParam ];
+
+                // No return values check needed. Request completed with error value by multiplexer
+                iIscDevice->iIscMultiplexerInterface->Send( ( TUint16 )aFunction,
+                                                            iChannelNumber, 
+                                                            *ptr,
+                                                            this );
+                }
+            else
+                {
+                if ( iULFlowControlStatus != EIscFlowControlOff )
+                    {
+                    CompleteRequest( aFunction, KErrOverflow );
+                    }
+                else
+                    {
+                    CompleteRequest( aFunction, KErrNotReady );
+                    }
+                }
+            break;
+            }
+        case EIscAsyncReceive:
+            {    
+            TRACE_ASSERT( tablePtr[ KFirstParam ] );
+            TRACE_ASSERT( tablePtr[ KSecondParam ] );
+            TRACE_ASSERT( tablePtr[ KThirdParam ] );
+            
+            // check for descriptor validity
+            TRACE_ASSERT( Kern::ThreadGetDesMaxLength( iThread, (TPtr8* )tablePtr[KSecondParam] ) > 0 ); 
+            
+            //Store needed length ptr
+            iNeededBufLen = ( TPtr8* )tablePtr[ KThirdParam ];
+            
+            //Store msg data ptr
+            iReceiveBufPtr = ( TPtr8* )tablePtr[ KSecondParam ];
+            
+            iIscRequests[EIscAsyncReceive] = ( TRequestStatus* )( tablePtr[ KFirstParam ] );
+                
+            break;
+            }
+        case EIscAsyncDataSend:
+            {
+            iIscRequests[EIscAsyncDataSend] = ( TRequestStatus* )( tablePtr[ KFirstParam ] );
+                
+            if ( iIscDevice->ConnectionStatus() == EIscConnectionOk
+                && iULFlowControlStatus == EIscFlowControlOff )
+                {
+                TDesC8* ptr = ( TDesC8* )tablePtr[ KSecondParam ];
+                iIscDevice->iIscMultiplexerInterface->DataSend( ( TUint16 )aFunction,
+                                                                iChannelNumber,
+                                                                *ptr,
+                                                                this );
+                }
+            else
+                {
+                if ( iULFlowControlStatus != EIscFlowControlOff )
+                    {
+                    CompleteRequest( aFunction, KErrOverflow );
+                    }
+                else
+                    {
+                    CompleteRequest( aFunction, KErrNotReady );
+                    }
+                }
+            break;
+            }
+        case EIscAsyncDataReceive:
+            {
+            TRACE_ASSERT( tablePtr[ KFirstParam ] );
+            TRACE_ASSERT( tablePtr[ KSecondParam ] );
+            TRACE_ASSERT( tablePtr[ KThirdParam ] );
+
+            // check for descriptor validity
+            TRACE_ASSERT( Kern::ThreadGetDesMaxLength( iThread, (TPtr8* )tablePtr[KSecondParam] ) > 0 ); 
+            
+            //Store needed length ptr
+            iNeededDataBufLen = ( TPtr8* )tablePtr[ KThirdParam ];
+            
+            //Store msg data ptr
+            iDataReceiveBufPtr = ( TPtr8* )tablePtr[ KSecondParam ];
+            
+            iIscRequests[EIscAsyncDataReceive] = ( TRequestStatus* )( tablePtr[ KFirstParam ] );
+                
+            break;
+            }
+        case EIscAsyncNotifyConnectionStatus:
+            {
+            iIscConnectionStatusPtr = ( TPtr8* )tablePtr[ KSecondParam ];
+            iIscRequests[EIscAsyncNotifyConnectionStatus] = ( TRequestStatus* )( tablePtr[ KFirstParam ] );
+            break;
+            }
+        case EIscAsyncNotifyFlowControlStatus:
+            {
+            iIscFlowControlStatusPtr = reinterpret_cast<TPtr8*>( tablePtr[ KSecondParam ] );
+            iIscRequests[ EIscAsyncNotifyFlowControlStatus ] = reinterpret_cast<TRequestStatus*>( tablePtr[ KFirstParam ] );
+            C_TRACE( ( _T( "DIscChannel::NotifyFlowControl iLastNotifiedULFlowstatus = %d iULFlowControlStatus = %d" ), iLastNotifiedULFlowstatus, iULFlowControlStatus ) );
+            
+            if( iULFlowControlStatus != iLastNotifiedULFlowstatus )
+                {
+                // Complete immediately.
+                C_TRACE( ( _T( "DIscChannel::HandleAsyncRequest iULFlowControlStatus != iLastNotifiedULFlowstatus" ) ) );
+                NotifyFlowControl( iULFlowControlStatus );    
+                }
+            else
+                {
+                // None
+                }
+            break;
+            }
+        case EIscAsyncCustomOperation1:
+        case EIscAsyncCustomOperation2:
+        case EIscAsyncCustomOperation3:
+        case EIscAsyncCustomOperation4:
+        case EIscAsyncCustomOperation5:
+            {
+            iIscRequests[aFunction] = ( TRequestStatus* )( tablePtr[ KFirstParam ] );
+            TAny* tempPtr = ( TAny* )tablePtr[ KSecondParam ];
+            iIscDevice->iIscMultiplexerInterface->CustomFunction( iChannelNumber, 
+                                                             ( TUint16 )aFunction, 
+                                                             tempPtr,
+                                                             this );
+            break;
+            }
+        case EIscAsyncClose:
+            {
+            iIscRequests[aFunction] = ( TRequestStatus* )( tablePtr[ KFirstParam ] );
+
+            ResetBuffers();
+            
+            // Cancel all active requests except asynchronous close
+            for ( TInt i( KErrNone ); i < EIscAsyncLast; i++ )
+                {
+                // if request is active complete it with KErrCancel
+                if ( iIscRequests[i] && i != EIscAsyncClose )
+                    {
+                    iIscDevice->iIscMultiplexerInterface->CancelNotify( iChannelNumber, i, this );
+                    CompleteRequest( i, KErrCancel );
+                    }
+                }            
+
+            iChannelOpen = EFalse;
+
+            iIscDevice->iIscMultiplexerInterface->CloseDLC( iChannelNumber, this );
+            
+            break;
+            }
+        default:
+            {
+            ASSERT_RESET_ALWAYS( 0,"IscDriver",EIscUnknownCommand );
+            break;
+            }
+        }
+
+    IscChannelContainer::AddDfc();
+    
+    }
+
+
+// -----------------------------------------------------------------------------
+// DIscChannel::HandleSyncRequest
+// Handles synchronous client requests
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+TInt DIscChannel::HandleSyncRequest( 
+        TInt aFunction, 
+        TAny* a1 )
+    {
+    C_TRACE( ( _T( "DIscChannel::HandleSyncRequest(0x%x, 0x%x) channelPtr 0x%x" ), aFunction, a1, this ) );
+
+    TInt error( KErrNone );
+    TUint32* tablePtr = ( TUint32* )a1;
+
+    switch ( aFunction )
+        {
+        case EIscSyncClose:
+            {
+            ResetBuffers();
+            
+            iIscDevice->iIscMultiplexerInterface->CloseDLC( iChannelNumber, this );
+            
+            // Cancel all active requests 
+            for ( TInt i( KErrNone ); i < EIscAsyncLast; i++ )
+                {
+                // if request is active complete it with KErrCancel
+                if ( iIscRequests[i] )
+                    {
+                    iIscDevice->iIscMultiplexerInterface->CancelNotify( iChannelNumber, i, this );
+                    CompleteRequest( i, KErrCancel );
+                    }
+                }
+
+            error = KErrNone;
+            iChannelOpen = EFalse;
+            break;
+            }
+        case EIscSyncSend:
+            {
+            if ( iIscDevice->ConnectionStatus() == EIscConnectionOk 
+                && iULFlowControlStatus == EIscFlowControlOff ) 
+                {
+                
+                TDesC8* ptr = ( TDesC8* ) tablePtr[ KFirstParam ];
+                error = iIscDevice->iIscMultiplexerInterface->Send( ( TUint16 )aFunction,
+                                                            iChannelNumber, 
+                                                            *ptr,
+                                                            this );
+                }
+            else
+                {
+                if ( iULFlowControlStatus != EIscFlowControlOff )
+                    {
+                    error = KErrOverflow;
+                    }
+                else
+                    {
+                    error = KErrNotReady;
+                    }
+                }
+            break;
+            }
+        case EIscSyncDataSend:
+            {
+            if ( iIscDevice->ConnectionStatus() == EIscConnectionOk 
+                && iULFlowControlStatus == EIscFlowControlOff ) 
+                {
+                TDesC8* ptr = ( TDesC8* ) tablePtr[ KFirstParam ];
+                error = iIscDevice->iIscMultiplexerInterface->DataSend( ( TUint16 )aFunction,
+                                                                iChannelNumber,
+                                                                *ptr,
+                                                                this );
+                }
+            else
+                {
+                if ( iULFlowControlStatus != EIscFlowControlOff )
+                    {
+                    error = KErrOverflow;
+                    }
+                else
+                    {
+                    error = KErrNotReady;
+                    }
+                }
+            break;
+            }
+        case EIscSyncGetConnectionStatus:
+            {
+            error = iIscDevice->ConnectionStatus();
+            break;
+            }
+        case EIscSyncGetFlowControlStatus:
+            {
+            error = iULFlowControlStatus;
+            break;
+            }
+        case EIscSyncGetChannelInfo:
+            {
+            TDes8* tempPtr = ( TDes8* ) tablePtr[1];
+            error = iIscDevice->iIscMultiplexerInterface->GetChannelInfo( ( TUint16 )tablePtr[ KFirstParam ],
+                                                                  *tempPtr );
+            break;
+            }
+        case EIscSyncGetMaximunDataSize:
+            {
+            error = iIscDevice->iIscMultiplexerInterface->MaximumDataSize( iChannelNumber );
+            break;
+            }
+        case EIscSyncCustomOperation1:
+        case EIscSyncCustomOperation2:
+        case EIscSyncCustomOperation3:
+        case EIscSyncCustomOperation4:
+        case EIscSyncCustomOperation5:
+            {
+            TAny* tempPtr = ( TAny* )tablePtr[ KFirstParam ];
+            error = iIscDevice->iIscMultiplexerInterface->CustomFunction( iChannelNumber,
+                                                                     ( TUint16 )aFunction, 
+                                                                     tempPtr,
+                                                                     this );
+            break;
+            }
+        case EIscSyncResetBuffers:
+            {
+            ResetBuffers();
+            error = KErrNone;
+            break;
+            }
+        default:
+            {
+            ASSERT_RESET_ALWAYS( 0,"IscDriver",EIscUnknownCommand );
+            break;
+            }
+        }
+    return error;
+    }
+
+// -----------------------------------------------------------------------------
+// DIscChannel::HandleCancelRequest
+// Cancels active request
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+TInt DIscChannel::HandleCancelRequest( 
+    TInt aFunction, 
+    TAny* /*a1*/ )
+    {
+    C_TRACE( ( _T( "DIscChannel::HandleCancelRequest(0x%x)" ), aFunction ) );
+
+    TUint16 operationToCancel( 0 );
+    switch ( aFunction )
+        {
+        
+        case EIscCancelAsyncInitialize:
+            {
+            if ( iDataTransmissionIniData )
+                {
+                Kern::Free( iDataTransmissionBuffer );
+                delete iDataTransmissionIniData;
+                iDataTransmissionIniData = NULL;
+                }
+            if ( iMultiplexerIniData )
+                {
+                Kern::Free( iMultiplexerBuffer );
+                delete iMultiplexerIniData;
+                iMultiplexerIniData = NULL; 
+                }
+
+            operationToCancel = EIscAsyncInitializeModemInterface;
+            break;
+            }
+        case EIscCancelAsyncOpen:
+            {
+            if ( KRequestPending == IsPending( EIscAsyncOpen ) )
+                {
+                iChannelOpen = EFalse;
+                }            
+            operationToCancel = EIscAsyncOpen;
+            break;
+            }
+        case EIscCancelAsyncSend:
+            {
+            operationToCancel = EIscAsyncSend;
+            // Cancel sending / empty send queues
+            iIscDevice->CancelSending( iChannelNumber, this );
+            break;
+            }
+        case EIscCancelAsyncDataSend:
+            {
+            operationToCancel = EIscAsyncDataSend;
+            // Cancel sending / empty send queues
+            iIscDevice->CancelSending( iChannelNumber, this );
+            break;
+            }
+        
+        case EIscCancelAsyncReceive:
+            {
+            iReceiveBufPtr = NULL;
+            iNeededBufLen = NULL;
+            operationToCancel = EIscAsyncReceive;
+            break;
+            }
+        
+        case EIscCancelAsyncDataReceive:
+            {
+            iDataReceiveBufPtr = NULL;
+            iNeededDataBufLen = NULL;
+            operationToCancel = EIscAsyncDataReceive;
+            break;
+            }
+        
+        case EIscCancelAsyncNotifyConnection:
+            {
+            iIscConnectionStatusPtr = NULL;
+            operationToCancel = EIscAsyncNotifyConnectionStatus;
+            break;
+            }
+        
+        case EIscCancelAsyncNotifyFlowControl:
+            {
+            iIscFlowControlStatusPtr = NULL;
+            operationToCancel = EIscAsyncNotifyFlowControlStatus;
+            break;
+            }
+        case EIscCancelAsyncCustomOperation1:
+            {
+            operationToCancel = EIscAsyncCustomOperation1;
+            break;
+            }
+        case EIscCancelAsyncCustomOperation2:
+            {
+            operationToCancel = EIscAsyncCustomOperation2;
+            break;
+            }
+        case EIscCancelAsyncCustomOperation3:
+            {
+            operationToCancel = EIscAsyncCustomOperation3;
+            break;
+            }
+        case EIscCancelAsyncCustomOperation4:
+            {
+            operationToCancel = EIscAsyncCustomOperation4;
+            break;
+            }
+        case EIscCancelAsyncCustomOperation5:
+            {
+            operationToCancel = EIscAsyncCustomOperation5;
+            break;
+            }
+        case EIscCancelAsyncClose:
+            {
+            TRACE_ASSERT_ALWAYS;
+            operationToCancel = EIscAsyncClose;
+            break;
+            }
+        default:
+            {
+            ASSERT_RESET_ALWAYS( 0,"IscDriver",EIscUnknownCommand );
+            break;
+            }
+        }
+
+    iIscDevice->iIscMultiplexerInterface->CancelNotify( iChannelNumber, ( TUint16 )operationToCancel, this );
+    CompleteRequest( operationToCancel, KErrCancel );
+
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// DIscChannel::DoCreate
+// Secondary initialization of channel
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+TInt DIscChannel::DoCreate( 
+    TInt aUnit, 
+    const TDesC8* anInfo, 
+    const TVersion& /*aVer*/ )
+    {
+    C_TRACE( ( _T( "DIscChannel::DoCreate(0x%x, 0x%x, 0x%x)" ), aUnit, anInfo, this ) );
+    if ( !Kern::CurrentThreadHasCapability( ECapabilityCommDD,__PLATSEC_DIAGNOSTIC_STRING
+        ( "Checked by ISCDRIVER.LDD ( Inter-System Communication Driver )" ) ) )
+        {
+        return KErrPermissionDenied;
+        }    
+    TUint16 channelNumber = ( TUint16 )aUnit;
+    if ( anInfo )
+        {
+        // check for channel number inside anInfo
+        TUint8 channel = ( TUint8 )( *anInfo )[0];
+        if ( channel >= KIscMaxChannelsInLdd )
+            {
+            channelNumber += KIscMaxChannelsInLdd;
+            }
+        C_TRACE( ( _T( "DIscChannel::DoCreate channel=0x%x" ), channelNumber ) );
+        }
+
+    if ( channelNumber != KIscControlChannel )
+        {
+        TIscConfiguration config;
+        iIscDevice->iIscMultiplexerInterface->GetConfiguration( config );
+        TInt i( KErrNone );
+        iFrameRx = new TUint32*[config.channelRcvQueueSize];
+        ASSERT_RESET_ALWAYS( iFrameRx, "IscDriver",EIscMemoryAllocationFailure );
+        for ( i = KErrNone; i < config.channelRcvQueueSize; i++ )
+            {
+            iFrameRx[i] = 0;
+            }
+
+        iDataFrameRx = new TUint32*[config.channelDataRcvQueueSize];
+        ASSERT_RESET_ALWAYS( iDataFrameRx, "IscDriver",EIscMemoryAllocationFailure );
+        for ( i = KErrNone; i < config.channelDataRcvQueueSize; i++ )
+            {
+            iDataFrameRx[i] = 0;
+            }
+
+        // creating frame queue for incoming frames
+        iFrameRxQueue = new  DIscQueue( iFrameRx, config.channelRcvQueueSize );
+        ASSERT_RESET_ALWAYS( iFrameRxQueue, "IscDriver",EIscMemoryAllocationFailure );
+
+        // creating frame queue for incoming data frames
+        iDataFrameRxQueue = new  DIscQueue( iDataFrameRx, config.channelDataRcvQueueSize );
+        ASSERT_RESET_ALWAYS( iDataFrameRxQueue, "IscDriver",EIscMemoryAllocationFailure );
+    
+        // Flowcontrol marks for data frames
+        iIscChannelHighWaterMark = ( TUint16 )( ( ( ( TUint16 )config.channelDataRcvQueueSize ) * KMultiplyByThree ) / KDivideByFour );// 75% = multiply with 3, divide by 4 
+        iIscChannelLowWaterMark =  ( TUint16 )( ( ( ( TUint16 )config.channelDataRcvQueueSize ) * KMultiplyByOne ) / KDivideByFour );// 25% = multiply with 1, divide by 4 
+    
+        TRACE_ASSERT( iIscChannelHighWaterMark != 0 );
+        }
+
+#ifndef ISC_CHANNEL_SHARING_IN_USE
+    // Remove checking if channel already set to enable channel sharing
+    //Check if channel already set
+    if ( IscChannelContainer::Channel( channelNumber, 0 ) )
+        {
+        C_TRACE( ( _T( "DIscChannel::DoCreate channel 0x%x already set!!!!" ), channelNumber ) );
+        return KErrAlreadyExists;
+        }
+#endif //ISC_CHANNEL_SHARING_IN_USE
+
+    //Add itself to channel table.
+    TInt error = IscChannelContainer::SetChannel( ( DIscChannel* )this, channelNumber );
+    if ( KErrNone != error )
+        {
+        return error;
+        }
+
+    iChannelOpen = ETrue;
+    
+    // Store channel number.
+    iChannelNumber = channelNumber;    
+    SetDfcQ( Kern::DfcQue0() );
+    iMsgQ.Receive();
+    
+    return KErrNone;
+
+    }
+
+
+// -----------------------------------------------------------------------------
+// DIscChannel::NotifyFlowControl
+// Notify user side client that uplink flow control is on/off
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void DIscChannel::NotifyFlowControl
+        ( 
+        const TInt aFlowControlStatus
+        )
+    {
+    C_TRACE( ( _T( "DIscChannel::NotifyFlowControl(0x%x) iChannelNumber 0x%x channelPtr 0x%x" ), aFlowControlStatus, iChannelNumber, this ) );
+
+    iULFlowControlStatus = aFlowControlStatus;
+    if( iIscRequests[ EIscAsyncNotifyFlowControlStatus ]
+        && iIscFlowControlStatusPtr )
+        {
+        TPtr8 tempDes( reinterpret_cast<TUint8*>( &iULFlowControlStatus ), sizeof ( TInt ), sizeof ( TInt ) );
+        iLastNotifiedULFlowstatus = aFlowControlStatus;
+        TInt r = ThreadWrite( static_cast<TAny*>( iIscFlowControlStatusPtr ), &tempDes, 0 );
+        TRACE_ASSERT( r == KErrNone ); 
+        CompleteRequest( EIscAsyncNotifyFlowControlStatus, r );
+        }
+    else
+        {
+        C_TRACE( ( _T( "DIscChannel::NotifyFlowControl No request pending!" ) ) );        
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// DIscChannel::NotifyConnectionStatus
+// Notify user side client that connection status has changed
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void DIscChannel::NotifyConnectionStatus( 
+    const TInt aConnectionStatus ) 
+    {
+    C_TRACE( ( _T( "DIscChannel::NotifyConnectionStatus(0x%x) channelPtr 0x%x" ), aConnectionStatus, this ) );
+
+    if ( iIscRequests[EIscAsyncNotifyConnectionStatus] 
+         && iIscConnectionStatusPtr )
+        {
+        TInt temp = aConnectionStatus;
+        TPtr8 tempDes( ( TUint8* )&temp,sizeof ( TInt ),sizeof ( TInt ) );
+        TInt r = ThreadWrite( ( TAny* )iIscConnectionStatusPtr, &tempDes, 0 );
+        TRACE_ASSERT( r == KErrNone );
+
+        CompleteRequest( EIscAsyncNotifyConnectionStatus, r );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// DIscChannel::IsPending
+// Check if asynchronous request is active
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+TInt DIscChannel::IsPending( 
+    const TUint16 aReqNumber )
+    {
+    TInt error( KErrNone );
+    if ( iIscRequests[aReqNumber] )
+        {
+        error = KRequestPending;
+        }
+    else
+        {
+        // error is KErrNone
+        }
+    return error;
+    }
+// -----------------------------------------------------------------------------
+// DIscChannel::CompleteRequest
+// Function to complete clients pending asynchronous request
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void DIscChannel::CompleteRequest( 
+    TInt aOperation, 
+    TInt aCompleteStatus )
+    {
+    C_TRACE( ( _T( "DIscChannel::CompleteRequest(0x%x, 0x%x) iChannelNumber 0x%x channelPtr 0x%x" ), aOperation, aCompleteStatus, iChannelNumber, this ) );
+  
+    if ( aOperation < EIscAsyncLast )
+        {
+        
+        TRequestStatus* requestStatus = iIscRequests[aOperation];
+        if ( requestStatus )
+            {        
+            // In case of higher priority thread, set request to NULL from the request table before actual completing
+            iIscRequests[aOperation] = NULL;
+            Kern::RequestComplete( iThread, requestStatus, aCompleteStatus );
+            }
+        }
+    else
+        {
+        // Do nothing
+        }
+
+    C_TRACE( ( _T( "DIscChannel::CompleteRequest - return void" ) ) );
+
+    }
+
+// -----------------------------------------------------------------------------
+// DIscChannel::InitializeComplete
+// Initialization complete dfc
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void DIscChannel::InitializeComplete( 
+    TAny* aPtr )
+    {
+    C_TRACE( ( _T( "DIscChannel::InitializeComplete(0x%x)" ), aPtr ) );
+
+    DIscChannel* ThisPtr = ( DIscChannel* )aPtr;
+    if ( KErrNone == ThisPtr->iDataTransmissionErrorCode )
+        {        
+        ThisPtr->DoMultiplexerInitialize();
+        }
+    else
+        {
+        ThisPtr->CompleteRequest( EIscAsyncInitializeModemInterface, ThisPtr->iDataTransmissionErrorCode );
+        }
+    C_TRACE( ( _T( "DIscChannel::InitializeComplete - return 0x%x" ) ) );
+
+    }
+
+// -----------------------------------------------------------------------------
+// DIscChannel::DoMultiplexerInitialize
+// Completes the multiplexer initialization
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void DIscChannel::DoMultiplexerInitialize()
+    {
+    C_TRACE( ( _T( "DIscChannel::DoMultiplexerInitialize() channelPtr 0x%x" ), this ) );
+    
+    if ( iIscRequests[EIscAsyncInitializeModemInterface] )
+        {
+        
+        iIscDevice->iIscMultiplexerInterface->InitializeMultiplexer( 
+                EIscAsyncInitializeModemInterface, 
+                *iMultiplexerIniData,
+                this );
+        }
+
+    C_TRACE( ( _T( "DIscChannel::DoMultiplexerInitialize - return void" ) ) );
+    }
+
+// -----------------------------------------------------------------------------
+// DIscChannel::StoreFrame
+// Stores the incoming frame to channels receive queue
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void DIscChannel::StoreFrame( TDesC8* aData )
+    {
+    C_TRACE( ( _T( "DIscChannel::StoreFrame(0x%x) channelId 0x%x channelPtr 0x%x" ), aData, iChannelNumber, this ) );
+    
+    TInt error( KErrNone );
+
+    TIscFrameInfo frameInfo;
+    iIscDevice->iIscMultiplexerInterface->GetFrameInfo( *aData, frameInfo );
+
+    if ( frameInfo.frameType == EIscDataFrame )
+        {
+        C_TRACE( ( _T( "DIscChannel::StoreFrame dataFrame" ) ) );
+        error = iDataFrameRxQueue->Add( ( TAny* )aData );
+        if ( error == KErrNone )
+            {
+            if ( iDataFrameRxQueue->Count() >= iIscChannelHighWaterMark 
+                && iDLFlowControlStatus == EIscFlowControlOff )
+                {
+                iIscDevice->DLFlowControlNotify( EIscFlowControlOn, iChannelNumber, this );
+                iDLFlowControlStatus = EIscFlowControlOn;
+                }
+            else if ( iDataFrameRxQueue->Count() <= iIscChannelLowWaterMark 
+                     && iDLFlowControlStatus != EIscFlowControlOff )
+                {
+                iIscDevice->DLFlowControlNotify( EIscFlowControlOff, iChannelNumber, this );
+                iDLFlowControlStatus = EIscFlowControlOff;
+                }
+            else
+                {
+                // Do nothing
+                }
+            }
+        else
+            {
+            // Set overflow flag on. Complete next DataReceive with KErrOverFlow
+            TRACE_ASSERT_ALWAYS;
+            iOverFlow = ETrue;
+            iIscDevice->ReleaseMemoryBlock( ( TDes8* )aData );
+            }
+        }
+
+    else
+        {
+        C_TRACE( ( _T( "DIscChannel::StoreFrame controlFrame" ) ) );
+        error = iFrameRxQueue->Add( ( TAny* )aData );
+        if ( error != KErrNone )
+            {
+            C_TRACE( ( _T( "DIscChannel::StoreFrame() CONTROL FRAME OVERFLOW channel %d" ), iChannelNumber ) );
+            TRACE_ASSERT_ALWAYS;
+            iClientPanic = ETrue;
+            iIscDevice->ReleaseMemoryBlock( ( TDes8* )aData );
+            }
+        }
+
+    C_TRACE( ( _T( "DIscChannel::StoreFrame - return void" ) ) );
+    }
+
+// -----------------------------------------------------------------------------
+// DIscChannel::EmptyBuffers
+// Goes through channel's queue and delivers possible frame( s ) to client
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void DIscChannel::EmptyBuffers()
+    {    
+    C_TRACE( ( _T( "DIscChannel::EmptyBuffers() channelId 0x%x channelPtr 0x%x" ),iChannelNumber, this ) );
+
+    if ( iDataFrameRxQueue->NextBufferLength() > KErrNone )
+        {
+        TDes8* tempPtr = ( TDes8* ) iDataFrameRxQueue->GetFirst();
+        TIscFrameInfo frameInfo;
+        TInt desMaxLen( KErrNone );
+ 
+        iIscDevice->iIscMultiplexerInterface->GetFrameInfo( *tempPtr, frameInfo );
+        
+        // frame incoming, and datareceive request active
+        if ( iIscRequests[EIscAsyncDataReceive] && frameInfo.frameType == EIscDataFrame )             
+            {
+            if ( frameInfo.concatenation == EIscNoConcatenation )
+                {
+                desMaxLen = Kern::ThreadGetDesMaxLength( iThread, iDataReceiveBufPtr );                    
+
+                C_TRACE( ( _T( "DIscChannel::EmptyBuffers() data desMaxLen %d" ),desMaxLen ) );
+
+                TRACE_ASSERT( desMaxLen > KErrNone );
+                
+                // check that client's memory block is big enough
+                if ( desMaxLen >= frameInfo.writeLength )
+                    {
+                    // create a temporary descriptor for writing since we're
+                    // necessary not writing the whole contents of the 
+                    // source descriptor, only the part that ISC Multiplexer
+                    // wants
+                    TPtr8 writePtr( ( TUint8* )( tempPtr->Ptr() + frameInfo.writeStartIndex ),
+                                    frameInfo.writeLength,
+                                    frameInfo.writeLength );
+
+                    TInt r = ThreadWrite( iDataReceiveBufPtr, &writePtr, 0 );
+
+                    TRACE_ASSERT( r == KErrNone );
+                    
+                    // remove the pointer from queue and release the memory block 
+                    // but only if the ThreadWrite was successfull
+                    if  ( r == KErrNone )
+                        {
+                        iDataFrameRxQueue->DeleteFirst();
+                        iIscDevice->ReleaseMemoryBlock( tempPtr );
+                        if ( iOverFlow )
+                            {
+                            iOverFlow = EFalse;
+                            CompleteRequest( EIscAsyncDataReceive, KErrOverflow );
+                            }
+                        else
+                            {
+                            CompleteRequest( EIscAsyncDataReceive, KErrNone );
+                            }
+                        }
+                    else
+                        {
+                        C_TRACE( ( _T( "DIscChannel::EmptyBuffers() data ThreadWrite %d" ), r ) );
+                        CompleteRequest( EIscAsyncDataReceive, r );
+                        }
+                    }
+                // client buffer too small
+                else
+                    {
+                    TUint16 tempLen( frameInfo.writeLength );
+                    TPtr8 tempLenDes( ( TUint8* )&tempLen, sizeof ( TUint16 ), sizeof ( TUint16 ) );
+                    
+                    TInt r = ThreadWrite( ( TAny* )iNeededDataBufLen, &tempLenDes, 0 );
+                    TRACE_ASSERT( r == KErrNone );
+                    if ( r != KErrNone ) 
+                        {
+                        C_TRACE( ( _T( "DIscChannel::EmptyBuffers() data ThreadWrite %d" ), r ) );
+                        }
+                    
+                    CompleteRequest( EIscAsyncDataReceive, KErrNoMemory );
+                    }
+                }
+            else
+                {
+                HandleConcatenatedDataFrame( tempPtr, frameInfo );
+                }
+            }
+        }
+        // no frames in data queue
+    else
+        {
+        C_TRACE( ( _T( "DIscChannel::EmptyBuffers() channelId 0x%x channelPtr No frames in data queue" ), iChannelNumber, this ) );
+        }
+
+    // Check if there is frame in queue
+    if ( iFrameRxQueue->NextBufferLength() > KErrNone )
+        {
+        TDes8* tempPtr = ( TDes8* ) iFrameRxQueue->GetFirst();
+        TIscFrameInfo frameInfo;
+        TInt desMaxLen( KErrNone );
+ 
+        iIscDevice->iIscMultiplexerInterface->GetFrameInfo( *tempPtr, frameInfo );
+    
+        // frame incoming and normal receive request active
+        if ( iIscRequests[EIscAsyncReceive] && frameInfo.frameType == EIscNonDataFrame )
+            {
+            if ( frameInfo.concatenation == EIscNoConcatenation )
+                {
+                desMaxLen = Kern::ThreadGetDesMaxLength( iThread, iReceiveBufPtr );
+                
+                C_TRACE( ( _T( "DIscChannel::EmptyBuffers() desMaxLen %d" ),desMaxLen ) );
+
+                TRACE_ASSERT( desMaxLen > KErrNone );
+
+                // check that client's memory block is big enough
+                if ( desMaxLen >= frameInfo.writeLength )
+                    {
+                    // create a temporary descriptor for writing since we're
+                    // necessary not writing the whole contents of the 
+                    // source descriptor, only the part that ISC Multiplexer
+                    // wants
+                    TPtr8 writePtr( ( TUint8* )( tempPtr->Ptr() + frameInfo.writeStartIndex ),
+                                    frameInfo.writeLength,
+                                    frameInfo.writeLength );
+                    
+                    TInt r = ThreadWrite( iReceiveBufPtr, &writePtr, 0 );
+
+                    TRACE_ASSERT( r == KErrNone );
+                    
+                    // remove the pointer from queue and release the memory block 
+                    // but only if the ThreadWrite was successfull
+                    if ( r == KErrNone )
+                        {
+                        iFrameRxQueue->DeleteFirst();
+                        iIscDevice->ReleaseMemoryBlock( tempPtr );
+                        if ( iClientPanic )
+                            {
+                            iClientPanic = EFalse;
+                            CompleteRequest( EIscAsyncReceive, KErrOverflow );                            
+                            }
+                        else
+                            {
+                            CompleteRequest( EIscAsyncReceive, KErrNone );
+                            }
+                        }
+                    else
+                        {
+                        C_TRACE( ( _T( "DIscChannel::EmptyBuffers() ThreadWrite %d" ), r ) );
+                        CompleteRequest( EIscAsyncReceive, r );
+                        }
+                    }
+                // client buffer too small
+                else
+                    {
+                    TUint16 tempLen = frameInfo.writeLength;
+                    TPtr8 tempLenDes( ( TUint8* )&tempLen, sizeof ( TUint16 ), sizeof ( TUint16 ) );
+                    
+                    TInt r = ThreadWrite ( ( TAny* )iNeededBufLen, &tempLenDes, 0 );
+                    TRACE_ASSERT( r == KErrNone );
+                    if ( r != KErrNone ) 
+                        {
+                        C_TRACE( ( _T( "DIscChannel::EmptyBuffers() ThreadWrite %d" ), r ) );
+                        }
+                    
+                    CompleteRequest( EIscAsyncReceive, KErrNoMemory );
+                    }
+                }
+            else
+                {
+                HandleConcatenatedFrame( tempPtr, frameInfo );
+                }
+            }
+        }
+    // no frames in queue
+    else
+        {
+        C_TRACE( ( _T( "DIscChannel::EmptyBuffers() channelId 0x%x channelPtr 0x%x No frames in queue" ), iChannelNumber, this ) );
+        }
+
+    // If possible, set flow control off from data frame receiving
+    if ( iDataFrameRxQueue->Count() <= iIscChannelLowWaterMark 
+         && iDLFlowControlStatus != EIscFlowControlOff )
+        {
+        iIscDevice->DLFlowControlNotify( EIscFlowControlOff, iChannelNumber, this );
+        iDLFlowControlStatus = EIscFlowControlOff;
+        }
+        
+
+    C_TRACE( ( _T( "DIscChannel::EmptyBuffers - return void" ) ) );
+
+    }
+
+// -----------------------------------------------------------------------------
+// DIscChannel::HandleConcatenatedDataFrame
+// Copies several data frames to clients buffer if needed before compliting receive request
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void DIscChannel::HandleConcatenatedDataFrame( TDes8* aPtr, TIscFrameInfo& aInfo )
+    {
+    C_TRACE( ( _T( "DIscChannel::HandleConcatenatedDataFrame(0x%x, 0x%x) channelPtr 0x%x" ), aPtr, &aInfo, this ) );
+    TInt desMaxLen( KErrNone );
+    TInt desLen( KErrNone );
+    TUint16 totalLength( 0 );
+
+    desMaxLen = Kern::ThreadGetDesMaxLength( iThread, iDataReceiveBufPtr );
+    desLen = Kern::ThreadGetDesLength( iThread, iDataReceiveBufPtr );
+    
+    if ( aInfo.totalLength > KErrNone )
+        {
+        totalLength = aInfo.totalLength;
+        }
+    else
+        { 
+        totalLength = desMaxLen;
+        }
+    switch ( aInfo.concatenation )
+        {
+        // first frame of a larger data chunk
+        case EIscConcatenationDataStart:
+            {
+            // check whether the whole data amount will fit into the user buffer
+            if ( desMaxLen >= ( desLen + aInfo.writeLength ) && desMaxLen >= totalLength )
+                {
+                // create a temporary descriptor for writing since we're
+                // necessary not writing the whole contents of the 
+                // source descriptor, only the part that ISC Multiplexer
+                // wants
+                TPtr8 writePtr( ( TUint8* )( aPtr->Ptr() + aInfo.writeStartIndex ),
+                                aInfo.writeLength,
+                                aInfo.writeLength );
+                
+                // start writing the data at offset 0 since this is the first frame 
+                TInt r = ThreadWrite( iDataReceiveBufPtr, &writePtr, 0 );
+                    
+                // remove the pointer from queue and release the memory block 
+                // but only if the ThreadWrite was successfull
+                // we do not complete the user request until EIscConcatenationDataEnd
+                if ( r == KErrNone )
+                    {
+                    iDataFrameRxQueue->DeleteFirst();
+                    iIscDevice->ReleaseMemoryBlock( aPtr );
+                    }
+                else
+                    {
+                    C_TRACE( ( _T( "DIscChannel::HandleConcatenatedDataFrame() ThreadWrite %d" ), r ) );
+                    TRACE_ASSERT_ALWAYS;
+                    CompleteRequest( EIscAsyncDataReceive, KErrWrite );
+                    }
+                }            
+            else // buffer too small
+                {
+                TRACE_ASSERT( totalLength >= ( desLen + aInfo.writeLength ) );
+                TPtr8 tempLenDes( ( TUint8* )&totalLength, sizeof ( TUint16 ), sizeof ( TUint16 ) );
+                TInt r = ThreadWrite ( ( TAny* )iNeededDataBufLen, &tempLenDes, 0 );
+                TRACE_ASSERT( r == KErrNone );
+                if ( r != KErrNone ) 
+                    {
+                    C_TRACE( ( _T( "DIscChannel::HandleConcatenatedDataFrame() data start KErrNoMemory ThreadWrite %d" ), r ) );
+                    }
+                
+                CompleteRequest( EIscAsyncDataReceive, KErrNoMemory );
+                }
+            break;
+            }
+        case EIscConcatenationData:
+        case EIscConcatenationDataEnd:    
+            {
+            // check whether the next frame fits to the remaining buffer
+            if ( ( desMaxLen - desLen ) >= aInfo.writeLength ) 
+                {
+                // create a temporary descriptor for writing since we're
+                // necessary not writing the whole contents of the 
+                // source descriptor, only the part that ISC Multiplexer
+                // wants
+                TPtr8 writePtr( ( TUint8* )( aPtr->Ptr() + aInfo.writeStartIndex ),
+                                aInfo.writeLength,
+                                aInfo.writeLength );
+                
+                // start writing the data at offset desLen
+                TInt r = ThreadWrite( iDataReceiveBufPtr, &writePtr, desLen );
+                TRACE_ASSERT( r == KErrNone );
+                // remove the pointer from queue and release the memory block 
+                // but only if the ThreadWrite was successfull
+                if ( r == KErrNone ) 
+                    {
+                    iDataFrameRxQueue->DeleteFirst();
+                    iIscDevice->ReleaseMemoryBlock( aPtr );
+                    }                
+                else
+                    {                    
+                    C_TRACE( ( _T( "DIscChannel::HandleConcatenatedDataFrame() data ThreadWrite %d" ), r ) );
+                    }
+
+                // complete client request if the frame was the last one
+                if ( aInfo.concatenation == EIscConcatenationDataEnd )
+                    {
+                    if ( r == KErrNone )
+                        {
+                        CompleteRequest( EIscAsyncDataReceive, KErrNone );
+                         }
+                    else
+                        {
+                        CompleteRequest( EIscAsyncDataReceive, KErrWrite );
+                        }
+                    }
+                }
+            else
+                {
+                CompleteRequest( EIscAsyncDataReceive, KErrUnderflow );
+                }
+            break;
+            }
+        default:
+            {
+            ASSERT_RESET_ALWAYS( 0,"IscDriver",EIscNotAllowedCallToDoCancel );
+            break;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// DIscChannel::HandleConcatenatedFrame
+// Copies several frames to clients buffer if needed before compliting receive request
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void DIscChannel::HandleConcatenatedFrame( TDes8* aPtr, TIscFrameInfo& aInfo )
+    {
+    C_TRACE( ( _T( "DIscChannel::HandleConcatenatedFrame(0x%x, 0x%x) channelPtr 0x%x" ), aPtr, &aInfo, this ) );
+    TInt desMaxLen( 0 );
+    TInt desLen( 0 );
+    TUint16 totalLength( 0 );
+
+    desMaxLen = Kern::ThreadGetDesMaxLength( iThread, iReceiveBufPtr );
+    desLen = Kern::ThreadGetDesLength( iThread, iReceiveBufPtr );
+
+    if ( aInfo.totalLength > 0 )
+        {
+        totalLength = aInfo.totalLength;
+        }
+    else
+        { 
+        totalLength = desMaxLen;
+        }
+    switch ( aInfo.concatenation )
+        {
+        // first frame of a larger data chunk
+        case EIscConcatenationDataStart:
+            {
+            // check whether the whole data amount will fit into the user buffer
+            if ( desMaxLen >= ( desLen + aInfo.writeLength ) && desMaxLen >= totalLength )
+                {
+                // create a temporary descriptor for writing since we're
+                // necessary not writing the whole contents of the 
+                // source descriptor, only the part that ISC Multiplexer
+                // wants
+                TPtr8 writePtr( ( TUint8* )( aPtr->Ptr() + aInfo.writeStartIndex ),
+                                aInfo.writeLength,
+                                aInfo.writeLength );
+                
+                // start writing the data at offset 0 since this is the first frame 
+                TInt r = ThreadWrite( iReceiveBufPtr, &writePtr, 0 );
+                TRACE_ASSERT( r == KErrNone );
+                    
+                // remove the pointer from queue and release the memory block 
+                // but only if the ThreadWrite was successfull
+                // we do not complete the user request until EIscConcatenationDataEnd
+                if ( r == KErrNone )
+                    {
+                    iFrameRxQueue->DeleteFirst();
+                    iIscDevice->ReleaseMemoryBlock( aPtr );
+                    }
+                else 
+                    {
+                    C_TRACE( ( _T( "DIscChannel::HandleConcatenatedFrame() ThreadWrite %d" ), r ) );
+                    CompleteRequest( EIscAsyncReceive, KErrWrite );
+                    }
+                }
+            else // buffer too small
+                {
+                TRACE_ASSERT( totalLength >= ( desLen + aInfo.writeLength ) );
+                TPtr8 tempLenDes( ( TUint8* )&totalLength, sizeof ( TUint16 ), sizeof ( TUint16 ) );
+                TInt r = ThreadWrite ( ( TAny* )iNeededBufLen, &tempLenDes, 0 );
+                TRACE_ASSERT( r == KErrNone );
+                if ( r != KErrNone ) 
+                    {
+                    C_TRACE( ( _T( "DIscChannel::HandleConcatenatedFrame() ThreadWrite %d" ), r ) );
+                    }
+                
+                CompleteRequest( EIscAsyncReceive, KErrNoMemory );
+                }
+            break;
+            }
+        case EIscConcatenationData:
+        case EIscConcatenationDataEnd:    
+            {
+            // check whether the next frame fits to the remaining buffer
+            if ( ( desMaxLen - desLen ) >= aInfo.writeLength ) 
+                {
+                // create a temporary descriptor for writing since we're
+                // necessary not writing the whole contents of the 
+                // source descriptor, only the part that ISC Multiplexer
+                // wants
+                TPtr8 writePtr( ( TUint8* )( aPtr->Ptr() + aInfo.writeStartIndex ),
+                                aInfo.writeLength,
+                                aInfo.writeLength );
+                
+                // start writing the data at offset desLen
+                TInt r = ThreadWrite( iReceiveBufPtr, &writePtr, desLen );
+                
+                if ( r != KErrNone ) 
+                    {
+                    C_TRACE( ( _T( "DIscChannel::HandleConcatenatedFrame() ThreadWrite %d" ), r ) );
+                    }
+                // remove the pointer from queue and release the memory block 
+                // but only if the ThreadWrite was successfull
+                if ( r == KErrNone )
+                    {
+                    iFrameRxQueue->DeleteFirst();
+                    iIscDevice->ReleaseMemoryBlock( aPtr );
+                    }
+
+                // complete client request if the frame was the last one
+                if ( aInfo.concatenation == EIscConcatenationDataEnd )
+                    {
+                    if ( r == KErrNone )
+                        {
+                        CompleteRequest( EIscAsyncReceive, KErrNone );
+                         }
+                    else
+                        {
+                        CompleteRequest( EIscAsyncReceive, KErrWrite );
+                        }
+                    }
+                }
+            else
+                {
+                CompleteRequest( EIscAsyncDataReceive, KErrUnderflow );
+                }
+            break;
+            }
+        default:
+            {
+            ASSERT_RESET_ALWAYS( 0,"IscDriver",EIscUnknownCommand );
+            break;
+            }
+        }
+
+    }
+
+// -----------------------------------------------------------------------------
+// DIscChannel::CopyFromUserBuffer
+// Copy data from user-thread memory space.
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+TInt DIscChannel::CopyFromUserBuffer( 
+    const TDesC8& aUserBuffer,
+    TDes8& aKernelBuffer,
+    const TInt aOffset )
+    {
+    C_TRACE( ( _T( "DIscChannel::CopyFromUserBuffer(0x%x, 0x%x, 0x%x) channelPtr 0x%x" ), &aUserBuffer, &aKernelBuffer, aOffset, this ) );
+    return Kern::ThreadDesRead( iThread, ( TAny* )&aUserBuffer, aKernelBuffer, aOffset, KChunkShiftBy0 );
+
+    }
+
+// -----------------------------------------------------------------------------
+// DIscChannel::ThreadWrite
+// Writes data/frames to clients buffer
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+TInt DIscChannel::ThreadWrite( 
+    TAny* dest,
+    const TDesC8* src,
+    const TInt aOffset )
+    {
+    C_TRACE( ( _T( "DIscChannel::ThreadWrite(0x%x, 0x%x, 0x%x)" ), dest, src, aOffset ) );
+    C_TRACE( ( _T( "DIscChannel::ThreadWrite writeLen 0x%x" ), src->Length() ) );
+    
+    return Kern::ThreadDesWrite( iThread, dest, *src, aOffset, iThread ); 
+
+    }
+
+// -----------------------------------------------------------------------------
+// DIscChannel::ResetBuffers
+// Resets buffers
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void DIscChannel::ResetBuffers()
+    {
+    // Delete pending send frames
+    iIscDevice->CancelSending( iChannelNumber, this );
+
+    // Empty receive queue
+    if ( iFrameRxQueue )
+        {
+        while ( !iFrameRxQueue->Empty() )
+            {
+            TDes8* tempPtr = ( TDes8* ) iFrameRxQueue->GetFirst();
+            iFrameRxQueue->DeleteFirst();
+            iIscDevice->ReleaseMemoryBlock( tempPtr );
+            }
+        }
+    
+    // Empty data receive queue
+    if ( iDataFrameRxQueue )
+        {
+        while ( !iDataFrameRxQueue->Empty() )
+            {
+            TDes8* tempPtr = ( TDes8* ) iDataFrameRxQueue->GetFirst();
+            iDataFrameRxQueue->DeleteFirst();
+            iIscDevice->ReleaseMemoryBlock( tempPtr );
+            }
+        }
+    }
+
+//  End of File