--- /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 <bluetooth/hci/delay.h>
+
+
+#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 <TUint8>((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<CHCTLBcspSequencer*>(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<CHCTLBcspSequencer*>(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;
+ }
+
+