bluetooth/btstack/l2cap/L2CapDataController.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2004-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 
       
    18 #include <e32base.h>
       
    19 
       
    20 #include "L2CapDataController.h"
       
    21 #include "L2CapEnhancedDataController.h"
       
    22 
       
    23 #include "L2CapSDUQueue.h"
       
    24 #include "l2signalmgr.h"
       
    25 
       
    26 #include "btsockettimer.h"
       
    27  
       
    28 #include "l2util.h"
       
    29 #include "L2CapDebugControlInterface.h"
       
    30 
       
    31 #include "l2constants.h"	
       
    32 
       
    33 #ifdef __FLOG_ACTIVE
       
    34 _LIT8(KLogComponent, LOG_COMPONENT_L2CAP_DATA_CONTROLLER);
       
    35 #endif
       
    36 
       
    37 using namespace L2CapDataUtils;
       
    38 
       
    39 // ***** CL2CapBasicDataController Implementation
       
    40 /*static*/ CL2CapBasicDataController* CL2CapBasicDataController::NewL(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, CL2CapSDUQueue& aSDUQueue, TL2CapDataControllerConfig* aConfig)
       
    41 	{
       
    42 	LOG_STATIC_FUNC
       
    43 	// Create the required data controller. 
       
    44 	CL2CapBasicDataController* controller = NULL;
       
    45 
       
    46 	switch(aConfig->LinkMode())
       
    47 		{
       
    48 		case EL2CAPBasicMode:
       
    49 			LOG(_L("FEC L2CapBasicDataController Basic Mode"))
       
    50 			controller = new(ELeave) CL2CapBasicDataController(aLocalCID, aRemoteCID, aMuxer, aSDUQueue, aConfig, ETrue);
       
    51 			break;
       
    52 			
       
    53 		case EL2CAPRetransmissionMode:
       
    54 			LOG(_L("FEC L2CapBasicDataController Retransmission Mode"))
       
    55 			controller = new(ELeave) CL2CapDataReTxController(aLocalCID, aRemoteCID, aMuxer, aSDUQueue, aConfig);		
       
    56 			break;
       
    57 			
       
    58 		case EL2CAPFlowControlMode:
       
    59 			LOG(_L("FEC L2CapBasicDataController Flow Control Mode"))
       
    60 			controller = new(ELeave) CL2CapDataFlowController(aLocalCID, aRemoteCID, aMuxer, aSDUQueue, aConfig);		
       
    61 			break;
       
    62 
       
    63 		case EL2CAPStreamingMode:
       
    64 			LOG(_L("FEC L2CapBasicDataController Streaming Mode"))
       
    65 			controller = new(ELeave) CL2CapStreamingController(aLocalCID, aRemoteCID, aMuxer, aSDUQueue, aConfig);		
       
    66 			break;
       
    67 
       
    68 		case EL2CAPEnhancedRetransmissionMode:
       
    69 			LOG(_L("FEC L2CapBasicDataController Enhnaced Retransmission Mode"))
       
    70 			controller = CL2CapEnhancedReTxController::NewL(aLocalCID, aRemoteCID, aMuxer, aSDUQueue, aConfig);		
       
    71 			break;
       
    72 		
       
    73 		default:
       
    74 			Panic(EL2CAPInvalidLinkMode);
       
    75 			break;
       
    76 		};
       
    77 	
       
    78 	return controller;
       
    79 	}
       
    80 
       
    81 CL2CapBasicDataController::CL2CapBasicDataController(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, CL2CapSDUQueue& aSDUQueue, TL2CapDataControllerConfig* aConfig, TBool aIsBasicDataVersion)
       
    82  : iSDUQueue(aSDUQueue),
       
    83    iMuxer(aMuxer),
       
    84    iLocalCID(aLocalCID),
       
    85    iRemoteCID(aRemoteCID),
       
    86    iConfig(aConfig),
       
    87    iIsBasicDataVersion(aIsBasicDataVersion)
       
    88 	{
       
    89 	LOG_FUNC
       
    90 	// Register with the Mux.
       
    91 	iMuxer.RegisterDataPDUHandler(*this);
       
    92 
       
    93 	L2CAP_DEBUG(ObjectAllocation(L2capDebugInfo::EDataPlanes,
       
    94 	                             L2capDebugInfo::EAllocated));	
       
    95 	}
       
    96 
       
    97 CL2CapBasicDataController::~CL2CapBasicDataController()
       
    98 	{
       
    99 	LOG_FUNC
       
   100 	delete iConfig;
       
   101 
       
   102 	L2CAP_DEBUG(ObjectAllocation(L2capDebugInfo::EDataPlanes,
       
   103 	                             L2capDebugInfo::EDeleted));	
       
   104 	}	
       
   105 
       
   106 HL2CapPDU* CL2CapBasicDataController::GetPdu()
       
   107 	{
       
   108 	LOG_FUNC
       
   109 	HL2CapPDU* pdu = NULL;
       
   110 	TRAPD(err, pdu = GetPduL());
       
   111 	if (err != KErrNone)
       
   112 		{
       
   113 		// The protocol here is that all leaves propagated up to here cause
       
   114 		// us to ErrorD() ourselves, which will destruct data plane objects
       
   115 		// (the data controller, SDU queue and the whole shebang) and error
       
   116 		// the socket with the leave error code.
       
   117 		ErrorD(err);
       
   118 		}
       
   119 	return pdu;
       
   120 	}
       
   121 
       
   122 HL2CapPDU* CL2CapBasicDataController::GetPduL()
       
   123 	{
       
   124 	LOG_FUNC
       
   125 	HL2CapPDU* pduToSend = NULL;
       
   126 	if((pduToSend = iSDUQueue.GetPDU()) != NULL)
       
   127 		{
       
   128 		pduToSend->SetPDUCID(iRemoteCID);
       
   129 		}
       
   130 	return pduToSend;
       
   131 	}
       
   132 
       
   133 void CL2CapBasicDataController::ProcessFlushTimerExpiry()
       
   134 	{
       
   135 	LOG_FUNC
       
   136 	iMuxer.ProcessFlushTimerExpiry();
       
   137 	}
       
   138 
       
   139 void CL2CapBasicDataController::OutgoingPduAvailableOnSduQ()
       
   140 	{
       
   141 	LOG_FUNC
       
   142 	iMuxer.PDUAvailable();
       
   143 	}
       
   144 
       
   145 void CL2CapBasicDataController::UpdateConfig(TL2CapDataControllerConfig* aConfig)
       
   146 	{
       
   147 	LOG_FUNC
       
   148 	TBool channelPriorityUpdated = (iConfig->ChannelPriority() != aConfig->ChannelPriority());
       
   149 	// Delete the existing config, and replace it with the new one.
       
   150 	delete iConfig;
       
   151 	iConfig = aConfig;
       
   152 
       
   153 	if(channelPriorityUpdated)
       
   154 		{
       
   155 		iMuxer.ChannelPriorityUpdated(*this);
       
   156 		}
       
   157 	}
       
   158 
       
   159 void CL2CapBasicDataController::UpdateChannelPriority(TUint8 aNewPriority)
       
   160 	{
       
   161 	LOG_FUNC
       
   162 	if(iConfig->ChannelPriority() != aNewPriority)
       
   163 		{
       
   164 		iConfig->SetChannelPriority(aNewPriority);
       
   165 		iMuxer.ChannelPriorityUpdated(*this);
       
   166 		}
       
   167 	}
       
   168 	
       
   169 	
       
   170 void CL2CapBasicDataController::ErrorD(TInt aError)
       
   171 	{
       
   172 	LOG_FUNC
       
   173 	LOG1(_L("FEC CL2CapBasicDataController::Error %d"), aError)
       
   174 	iDataPlaneErrored = ETrue;
       
   175 	iSDUQueue.ErrorD(aError);
       
   176 	}
       
   177 
       
   178 void CL2CapBasicDataController::SetIncomingSduQFull(TBool /*aIncomingSduQFull*/)
       
   179 	{
       
   180 	LOG_FUNC
       
   181 	// No action can be taken in basic mode.
       
   182 	}
       
   183 
       
   184 TBool CL2CapBasicDataController::DeliverOutgoingDataAndSignalToSduQWhenDone()
       
   185 	{
       
   186 	LOG_FUNC
       
   187 	// We can be deleted right away.
       
   188 	return ETrue;
       
   189 	}
       
   190 
       
   191 void CL2CapBasicDataController::DeregisterFromMuxer()
       
   192 	{
       
   193 	LOG_FUNC
       
   194 	iMuxer.DataChannelRemoved(this);
       
   195 	}
       
   196 
       
   197 #ifdef _DEBUG
       
   198 TInt CL2CapBasicDataController::GetDataPlaneConfig(TL2DataPlaneConfig& conf) const
       
   199 	{
       
   200 	LOG_FUNC
       
   201 	TInt rerr = KErrNone;
       
   202 	// Populate the debug structure.
       
   203 	if(iConfig)
       
   204 		{
       
   205 		conf.iPriority = iConfig->ChannelPriority();
       
   206 		conf.iLinkMode = iConfig->LinkMode();
       
   207 		conf.iTxWindowSize = iConfig->TXWindowSize();
       
   208 		conf.iMaxTransmit = iConfig->MaxTransmit();
       
   209 		conf.iRetransmissionTimeout = iConfig->RetransmissionTimeout();
       
   210 		conf.iMonitorTimeout = iConfig->MonitorTimeout();
       
   211 		}
       
   212 	else
       
   213 		{
       
   214 		rerr = KErrNotReady;
       
   215 		}
       
   216 	return rerr;
       
   217 	}
       
   218 #endif
       
   219 
       
   220 TBool CL2CapBasicDataController::HandleIncomingDataFrame(RMBufChain& aDataFrame)
       
   221 	{
       
   222 	LOG_FUNC
       
   223 	TBool packetDelivered = EFalse;
       
   224 	TRAPD(err, packetDelivered = HandleIncomingDataFrameL(aDataFrame));
       
   225 	if (err != KErrNone)
       
   226 		{
       
   227 		// The protocol here is that all leaves propagated up to here cause
       
   228 		// us to ErrorD() ourselves, which will destruct data plane objects
       
   229 		// (the data controller, SDU queue and the whole shebang) and error
       
   230 		// the socket with the leave error code.
       
   231 		ErrorD(err);
       
   232 
       
   233 		if (aDataFrame.IsEmpty())
       
   234 			{
       
   235 			packetDelivered = ETrue;
       
   236 			}
       
   237 		// else frame will be offered to other data controllers
       
   238 		}
       
   239 	return packetDelivered;
       
   240 	}
       
   241 
       
   242 void CL2CapBasicDataController::HandleIncomingIFrameL(RMBufChain& /*aDataFrame*/)
       
   243 	{
       
   244 	LOG_FUNC
       
   245 	Panic(EL2CAPIFrameOrSFrameHandledByBasicController);
       
   246 	}
       
   247 
       
   248 void CL2CapBasicDataController::HandleIncomingBFrameL(RMBufChain& aDataFrame)
       
   249 	{
       
   250 	LOG_FUNC
       
   251 	iSDUQueue.PutBFramePDU(aDataFrame);
       
   252 	}
       
   253 
       
   254 void CL2CapBasicDataController::HandleIncomingSFrameL(RMBufChain& /*aDataFrame*/)
       
   255 	{
       
   256 	LOG_FUNC
       
   257 	Panic(EL2CAPIFrameOrSFrameHandledByBasicController);
       
   258 	}
       
   259 
       
   260 TBool CL2CapBasicDataController::HandleIncomingDataFrameL(RMBufChain& aDataFrame)
       
   261 	{
       
   262 	LOG_FUNC
       
   263 	TBool PDUProcessed = EFalse;
       
   264 	TInt err = KErrNone;
       
   265 	
       
   266 	if(HL2CapPDU::PDUCID(aDataFrame) == iLocalCID)
       
   267 		{
       
   268 		if(iIsBasicDataVersion)
       
   269 			{
       
   270 			// This can only be a B-Frame.
       
   271 			if(HBFramePDU::CheckDecode(aDataFrame) == KErrNone)
       
   272 			   	{
       
   273 			   	HandleIncomingBFrameL(aDataFrame);
       
   274 			   	}
       
   275 			else
       
   276 				{
       
   277 				// Invalid frame.  Drop it.
       
   278 				aDataFrame.Free();
       
   279 				LOG(_L("FEC L2CapBasicDataController B-Frame Dropped"))
       
   280 				}
       
   281 			}
       
   282 		else
       
   283 			{
       
   284 			if(HIFramePDU::IFrameIdentifier(aDataFrame))
       
   285 				{
       
   286 				// This is an I-Frame
       
   287 
       
   288 				// Check stuff that causes us to drop frames first:
       
   289 				// - FCS (2.1 Core Spec Addendum 1: 3.3.7 Invalid Frame Detection Algorithm pt. 2)
       
   290 				// - length field matching the actual payload length (funnily 3.3.7 doesn't say
       
   291 				//   what to do with it, pt. 7.2.2 Recombination Of L2CAP PDUs mentions it in
       
   292 				//   passing).
       
   293 				// Note: the frame is dropped when length is incorrect (instead of disconnecting)
       
   294 				// because we don't know where FCS is (it's at the end of the packet and we don't
       
   295 				// know where that is), so have to assume that the length field problem is due to
       
   296 				// transmission corruption and not the remote misbehaving.
       
   297 				if (HIFramePDU::CheckPayloadDecode(aDataFrame) != KErrNone ||
       
   298 					HL2CapPDU::CheckDecode(aDataFrame) != KErrNone)
       
   299 					{
       
   300 					aDataFrame.Free();
       
   301 					LOG(_L("FEC L2CapBasicDataController I-Frame Dropped"))
       
   302 					}
       
   303 				else
       
   304 					{
       
   305 					// Now check stuff that causes us to disconnect (per CSA1 3.3.7).
       
   306 					err = HIFramePDU::CheckLengthWithinLimits(aDataFrame, iConfig->IncomingMps());
       
   307 					if (err != KErrNone)
       
   308 						{
       
   309 						LOG(_L("FEC L2CapBasicDataController I-Frame invalid"))
       
   310 
       
   311 						aDataFrame.Free();
       
   312 						// This will cause the channel to be closed.
       
   313 						LEAVEL(err);
       
   314 						}
       
   315 					else
       
   316 						{
       
   317 						HandleIncomingIFrameL(aDataFrame);
       
   318 						}
       
   319 					}
       
   320 				}
       
   321 			else
       
   322 				{
       
   323 				// S-Frame
       
   324 
       
   325 				// Check stuff that causes the frame to be dropped first.
       
   326 				if (HSFramePDU::CheckPayloadDecode(aDataFrame) != KErrNone ||
       
   327 					HL2CapPDU::CheckDecode(aDataFrame) != KErrNone)
       
   328 					{
       
   329 					LOG(_L("FEC L2CapBasicDataController S-Frame Dropped"))
       
   330 					}
       
   331 				else
       
   332 					{
       
   333 					// Now check stuff that causes us to disconnect (per CSA1 3.3.7).
       
   334 					err = HSFramePDU::CheckLengthField(aDataFrame);
       
   335 					if (err != KErrNone)
       
   336 						{
       
   337 						LOG(_L("FEC L2CapBasicDataController S-Frame Invalid"))
       
   338 
       
   339 						aDataFrame.Free();
       
   340 						// This will cause the channel to be closed.
       
   341 						LEAVEL(err);
       
   342 						}
       
   343 					else
       
   344 						{
       
   345 						HandleIncomingSFrameL(aDataFrame);
       
   346 					  	}
       
   347 					}
       
   348 				// Finished with the S-Frame.
       
   349 				aDataFrame.Free();
       
   350 				}
       
   351 			}
       
   352 		PDUProcessed = ETrue;
       
   353 		}
       
   354 	return PDUProcessed;
       
   355 	}
       
   356 
       
   357 // Outgoing PDU handler.
       
   358 TInt CL2CapBasicDataController::HandleOutgoingIFrame(HIFramePDU* /*aIFrame*/)
       
   359 	{
       
   360 	LOG_FUNC
       
   361 	return KErrNone;
       
   362 	}
       
   363 
       
   364 TInt CL2CapBasicDataController::HandleOutgoingBFrame(HBFramePDU* /*aBFrame*/)
       
   365 	{
       
   366 	LOG_FUNC
       
   367 	return KErrNone;
       
   368 	}
       
   369 
       
   370 TInt CL2CapBasicDataController::HandleOutgoingGFrame(HGFramePDU* /*aGFrame*/)
       
   371 	{
       
   372 	LOG_FUNC
       
   373 	return KErrNone;
       
   374 	}
       
   375 
       
   376 TInt CL2CapBasicDataController::HandleOutgoingCFrame(HCFramePDU* /*aCFrame*/)
       
   377 	{
       
   378 	LOG_FUNC
       
   379 	return KErrNone;
       
   380 	}
       
   381 
       
   382 TInt CL2CapBasicDataController::HandleOutgoingSFrame(HSFramePDU* /*aSFrame*/)
       
   383 	{
       
   384 	LOG_FUNC
       
   385 	return KErrNone;
       
   386 	}
       
   387 
       
   388 // ***** CL2CapDataFlowController Implementation
       
   389 CL2CapDataFlowController::CL2CapDataFlowController(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, CL2CapSDUQueue& aSDUQueue, TL2CapDataControllerConfig* aConfig)
       
   390  : CL2CapBasicDataController(aLocalCID, aRemoteCID, aMuxer, aSDUQueue, aConfig, EFalse),
       
   391    iPendingSentPDUs(_FOFF(HIFramePDU, iLink)),
       
   392    iSentPDUs(_FOFF(HIFramePDU, iLink)),
       
   393    iTimerMan(*this),
       
   394    iIncomingSduQFull(EFalse)
       
   395 	{
       
   396 	LOG_FUNC
       
   397 	}
       
   398 
       
   399 CL2CapDataFlowController::~CL2CapDataFlowController()
       
   400 	{
       
   401 	LOG_FUNC
       
   402 	// Some PDUs may hold a reference to this data controller.
       
   403 	TDblQueIter<HIFramePDU> pendingIter(iPendingSentPDUs);
       
   404 	TDblQueIter<HIFramePDU> sentIter(iSentPDUs);
       
   405 	HIFramePDU* pduPtr;
       
   406 	
       
   407 	while((pduPtr = pendingIter++) != NULL)
       
   408 		{
       
   409 		LOG1(_L("Deregistering TxSeq = %d"), pduPtr->TxSeqNumber());
       
   410 		pduPtr->DeregisterPduOwner();
       
   411 		}
       
   412 
       
   413 	// Delete any PDUs that have already been sent.
       
   414 	while((pduPtr = sentIter++) != NULL)
       
   415 		{
       
   416 		delete pduPtr;
       
   417 		}
       
   418 
       
   419 	// Cancel any outstanding timers.
       
   420 	iTimerMan.Close();
       
   421 	}
       
   422 
       
   423 
       
   424 void CL2CapDataFlowController::ProcessFlushTimerExpiry()
       
   425 	{
       
   426 	LOG_FUNC
       
   427 	iMuxer.ProcessFlushTimerExpiry();
       
   428 	PDUAvailable();
       
   429 
       
   430 	if(!iSentPDUs.IsEmpty())
       
   431 		{
       
   432 		iNextTxSeq = Mod64(iSentPDUs.Last()->TxSeqNumber() + 1);
       
   433 		}
       
   434 	else
       
   435 		{
       
   436 		iNextTxSeq = iExpectedAckSeq;
       
   437 		}
       
   438 	}
       
   439 
       
   440 void CL2CapDataFlowController::HandleIncomingIFrameL(RMBufChain& aDataFrame)
       
   441 	{
       
   442 	LOG_FUNC
       
   443 	// Check if flow control is active for incoming data.
       
   444 	if(iIncomingSduQFull)
       
   445 		{
       
   446 		// Check that the PDU sequence number is within the expected range.
       
   447 		if(!iSenderTxWindowClosed && Mod64(HIFramePDU::TxSeqNumber(aDataFrame) - iLastAckSentRxSeqNum) >= iConfig->PeerTXWindowSize())
       
   448 			{
       
   449 			// The number is not in range.  No more I-Frames will be processed
       
   450 			// until flow control is deactivated.
       
   451 			iSenderTxWindowClosed = ETrue;
       
   452 			}
       
   453 		}
       
   454 
       
   455 	LOG(_L("FEC CL2CapDataFlowController: HandleIncomingIFrame"))
       
   456 	LOG1(_L("\tTxSeqNumber = %d"), HIFramePDU::TxSeqNumber(aDataFrame))
       
   457 	LOG1(_L("\tLastAckSentRxSeqNum = %d"), iLastAckSentRxSeqNum)
       
   458 	
       
   459 	if(!iSenderTxWindowClosed)
       
   460 		{
       
   461 		ProcessIFrameL(aDataFrame);
       
   462 		}
       
   463 	else
       
   464 		{
       
   465 		// Drop the frame.
       
   466 		aDataFrame.Free();
       
   467 		LOG(_L("FEC CL2CapDataFlowController: Incoming PDU seq number of I-Frame is not in range!"))
       
   468 		}
       
   469 	}
       
   470 
       
   471 void CL2CapDataFlowController::ProcessIFrameL(RMBufChain& aDataFrame)
       
   472 	{
       
   473 	LOG_FUNC
       
   474 	iExpectedTxSeq = Mod64(iExpectedTxSeq + 1); 
       
   475 	iExpectedAckSeq = HIFramePDU::ReqSeqNumber(aDataFrame);
       
   476 	
       
   477 	LEAVEIFERRORL(iSDUQueue.PutIFramePDU(aDataFrame));
       
   478 
       
   479 	// Check if the acknowledged frame(s) has created
       
   480 	// space in the window.	
       
   481 	RemoveAckedPDUsFromSentQueue();
       
   482 
       
   483 	// Only send an ack if incoming data is not currently flow controlled off.
       
   484 	if(!iIncomingSduQFull)
       
   485 		{
       
   486 		// Check if the peer frames need to be acknowledged now.
       
   487 		// Check the peer TxWindow.  This check is
       
   488 		// (Number of I-Frames recv since last Ack was sent > (TxWindow - Constant)
       
   489 		if(Mod64(iExpectedTxSeq - iLastAckSentRxSeqNum) > (iConfig->PeerTXWindowSize() - KTxWinAckThresholdOffset))
       
   490 			{
       
   491 			// Send an ack.
       
   492 			iSendAckToPeer = ETrue;
       
   493 			}
       
   494 		else
       
   495 			{
       
   496 			// If the timer is not running, start it.
       
   497 			if(!iTimerMan.IsSendPeerAckTimerRunning())
       
   498 				{
       
   499 				if(!iTimerMan.StartSendPeerAckTimer())
       
   500 					{
       
   501 					// A timer could not be started.  Send an ack immediately.
       
   502 					iSendAckToPeer = ETrue;
       
   503 					}
       
   504 				}
       
   505 			}
       
   506 		}
       
   507 	// Check if any outbound data can be sent.
       
   508 	PDUAvailable();
       
   509 	}
       
   510 
       
   511 void CL2CapDataFlowController::HandleIncomingSFrameL(RMBufChain& aDataFrame)
       
   512 	{
       
   513 	LOG_FUNC
       
   514 	// Check that the function is RR.  If not this S-Frame is not valid for
       
   515 	// flow control mode.
       
   516 	if(HSFramePDU::SupervisoryFunction(aDataFrame) == EReceiverReady)
       
   517 		{
       
   518 		iExpectedAckSeq = HSFramePDU::ReqSeqNumber(aDataFrame);
       
   519 		// Check if the acknowledged frame(s) has created
       
   520 		// space in the window.	
       
   521 		RemoveAckedPDUsFromSentQueue();
       
   522 		PDUAvailable();				
       
   523 		LOG(_L("FEC CL2CapDataFlowController: Incoming S-Frame: RR"))				
       
   524 		LOG1(_L("\tiLastAckedFrameNum = %d"),  iExpectedAckSeq)
       
   525 		}
       
   526 	}
       
   527 
       
   528 TInt CL2CapDataFlowController::HandleOutgoingIFrame(HIFramePDU* aIFrame)
       
   529 	{
       
   530 	LOG_FUNC
       
   531 	aIFrame->SetPDUCID(iRemoteCID);
       
   532 	aIFrame->SetTxSeqNumber(iNextTxSeq);
       
   533 	LOG(_L("FEC CL2CapDataFlowController: HandleOutgoingIFrame"))
       
   534 	LOG1(_L("\tTxSeqNumber = %d"), iNextTxSeq)
       
   535 	iNextTxSeq = Mod64(iNextTxSeq + 1);
       
   536 
       
   537 	// If flow controlled off - don't acknowledge any new I-Frames
       
   538 	aIFrame->SetReqSeqNumber(iIncomingSduQFull ? iLastAckSentRxSeqNum : iExpectedTxSeq);
       
   539 
       
   540 	// Set the retransmission disable bit if flow control is on.
       
   541 	aIFrame->SetRetransmitDisable(iIncomingSduQFull);
       
   542 	aIFrame->CalculateAndSetFCS();
       
   543 
       
   544 	aIFrame->iLink.Deque(); // just in case, it shouldn't be on any list at this point
       
   545 	aIFrame->SetPduOwner(this);
       
   546 	iPendingSentPDUs.AddLast(*aIFrame);
       
   547 	
       
   548 	// Cancel the peer ack timer.
       
   549 	iTimerMan.StopSendPeerAckTimer();
       
   550 	iSendAckToPeer = EFalse;
       
   551 
       
   552 	// Store the last acknowledged frame index.
       
   553 	if(!iIncomingSduQFull)
       
   554 		{
       
   555 		iLastAckSentRxSeqNum = iExpectedTxSeq;
       
   556 		}
       
   557 	LOG1(_L("\tLastAckSentRxSeqNum = %d"), iLastAckSentRxSeqNum)
       
   558 	
       
   559 	return KErrNone;
       
   560 	}
       
   561 
       
   562 TInt CL2CapDataFlowController::HandleOutgoingSFrame(HSFramePDU* aSFrame)
       
   563 	{
       
   564 	LOG_FUNC
       
   565 	aSFrame->SetPDUCID(iRemoteCID);
       
   566 	// If flow controlled off - don't acknowledge any new I-Frames
       
   567 	aSFrame->SetReqSeqNumber(iIncomingSduQFull ? iLastAckSentRxSeqNum : iExpectedTxSeq);
       
   568 	LOG(_L("FEC CL2CapDataFlowController: HandleOutgoingSFrame"))		
       
   569 	LOG1(_L("\tReqSeqNUmber = %d"), iIncomingSduQFull ? iLastAckSentRxSeqNum : iExpectedTxSeq)
       
   570 	// Set the retransmission disable bit if flow control is on.
       
   571 	aSFrame->SetRetransmitDisable(iIncomingSduQFull);
       
   572 	aSFrame->CalculateAndSetFCS();
       
   573 
       
   574 	// If the monitor timer is currently running.  Re-start it.
       
   575 	if(!iTimerMan.IsAckTimerRunning())
       
   576 		{
       
   577 		iTimerMan.StartMonitorTimer();
       
   578 		}
       
   579 
       
   580 	// Store the last acknowledged frame index.
       
   581 	if(!iIncomingSduQFull)
       
   582 		{
       
   583 		iLastAckSentRxSeqNum = iExpectedTxSeq;
       
   584 		}
       
   585 		
       
   586 	// Cancel the peer ack timer.
       
   587 	iTimerMan.StopSendPeerAckTimer();
       
   588 	iSendAckToPeer = EFalse;
       
   589 	LOG1(_L("\tLastAckSentRxSeqNum = %d"), iLastAckSentRxSeqNum)
       
   590 	return KErrNone;
       
   591 	}
       
   592 
       
   593 TBool CL2CapDataFlowController::CanSendPDU()
       
   594 	{
       
   595 	LOG_FUNC
       
   596 	TBool canSend = ETrue;
       
   597 
       
   598 	// This condition is (V(S) - V(A))mod64 >= TxWindow
       
   599 	if(Mod64(iNextTxSeq - iExpectedAckSeq) >= iConfig->TXWindowSize())
       
   600 		{
       
   601 		canSend = EFalse;
       
   602 		}	
       
   603 	return canSend;
       
   604 	}
       
   605 
       
   606 					
       
   607 HL2CapPDU* CL2CapDataFlowController::GetPduL()
       
   608 	{
       
   609 	LOG_FUNC
       
   610 	// This is called from the signal manager.
       
   611 	HL2CapPDU* pduToSend = NULL;
       
   612 
       
   613 	if(CanSendPDU())
       
   614 		{	
       
   615 		pduToSend = iSDUQueue.GetPDU();
       
   616 		}
       
   617 
       
   618 	if(pduToSend)
       
   619 		{
       
   620 		pduToSend->DeliverOutgoingPDU(*this);
       
   621 		}
       
   622 
       
   623 	// Note:  If pduToSend has a valid pointer then the call to 
       
   624 	// pduToSend->DeliverOutgoingPDU(*this) (above) will clear the 
       
   625 	// iSendAckToPeer flag.
       
   626 	if(iSendAckToPeer)
       
   627 		{
       
   628 		pduToSend = HSFramePDU::New(EReceiverReady);
       
   629 		if(pduToSend)
       
   630 			{
       
   631 			pduToSend->DeliverOutgoingPDU(*this);
       
   632 			}
       
   633 		else
       
   634 			{
       
   635 			ErrorD(KErrNoMemory);
       
   636 			// We've been deleted!
       
   637 			}
       
   638 		}
       
   639 	return pduToSend;
       
   640 	}
       
   641 
       
   642 
       
   643 void CL2CapDataFlowController::PDUAvailable()
       
   644 	{
       
   645 	LOG_FUNC
       
   646 
       
   647 	// Note that CanSend only checks whether there's available outgoing window space,
       
   648 	// not whether there really is some outstanding data on SDU Q. GetPduL will check
       
   649 	// that and do nothing if there isn't.
       
   650 	if(CanSendPDU() || iSendAckToPeer)
       
   651 		{
       
   652 		iMuxer.PDUAvailable();
       
   653 		}
       
   654 	}
       
   655 
       
   656 void CL2CapDataFlowController::RemoveAckedPDUsFromSentQueue()
       
   657 	{
       
   658 	LOG_FUNC
       
   659 	TDblQueIter<HIFramePDU> iter(iSentPDUs);
       
   660 	HIFramePDU* pduPtr;
       
   661 	TInt ackedPDUs = 0;
       
   662 	TInt count = 0;
       
   663 
       
   664 	TUint8 frameSeqNumber = Mod64(iExpectedAckSeq - 1);
       
   665 
       
   666 	// Find out how many PDU's have been ack'd
       
   667 	while((pduPtr = iter++) != NULL)
       
   668 		{
       
   669 		if(pduPtr->TxSeqNumber() == frameSeqNumber)
       
   670 			{
       
   671 			// Increment the count by one and exit the loop.
       
   672 			ackedPDUs = count + 1;
       
   673 			break;
       
   674 			}
       
   675 		count++;
       
   676 		}
       
   677 
       
   678 	// Remove all ack'd PDUs
       
   679 	iter.SetToFirst();
       
   680 	for(TInt i=0;i<ackedPDUs;i++)
       
   681 		{
       
   682 		pduPtr = iter++;
       
   683 		delete pduPtr;
       
   684 		}
       
   685 
       
   686 	// Some PDUs have been ack'd.
       
   687 	if(ackedPDUs)
       
   688 		{
       
   689 		if(iSentPDUs.IsEmpty())
       
   690 			{
       
   691 			iTimerMan.StartMonitorTimer();
       
   692 			}
       
   693 		else
       
   694 			{
       
   695 			iTimerMan.StopMonitorTimer();
       
   696 			iTimerMan.StartAckTimer();
       
   697 			}
       
   698 		}
       
   699 	}
       
   700 
       
   701 void CL2CapDataFlowController::MonitorTimerExpired()
       
   702 	{
       
   703 	LOG_FUNC
       
   704 	// The monitor timer has expired.  Send a S-Frame to the peer by setting
       
   705 	// the ack outstanding flag and calling PDUAvailable.  This method will
       
   706 	// call this back at which point the S-Frame will be created.
       
   707 	LOG(_L("FEC CL2CapDataFlowController::MonitorTimerExpired"))
       
   708 	iSendAckToPeer = ETrue;
       
   709 	PDUAvailable();
       
   710 	}
       
   711 	
       
   712 	
       
   713 void CL2CapDataFlowController::AckTimerExpired()
       
   714 	{
       
   715 	LOG_FUNC
       
   716 	// Remove the PDU that the timer is supervising.  This can
       
   717 	// only be the first Sent PDU.
       
   718 	LOG(_L("FEC CL2CapDataFlowController::AckTimerExpired"))
       
   719 	__ASSERT_DEBUG(!iSentPDUs.IsEmpty(), Panic(EL2CAPAckTimerExpiryWithoutPDUToSupervise));
       
   720 	
       
   721 	HL2CapPDU* pdu = iSentPDUs.First();
       
   722 	delete pdu;
       
   723 
       
   724 	iExpectedAckSeq = Mod64(iExpectedAckSeq + 1);
       
   725 
       
   726 	if(iSentPDUs.IsEmpty())
       
   727 		{
       
   728 		iTimerMan.StartMonitorTimer();
       
   729 		}
       
   730 	else
       
   731 		{
       
   732 		iTimerMan.StopMonitorTimer();
       
   733 		iTimerMan.StartAckTimer();
       
   734 		}
       
   735 	PDUAvailable();	
       
   736 	}
       
   737 
       
   738 void CL2CapDataFlowController::SendPeerAckTimerExpired()
       
   739 	{
       
   740 	LOG_FUNC
       
   741 
       
   742 	// Indicate that an ack should be sent to the peer to
       
   743 	// acknowledge receipt of I-Frames.
       
   744 	iSendAckToPeer = ETrue;
       
   745 	PDUAvailable();	
       
   746 	}
       
   747 
       
   748 TUint16 CL2CapDataFlowController::MonitorTimeout()
       
   749 	{
       
   750 	return iConfig->MonitorTimeout();
       
   751 	}
       
   752 
       
   753 TUint16 CL2CapDataFlowController::RetransmissionTimeout()
       
   754 	{
       
   755 	return iConfig->RetransmissionTimeout();
       
   756 	}
       
   757 
       
   758 TUint16 CL2CapDataFlowController::PeerRetransmissionTimeout()
       
   759 	{
       
   760 	return iConfig->PeerRetransmissionTimeout();
       
   761 	}
       
   762 
       
   763 
       
   764 void CL2CapDataFlowController::HandlePduSendComplete(HL2CapPDU& aPdu)
       
   765 	{
       
   766 	LOG_FUNC
       
   767 
       
   768 	// We only claim ownership of I-Frames.
       
   769 	HIFramePDU& IFrame = static_cast<HIFramePDU&>(aPdu);
       
   770 
       
   771 	// Remove the PDU from the pending send queue.
       
   772 	IFrame.iLink.Deque();
       
   773 	
       
   774 	// If there are outstanding (i.e., un-ack'ed) PDU's, the
       
   775 	// Ack timer will already be running.  Otherwise it should
       
   776 	// be started.
       
   777 	if(iSentPDUs.IsEmpty())
       
   778 		{
       
   779 		iTimerMan.StartAckTimer();
       
   780 		}
       
   781 
       
   782 	// It's waiting for acknowledgement now.
       
   783 	iSentPDUs.AddLast(IFrame);
       
   784 	PDUAvailable();
       
   785 	}
       
   786 
       
   787 void CL2CapDataFlowController::HandlePduSendError(HL2CapPDU& /*aPdu*/)
       
   788 	{
       
   789 	LOG_FUNC
       
   790 	// In FC mode the frame will get deleted when we get an acknowledgement.
       
   791 	// In RTM, protocol-level retransmissions will be run when peer rejects or
       
   792 	// our ack timer expires.
       
   793 	}
       
   794 
       
   795 
       
   796 void CL2CapDataFlowController::SetIncomingSduQFull(TBool aIncomingSduQFull)
       
   797 	{
       
   798 	LOG_FUNC
       
   799 	// Check that the FC status has changed
       
   800 	if(iIncomingSduQFull != aIncomingSduQFull)
       
   801 		{
       
   802 		iIncomingSduQFull = aIncomingSduQFull;
       
   803 		iSenderTxWindowClosed = EFalse;
       
   804 
       
   805 		// Send an acknowledgement to the peer indicate the new
       
   806 		// flow control status.
       
   807 		iSendAckToPeer = ETrue;
       
   808 		PDUAvailable();
       
   809 		}
       
   810 	}
       
   811 
       
   812 
       
   813 // ***** CL2CapDataReTxController Implementation
       
   814 CL2CapDataReTxController::CL2CapDataReTxController(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, CL2CapSDUQueue& aSDUQueue, TL2CapDataControllerConfig* aConfig)
       
   815  : CL2CapDataFlowController(aLocalCID, aRemoteCID, aMuxer, aSDUQueue, aConfig),
       
   816    iRejectPDU(0),
       
   817    iRetransmitSentPDUs(EFalse),
       
   818    iRejectSent(EFalse),
       
   819    iRetransmissionDisabled(EFalse),
       
   820    iRestartAckTimer(EFalse),
       
   821    iRetransTxVal(iNextTxSeq)
       
   822 	{
       
   823 	LOG_FUNC
       
   824 	}
       
   825 	
       
   826 void CL2CapDataReTxController::HandleIncomingIFrameL(RMBufChain& aDataFrame)
       
   827 	{
       
   828 	LOG_FUNC
       
   829 	TBool newRtxDisable = HIFramePDU::RetransmitDisable(aDataFrame);
       
   830 	if(iExpectedTxSeq == HIFramePDU::TxSeqNumber(aDataFrame))
       
   831 		{
       
   832 		LOG(_L("FEC CL2CapDataReTxController: HandleIncomingIFrame"))
       
   833 		LOG1(_L("\tTxSeqNumber = %d"), HIFramePDU::TxSeqNumber(aDataFrame))	
       
   834 		ProcessIFrameL(aDataFrame);
       
   835 		iRejectSent = EFalse;
       
   836 		}
       
   837 	else
       
   838 		{
       
   839 		// This I-Frame has an invalid sequence number.
       
   840 		// Check that a Reject Exception is not already being
       
   841 		// handled.
       
   842 		if(!iRejectSent)
       
   843 			{
       
   844 			iRejectPDU = HSFramePDU::NewL(EReject);
       
   845 			iRejectPDU->DeliverOutgoingPDU(*this);
       
   846 			// Send the Reject PDU.
       
   847 			iMuxer.PDUAvailable();
       
   848 			iRejectSent = ETrue;
       
   849 			}
       
   850 		aDataFrame.Free();
       
   851 		LOG(_L("FEC CL2CapDataReTxController: Incoming PDU seq number of I-Frame is not in range!"))
       
   852 		}
       
   853 	
       
   854 	// Check if the re-transmission disable bit has transitioned.
       
   855 	if(iRetransmissionDisabled != newRtxDisable)
       
   856 		{
       
   857 		if(newRtxDisable)
       
   858 			{
       
   859 			// Re-transmission has been disabled.
       
   860 			iTimerMan.StartMonitorTimer();
       
   861 			}
       
   862 		else
       
   863 			{
       
   864 			// Re-transmission has been enabled.
       
   865 			if(!iSentPDUs.IsEmpty())
       
   866 				{
       
   867 				iTimerMan.StopMonitorTimer();
       
   868 				iTimerMan.StartAckTimer();
       
   869 				}
       
   870 			}
       
   871 		iRetransmissionDisabled = newRtxDisable;
       
   872 		}
       
   873 	}
       
   874 
       
   875 void CL2CapDataReTxController::HandleIncomingSFrameL(RMBufChain& aDataFrame)
       
   876 	{
       
   877 	LOG_FUNC
       
   878 	if(HSFramePDU::SupervisoryFunction(aDataFrame) == EReject)
       
   879 		{
       
   880 		iRetransmitSentPDUs = ETrue;
       
   881 		iRetransTxVal = HSFramePDU::ReqSeqNumber(aDataFrame);
       
   882 		LOG(_L("FEC CL2CapDataReTxController: Incoming S-Frame: Reject"))		
       
   883 		}
       
   884 	iExpectedAckSeq = HSFramePDU::ReqSeqNumber(aDataFrame);
       
   885 	LOG(_L("FEC CL2CapDataReTxController: Incoming S-Frame"))
       
   886 	LOG1(_L("\tLastAckedFrameNum = %d"), iExpectedAckSeq)
       
   887 
       
   888 	TBool newRtxDisable = HSFramePDU::RetransmitDisable(aDataFrame);
       
   889 
       
   890 	// Check if the acknowledged frame(s) has created
       
   891 	// space in the window.	
       
   892 	RemoveAckedPDUsFromSentQueue();
       
   893 	PDUAvailable();				
       
   894 	
       
   895 	// Check if the re-transmission disable bit has transitioned.
       
   896 	if(iRetransmissionDisabled != newRtxDisable)
       
   897 		{
       
   898 		if(newRtxDisable)
       
   899 			{
       
   900 			// Re-transmission has been disabled.
       
   901 			iTimerMan.StartMonitorTimer();
       
   902 			}
       
   903 		else
       
   904 			{
       
   905 			// Re-transmission has been enabled.
       
   906 			if(!iSentPDUs.IsEmpty())
       
   907 				{
       
   908 				iTimerMan.StopMonitorTimer();
       
   909 				iTimerMan.StartAckTimer();
       
   910 				}
       
   911 			}
       
   912 		iRetransmissionDisabled = newRtxDisable;
       
   913 		}
       
   914 	}
       
   915 
       
   916 HL2CapPDU* CL2CapDataReTxController::GetPduL()
       
   917 	{
       
   918 	LOG_FUNC
       
   919 	// This is called from the signal manager.
       
   920 	HL2CapPDU* pduToSend = NULL;
       
   921 
       
   922 	// Check the re-transmission disabled flag.  If its set
       
   923 	// then only S-Frames can be sent.
       
   924 	if(!iRetransmissionDisabled && !iDataPlaneErrored)
       
   925 		{
       
   926 		if(iRejectPDU)
       
   927 			{
       
   928 			pduToSend = iRejectPDU;
       
   929 			iRejectPDU = NULL;
       
   930 			}
       
   931 		else
       
   932 			{
       
   933 			if(iRetransmitSentPDUs)
       
   934 				{
       
   935 				pduToSend = RetransmitSentPDU();
       
   936 				}	
       
   937 
       
   938 			if(!pduToSend && CanSendPDU())
       
   939 				{	
       
   940 				pduToSend = iSDUQueue.GetPDU();
       
   941 				}
       
   942 			}
       
   943 		}
       
   944 
       
   945 	if(pduToSend)
       
   946 		{
       
   947 		pduToSend->DeliverOutgoingPDU(*this);
       
   948 		}
       
   949 
       
   950 	// Note:  If pduToSend has a valid pointer then the call to 
       
   951 	// pduToSend->DeliverOutgoingPDU(*this) (above) will clear the 
       
   952 	// iSendAckToPeer flag.
       
   953 	if(iSendAckToPeer)
       
   954 		{
       
   955 		pduToSend = HSFramePDU::New(EReceiverReady);
       
   956 		if(pduToSend)
       
   957 			{
       
   958 			pduToSend->DeliverOutgoingPDU(*this);
       
   959 			}
       
   960 		else
       
   961 			{
       
   962 			ErrorD(KErrNoMemory);
       
   963 			// We've been deleted!
       
   964 			}
       
   965 		}
       
   966 	return pduToSend;
       
   967 	}
       
   968 
       
   969 void CL2CapDataReTxController::PDUAvailable()
       
   970 	{
       
   971 	LOG_FUNC
       
   972 
       
   973 	// Note that CanSend only checks whether there's available outgoing window space,
       
   974 	// not whether there really is some outstanding data on SDU Q. GetPduL will check
       
   975 	// that and do nothing if there isn't.
       
   976 	if(CanSendPDU() || iSendAckToPeer || iRetransmitSentPDUs)
       
   977 		{
       
   978 		iMuxer.PDUAvailable();
       
   979 		}
       
   980 	}
       
   981 
       
   982 void CL2CapDataReTxController::AckTimerExpired()
       
   983 	{
       
   984 	LOG_FUNC
       
   985 	__ASSERT_DEBUG(!iSentPDUs.IsEmpty(), Panic(EL2CAPAckTimerExpiryWithoutPDUToSupervise));
       
   986 
       
   987 	// Check if the PDU can be re-sent (i.e., the Max.
       
   988 	// transmit has not been exceeded.)
       
   989 	
       
   990     HIFramePDU* pdu = iSentPDUs.First();
       
   991         
       
   992 	if(pdu->CanTransmit(iConfig->MaxTransmit()))
       
   993 		{
       
   994 		// Set the next frame to be transmitted to the PDU 
       
   995 		// whose timer expired.
       
   996 		iRetransTxVal = pdu->TxSeqNumber();
       
   997 		iRetransmitSentPDUs = ETrue;
       
   998 		iRestartAckTimer = ETrue;
       
   999 
       
  1000 		// The frame will be re-transmitted when GetPDU is called.
       
  1001 		// This will also re-start the Retransmission timer.
       
  1002 		PDUAvailable();	
       
  1003 		}
       
  1004 	else
       
  1005 		{
       
  1006 		// The channel can not support the requested quality.
       
  1007 		// i.e., the number of retransmissions before the channel is
       
  1008 		// disconnected has been exceeded.
       
  1009 		// Error the SAP to disconnect the channel.
       
  1010 		ErrorD(KErrL2CAPMaxTransmitExceeded);
       
  1011 		LOG(_L("FEC CL2CapDataReTxController::AckTimerExpired - KErrL2CAPMaxTransmitExceeded"))	
       
  1012 		}
       
  1013 	}
       
  1014 
       
  1015 HL2CapPDU* CL2CapDataReTxController::RetransmitSentPDU()
       
  1016 	{
       
  1017 	LOG_FUNC
       
  1018 	HIFramePDU* pduToSend = NULL;
       
  1019 	TDblQueIter<HIFramePDU> iter(iSentPDUs);
       
  1020 	HIFramePDU* pduPtr;
       
  1021 	
       
  1022 	while((pduPtr = iter++) != NULL)
       
  1023 		{
       
  1024 		if(pduPtr->TxSeqNumber() == iRetransTxVal)
       
  1025 			{
       
  1026 			pduToSend = pduPtr;
       
  1027 			break;
       
  1028 			}
       
  1029 		}
       
  1030 
       
  1031 	if(!pduToSend)
       
  1032 		{
       
  1033 		iRetransmitSentPDUs = EFalse;
       
  1034 		}
       
  1035 	return pduToSend;
       
  1036 	}
       
  1037 
       
  1038 void CL2CapDataReTxController::HandlePduSendComplete(HL2CapPDU& aPdu)
       
  1039 	{
       
  1040 	LOG_FUNC
       
  1041 
       
  1042 	// We only claim ownership of I-Frames.
       
  1043 	HIFramePDU& IFrame = static_cast<HIFramePDU&>(aPdu);
       
  1044 
       
  1045 	// Remove the PDU from the pending send queue.
       
  1046 	IFrame.iLink.Deque();
       
  1047 	
       
  1048 	// If there are outstanding (i.e., un-ack'ed) PDU's, the
       
  1049 	// Ack timer will already be running.  Otherwise it should
       
  1050 	// be started.
       
  1051 	if(iSentPDUs.IsEmpty() || iRestartAckTimer)
       
  1052 		{
       
  1053 		iTimerMan.StopMonitorTimer();
       
  1054 		iRestartAckTimer = EFalse;
       
  1055 		iTimerMan.StartAckTimer();
       
  1056 		}
       
  1057 
       
  1058 	iSentPDUs.AddLast(IFrame);
       
  1059 	
       
  1060 	// When operating in lossy conditions such as when running 
       
  1061 	// concurrently with a name inquiry it is possible for an 
       
  1062 	// acknowledgement to arrive before the sent completion code is called
       
  1063 	// for the relevant PDU.  As a result aIFrame may have already been 
       
  1064 	// acknowledged.  Now that we have ownership of the PDU we can 
       
  1065 	// remove it and cancel the Ack timer if necessary.
       
  1066 	
       
  1067 	// N.B. Here we have assumed that the delay in the notification 
       
  1068 	// that a PDU has been sent (thereby moving it from the pending sent
       
  1069 	// queue to the sent queue) is not so large that in the mean time we
       
  1070 	// have sent so many new PDUs that the transmission window has wrapped
       
  1071 	// so far around that an old I-Frame from the last cycle is 
       
  1072 	// considered an unacknowledged one because the Tx Seq value is once again 
       
  1073 	// in the valid transmission window.  This would require BT to be much
       
  1074 	// faster than it currently is (11/04/2007). 
       
  1075 	RemoveAckedPDUsFromSentQueue();
       
  1076 	PDUAvailable();
       
  1077 	}
       
  1078 	
       
  1079 void CL2CapDataReTxController::RemoveAckedPDUsFromSentQueue()
       
  1080 	{
       
  1081 	LOG_FUNC
       
  1082 	TDblQueIter<HIFramePDU> iter(iSentPDUs);
       
  1083 	HIFramePDU* pduPtr;
       
  1084 	TBool ackedPDUs = EFalse;
       
  1085 
       
  1086 	// Remove PDUs which have been previously acknowledged.
       
  1087 	// The queue may be out of order due to retransmissions 
       
  1088 	// being appended at the end of the sent queue.
       
  1089 	while((pduPtr = iter++) != NULL)
       
  1090 		{
       
  1091 		// If the PDU's Tx Seq number is not in the current valid transmission window it is considered a previously acknowledged I-Frame and is removed.
       
  1092 		if (!(((pduPtr->TxSeqNumber()>= iExpectedAckSeq) && (pduPtr->TxSeqNumber()< (iExpectedAckSeq + iConfig->TXWindowSize()))) || (((iExpectedAckSeq + iConfig->TXWindowSize()) > KL2CapTxSeqValues) && (pduPtr->TxSeqNumber()< Mod64((iExpectedAckSeq + iConfig->TXWindowSize()))))))
       
  1093 			{
       
  1094 			ackedPDUs = ETrue;
       
  1095 			delete pduPtr;
       
  1096 			}
       
  1097 		}
       
  1098 
       
  1099 	// Some PDUs have been ack'd.
       
  1100 	if(ackedPDUs)
       
  1101 		{
       
  1102 		if(iSentPDUs.IsEmpty())
       
  1103 			{
       
  1104 			if (iDeliverOutgoingDataAndSignalToSduQWhenDone && iPendingSentPDUs.IsEmpty())
       
  1105 				{
       
  1106 				iSDUQueue.DataControllerDeliveredOutgoingData();
       
  1107 				}
       
  1108 			else
       
  1109 				{
       
  1110 				iTimerMan.StartMonitorTimer();
       
  1111 				}
       
  1112 			}
       
  1113 		else
       
  1114 			{
       
  1115 			iTimerMan.StopMonitorTimer();
       
  1116 			iTimerMan.StartAckTimer();
       
  1117 			}
       
  1118 		}
       
  1119 	}
       
  1120 
       
  1121 TInt CL2CapDataReTxController::HandleOutgoingIFrame(HIFramePDU* aIFrame)
       
  1122 	{
       
  1123 	LOG_FUNC
       
  1124 	aIFrame->SetPDUCID(iRemoteCID);
       
  1125 	
       
  1126 	// When sending a retransmission iRetransmitSentPDUs = ETrue.
       
  1127 	// When doing a retransmission the I-Frame has already had its Tx Seq
       
  1128 	// value set and iRetransTxVal is incremented so that we will continue
       
  1129 	// iterating through the sent PDUs for retransmission.
       
  1130 	// When sending a new I-Frame iNextTxSeq is used to get the next
       
  1131 	// brand new Tx Seq value (given the limitations of wrapping round the number
       
  1132 	// space).
       
  1133 	if (!iRetransmitSentPDUs)
       
  1134 		{
       
  1135 		aIFrame->SetTxSeqNumber(iNextTxSeq);
       
  1136 		iNextTxSeq = Mod64(iNextTxSeq + 1);
       
  1137 		}
       
  1138 	else
       
  1139 		{
       
  1140 		++iRetransTxVal;
       
  1141 		}
       
  1142 	
       
  1143 	LOG(_L("FEC CL2CapDataReTxController::HandleOutgoingIFrame"))		
       
  1144 	LOG1(_L("\tTxSeqNumber = %d"), (aIFrame->TxSeqNumber()))
       
  1145 
       
  1146 	// If flow controlled off - don't acknowledge any new I-Frames
       
  1147 	aIFrame->SetReqSeqNumber(iIncomingSduQFull ? iLastAckSentRxSeqNum : iExpectedTxSeq);
       
  1148 
       
  1149 	// Set the retransmission disable bit if flow control is on.
       
  1150 	aIFrame->SetRetransmitDisable(iIncomingSduQFull);
       
  1151 	aIFrame->CalculateAndSetFCS();
       
  1152 
       
  1153 	aIFrame->iLink.Deque(); // may be on Sent PDU list if it's a retransmission
       
  1154 	aIFrame->SetPduOwner(this);
       
  1155 	iPendingSentPDUs.AddLast(*aIFrame);
       
  1156 	if ((iSentPDUs.IsEmpty()) && iTimerMan.IsAckTimerRunning())
       
  1157 		{
       
  1158 		iRestartAckTimer = EFalse;
       
  1159 		iTimerMan.StartMonitorTimer();
       
  1160 		}
       
  1161 
       
  1162 	// Cancel the peer ack timer.
       
  1163 	iTimerMan.StopSendPeerAckTimer();
       
  1164 	iSendAckToPeer = EFalse;
       
  1165 
       
  1166 	// Store the last acknowledged frame index.
       
  1167 	if(!iIncomingSduQFull)
       
  1168 		{
       
  1169 		iLastAckSentRxSeqNum = iExpectedTxSeq;
       
  1170 		}
       
  1171 	LOG1(_L("\tLastAckSentRxSeqNum = %d"), iLastAckSentRxSeqNum)
       
  1172 
       
  1173 	return KErrNone;
       
  1174 	}
       
  1175 
       
  1176 TBool CL2CapDataReTxController::DeliverOutgoingDataAndSignalToSduQWhenDone()
       
  1177 	{
       
  1178 	LOG_FUNC
       
  1179 	iDeliverOutgoingDataAndSignalToSduQWhenDone = ETrue;
       
  1180 	// Returning true means we don't have any outstanding data to deliver and
       
  1181 	// hence can be deleted immediately.
       
  1182 	return iPendingSentPDUs.IsEmpty() && iSentPDUs.IsEmpty();
       
  1183 	}
       
  1184 
       
  1185 
       
  1186 RL2CapRetransmissionModeTimerManager::RL2CapRetransmissionModeTimerManager(MRetransmissionModeTimerClient& aClient)
       
  1187  :	iClient(aClient) 
       
  1188 	{
       
  1189 	LOG_FUNC
       
  1190 	}
       
  1191 
       
  1192 void RL2CapRetransmissionModeTimerManager::Close()
       
  1193 	{
       
  1194 	LOG_FUNC
       
  1195 	CancelFECTimer();
       
  1196 	StopSendPeerAckTimer();
       
  1197 	}
       
  1198 
       
  1199 void RL2CapRetransmissionModeTimerManager::StartMonitorTimer()
       
  1200 	{
       
  1201 	LOG_FUNC
       
  1202 	// Monitor timer preempts the Ack timer, so we can stop whichever we have running.
       
  1203 	CancelFECTimer();
       
  1204 	
       
  1205 	TCallBack cb(FECTimerExpired, this);
       
  1206 	iFECTimerEntry.Set(cb);
       
  1207 	
       
  1208 	// Set the timeout.  The value is in Milliseconds.
       
  1209 	BTSocketTimer::Queue(iClient.MonitorTimeout()*1000, iFECTimerEntry);
       
  1210 	iFECTimerState = EMonitorTimerRunning;
       
  1211 	}
       
  1212 
       
  1213 void RL2CapRetransmissionModeTimerManager::StartAckTimer()
       
  1214 	{
       
  1215 	LOG_FUNC
       
  1216 
       
  1217 	if (iFECTimerState != EMonitorTimerRunning)
       
  1218 		// Ack timer can't be run when the Monitor timer is running.
       
  1219 		{
       
  1220 		CancelFECTimer();
       
  1221 	
       
  1222 		TCallBack cb(FECTimerExpired, this);
       
  1223 		iFECTimerEntry.Set(cb);
       
  1224 	
       
  1225 		// Set the timeout.  The value is in Milliseconds.
       
  1226 		BTSocketTimer::Queue(iClient.RetransmissionTimeout()*1000, iFECTimerEntry);
       
  1227 		iFECTimerState = EAckTimerRunning;
       
  1228 		}
       
  1229 	}
       
  1230 
       
  1231 void RL2CapRetransmissionModeTimerManager::StopMonitorTimer()
       
  1232 	{
       
  1233 	LOG_FUNC
       
  1234 	if (iFECTimerState == EMonitorTimerRunning)
       
  1235 		{
       
  1236 		CancelFECTimer();
       
  1237 		}
       
  1238 	}
       
  1239 
       
  1240 void RL2CapRetransmissionModeTimerManager::StopAckTimer()
       
  1241 	{
       
  1242 	LOG_FUNC
       
  1243 	if (iFECTimerState == EAckTimerRunning)
       
  1244 		{
       
  1245 		CancelFECTimer();
       
  1246 		}
       
  1247 	}
       
  1248 
       
  1249 void RL2CapRetransmissionModeTimerManager::CancelFECTimer()
       
  1250 	{
       
  1251 	LOG_FUNC
       
  1252 	// Cancel either the monitor or ack timer.
       
  1253 	if(iFECTimerState != EFECTimerIdle)
       
  1254 		{
       
  1255 		// Cancel the current outgoing timer.
       
  1256 		BTSocketTimer::Remove(iFECTimerEntry);
       
  1257 		iFECTimerState = EFECTimerIdle;
       
  1258 		}
       
  1259 	}
       
  1260 
       
  1261 void RL2CapRetransmissionModeTimerManager::HandleFECTimerExpired()
       
  1262 	{
       
  1263 	LOG_FUNC
       
  1264 	// Call the appropriate method to handle this expiry.
       
  1265 	switch(iFECTimerState)
       
  1266 		{
       
  1267 		case EFECTimerIdle:
       
  1268 			Panic(EL2CAPInvalidDataControllerTimerState);
       
  1269 			break;
       
  1270 			
       
  1271 		case EMonitorTimerRunning:
       
  1272 			iFECTimerState = EFECTimerIdle;
       
  1273 			iClient.MonitorTimerExpired();
       
  1274 			break;
       
  1275 			
       
  1276 		case EAckTimerRunning:
       
  1277 			iFECTimerState = EFECTimerIdle;
       
  1278 			iClient.AckTimerExpired();
       
  1279 			break;
       
  1280 
       
  1281 		default:
       
  1282 			Panic(EL2CAPInvalidDataControllerTimerState);
       
  1283 			break;
       
  1284 		}
       
  1285 	}
       
  1286 
       
  1287 void RL2CapRetransmissionModeTimerManager::HandleSendPeerAckTimerExpired()
       
  1288 	{
       
  1289 	LOG_FUNC
       
  1290 	__ASSERT_ALWAYS(iSendPeerAckTimerRunning, Panic(EL2CAPInvalidDataControllerTimerState));
       
  1291 	iSendPeerAckTimerRunning = EFalse;
       
  1292 	iClient.SendPeerAckTimerExpired();
       
  1293 	}
       
  1294 
       
  1295 TBool RL2CapRetransmissionModeTimerManager::StartSendPeerAckTimer()
       
  1296 	{
       
  1297 	LOG_FUNC
       
  1298 	// This timer should only be started if the peer is using a long re-transmission timer.
       
  1299 	__ASSERT_ALWAYS(!iSendPeerAckTimerRunning, Panic(EL2CAPInvalidDataControllerTimerState));
       
  1300 	
       
  1301 	TInt peerAckTimer = iClient.PeerRetransmissionTimeout() - KAveTimeToTransmitAckToPeer;
       
  1302 	if(peerAckTimer > KMinimumPeerAckTimeout)
       
  1303 		{
       
  1304 		TCallBack cb(SendPeerAckTimerExpired, this);
       
  1305 		iSendPeerAckTimerEntry.Set(cb);
       
  1306 
       
  1307 		// Set the timeout.  The value os in Milliseconds.
       
  1308 		BTSocketTimer::Queue(peerAckTimer*1000, iSendPeerAckTimerEntry);
       
  1309 		iSendPeerAckTimerRunning = ETrue;
       
  1310 		}
       
  1311 	return iSendPeerAckTimerRunning;
       
  1312 	}
       
  1313 
       
  1314 void RL2CapRetransmissionModeTimerManager::StopSendPeerAckTimer()
       
  1315 	{
       
  1316 	LOG_FUNC
       
  1317 	if (iSendPeerAckTimerRunning)
       
  1318 		{
       
  1319 		BTSocketTimer::Remove(iSendPeerAckTimerEntry);
       
  1320 		iSendPeerAckTimerRunning = EFalse;
       
  1321 		}
       
  1322 	}
       
  1323 
       
  1324 /*static*/ TInt RL2CapRetransmissionModeTimerManager::SendPeerAckTimerExpired(TAny* aTimerMan)
       
  1325 	{
       
  1326 	LOG_STATIC_FUNC
       
  1327 	RL2CapRetransmissionModeTimerManager* timerMan = reinterpret_cast<RL2CapRetransmissionModeTimerManager*>(aTimerMan);
       
  1328 	timerMan->HandleSendPeerAckTimerExpired();
       
  1329 	return EFalse;
       
  1330 	}
       
  1331 
       
  1332 /*static*/ TInt RL2CapRetransmissionModeTimerManager::FECTimerExpired(TAny* aTimeMan)
       
  1333 	{
       
  1334 	LOG_STATIC_FUNC
       
  1335 	RL2CapRetransmissionModeTimerManager* timeMan = reinterpret_cast<RL2CapRetransmissionModeTimerManager*>(aTimeMan);
       
  1336 	timeMan->HandleFECTimerExpired();
       
  1337 	return EFalse;
       
  1338 	}