diff -r 000000000000 -r 29b1cd4cb562 bthci/hci2implementations/hctls/bcsp/src/hctlbcspsequencer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bthci/hci2implementations/hctls/bcsp/src/hctlbcspsequencer.cpp Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,317 @@ +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// + +/** + @file + @internalComponent +*/ + +#include "hctlbcspsequencer.h" + +#include "hctlbcspFrameQueue.h" +#include "hctlbcsp.h" +#include "hctlbcspframe.h" +#include "hctlbcspconsts.h" +#include "hctlbcspsender.h" + +#include "debug.h" + +#include + + +#define MAX_RX_TIMEOUT_ALLOWED 5 +/** +Implementation of Class CHCTLBcspSequencer +*/ + +CHCTLBcspSequencer::CHCTLBcspSequencer(CHCTLBcsp& aHctlBcsp, CHCTLBcspFrameQueue& aBcspFrameQueue): + iRelRxState(EIdle), + iHctlBcsp(aHctlBcsp), + iFrameQueue(aBcspFrameQueue) + { + LOG_FUNC + } + +CHCTLBcspSequencer* CHCTLBcspSequencer::NewL(CHCTLBcsp &aHCTLBcsp, RBusDevComm& aPort, CHCTLBcspFrameQueue& aBcspFrameQueue) + { + LOG_STATIC_FUNC + + CHCTLBcspSequencer* self=new(ELeave) CHCTLBcspSequencer(aHCTLBcsp, aBcspFrameQueue); + CleanupStack::PushL(self); + self->ConstructL(aPort); + CleanupStack::Pop(); + return self; + } + +void CHCTLBcspSequencer::ConstructL(RBusDevComm& aPort) + { + LOG_FUNC + + TCallBack cb = TCallBack(CHCTLBcspSequencer::RxTimeout, this); + iRxAckTimer = CDelay::NewL(cb, CActive::EPriorityStandard); + + cb = TCallBack(CHCTLBcspSequencer::TxTimeout, this); + iTxAckTimer = CDelay::NewL(cb, CActive::EPriorityStandard); + + iSender = CHCTLBcspSender::NewL(*this,aPort); + } + +CHCTLBcspSequencer::~CHCTLBcspSequencer() + { + LOG_FUNC + + delete iRxAckTimer; + delete iTxAckTimer; + delete iSender; + } + +/** + Resets the BCSP sequencer to default state. +*/ +void CHCTLBcspSequencer::Reset() + { + LOG_FUNC + + iSender->Cancel(); + //reset rx variables + iRxAck = 0; + iRxSeq = 0; + iRxSeqExpected = 0; + iRxSeqLast = 0; + } + +/** + Called when a peer reset of BCSP is detected + Passes the notification up the BCSP stack for handling +*/ +void CHCTLBcspSequencer::HandlePeerReset() + { + LOG_FUNC + + iHctlBcsp.HandlePeerReset(); + } + +void CHCTLBcspSequencer::HandleRx(CRxHctlBcspFrame* aFrame) + { + LOG_FUNC + + iRelRxState = EReceiving; + + iRxSeqLast = iRxSeq; + iRxAck = aFrame->Ack(); + + if (aFrame->IsReliableProtcolType()) + { + iRxSeq=aFrame->Sequence(); + } + + +#ifdef __DEBUG_SEQ_Values__ + + LOG1(_L8("\tiRxAck value = %d"),iRxAck); + LOG1(_L8("\tiRxSeq value = %d"),iRxSeq); + LOG1(_L8("\tiRxSeqLast value = %d"),iRxSeqLast); + LOG1(_L8("\tiRxSeqExpected value = %d"),iRxSeqExpected); + LOG1(_L8("\tiTxAck value = %d"),iTxAck); +#endif + + // Call HandleRxAck() to process the Ack Value conveyed in the received frame header + HandleRxAck(); + + // Check if the received frame is unreliable and on the BCSP Link Establihsment channel + // If it is then route directly to the iHctlBcsp.PacketRouter() + if(!aFrame->IsReliableProtcolType() && aFrame->ProtocolId() == KBcspLinkChnl) //Route LE packets + { +#ifdef __DEBUG_SEQ_VERBOSE__ //Enable flogging for Sequencer + LOG(_L8("HCTLBCSP: CHCTLBcspSequencer::HandleRx() Pass LE Packet to LE Entity\n\n")); +#endif + iHctlBcsp.PacketRouter(); + return; + } + + // Otherwise the packet is reliable and passes into this switch statement + switch (iRelRxState) //Verify ProtocolId is valid and permissable + { + case EIdle: // Fall through. + case EReceiving: + { + if(iRxSeq == iRxSeqExpected && (iHctlBcsp.CheckIsAckPacket()==EFalse)) + { + iTxAck = static_cast ((iRxSeq+1)%8); + iRxSeqExpected = iTxAck; + iHctlBcsp.PacketRouter(); // Forward RxFrame to PacketRouter + } + //else drop the packet + StartTxAckTimer(); + } + break; + + default: + break; + }; + } + +void CHCTLBcspSequencer::SendNextPacket() +/** + This method attempts to send the next frame on the queue. +*/ + { + LOG_FUNC + + if(SendQueuedFrame() == KErrBcspMaxRetries) + { + HandlePeerReset(); + } + } + +TUint8 CHCTLBcspSequencer::TxAck() const + { + LOG_FUNC + + return iTxAck; + } + +void CHCTLBcspSequencer::HandleRxAck() + { + LOG_FUNC + + // An ACK has been received, so reset the Tx timeout counter + iRxTimeoutCount = 0; + // Returns ETrue if there are unacknowledged packets remaining + // in the window + if(iFrameQueue.AckReceived(iRxAck)) + { + StartRxAckTimer(); + } + else + { + iRxAckTimer->Cancel(); + } + } + +/*static*/ TInt CHCTLBcspSequencer::RxTimeout(TAny* aThis) + { + LOG_STATIC_FUNC + + reinterpret_cast(aThis)->HandleRxAckTimeout(); + + return KErrNone; + } + +void CHCTLBcspSequencer::SendPacket(TDesC8* aFrame, TBool aIsReliable) +/** + + This method writes @param aFrame and starts the RxAckTimer if @param aIsReliable + is ETrue +*/ + { + LOG_FUNC + + iSender->Write(*aFrame); + + if (aIsReliable) + { + StartRxAckTimer(); + } + } + +TInt CHCTLBcspSequencer::TxTimeout(TAny* aThis) + { + LOG_STATIC_FUNC + + reinterpret_cast(aThis)->TxAckMsg(); + + return KErrNone; + } + +void CHCTLBcspSequencer::TxAckMsg() + { + LOG_FUNC + + iHctlBcsp.TxAckMsg(); + } + +void CHCTLBcspSequencer::StartRxAckTimer() + { + LOG_FUNC + + iRxAckTimer->Cancel(); + iRxAckTimer->After(KRxAckTimeout); + } + +void CHCTLBcspSequencer::StartTxAckTimer() + { + LOG_FUNC + + if ( !iTxAckTimer->IsActive() ) + { + iTxAckTimer->After(KRxAckTimeout); + } + } + +void CHCTLBcspSequencer::HandleRxAckTimeout() + { + LOG_FUNC + + // Increment the Rx ACK Timeout counter + iRxTimeoutCount++; + iFrameQueue.AckTimeout(); + // While the maximum rx timeout allowed is not reached, rearm the timer + // waiting for the ACK. + // If the max is reached, we consider that the peer will not respond and + // has been poweroff. So, do not rearm the timer and reset the counter. + // Notice that the BC4 ship implements the same mechanism. + if (iRxTimeoutCount < MAX_RX_TIMEOUT_ALLOWED) + { + StartRxAckTimer(); + } + else + { + iRxTimeoutCount = 0; + } + } + +void CHCTLBcspSequencer::WakeUp() +/** + Method made available to trigger the TxStateMachine to do something + depending upon its current state +*/ + { + LOG_FUNC + if(!iSender->IsActive()) + { + SendNextPacket(); + } + } + +TInt CHCTLBcspSequencer::SendQueuedFrame() +/** + Method to get the Next Frame from the frame queue and then write it via + the SendPacket method +*/ + { + LOG_FUNC + + TDesC8* frame = NULL; + TBool isReliable = EFalse; + TInt err = iFrameQueue.GetNextFrame(frame,isReliable); + if (!err) + { + SendPacket(frame,isReliable); + } + return err; + } + +