adaptationlayer/dataport/dataport_csy/src/dprx2dte.cpp
changeset 0 63b37f68c1ce
child 5 8ccc39f9d787
--- /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