--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/adaptationlayer/dataport/dataport_csy/src/dppn2rx.cpp Fri Nov 06 17:28:23 2009 +0000
@@ -0,0 +1,625 @@
+/*
+* 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 "dppn2rx.h" // moves data from isc api to rx buffer
+#include "dppif.h" // pipe interface (pif)
+#include "dpflowctrl.h" // flow control handling
+#include "dpdataconfig.h" // configuration store
+#include "dpparityhandler.h" // parity bit handling in 7-bit data mode
+#include "dplog.h" // dataport logging
+#include "osttracedefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "dppn2rxtraces.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 ===============================
+
+// -----------------------------------------------------------------------------
+// CDpPn2Rx::CDpPn2Rx
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CDpPn2Rx::CDpPn2Rx(
+ CDpDataPort& aDataPort ) :
+ CActive( KDpPn2RxPriority ),
+ iDataPort( aDataPort ),
+ iBufferRx( iDataPort.Rx() ),
+ iPifDcs( iDataPort.Pif() ),
+ iDataConfig( iDataPort.DataConfig() ),
+ iFlowCtrl( iDataPort.FlowCtrl() ),
+ iParityHandler( iDataPort.ParityHandler() ),
+ iRx( 0, 0 ),
+ iState( EElementWait ),
+ iInBufHasDataNotify( EFalse ),
+ iRequestActive( EFalse ),
+ iRole( MDpDataClient::EDbDataClientWriter )
+ {
+ OstTrace0( TRACE_NORMAL, CDPPN2RX_CDPPN2RX, "CDpPn2Rx::CDpPn2Rx" );
+ LOGM(" CDpPn2Rx::CDpPn2Rx");
+ }
+
+// -----------------------------------------------------------------------------
+// CDpPn2Rx::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CDpPn2Rx::ConstructL()
+ {
+ OstTrace0( TRACE_NORMAL, CDPPN2RX_CONSTRUCTL, "CDpPn2Rx::ConstructL" );
+ LOGM("CDpPn2Rx::ConstructL");
+
+ // initialise inner observer object
+ iDpPn2RxObserver.Init( this );
+ // register to PIF as observer
+ iPifDcs.Attach( iDpPn2RxObserver );
+ // If registering fails => can't do nothing here => must leave
+ User::LeaveIfError( iBufferRx.RegisterDataClient( *this ) );
+
+ CActiveScheduler::Add( this );
+ }
+
+// -----------------------------------------------------------------------------
+// CDpPn2Rx::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CDpPn2Rx* CDpPn2Rx::NewL(
+ CDpDataPort& aDataPort )
+ {
+ OstTrace0( TRACE_NORMAL, CDPPN2RX_NEWL, "CDpPn2Rx::NewL" );
+ LOGM("CDpPn2Rx::NewL");
+
+ CDpPn2Rx* self = new (ELeave) CDpPn2Rx( aDataPort );
+
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpPn2Rx::~CDpPn2Rx
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CDpPn2Rx::~CDpPn2Rx()
+ {
+ OstTrace0( TRACE_NORMAL, DUP1_CDPPN2RX_CDPPN2RX, "CDpPn2Rx::~CDpPn2Rx" );
+ LOGM("CDpPn2Rx::~CDpPn2Rx");
+ // unregister from PIF as observer
+ iPifDcs.Detach( iDpPn2RxObserver );
+ }
+
+// -----------------------------------------------------------------------------
+// CDpPn2Rx::RunL
+// This active object is signalled by Isc Api.
+// We will renew read to Isc Api.
+// -----------------------------------------------------------------------------
+//
+void CDpPn2Rx::RunL()
+ {
+ OstTrace0( TRACE_NORMAL, CDPPN2RX_RUNL, "CDpPn2Rx::RunL" );
+ OstTraceExt2( TRACE_NORMAL, DUP1_CDPPN2RX_RUNL, "CDpPn2Rx:: Port: %u, Status: %d", iDataPort.PortUnit(), iStatus.Int() );
+
+ LOGM2("CDpPn2Rx::RunL - Port %d, Status: %d ",
+ iDataPort.PortUnit(), iStatus.Int() );
+
+ iRequestActive = EFalse;
+ User::LeaveIfError( Read() );
+
+ // don't set iStatus nor set_active here as it is better done in functions
+ }
+
+// -----------------------------------------------------------------------------
+// CDpPn2Rx::RunError
+// Leave in RunL() is handled here. Error code is returned,
+// when internal error has occured.
+// -----------------------------------------------------------------------------
+//
+TInt CDpPn2Rx::RunError(
+ TInt aError )
+ {
+ OstTrace0( TRACE_NORMAL, CDPPN2RX_RUNERROR, "CDpPn2Rx::RunError" );
+ OstTraceExt2( TRACE_NORMAL, DUP1_CDPPN2RX_RUNERROR, "CDpPn2Rx:: Port: %u, error code: %d", iDataPort.PortUnit(), aError );
+
+ LOGM2("CDpPn2Rx::RunError - Port %d, error code: %d",
+ iDataPort.PortUnit(), aError );
+
+ return aError;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpPn2Rx::DoCancel
+// Cancels this active object and cancels pipe receive.
+// -----------------------------------------------------------------------------
+//
+void CDpPn2Rx::DoCancel()
+ {
+ OstTrace0( TRACE_NORMAL, CDPPN2RX_DOCANCEL, "CDpPn2Rx::DoCancel" );
+ LOGM("CDpPn2Rx::DoCancel");
+
+ switch ( iState )
+ {
+ case EDpReadWait:
+ {
+ if ( iRequestActive )
+ {
+ // cancel pipe
+ iDataPort.ISAHandle().DataReceiveCancel();
+
+ LOG(" CDpPn2Rx::DoCancel, Rx element release");
+ OstTrace0( TRACE_NORMAL, DUP1_CDPPN2RX_DOCANCEL, "CDpPn2Rx:: Rx element release" );
+
+ TInt ret = iBufferRx.WriteElement().Release( iRx.Length() );
+
+ if ( KErrNone == ret )
+ {
+#ifdef USE_FILE_SERIAL_TRUST_DEBUG
+ iDataPort.DebugBytesFromPn( iRx.Length() );
+#endif
+ if ( 0 < iRx.Length() )
+ {
+ // 7-bit data extract parity bits
+ if ( EData7 == iDataConfig.DataBits() )
+ {
+ iParityHandler.ExtractParityBits( iRx );
+ }
+ //no else
+
+ if ( iDataPort.IsRx2DteReadPending() )
+ {
+ // Signal RX2DTE
+ iDataPort.SignalRx2Dte();
+ }
+ //no else
+
+ // New data is available. is client interested about that
+ if ( iInBufHasDataNotify )
+ {
+ // We should notify client
+ iInBufHasDataNotify = EFalse;
+ iDataPort.NotifyDataAvailableCompleted( KErrNone );
+ }
+ //no else
+ }
+ //no else
+ }
+ else
+ {
+ // Element release couldn't be done. Can't leave here.
+ // Element remains reserved and something has gone totally
+ // wrong before release.
+ LOG(" ERROR, CDpPn2Rx::DoCancel, Element release failed");
+ OstTrace0( TRACE_NORMAL, DUP2_CDPPN2RX_DOCANCEL, "CDpPn2Rx:: Element release failed" );
+ }
+ //no else
+
+ // reset the state
+ iState = EDefault;
+ iRequestActive = EFalse;
+ }
+ //no else
+ break;
+ }
+ case EElementWait:
+ {
+ // Do not complete request if pipe is closed
+ if ( CDpPif::EDpPipeDisabled != iPifDcs.PipeState() &&
+ CDpPif::EDpPipeDisconnected != iPifDcs.PipeState() )
+ {
+ // do the required signaling
+ if ( iStatus == KRequestPending )
+ {
+ if ( iRequestActive )
+ {
+ // do the required signaling
+ iRequestActive = EFalse;
+ iState = EDefault;
+ TRequestStatus* s = &iStatus;
+ User::RequestComplete( s, KErrCancel );
+ }
+ //no else
+ }
+ //no else
+ }
+ //no else
+ break;
+ }
+ case EDefault:
+ {
+ break;
+ }
+ default:
+ {
+ LOG(" ERROR, CDpPn2Rx::DoCancel, Unknown iState");
+ OstTrace0( TRACE_NORMAL, DUP3_CDPPN2RX_DOCANCEL, "ERROR, CDpPn2Rx::DoCancel, Unknown iState" );
+ break;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CDpPn2Rx::Read
+// Reserves space from rx buffer and makes new PipeReceive
+// to Isc Api. Checks if flow control high water mark is reached.
+// Extracts paritybits if 7-bit data.Signals Rx2Dte.
+// -----------------------------------------------------------------------------
+//
+TInt CDpPn2Rx::Read()
+ {
+ OstTrace0( TRACE_NORMAL, CDPPN2RX_READ, "CDpPn2Rx::Read" );
+ OstTrace1( TRACE_NORMAL, DUP1_CDPPN2RX_READ, "CDpPn2Rx::Read %x", &iDataPort );
+ OstTraceExt2( TRACE_NORMAL, DUP2_CDPPN2RX_READ, "CDpPn2Rx:: (Read from ISC) - Port: %u, iRx.Length: %d", iDataPort.PortUnit(), iRx.Length() );
+
+ LOGM1("CDpPn2Rx::Read %x", &iDataPort);
+ LOGM2("CDpPn2Rx::Read (Read from ISC) - Port %d, iRx.Length: %d",
+ iDataPort.PortUnit(), iRx.Length() );
+
+ TInt ret( KErrNone );
+
+ // We've been listening pn_pipe
+ if ( EDpReadWait == iState )
+ {
+ LOGHEX(iRx, EFalse);
+ OstTraceExt1( TRACE_NORMAL, DUP10_CDPPN2RX_READ, "CDpPn2Rx:: RX = %s", iRx );
+
+ ret = iBufferRx.WriteElement().Release( iRx.Length() );
+
+ if ( KErrNone == ret )
+ {
+#ifdef USE_FILE_SERIAL_TRUST_DEBUG
+ iDataPort.DebugBytesFromPn( iRx.Length() );
+#endif
+ if ( 0 < iRx.Length() )
+ {
+ // 7-bit data extract parity bits
+ if ( EData7 == iDataConfig.DataBits() )
+ {
+ iParityHandler.ExtractParityBits( iRx );
+ }
+ //no else
+
+ if ( iDataPort.IsRx2DteReadPending() )
+ {
+ // Signal RX2DTE
+ iDataPort.SignalRx2Dte();
+ }
+ //no else
+
+ // New data is available. is client interested about that
+ if ( iInBufHasDataNotify )
+ {
+ // We should notify client
+ iInBufHasDataNotify = EFalse;
+ iDataPort.NotifyDataAvailableCompleted( KErrNone );
+ }
+ //no else
+ }
+ //no else
+ }
+ //no else
+ }
+ //no else
+
+ // Check pipe state
+ if ( KErrNone == ret && CDpPif::EDpPipeEnabled != iPifDcs.PipeState() )
+ {
+ ret = KErrNotReady;
+ }
+ else if ( KErrNone == ret )
+ {
+ // Try reserve element for writing
+ TPtr8 nullPtr( 0, 0 );
+
+ // Check if reserved buffer was too small
+ // => override MaxReservationSize for next read request.
+ if ( KErrNoMemory == iStatus.Int() &&
+ iLen > iBufferRx.MaxReservationSize() )
+ {
+ OstTrace0( TRACE_NORMAL, DUP4_CDPPN2RX_READ, "CDpPn2Rx::KErrNoMemory from ISC =>" );
+ OstTraceExt1( TRACE_NORMAL, DUP5_CDPPN2RX_READ, "CDpPn2Rx:: -- Try to read more than MaxReservationSize, %hu --", iLen );
+
+ LOG(" CDpPn2Rx::Read, KErrNoMemory from ISC =>");
+ LOG1(" -- Try to read more than MaxReservationSize, %d --", iLen );
+
+ ret = iBufferRx.WriteElement().Reserve(
+ iLen, iRx, nullPtr, ETrue );
+ // Set iLen to zero (required buffer lenght for read,
+ // received from ISC if buffer was too small)
+ iLen = 0;
+ }
+ else
+ {
+ ret = iBufferRx.WriteElement().Reserve(
+ iBufferRx.MaxReservationSize(), iRx, nullPtr );
+ }
+
+ // Is flowctrl off and rx "high watermark" reached
+ if ( EFlowControlOff == iFlowCtrl.FlowCtrlDcs2Dp() )
+ {
+ if ( IsHighWaterMarkReached() )
+ {
+ // Buffer is almost full set flowcontrol on
+ LOG(" CDpPn2Rx::Read, Rx High WaterMarkReached");
+ OstTrace0( TRACE_NORMAL, DUP6_CDPPN2RX_READ, "CDpPn2Rx:: Rx High WaterMark reached" );
+
+ iFlowCtrl.WaterMarkHighReached();
+ }
+ //no else
+ }
+ //no else
+
+ switch ( ret )
+ {
+ // Reservation successed
+ case KErrNone:
+ {
+ LOG1(" CDpPn2Rx::Read, ISAHandle Pipe Receive. iRx.MaxLength: %d",
+ iRx.MaxLength() );
+ OstTrace1( TRACE_NORMAL, DUP7_CDPPN2RX_READ, "CDpPn2Rx:: ISAHandle Pipe Receive. iRx.MaxLength: %d", iRx.MaxLength() );
+
+ // Set pipe receive
+ if ( !IsActive() )
+ {
+ iDataPort.ISAHandle().DataReceive( iStatus, iRx, iLen );
+
+ iRequestActive = ETrue;
+ // Change state
+ iState = EDpReadWait;
+
+ SetActive();
+ }
+ //no else
+ break;
+ }
+ // Reservation failed
+ case KErrNotReady:
+ {
+ LOG(" ERROR, CDpPn2Rx::Read, Element reservation failed (KErrNotReady).");
+ OstTrace0( TRACE_NORMAL, DUP8_CDPPN2RX_READ, "ERROR, CDpPn2Rx::Read, Element reservation failed (KErrNotReady)" );
+
+ // Change state
+ iState = EElementWait;
+ // Better done here
+ if ( !IsActive() )
+ {
+ iStatus = KRequestPending;
+ SetActive();
+ }
+ //no else
+ iRequestActive = ETrue;
+
+ ret = KErrNone;
+
+ break;
+ }
+ default:
+ {
+ // An error value returned
+ LOG1(" ERROR, CDpPn2Rx::Read, Fail to reserve Element, error code: %d",
+ ret );
+ OstTrace1( TRACE_NORMAL, DUP9_CDPPN2RX_READ, "CDpPn2Rx:: ERROR, CDpPn2Rx::Read, Fail to reserve Element, error code: %d", ret );
+ }
+ }
+ }
+ //no else
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpPn2Rx::UpDate
+// Pipe state has been changed.
+// -----------------------------------------------------------------------------
+//
+void CDpPn2Rx::UpDate(
+ CDpSubject* /*aChangedSubject*/ )
+ {
+ OstTrace0( TRACE_NORMAL, CDPPN2RX_UPDATE, "CDpPn2Rx::UpDate" );
+ LOGM("CDpPn2Rx::UpDate");
+
+ TInt r( KErrNone );
+ // DCS PIF state changed
+ switch ( iPifDcs.PipeState() )
+ {
+ case CDpPif::EDpPipeEnabled:
+ {
+ // start read but beware double read
+ if ( iState == EElementWait )
+ {
+ r = Read();
+ if ( r != KErrNone )
+ {
+ LOG(" ERROR, CDpPn2Rx::UpDate, Read() failed");
+ OstTrace0( TRACE_NORMAL, DUP1_CDPPN2RX_UPDATE, "ERROR, CDpPn2Rx::UpDate, Read() failed" );
+ }
+ //no else
+ }
+ //no else
+ break;
+ }
+ case CDpPif::EDpPipeDisabled: // Fall through
+ case CDpPif::EDpPipeDisconnected:
+ {
+ if ( IsActive() )
+ {
+ Cancel();
+ }
+ //no else
+ break;
+ }
+ default:
+ {
+ // Pipe is in state that is not regonized
+ LOG1(" ERROR, CDpPn2Rx::UpDate, Unrecognized pipe state: %d",
+ iPifDcs.PipeState() );
+ OstTraceExt1( TRACE_NORMAL, DUP2_CDPPN2RX_UPDATE, "ERROR, CDpPn2Rx::UpDate, Unrecognized pipe state: %s", iPifDcs.PipeState() );
+
+ Cancel();
+ break;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CDpPn2Rx::ReleaseNotify
+// This method signals ourselves.
+// -----------------------------------------------------------------------------
+//
+void CDpPn2Rx::ReleaseNotify()
+ {
+ OstTrace0( TRACE_NORMAL, CDPPN2RX_RELEASENOTIFY, "CDpPn2Rx::ReleaseNotify" );
+ LOGM("CDpPn2Rx::ReleaseNotify");
+
+ // This is done because receive data might me also active
+ DoCancel();
+ }
+
+// -----------------------------------------------------------------------------
+// CDpPn2Rx::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 CDpPn2Rx::FlushNotify()
+ {
+ OstTrace0( TRACE_NORMAL, CDPPN2RX_FLUSHNOTIFY, "CDpPn2Rx::FlushNotify" );
+ LOGM("CDpPn2Rx::FlushNotify()");
+
+ ReleaseNotify();
+ }
+
+// -----------------------------------------------------------------------------
+// CDpPn2Rx::Role
+// This method gets the role (reader/writer) of data client.
+// -----------------------------------------------------------------------------
+//
+TUint8 CDpPn2Rx::Role()
+ {
+ OstTrace0( TRACE_NORMAL, CDPPN2RX_ROLE, "CDpPn2Rx::Role" );
+
+ return iRole;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpPn2Rx::SetDataAvailableNotification
+// Set flag that indicates are requested to notify the C32
+// client, if there is data available in rx buffer.
+// -----------------------------------------------------------------------------
+//
+TInt CDpPn2Rx::SetDataAvailableNotification(
+ const TBool aUsedOrNot )
+ {
+ OstTrace0( TRACE_NORMAL, CDPPN2RX_SETDATAAVAILABLENOTIFICATION, "CDpPn2Rx::SetDataAvailableNotification" );
+ LOGM(" CDpPn2Rx::SetDataAvailableNotification");
+
+ iInBufHasDataNotify = aUsedOrNot;
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpPn2Rx::IsHighWaterMarkReached
+// Is high water mark reached
+// -----------------------------------------------------------------------------
+//
+TBool CDpPn2Rx::IsHighWaterMarkReached()
+ {
+ OstTrace0( TRACE_NORMAL, CDPPN2RX_ISHIGHWATERMARKREACHED, "CDpPn2Rx::IsHighWaterMarkReached" );
+ TBool waterMarkReached( EFalse );
+
+ if ( iBufferRx.UsedBytes() >= iDataConfig.WaterMarkHighSize( iBufferRx ) )
+ {
+ waterMarkReached = ETrue;
+ }
+ else
+ {
+ waterMarkReached = EFalse;
+ }
+
+ return waterMarkReached;
+ }
+
+//==============================================================================
+
+// -----------------------------------------------------------------------------
+// CDpPn2Rx::CDpPn2RxObserver::Init
+// This method initializes Pn2Rx observer.
+// -----------------------------------------------------------------------------
+//
+void CDpPn2Rx::CDpPn2RxObserver::Init(
+ CDpPn2Rx* aDpPn2Rx )
+ {
+ iDpPn2Rx = aDpPn2Rx;
+ }
+
+// -----------------------------------------------------------------------------
+// CDpPn2Rx::CDpPn2RxObserver::UpDate
+// This method updates Pn2Rx.
+// -----------------------------------------------------------------------------
+//
+void CDpPn2Rx::CDpPn2RxObserver::UpDate(
+ CDpSubject* aChangedSubject )
+ {
+ LOGM("CDpPn2Rx::CDpPn2RxObserver::UpDate");
+
+ if ( iDpPn2Rx )
+ {
+ iDpPn2Rx->UpDate( aChangedSubject );
+ }
+ //no else
+ }
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+// none
+
+// End of File