/*
* 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 "dpdatabuffer.h" // base class for rx and tx buffers
#include "dpdataelement.h" // data elements
#include "dpdataclient.h" // data client that access buffer
#include "dplog.h" // dataport logging
#include "OstTraceDefinitions.h"
#ifdef OST_TRACE_COMPILER_IN_USE
#include "dpdatabufferTraces.h"
#endif
// LOCAL FUNCTION PROTOTYPES
// none
// ==================== LOCAL FUNCTIONS ====================
// none
// ================= MEMBER FUNCTIONS =======================
// ---------------------------------------------------------
// CDpDataBuffer::CDpDataBuffer
// C++ default constructor.
// ---------------------------------------------------------
CDpDataBuffer::CDpDataBuffer(
const TInt aMaximumReservationSize,
const TInt aBufferInitialSize):
iRE(*this,CDpDataElement::EDeRead),
iWE(*this,CDpDataElement::EDeWrite),
iMaxReservationSize( aMaximumReservationSize ),
iBufferInitialSize( aBufferInitialSize )
{
OstTrace0( TRACE_NORMAL, CDPDATABUFFER_CDPDATABUFFER, "CDpDataBuffer::CDpDataBuffer" );
LOGM(" CDpDataBuffer::CDpDataBuffer");
}
// ---------------------------------------------------------
// CDpDataBuffer::ConstructL
// Symbian 2nd phase constructor.
// ---------------------------------------------------------
void CDpDataBuffer::ConstructL()
{
OstTrace0( TRACE_NORMAL, CDPDATABUFFER_CONSTRUCTL, "CDpDataBuffer::ConstructL" );
LOGM(" CDpDataBuffer::ConstructL");
iBufSize = iBufferInitialSize + iMaxReservationSize;
// obey configuration pbs+ebs in design document
iBuf=HBufC8::NewL( iBufSize );
// length to the max
iBuf->Des().SetLength( iBufSize );
iBuf->Des().Fill( KDpFillChar );
iTreshold = iBufferInitialSize;
}
// ---------------------------------------------------------
// CDpDataBuffer::NewL
// Static constructor.
// ---------------------------------------------------------
CDpDataBuffer* CDpDataBuffer::NewL(
const TInt aMaximumReservationSize,
const TInt aBufferInitialSize)
{
OstTrace0( TRACE_NORMAL, CDPDATABUFFER_NEWL, "CDpDataBuffer::NewL" );
LOGM(" CDpDataBuffer::NewL");
CDpDataBuffer* self = new (ELeave) CDpDataBuffer(
aMaximumReservationSize, aBufferInitialSize );
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop( self );
return self;
}
// ---------------------------------------------------------
// CDpDataBuffer::~CDpDataBuffer
// Destructor
// ---------------------------------------------------------
CDpDataBuffer::~CDpDataBuffer()
{
OstTrace0( TRACE_NORMAL, DUP1_CDPDATABUFFER_CDPDATABUFFER, "CDpDataBuffer::~CDpDataBuffer" );
LOGM(" CDpDataBuffer::~CDpDataBuffer");
if ( iBuf )
{
delete iBuf;
}
iReader = NULL;
iWriter = NULL;
}
// ---------------------------------------------------------
// CDpDataBuffer::SetLength
// This method sets length of buffer. This is called from
// CDpDataPort::SetReceiveBufferLength() method.
// ---------------------------------------------------------
//
TInt CDpDataBuffer::SetLength(
const TInt aLen)
{
OstTrace0( TRACE_NORMAL, CDPDATABUFFER_SETLENGTH, "CDpDataBuffer::SetLength" );
LOGM(" CDpDataBuffer::SetLength");
//Initialization
TInt max( 0 );
TInt ret( KErrNone );
if ( iHead + iWE.iSize > iEnd )
{
max = iHead + iWE.iSize;
}
else
{
max = iEnd;
}
OstTraceExt2( TRACE_NORMAL, DUP1_CDPDATABUFFER_SETLENGTH, "CDpDataBuffer:: iHead: %d, iWE.iSize: %d", iHead, iWE.iSize );
OstTraceExt2( TRACE_NORMAL, DUP2_CDPDATABUFFER_SETLENGTH, "CDpDataBuffer:: iEnd : %d, aLen : %d", iEnd, aLen );
LOG2(" iHead: %d, \t iWE.iSize: %d", iHead, iWE.iSize );
LOG2(" iEnd : %d, \t aLen : %d", iEnd, aLen );
if ( ( max >= ( aLen + iMaxReservationSize ) ) ||
( aLen < 2*iMaxReservationSize ) )
{
// buffer may be filled further than length
OstTrace0( TRACE_NORMAL, DUP3_CDPDATABUFFER_SETLENGTH, "CDpDataBuffer:: ERROR, Client tried to reserve too big or too small Receive Buffer Size" );
OstTraceExt2( TRACE_NORMAL, DUP4_CDPDATABUFFER_SETLENGTH, "CDpDataBuffer:: aLen: %d, iMaxReservationSize: %d", aLen, iMaxReservationSize );
OstTrace1( TRACE_NORMAL, DUP5_CDPDATABUFFER_SETLENGTH, "CDpDataBuffer:: max: %d", max );
LOG(" ERROR, Client tried to reserve too big or too small Receive Buffer Size");
LOG2(" aLen: %d, \t iMaxReservationSize: %d", aLen, iMaxReservationSize );
LOG1(" max: %d", max );
ret = KErrArgument;
}
else
{
iBuf->Des().SetLength( max );
HBufC8* tmp = NULL;
// ReAllocL returns address of the expanded or contracted HBufC descriptor.
// ReAllocL() leaves, if there is insufficient memory.
TRAP(ret, ( tmp = iBuf->ReAllocL( aLen+iMaxReservationSize ) ));
if ( KErrNone == ret )
{
iBuf=tmp;
iBuf->Des().SetLength( aLen + iMaxReservationSize );
iBufSize = aLen + iMaxReservationSize;
iTreshold = aLen;
}
}
return ret;
}
// ---------------------------------------------------------
// CDpDataBuffer::RegisterDataClient
// This method registers data client to the buffer.
// ---------------------------------------------------------
//
TInt CDpDataBuffer::RegisterDataClient(
MDpDataClient& aClient )
{
OstTrace0( TRACE_NORMAL, CDPDATABUFFER_REGISTERDATACLIENT, "CDpDataBuffer::RegisterDataClient" );
LOGM(" CDpDataBuffer::RegisterDataClient");
TInt ret( KErrNone );
switch ( aClient.Role() )
{
case EDbReader:
{
if ( iReader )
{
LOG(" CDpDataBuffer::RegisterDataClient, iReader already exists");
OstTrace0( TRACE_NORMAL, DUP1_CDPDATABUFFER_REGISTERDATACLIENT, "CDpDataBuffer:: iReader already exists" );
ret = KErrGeneral;
}
else
{
iReader = &aClient;
}
break;
}
case EDbWriter:
{
if ( iWriter )
{
LOG(" CDpDataBuffer::RegisterDataClient, iWriter already exists");
OstTrace0( TRACE_NORMAL, DUP2_CDPDATABUFFER_REGISTERDATACLIENT, "CDpDataBuffer:: iWriter already exists" );
ret = KErrGeneral;
}
else
{
iWriter = &aClient;
}
break;
}
default:
{
LOG(" CDpDataBuffer::RegisterDataClient, default, return KErrGeneral");
OstTrace0( TRACE_NORMAL, DUP3_CDPDATABUFFER_REGISTERDATACLIENT, "CDpDataBuffer:: default, return KErrGeneral" );
ret = KErrGeneral;
break;
}
}
return ret;
}
// ---------------------------------------------------------
// CDpDataBuffer::UsedBytes
// This method gets the amount of used bytes.
// Note that when virtual circular buffer has wrapped around
// there might be iTailWhenWrappedAround > 0 and therefore we
// have to notice that also in calculation. Normally
// iTailWhenWrappedAround == 0.
//
// In other words: When we have data in ebs (enhanced buffer
// space) we have to calculate it too. When
// iTailWhenWrappedAround>0 iTail==0.
//
// t h twr
// | | n |
// |-------pbs--------|--ebs--|
//
// ---------------------------------------------------------
//
TInt CDpDataBuffer::UsedBytes()
{
OstTrace0( TRACE_NORMAL, CDPDATABUFFER_USEDBYTES, "CDpDataBuffer::UsedBytes" );
LOGM(" CDpDataBuffer::UsedBytes");
TInt ret( 0 );
if ( iHead != iTail )
{
if ( iHead > ( iTail + iTailWhenWrappedAround ) )
{
ret = iHead - iTail;
}
else
{
ret = iEnd - iTail - iTailWhenWrappedAround + iHead;
}
}
return ret;
}
// ---------------------------------------------------------
// CDpDataBuffer::FreeBytes
// This method gets the amount of free bytes.
// ---------------------------------------------------------
//
TInt CDpDataBuffer::FreeBytes()
{
OstTrace0( TRACE_NORMAL, CDPDATABUFFER_FREEBYTES, "CDpDataBuffer::FreeBytes" );
LOGM(" CDpDataBuffer::FreeBytes");
return ( iBufSize - UsedBytes() - iMaxReservationSize );
}
// ---------------------------------------------------------
// CDpDataBuffer::Flush
// This method empties the buffer and notifies waiting reader
// and writer about the flush.
// ---------------------------------------------------------
//
void CDpDataBuffer::Flush()
{
OstTrace0( TRACE_NORMAL, CDPDATABUFFER_FLUSH, "CDpDataBuffer::Flush" );
LOGM(" CDpDataBuffer::Flush");
// throw reader out
//signal waiting reader
if ( iIsReaderWaiting && iReader )
{
iReader->FlushNotify();
iIsReaderWaiting = EFalse;
}
// throw writer out
//signal waiting writer
if ( iIsWriterWaiting && iWriter )
{
iWriter->FlushNotify();
iIsWriterWaiting = EFalse;
}
// As (currently) data accesses to buffer are synchronous, there can be no
// data client accessing the buffer.
iEnd = 0;
iHead = 0;
iTail = 0;
iTailWhenWrappedAround = 0;
iBuf->Des().Fill( KDpFillChar );
}
//=============================================================================
// OTHER EXPORTED FUNCTIONS
// none
// End of File