bluetooth/btstack/l2cap/L2CapEnhancedDataController.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2008-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 #include <bluetooth/logger.h>
       
    17 #include "btsockettimer.h"
       
    18 #include "L2CapEnhancedDataController.h"
       
    19 #include "L2CapSDUQueue.h"
       
    20 #include "l2signalmgr.h"
       
    21 #include "l2util.h"
       
    22 #include "L2CapDebugControlInterface.h"
       
    23 
       
    24 #ifdef __FLOG_ACTIVE
       
    25 _LIT8(KLogComponent, LOG_COMPONENT_L2CAP_DATA_CONTROLLER);
       
    26 #endif
       
    27 
       
    28 using namespace L2CapDataUtils;
       
    29 
       
    30 
       
    31 CL2CapStreamingController::CL2CapStreamingController(TL2CAPPort aLocalCID,
       
    32 													 TL2CAPPort aRemoteCID,
       
    33 													 CL2CAPMux& aMuxer,
       
    34 													 CL2CapSDUQueue& aSDUQueue,
       
    35 													 TL2CapDataControllerConfig* aConfig)
       
    36  :	CL2CapBasicDataController(aLocalCID, aRemoteCID, aMuxer, aSDUQueue, aConfig, EFalse)
       
    37 	{
       
    38 	LOG_FUNC
       
    39 	}
       
    40 
       
    41 CL2CapStreamingController::~CL2CapStreamingController()
       
    42 	{
       
    43 	LOG_FUNC
       
    44 	}
       
    45 
       
    46 void CL2CapStreamingController::ProcessFlushTimerExpiry()
       
    47 	{
       
    48 	LOG_FUNC
       
    49 	__ASSERT_DEBUG(EFalse, Panic(EL2CAPFlushingNotReallySupported));
       
    50 	}
       
    51 
       
    52 HL2CapPDU* CL2CapStreamingController::GetPduL()
       
    53 	{
       
    54 	LOG_FUNC
       
    55 	// This is called from the signal manager.
       
    56 	HL2CapPDU* pduToSend = NULL;
       
    57 
       
    58 	pduToSend = iSDUQueue.GetPDU();
       
    59 
       
    60 	if(pduToSend)
       
    61 		{
       
    62 		pduToSend->DeliverOutgoingPDU(*this);
       
    63 		}
       
    64 	
       
    65     if (iSDUQueue.HavePDUToSend())
       
    66         {
       
    67         iMuxer.PDUAvailable();
       
    68         }
       
    69 	
       
    70 	return pduToSend;
       
    71 	}
       
    72 
       
    73 void CL2CapStreamingController::HandleIncomingIFrameL(RMBufChain& aIFrame)
       
    74 	{
       
    75 	LOG_FUNC
       
    76 
       
    77 	const TUint8 txSeq = HIFramePDU::TxSeqNumber(aIFrame);
       
    78 	
       
    79 	if (txSeq != iExpectedTxSeq)
       
    80 		{
       
    81 		// SDU currently being assembled is no good now. Need to tell the SDU Q to flush
       
    82 		// it, otherwise if we lost the right amount of I-Frames, we would end up assembling
       
    83 		// an FDU (Frankenstein Data Unit) - half SDU number n, half SDU number n+1.
       
    84 		// Note that FDUs are still possible if 63 frames are lost. There'se no notion of
       
    85 		// SDU checksumming in the protocol, so that can't be prevented.
       
    86 		iSDUQueue.FlushCurrentlyAssembledSdu();
       
    87 		}
       
    88 
       
    89 	if (iSDUQueue.IsIncomingQueueFull())
       
    90 		{
       
    91 		// Make room for new data. From the spec:
       
    92 		// "If there is no buffer space for the received I-frame an existing I-frame
       
    93 		// (i.e. the oldest) shall be discarded (flushed) freeing up buffer space for
       
    94 		// the new I-frame.	The discarded I-frame shall be marked as missing."
       
    95 		iSDUQueue.FlushOldestIncomingSdu();
       
    96 		}
       
    97 	LEAVEIFERRORL(iSDUQueue.PutIFramePDU(aIFrame));
       
    98 
       
    99 	iExpectedTxSeq = Mod64(txSeq + 1);
       
   100 
       
   101 	// SDU Q sucks out the content, so we can free the frame whether it's been consumed or dropped.
       
   102 	aIFrame.Free();
       
   103 	}
       
   104 
       
   105 TInt CL2CapStreamingController::HandleOutgoingIFrame(HIFramePDU* aIFrame)
       
   106 	{
       
   107 	LOG_FUNC
       
   108 	aIFrame->SetPDUCID(iRemoteCID);
       
   109 	aIFrame->SetTxSeqNumber(iNextTxSeq);
       
   110 	iNextTxSeq = Mod64(iNextTxSeq + 1);
       
   111 
       
   112 	// The Control field is zero-ed when the frame is created.
       
   113 
       
   114 	aIFrame->CalculateAndSetFCS();
       
   115 
       
   116 	return KErrNone;
       
   117 	}
       
   118 
       
   119 void CL2CapStreamingController::HandlePduSendComplete(HL2CapPDU& aPdu)
       
   120 	{
       
   121 	LOG_FUNC
       
   122 	delete &aPdu;
       
   123 	}
       
   124 
       
   125 void CL2CapStreamingController::HandlePduSendError(HL2CapPDU& aPdu)
       
   126 	{
       
   127 	LOG_FUNC
       
   128 	delete &aPdu;
       
   129 	}
       
   130 
       
   131 
       
   132 RL2CapErtmTimerManager::RL2CapErtmTimerManager(CL2CapEnhancedReTxController& aClient)
       
   133  :	RL2CapRetransmissionModeTimerManager(aClient),
       
   134  	iLocalBusyDelayTimerRunning(EFalse)
       
   135 	{
       
   136 	LOG_FUNC
       
   137 	}
       
   138 
       
   139 void RL2CapErtmTimerManager::Close()
       
   140 	{
       
   141 	LOG_FUNC
       
   142 	StopLocalBusyDelayTimer();
       
   143 	RL2CapRetransmissionModeTimerManager::Close();
       
   144 	}
       
   145 
       
   146 void RL2CapErtmTimerManager::StartLocalBusyDelayTimer()
       
   147 	{
       
   148 	LOG_FUNC
       
   149 	// Shouldn't happen, but no big deal if it does.
       
   150 	__ASSERT_DEBUG(!iLocalBusyDelayTimerRunning, Panic(EL2CAPInvalidDataControllerTimerState));
       
   151 
       
   152 	if (!iLocalBusyDelayTimerRunning)
       
   153 		{
       
   154 		TCallBack cb(LocalBusyDelayTimerExpired, this);
       
   155 		iLocalBusyDelayTimerEntry.Set(cb);
       
   156 	
       
   157 		// Set the timeout. The value is in Milliseconds.
       
   158 		BTSocketTimer::Queue((iClient.PeerRetransmissionTimeout() * 1000) / KLocalBusyDelayTimerDenominator,
       
   159 							 iLocalBusyDelayTimerEntry);
       
   160 		iLocalBusyDelayTimerRunning = ETrue;
       
   161 		}
       
   162 	}
       
   163 
       
   164 void RL2CapErtmTimerManager::StopLocalBusyDelayTimer()
       
   165 	{
       
   166 	LOG_FUNC
       
   167 	if (iLocalBusyDelayTimerRunning)
       
   168 		{
       
   169 		BTSocketTimer::Remove(iLocalBusyDelayTimerEntry);
       
   170 		iLocalBusyDelayTimerRunning = EFalse;
       
   171 		}
       
   172 	}
       
   173 
       
   174 void RL2CapErtmTimerManager::HandleLocalBusyDelayTimerExpired()
       
   175 	{
       
   176 	LOG_FUNC
       
   177 	iLocalBusyDelayTimerRunning = EFalse;
       
   178 	static_cast<CL2CapEnhancedReTxController&>(iClient).LocalBusyDelayTimerExpired();
       
   179 	}
       
   180 
       
   181 /*static*/ TInt RL2CapErtmTimerManager::LocalBusyDelayTimerExpired(TAny* aTimerMan)
       
   182 	{
       
   183 	LOG_STATIC_FUNC
       
   184 	RL2CapErtmTimerManager* timerMan = reinterpret_cast<RL2CapErtmTimerManager*>(aTimerMan);
       
   185 	timerMan->HandleLocalBusyDelayTimerExpired();
       
   186 	return EFalse;
       
   187 	}
       
   188 
       
   189 
       
   190 
       
   191 RL2CapErtmUnacknowledgedIFrames::RL2CapErtmUnacknowledgedIFrames()
       
   192  :	iFrameList(_FOFF(HIFramePDU, iLink))
       
   193 	{
       
   194 	LOG_FUNC
       
   195 	iFrameIndex.Reset();
       
   196 	}
       
   197 
       
   198 void RL2CapErtmUnacknowledgedIFrames::Close()
       
   199 	{
       
   200 	LOG_FUNC
       
   201 
       
   202 	// Some PDUs may hold a reference to this data controller.
       
   203 	TDblQueIter<HIFramePDU> unackedIter(iFrameList);
       
   204 	HIFramePDU* pdu;
       
   205 
       
   206 	while((pdu = unackedIter++) != NULL)
       
   207 		{
       
   208 		Remove(*pdu);
       
   209 		if (!pdu->IsAwaitingHciCompletion())
       
   210 			{
       
   211 			delete pdu;
       
   212 			}
       
   213 		else
       
   214 			{
       
   215 			// Will delete itself on HCI completion.
       
   216 			pdu->DeregisterPduOwner();
       
   217 			}
       
   218 		}
       
   219 	}
       
   220 
       
   221 
       
   222 CL2CapErtmDataTransmitter* CL2CapErtmDataTransmitter::NewL(CL2CapEnhancedReTxController& aController)
       
   223 	{
       
   224 	LOG_STATIC_FUNC
       
   225 	return new (ELeave) CL2CapErtmDataTransmitter(aController);
       
   226 	}
       
   227 
       
   228 CL2CapErtmDataTransmitter::~CL2CapErtmDataTransmitter()
       
   229 	{
       
   230 	LOG_FUNC
       
   231 	iUnackedIFrames.Close();
       
   232 	}
       
   233 
       
   234 CL2CapErtmDataTransmitter::CL2CapErtmDataTransmitter(CL2CapEnhancedReTxController& aController)
       
   235  :	iController(aController),
       
   236 	iNextTxSeq(0),
       
   237 	iExpectedAckSeq(0),
       
   238 	iRemoteBusy(EFalse),
       
   239 	iSRejActioned(EFalse),
       
   240 	iSRejSaveReqSeq(0),
       
   241 	iWaitAckStatePending(EFalse),
       
   242 	iInWaitAckState(EFalse)
       
   243 	{
       
   244 	LOG_FUNC
       
   245 	}
       
   246 
       
   247 void CL2CapErtmDataTransmitter::HandleIncomingIFrame(RMBufChain& aIFrame)
       
   248 	{
       
   249 	LOG_FUNC
       
   250 	LOG2(_L("NextTxSeq=%d, ExpectedAckSeq = %d"), iNextTxSeq, iExpectedAckSeq)
       
   251 
       
   252 	const TUint8 reqSeq = HIFramePDU::ReqSeqNumber(aIFrame);
       
   253 	const TBool final = HIFramePDU::FinalBit(aIFrame);
       
   254 
       
   255 	HandleReqSeqAck(reqSeq);
       
   256 	if (final)
       
   257 		{
       
   258 		HandleFinalAck();
       
   259 		}
       
   260 	}
       
   261 
       
   262 void CL2CapErtmDataTransmitter::HandleIncomingSFrameL(RMBufChain& aSFrame)
       
   263 	{
       
   264 	LOG_FUNC
       
   265 	LOG2(_L("NextTxSeq=%d, ExpectedAckSeq = %d"), iNextTxSeq, iExpectedAckSeq)
       
   266 
       
   267 	const TUint8 reqSeq = HSFramePDU::ReqSeqNumber(aSFrame);
       
   268 	const TSupervisoryFunction function = HSFramePDU::SupervisoryFunction(aSFrame);
       
   269 	const TBool final = HSFramePDU::FinalBit(aSFrame);
       
   270 	const TBool poll = HSFramePDU::PollBit(aSFrame);
       
   271 
       
   272 	// An S-Frame [SREJ] with the POLL=0 does NOT acknowledge any I-Frames.
       
   273 	if (!(function == ESelectiveReject && !poll))
       
   274 		{
       
   275 		HandleReqSeqAck(reqSeq);
       
   276 		}
       
   277 	else // SREJ [P=0]
       
   278 		{
       
   279 		// The remote detected packet loss itself, so restart the retransmission timer -
       
   280 		// - SREJ -> I-Frame -> RR roundtrip time is too long and would almost always
       
   281 		// cause it to expire if we didn't (most probably unnecessarily).
       
   282 		if (TimerMan().IsAckTimerRunning())
       
   283 			{
       
   284 			TimerMan().StartAckTimer();
       
   285 			}
       
   286 		}
       
   287 
       
   288 	switch (function)
       
   289 		{
       
   290 		case EReceiverNotReady:
       
   291 			iRemoteBusy = ETrue;
       
   292 			TimerMan().StopAckTimer();
       
   293 			if (final && iInWaitAckState)
       
   294 				{
       
   295 				iInWaitAckState = EFalse;
       
   296 				// We'll start retransmitting when we get RR from the peer. 
       
   297 				}
       
   298 			break;
       
   299 	
       
   300 		case EReceiverReady:
       
   301 			if (final)
       
   302 				{
       
   303 				HandleFinalAck();
       
   304 				}
       
   305 			// iRemoteBusy cleared at the bottom of the function.
       
   306 			break;
       
   307 	
       
   308 		case EReject:
       
   309 			// A REJ should be ignored if we're in WAIT_ACK and the Final bit in the
       
   310 			// frame is 0. We'll receive a Final packet in a while anyway, and that
       
   311 			// packet is guaranteed to contain the same ReqSeq, because the remote
       
   312 			// can't acknowledge anything new until we retransmit, and we won't
       
   313 			// retransmit until we receive the Final ack.
       
   314 			if (!(iInWaitAckState && !final))
       
   315 				{
       
   316 				RetransmitUnackedIFrames();
       
   317 	
       
   318 				TimerMan().StopAckTimer();
       
   319 				// The timer will be started again when the first retransmitted I-Frame
       
   320 				// is completed.
       
   321 				}
       
   322 	
       
   323 			if (final)
       
   324 				{
       
   325 				HandleFinalAck();
       
   326 				}
       
   327 			// iRemoteBusy cleared at the bottom of the function.
       
   328 			break;
       
   329 			
       
   330 		case ESelectiveReject:
       
   331 			HandleIncomingSRejL(aSFrame);
       
   332 			// iRemoteBusy cleared at the bottom of the function.
       
   333 			break;
       
   334 		}
       
   335 
       
   336 	// Anything other than RNR means remote isn't busy anymore.
       
   337 	if (iRemoteBusy && function != EReceiverNotReady)
       
   338 		{
       
   339 		__ASSERT_DEBUG(!TimerMan().IsAckTimerRunning(), Panic(EL2CAPAckTimerRunningWhenRemoteBusy));
       
   340 		iRemoteBusy = EFalse;
       
   341 		if (!iUnackedIFrames.IsEmpty())
       
   342 			{
       
   343 			TimerMan().StartAckTimer();
       
   344 			}
       
   345 		LOG(_L("Exitted RemoteBusy condition"))
       
   346 		}
       
   347 	}
       
   348 
       
   349 void CL2CapErtmDataTransmitter::HandleIncomingSRejL(RMBufChain& aSRejFrame)
       
   350 	{
       
   351 	LOG_FUNC
       
   352 
       
   353 	const TUint8 reqSeq = HSFramePDU::ReqSeqNumber(aSRejFrame);
       
   354 	const TSupervisoryFunction function = HSFramePDU::SupervisoryFunction(aSRejFrame);
       
   355 	const TBool final = HSFramePDU::FinalBit(aSRejFrame);
       
   356 	const TBool poll = HSFramePDU::PollBit(aSRejFrame);
       
   357 
       
   358 	HIFramePDU* requestedIFrame = iUnackedIFrames[reqSeq];
       
   359 	// If the ReqSeq is invalid then it should've been caught earlier.
       
   360 	__ASSERT_ALWAYS(requestedIFrame != NULL, Panic(EL2CAPSRejReqSeqNotOnUnackedList));
       
   361 
       
   362 	if (poll)
       
   363 		{
       
   364 		// Set the Final bit directly here to make sure it's in the right frame.
       
   365 		requestedIFrame->SetFinalBit(ETrue);
       
   366 		SendOrPendL(*requestedIFrame);
       
   367 
       
   368 		if (iController.IsPollOutstanding())
       
   369 			{
       
   370 			iSRejActioned = ETrue;
       
   371 			iSRejSaveReqSeq = reqSeq;
       
   372 			// If Poll is set, then Final must be 0, so we don't have to check for it.
       
   373 			}
       
   374 		} // Poll = 1
       
   375 	else
       
   376 		{
       
   377 		// If peer is in SREJ_SENT when it receives the Poll, then it needs to respond
       
   378 		// with an SREJ[F=1]. This SREJ may contain a ReqSeq it has already sent in the
       
   379 		// previous SREJ[F=0], and we need to guard against this on our side, so that we
       
   380 		// don't retransmit a packet twice - it could cause the channel to be closed, as
       
   381 		// the second copy would be outside of peer's receive window and thus invalid.
       
   382 		TBool duplicateWithFinal = EFalse;
       
   383 
       
   384 		if (iController.IsPollOutstanding())
       
   385 			{
       
   386 			if (final)
       
   387 				{
       
   388 				if (iSRejActioned && iSRejSaveReqSeq == reqSeq)
       
   389 					{
       
   390 					// Peer has sent us a SREJ F=0 for the same frame before, need to
       
   391 					// ignore this SREJ.
       
   392 					duplicateWithFinal = ETrue;
       
   393 					LOG1(_L("Received a duplicate SREJ with ReqSeq=%d with Final=1, will drop it"),
       
   394 						 reqSeq)
       
   395 					}
       
   396 
       
   397 				if (!iUnackedIFrames.IsEmpty() && !iRemoteBusy)
       
   398 					{
       
   399 					TimerMan().StartAckTimer();
       
   400 					}
       
   401 
       
   402 				iSRejActioned = EFalse;
       
   403 				iInWaitAckState = EFalse;
       
   404 				// Don't go into ERetransmitAllUnackedFrames, even in WAIT_ACK:
       
   405 				// - an SREJ[P=0,F=1] frame doesn't carry an acking ReqSeq, so we
       
   406 				//   wouldn't know at which frame we should start the retransmission;
       
   407 				// - the peer has just SREJed some I-Frames so there's a chance
       
   408 				//   we're already retransmitting the stuff we timed out on.
       
   409 				//   If we're not (which is possible if acknowledgments from the
       
   410 				//   peer have been lost), then we'll need to wait for the
       
   411 				//   next Retransmission Timeout and then retransmit (unless we
       
   412 				//   we hit remote being in SREJ_SENT again, rinse-and-repeat then).
       
   413 				OutgoingQ().SendPendingRetransmitIFramesL();
       
   414 				}
       
   415 			else
       
   416 				{
       
   417 				iSRejActioned = ETrue;
       
   418 				iSRejSaveReqSeq = reqSeq;
       
   419 				}
       
   420 			} // waiting for final ack
       
   421 
       
   422 		if (!duplicateWithFinal)
       
   423 			{
       
   424 			// Clean the F-bit in case it was set during previous transmission.
       
   425 			requestedIFrame->SetFinalBit(EFalse);
       
   426 			SendOrPendL(*requestedIFrame);
       
   427 			}
       
   428 		} // Poll bit = 0
       
   429 	}
       
   430 
       
   431 void CL2CapErtmDataTransmitter::HciCompletedIFrame(HIFramePDU& aIFrame)
       
   432 	{
       
   433 	LOG_FUNC
       
   434 	if (aIFrame.Acked())
       
   435 		{
       
   436 		__ASSERT_DEBUG(iUnackedIFrames[aIFrame.TxSeqNumber()] == NULL,
       
   437 					   Panic(EL2CAPAckedTxSeqFoundOnUnackedList));
       
   438 
       
   439 		// This condition will happen extremely rarely or none at all on real hardware.
       
   440 		// It does happen on the emulator with USB HCTL.
       
   441 		LOG1(_L("I-Frame %d has been acknowledged before HCI completion"), aIFrame.TxSeqNumber())
       
   442 		// Frame has been already sent and acked - skip putting it on the Send queue, just delete.
       
   443 		delete &aIFrame;
       
   444 		// We'll start the retransmission timer the first time a frame that hasn't been acked is
       
   445 		// completed (the else branch below). 
       
   446 		}
       
   447 	else
       
   448 		{
       
   449 		__ASSERT_DEBUG(iUnackedIFrames[aIFrame.TxSeqNumber()] != NULL,
       
   450 					   Panic(EL2CAPUnackedTxSeqNotFoundOnUnackedList));
       
   451 
       
   452 		if (!TimerMan().IsAckTimerRunning() && !iRemoteBusy)
       
   453 			{
       
   454 			// It's the first frame sent out after a period of silence.
       
   455 			// ... or it's the first frame of a retransmission.
       
   456 			// ... or we can has a bug (LOL that's impossible, I coded this myself).
       
   457 			TimerMan().StartAckTimer();
       
   458 			}
       
   459 		}
       
   460 	}
       
   461 
       
   462 void CL2CapErtmDataTransmitter::AckTimerExpired()
       
   463 	{
       
   464 	LOG_FUNC
       
   465 	__ASSERT_DEBUG(!iUnackedIFrames.IsEmpty(), Panic(EL2CAPAckTimerExpiryWithoutPDUToSupervise));
       
   466 	// Signal to GetPdu that we need to enter WAIT_ACK.
       
   467 	iWaitAckStatePending = ETrue;
       
   468 	iController.NotifyMuxerOfPdusToSendIfHaveSome();
       
   469 	}
       
   470 
       
   471 HIFramePDU* CL2CapErtmDataTransmitter::GetIFrameToSendL()
       
   472 	{
       
   473 	LOG_FUNC
       
   474 	HIFramePDU* pduToSend = NULL;
       
   475 
       
   476 	// Can't send data in WAIT_ACK.
       
   477 	// We send data in RemoteBusy until the window fills up, but with the ack timer stopped.
       
   478 	if (!iInWaitAckState)
       
   479 		{
       
   480 		if (iUnackedIFrames[iNextTxSeq] != NULL)
       
   481 			{
       
   482 			// Rreceived a REJ or Ack timer expired.
       
   483 			pduToSend = iUnackedIFrames[iNextTxSeq];
       
   484 			if (pduToSend->IsAwaitingHciCompletion())
       
   485 				{
       
   486 				pduToSend = NULL;
       
   487 				}
       
   488 			else
       
   489 				{
       
   490 				// In case it was set for the previous transmission. 
       
   491 				pduToSend->SetFinalBit(EFalse);
       
   492 				}
       
   493 			}
       
   494 		else if (HaveSpaceInOutgoingWindow())
       
   495 			{
       
   496 			pduToSend = static_cast<HIFramePDU*>(iController.SDUQueue().GetPDU());
       
   497 			if (pduToSend != NULL)
       
   498 				{
       
   499 				pduToSend->SetTxSeqNumber(iNextTxSeq);
       
   500 				// It's a new frame that hasn't been sent before, so we need to append it to the
       
   501 				// unacked list. Once put on the list, it should never get delinked from it until
       
   502 				// acknowledged, even during retransmissions.
       
   503 				__ASSERT_DEBUG(iUnackedIFrames[iNextTxSeq] == NULL, Panic(EL2CAPNewTxSeqFoundOnUnackedList));
       
   504 				iUnackedIFrames.Append(*pduToSend);
       
   505 				}
       
   506 			}
       
   507 
       
   508 		if (pduToSend != NULL)
       
   509 			{
       
   510 			iNextTxSeq = Mod64(iNextTxSeq + 1);
       
   511 			}
       
   512 		} // state != WAIT_ACK (can transmit data)
       
   513 	return pduToSend;
       
   514 	}
       
   515 
       
   516 TBool CL2CapErtmDataTransmitter::HaveSpaceInOutgoingWindow() const
       
   517 	{
       
   518 	LOG_FUNC
       
   519 	TBool canSend = ETrue;
       
   520 	if (Mod64(iNextTxSeq - iExpectedAckSeq) >= iController.Config().TXWindowSize())
       
   521 		{
       
   522 		canSend = EFalse;
       
   523 		}
       
   524 	return canSend;
       
   525 	}
       
   526 
       
   527 void CL2CapErtmDataTransmitter::HandleFinalAck()
       
   528 	{
       
   529 	LOG_FUNC
       
   530 
       
   531 	if (iInWaitAckState)
       
   532 		{
       
   533 		iInWaitAckState = EFalse;
       
   534 		RetransmitUnackedIFrames();
       
   535 		}
       
   536 
       
   537 	// Whether it was WAIT_ACK or WAIT_F, Ack timer was stopped because Monitor timer
       
   538 	// was running.
       
   539 	if (!iUnackedIFrames.IsEmpty() && !iRemoteBusy)
       
   540 		{
       
   541 		TimerMan().StartAckTimer();
       
   542 		}
       
   543 	}
       
   544 
       
   545 void CL2CapErtmDataTransmitter::HandleReqSeqAck(TUint8 aReqSeq)
       
   546 	{
       
   547 	LOG_FUNC
       
   548 
       
   549 	__ASSERT_DEBUG((aReqSeq == iExpectedAckSeq) || !iUnackedIFrames.IsEmpty(),
       
   550 				   Panic(EL2CAPUnacknowledgedPdusMissingFromList));
       
   551 
       
   552 	// See if any I-Frames have been acknowledged by the peer, slide the send window,
       
   553 	// send new data if window space is now available, restart ack timer.
       
   554 
       
   555 	if (!iUnackedIFrames.IsEmpty() && aReqSeq != iExpectedAckSeq)
       
   556 		{
       
   557 		const TBool wasWindowFull = !HaveSpaceInOutgoingWindow();
       
   558 
       
   559 		TDblQueIter<HIFramePDU> iter(iUnackedIFrames.Iterator());
       
   560 		HIFramePDU* pduPtr;
       
   561 		TBool ackedPDUs = EFalse;
       
   562 
       
   563 		__ASSERT_DEBUG(iUnackedIFrames.First()->TxSeqNumber() == iExpectedAckSeq,
       
   564 					   Panic(EL2CAPOldestUnackedPduTxSeqNotMatchingExpectedAck));
       
   565 
       
   566 		while ((pduPtr = iter++) != NULL)
       
   567 			{
       
   568 			if (InWindow(pduPtr->TxSeqNumber(), iExpectedAckSeq, Mod64(aReqSeq - 1)))
       
   569 				{
       
   570 				iUnackedIFrames.Remove(*pduPtr);
       
   571 				pduPtr->SetAcked(ETrue);
       
   572 				ackedPDUs = ETrue;
       
   573 
       
   574 				if (!pduPtr->IsAwaitingHciCompletion())
       
   575 					{
       
   576 					delete pduPtr;
       
   577 					}
       
   578 				else
       
   579 					{
       
   580 					LOG1(_L("I-Frame %d has been acknowledged before HCI completion!"),
       
   581 						 pduPtr->TxSeqNumber())
       
   582 					// Will delete itself on HCI completion.
       
   583 					pduPtr->DeregisterPduOwner();
       
   584 					}
       
   585 				} // pdu in acked window
       
   586 			else
       
   587 				{
       
   588 				// The queue is sorted chronologically - the head is always the oldest PDU.
       
   589 				// First PDU outside of the acknowledged window means we can stop the loop.
       
   590 				break;
       
   591 				}
       
   592 			}
       
   593 
       
   594 		if (iUnackedIFrames.IsEmpty())
       
   595 			{
       
   596 			TimerMan().StopAckTimer();
       
   597 			}
       
   598 		else if (ackedPDUs && !iRemoteBusy)
       
   599 			{
       
   600 			// This will actually REstart the timer.
       
   601 			TimerMan().StartAckTimer();
       
   602 			}
       
   603 
       
   604 		iExpectedAckSeq = aReqSeq;
       
   605 		LOG1(_L("New ExpectedAckSeq=%d"), aReqSeq)
       
   606 
       
   607 		if (iController.IsOutgoingDataPathClosing() && iUnackedIFrames.IsEmpty())
       
   608 			{
       
   609 			iController.SignalOutgoingDataDeliveredToSduQ();
       
   610 			}
       
   611 		}
       
   612 	}
       
   613 
       
   614 void CL2CapErtmDataTransmitter::RetransmitUnackedIFrames()
       
   615 	{
       
   616 	LOG_FUNC
       
   617 	LOG1(_L("Setting NextTxSeq to ExpectedAckSeq = %d"), iExpectedAckSeq)
       
   618 	iNextTxSeq = iExpectedAckSeq;
       
   619 	// This is important when exiting WAIT_ACK: forget about all I-Frames SREJ-requested
       
   620 	// by the peer. We'll retransmit them as part of the whole bunch. And we can't transmit
       
   621 	// the same frame twice, which would happen had we left these hanging around.
       
   622 	OutgoingQ().CancelPendingRetransmitIFrames();
       
   623 	}
       
   624 
       
   625 
       
   626 TL2CapErtmMissingTxSeqs::TL2CapErtmMissingTxSeqs()
       
   627  :	iNumMissingTxSeqs(0),
       
   628 	iExpectedRecvIdx(0),
       
   629 	iResendIdx(0)
       
   630 	{}
       
   631 
       
   632 TBool TL2CapErtmMissingTxSeqs::IsTxSeqOnTheList(TUint8 aTxSeq) const
       
   633 	{
       
   634 	TBool found = EFalse;
       
   635 	for (TInt i = 0; i < iNumMissingTxSeqs && !found; i++)
       
   636 		{
       
   637 		if (iMissingTxSeqs[i] == aTxSeq)
       
   638 			{
       
   639 			found = ETrue;
       
   640 			}
       
   641 		}
       
   642 	return found;
       
   643 	}
       
   644 
       
   645 TBool TL2CapErtmMissingTxSeqs::ReceivedTxSeq(TUint8 aTxSeq)
       
   646 	{
       
   647 	LOG_FUNC
       
   648 	TBool resendNeeded = EFalse;
       
   649 	if (iMissingTxSeqs[iExpectedRecvIdx] == aTxSeq)
       
   650 		{
       
   651 		// This is the only path possible with the default of max. 1 SREJ at a time.
       
   652 		iExpectedRecvIdx++;
       
   653 		}
       
   654 	else
       
   655 		{
       
   656 		// Should only fall here with the experimental KMaxSRejsInFlight > 1
       
   657 		__ASSERT_DEBUG(KMaxSRejsInFlight > 1, Panic(EL2CAPMultiSRejPathHitWhenNotSoConfigured));
       
   658 
       
   659 		LOG1(_L("SREJ resend path hit, TxSeq=%d"), aTxSeq);
       
   660 #ifdef __FLOG_ACTIVE
       
   661 		Log();
       
   662 #endif
       
   663 		resendNeeded = ETrue;
       
   664 
       
   665 		// General idea: reshuffle the array to maintain chronological ordering, in which
       
   666 		// we expect the requested I-Frames to come through. All I-Frames between iExpectedRecvIdx
       
   667 		// and the one we're processing now are considered to have been lost and will be
       
   668 		// re-requested, so we need to move them to the very end of the list.
       
   669 		//
       
   670 		// E.g.:
       
   671 		// 0. Current list is 6 elements (iNumMissingTxSeqs == 6):
       
   672 		//     32 33 | 20 21 45 46
       
   673 		//   32 and 33 have been received (iExpectedRecvIdx == 2), we're still waiting for the
       
   674 		//   rest.
       
   675 		// 1. 45 comes through, we fall here. We need to move it to right after 33 and increase
       
   676 		//   iExpectedRecvIdx:
       
   677 		//     32 33 45 | 20 21 46
       
   678 		// 2. But the order in the array implied that 20 & 21 were requested before 45 and
       
   679 		//   haven't come through, so they must have been lost (remote has to respond to SREJs
       
   680 		//   in order they are sent). Ergo, we need to resend the SREJs for 20 and 21, which in
       
   681 		//   turn means we're now expecting them after all other frames, so finally:
       
   682 		//     32 33 45 | 46 20 21
       
   683 
       
   684 		// Find the index of the received TxSeq.
       
   685 		TInt receivedIdx = iExpectedRecvIdx;
       
   686 		while (iMissingTxSeqs[receivedIdx] != aTxSeq && receivedIdx < iNumMissingTxSeqs)
       
   687 			{
       
   688 			receivedIdx++;
       
   689 			}
       
   690 
       
   691 		const TInt numToResend = receivedIdx - iExpectedRecvIdx;
       
   692 		LOG2(_L("Last received = %d, num SREJs to resend = %d"),
       
   693 			 (iExpectedRecvIdx > 0 ? iMissingTxSeqs[iExpectedRecvIdx] : -1), numToResend);
       
   694 
       
   695 		// To maintain the partitioning of the array we need to move the received
       
   696 		// TxSeq towards the < iExpectedRecvIdx half, over the to-be-SREJed again TxSeqs.
       
   697 		// (step 1 in the example)
       
   698 		while (receivedIdx > iExpectedRecvIdx)
       
   699 			{
       
   700 			TUint8 tmp = iMissingTxSeqs[receivedIdx - 1];
       
   701 			iMissingTxSeqs[receivedIdx - 1] = iMissingTxSeqs[receivedIdx];
       
   702 			iMissingTxSeqs[receivedIdx] = tmp;
       
   703 			receivedIdx--;
       
   704 			}
       
   705 		iExpectedRecvIdx++;
       
   706 
       
   707 		// Now move the TxSeqs to be SREJed again onto the end of the list to maintain correct
       
   708 		// ordering (step 2 in the example).
       
   709 		// Note: this could be optimized a bit at least theoretically down to O(1) by
       
   710 		// copying the TxSeqs to re-SREJ out to a temp array, then moving the ones currently
       
   711 		// at the end, and then copying the ones from the temp array back in at the end.
       
   712 		// Note 2: this is the first time I've used bubble sort in my carreer. Honest.
       
   713 		for (TInt i = 0; i < numToResend; i++)
       
   714 			{
       
   715 			for (TInt bubble = iExpectedRecvIdx; bubble < iNumMissingTxSeqs - 1; bubble++)
       
   716 				{
       
   717 				TUint8 tmp = iMissingTxSeqs[bubble];
       
   718 				iMissingTxSeqs[bubble] = iMissingTxSeqs[bubble + 1];
       
   719 				iMissingTxSeqs[bubble + 1] = tmp;
       
   720 				}
       
   721 			}
       
   722 
       
   723 		// Store the index of the beginning of the TxSeqs to re-request, they will be pulled
       
   724 		// in an outer loop until the index reaches iNumMissingTxSeqs.
       
   725 		iResendIdx = iNumMissingTxSeqs - numToResend;
       
   726 #ifdef __FLOG_ACTIVE
       
   727 		Log();
       
   728 #endif
       
   729 		}
       
   730 	return resendNeeded;
       
   731 	}
       
   732 
       
   733 #ifdef __FLOG_ACTIVE
       
   734 void TL2CapErtmMissingTxSeqs::Log()
       
   735 	{
       
   736 	LOG3(_L("ExpectedRecvIdx=%d, ResendIdx=%d, NumMissingTxSeqs=%d"),
       
   737 		 iExpectedRecvIdx, iResendIdx, iNumMissingTxSeqs);
       
   738 
       
   739 	TBuf<256> buf;
       
   740 	for (TInt i = 0; i < iNumMissingTxSeqs; i++)
       
   741 		{
       
   742 		buf.AppendFormat(_L("%d "), iMissingTxSeqs[i]);
       
   743 		}
       
   744 	LOG1(_L("%S"), &buf)
       
   745 	}
       
   746 #endif
       
   747 
       
   748 
       
   749 TL2CapErtmReceiverStateBase::TL2CapErtmReceiverStateBase(CL2CapErtmDataReceiver& aReceiver)
       
   750  : iReceiver(aReceiver)
       
   751 	{
       
   752 	LOG_FUNC
       
   753 	}
       
   754 
       
   755 void TL2CapErtmReceiverStateBase::EnterL(RMBufChain* /*aIFrame*/)
       
   756 	{
       
   757 	LOG_FUNC
       
   758 	}
       
   759 
       
   760 void TL2CapErtmReceiverStateBase::ExitL()
       
   761 	{
       
   762 	LOG_FUNC
       
   763 	}
       
   764 
       
   765 TBool TL2CapErtmReceiverStateBase::IsLocalBusySupported() const
       
   766 	{
       
   767 	LOG_FUNC
       
   768 	return EFalse;
       
   769 	}
       
   770 
       
   771 
       
   772 TL2CapErtmReceiverStateRecv::TL2CapErtmReceiverStateRecv(CL2CapErtmDataReceiver& aReceiver)
       
   773  : TL2CapErtmReceiverStateBase(aReceiver)
       
   774 	{
       
   775 	LOG_FUNC
       
   776 	}
       
   777 
       
   778 void TL2CapErtmReceiverStateRecv::EnterL(RMBufChain* /*aIFrame*/)
       
   779 	{
       
   780 	LOG_FUNC
       
   781 
       
   782 	if (iReceiver.IsIncomingSduQFull())
       
   783 		{
       
   784 		// We may have transitioned from REJ_SENT or SREJ_SENT, which don't allow LocalBusy.
       
   785 		// We can enter it now.
       
   786 		iReceiver.TimerMan().StopLocalBusyDelayTimer();
       
   787 		iReceiver.UpdateLocalBusyStatusL();
       
   788 		}
       
   789 
       
   790 	__ASSERT_DEBUG((iReceiver.IsIncomingSduQFull() && iReceiver.LocalBusy()) ||
       
   791 				   (!iReceiver.IsIncomingSduQFull() && !iReceiver.LocalBusy()) ||
       
   792 				   (iReceiver.IsIncomingSduQFull() && iReceiver.TimerMan().IsLocalBusyDelayTimerRunning()) ||
       
   793 				   (!iReceiver.IsIncomingSduQFull() && !iReceiver.TimerMan().IsLocalBusyDelayTimerRunning()),
       
   794 				   Panic(EL2CapSduQAndLocalBusyStateInconsistent));
       
   795 	}
       
   796 
       
   797 void TL2CapErtmReceiverStateRecv::HandleIncomingIFrameL(RMBufChain& aIFrame)
       
   798 	{
       
   799 	LOG_FUNC
       
   800 	__ASSERT_DEBUG((iReceiver.IsIncomingSduQFull() && iReceiver.LocalBusy()) ||
       
   801 				   (!iReceiver.IsIncomingSduQFull() && !iReceiver.LocalBusy()) ||
       
   802 				   (iReceiver.IsIncomingSduQFull() && iReceiver.TimerMan().IsLocalBusyDelayTimerRunning()) ||
       
   803 				   (!iReceiver.IsIncomingSduQFull() && !iReceiver.TimerMan().IsLocalBusyDelayTimerRunning()),
       
   804 				   Panic(EL2CapSduQAndLocalBusyStateInconsistent));
       
   805 
       
   806 	__ASSERT_DEBUG(!iReceiver.IsIncomingSduQFull() ||
       
   807 				   InWindow(iReceiver.TxSeqExpectedBySduQ(), iReceiver.BufferSeq(), iReceiver.ExpectedTxSeq()),
       
   808 				   Panic(EL2CAPTxSeqExpectedBySduQNotWithinBufferSeqAndExpectedTxSeq));
       
   809 
       
   810 	__ASSERT_DEBUG(iReceiver.IsIncomingSduQFull() ||
       
   811 				   (iReceiver.ExpectedTxSeq() == iReceiver.BufferSeq() &&
       
   812 					iReceiver.BufferSeq() == iReceiver.TxSeqExpectedBySduQ()),
       
   813 				   Panic(EL2CAPExpectedTxSeqAndBufferSeqAndTxSeqExpectedBySduQNotEqualWhenIncomingQEmptyAndInRecvState));
       
   814 
       
   815 	const TUint8 txSeq = HIFramePDU::TxSeqNumber(aIFrame);
       
   816 
       
   817 	TBool freeFrame = ETrue;
       
   818 
       
   819 	if (iReceiver.ExpectedTxSeq() == txSeq)
       
   820 		// With-Expected-TxSeq
       
   821 		{
       
   822 		iReceiver.IncExpectedTxSeq();
       
   823 		if (!iReceiver.IsIncomingSduQFull())
       
   824 			{
       
   825 			iReceiver.SetBufferSeq(iReceiver.ExpectedTxSeq());
       
   826 			}
       
   827 		iReceiver.PassToIncomingQL(aIFrame);
       
   828 		freeFrame = EFalse;
       
   829 		}
       
   830 	else if (!iReceiver.LocalBusy())
       
   831 		{
       
   832 		if (iReceiver.IsTxSeqUnexpected(txSeq))
       
   833 			// With-Unexpected-TxSeq
       
   834 			{
       
   835 			if (iReceiver.IsSRejPreferredToRej(iReceiver.ExpectedTxSeq(), txSeq))
       
   836 				{
       
   837 				iReceiver.SetStateSRejSentL(aIFrame);
       
   838 				freeFrame = EFalse;
       
   839 				}
       
   840 			else
       
   841 				{
       
   842 				if (iReceiver.BufferSeq() == iReceiver.ExpectedTxSeq())
       
   843 					{
       
   844 					iReceiver.SetStateRejSentL();
       
   845 					}
       
   846 				else
       
   847 					{
       
   848 					// BufferSeq != ExpectedTxSeq only when SDU Q is full or in SREJ_SENT.
       
   849 					__ASSERT_DEBUG(iReceiver.IsIncomingSduQFull(),
       
   850 								   Panic(EL2CAPBufferSeqNotEqualToExpectedTxSeqWhenInRecvAndSduQNotFull));
       
   851 
       
   852 					__ASSERT_DEBUG(iReceiver.TimerMan().IsLocalBusyDelayTimerRunning(),
       
   853 								   Panic(EL2CAPLocalBusyDelayTimerNotRunningWhenSduQFullButNotInLB));
       
   854 
       
   855 					iReceiver.TimerMan().StopLocalBusyDelayTimer();
       
   856 
       
   857 					iReceiver.UpdateLocalBusyStatusL();
       
   858 					}
       
   859 				}
       
   860 			} // Unexpected TxSeq
       
   861 			// else must be duplicate (With-Duplicate-TxSeq), in which case we just drop it
       
   862 		} // !LocalBusy
       
   863 	// LocalBusy and !ExpectedTxSeq - drop it - the remote will initiate a retransmission
       
   864 	// when we exit LocalBusy anyway.
       
   865 
       
   866 	if (freeFrame)
       
   867 		{
       
   868 		aIFrame.Free();
       
   869 		}
       
   870 	}
       
   871 
       
   872 void TL2CapErtmReceiverStateRecv::HandlePollL()
       
   873 	{
       
   874 	LOG_FUNC
       
   875 	if (iReceiver.IsIncomingSduQFull())
       
   876 		{
       
   877 		// If the Poll is a result of the peer's retransmission timer expiry, then the peer will
       
   878 		// start retransmitting I-Frames from the sequence number given here by us (our current
       
   879 		// BufferSeq). Basically, the point of a Poll in WAIT_ACK is the peer asking "what have
       
   880 		// you received, need to know where to start retransmitting from", and we're supposed
       
   881 		// to be honest.
       
   882 		// Otherwise, if our upper layer Read()s and we process buffered I-Frames between now
       
   883 		// and the moment the first retransmitted packet comes through, we will have moved
       
   884 		// BufferSeq and render that packet invalid (a duplicate effectively). Therefore we
       
   885 		// need to drop the buffered I-Frames to prevent duplicates and guarantee that BufferSeq
       
   886 		// won't move.
       
   887 		iReceiver.FlushBufferedIncomingIFrames();
       
   888 
       
   889 		// Incoming I-Frame buffer empty and state = RECV:
       
   890 		__ASSERT_DEBUG(// no buffered I-Frames
       
   891 					   iReceiver.ExpectedTxSeq() == iReceiver.BufferSeq() &&
       
   892 					   // most recent ReqSeq
       
   893 					   iReceiver.BufferSeq() == iReceiver.TxSeqExpectedBySduQ(),
       
   894 					   Panic(EL2CAPExpectedTxSeqAndBufferSeqAndTxSeqExpectedBySduQNotEqualWhenIncomingQEmptyAndInRecvState));
       
   895 		}
       
   896 	// Now respond with a data frame or an ack frame with the Final bit set.
       
   897 	iReceiver.Controller().SendIOrRrOrRnrL(ETrue);
       
   898 	}
       
   899 
       
   900 TBool TL2CapErtmReceiverStateRecv::IsLocalBusySupported() const
       
   901 	{
       
   902 	LOG_FUNC
       
   903 	return ETrue;
       
   904 	}
       
   905 
       
   906 void TL2CapErtmReceiverStateRecv::TxSeqExpectedBySduQChanged(TUint8 aTxSeq)
       
   907 	{
       
   908 	LOG_FUNC
       
   909 	LOG1(_L("Slipping BufferSeq to %d"), aTxSeq)
       
   910 	iReceiver.SetBufferSeq(aTxSeq);
       
   911 	__ASSERT_DEBUG(iReceiver.IsIncomingSduQFull() || iReceiver.BufferSeq() == iReceiver.ExpectedTxSeq(),
       
   912 				   Panic(EL2CAPBufferSeqNotEqualToExpectedTxSeqWhenInRecvAndSduQNotFull));
       
   913 	}
       
   914 
       
   915 
       
   916 TL2CapErtmReceiverStateRejSent::TL2CapErtmReceiverStateRejSent(CL2CapErtmDataReceiver& aReceiver)
       
   917  :	TL2CapErtmReceiverStateBase(aReceiver)
       
   918 	{
       
   919 	LOG_FUNC
       
   920 	}
       
   921 
       
   922 void TL2CapErtmReceiverStateRejSent::EnterL(RMBufChain* /*aIFrame*/)
       
   923 	{
       
   924 	LOG_FUNC
       
   925 
       
   926 	// LocalBusy is only allowed in RECV.
       
   927 	__ASSERT_DEBUG(!iReceiver.LocalBusy(), Panic(EL2CAPInRejSentAndLocalBusy));
       
   928 
       
   929 	// Otherwise by sending the REJ we'd acknowledge frames between BufferSeq and ExpectedTxSeq
       
   930 	// (and if BufferSeq != ExpectedTxSeq and we're not in SREJ_SENT then incoming SDU Q is full
       
   931 	// and we can not acknowledge anything new).
       
   932 	__ASSERT_DEBUG(iReceiver.BufferSeq() == iReceiver.ExpectedTxSeq(),
       
   933 				   Panic(EL2CAPRejSentEnteredWithBufferedFrames));
       
   934 	
       
   935 	iReceiver.Controller().OutgoingQ().QueueNonAckingSFrame(*HSFramePDU::NewL(EReject), iReceiver.ExpectedTxSeq());
       
   936 	}
       
   937 
       
   938 void TL2CapErtmReceiverStateRejSent::HandleIncomingIFrameL(RMBufChain& aIFrame)
       
   939 	{
       
   940 	LOG_FUNC
       
   941 
       
   942 	__ASSERT_DEBUG(iReceiver.TxSeqExpectedBySduQ() == iReceiver.BufferSeq(),
       
   943 				   Panic(EL2CAPNextTxSeqExpectedBySduQNotEqualToBufferSeqWhenNotInSRejSent));
       
   944 
       
   945 	__ASSERT_DEBUG(InWindow(iReceiver.TxSeqExpectedBySduQ(), iReceiver.BufferSeq(), iReceiver.ExpectedTxSeq()),
       
   946 				   Panic(EL2CAPTxSeqExpectedBySduQNotWithinBufferSeqAndExpectedTxSeq));
       
   947 
       
   948 	__ASSERT_DEBUG(!iReceiver.LocalBusy(), Panic(EL2CAPInRejSentAndLocalBusy));
       
   949 
       
   950 	const TUint8 txSeq = HIFramePDU::TxSeqNumber(aIFrame);
       
   951 
       
   952 	if (iReceiver.ExpectedTxSeq() == txSeq)
       
   953 		// With-Expected-TxSeq
       
   954 		{
       
   955 		iReceiver.IncExpectedTxSeq();
       
   956 		if (!iReceiver.IsIncomingSduQFull())
       
   957 			{
       
   958 			iReceiver.SetBufferSeq(iReceiver.ExpectedTxSeq());
       
   959 			}
       
   960 
       
   961 		// Received the missing frame, clear REJ exception condition.
       
   962 		iReceiver.SetStateRecvL();
       
   963 
       
   964 		iReceiver.PassToIncomingQL(aIFrame);
       
   965 		}
       
   966 	else
       
   967 		{
       
   968 		// else it's a duplicate or unexpected frame:
       
   969 		// - drop the duplicate as usual,
       
   970 		// - drop the unexpected frame as we're already in a REJ exception condition
       
   971 		//   and aren't allowed to send a second REJ until the first one is cleared.
       
   972 		aIFrame.Free();
       
   973 		}
       
   974 	}
       
   975 
       
   976 void TL2CapErtmReceiverStateRejSent::HandlePollL()
       
   977 	{
       
   978 	LOG_FUNC
       
   979 	// General-case Poll handling: simply respond with a data frame or an ack frame with
       
   980 	// the Final bit set.
       
   981 	iReceiver.Controller().SendIOrRrOrRnrL(ETrue);
       
   982 	}
       
   983 
       
   984 void TL2CapErtmReceiverStateRejSent::TxSeqExpectedBySduQChanged(TUint8 aTxSeq)
       
   985 	{
       
   986 	LOG_FUNC
       
   987 	LOG1(_L("NextConsumedTxSeq moved: slipping BufferSeq to %d"), aTxSeq)
       
   988 	iReceiver.SetBufferSeq(aTxSeq);
       
   989 	__ASSERT_DEBUG(iReceiver.IsIncomingSduQFull() || iReceiver.BufferSeq() == iReceiver.ExpectedTxSeq(),
       
   990 				   Panic(EL2CAPBufferSeqNotEqualToExpectedTxSeqWhenInRecvAndSduQNotFull));
       
   991 	}
       
   992 
       
   993 
       
   994 TL2CapErtmReceiverStateSRejSent::TL2CapErtmReceiverStateSRejSent(CL2CapErtmDataReceiver& aReceiver)
       
   995  :	TL2CapErtmReceiverStateBase(aReceiver),
       
   996  	iGoToRej(EFalse)
       
   997 	{
       
   998 	LOG_FUNC
       
   999 	}
       
  1000 
       
  1001 void TL2CapErtmReceiverStateSRejSent::EnterL(RMBufChain* aIFrame)
       
  1002 	{
       
  1003 	LOG_FUNC
       
  1004 
       
  1005 	__ASSERT_DEBUG(!iReceiver.LocalBusy(), Panic(EL2CAPInSRejSentAndLocalBusy));
       
  1006 	__ASSERT_DEBUG(iMissingTxSeqs.IsEmpty(), Panic(EL2CAPNormalReceiveStateWhenMissingSRejFramesListIsNotEmpty));
       
  1007 	__ASSERT_DEBUG(aIFrame != NULL, Panic(EL2CAPDataFrameNotPassedOnEntryToSRejSent));
       
  1008 
       
  1009 	iGoToRej = EFalse;
       
  1010 	SendSRejsUpToReceivedIFrameL(*aIFrame);
       
  1011 	}
       
  1012 
       
  1013 void TL2CapErtmReceiverStateSRejSent::ExitL()
       
  1014 	{
       
  1015 	LOG_FUNC
       
  1016 	TL2CapErtmReceiverStateBase::ExitL();
       
  1017 	
       
  1018 	iMissingTxSeqs.Reset();
       
  1019 
       
  1020 	// BufferSeq was frozen once SREJ_SENT was entered. Now we can move it forward.
       
  1021 	if (iReceiver.IsIncomingSduQFull())
       
  1022 		{
       
  1023 		// If incoming SDU Q filled up during SREJ_SENT, then we can only move BufferSeq up to
       
  1024 		// the point at which that happened, not ExpectedTxSeq.
       
  1025 		iReceiver.SetBufferSeq(iReceiver.TxSeqExpectedBySduQ());
       
  1026 		}
       
  1027 	else
       
  1028 		{
       
  1029 		// Bring BufferSeq back in sync with ExpectedTxSeq.
       
  1030 		iReceiver.SetBufferSeq(iReceiver.ExpectedTxSeq());
       
  1031 		}
       
  1032 	LOG2(_L("On exit from SREJ_SENT[IsIncomingSduQFull = %d]: slipped BufferSeq to %d"),
       
  1033 		 iReceiver.IsIncomingSduQFull(), iReceiver.BufferSeq())
       
  1034 	}
       
  1035 
       
  1036 void TL2CapErtmReceiverStateSRejSent::HandleIncomingIFrameL(RMBufChain& aIFrame)
       
  1037 	{
       
  1038 	LOG_FUNC
       
  1039 
       
  1040 	__ASSERT_DEBUG(InWindow(iReceiver.TxSeqExpectedBySduQ(), iReceiver.BufferSeq(), iReceiver.ExpectedTxSeq()),
       
  1041 				   Panic(EL2CAPTxSeqExpectedBySduQNotWithinBufferSeqAndExpectedTxSeq));
       
  1042 
       
  1043 	__ASSERT_DEBUG(!iReceiver.LocalBusy(), Panic(EL2CAPInSRejSentAndLocalBusy));
       
  1044 
       
  1045 	const TUint8 txSeq = HIFramePDU::TxSeqNumber(aIFrame);
       
  1046 
       
  1047 	TBool freeFrame = ETrue;
       
  1048 	
       
  1049 	if (iMissingTxSeqs.ExpectedSRejTxSeq() == txSeq)
       
  1050 		// With-Expected-TxSeq-Srej
       
  1051 		{
       
  1052 		LOG1(_L("With-Expected-TxSeq-Srej: TxSeq=%d"), txSeq)
       
  1053 		iReceiver.PassToIncomingQL(aIFrame);
       
  1054 		freeFrame = EFalse;
       
  1055 
       
  1056 		TBool resendPreviousSRej = iMissingTxSeqs.ReceivedTxSeq(txSeq);
       
  1057 		__ASSERT_ALWAYS(!resendPreviousSRej, Panic(EL2CAPHaveSRejsToResendEvenThoughReceivedFirstInOrder));
       
  1058 
       
  1059 		if (iMissingTxSeqs.AllRequestedFramesReceived())
       
  1060 			{
       
  1061 			if (iGoToRej)
       
  1062 				{
       
  1063 				if (iReceiver.IsIncomingSduQFull())
       
  1064 					{
       
  1065 					// We couldn't have entered LocalBusy in SREJ_SENT, but now we can transition
       
  1066 					// to RECV with LocalBusy instead of REJ_SENT. The retransmission will be
       
  1067 					// started when we exit LocalBusy anyway.
       
  1068 					iReceiver.SetStateRecvL();
       
  1069 					// We rely on this...
       
  1070 					__ASSERT_DEBUG(iReceiver.LocalBusy(),
       
  1071 								   Panic(EL2CAPNotInLocalBusyAfterTransitionToRecvFromSrejSentWithSduQFull));
       
  1072 					}
       
  1073 				else
       
  1074 					{
       
  1075 					iReceiver.SetStateRejSentL();
       
  1076 					}
       
  1077 				}
       
  1078 			else // !iGoToRej
       
  1079 				{
       
  1080 				iReceiver.SetStateRecvL();
       
  1081 				}
       
  1082 			} // all SREJed frames received
       
  1083 		} // With-Expected-TxSeq-Srej
       
  1084 	else
       
  1085 		{
       
  1086 		if (iReceiver.ExpectedTxSeq() == txSeq)
       
  1087 			{
       
  1088 			// With-Expected-TxSeq
       
  1089 			if (!iGoToRej)
       
  1090 				{
       
  1091 				LOG1(_L("With-Expected-TxSeq: TxSeq=%d"), txSeq)
       
  1092 				iReceiver.IncExpectedTxSeq();
       
  1093 				iReceiver.PassToIncomingQL(aIFrame);
       
  1094 				freeFrame = EFalse;
       
  1095 				}
       
  1096 			}
       
  1097 		else if (InWindow(txSeq, iReceiver.BufferSeq(), iReceiver.ExpectedTxSeq()))
       
  1098 			{
       
  1099 			if (iMissingTxSeqs.IsTxSeqOnTheList(txSeq))
       
  1100 				// With-Unexpected-TxSeq-Srej
       
  1101 				{
       
  1102 				__ASSERT_DEBUG(TL2CapErtmMissingTxSeqs::KMaxSRejsInFlight > 1,
       
  1103 							   Panic(EL2CAPMultiSRejPathHitWhenNotSoConfigured));
       
  1104 
       
  1105 				// Multiple SRej requests have been made and some of the retransmitted I-Frames
       
  1106 				// were lost again. Send new SREJs for those frames.
       
  1107 
       
  1108 				__ASSERT_DEBUG(!iMissingTxSeqs.IsEmpty(), Panic(EL2CAPOldestSRejedFrameNotOnMissingList));
       
  1109 				LOG2(_L("With-Unexpected-TxSeq-Srej: TxSeq=%d. Expected was=%d"),
       
  1110 					 txSeq, iMissingTxSeqs.ExpectedSRejTxSeq())
       
  1111 
       
  1112 				TBool resendSRej = iMissingTxSeqs.ReceivedTxSeq(txSeq);
       
  1113 				while (resendSRej)
       
  1114 					{
       
  1115 					TUint8 resendTxSeq;
       
  1116 					resendSRej = iMissingTxSeqs.GetNextTxSeqForResend(resendTxSeq);
       
  1117 					iReceiver.Controller().OutgoingQ().QueueNonAckingSFrame(*HSFramePDU::NewL(ESelectiveReject), resendTxSeq);
       
  1118 					LOG1(_L("Resending SREJ for TxSeq=%d"), resendTxSeq)
       
  1119 					}
       
  1120 				iReceiver.PassToIncomingQL(aIFrame);
       
  1121 				freeFrame = EFalse;
       
  1122 				}
       
  1123 			else // else must be a duplicate: With-duplicate-TxSeq-Srej
       
  1124 				{
       
  1125 				LOG1(_L("With-duplicate-TxSeq-Srej: TxSeq=%d"), txSeq)
       
  1126 				}
       
  1127 			}
       
  1128 		else if (!iGoToRej) // With-Unexpected-TxSeq
       
  1129 			{
       
  1130 			LOG1(_L("With-Unexpected-TxSeq: TxSeq=%d."), txSeq)
       
  1131 			if (iReceiver.IsSRejPreferredToRej(iReceiver.ExpectedTxSeq(), txSeq) &&
       
  1132 				iMissingTxSeqs.HaveSpaceForNewTxSeqs(Mod64(txSeq - iReceiver.ExpectedTxSeq())))
       
  1133 				{
       
  1134 				__ASSERT_DEBUG(TL2CapErtmMissingTxSeqs::KMaxSRejsInFlight > 1,
       
  1135 							   Panic(EL2CAPMultiSRejPathHitWhenNotSoConfigured));
       
  1136 				SendSRejsUpToReceivedIFrameL(aIFrame);
       
  1137 				freeFrame = EFalse;
       
  1138 				}
       
  1139 			else
       
  1140 				{
       
  1141 				// Don't send more SREJs. Wait for I-Frames requested so far to be
       
  1142 				// retransmitted and go to REJ mode.
       
  1143 				iGoToRej = ETrue;
       
  1144 				LOG1(_L("NumMissingTxSeqs=%d, GoToRej=1"), iMissingTxSeqs.NumMissingTxSeqs())
       
  1145 				}
       
  1146 			}
       
  1147 		} // !With-Expected-TxSeq-Srej
       
  1148 
       
  1149 	if (freeFrame)
       
  1150 		{
       
  1151 		aIFrame.Free();
       
  1152 		}
       
  1153 	}
       
  1154 
       
  1155 void TL2CapErtmReceiverStateSRejSent::HandlePollL()
       
  1156 	{
       
  1157 	LOG_FUNC
       
  1158 	__ASSERT_DEBUG(!iMissingTxSeqs.IsEmpty(), Panic(EL2CAPCaughtInSRejSentWithNoMissingTxSeqs));
       
  1159 
       
  1160 	HSFramePDU* frame = HSFramePDU::NewL(ESelectiveReject);
       
  1161 	frame->SetFinalBit(ETrue);
       
  1162 	iReceiver.OutgoingQ().QueueNonAckingSFrame(*frame, iMissingTxSeqs.LastTxSeq());
       
  1163 	}
       
  1164 
       
  1165 void TL2CapErtmReceiverStateSRejSent::TxSeqExpectedBySduQChanged(TUint8 /*aTxSeq*/)
       
  1166 	{
       
  1167 	LOG_FUNC
       
  1168 	// Can't slip BufferSeq until SREJ_SENT is left.
       
  1169 	}
       
  1170 
       
  1171 void TL2CapErtmReceiverStateSRejSent::SendSRejsUpToReceivedIFrameL(RMBufChain& aIFrame)
       
  1172 	{
       
  1173 	LOG_FUNC
       
  1174 
       
  1175 	const TUint8 receivedTxSeq = HIFramePDU::TxSeqNumber(aIFrame);
       
  1176 
       
  1177 	for (TUint8 sRejSeq = iReceiver.ExpectedTxSeq(); sRejSeq != receivedTxSeq; sRejSeq = Mod64(sRejSeq + 1))
       
  1178 		{
       
  1179 		iMissingTxSeqs.AppendTxSeq(sRejSeq);
       
  1180 		iReceiver.OutgoingQ().QueueNonAckingSFrame(*HSFramePDU::NewL(ESelectiveReject), sRejSeq);
       
  1181 		}
       
  1182 
       
  1183 	iReceiver.SetExpectedTxSeq(Mod64(receivedTxSeq + 1));
       
  1184 	iReceiver.PassToIncomingQL(aIFrame);
       
  1185 
       
  1186 	LOG3(_L("ExpectedTxSeq = %d, First Expected SREJed TxSeq = %d, Last Expected SREJed TxSeq = %d"),
       
  1187 		 iReceiver.ExpectedTxSeq(), iMissingTxSeqs.ExpectedSRejTxSeq(), iMissingTxSeqs.LastTxSeq())
       
  1188 	}
       
  1189 
       
  1190 RL2CapErtmIncomingIFrameQueue::RL2CapErtmIncomingIFrameQueue()
       
  1191  : iTxSeqExpectedBySduQ(0)
       
  1192 	{
       
  1193 	LOG_FUNC
       
  1194 	}
       
  1195 
       
  1196 void RL2CapErtmIncomingIFrameQueue::Close()
       
  1197 	{
       
  1198 	LOG_FUNC
       
  1199 	if (!iQueue.IsEmpty())
       
  1200 		{
       
  1201 		LOG(_L("Incoming I-Frame queue not empty, freeing mbufs."))
       
  1202 		iQueue.Free();
       
  1203 		}
       
  1204 	}
       
  1205 
       
  1206 
       
  1207 void RL2CapErtmIncomingIFrameQueue::HandleIncomingIFrameL(RMBufChain& aIFrame, const CL2CapErtmDataReceiver& aReceiver)
       
  1208 	{
       
  1209 	LOG_FUNC
       
  1210 	Insert(aIFrame);
       
  1211 	if (!aReceiver.IsIncomingSduQFull())
       
  1212 		{
       
  1213 		ConsumeUpToFirstGapL(aReceiver);
       
  1214 		}
       
  1215 	}
       
  1216 
       
  1217 void RL2CapErtmIncomingIFrameQueue::Insert(RMBufChain& aIFrame)
       
  1218 	{
       
  1219 	LOG_FUNC
       
  1220 	const TUint8 txSeq = HIFramePDU::TxSeqNumber(aIFrame);
       
  1221 	LOG2(_L("TxSeq=%d, NextConsumedTxSeq=%d"), txSeq, iTxSeqExpectedBySduQ)
       
  1222 
       
  1223 	if (iQueue.IsEmpty() || !InWindow(txSeq, iTxSeqExpectedBySduQ, HIFramePDU::TxSeqNumber(iQueue.Last())))
       
  1224 		// Fast path for the most common cases.
       
  1225 		{
       
  1226 		__ASSERT_DEBUG(iQueue.IsEmpty() || txSeq != HIFramePDU::TxSeqNumber(iQueue.Last()),
       
  1227 					   Panic(EL2CapDuplicateIFramePassedToIncomingQ));
       
  1228 		iQueue.Append(aIFrame);
       
  1229 		LOG(_L("Appending on fast path"))
       
  1230 		}
       
  1231 	else
       
  1232 		// Generic insertion algorithm.
       
  1233 		// Depends on there not being duplicate TxSeqs on the queue, i.e. the queue mustn't contain
       
  1234 		// acknowledged frames. It can only contain frames within the current receive window.
       
  1235 		{
       
  1236 		TBool inserted = EFalse;
       
  1237 		for (TMBufPktQIter iter(iQueue); !inserted && iter.More(); iter++)
       
  1238 			{
       
  1239 			TUint8 currentTxSeq = HIFramePDU::TxSeqNumber(iter.Current());
       
  1240 			__ASSERT_DEBUG(txSeq != currentTxSeq, Panic(EL2CapDuplicateIFramePassedToIncomingQ));
       
  1241 
       
  1242 			if (InWindow(txSeq, iTxSeqExpectedBySduQ, currentTxSeq))
       
  1243 				{
       
  1244 				LOG1(_L("Inserting before %d"), currentTxSeq)
       
  1245 				iter.Insert(aIFrame);
       
  1246 				inserted = ETrue;
       
  1247 				}
       
  1248 			}
       
  1249 		if (!inserted)
       
  1250 			{
       
  1251 			// It's actually impossible to get here with the fast path in the beginning
       
  1252 			// of the function, but it's here for testing of the loop. Might change to
       
  1253 			// __ASSERT_DEBUG when the testing dust settles.
       
  1254 			LOG(_L("Gone through the Q, appending"))
       
  1255 			iQueue.Append(aIFrame);
       
  1256 			}
       
  1257 		}
       
  1258 #ifdef _DEBUG
       
  1259 	LogQ();
       
  1260 #endif
       
  1261 	}
       
  1262 
       
  1263 #ifdef _DEBUG
       
  1264 void RL2CapErtmIncomingIFrameQueue::LogQ()
       
  1265 	{
       
  1266 	LOG_FUNC
       
  1267 	TMBufPktQIter i(iQueue);
       
  1268 	TBuf<512> buf;
       
  1269 	while (i.More())
       
  1270 		{
       
  1271 		buf.AppendFormat(_L("%d "), HIFramePDU::TxSeqNumber(i++));
       
  1272 		}
       
  1273 	LOG1(_L("Q: %S"), &buf)
       
  1274 	}
       
  1275 #endif
       
  1276 
       
  1277 void RL2CapErtmIncomingIFrameQueue::ConsumeUpToFirstGapL(const CL2CapErtmDataReceiver& aReceiver)
       
  1278 	{
       
  1279 	LOG_FUNC
       
  1280 	while (!iQueue.IsEmpty() && iTxSeqExpectedBySduQ == HIFramePDU::TxSeqNumber(iQueue.First())
       
  1281 		   && !aReceiver.IsIncomingSduQFull())
       
  1282 		{
       
  1283 		RMBufChain frame;
       
  1284 		//Check on return value of iQueue.Remove() is unnecessary, since we've checked iQueue.IsEmpty()
       
  1285 		static_cast<void>(iQueue.Remove(frame));
       
  1286 		iTxSeqExpectedBySduQ = Mod64(iTxSeqExpectedBySduQ + 1);
       
  1287 		// This feeds the frame to the SDU Queue. This is also the place where we get notified
       
  1288 		// if the queue gets full. If that happens, SetIncomingSduQFull is synchronously
       
  1289 		// called by SDU Q here in the same stack frame - hence the guard in the loop condition.
       
  1290 		aReceiver.PassToSduQL(frame);
       
  1291 		}
       
  1292 	LOG3(_L("On return from ConsumeUpToFirstGap: Queue empty=%d, NextConsumedTxSeq=%d, IsIncomingSduQFull=%d"),
       
  1293 		 iQueue.IsEmpty(), iTxSeqExpectedBySduQ, aReceiver.IsIncomingSduQFull())
       
  1294 
       
  1295 #ifdef _DEBUG
       
  1296 	LogQ();
       
  1297 #endif
       
  1298 	}
       
  1299 
       
  1300 
       
  1301 CL2CapErtmDataReceiver* CL2CapErtmDataReceiver::NewL(CL2CapEnhancedReTxController& aController)
       
  1302 	{
       
  1303 	LOG_STATIC_FUNC
       
  1304 	CL2CapErtmDataReceiver* receiver = new (ELeave) CL2CapErtmDataReceiver(aController);
       
  1305 	CleanupStack::PushL(receiver);
       
  1306 	receiver->ConstructL();
       
  1307 	CleanupStack::Pop(receiver);
       
  1308 	return receiver;
       
  1309 	}
       
  1310 
       
  1311 void CL2CapErtmDataReceiver::ConstructL()
       
  1312 	{
       
  1313 	LOG_FUNC
       
  1314 	iReceiveState = &iStateRecv;
       
  1315 	iReceiveState->EnterL(NULL);
       
  1316 	}
       
  1317 
       
  1318 CL2CapErtmDataReceiver::CL2CapErtmDataReceiver(CL2CapEnhancedReTxController& aController)
       
  1319  :	iController(aController),
       
  1320 	iExpectedTxSeq(0),
       
  1321 	iBufferSeq(0),
       
  1322 	iLastAckReqSeq(0),
       
  1323 	iIncomingSduQFull(EFalse),
       
  1324 	iLocalBusy(EFalse),
       
  1325 	iInWaitFState(EFalse),
       
  1326 	iWaitFStatePending(EFalse),
       
  1327 	iSendAck(EFalse),
       
  1328 	iStateRecv(*this),
       
  1329 	iStateRejSent(*this),
       
  1330 	iStateSRejSent(*this)
       
  1331 	{
       
  1332 	LOG_FUNC
       
  1333 	}
       
  1334 
       
  1335 CL2CapErtmDataReceiver::~CL2CapErtmDataReceiver()
       
  1336 	{
       
  1337 	LOG_FUNC
       
  1338 	iIncomingIFrameQ.Close();
       
  1339 	}
       
  1340 
       
  1341 void CL2CapErtmDataReceiver::HandleIncomingIFrameL(RMBufChain& aIFrame)
       
  1342 	{
       
  1343 	LOG_FUNC
       
  1344 	LOG3(_L("ExpectedTxSeq=%d, BufferSeq=%d, LastAckReqSeq=%d"),
       
  1345 		 iExpectedTxSeq, iBufferSeq, iLastAckReqSeq)
       
  1346 
       
  1347 	if (HIFramePDU::FinalBit(aIFrame))
       
  1348 		{
       
  1349 		// It's important that this is executed first, we wouldn't like to drop an I-Frame that
       
  1350 		// carries the Final Ack if we're in WAIT_F. If the remote has set F=1 then it must have
       
  1351 		// received the Poll and is therefore aware of the ReqSeq we've sent in RR[P=1].
       
  1352 		// So if the remote is a correct implementation, then this I-Frame is the one we're
       
  1353 		// expecting and we shouldn't drop it.
       
  1354 		HandleFinalAckL();
       
  1355 		}
       
  1356 
       
  1357 	if (// While we're in WAIT_F, peer may be still sending us I-Frames that are newer than those
       
  1358 		// acknowledged by the RR[P=1] frame. They will be retransmitted when it receives the RR,
       
  1359 		// so we can't accept the original transmissions, as that would move ExpectedAckSeq and
       
  1360 		// thus cause the retransmissions to be invalid - we'd close the connection.
       
  1361 		!iInWaitFState &&
       
  1362 		// ... also need to drop I-Frames when waiting to enter WAIT_F - if we're in WAIT_ACK,
       
  1363 		// then iWaitFStatePending persists for an extended period of time during which we may
       
  1364 		// have sent an RR due to some other unrelated reason. The peer started retransmitting
       
  1365 		// when it got that RR, which makes the situation identical to being in WAIT_F.
       
  1366 		// Ideally the spec would say that RR[P=1] makes the peer start retransmitting from
       
  1367 		// the given ReqSeq and RR[P=0] just makes it pick up where it left it, but it's not
       
  1368 		// the case - both restart the transmission, so both must be treated equally.
       
  1369 		!iWaitFStatePending)
       
  1370 		{
       
  1371 		const TUint8 bufferSeqBefore = iBufferSeq;
       
  1372 
       
  1373 		iReceiveState->HandleIncomingIFrameL(aIFrame);
       
  1374 
       
  1375 		if (iBufferSeq != bufferSeqBefore	// anything new to ack ?
       
  1376 			&& !iSendAck)					// an ack already pending ?
       
  1377 			{
       
  1378 			iSendAck = IsEndOfReceiveWindowApproaching();
       
  1379 			if (!iSendAck)
       
  1380 				{
       
  1381 				// Note that we'll never fall here if PeerTxWin <= KReceiveWinFreeSpaceLeftToTriggerAck
       
  1382 				if (!TimerMan().IsSendPeerAckTimerRunning())
       
  1383 					{
       
  1384 					if (!TimerMan().StartSendPeerAckTimer())
       
  1385 						{
       
  1386 						// The timer could not be started. Send an ack immediately.
       
  1387 						iSendAck = ETrue;
       
  1388 						}
       
  1389 					}
       
  1390 				}
       
  1391 			}
       
  1392 		} // !WAIT_F
       
  1393 	else
       
  1394 		{
       
  1395 		aIFrame.Free();
       
  1396 		}
       
  1397 	}
       
  1398 
       
  1399 void CL2CapErtmDataReceiver::HandleIncomingSFrameL(RMBufChain& aSFrame)
       
  1400 	{
       
  1401 	LOG_FUNC
       
  1402 	LOG3(_L("ExpectedTxSeq=%d, BufferSeq=%d, LastAckReqSeq=%d"),
       
  1403 		 iExpectedTxSeq, iBufferSeq, iLastAckReqSeq)
       
  1404 
       
  1405 	const TBool poll = HSFramePDU::PollBit(aSFrame);
       
  1406 	const TBool final = HSFramePDU::FinalBit(aSFrame);
       
  1407 	const TSupervisoryFunction function = HSFramePDU::SupervisoryFunction(aSFrame);
       
  1408 
       
  1409 	if (poll && final)
       
  1410 		{
       
  1411 		LOG(_L("Incoming S-Frame has both P and F bits set!"))
       
  1412 		LEAVEL(KErrL2CAPIllegalRemoteBehavior);
       
  1413 		}
       
  1414 
       
  1415 	if (final)
       
  1416 		{
       
  1417 		HandleFinalAckL();
       
  1418 		}
       
  1419 	
       
  1420 	if (poll && function != ESelectiveReject) // SREJ[P=1] is handled by the transmitter.
       
  1421 		{
       
  1422 		iReceiveState->HandlePollL();
       
  1423 		}
       
  1424 	}
       
  1425 
       
  1426 void CL2CapErtmDataReceiver::HandleFinalAckL()
       
  1427 	{
       
  1428 	LOG_FUNC
       
  1429 	if (iInWaitFState)
       
  1430 		{
       
  1431 		iInWaitFState = EFalse;
       
  1432 		if (iIncomingSduQFull)
       
  1433 			{
       
  1434 			// Incoming SDU Q filled up again while we were exiting the previous LB condition.
       
  1435 			UpdateLocalBusyStatusL();
       
  1436 			}
       
  1437 		}
       
  1438 	}
       
  1439 
       
  1440 void CL2CapErtmDataReceiver::SetIncomingSduQFullL(TBool aIncomingSduQFull)
       
  1441 	{
       
  1442 	LOG_FUNC
       
  1443 	LOG2(_L("Incoming SDU Q full %d -> %d"), iIncomingSduQFull, aIncomingSduQFull)
       
  1444 
       
  1445 	if (!iIncomingSduQFull && aIncomingSduQFull)
       
  1446 		{
       
  1447 		// Don't enter LocalBusy even if we can, start the delay timer instead.
       
  1448 		// If the queue remains full until its expiry, we'll enter LocalBusy then.
       
  1449 		// LocalBusy means we inform the peer of our busy condition by sending RNRs
       
  1450 		// instead of RRs.
       
  1451 		// We refrain from entering LocalBusy right off because exiting it means
       
  1452 		// that the peer will have to restart the transmission from a seqnum given by us
       
  1453 		// in the RR exiting the LocalBusy condition, which in turn means some frames
       
  1454 		// which are already in transit (if there are any) will be lost. So if the full
       
  1455 		// SDU Q is just a momentary hiccup, we hide this from the peer and just buffer
       
  1456 		// the incoming frames and anchor BufferSeq at its current value to prevent the
       
  1457 		// receive window from moving.
       
  1458 		TimerMan().StartLocalBusyDelayTimer();
       
  1459 		}
       
  1460 	else if (iIncomingSduQFull && !aIncomingSduQFull)
       
  1461 		{
       
  1462 		TimerMan().StopLocalBusyDelayTimer();
       
  1463 		}
       
  1464 
       
  1465 	iIncomingSduQFull = aIncomingSduQFull;
       
  1466 	UpdateLocalBusyStatusL();
       
  1467 	}
       
  1468 
       
  1469 // This routine manages the LocalBusy status by evaluating the necessary conditions:
       
  1470 // - whether the incoming SDU queue is full at the moment,
       
  1471 // - whether LocalBusy delay timer is still running,
       
  1472 // - whether we're exiting a previous LocalBusy condition,
       
  1473 // - whether we're able to enter LB in current receive state (LB is only allowed in RECV).
       
  1474 void CL2CapErtmDataReceiver::UpdateLocalBusyStatusL()
       
  1475 	{
       
  1476 	LOG_FUNC
       
  1477 	LOG5(_L("iIncomingSduQFull=%d, iLocalBusy=%d, iWaitF=%d, iWaitFPending=%d, recv state = 0x%08x"),
       
  1478 		 iIncomingSduQFull, iLocalBusy, iInWaitFState, iWaitFStatePending, iReceiveState)
       
  1479 
       
  1480 	if (iIncomingSduQFull)
       
  1481 		{
       
  1482 		if (!iLocalBusy && !TimerMan().IsLocalBusyDelayTimerRunning())
       
  1483 			{
       
  1484 			if (!iInWaitFState && !iWaitFStatePending // have to wait until previous LB is properly finished
       
  1485 				&& iReceiveState->IsLocalBusySupported()) // only RECV
       
  1486 				{
       
  1487 				EnterLocalBusyL();
       
  1488 				}
       
  1489 			}
       
  1490 		// Once we enter LB the receive state is locked onto RECV so don't have to check whether
       
  1491 		// it's changed.
       
  1492 		}
       
  1493 	else // !iIncomingSduQFull
       
  1494 		{
       
  1495 		// First we need to consume the frames on the incoming Q, which may cause the SDU Q to
       
  1496 		// fill up again.
       
  1497 		iIncomingIFrameQ.ConsumeUpToFirstGapL(*this);
       
  1498 
       
  1499 		if (!iIncomingSduQFull)
       
  1500 			// Incoming SDU Q didn't fill up again in ConsumeUpToFirstGapL().
       
  1501 			{
       
  1502 			if (iLocalBusy)
       
  1503 				{
       
  1504 				// iLocalBusy is only possible when iInWaitFState && iWaitFStatePending are false
       
  1505 				// and the only receive state in LB is RECV, so we can exit it anytime.
       
  1506 				__ASSERT_DEBUG(iReceiveState == &iStateRecv && !iInWaitFState && !iWaitFStatePending,
       
  1507 							   Panic(EL2CAPLocalBusyUnderIllegalConditions));
       
  1508 				ExitLocalBusy();
       
  1509 				}
       
  1510 			}
       
  1511 		else // Incoming SDU Q filled up again in ConsumeUpToFirstGapL().
       
  1512 			{
       
  1513 			// Some frames have been consumed and we've restarted the LB delay timer,
       
  1514 			// so it's a good idea to ack now. 
       
  1515 			iSendAck = ETrue;
       
  1516 			}
       
  1517 
       
  1518 		// Give the receive state a chance to sync BufferSeq with TxSeqExpectedBySduQ.
       
  1519 		// Must keep them in sync with if we can - there're reasons for that - see
       
  1520 		// TL2CapErtmReceiverStateRecv::HandlePollL. We don't do that in SREJ_SENT though
       
  1521 		// as BufferSeq can't change in that state but it's cool because our response to
       
  1522 		// a Poll in SREJ_SENT will be SREJ which doesn't trigger retransmission of all
       
  1523 		// unacked I-Frames and there's a separate mechanism for the peer to protect
       
  1524 		// itself against a duplicate SREJ[F=1].
       
  1525 		// This is asserted through the code.
       
  1526 		iReceiveState->TxSeqExpectedBySduQChanged(iIncomingIFrameQ.TxSeqExpectedBySduQ());
       
  1527 
       
  1528 		__ASSERT_DEBUG(iIncomingSduQFull ||
       
  1529 					   ((iReceiveState != &iStateSRejSent &&
       
  1530 						 iIncomingIFrameQ.TxSeqExpectedBySduQ() == iBufferSeq &&
       
  1531 						 iBufferSeq == iExpectedTxSeq) ||
       
  1532 					    (iReceiveState == &iStateSRejSent)),
       
  1533 					   Panic(EL2CAPWindowInformationInconsistentWhenExitingSduQFull));
       
  1534 
       
  1535 		__ASSERT_DEBUG(!iIncomingSduQFull ||
       
  1536 					   ((iReceiveState != &iStateSRejSent &&
       
  1537 						 iIncomingIFrameQ.TxSeqExpectedBySduQ() == iBufferSeq) ||
       
  1538 						(iReceiveState == &iStateSRejSent)),
       
  1539 					   Panic(EL2CAPWindowInformationInconsistentAfterMovingBufferSeqWhenSduQFull));
       
  1540 		} // !iIncomingSduQFull
       
  1541 	}
       
  1542 
       
  1543 void CL2CapErtmDataReceiver::EnterLocalBusyL()
       
  1544 	{
       
  1545 	LOG_FUNC
       
  1546 	__ASSERT_DEBUG(!TimerMan().IsLocalBusyDelayTimerRunning(),
       
  1547 				   Panic(EL2CAPEnterLocalBusyCalledWhileDelayTimerStillRunning));
       
  1548 
       
  1549 	iLocalBusy = ETrue;
       
  1550 	// Send an RNR immediately.
       
  1551 	iSendAck = ETrue;
       
  1552 	iController.NotifyMuxerOfPdusToSendIfHaveSome();
       
  1553 	}
       
  1554 
       
  1555 void CL2CapErtmDataReceiver::ExitLocalBusy()
       
  1556 	{
       
  1557 	LOG_FUNC
       
  1558 	iLocalBusy = EFalse;
       
  1559 	// Signal to GetPdu that we need to enter WAIT_F.
       
  1560 	iWaitFStatePending = ETrue;
       
  1561 	iController.NotifyMuxerOfPdusToSendIfHaveSome();
       
  1562 	}
       
  1563 
       
  1564 template<typename FrameType>
       
  1565 void CL2CapErtmDataReceiver::StampWithReqSeq(FrameType& aFrame)
       
  1566 	{
       
  1567 	LOG_FUNC
       
  1568 	__ASSERT_DEBUG(!aFrame.IsQueuedForSend(), Panic(EL2CAPReqSeqSetOnFrameAlreadyQueuedForSend));
       
  1569 
       
  1570 	aFrame.SetReqSeqNumber(iLastAckReqSeq = iBufferSeq);
       
  1571 	TimerMan().StopSendPeerAckTimer();
       
  1572 	iSendAck = EFalse;
       
  1573 	}
       
  1574 
       
  1575 TBool CL2CapErtmDataReceiver::IsSRejPreferredToRej(TUint8 aExpectedTxSeq, TUint8 aReceivedTxSeq)
       
  1576 	{
       
  1577 	LOG_FUNC
       
  1578 	return InWindow(aReceivedTxSeq, aExpectedTxSeq, Mod64(aExpectedTxSeq + KSRejMissingFrameThreshold));
       
  1579 	}
       
  1580 
       
  1581 void CL2CapErtmDataReceiver::LocalBusyDelayTimerExpired()
       
  1582 	{
       
  1583 	LOG_FUNC
       
  1584 
       
  1585 	// This guards from the classic state-changed-between-timer-expiry-and-handler-entry
       
  1586 	// race condition.
       
  1587 	if (iIncomingSduQFull)
       
  1588 		{
       
  1589 		TRAPD(err, UpdateLocalBusyStatusL());
       
  1590 		if (err != KErrNone)
       
  1591 			{
       
  1592 			iController.ErrorD(err);
       
  1593 			// Just joined the majority.
       
  1594 			}
       
  1595 		}
       
  1596 	}
       
  1597 
       
  1598 TBool CL2CapErtmDataReceiver::IsEndOfReceiveWindowApproaching() const
       
  1599 	{
       
  1600 	LOG_FUNC
       
  1601 	TBool ackNeeded = EFalse;
       
  1602 
       
  1603 	const TUint8 numFramesReceivedSinceLastAck = Mod64(iExpectedTxSeq - iLastAckReqSeq);
       
  1604 	const TInt numFramesReceivedBeforeWantToSendAck = iController.Config().PeerTXWindowSize() - KReceiveWinFreeSpaceLeftToTriggerAck; 
       
  1605 	if (numFramesReceivedSinceLastAck >= numFramesReceivedBeforeWantToSendAck)
       
  1606 		{
       
  1607 		LOG2(_L("LastAckReqSeq = %d, ExpectedTxSeq = %d. Reaching end of window, will send an ack."),
       
  1608 			 iLastAckReqSeq, iExpectedTxSeq)
       
  1609 		ackNeeded = ETrue;
       
  1610 		}
       
  1611 	return ackNeeded;
       
  1612 	}
       
  1613 
       
  1614 void CL2CapErtmDataReceiver::SendPeerAckTimerExpiredL()
       
  1615 	{
       
  1616 	LOG_FUNC
       
  1617 	if (iBufferSeq != iLastAckReqSeq)
       
  1618 		{
       
  1619 		iSendAck = ETrue;
       
  1620 		iController.NotifyMuxerOfPdusToSendIfHaveSome();
       
  1621 		}
       
  1622 	}
       
  1623 
       
  1624 HSFramePDU* CL2CapErtmDataReceiver::GetAckFrameL(TBool aFinal)
       
  1625 	{
       
  1626 	HSFramePDU* frame = HSFramePDU::NewL(iLocalBusy ? EReceiverNotReady : EReceiverReady);
       
  1627 	frame->SetFinalBit(aFinal);
       
  1628 	return frame;
       
  1629 	}
       
  1630 
       
  1631 void CL2CapErtmDataReceiver::SetStateL(TL2CapErtmReceiverStateBase& aState, RMBufChain* aIFrame)
       
  1632 	{
       
  1633 	LOG_FUNC
       
  1634 	iReceiveState->ExitL();
       
  1635 	iReceiveState = &aState;
       
  1636 	iReceiveState->EnterL(aIFrame);
       
  1637 	}
       
  1638 
       
  1639 
       
  1640 RL2CapErtmOutgoingQueue::RL2CapErtmOutgoingQueue(CL2CapEnhancedReTxController& aController)
       
  1641  :	iController(aController),
       
  1642 	iOutgoingQ(_FOFF(HL2CapPDU, iDataControllerInternalQLink)),
       
  1643 	iPendRetransmitIFrameQ(_FOFF(HL2CapPDU, iDataControllerInternalQLink))
       
  1644 	{
       
  1645 	LOG_FUNC
       
  1646 	}
       
  1647 
       
  1648 void RL2CapErtmOutgoingQueue::Close()
       
  1649 	{
       
  1650 	LOG_FUNC
       
  1651 	DeleteAllFrames();
       
  1652 	}
       
  1653 
       
  1654 void RL2CapErtmOutgoingQueue::QueueIFrameL(HIFramePDU& aIFrame)
       
  1655 	{
       
  1656 	LOG_FUNC
       
  1657 	if (!TRetransmissionAndFlowControlOption::EnhancedMaxTransmitLessOrEqual(aIFrame.TransmissionCount() + 1,
       
  1658 																			 iController.Config().MaxTransmit()))
       
  1659 		{
       
  1660 		LOG2(_L("MaxTransmit=%d exceeded by I-Frame no %d"),
       
  1661 			 iController.Config().MaxTransmit(), aIFrame.TxSeqNumber())
       
  1662 		LEAVEL(KErrL2CAPMaxTransmitExceeded);
       
  1663 		}
       
  1664 	else if (aIFrame.IsQueuedForSend())
       
  1665 		{
       
  1666 		// This is either due to the I-Frame being SREJ-requested twice or a bug
       
  1667 		// in our code. We don't have enough information to tell between the two,
       
  1668 		// so have to assume it's the former.
       
  1669 		LOG1(_L("I-Frame no %d already queued for send"), aIFrame.TxSeqNumber())
       
  1670 		LEAVEL(KErrL2CAPIllegalRemoteBehavior);
       
  1671 		}
       
  1672 
       
  1673 	iController.StampWithReqSeq(aIFrame);
       
  1674 	iOutgoingQ.AddLast(aIFrame);
       
  1675 	aIFrame.SetQueuedForSend(ETrue);
       
  1676 	LOG3(_L("Queued I-Frame for send, TxSeq=%d, ReqSeq=%d, F=%d"),
       
  1677 		 aIFrame.TxSeqNumber(), aIFrame.ReqSeqNumber(), aIFrame.FinalBit())
       
  1678 	}
       
  1679 
       
  1680 void RL2CapErtmOutgoingQueue::QueueAckingSFrame(HSFramePDU& aSFrame)
       
  1681 	{
       
  1682 	LOG_FUNC
       
  1683 	// This method is meant only for those S-Frames which carry an acknowledgement number.
       
  1684 	__ASSERT_DEBUG(aSFrame.SupervisoryFunction() != ESelectiveReject || aSFrame.PollBit(),
       
  1685 				   Panic(EL2CAPSendSFrameWithAckCalledForSRejP0));
       
  1686 	// S-Frames are fire-n-forget, no healthy S-Frame gets queued twice!
       
  1687 	__ASSERT_DEBUG(!aSFrame.IsQueuedForSend(), Panic(EL2CAPSFrameQueuedForSendTwice));
       
  1688 
       
  1689 	iController.StampWithReqSeq(aSFrame);
       
  1690 	iOutgoingQ.AddLast(aSFrame);
       
  1691 	aSFrame.SetQueuedForSend(ETrue);
       
  1692 	LOG4(_L("Queued S-Frame for send, S=%d, ReqSeq=%d, P=%d, F=%d"),
       
  1693 		 aSFrame.SupervisoryFunction(), aSFrame.ReqSeqNumber(), aSFrame.PollBit(), aSFrame.FinalBit())
       
  1694 	}
       
  1695 
       
  1696 void RL2CapErtmOutgoingQueue::QueueNonAckingSFrame(HSFramePDU& aSFrame, TUint8 aReqSeq)
       
  1697 	{
       
  1698 	LOG_FUNC
       
  1699 	// S-Frames are fire-n-forget, no healthy S-Frame gets queued twice!
       
  1700 	__ASSERT_DEBUG(!aSFrame.IsQueuedForSend(), Panic(EL2CAPSFrameQueuedForSendTwice));
       
  1701 
       
  1702 	aSFrame.SetReqSeqNumber(aReqSeq);
       
  1703 	iOutgoingQ.AddLast(aSFrame);
       
  1704 	aSFrame.SetQueuedForSend(ETrue);
       
  1705 	LOG4(_L("Queued S-Frame for send, S=%d, ReqSeq=%d, P=%d, F=%d"),
       
  1706 		 aSFrame.SupervisoryFunction(), aSFrame.ReqSeqNumber(), aSFrame.PollBit(), aSFrame.FinalBit())
       
  1707 	}
       
  1708 
       
  1709 void RL2CapErtmOutgoingQueue::PendRetransmitIFrameL(HIFramePDU& aIFrame)
       
  1710 	{
       
  1711 	LOG_FUNC
       
  1712 	if (aIFrame.IsQueuedForSend())
       
  1713 		{
       
  1714 		// This is either due to the I-Frame being SREJ-requested twice or a bug
       
  1715 		// in our code. We don't have enough information to tell between the two,
       
  1716 		// so have to assume it's the former.
       
  1717 		LOG1(_L("I-Frame no %d already queued for send!"), aIFrame.TxSeqNumber())
       
  1718 		LEAVEL(KErrL2CAPIllegalRemoteBehavior);
       
  1719 		}
       
  1720 	iPendRetransmitIFrameQ.AddLast(aIFrame);
       
  1721 	aIFrame.SetQueuedForSend(ETrue);
       
  1722 	LOG3(_L("Queued I-Frame pending retransmission, TxSeq=%d, ReqSeq=%d, F=%d"),
       
  1723 		 aIFrame.TxSeqNumber(), aIFrame.ReqSeqNumber(), aIFrame.FinalBit())
       
  1724 	}
       
  1725 
       
  1726 void RL2CapErtmOutgoingQueue::SendPendingRetransmitIFramesL()
       
  1727 	{
       
  1728 	LOG_FUNC
       
  1729 	if (!iPendRetransmitIFrameQ.IsEmpty())
       
  1730 		{
       
  1731 		TSglQueIter<HIFramePDU> iter(iPendRetransmitIFrameQ);
       
  1732 		while (HIFramePDU* eyeFrame = iter++)
       
  1733 			{
       
  1734 			eyeFrame->SetQueuedForSend(EFalse);	// QueueIFrameL would leave if this flag was set.
       
  1735 			QueueIFrameL(*eyeFrame);
       
  1736 			}
       
  1737 		iPendRetransmitIFrameQ.Reset();
       
  1738 		}
       
  1739 	}
       
  1740 
       
  1741 void RL2CapErtmOutgoingQueue::CancelPendingRetransmitIFrames()
       
  1742 	{
       
  1743 	LOG_FUNC
       
  1744 	if (!iPendRetransmitIFrameQ.IsEmpty())
       
  1745 		{
       
  1746 		TSglQueIter<HIFramePDU> iter(iPendRetransmitIFrameQ);
       
  1747 		while (HIFramePDU* eyeFrame = iter++)
       
  1748 			{
       
  1749 			LOG1(_L("Cancelling SREJ-requested pending retransmission of I-Frame %d"),
       
  1750 				 eyeFrame->TxSeqNumber())
       
  1751 			eyeFrame->SetQueuedForSend(EFalse);
       
  1752 			}
       
  1753 		iPendRetransmitIFrameQ.Reset();
       
  1754 		}
       
  1755 	}
       
  1756 
       
  1757 void RL2CapErtmOutgoingQueue::DeleteAllFrames()
       
  1758 	{
       
  1759 	LOG_FUNC
       
  1760 	if (!iPendRetransmitIFrameQ.IsEmpty())
       
  1761 		{
       
  1762 		TSglQueIter<HIFramePDU> iter(iPendRetransmitIFrameQ);
       
  1763 		while (HIFramePDU* eyeFrame = iter++)
       
  1764 			{
       
  1765 			delete eyeFrame;
       
  1766 			}
       
  1767 		iPendRetransmitIFrameQ.Reset();
       
  1768 		}
       
  1769 
       
  1770 	if (!iOutgoingQ.IsEmpty())
       
  1771 		{
       
  1772 		TSglQueIter<HL2CapPDU> iter(iOutgoingQ);
       
  1773 		while (HL2CapPDU* pdu = iter++)
       
  1774 			{
       
  1775 			delete pdu;
       
  1776 			}
       
  1777 		iOutgoingQ.Reset();
       
  1778 		}	
       
  1779 	}
       
  1780 
       
  1781 HL2CapPDU* RL2CapErtmOutgoingQueue::DequeueNextToSend()
       
  1782 	{
       
  1783 	LOG_FUNC
       
  1784 	HL2CapPDU* pdu = NULL;
       
  1785 	if (!iOutgoingQ.IsEmpty())
       
  1786 		{
       
  1787 		pdu = iOutgoingQ.First();
       
  1788 		if (!pdu->IsAwaitingHciCompletion())
       
  1789 			{
       
  1790 			iOutgoingQ.Remove(*pdu);
       
  1791 			pdu->SetQueuedForSend(EFalse);
       
  1792 			}
       
  1793 		else
       
  1794 			{
       
  1795 			LOG(_L("OutgoingQ stalled pending HCI Completion of the previous transmission of the next PDU"))
       
  1796 			pdu = NULL;
       
  1797 			}
       
  1798 		}
       
  1799 	return pdu;
       
  1800 	}
       
  1801 
       
  1802 
       
  1803 CL2CapEnhancedReTxController* CL2CapEnhancedReTxController::NewL(TL2CAPPort aLocalCID,
       
  1804 																 TL2CAPPort aRemoteCID,
       
  1805 																 CL2CAPMux& aMuxer,
       
  1806 																 CL2CapSDUQueue& aSDUQueue,
       
  1807 																		TL2CapDataControllerConfig* aConfig)
       
  1808 	{
       
  1809 	LOG_STATIC_FUNC
       
  1810 	CL2CapEnhancedReTxController* controller = new (ELeave) CL2CapEnhancedReTxController(aLocalCID, aRemoteCID, aMuxer, aSDUQueue, aConfig);
       
  1811 	CleanupStack::PushL(controller);
       
  1812 	controller->ConstructL();
       
  1813 	CleanupStack::Pop(controller);
       
  1814 	return controller;
       
  1815 	}
       
  1816 
       
  1817 void CL2CapEnhancedReTxController::ConstructL()
       
  1818 	{
       
  1819 	LOG_FUNC
       
  1820 	iTransmitter = CL2CapErtmDataTransmitter::NewL(*this);
       
  1821 	iReceiver = CL2CapErtmDataReceiver::NewL(*this);
       
  1822 	}
       
  1823 
       
  1824 // ***** CL2CapEnhancedReTxController Implementation
       
  1825 CL2CapEnhancedReTxController::CL2CapEnhancedReTxController(TL2CAPPort aLocalCID,
       
  1826 														   TL2CAPPort aRemoteCID,
       
  1827 														   CL2CAPMux& aMuxer,
       
  1828 														   CL2CapSDUQueue& aSDUQueue,
       
  1829 														   TL2CapDataControllerConfig* aConfig)
       
  1830  :	CL2CapBasicDataController(aLocalCID, aRemoteCID, aMuxer, aSDUQueue, aConfig, EFalse),
       
  1831 	iDeliverOutgoingDataAndSignalToSduQWhenDone(EFalse),
       
  1832 	iOutgoingQ(*this),
       
  1833  	iTimerMan(*this)
       
  1834 	{
       
  1835 	LOG_FUNC
       
  1836 	LOG2(_L("CL2CapEnhancedReTxController: local CID = %d, remote CID = %d"), aLocalCID, aRemoteCID)
       
  1837 	}
       
  1838 
       
  1839 CL2CapEnhancedReTxController::~CL2CapEnhancedReTxController()
       
  1840 	{
       
  1841 	LOG_FUNC
       
  1842 	iTimerMan.Close();
       
  1843 	iOutgoingQ.Close();
       
  1844 	delete iTransmitter;
       
  1845 	delete iReceiver;
       
  1846 	}
       
  1847 
       
  1848 void CL2CapEnhancedReTxController::HandleIncomingIFrameL(RMBufChain& aIFrame)
       
  1849 	{
       
  1850 	LOG_FUNC
       
  1851 	const TUint8 txSeq = HIFramePDU::TxSeqNumber(aIFrame);
       
  1852 	const TUint8 reqSeq = HIFramePDU::ReqSeqNumber(aIFrame);
       
  1853 	const TBool final = HIFramePDU::FinalBit(aIFrame);
       
  1854 
       
  1855 	LOG3(_L("Incoming I-Frame: TxSeq = %d, F = %d, ReqSeq = %d"), 
       
  1856 		 txSeq, final, reqSeq)
       
  1857 	
       
  1858 	if (iReceiver->IsTxSeqInvalid(txSeq))
       
  1859 		{
       
  1860 		LOG3(_L("Received invalid TxSeq num %d, [BufferSeq = %d, Receive TxWin = %d]"),
       
  1861 			 txSeq, iReceiver->BufferSeq(), iConfig->PeerTXWindowSize())
       
  1862 		LEAVEL(KErrL2CAPInvalidPacketSequenceNumber);
       
  1863 		}
       
  1864 	else if (!iTransmitter->IsReqSeqValid(reqSeq))
       
  1865 		{
       
  1866 		LOG3(_L("Received invalid ReqSeq num %d, [ExpectedAckSeq = %d, NextTxSeq = %d]"),
       
  1867 			 reqSeq, iTransmitter->ExpectedAckSeq(), iTransmitter->NextTxSeq())
       
  1868 		LEAVEL(KErrL2CAPInvalidAcknowledgementNumber);
       
  1869 		}
       
  1870 	else if (IsFBitValid(final)) // ... and TxSeq and ReqSeq are valid
       
  1871 		{
       
  1872 		// ReqSeq & FBit valid: use this information whatever TxSeq value is, as long as it's
       
  1873 		// within window.
       
  1874 
       
  1875 		if (final)
       
  1876 			{
       
  1877 			HandleFinalAck();
       
  1878 			}
       
  1879 
       
  1880 		iTransmitter->HandleIncomingIFrame(aIFrame);
       
  1881 		iReceiver->HandleIncomingIFrameL(aIFrame);
       
  1882 
       
  1883 		NotifyMuxerOfPdusToSendIfHaveSome();
       
  1884 		} // ReqSeq & Final Valid, TxSeq within window
       
  1885 	else
       
  1886 		{
       
  1887 		LOG(_L("F-bit invalid, dropping the I-Frame"))
       
  1888 		aIFrame.Free();
       
  1889 		}
       
  1890 	}
       
  1891 
       
  1892 void CL2CapEnhancedReTxController::HandleIncomingSFrameL(RMBufChain& aSFrame)
       
  1893 	{
       
  1894 	LOG_FUNC
       
  1895 
       
  1896 	const TUint8 reqSeq = HSFramePDU::ReqSeqNumber(aSFrame);
       
  1897 	const TBool poll = HSFramePDU::PollBit(aSFrame);
       
  1898 	const TBool final = HSFramePDU::FinalBit(aSFrame);
       
  1899 
       
  1900 	LOG4(_L("Incoming S-Frame: S = %d, P = %d, F = %d, ReqSeq = %d"),
       
  1901 		 HSFramePDU::SupervisoryFunction(aSFrame), poll, final, reqSeq)
       
  1902 
       
  1903 	if (!iTransmitter->IsReqSeqValid(reqSeq))
       
  1904 		{
       
  1905 		LOG3(_L("Received invalid ReqSeq num %d, [ExpectedAckSeq = %d, NextTxSeq = %d]"),
       
  1906 			 reqSeq, iTransmitter->ExpectedAckSeq(), iTransmitter->NextTxSeq())
       
  1907 		LEAVEL(KErrL2CAPInvalidAcknowledgementNumber);
       
  1908 		}
       
  1909 	else if (IsFBitValid(final)) // ... and TxSeq and ReqSeq are valid
       
  1910 		{
       
  1911 		// ReqSeq & FBit valid: use this information whatever TxSeq value is, as long as it's
       
  1912 		// within window.
       
  1913 
       
  1914 		if (final)
       
  1915 			{
       
  1916 			HandleFinalAck();
       
  1917 			}
       
  1918 
       
  1919 		iTransmitter->HandleIncomingSFrameL(aSFrame);
       
  1920 		iReceiver->HandleIncomingSFrameL(aSFrame);
       
  1921 
       
  1922 		NotifyMuxerOfPdusToSendIfHaveSome();
       
  1923 		}
       
  1924 	else
       
  1925 		{
       
  1926 		LOG(_L("F-bit invalid, dropping the S-Frame"))
       
  1927 		aSFrame.Free();
       
  1928 		}
       
  1929 	}
       
  1930 
       
  1931 void CL2CapEnhancedReTxController::HandleFinalAck()
       
  1932 	{
       
  1933 	LOG_FUNC
       
  1934 	// Just do housekeeping here. Transmitter/Receiver maintain their respective WAIT_* states
       
  1935 	// and know what to do with the final ack.
       
  1936 	iTimerMan.StopMonitorTimer();
       
  1937 
       
  1938 	iPollSFrameTransmitCount = 0;
       
  1939 	}
       
  1940 
       
  1941 void CL2CapEnhancedReTxController::SendIOrRrOrRnrL(TBool aFinal)
       
  1942 	{
       
  1943 	LOG_FUNC
       
  1944 	// Try piggybacking on an I-Frame first...
       
  1945 	HIFramePDU* eyeFrame = iTransmitter->GetIFrameToSendL();
       
  1946 	if (eyeFrame)
       
  1947 		{
       
  1948 		eyeFrame->SetFinalBit(aFinal);
       
  1949 		iOutgoingQ.QueueIFrameL(*eyeFrame);
       
  1950 		}
       
  1951 	else
       
  1952 		{
       
  1953 		// ... no I-Frame to send or can't send one.
       
  1954 		iOutgoingQ.QueueAckingSFrame(*iReceiver->GetAckFrameL(aFinal));
       
  1955 		}
       
  1956 	}
       
  1957 
       
  1958 HL2CapPDU* CL2CapEnhancedReTxController::GetPduL()
       
  1959 	{
       
  1960 	LOG_FUNC
       
  1961 	// Note that:
       
  1962 	// - the queue contains S-Frames (naturally) and I-Frames (if they're SREJ-requested by
       
  1963 	// the peer or a Poll request was received and we had a data frame to piggyback the Final
       
  1964 	// response on);
       
  1965 	// - once a packet is put on the Q, it should be virtually considered to be on the air from
       
  1966 	// a logical POV.
       
  1967 	if (!iOutgoingQ.HaveFramesToTransmit())
       
  1968 		{
       
  1969 		// Check for async events to handle.
       
  1970 		// Note: polls are only sent when the OutgoingQ is empty.
       
  1971 		// Reason:
       
  1972 		// 1. The frames on the queue may be I-Frames queued in response to SREJs from the peer.
       
  1973 		// Sending the Poll before responding to the SREJs would lead to a race condition
       
  1974 		// (in WAIT_F) - the SREJs were received when XMIT state = Normal and so SRejActioned was
       
  1975 		// not set to True. So if they're not responded to before the Poll, we'll receive a
       
  1976 		// duplicate SREJ with the Final ack and respond to it with a duplicate I-Frame, which
       
  1977 		// causes disconnect.
       
  1978 		//
       
  1979 		// 2. Even though this may increase the latency of handling an Ack timer expiry if
       
  1980 		// there're packets on the queue, it actually bets on the assumption that these packets are
       
  1981 		// I-Frames SREJ-requested by the peer (same one(s) that caused us to time out) and
       
  1982 		// sending them before the Poll packet still gives the SREJ chance to work and hence
       
  1983 		// minimizes the amount of stuff we'll have to retransmit once we receive the final ack.]
       
  1984 		if ((iReceiver->IsWaitFStatePending() || iTransmitter->IsWaitAckStatePending()) &&
       
  1985 			!IsPollOutstanding())
       
  1986 			// ^- this serializes poll cycles - only one poll can be outstanding at a time
       
  1987 			// but the conditions for WAIT_F and WAIT_ACK are independent and can occur
       
  1988 			// simultaneously.
       
  1989 			{
       
  1990 			// Start a new Poll cycle.
       
  1991 			__ASSERT_DEBUG(iPollSFrameTransmitCount == 0, Panic(EL2CAPPollFrameNumberTransmitIsNotZero));
       
  1992 
       
  1993 			HSFramePDU* sFrame = iReceiver->GetAckFrameL();
       
  1994 			sFrame->SetPollBit(ETrue);
       
  1995 
       
  1996 			// Give WAIT_ACK preference in case both are outstanding.
       
  1997 			if (iTransmitter->IsWaitAckStatePending())
       
  1998 				{
       
  1999 				LOG(_L("Entering WaitAck"))
       
  2000 				iTransmitter->EnterWaitAckState();
       
  2001 				}
       
  2002 			else
       
  2003 				{
       
  2004 				LOG(_L("Entering WaitF"))
       
  2005 				iReceiver->EnterWaitFState();
       
  2006 				}
       
  2007 
       
  2008 			iPollSFrameTransmitCount++;
       
  2009 			iTimerMan.StartMonitorTimer();
       
  2010 
       
  2011 			iOutgoingQ.QueueAckingSFrame(*sFrame);
       
  2012 			}
       
  2013 		else // outgoing Q empty & no async events outstanding, can send data
       
  2014 			{
       
  2015 			HIFramePDU* eyeFrame = iTransmitter->GetIFrameToSendL();
       
  2016 			if (eyeFrame)
       
  2017 				{
       
  2018 				iOutgoingQ.QueueIFrameL(*eyeFrame);
       
  2019 				}
       
  2020 			}
       
  2021 		}
       
  2022 
       
  2023 	// If an acking frame was queued in the previous step, this flag has been cleared.
       
  2024 	if (iReceiver->SendAck())
       
  2025 		{
       
  2026 		SendIOrRrOrRnrL(EFalse);
       
  2027 		}
       
  2028 
       
  2029 	// If there's anything ready to send it's on the queue by now.
       
  2030 	HL2CapPDU* pduToSend = iOutgoingQ.DequeueNextToSend();
       
  2031 	if (pduToSend)
       
  2032 		{
       
  2033 		pduToSend->DeliverOutgoingPDU(*this);
       
  2034 		NotifyMuxerOfPdusToSendIfHaveSome();
       
  2035 		}
       
  2036 
       
  2037 	return pduToSend;
       
  2038 	}
       
  2039 
       
  2040 void CL2CapEnhancedReTxController::HandlePduSendComplete(HL2CapPDU& aPdu)
       
  2041 	{
       
  2042 	LOG_FUNC
       
  2043 	// We only claim ownership of I-Frames.
       
  2044 	iTransmitter->HciCompletedIFrame(static_cast<HIFramePDU&>(aPdu));
       
  2045     // May be waiting for the current I-Frame to complete if it's already been
       
  2046     // requested for retransmission.
       
  2047     NotifyMuxerOfPdusToSendIfHaveSome();
       
  2048 	}
       
  2049 
       
  2050 void CL2CapEnhancedReTxController::HandlePduSendError(HL2CapPDU& /*aPdu*/)
       
  2051 	{
       
  2052 	LOG_FUNC
       
  2053 	// We use protocol-level retransmissions for I-Frames.
       
  2054 	}
       
  2055 
       
  2056 TInt CL2CapEnhancedReTxController::HandleOutgoingIFrame(HIFramePDU* aIFrame)
       
  2057 	{
       
  2058 	LOG_FUNC
       
  2059 	__ASSERT_DEBUG(!iTransmitter->InWaitAckState(), Panic(EL2CAPIFrameSentInWaitAck));
       
  2060 
       
  2061 	aIFrame->SetPDUCID(iRemoteCID);
       
  2062 	aIFrame->CalculateAndSetFCS();
       
  2063 
       
  2064 	aIFrame->SetPduOwner(this);
       
  2065 
       
  2066 	LOG3(_L("Outgoing I-Frame: TxSeq = %d, F = %d, ReqSeq = %d"), 
       
  2067 		 aIFrame->TxSeqNumber(), aIFrame->FinalBit(), aIFrame->ReqSeqNumber())
       
  2068 
       
  2069 	return KErrNone;
       
  2070 	}
       
  2071 
       
  2072 TInt CL2CapEnhancedReTxController::HandleOutgoingSFrame(HSFramePDU* aSFrame)
       
  2073 	{
       
  2074 	LOG_FUNC
       
  2075 	aSFrame->SetPDUCID(iRemoteCID);
       
  2076 	aSFrame->CalculateAndSetFCS();
       
  2077 
       
  2078 	LOG4(_L("Outgoing S-Frame: S = %d, P = %d, F = %d, ReqSeq = %d"),
       
  2079 		 aSFrame->SupervisoryFunction(), aSFrame->PollBit(), aSFrame->FinalBit(), aSFrame->ReqSeqNumber())
       
  2080 
       
  2081 	return KErrNone;
       
  2082 	}
       
  2083 
       
  2084 void CL2CapEnhancedReTxController::SendPeerAckTimerExpired()
       
  2085 	{
       
  2086 	LOG_FUNC
       
  2087 	TRAPD(err, iReceiver->SendPeerAckTimerExpiredL());
       
  2088 	if (err != KErrNone)
       
  2089 		{
       
  2090 		ErrorD(err);
       
  2091 		// RIP
       
  2092 		}
       
  2093 	}
       
  2094 
       
  2095 void CL2CapEnhancedReTxController::AckTimerExpired()
       
  2096 	{
       
  2097 	LOG_FUNC
       
  2098 	// Reset the POLL transmit count (it will be incremented when the SFrame[POLL] is pulled for sending
       
  2099 	iPollSFrameTransmitCount = 0;
       
  2100 	iTransmitter->AckTimerExpired();
       
  2101 	}
       
  2102 
       
  2103 void CL2CapEnhancedReTxController::LocalBusyDelayTimerExpired()
       
  2104 	{
       
  2105 	LOG_FUNC
       
  2106 	iReceiver->LocalBusyDelayTimerExpired();
       
  2107 	}
       
  2108 
       
  2109 void CL2CapEnhancedReTxController::MonitorTimerExpired()
       
  2110 	{
       
  2111 	LOG_FUNC
       
  2112 	__ASSERT_DEBUG(IsPollOutstanding(), Panic(EL2CAPUnexpectedMonitorTimeout));
       
  2113 	__ASSERT_DEBUG(iPollSFrameTransmitCount > 0, Panic(EL2CAPPollFrameNumberTransmitIsZero));
       
  2114 
       
  2115 	TInt err = KErrNone;
       
  2116 
       
  2117 	if (!TRetransmissionAndFlowControlOption::EnhancedMaxTransmitLessOrEqual(iPollSFrameTransmitCount + 1,
       
  2118 																			 iConfig->MaxTransmit()))
       
  2119 		{
       
  2120 		LOG1(_L("MaxTransmit=%d exceeded by a Poll S-Frame"), iConfig->MaxTransmit())
       
  2121 		err = KErrL2CAPMaxTransmitExceeded;
       
  2122 		}
       
  2123 	else
       
  2124 		{
       
  2125 		HSFramePDU* frame = NULL;
       
  2126 		TRAP(err, frame = iReceiver->GetAckFrameL());
       
  2127 		if (err == KErrNone)
       
  2128 			{
       
  2129 			frame->SetPollBit(ETrue);
       
  2130 			iOutgoingQ.QueueAckingSFrame(*frame);
       
  2131 
       
  2132 			iPollSFrameTransmitCount++;
       
  2133 			iTimerMan.StartMonitorTimer();
       
  2134 
       
  2135 			NotifyMuxerOfPdusToSendIfHaveSome();
       
  2136 			}
       
  2137 		}
       
  2138 	if (err != KErrNone)
       
  2139 		{
       
  2140 		ErrorD(err);
       
  2141 		// RIP
       
  2142 		}
       
  2143 	}
       
  2144 
       
  2145 TUint16 CL2CapEnhancedReTxController::MonitorTimeout()
       
  2146 	{
       
  2147 	return iConfig->MonitorTimeout();
       
  2148 	}
       
  2149 
       
  2150 TUint16 CL2CapEnhancedReTxController::RetransmissionTimeout()
       
  2151 	{
       
  2152 	return iConfig->RetransmissionTimeout();
       
  2153 	}
       
  2154 
       
  2155 TUint16 CL2CapEnhancedReTxController::PeerRetransmissionTimeout()
       
  2156 	{
       
  2157 	return iConfig->PeerRetransmissionTimeout();
       
  2158 	}
       
  2159 
       
  2160 void CL2CapEnhancedReTxController::OutgoingPduAvailableOnSduQ()
       
  2161 	{
       
  2162 	LOG_FUNC
       
  2163 	NotifyMuxerOfPdusToSendIfHaveSome();
       
  2164 	}
       
  2165 
       
  2166 void CL2CapEnhancedReTxController::SetIncomingSduQFull(TBool aIncomingSduQFull)
       
  2167 	{
       
  2168 	LOG_FUNC
       
  2169 	TRAPD(err, iReceiver->SetIncomingSduQFullL(aIncomingSduQFull));
       
  2170 	if (err != KErrNone)
       
  2171 		{
       
  2172 		ErrorD(err);
       
  2173 		// RIP
       
  2174 		}
       
  2175 	}
       
  2176 
       
  2177 TBool CL2CapEnhancedReTxController::DeliverOutgoingDataAndSignalToSduQWhenDone()
       
  2178 	{
       
  2179 	LOG_FUNC
       
  2180 	iDeliverOutgoingDataAndSignalToSduQWhenDone = ETrue;
       
  2181 	// Returning true means we don't have any outstanding data to deliver and
       
  2182 	// hence can be deleted immediately.
       
  2183 	return !iTransmitter->HaveUnackedIFrames();
       
  2184 	}
       
  2185 
       
  2186 inline void CL2CapEnhancedReTxController::NotifyMuxerOfPdusToSendIfHaveSome()
       
  2187     {
       
  2188     LOG_FUNC
       
  2189     // This is intended to be your one-stop kick-the-muxer routine.
       
  2190     // It should evaluate all conditions that may cause us to want to send
       
  2191     // a PDU and should be called at the end of handling of every event which
       
  2192     // may cause us to want to send stuff.
       
  2193     //
       
  2194     // The conditions are:
       
  2195     // - if there's something on the OutgoingQ, then always transmit it ASAP,
       
  2196     //   Outgoing Q is "the air" from the protocols point of view;
       
  2197     // - if we're not in WAIT_ACK (now called WAIT_F in the spec), then send
       
  2198     //   data:
       
  2199     //      - I-Frames requested for retransmission (with REJ or ack timer expiry,
       
  2200     //        SREJ-requested ones are put on the OutgoingQ),
       
  2201     //      - new I-Frames from SDUs on the SDU Q.
       
  2202     // - if there's some signalling to be send that hasn't been directly put
       
  2203     //   on the OutgoingQ - send it:
       
  2204     //      - need to go through WAIT_ACK and can enter it (WAIT_F not in progress),
       
  2205     //      - need to go through WAIT_F and can enter it (WAIT_ACK not in progress);
       
  2206     //      - time to send an acknowledgement to the peer.
       
  2207 
       
  2208     if (iOutgoingQ.HaveFramesToTransmit()  ||  // various stuff already on the transmit Q,
       
  2209         // ... or data:
       
  2210         (!iTransmitter->InWaitAckState() &&
       
  2211             // ... in need of retransmission ...
       
  2212             ((iTransmitter->IsRetransmittingUnackedIFrames() && !iTransmitter->IsNextUnackedIFrameAwaitingHciCompletion()) ||
       
  2213             // ... or waiting to be pulled from SDU Q,
       
  2214             (!iTransmitter->IsRetransmittingUnackedIFrames() && iSDUQueue.HavePDUToSend() && iTransmitter->HaveSpaceInOutgoingWindow()))
       
  2215         ) ||
       
  2216         // or some boring signalling:
       
  2217         // ... want to enter WAIT_ACK and not already in WAIT_F ...
       
  2218         (iTransmitter->IsWaitAckStatePending() && !iReceiver->InWaitFState()) ||
       
  2219         // ... want to enter WAIT_F and not already in WAIT_ACK ...
       
  2220         (iReceiver->IsWaitFStatePending()      && !iTransmitter->InWaitAckState()) ||
       
  2221         // ... time to send an acknowledgement.
       
  2222         iReceiver->SendAck())
       
  2223         {
       
  2224         iMuxer.PDUAvailable();
       
  2225         }
       
  2226 
       
  2227     #ifdef __L2CAP_ERTM_GETPDU_DEBUG
       
  2228     LOG1(_L("iOutgoingQ.HaveFramesToTransmit(): %d"), iOutgoingQ.HaveFramesToTransmit())
       
  2229     LOG1(_L("iTransmitter->HaveSpaceInOutgoingWindow(): %d"), iTransmitter->HaveSpaceInOutgoingWindow())
       
  2230     LOG1(_L("iTransmitter->InWaitAckState(): %d"), iTransmitter->InWaitAckState())
       
  2231     LOG1(_L("iTransmitter->IsRetransmittingUnackedIFrames(): %d"), iTransmitter->IsRetransmittingUnackedIFrames())
       
  2232     if (iTransmitter->IsRetransmittingUnackedIFrames())
       
  2233         {
       
  2234         LOG1(_L("iTransmitter->IsNextUnackedIFrameAwaitingHciCompletion(): %d"), iTransmitter->IsNextUnackedIFrameAwaitingHciCompletion())
       
  2235         }
       
  2236     LOG1(_L("iChannel.DataQueue().HavePDUToSend(): %d"), iSDUQueue.HavePDUToSend())
       
  2237     LOG1(_L("iTransmitter->IsWaitAckStatePending(): %d"), iTransmitter->IsWaitAckStatePending())
       
  2238     LOG1(_L("iReceiver->InWaitFState(): %d"), iReceiver->InWaitFState())
       
  2239     LOG1(_L("iReceiver->IsWaitFStatePending(): %d"), iReceiver->IsWaitFStatePending())
       
  2240     LOG1(_L("iTransmitter->InWaitAckState(): %d"), iTransmitter->InWaitAckState())
       
  2241     LOG1(_L("iReceiver->SendAck(): %d"), iReceiver->SendAck())
       
  2242     #endif
       
  2243     }