--- /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