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