--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/adaptationlayer/dataport/dataport_csy/src/dprx2dte.cpp Fri Nov 06 17:28:23 2009 +0000
@@ -0,0 +1,961 @@
+/*
+* Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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:
+*
+*/
+
+
+
+// INCLUDE FILES
+#include "dpdef.h" // dataport definitions
+#include "dpdataport.h" // dataport main and c32 interface
+#include "dprx2dte.h" // moves data from rx buffer to client
+#include "dpbreak.h" // break handling
+#include "dpflowctrl.h" // flow control handling
+#include "dpdataconfig.h" // configuration store
+#include "dptermdetect.h" // terminator detection
+#include "dplog.h" // dataport logging
+#include "osttracedefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "dprx2dtetraces.h"
+#endif
+
+// EXTERNAL DATA STRUCTURES
+// none
+
+// EXTERNAL FUNCTION PROTOTYPES
+// none
+
+// CONSTANTS
+// none
+
+// MACROS
+// none
+
+// LOCAL CONSTANTS AND MACROS
+// none
+
+// MODULE DATA STRUCTURES
+// none
+
+// LOCAL FUNCTION PROTOTYPES
+// none
+
+// FORWARD DECLARATIONS
+// none
+
+// ============================= LOCAL FUNCTIONS ===============================
+// none
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::CDpRx2Dte
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CDpRx2Dte::CDpRx2Dte (
+ CDpDataPort& aDataPort ) :
+ CActive( KDpRx2DtePriority ),
+ iDataPort( aDataPort ),
+ iBufferRx( iDataPort.Rx() ),
+ iFlowCtrl( iDataPort.FlowCtrl() ),
+ iDataConfig( iDataPort.DataConfig() ),
+ iBreak( iDataPort.BreakHandler() ),
+ iTermDetect( iDataPort.TermDetect() ),
+ iRx( 0, 0 ),
+ iRxTail( 0, 0 ),
+ iRole( MDpDataClient::EDbDataClientReader )
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_CDPRX2DTE, "CDpRx2Dte::CDpRx2Dte" );
+ LOGM("CDpRx2Dte::CDpRx2Dte");
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CDpRx2Dte::ConstructL()
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_CONSTRUCTL, "CDpRx2Dte::ConstructL" );
+ LOGM("CDpRx2Dte::ConstructL");
+
+ // If registering fails => can't do nothing here => must leave
+ User::LeaveIfError( iBufferRx.RegisterDataClient( *this ) );
+
+ CActiveScheduler::Add( this );
+
+ if ( !IsActive() )
+ {
+ iStatus = KRequestPending;
+ iRequestActive = ETrue;
+ SetActive();
+ }
+ //no else
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CDpRx2Dte* CDpRx2Dte::NewL(
+ CDpDataPort& aDataPort )
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_NEWL, "CDpRx2Dte::NewL" );
+ LOGM("CDpRx2Dte::NewL");
+
+ CDpRx2Dte* self = new (ELeave) CDpRx2Dte( aDataPort );
+
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::~CDpRx2Dte
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CDpRx2Dte::~CDpRx2Dte()
+ {
+ OstTrace0( TRACE_NORMAL, DUP1_CDPRX2DTE_CDPRX2DTE, "CDpRx2Dte::~CDpRx2Dte" );
+ LOGM("CDpRx2Dte::~CDpRx2Dte");
+
+ iClientBuffer = 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::RunL
+// We are signalled from Pn2Rx or from ourselves (Rx2Dte).
+// Always when we are signalled there is data available to be written
+// into client space. This method also checks if RX flow control
+// 'water mark low' is reached and informs flow control handler about that.
+// -----------------------------------------------------------------------------
+//
+void CDpRx2Dte::RunL()
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_RUNL, "CDpRx2Dte::RunL" );
+ OstTrace1( TRACE_NORMAL, DUP1_CDPRX2DTE_RUNL, "CDpRx2Dte:: Port: %u", iDataPort.PortUnit() );
+
+ LOGM1("CDpRx2Dte::RunL - Port %d", iDataPort.PortUnit() );
+
+ if ( iStatus != KErrCancel )
+ {
+#ifdef _DEBUG
+ TInt ret( KErrNone );
+#endif
+
+ if ( 0 < iEchoData.Length() && iReadPending )
+ {
+ // Writes echo bytes to the client
+#ifdef _DEBUG
+ ret =
+#endif
+ WriteEchoToClient();
+ }
+ else if ( iReadPending )
+ {
+#ifdef _DEBUG
+ ret =
+#endif
+ WriteIntoClientSpace();
+ }
+ //no else
+
+#ifdef _DEBUG
+ if ( ret != KErrNone )
+ {
+ LOG(" ERROR, CDpRx2Dte::RunL, Writing echo bytes to the client");
+ OstTrace0( TRACE_NORMAL, DUP2_CDPRX2DTE_RUNL, "ERROR, CDpRx2Dte::RunL, Writing echo bytes to the client" );
+ }
+ //no else
+#endif
+
+ if ( !IsActive() )
+ {
+ iStatus = KRequestPending;
+ iRequestActive = ETrue;
+ SetActive();
+ }
+ //no else
+
+ if ( iReadPending &&
+ ( 0 < iBufferRx.UsedBytes() || 0 < iEchoData.Length() ) )
+ {
+ iDataPort.SignalRx2Dte();
+ }
+ //no else
+ }
+ //no else
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::RunError
+// Leave in RunL() is handled here. RunL() should not leave.
+// -----------------------------------------------------------------------------
+//
+TInt CDpRx2Dte::RunError(
+ TInt aError )
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_RUNERROR, "CDpRx2Dte::RunError" );
+ OstTraceExt2( TRACE_NORMAL, DUP1_CDPRX2DTE_RUNERROR, "CDpRx2Dte:: Port: %u, error code: %d", iDataPort.PortUnit(), aError );
+
+ LOGM2("CDpRx2Dte::RunError - Port %d, error code: %d",
+ iDataPort.PortUnit(), aError );
+
+ return aError;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::DoCancel
+// This method cancels this active object
+// -----------------------------------------------------------------------------
+//
+void CDpRx2Dte::DoCancel()
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_DOCANCEL, "CDpRx2Dte::DoCancel" );
+ LOGM("CDpRx2Dte::DoCancel");
+
+ if ( iRequestActive )
+ {
+ // do the required signaling
+ iRequestActive = EFalse;
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete( status, KErrCancel );
+ }
+ //no else
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::SetDteRead
+// This is forwarded client StartRead().
+// -----------------------------------------------------------------------------
+//
+TInt CDpRx2Dte::SetDteRead(
+ const TAny* aDes,
+ TInt aLength )
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_SETDTEREAD, "CDpRx2Dte::SetDteRead" );
+ LOGM("CDpRx2Dte::SetDteRead");
+
+ TInt ret( KErrNone );
+
+ // no pending read
+ if ( !iReadPending )
+ {
+ iReadPending = ETrue;
+
+ // pointer into client buffer
+ iClientBuffer = const_cast<TAny*>( aDes );
+ iClientRequestedLength = aLength;
+
+ if ( 0 > aLength )
+ {
+ // ReadOneOrMore
+ // C32 gives client buffer size as negative value
+ // see ECUART implementation
+ iClientBufferLength = -aLength;
+ }
+ else
+ {
+ iClientBufferLength = aLength;
+ }
+
+ // if there is data ready signal ourselves
+ if ( 0 < iBufferRx.UsedBytes() || 0 < iEchoData.Length() )
+ {
+ iDataPort.SignalRx2Dte();
+ }
+ //no else
+ }
+ else
+ {
+ // read twice attempted
+ ret = KErrInUse;
+ }
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::ResetDteRead
+// This is forwarded client made ReadCancel().
+// C32 makes ReadCompleted() to DTE --> don't make it here at all.
+// This is because DTE may have made timed read and when timer runs
+// out C32 wants to complete read by KErrTimedOut.
+// -----------------------------------------------------------------------------
+//
+TInt CDpRx2Dte::ResetDteRead()
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_RESETDTEREAD, "CDpRx2Dte::ResetDteRead" );
+ OstTrace1( TRACE_NORMAL, DUP1_CDPRX2DTE_RESETDTEREAD, "CDpRx2Dte:: Port: %u", iDataPort.PortUnit() );
+
+ LOGM1("CDpRx2Dte::ResetDteRead - Port %d", iDataPort.PortUnit() );
+
+ // reset pointer pointing into client space & its length
+ iReadPending = EFalse;
+ iClientBuffer = 0;
+ iClientBufferLength = 0;
+ iClientRequestedLength = 0;
+ iIPCWriteOffset = 0;
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::Write
+// Reserve read element and IPCWrite data to client space.
+// -----------------------------------------------------------------------------
+//
+TInt CDpRx2Dte::Write()
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_WRITE, "CDpRx2Dte::Write" );
+ OstTrace1( TRACE_NORMAL, DUP1_CDPRX2DTE_WRITE, "CDpRx2Dte:: Port: %u", iDataPort.PortUnit() );
+
+ LOGM1("CDpRx2Dte::Write - Port %d", iDataPort.PortUnit() );
+
+ TInt len( 0 );
+ TInt maxLen( 0 );
+ TInt ret( KErrNone );
+
+ TCommRole role;
+ iDataPort.GetRole( role );
+
+ // verify read pending, else do nothing
+ if ( !iReadPending )
+ {
+ ret = KErrNotReady;
+ }
+ // check line fail
+ else if ( iDataConfig.IsLineFail( role ) )
+ {
+ iDataPort.ReadCompleted( KErrCommsLineFail );
+ ResetDteRead();
+ }
+ else
+ {
+ // Find maximum length. i.e. which one is smaller our
+ // maximum reservation size or client buffer to write
+ // We can't write data over client buffer size -> smaller must be chocen
+ maxLen = FindMaximumLength();
+ // Lenght is count of bytes before break, but maximum maxLen or
+ // lenght is as much as possible, but maximum maxLen
+ len = FindLength( maxLen );
+
+ LOG1(" CDpRx2Dte::Write, Rx element reservation - len: %d", len );
+ OstTrace1( TRACE_NORMAL, DUP8_CDPRX2DTE_WRITE, "CDpRx2Dte:: Rx element reservation - len: %d", len );
+
+ // try reserve read element, if return success descriptors are
+ // set into buffer data
+ ret = iBufferRx.ReadElement().Reserve( len, iRx, iRxTail, ETrue );
+
+ switch ( ret )
+ {
+ case KErrNone:
+ {
+#ifdef _DEBUG
+ iTotalReceived = iTotalReceived + iRx.Length();
+
+ OstTrace1( TRACE_NORMAL, DUP2_CDPRX2DTE_WRITE, "CDpRx2Dte:: iBufferRx.UsedBytes = %d", iBufferRx.UsedBytes() );
+ OstTraceExt2( TRACE_NORMAL, DUP3_CDPRX2DTE_WRITE, "CDpRx2Dte:: len = %d, Total Received Bytes = %d", iRx.Length(), iTotalReceived );
+ OstTraceExt2( TRACE_NORMAL, DUP4_CDPRX2DTE_WRITE, "CDpRx2Dte:: Client buffer size = %d, DP Max. resv. size = %d", (iClientBufferLength - iIPCWriteOffset), iBufferRx.MaxReservationSize() );
+ OstTraceExt2( TRACE_NORMAL, DUP5_CDPRX2DTE_WRITE, "CDpRx2Dte:: Chosen maxLength = %d, Elem. reserved length = %d", maxLen, len );
+ OstTraceExt2( TRACE_NORMAL, DUP6_CDPRX2DTE_WRITE, "CDpRx2Dte:: iClientBufferLength = %d, iIPCWriteOffset = %d", iClientBufferLength, iIPCWriteOffset );
+ if( iRx.Length() > 0 )
+ {
+ OstTraceExt1( TRACE_NORMAL, DUP7_CDPRX2DTE_WRITE, "CDpRx2Dte:: RX = %s", iRx );
+ }
+ else
+ {
+ OstTrace0( TRACE_NORMAL, DUP12_CDPRX2DTE_WRITE, "CDpRx2Dte:: RX buffer empty" );
+ }
+
+ LOG1(" \tiBufferRx.UsedBytes() = %d", iBufferRx.UsedBytes() );
+ LOG2(" \tlen = %d, Total Received Bytes = %d",
+ iRx.Length(), iTotalReceived );
+ LOG2(" \tClient buffer size = %d, DP Max. resv. size = %d",
+ ( iClientBufferLength - iIPCWriteOffset ),
+ iBufferRx.MaxReservationSize() );
+ LOG2(" \tChocen maxLength = %d, Elem. reserved length = %d",
+ maxLen, len );
+ LOG2(" \tiClientBufferLength = %d, iIPCWriteOffset = %d",
+ iClientBufferLength, iIPCWriteOffset );
+ LOGHEX( iRx, EFalse );
+
+#endif
+ if ( iRxTail.Length() )
+ {
+ OstTrace1( TRACE_NORMAL, DUP9_CDPRX2DTE_WRITE, "CDpRx2Dte:: len tail = %d", iRxTail.Length() );
+ OstTraceExt1( TRACE_NORMAL, DUP10_CDPRX2DTE_WRITE, "CDpRx2Dte:: RXTail = %s", iRxTail );
+
+ LOG1(" \tlen tail = %d", iRxTail.Length() );
+ LOGHEX( iRxTail, EFalse );
+ }
+ //no else
+
+ // Write operation is handled here.
+ ret = MakeRx2DteWrite( len );
+ break;
+ }
+ case KErrNotReady:
+ {
+ // we are set active in RunL
+ // OBS: returning KErrNone
+ ret = KErrNone;
+ break;
+ }
+ default:
+ {
+ LOG1(" ERROR, CDpRx2Dte::Write Element reservation FAILED, error code: %d",
+ ret );
+ OstTrace1( TRACE_NORMAL, DUP11_CDPRX2DTE_WRITE, "ERROR, CDpRx2Dte::Write Element reservation FAILED, error code: %d", ret );
+
+ // returning error code. There's no need to leave because
+ // the error situation can be handeled.
+ }
+ }
+ }
+
+ // if there is still data in buffer we are signalled from
+ // 1. CDpRx2Dte::SetDteRead when client makes new read
+ // 2. from end of RunL when buffer has data and read is pending
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::ReleaseNotify
+// This method signals ourselves (Rx2Dte).
+// -----------------------------------------------------------------------------
+//
+void CDpRx2Dte::ReleaseNotify()
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_RELEASENOTIFY, "CDpRx2Dte::ReleaseNotify" );
+ LOG("CDpRx2Dte::ReleaseNotify");
+
+ // signal ourselves
+ if ( iRequestActive )
+ {
+ iRequestActive = EFalse;
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete( status, KErrNone );
+ }
+ //no else
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::FlushNotify
+// This method notifies that buffer is flushed. Classes which have access
+// to buffers are derived from this class. Derived class could override
+// this method, otherwise this default method will be used.
+// -----------------------------------------------------------------------------
+//
+void CDpRx2Dte::FlushNotify()
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_FLUSHNOTIFY, "CDpRx2Dte::FlushNotify" );
+ LOGM("CDpRx2Dte::FlushNotify()");
+
+ ReleaseNotify();
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::Role
+// This method gets the role (reader/writer) of data client.
+// -----------------------------------------------------------------------------
+//
+TUint8 CDpRx2Dte::Role()
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_ROLE, "CDpRx2Dte::Role" );
+ return iRole;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::SetBreakBytes
+// Set break bytes to be send before break. If no breakbytes
+// we can complete break notify right here.
+// -----------------------------------------------------------------------------
+//
+void CDpRx2Dte::SetBreakBytes(
+ const TInt aBreakBytes )
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_SETBREAKBYTES, "CDpRx2Dte::SetBreakBytes" );
+ LOGM("CDpRx2Dte::SetBreakBytes");
+
+ iBreakBytes = aBreakBytes;
+
+ if ( iBreakBytes > 0 )
+ {
+ // there is some data before break
+ iBreakPending = ETrue;
+ }
+ else
+ {
+ // data before break has sent
+ iDataPort.BreakNotifyCompleted( KErrNone );
+ iBreak.SetBreakNotify( EFalse );
+ iBreakPending = EFalse;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::EchoTx
+// We are requested to write TX data back to client buffer.
+// - Append echo data to small buffer.
+// - Signal ourselves to data be written into client space
+// -----------------------------------------------------------------------------
+//
+void CDpRx2Dte::EchoTx(
+ const TPtr8& aEchoData )
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_ECHOTX, "CDpRx2Dte::EchoTx" );
+ LOGM("CDpRx2Dte::EchoTx");
+
+ if ( EchoBytesFreeSpace() >= aEchoData.Length() )
+ {
+ iEchoData.Append( aEchoData );
+ ReleaseNotify();
+ }
+ //no else
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::EchoBytes
+// This method gets count of echo bytes.
+// -----------------------------------------------------------------------------
+TInt CDpRx2Dte::EchoBytes()
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_ECHOBYTES, "CDpRx2Dte::EchoBytes" );
+ LOGM("CDpRx2Dte::EchoBytes");
+
+ return iEchoData.Length();
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::EchoBytesFreeSpace
+// This method gets echo buffer's free space.
+// -----------------------------------------------------------------------------
+//
+TInt CDpRx2Dte::EchoBytesFreeSpace()
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_ECHOBYTESFREESPACE, "CDpRx2Dte::EchoBytesFreeSpace" );
+ LOGM("CDpRx2Dte::EchoBytesFreeSpace");
+
+ TInt space( iEchoData.MaxLength() - iEchoData.Length() );
+
+ if ( 0 > space )
+ {
+ space = 0;
+ }
+ //no else
+
+ return space;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::ResetEchoBytes
+// This method resets bytes from echo data.
+// -----------------------------------------------------------------------------
+//
+void CDpRx2Dte::ResetEchoBytes()
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_RESETECHOBYTES, "CDpRx2Dte::ResetEchoBytes" );
+ LOGM("CDpRx2Dte::ResetEchoBytes");
+
+ iEchoData.Zero();
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::WriteEchoToClient
+// Writes echo bytes back to client
+// -----------------------------------------------------------------------------
+//
+TInt CDpRx2Dte::WriteEchoToClient()
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_WRITEECHOTOCLIENT, "CDpRx2Dte::WriteEchoToClient" );
+ OstTrace1( TRACE_NORMAL, DUP1_CDPRX2DTE_WRITEECHOTOCLIENT, "CDpRx2Dte:: Port: %u", iDataPort.PortUnit() );
+
+ LOGM1("CDpRx2Dte::WriteEchoToClient - Port %d", iDataPort.PortUnit() );
+
+ TInt ret( KErrNone );
+ TInt spaceLeft( iClientBufferLength - iIPCWriteOffset );
+
+ LOG1(" Rx2Dte::WriteEchoToClient, Client buffer length: %d",
+ iClientBufferLength );
+ OstTrace1( TRACE_NORMAL, DUP2_CDPRX2DTE_WRITEECHOTOCLIENT, "CDpRx2Dte:: Client buffer length: %d", iClientBufferLength );
+
+ if ( iEchoData.Length() > spaceLeft )
+ {
+ // Avoid client buffer overflow when writing echo data
+ // (e.g. at-commands)
+ ret = iDataPort.IPCWrite(
+ iClientBuffer, iEchoData.Left(spaceLeft), iIPCWriteOffset );
+ // Move rest data to left
+ iEchoData.Copy( iEchoData.Mid( spaceLeft ) );
+ iIPCWriteOffset = iIPCWriteOffset + spaceLeft;
+ }
+ else
+ {
+ ret = iDataPort.IPCWrite( iClientBuffer, iEchoData, iIPCWriteOffset );
+ iIPCWriteOffset = iIPCWriteOffset + iEchoData.Length();
+ iEchoData.Zero();
+ }
+
+ if ( KErrNone != ret )
+ {
+ // Try to recover from write fail
+ iEchoData.Zero();
+
+ // Reset read
+ iReadPending = EFalse;
+ iStatus = KRequestPending;
+
+ if ( !IsActive() )
+ {
+ iStatus = KRequestPending;
+ iRequestActive = ETrue;
+ SetActive();
+ }
+ //no else
+
+ // Complete the read
+ iDataPort.ReadCompleted( ret );
+ ResetDteRead();
+ }
+ else
+ {
+ // We have space
+ iDataPort.SignalDte2Tx();
+
+ if ( ( 0 > iClientRequestedLength ) ||
+ ( iIPCWriteOffset >= iClientRequestedLength ) ||
+ ( iIPCWriteOffset >= iClientBufferLength ) )
+ {
+ // Complete the read in these situations:
+ // 1. ReadOneOrMore (iClientRequestedLength is then negative)
+ // 2. client requested length is full
+ // 3. client buffer is full
+ iDataPort.ReadCompleted( ret );
+ ResetDteRead();
+ }
+ //no else
+ }
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::WriteIntoClientSpace
+// Writes bytes into the client space
+// -----------------------------------------------------------------------------
+//
+TInt CDpRx2Dte::WriteIntoClientSpace()
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_WRITEINTOCLIENTSPACE, "CDpRx2Dte::WriteIntoClientSpace" );
+ LOGM1("CDpRx2Dte::WriteIntoClientSpace - Port %d", iDataPort.PortUnit() );
+
+ TInt ret( KErrNone );
+
+ // Write into client space
+ ret = Write();
+ if ( ret != KErrNone )
+ {
+ // Try to recover from write fail
+ iDataPort.ReadCompleted( ret );
+ ResetDteRead();
+
+ if ( !IsActive() )
+ {
+ iStatus = KRequestPending;
+ iRequestActive = ETrue;
+ SetActive();
+ }
+ //no else
+ }
+ else
+ {
+ // Is flowctrl on and rxBuffer "low watermark" reached
+ if ( iFlowCtrl.FlowCtrlDcs2Dp() == EFlowControlOn )
+ {
+ if ( iBufferRx.UsedBytes() <= iDataConfig.WaterMarkLowSize( iBufferRx ) )
+ {
+ // OK, now we have again space in buffer
+ LOG(" CDpRx2Dte::WriteIntoClientSpace, Rx Low WaterMarkReached.");
+ OstTrace0( TRACE_NORMAL, DUP1_CDPRX2DTE_WRITEINTOCLIENTSPACE, "CDpRx2Dte:: Rx Low WaterMark reached" );
+ iFlowCtrl.WaterMarkLowReached();
+ }
+ //no else
+ }
+ //no else
+ }
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::FindMaximumLength
+// Find maximum length i.e. which one is smaller: our maximum
+// reservation size or client buffer where we write. We can't
+// write data over client buffer size -> smaller must be chocen.
+// -----------------------------------------------------------------------------
+//
+TInt CDpRx2Dte::FindMaximumLength()
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_FINDMAXIMUMLENGTH, "CDpRx2Dte::FindMaximumLength" );
+ LOGM("CDpRx2Dte::FindMaximumLength");
+
+ TInt len( 0 );
+
+ if ( ( iClientBufferLength - iIPCWriteOffset ) >
+ iBufferRx.UsedBytes() )
+ {
+ len = iBufferRx.UsedBytes();
+ }
+ else
+ {
+ len = iClientBufferLength - iIPCWriteOffset;
+ }
+
+ return len;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::FindLength
+// This method returns amount of break bytes, if break is pending.
+// Amount of used bytes is returned, if break is not pending. If the
+// amount exceeds given length, the length is returned.
+// -----------------------------------------------------------------------------
+//
+TInt CDpRx2Dte::FindLength(
+ const TInt aMaxLen )
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_FINDLENGTH, "CDpRx2Dte::FindLength" );
+ LOGM("CDpRx2Dte::FindLength");
+
+ TInt len( 0 );
+
+ if ( iBreakPending )
+ {
+ // lenght is count of bytes before break, but maximum maxLen
+ if ( iBreakBytes <= aMaxLen )
+ {
+ len = iBreakBytes;
+ }
+ else
+ {
+ len = aMaxLen;
+ }
+ }
+ else
+ {
+ // lenght is as much as possible, but maximum maxLen
+ if ( iBufferRx.UsedBytes() <= aMaxLen )
+ {
+ len = iBufferRx.UsedBytes();
+ }
+ else
+ {
+ len = aMaxLen;
+ }
+ }
+
+ return len;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::MakeRx2DteWrite
+// Makes the actual write operation.
+// -----------------------------------------------------------------------------
+//
+TInt CDpRx2Dte::MakeRx2DteWrite(
+ const TInt aLen )
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_MAKERX2DTEWRITE, "CDpRx2Dte::MakeRx2DteWrite" );
+ OstTraceExt2( TRACE_NORMAL, DUP1_CDPRX2DTE_MAKERX2DTEWRITE, "CDpRx2Dte::MakeRx2DteWrite %x, Port: %u", (TUint)&iDataPort, iDataPort.PortUnit() );
+
+ LOGM2("CDpRx2Dte::MakeRx2DteWrite %x, Port %d",
+ &iDataPort, iDataPort.PortUnit() );
+
+ TInt ret( KErrNone );
+ TInt ind( 0 );
+ TInt termCount( iDataConfig.TerminatorCount() );
+
+ // There is data in rx buffer
+ if ( iRx.Length() )
+ {
+ // Scan terminator from iRx
+ if ( 0 < termCount )
+ {
+ ind = iTermDetect.Scan( iRx );
+ // terminator found
+ if ( 0 <= ind )
+ {
+ iRx.SetLength( ind + 1 );
+ iRxTail.SetLength( 0 );
+ }
+ //no else
+ }
+ //no else
+
+ // IPC write into client space
+ ret = iDataPort.IPCWrite( iClientBuffer, iRx, iIPCWriteOffset );
+ iIPCWriteOffset = iIPCWriteOffset + iRx.Length();
+
+ if ( KErrNone != ret )
+ {
+ LOG(" CDpRx2Dte::MakeRx2DteWrite, Rx element release (IPCWrite failed)");
+ OstTrace0( TRACE_NORMAL, DUP2_CDPRX2DTE_MAKERX2DTEWRITE, "CDpRx2Dte:: Rx element release (IPCWrite failed)" );
+
+ // Release element, because IPCWrite failed
+ TInt err ( iBufferRx.ReadElement().Release( 0 ) );
+
+ if ( KErrNone != err )
+ {
+ ret = err;
+ }
+ //no else
+
+ }
+ //no else
+ }
+ //no else
+
+ // Tail has a length, make the write in two pieces
+ if ( KErrNone == ret && iRxTail.Length() )
+ {
+ ret = WriteTail( ind, termCount );
+
+ iIPCWriteOffset = iIPCWriteOffset + iRxTail.Length();
+
+ if ( KErrNone != ret )
+ {
+ LOG(" CDpRx2Dte::MakeRx2DteWrite, Rx element release (IPCWrite failed)");
+ OstTrace0( TRACE_NORMAL, DUP3_CDPRX2DTE_MAKERX2DTEWRITE, "CDpRx2Dte:: Rx element release (IPCWrite failed)" );
+
+ // Release element, because IPCWrite failed
+ TInt err ( iBufferRx.ReadElement().Release( iRx.Length() ) );
+
+ if ( KErrNone == err )
+ {
+ iReadPending = EFalse;
+ }
+ else
+ {
+ ret = err;
+ }
+ }
+ //no else
+ }
+ //no else
+
+ if ( KErrNone == ret )
+ {
+ if ( ( 0 > iClientRequestedLength ) ||
+ ( 0 < termCount && 0 <= ind ) ||
+ ( iIPCWriteOffset >= iClientRequestedLength ) ||
+ ( iIPCWriteOffset >= iClientBufferLength ) )
+ {
+ // Complete the read in these situations:
+ // 1. ReadOneOrMore (iClientRequestedLength is then negative)
+ // 2. client uses terminated_read and terminator byte found
+ // 3. client requested length is full
+ // 4. client buffer is full
+ //
+ // (if terminator not found we don't complete read yet)
+ iDataPort.ReadCompleted( ret );
+ ResetDteRead();
+ }
+ //no else
+
+ // Release read element
+ OstTrace0( TRACE_NORMAL, DUP4_CDPRX2DTE_MAKERX2DTEWRITE, "CDpRx2Dte:: Rx element release" );
+ OstTrace1( TRACE_NORMAL, DUP5_CDPRX2DTE_MAKERX2DTEWRITE, "CDpRx2Dte:: Rx element release - iRx: %d", iRx.Length() );
+ OstTrace1( TRACE_NORMAL, DUP6_CDPRX2DTE_MAKERX2DTEWRITE, "CDpRx2Dte:: Rx element release - iRxTail: %d", iRxTail.Length() );
+
+ LOG(" CDpRx2Dte::MakeRx2DteWrite, Rx element release");
+ LOG1(" CDpRx2Dte::MakeRx2DteWrite, Rx element release - iRx: %d",
+ iRx.Length() );
+ LOG1(" CDpRx2Dte::MakeRx2DteWrite, Rx element release - iRxTail: %d",
+ iRxTail.Length() );
+
+ ret = iBufferRx.ReadElement().Release( iRx.Length() + iRxTail.Length() );
+ if ( KErrNone == ret )
+ {
+ // Reset descriptors
+ iRx.SetLength( 0 );
+ iRxTail.SetLength( 0 );
+
+ if ( iBreakPending )
+ {
+ iBreakBytes -= aLen;
+ if ( 0 == iBreakBytes )
+ {
+ iBreakPending = EFalse;
+ iDataPort.BreakNotifyCompleted( KErrNone );
+ iBreak.SetBreakNotify( EFalse );
+ }
+ //no else
+ }
+ //no else
+ }
+ }
+ //no else
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpRx2Dte::WriteTail
+// Writes the tail.
+// -----------------------------------------------------------------------------
+//
+TInt CDpRx2Dte::WriteTail(
+ TInt& aInd,
+ const TInt aTermCount )
+ {
+ OstTrace0( TRACE_NORMAL, CDPRX2DTE_WRITETAIL, "CDpRx2Dte::WriteTail" );
+ OstTrace1( TRACE_NORMAL, DUP1_CDPRX2DTE_WRITETAIL, "CDpRx2Dte:: Port: %u", iDataPort.PortUnit() );
+ OstTrace0( TRACE_NORMAL, DUP2_CDPRX2DTE_WRITETAIL, "CDpRx2Dte:: -------------- Write Rx Tail --------------" );
+
+ LOGM1("CDpRx2Dte::WriteTail - Port %d", iDataPort.PortUnit() );
+ LOG("-------------- Write Rx Tail --------------");
+
+ // scan terminator from iRxTail
+ if ( 0 < aTermCount )
+ {
+ aInd = iTermDetect.Scan( iRxTail );
+
+ // terminator found
+ if ( 0 <= aInd )
+ {
+ iRxTail.SetLength( aInd + 1 );
+ }
+ //no else
+ }
+ //no else
+
+ // we have to make two writes to client buffer. Second write starts
+ // from where first one ends --> offset = iRx.Length().
+ return ( iDataPort.IPCWrite( iClientBuffer, iRxTail, iIPCWriteOffset ) );
+ }
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+// none
+
+// End of File