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