bthci/hci2implementations/hctls/bcsp/src/hctlbcspsequencer.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @internalComponent
       
    19 */
       
    20 
       
    21 #include "hctlbcspsequencer.h"
       
    22 
       
    23 #include "hctlbcspFrameQueue.h"
       
    24 #include "hctlbcsp.h"
       
    25 #include "hctlbcspframe.h"
       
    26 #include "hctlbcspconsts.h"
       
    27 #include "hctlbcspsender.h"
       
    28 
       
    29 #include "debug.h"
       
    30 
       
    31 #include <bluetooth/hci/delay.h>
       
    32 
       
    33 
       
    34 #define MAX_RX_TIMEOUT_ALLOWED			5
       
    35 /**
       
    36 Implementation of Class CHCTLBcspSequencer
       
    37 */
       
    38 
       
    39 CHCTLBcspSequencer::CHCTLBcspSequencer(CHCTLBcsp& aHctlBcsp, CHCTLBcspFrameQueue& aBcspFrameQueue):
       
    40 	iRelRxState(EIdle), 
       
    41 	iHctlBcsp(aHctlBcsp),
       
    42 	iFrameQueue(aBcspFrameQueue)
       
    43 	{
       
    44 	LOG_FUNC
       
    45 	}
       
    46 
       
    47 CHCTLBcspSequencer* CHCTLBcspSequencer::NewL(CHCTLBcsp &aHCTLBcsp, RBusDevComm& aPort, CHCTLBcspFrameQueue& aBcspFrameQueue)
       
    48 	{
       
    49 	LOG_STATIC_FUNC
       
    50 
       
    51 	CHCTLBcspSequencer* self=new(ELeave) CHCTLBcspSequencer(aHCTLBcsp, aBcspFrameQueue);
       
    52     CleanupStack::PushL(self);
       
    53     self->ConstructL(aPort);
       
    54     CleanupStack::Pop();
       
    55     return self;
       
    56 	}
       
    57 
       
    58 void CHCTLBcspSequencer::ConstructL(RBusDevComm& aPort)
       
    59     {
       
    60 	LOG_FUNC
       
    61 
       
    62 	TCallBack cb = TCallBack(CHCTLBcspSequencer::RxTimeout, this);
       
    63 	iRxAckTimer = CDelay::NewL(cb, CActive::EPriorityStandard);
       
    64 
       
    65 	cb = TCallBack(CHCTLBcspSequencer::TxTimeout, this);
       
    66 	iTxAckTimer = CDelay::NewL(cb, CActive::EPriorityStandard);
       
    67 
       
    68     iSender  = CHCTLBcspSender::NewL(*this,aPort);
       
    69     }
       
    70 
       
    71 CHCTLBcspSequencer::~CHCTLBcspSequencer()
       
    72 	{
       
    73 	LOG_FUNC
       
    74 
       
    75 	delete iRxAckTimer;
       
    76 	delete iTxAckTimer;
       
    77 	delete iSender;
       
    78 	}
       
    79 
       
    80 /**
       
    81   	Resets the BCSP sequencer to default state.
       
    82 */
       
    83 void CHCTLBcspSequencer::Reset()
       
    84  	{
       
    85 	LOG_FUNC
       
    86 
       
    87  	iSender->Cancel();
       
    88  	//reset rx variables
       
    89  	iRxAck = 0;
       
    90  	iRxSeq = 0;
       
    91  	iRxSeqExpected = 0;
       
    92  	iRxSeqLast = 0;
       
    93  	}
       
    94  
       
    95 /**
       
    96   	Called when a peer reset of BCSP is detected
       
    97  	Passes the notification up the BCSP stack for handling
       
    98 */
       
    99 void CHCTLBcspSequencer::HandlePeerReset()
       
   100  	{
       
   101 	LOG_FUNC
       
   102 
       
   103  	iHctlBcsp.HandlePeerReset();
       
   104  	}
       
   105  
       
   106 void CHCTLBcspSequencer::HandleRx(CRxHctlBcspFrame* aFrame)
       
   107 	{
       
   108 	LOG_FUNC
       
   109 
       
   110 	iRelRxState = EReceiving;
       
   111 
       
   112 	iRxSeqLast = iRxSeq;	
       
   113 	iRxAck = aFrame->Ack();
       
   114 	
       
   115 	if (aFrame->IsReliableProtcolType())
       
   116 		{
       
   117 		iRxSeq=aFrame->Sequence();
       
   118 		}
       
   119 
       
   120 
       
   121 #ifdef __DEBUG_SEQ_Values__
       
   122 
       
   123 	LOG1(_L8("\tiRxAck value = %d"),iRxAck);
       
   124 	LOG1(_L8("\tiRxSeq value = %d"),iRxSeq);
       
   125 	LOG1(_L8("\tiRxSeqLast value = %d"),iRxSeqLast);
       
   126 	LOG1(_L8("\tiRxSeqExpected value = %d"),iRxSeqExpected);
       
   127 	LOG1(_L8("\tiTxAck value = %d"),iTxAck);
       
   128 #endif
       
   129 
       
   130 	// Call HandleRxAck() to process the Ack Value conveyed in the received frame header
       
   131 	HandleRxAck();
       
   132 
       
   133 	// Check if the received frame is unreliable and on the BCSP Link Establihsment channel
       
   134 	// If it is then route directly to the iHctlBcsp.PacketRouter()
       
   135 	if(!aFrame->IsReliableProtcolType() && aFrame->ProtocolId() == KBcspLinkChnl) //Route LE packets
       
   136 		{
       
   137 #ifdef __DEBUG_SEQ_VERBOSE__ //Enable flogging for Sequencer
       
   138 		LOG(_L8("HCTLBCSP: CHCTLBcspSequencer::HandleRx() Pass LE Packet to LE Entity\n\n"));
       
   139 #endif
       
   140 		iHctlBcsp.PacketRouter();
       
   141 		return;
       
   142 		}
       
   143 
       
   144 	// Otherwise the packet is reliable and passes into this switch statement
       
   145 	switch (iRelRxState)	//Verify ProtocolId is valid and permissable
       
   146 		{
       
   147 		case EIdle: // Fall through.
       
   148 		case EReceiving:
       
   149 			{
       
   150 			if(iRxSeq == iRxSeqExpected && (iHctlBcsp.CheckIsAckPacket()==EFalse))
       
   151 				{
       
   152 				iTxAck = static_cast <TUint8>((iRxSeq+1)%8);
       
   153 				iRxSeqExpected = iTxAck;
       
   154 				iHctlBcsp.PacketRouter();	// Forward RxFrame to PacketRouter
       
   155 				}
       
   156 			//else drop the packet
       
   157 			StartTxAckTimer();
       
   158 			}
       
   159 			break;
       
   160 
       
   161 		default:
       
   162 			break;
       
   163 		};
       
   164 	}
       
   165 
       
   166 void CHCTLBcspSequencer::SendNextPacket()
       
   167 /**
       
   168 	This method attempts to send the next frame on the queue.
       
   169 */
       
   170 	{
       
   171 	LOG_FUNC
       
   172 
       
   173 	if(SendQueuedFrame() == KErrBcspMaxRetries)
       
   174 		{
       
   175 		HandlePeerReset();
       
   176 		}
       
   177 	}
       
   178 
       
   179 TUint8 CHCTLBcspSequencer::TxAck() const
       
   180 	{
       
   181 	LOG_FUNC
       
   182 
       
   183 	return iTxAck;
       
   184 	}
       
   185 
       
   186 void CHCTLBcspSequencer::HandleRxAck()
       
   187 	{
       
   188 	LOG_FUNC
       
   189 
       
   190 	// An ACK has been received, so reset the Tx timeout counter
       
   191 	iRxTimeoutCount = 0;
       
   192 	// Returns ETrue if there are unacknowledged packets remaining
       
   193 	// in the window
       
   194 	if(iFrameQueue.AckReceived(iRxAck))
       
   195 		{
       
   196 		StartRxAckTimer();
       
   197 		}
       
   198 	else
       
   199 		{
       
   200 		iRxAckTimer->Cancel();
       
   201 		}
       
   202 	}
       
   203 
       
   204 /*static*/ TInt CHCTLBcspSequencer::RxTimeout(TAny* aThis)
       
   205 	{
       
   206 	LOG_STATIC_FUNC
       
   207 	
       
   208 	reinterpret_cast<CHCTLBcspSequencer*>(aThis)->HandleRxAckTimeout();
       
   209 	
       
   210 	return KErrNone;
       
   211 	}
       
   212 
       
   213 void CHCTLBcspSequencer::SendPacket(TDesC8* aFrame, TBool aIsReliable)	
       
   214 /**
       
   215 	
       
   216 	This method writes @param aFrame and starts the RxAckTimer if @param aIsReliable
       
   217 	is ETrue
       
   218 */
       
   219 	{
       
   220 	LOG_FUNC
       
   221 
       
   222 	iSender->Write(*aFrame);	
       
   223 
       
   224 	if (aIsReliable)
       
   225 		{
       
   226 		StartRxAckTimer();
       
   227 		}
       
   228 	}
       
   229 
       
   230 TInt CHCTLBcspSequencer::TxTimeout(TAny* aThis)
       
   231 	{
       
   232 	LOG_STATIC_FUNC
       
   233 	
       
   234 	reinterpret_cast<CHCTLBcspSequencer*>(aThis)->TxAckMsg();
       
   235 	
       
   236 	return KErrNone;
       
   237 	}
       
   238 
       
   239 void CHCTLBcspSequencer::TxAckMsg() 
       
   240 	{
       
   241 	LOG_FUNC
       
   242 
       
   243 	iHctlBcsp.TxAckMsg();
       
   244 	}
       
   245 
       
   246 void CHCTLBcspSequencer::StartRxAckTimer()
       
   247 	{
       
   248 	LOG_FUNC
       
   249 
       
   250 	iRxAckTimer->Cancel();
       
   251 	iRxAckTimer->After(KRxAckTimeout);
       
   252 	}
       
   253 
       
   254 void CHCTLBcspSequencer::StartTxAckTimer()
       
   255 	{
       
   256 	LOG_FUNC
       
   257 
       
   258 	if ( !iTxAckTimer->IsActive() )
       
   259 		{
       
   260 		iTxAckTimer->After(KRxAckTimeout);
       
   261 		}
       
   262 	}
       
   263 
       
   264 void CHCTLBcspSequencer::HandleRxAckTimeout()
       
   265 	{
       
   266 	LOG_FUNC
       
   267 
       
   268 	// Increment the Rx ACK Timeout counter
       
   269 	iRxTimeoutCount++;
       
   270 	iFrameQueue.AckTimeout();
       
   271 	// While the maximum rx timeout allowed is not reached, rearm the timer
       
   272 	// waiting for the ACK.
       
   273 	// If the max is reached, we consider that the peer will not respond and
       
   274 	// has been poweroff. So, do not rearm the timer and reset the counter.
       
   275 	// Notice that the BC4 ship implements the same mechanism.
       
   276 	if (iRxTimeoutCount < MAX_RX_TIMEOUT_ALLOWED)
       
   277 		{
       
   278 		StartRxAckTimer();
       
   279 		}
       
   280 	else
       
   281 		{
       
   282 		iRxTimeoutCount = 0;
       
   283 		}
       
   284 	}
       
   285 
       
   286 void CHCTLBcspSequencer::WakeUp()
       
   287 /**
       
   288 	Method made available to trigger the TxStateMachine to do something 
       
   289 	depending upon its current state
       
   290 */
       
   291 	{
       
   292 	LOG_FUNC
       
   293 	if(!iSender->IsActive())
       
   294 		{
       
   295 		SendNextPacket();
       
   296 		}
       
   297 	}
       
   298 
       
   299 TInt CHCTLBcspSequencer::SendQueuedFrame()
       
   300 /**
       
   301 	Method to get the Next Frame from the frame queue and then write it via 
       
   302 	the SendPacket method
       
   303 */
       
   304 	{
       
   305 	LOG_FUNC
       
   306 
       
   307 	TDesC8* frame = NULL;
       
   308 	TBool isReliable = EFalse;
       
   309 	TInt err = iFrameQueue.GetNextFrame(frame,isReliable);
       
   310 	if (!err)
       
   311 		{
       
   312 		SendPacket(frame,isReliable);
       
   313 		}
       
   314 	return err;
       
   315 	}
       
   316 
       
   317