adaptationlayer/dataport/dataport_csy/src/dpdte2tx.cpp
changeset 0 63b37f68c1ce
child 5 8ccc39f9d787
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/adaptationlayer/dataport/dataport_csy/src/dpdte2tx.cpp	Fri Nov 06 17:28:23 2009 +0000
@@ -0,0 +1,480 @@
+/*
+* 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 "dpdte2tx.h"     // moves data from client to tx buffer
+#include "dpflowctrl.h"   // flow control handling
+#include "dpdataconfig.h" // configuration store
+#include "dpescdetect.h"  // escape sequence detection
+#include "dprx2dte.h"     // moves data from rx buffer to client
+#include "dplog.h"        // dataport logging
+#include "osttracedefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "dpdte2txtraces.h"
+#endif
+
+// LOCAL FUNCTION PROTOTYPES
+// none
+
+// ==================== LOCAL FUNCTIONS ====================
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CDpDte2Tx::CDpDte2Tx
+// C++ default constructor.
+// ---------------------------------------------------------
+CDpDte2Tx::CDpDte2Tx(
+    CDpDataPort& aDataPort ) :
+    CActive( KDpDte2TxPriority ),
+    iDataPort( aDataPort ),
+    iBufferTx( iDataPort.Tx() ),
+    iFlowCtrl( iDataPort.FlowCtrl() ),
+    iEscDetect( iDataPort.EscDetect() ),
+    iDataConfig( iDataPort.DataConfig() ),
+    iRx2Dte( iDataPort.Rx2Dte() ),
+    iTx( 0, 0 ),
+    iRequestActive( EFalse ),
+    iRole( MDpDataClient::EDbDataClientWriter )
+    {
+    OstTrace0( TRACE_NORMAL, CDPDTE2TX_CDPDTE2TX, "CDpDte2Tx::CDpDte2Tx" );
+    LOGM(" CDpDte2Tx::CDpDte2Tx");
+    }
+
+// ---------------------------------------------------------
+// CDpDte2Tx::ConstructL
+// Symbian 2nd phase constructor.
+// ---------------------------------------------------------
+void CDpDte2Tx::ConstructL()
+    {
+    OstTrace0( TRACE_NORMAL, CDPDTE2TX_CONSTRUCTL, "CDpDte2Tx::ConstructL" );
+    LOGM(" CDpDte2Tx::ConstructL");
+
+    //  initialise inner observer object
+    iDpDte2TxFcObserver.Init(this);
+
+    // register to FlowCtrl as observer
+    iFlowCtrl.Attach( iDpDte2TxFcObserver );
+
+    // If registering fails => can't do nothing here => must leave
+    User::LeaveIfError( iBufferTx.RegisterDataClient( *this ) );
+
+    CActiveScheduler::Add( this );
+    }
+
+// ---------------------------------------------------------
+// CDpDte2Tx::NewL
+// Static constructor.
+// ---------------------------------------------------------
+CDpDte2Tx* CDpDte2Tx::NewL(
+    CDpDataPort& aDataPort )
+    {
+    OstTrace0( TRACE_NORMAL, CDPDTE2TX_NEWL, "CDpDte2Tx::NewL" );
+    LOGM(" CDpDte2Tx::NewL");
+
+    CDpDte2Tx* self = new ( ELeave ) CDpDte2Tx( aDataPort );
+
+    CleanupStack::PushL( reinterpret_cast< CActive* > ( self ) );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+
+    return self;
+    }
+
+// ---------------------------------------------------------
+// CDpDte2Tx::~CDpDte2Tx
+// Destructor
+// ---------------------------------------------------------
+CDpDte2Tx::~CDpDte2Tx()
+    {
+    OstTrace0( TRACE_NORMAL, DUP1_CDPDTE2TX_CDPDTE2TX, "CDpDte2Tx::~CDpDte2Tx" );
+    LOGM(" CDpDte2Tx::~CDpDte2Tx");
+
+    iPendingClientBuffer = 0;
+
+    // unregister from FlowCtrl as observer
+    iFlowCtrl.Detach( iDpDte2TxFcObserver );
+    }
+
+// ---------------------------------------------------------
+// CDpDte2Tx::WriteTx
+// This method puts write pending and signals itself
+// (Dte2Tx).
+// ---------------------------------------------------------
+//
+TInt CDpDte2Tx::WriteTx(
+    const TAny* aClientBuffer,
+    const TInt aLength)
+    {
+    OstTrace0( TRACE_NORMAL, CDPDTE2TX_WRITETX, "CDpDte2Tx::WriteTx" );
+    OstTrace1( TRACE_NORMAL, DUP1_CDPDTE2TX_WRITETX, "CDpDte2Tx:: Port: %u", iDataPort.PortUnit() );
+
+    LOGM1("CDpDte2Tx::WriteTx - Port %d", iDataPort.PortUnit() );
+
+    TInt ret( KErrNone );
+
+    if ( iWritePending )
+        {
+        //double write
+        ret = KErrWrite;
+        }
+    else if ( 0 > aLength  )
+        {
+        //underflow
+        ret = KErrArgument;
+        }
+    else if ( 0 != aLength )
+        {
+        // store pointer of client buffer
+        iPendingClientBuffer = ( TAny* ) aClientBuffer;
+        iPendingLength = aLength;
+
+        iWritePending = ETrue;
+
+        if ( !IsActive() )
+            {
+            iRequestActive = ETrue;
+            iStatus = KRequestPending;
+            SetActive();
+            }
+        //no else
+
+        iDataPort.SignalDte2Tx();
+        ret = KErrNotReady;
+        }
+
+    return ret;
+    }
+
+// ---------------------------------------------------------
+// CDpDte2Tx::RunL
+// This method handles write operation after signalling.
+// ---------------------------------------------------------
+//
+void CDpDte2Tx::RunL()
+    {
+    OstTrace0( TRACE_NORMAL, CDPDTE2TX_RUNL, "CDpDte2Tx::RunL" );
+    OstTrace1( TRACE_NORMAL, DUP1_CDPDTE2TX_RUNL, "CDpDte2Tx::RunL %x", &iDataPort );
+    OstTrace1( TRACE_NORMAL, DUP2_CDPDTE2TX_RUNL, "CDpDte2Tx:: Port: %u", iDataPort.PortUnit() );
+
+    LOGM1("CDpDte2Tx::RunL %x", &iDataPort);
+    LOGM1("CDpDte2Tx::RunL - Port %d", iDataPort.PortUnit() );
+
+    if ( iWritePending && iStatus != KErrCancel )
+        {
+        // check linefail
+        TCommRole role;
+        iDataPort.GetRole( role );
+        if ( iDataConfig.IsLineFail( role ) )
+            {
+            LOG(" ERROR, Dte2Tx::RunL, Dte write completed with LINE FAIL.");
+            OstTrace0( TRACE_NORMAL, DUP3_CDPDTE2TX_RUNL, "ERROR, Dte2Tx::RunL, Dte write completed with LINE FAIL." );
+
+            iDataPort.WriteCompleted( KErrCommsLineFail );
+            iWritePending = EFalse;
+            iPendingClientBuffer = 0;
+            iPendingLength = 0;
+            }
+        else if ( iDataConfig.IsEchoDte() &&
+            ( iPendingLength - iIPCReadOffset ) > iRx2Dte.EchoBytesFreeSpace() )
+            {
+            if ( !IsActive() )
+                {
+                iRequestActive = ETrue;
+                iStatus = KRequestPending;
+                SetActive();
+                }
+            //no else
+            }
+        else
+            {
+            // first take minimum of three elements
+            TInt clientLength( iPendingLength - iIPCReadOffset );
+            TInt freeBytes( iBufferTx.FreeBytes() );
+            TInt len( 0 );
+
+            if ( clientLength >= iBufferTx.MaxReservationSize() )
+                {
+                len = iBufferTx.MaxReservationSize();
+                }
+            else
+                {
+                len = clientLength;
+                }
+
+            if ( freeBytes > 0 )
+                {
+                if (len >= freeBytes)
+                    {
+                    len = freeBytes;
+                    }
+                //no else
+                }
+            //no else
+
+            TPtr8 nullPtr( 0, 0 );
+            CDpDataElement& elem = iBufferTx.WriteElement();
+
+            TInt ret( elem.Reserve( len, iTx, nullPtr ) );
+
+            if ( ret != KErrNone)
+                {
+                if ( ret == KErrNotReady )
+                    {
+                    if ( !IsActive() )
+                        {
+                        iRequestActive = ETrue;
+                        iStatus = KRequestPending;
+                        SetActive();
+                        }
+                    //no else
+                    }
+                else
+                    {
+                    LOG1(" ErrorDte2Tx Tx element reservation failure! Id: %d",
+                        ret );
+                    OstTrace1( TRACE_NORMAL, DUP4_CDPDTE2TX_RUNL, "CDpDte2Tx:: ErrorDte2Tx Tx element reservation failure! Id: %d", ret );
+
+                    User::Leave( ret );
+                    }
+                }
+            else
+                {
+                // we suppose it's always either KErrNone or KErrNotReady ...
+                User::LeaveIfError( iDataPort.IPCRead(
+                    iPendingClientBuffer, iTx, iIPCReadOffset ) );
+
+                if ( iDataConfig.IsEchoDte() && 0 < iTx.Length() )
+                    {
+                    // configured to echo tx bytes
+                    iRx2Dte.EchoTx( iTx );
+                    }
+                //no else
+
+                iEscDetect.Scan( iTx );
+
+                // WasReaderWaiting is used to check if the reader was waiting
+                // for more data until it is being able to read. Otherwise it
+                // should signal to reader (Tx2Pn) that it can then read
+                TBool WasReaderWaiting = iBufferTx.IsReaderWaiting();
+
+                User::LeaveIfError( elem.Release( iTx.Length() ) );
+
+                iIPCReadOffset += iTx.Length();
+
+                // If reader was waiting for more data and got the enough,
+                // DPElement from Release will notify Reader using ReleaseNotify().
+                // WasReaderWaiting checks if Reader was waiting, if it is not,
+                // it should signal the reader to read the buffer.
+                if ( !WasReaderWaiting )
+                    {
+                    iDataPort.SignalTx2Pn();
+                    }
+                //no else
+
+                if ( iIPCReadOffset >= iPendingLength )
+                    {
+                    LOG(" Dte2Tx::RunL, Dte write completed.");
+                    OstTrace0( TRACE_NORMAL, DUP5_CDPDTE2TX_RUNL, "CDpDte2Tx:: Dte write completed" );
+
+                    iIPCReadOffset = 0;
+                    iDataPort.WriteCompleted( KErrNone );
+                    iWritePending = EFalse;
+                    iPendingClientBuffer = 0;
+                    iPendingLength = 0;
+                    }
+                else
+                    {
+                    if ( !IsActive() )
+                        {
+                        iRequestActive = ETrue;
+                        iStatus = KRequestPending;
+                        SetActive();
+                        }
+                    //no else
+                    iDataPort.SignalDte2Tx();
+                    }
+                }
+            }
+        }
+        //no else
+    }
+
+// ---------------------------------------------------------
+// CDpDte2Tx::RunError
+// Leave in RunL() is handled here. Error code is returned,
+// when internal error has occured.
+// ---------------------------------------------------------
+//
+TInt CDpDte2Tx::RunError(
+    TInt aError )
+    {
+    OstTrace0( TRACE_NORMAL, CDPDTE2TX_RUNERROR, "CDpDte2Tx::RunError" );
+    OstTraceExt2( TRACE_NORMAL, DUP1_CDPDTE2TX_RUNERROR, "CDpDte2Tx:: Port: %u, error code: %d", iDataPort.PortUnit(), aError );
+
+    LOGM2("CDpDte2Tx::RunError - Port %d, error code: %d",
+        iDataPort.PortUnit(), aError );
+
+    return aError;
+    }
+
+// ---------------------------------------------------------
+// CDpDte2Tx::UpDate
+// We are observer of FlowCtrl. E.g. when flow control
+// status changes, we are called.
+// ---------------------------------------------------------
+//
+void CDpDte2Tx::UpDate(
+    CDpSubject* /*aChangedSubject*/)
+    {
+    OstTrace0( TRACE_NORMAL, CDPDTE2TX_UPDATE, "CDpDte2Tx::UpDate" );
+    LOGM(" CDpDte2Tx::UpDate");
+
+    ReleaseNotify();
+    }
+
+// ---------------------------------------------------------
+// CDpDte2Tx::DoCancel
+// This method cancels this active object by
+// RequestComplete(). This method must be called directly
+// (not through Cancel()), when RunL() should be completed
+// with KErrCancel.
+// ---------------------------------------------------------
+//
+void CDpDte2Tx::DoCancel()
+    {
+    OstTrace0( TRACE_NORMAL, CDPDTE2TX_DOCANCEL, "CDpDte2Tx::DoCancel" );
+    LOGM(" CDpDte2Tx::DoCancel");
+
+    if ( iRequestActive )
+        {
+        iRequestActive = EFalse;
+        // do the required signaling
+        TRequestStatus* s=&iStatus;
+        User::RequestComplete( s, KErrCancel );
+        }
+    //no else
+    }
+
+// ---------------------------------------------------------
+// CDpDte2Tx::ReleaseNotify
+// This method signals ourselves (Dte2Tx).
+// ---------------------------------------------------------
+//
+void CDpDte2Tx::ReleaseNotify()
+    {
+    OstTrace0( TRACE_NORMAL, CDPDTE2TX_RELEASENOTIFY, "CDpDte2Tx::ReleaseNotify" );
+    LOGM(" CDpDte2Tx::ReleaseNotify");
+
+    // signal ourselves
+    if ( iRequestActive )
+        {
+        iRequestActive = EFalse;
+        TRequestStatus* status = &iStatus;
+
+        User::RequestComplete( status, KErrNone );
+        }
+    //no else
+    }
+
+// ---------------------------------------------------------
+// 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.
+// release this cactive object
+// ---------------------------------------------------------
+//
+void CDpDte2Tx::FlushNotify()
+    {
+    OstTrace0( TRACE_NORMAL, CDPDTE2TX_FLUSHNOTIFY, "CDpDte2Tx::FlushNotify" );
+    LOGM(" CDpDte2Tx::FlushNotify()");
+
+    ReleaseNotify();
+    }
+
+// ---------------------------------------------------------
+// CDpDte2Tx::Role
+// This method gets the role (reader/writer) of data client.
+// ---------------------------------------------------------
+//
+TUint8 CDpDte2Tx::Role()
+    {
+    OstTrace0( TRACE_NORMAL, CDPDTE2TX_ROLE, "CDpDte2Tx::Role" );
+    return iRole;
+    }
+
+// ---------------------------------------------------------
+// CDpDte2Tx::CancelWrite
+// This method is called by client via
+// CDpDataPort::WriteCancel(). Client want to cancel pending
+// write operation. C32 makes WriteCompleted to DTE -->
+// don't make it here at all.
+// Status : Proposal
+// ---------------------------------------------------------
+//
+void CDpDte2Tx::CancelWrite()
+    {
+    OstTrace0( TRACE_NORMAL, CDPDTE2TX_CANCELWRITE, "CDpDte2Tx::CancelWrite" );
+    LOGM(" CDpDte2Tx::CancelWrite");
+
+    if ( iWritePending )
+        {
+        iPendingClientBuffer = 0;
+        iPendingLength = 0;
+        iWritePending = EFalse;
+        iIPCReadOffset = 0;
+        iDataPort.SignalDte2Tx();
+        }
+    //no else
+    }
+
+// ---------------------------------------------------------
+// CDpDte2Tx::CDpDte2TxObserver::Init
+// This method initializes Dte2Tx observer.
+// ---------------------------------------------------------
+//
+void CDpDte2Tx::CDpDte2TxObserver::Init(
+    CDpDte2Tx* aDpDte2Tx )
+    {
+    iDpDte2Tx = aDpDte2Tx;
+    }
+
+// ---------------------------------------------------------
+// CDpDte2Tx::CDpDte2TxObserver::UpDate
+// This method updates Dte2Tx.
+// ---------------------------------------------------------
+//
+void CDpDte2Tx::CDpDte2TxObserver::UpDate(
+    CDpSubject* aChangedSubject )
+    {
+    LOG(" CDpDte2Tx::CDpDte2TxObserver::UpDate");
+
+    if ( iDpDte2Tx )
+        {
+        iDpDte2Tx->UpDate( aChangedSubject );
+        }
+    //no else
+    }
+
+// ================= OTHER EXPORTED FUNCTIONS ==============
+// none
+
+//  End of File