bluetooth/btstack/l2cap/L2CapEnhancedDataController.h
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 #ifndef L2CAPENHANCEDDATACONTROLLER_H
       
    17 #define L2CAPENHANCEDDATACONTROLLER_H
       
    18 
       
    19 #include <e32std.h>
       
    20 #include <bt_sock.h>
       
    21 
       
    22 #include "L2CapPDU.h"
       
    23 #include "L2CapSDUQueue.h"
       
    24 #include "L2CapDataController.h"
       
    25 #include "l2signalmgr.h"
       
    26 
       
    27 
       
    28 NONSHARABLE_CLASS(CL2CapStreamingController) : public CL2CapBasicDataController, public MPduOwner
       
    29 	{
       
    30 public:
       
    31 	CL2CapStreamingController(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, CL2CapSDUQueue& aSDUQueue, TL2CapDataControllerConfig* aConfig);
       
    32 	virtual ~CL2CapStreamingController();
       
    33 
       
    34 	virtual void ProcessFlushTimerExpiry();
       
    35 
       
    36 	// MPduOwner
       
    37 	virtual void HandlePduSendComplete(HL2CapPDU& aPdu);
       
    38 	virtual void HandlePduSendError(HL2CapPDU& aPdu);
       
    39 
       
    40 protected:
       
    41 	virtual void HandleIncomingIFrameL(RMBufChain& aIFrame);
       
    42 	virtual TInt HandleOutgoingIFrame(HIFramePDU* aIFrame);
       
    43 
       
    44 	virtual HL2CapPDU* GetPduL();
       
    45 
       
    46 protected:
       
    47 	// Window related information, as defined in the spec.
       
    48 	// Sequencer for outgoing I-Frame numbers.
       
    49 	TUint8 iNextTxSeq;
       
    50 	// Next expected incoming I-Frame number. 
       
    51 	TUint8 iExpectedTxSeq;
       
    52 	};
       
    53 
       
    54 
       
    55 NONSHARABLE_CLASS(RL2CapErtmTimerManager) : public RL2CapRetransmissionModeTimerManager
       
    56 	{
       
    57 public:
       
    58 	RL2CapErtmTimerManager(class CL2CapEnhancedReTxController& aClient);
       
    59 	void Close();
       
    60 
       
    61 	void StartLocalBusyDelayTimer();
       
    62 	void StopLocalBusyDelayTimer();
       
    63 	inline TBool IsLocalBusyDelayTimerRunning() const;
       
    64 private:
       
    65 	void HandleLocalBusyDelayTimerExpired();
       
    66 	static TInt LocalBusyDelayTimerExpired(TAny* aTimerMan);
       
    67 private:
       
    68 	// Peer Retransmission Timer value is divided by this to obtain the LB delay timer
       
    69 	// value to use.
       
    70 	const static TInt KLocalBusyDelayTimerDenominator = 2;
       
    71 private:
       
    72 	TBool				iLocalBusyDelayTimerRunning;
       
    73 	TDeltaTimerEntry	iLocalBusyDelayTimerEntry;
       
    74 	};
       
    75 
       
    76 
       
    77 class CL2CapEnhancedReTxController;
       
    78 class RL2CapErtmOutgoingQueue;
       
    79 
       
    80 // Encapsulates a list of unacknowledged I-Frames and an index for fast TxSeqs
       
    81 // lookups for SREJ retransmissions.
       
    82 NONSHARABLE_CLASS(RL2CapErtmUnacknowledgedIFrames)
       
    83 	{
       
    84 public:
       
    85 	RL2CapErtmUnacknowledgedIFrames();
       
    86 	void Close();
       
    87 
       
    88 	inline void Append(HIFramePDU& aFrame);
       
    89 	inline void Remove(HIFramePDU& aFrame);
       
    90 	inline HIFramePDU* First() const;
       
    91 	inline HIFramePDU* Last() const;
       
    92 	inline HIFramePDU* operator[](TUint8 aTxSeq) const;
       
    93 	inline TBool IsEmpty() const;
       
    94 	inline TDblQueIter<HIFramePDU> Iterator();
       
    95 private:
       
    96 	// Ordered chronologically, oldest to youngest.
       
    97 	TDblQue<HIFramePDU>		iFrameList;
       
    98 	// Indexed by TxSeq.
       
    99 	TFixedArray<HIFramePDU*, KL2CapTxSeqValues>	iFrameIndex;
       
   100 	};
       
   101 
       
   102 NONSHARABLE_CLASS(CL2CapErtmDataTransmitter)
       
   103 	{
       
   104 public:
       
   105 	static CL2CapErtmDataTransmitter* NewL(CL2CapEnhancedReTxController& aController);
       
   106 	virtual ~CL2CapErtmDataTransmitter();	
       
   107 
       
   108 	void HandleIncomingIFrame(RMBufChain& aIFrame);
       
   109 	void HandleIncomingSFrameL(RMBufChain& aSFrame);
       
   110 
       
   111 	TBool HaveSpaceInOutgoingWindow() const;
       
   112 	HIFramePDU* GetIFrameToSendL();
       
   113  
       
   114 	void HciCompletedIFrame(HIFramePDU& aIFrame);
       
   115 
       
   116 	void AckTimerExpired();	
       
   117 
       
   118 	inline TBool RemoteBusy() const;
       
   119 
       
   120 	inline TBool IsWaitAckStatePending() const;
       
   121 	inline void EnterWaitAckState();
       
   122 	inline TBool InWaitAckState() const;
       
   123 
       
   124 	inline TUint8 NextTxSeq() const;
       
   125 	inline TUint8 ExpectedAckSeq() const;
       
   126 
       
   127 	inline TBool IsReqSeqValid(TUint8 aReqSeq);
       
   128 
       
   129 	inline TBool HaveUnackedIFrames() const;
       
   130 	inline TBool IsRetransmittingUnackedIFrames() const;
       
   131     inline TBool IsNextUnackedIFrameAwaitingHciCompletion() const;	
       
   132 
       
   133 private:
       
   134 	CL2CapErtmDataTransmitter(CL2CapEnhancedReTxController& aController);
       
   135 
       
   136 	void HandleReqSeqAck(TUint8 aReqSeq);
       
   137 	void HandleFinalAck();
       
   138 
       
   139 	void HandleIncomingSRejL(RMBufChain& aSRejFrame);
       
   140 
       
   141 	void RetransmitUnackedIFrames();
       
   142 
       
   143 	inline void SendOrPendL(HIFramePDU& aIFrame);
       
   144 
       
   145 	inline RL2CapRetransmissionModeTimerManager& TimerMan();
       
   146 	inline RL2CapErtmOutgoingQueue& OutgoingQ();
       
   147 private:
       
   148 	CL2CapEnhancedReTxController& iController;
       
   149 
       
   150 	// Outgoing window information, as defined by the spec.
       
   151 	// Sequencer for outgoing I-Frame numbers. With the little exception that when
       
   152 	// a decision to retransmit all unacked I-Frames is made, this gets set to the
       
   153 	// first number of the bunch and frames are retransmitted until iUnackedIFrames[iNextTxSeq]
       
   154 	// is NULL again.
       
   155 	TUint8				iNextTxSeq;
       
   156 	// I-Frames preceding this number have been acknowledged by the peer.
       
   157 	TUint8				iExpectedAckSeq;
       
   158 
       
   159 	RL2CapErtmUnacknowledgedIFrames	iUnackedIFrames;
       
   160 
       
   161 	// If remote indicates busy condition we keep transmitting within send window limits,
       
   162 	// but disable our retransmission timer.
       
   163 	TBool				iRemoteBusy;
       
   164 
       
   165 	// For protecting against duplicates. Explained in HandleIncomingSFrameL().
       
   166 	// See state tables in the spec.
       
   167 	TBool				iSRejActioned;
       
   168 	TUint8				iSRejSaveReqSeq;
       
   169 
       
   170 	// Signals to GetPdu that we need to enter WAIT_ACK.
       
   171 	TBool				iWaitAckStatePending;
       
   172 	// Xmit state WAIT_ACK (syncing ReqSeq to start retransmission from) - see spec.
       
   173 	TBool				iInWaitAckState;
       
   174 	};
       
   175 
       
   176 
       
   177 class CL2CapErtmDataReceiver;
       
   178 
       
   179 NONSHARABLE_CLASS(TL2CapErtmMissingTxSeqs)
       
   180 	{
       
   181 public:
       
   182 	TL2CapErtmMissingTxSeqs();
       
   183 
       
   184 	// Register SREJ-requested I-Frame TxSeq.
       
   185 	inline void AppendTxSeq(TUint8 aTxSeq);
       
   186 
       
   187 	// Received an SREJ requested I-Frame. Take note of this fact and indicate whether
       
   188 	// it was out of sequence wrt to previous ones. If so, GetNextTxSeqForResend() needs
       
   189 	// to be called in a loop to return all the TxSeqs to re-request.
       
   190 	TBool ReceivedTxSeq(TUint8 aTxSeq);
       
   191 	inline TBool GetNextTxSeqForResend(TUint8& aTxSeq);
       
   192 
       
   193 	TBool IsTxSeqOnTheList(TUint8 aTxSeq) const;
       
   194 	inline TUint8 LastTxSeq() const;
       
   195 	inline TBool IsEmpty() const;
       
   196 
       
   197 	inline TBool AllRequestedFramesReceived() const;
       
   198 	inline TUint8 ExpectedSRejTxSeq() const;
       
   199 	inline TInt NumMissingTxSeqs() const;
       
   200 	inline TBool HaveSpaceForNewTxSeqs(TInt aNumTxSeqs) const;
       
   201 	inline void Reset();
       
   202 private:
       
   203 #ifdef __FLOG_ACTIVE
       
   204 	void Log();
       
   205 #endif
       
   206 public:
       
   207 	const static TUint KMaxSRejsInFlight = 1;
       
   208 private:
       
   209 	TFixedArray<TUint8, KMaxSRejsInFlight>	iMissingTxSeqs;
       
   210 	// Number of TxSeqs missing since entering SREJ_SENT.
       
   211 	// The array is split in two parts - frames already received and the ones we're still
       
   212 	// waiting for.
       
   213 	TInt		iNumMissingTxSeqs;
       
   214 	// Frames below this index have been received.
       
   215 	TInt		iExpectedRecvIdx;
       
   216 	// Frames starting from this index need to be re-requested.
       
   217 	TInt		iResendIdx;
       
   218 	};
       
   219 
       
   220 
       
   221 NONSHARABLE_CLASS(TL2CapErtmReceiverStateBase)
       
   222 	{
       
   223 public:
       
   224 	// Note: think about the frame parameter as "the frame that caused the transition",
       
   225 	// though it's only really used for SREJ_SENT. Still, this is the cleanest form
       
   226 	// of passing the required information.
       
   227 	virtual void EnterL(RMBufChain* aIFrame);
       
   228 	virtual void ExitL();
       
   229 	virtual void HandleIncomingIFrameL(RMBufChain& aIFrame) = 0;
       
   230 	virtual void HandlePollL() = 0;
       
   231 	virtual TBool IsLocalBusySupported() const;
       
   232 
       
   233 	// Called to notify the state that the incoming SDU Q has just consumed some
       
   234 	// I-Frames and we could slide the receive window if we can (we can't in SREJ_SENT).
       
   235 	virtual void TxSeqExpectedBySduQChanged(TUint8 aTxSeq) = 0;
       
   236 protected:
       
   237 	TL2CapErtmReceiverStateBase(CL2CapErtmDataReceiver& aReceiver);
       
   238 protected:
       
   239 	CL2CapErtmDataReceiver& iReceiver;
       
   240 	};
       
   241 
       
   242 NONSHARABLE_CLASS(TL2CapErtmReceiverStateRecv) : public TL2CapErtmReceiverStateBase
       
   243 	{
       
   244 public:
       
   245 	TL2CapErtmReceiverStateRecv(CL2CapErtmDataReceiver& aReceiver);
       
   246 	virtual void EnterL(RMBufChain* aIFrame);
       
   247 	virtual void HandleIncomingIFrameL(RMBufChain& aIFrame);
       
   248 	virtual void HandlePollL();
       
   249 	virtual TBool IsLocalBusySupported() const;
       
   250 	virtual void TxSeqExpectedBySduQChanged(TUint8 aTxSeq);
       
   251 	};
       
   252 
       
   253 NONSHARABLE_CLASS(TL2CapErtmReceiverStateRejSent) : public TL2CapErtmReceiverStateBase
       
   254 	{
       
   255 public:
       
   256 	TL2CapErtmReceiverStateRejSent(CL2CapErtmDataReceiver& aReceiver);
       
   257 	virtual void EnterL(RMBufChain* aIFrame);
       
   258 	virtual void HandleIncomingIFrameL(RMBufChain& aIFrame);
       
   259 	virtual void HandlePollL();
       
   260 	virtual void TxSeqExpectedBySduQChanged(TUint8 aTxSeq);
       
   261 	};
       
   262 
       
   263 NONSHARABLE_CLASS(TL2CapErtmReceiverStateSRejSent) : public TL2CapErtmReceiverStateBase
       
   264 	{
       
   265 public:
       
   266 	TL2CapErtmReceiverStateSRejSent(CL2CapErtmDataReceiver& aReceiver);
       
   267 	virtual void EnterL(RMBufChain* aIFrame);
       
   268 	virtual void ExitL();
       
   269 	virtual void HandleIncomingIFrameL(RMBufChain& aIFrame);
       
   270 	virtual void HandlePollL();
       
   271 	virtual void TxSeqExpectedBySduQChanged(TUint8 aTxSeq);
       
   272 private:
       
   273 	void SendSRejsUpToReceivedIFrameL(RMBufChain& aIFrame);
       
   274 private:
       
   275 	TBool					iGoToRej;
       
   276 	TL2CapErtmMissingTxSeqs	iMissingTxSeqs;
       
   277 	};
       
   278 
       
   279 
       
   280 // Incoming I-Frame queue. Used both when the SDU Q is full and we have to buffer incoming
       
   281 // frames (a whole window is buffered) and when SREJ_SENT is entered and we wait for
       
   282 // SREJ-requested retransmissions to come through.
       
   283 NONSHARABLE_CLASS(RL2CapErtmIncomingIFrameQueue)
       
   284 	{
       
   285 public:
       
   286 	RL2CapErtmIncomingIFrameQueue();
       
   287 	void Close();
       
   288 
       
   289 	// Enqueue the new I-Frame and try to consume as much of the existing ones as possible.
       
   290 	void HandleIncomingIFrameL(RMBufChain& aIFrame, const CL2CapErtmDataReceiver& aReceiver);
       
   291 	// Pass as many consequent I-Frames to SDU Q ("consume them") as possible.
       
   292 	void ConsumeUpToFirstGapL(const CL2CapErtmDataReceiver& aReceiver);
       
   293 	inline void DeleteAllFrames();
       
   294 
       
   295 	inline TBool IsEmpty() const;
       
   296 	inline TUint8 TxSeqExpectedBySduQ() const;
       
   297 private:
       
   298 	void Insert(RMBufChain& aIFrame);
       
   299 #ifdef _DEBUG
       
   300 	void LogQ();
       
   301 #endif
       
   302 private:
       
   303 	RMBufPktQ		iQueue;
       
   304 	// Next TxSeq in sequence for SDU Q.
       
   305 	// If we're not in SREJ_SENT, it's = BufferSeq.
       
   306 	// If we're in SREJ_SENT, it's >= BufferSeq.
       
   307 	TUint8			iTxSeqExpectedBySduQ;
       
   308 	};
       
   309 
       
   310 NONSHARABLE_CLASS(CL2CapErtmDataReceiver)
       
   311 	{
       
   312 public:
       
   313 	static CL2CapErtmDataReceiver* NewL(CL2CapEnhancedReTxController& aController);
       
   314 	virtual ~CL2CapErtmDataReceiver();
       
   315 
       
   316 	void HandleIncomingIFrameL(RMBufChain& aIFrame);
       
   317 	void HandleIncomingSFrameL(RMBufChain& aSFrame);
       
   318 
       
   319 	// Recv window management.
       
   320 	void SendPeerAckTimerExpiredL();
       
   321 	TBool IsEndOfReceiveWindowApproaching() const;
       
   322 	template<typename FrameType>
       
   323 	void StampWithReqSeq(FrameType& aFrame);
       
   324 
       
   325 	// Send SREJ or REJ ?
       
   326 	TBool IsSRejPreferredToRej(TUint8 aExpectedTxSeq, TUint8 aReceivedTxSeq);
       
   327 
       
   328 	// Incoming SDU Q status/LocalBusy.
       
   329 	void SetIncomingSduQFullL(TBool aIncomingSduQFull);
       
   330 	void UpdateLocalBusyStatusL();
       
   331 	inline TBool IsIncomingSduQFull() const;
       
   332 	inline TBool LocalBusy() const;
       
   333 	void LocalBusyDelayTimerExpired();
       
   334 
       
   335 	inline void FlushBufferedIncomingIFrames();
       
   336 
       
   337 	inline TBool IsWaitFStatePending() const;
       
   338 	inline void EnterWaitFState();
       
   339 	inline TBool InWaitFState() const;
       
   340 
       
   341 	// Window state accessors, both for state objects and the controller.
       
   342 	inline TUint8 ExpectedTxSeq() const;
       
   343 	inline void SetExpectedTxSeq(TUint8 aTxSeq);
       
   344 	inline void IncExpectedTxSeq();
       
   345 
       
   346 	inline TUint8 BufferSeq() const;
       
   347 	inline void SetBufferSeq(TUint8 aTxSeq);
       
   348 
       
   349 	inline TUint8 LastAckReqSeq() const;
       
   350 
       
   351 	inline TUint8 TxSeqExpectedBySduQ() const;
       
   352 
       
   353 	inline TBool SendAck() const;
       
   354 
       
   355 	// As defined in the spec.
       
   356 	inline TBool IsTxSeqUnexpected(TUint8 aTxSeq);
       
   357 	inline TBool IsTxSeqInvalid(TUint8 aTxSeq);
       
   358 
       
   359 	// Handy helpers.
       
   360 	HSFramePDU* GetAckFrameL(TBool aFinal = EFalse);
       
   361 	inline void PassToIncomingQL(RMBufChain& aIFrame);
       
   362 	inline void PassToSduQL(RMBufChain& aIFrame) const;
       
   363 
       
   364 	inline void SetStateRecvL();
       
   365 	inline void SetStateRejSentL();
       
   366 	inline void SetStateSRejSentL(RMBufChain& aUnexpectedIFrame);
       
   367 
       
   368 	inline RL2CapErtmTimerManager& TimerMan();
       
   369 	inline RL2CapErtmOutgoingQueue& OutgoingQ();
       
   370 	inline CL2CapEnhancedReTxController& Controller() const;
       
   371 
       
   372 private:
       
   373 	CL2CapErtmDataReceiver(CL2CapEnhancedReTxController& aController);
       
   374 	void ConstructL();
       
   375 
       
   376 	void SetStateL(TL2CapErtmReceiverStateBase& aState, RMBufChain* aIFrame);
       
   377 
       
   378 	void HandleFinalAckL();
       
   379 
       
   380 	void EnterLocalBusyL();
       
   381 	void ExitLocalBusy();
       
   382 
       
   383 private:
       
   384 	// This value represents the number of frames the peer can still send within its current TxWin
       
   385 	// when we decide to send an acknowledgement. E.g. if the peer TxWindow is 20 then we'll send
       
   386 	// an acknowledgement after receiving the 18th frame, thus moving the peer's window and ready
       
   387 	// to receive next 18 frames before sending the next ack. Sending the ack before the end
       
   388 	// of the receive window is reached prevents transmission delays caused by the peer waiting
       
   389 	// for an ack before it can send more.
       
   390 	const static TUint8 KReceiveWinFreeSpaceLeftToTriggerAck = 2;
       
   391 	// Used to decide whether to send an SREJ or a REJ. An SREJ will never be sent if the gap
       
   392 	// between ExpectedTxSeq and the received frame's TxSeq is wider than this value.
       
   393 	const static TUint8 KSRejMissingFrameThreshold	= 1;
       
   394 
       
   395 	__ASSERT_COMPILE(KSRejMissingFrameThreshold <= TL2CapErtmMissingTxSeqs::KMaxSRejsInFlight);
       
   396 
       
   397 private:
       
   398 	CL2CapEnhancedReTxController& iController;
       
   399 
       
   400 	// Window variables as defined in the spec.
       
   401 	// Next expected I-Frame num.
       
   402 	TUint8		iExpectedTxSeq;
       
   403 	// Ack num (ReqSeq) that can be sent to the peer. Usually equal to ExpectedTxSeq,
       
   404 	// unless SDU Queue is full or we're in SREJ_SENT. IOW the beginning of our receive window.
       
   405 	TUint8		iBufferSeq;
       
   406 	// Stores the acknowledgment number most recently sent to the peer.
       
   407 	// Used to detect that we're reaching the end of peer's send window and hence should
       
   408 	// send an ack.
       
   409 	TUint8		iLastAckReqSeq;
       
   410 
       
   411 	// This means SDU queue won't accept any more data, so we can't acknowledge anything new.
       
   412 	// Whether LocalBusy can be entered depends on the receive state (RECV only) and other nasty
       
   413 	// details.
       
   414 	TBool		iIncomingSduQFull;
       
   415 	// This means we're sending out RNRs instead of RRs. Proper LocalBusy.
       
   416 	TBool		iLocalBusy;
       
   417 	// Xmit state WAIT_F (exiting Local Busy) - see spec.
       
   418 	TBool		iInWaitFState;
       
   419 	// Signals to GetPdu that we need to enter WAIT_F.
       
   420 	TBool		iWaitFStatePending;
       
   421 
       
   422 	// This is set to True when we're approaching the end of receive window or the send peer ack
       
   423 	// timer expires, or sending a generic ack is needed for some other reason.
       
   424 	// While flags are bad bad bad in general because they don't store time-ordering information
       
   425 	// of related events (that's why we have the outgoing Q instead), it is fine this case -
       
   426 	// - it's legitimate to send a vanilla ack at any time. It's an optimization that prevents
       
   427 	// multiple acks to be queued when the outgoing pipe gets clogged for a while but we keep
       
   428 	// receiving incoming I-Frames.
       
   429 	TBool		iSendAck;
       
   430 	
       
   431 	RL2CapErtmIncomingIFrameQueue	iIncomingIFrameQ;
       
   432 	
       
   433 	// "Heavyweight" State pattern.
       
   434 	TL2CapErtmReceiverStateBase*	iReceiveState;
       
   435 
       
   436 	TL2CapErtmReceiverStateRecv		iStateRecv;
       
   437 	TL2CapErtmReceiverStateRejSent	iStateRejSent;
       
   438 	TL2CapErtmReceiverStateSRejSent	iStateSRejSent;
       
   439 	};
       
   440 
       
   441 // This encapsulates the managament of the outgoing packet queue.
       
   442 // Every packet should go through the queue before it's sent - certain actions need to be
       
   443 // executed when a packet is enqueued/dequeued and to make sure that it's always done
       
   444 // the queue is hidden in this class.
       
   445 NONSHARABLE_CLASS(RL2CapErtmOutgoingQueue)
       
   446 	{
       
   447 public:
       
   448 	RL2CapErtmOutgoingQueue(CL2CapEnhancedReTxController& aController);
       
   449 	void Close();
       
   450 
       
   451 	// These queue frames that can be sent immediately.
       
   452 	void QueueIFrameL(HIFramePDU& aIFrame);
       
   453 	void QueueAckingSFrame(HSFramePDU& aSFrame);
       
   454 	void QueueNonAckingSFrame(HSFramePDU& aSFrame, TUint8 aReqSeq);
       
   455 
       
   456 	// This queues the I-Frame onto a separate list pending clearing of WAIT_ACK.
       
   457 	// It's used for I-Frames requested with SREJs coming through in WAIT_ACK.
       
   458 	void PendRetransmitIFrameL(HIFramePDU& aIFrame);
       
   459 
       
   460 	// This requeues the I-Frames from the pending list onto the normal send queue.
       
   461 	void SendPendingRetransmitIFramesL();
       
   462 	// Used when we decide to retransmit all I-Frames when we still haven't sent
       
   463 	// out the SREJ-requested ones.
       
   464 	void CancelPendingRetransmitIFrames();
       
   465 
       
   466 	void DeleteAllFrames();
       
   467 
       
   468 	// Called by controller's GetPdu when the link muxer asks for a frame to send.
       
   469 	HL2CapPDU* DequeueNextToSend();
       
   470 
       
   471 	inline TBool HaveFramesToTransmit() const;
       
   472 	inline TBool HavePendingRetransmitIFrames() const;
       
   473 private:
       
   474 	CL2CapEnhancedReTxController& iController;
       
   475 	TSglQue<HL2CapPDU>		iOutgoingQ;
       
   476 	// I-Frames SREJ-requested by the remote when we're in WAIT_ACK and thus can't send data.
       
   477 	TSglQue<HIFramePDU>		iPendRetransmitIFrameQ;
       
   478 	};
       
   479 
       
   480 NONSHARABLE_CLASS(CL2CapEnhancedReTxController)
       
   481 	: public CL2CapBasicDataController, public MPduOwner, public MRetransmissionModeTimerClient
       
   482 	{
       
   483 public:
       
   484 	static CL2CapEnhancedReTxController* NewL(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, CL2CapSDUQueue& aSDUQueue, TL2CapDataControllerConfig* aConfig);
       
   485 	virtual ~CL2CapEnhancedReTxController();
       
   486 
       
   487 	// MPduOwner
       
   488 	// Called back by I-Frames on HCI completion.
       
   489 	virtual void HandlePduSendComplete(HL2CapPDU& aPdu);
       
   490 	virtual void HandlePduSendError(HL2CapPDU& aPdu);
       
   491 
       
   492 	// Called back by PDUs going out through the HL2CapPDU::DeliverOutgoingPDU
       
   493 	// double-dispatch trickery, in the context of GetPduL.
       
   494 	virtual TInt HandleOutgoingIFrame(HIFramePDU* aIFrame);
       
   495 	virtual TInt HandleOutgoingSFrame(HSFramePDU* aSFrame);
       
   496 
       
   497 	// Called by the SDU Q when it gets full/space frees up.
       
   498 	virtual void SetIncomingSduQFull(TBool aIncomingSduQFull);
       
   499 
       
   500 	// Called by the SDU Q when the connection is being shutdown by the application
       
   501 	// and data needs to be delivered reliably before we disconnect.
       
   502 	virtual TBool DeliverOutgoingDataAndSignalToSduQWhenDone();
       
   503 	inline TBool IsOutgoingDataPathClosing();
       
   504 	// The data transmitter calls this when it wants to notify the SDU Q that it has
       
   505 	// delivered all outgoing data and so we can now be destroyed.
       
   506 	inline void SignalOutgoingDataDeliveredToSduQ();
       
   507 
       
   508 	// Incoming Q calls this to pass an I-Frame to the SDU Q.
       
   509 	inline void PassToSduQL(RMBufChain& aIFrame);
       
   510 
       
   511 	// Called from SDU Q when it's got new PDUs to send.
       
   512 	virtual void OutgoingPduAvailableOnSduQ();
       
   513 
       
   514     // Called to evaluate whether we want to send anything.
       
   515 	inline void NotifyMuxerOfPdusToSendIfHaveSome();
       
   516 
       
   517 	// Puts the current acknowledgement number into the frame being queued for send.
       
   518 	// Templated to handle both I-Frames and S-Frames.
       
   519 	template<typename FrameType>
       
   520 	inline void StampWithReqSeq(FrameType& aFrame);
       
   521 
       
   522 	// A helper for when a ReqSeq/Final ack needs to be sent - tries to piggy-back on I-Frames.
       
   523 	void SendIOrRrOrRnrL(TBool aFinal);
       
   524 
       
   525 	virtual void LocalBusyDelayTimerExpired();
       
   526  
       
   527 	inline TBool IsPollOutstanding() const;
       
   528 	inline TBool IsFBitValid(TBool aFinal);
       
   529 
       
   530 	inline RL2CapErtmOutgoingQueue& OutgoingQ();
       
   531 	inline RL2CapErtmTimerManager& TimerMan();
       
   532 
       
   533 protected:
       
   534 	CL2CapEnhancedReTxController(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, CL2CapSDUQueue& aSDUQueue, TL2CapDataControllerConfig* aConfig);
       
   535 	void ConstructL();
       
   536 
       
   537 	// These are the entry points for incoming PDUs, called and trapped by a dispatch routine
       
   538 	// in CL2CapBasicDataController.
       
   539 	virtual void HandleIncomingIFrameL(RMBufChain& aIFrame);
       
   540 	virtual void HandleIncomingSFrameL(RMBufChain& aSFrame);
       
   541 
       
   542 	// Provide a PDU for transmission. Called and trapped by GetPdu in CL2CapBasicDataController.
       
   543 	virtual HL2CapPDU* GetPduL();
       
   544 
       
   545 	void HandleFinalAck();
       
   546 
       
   547 	// From MErtmModeTimerClient
       
   548 	virtual void MonitorTimerExpired();
       
   549 	virtual void AckTimerExpired();
       
   550 	virtual void SendPeerAckTimerExpired();
       
   551 	virtual TUint16 MonitorTimeout();
       
   552 	virtual TUint16 RetransmissionTimeout();
       
   553 	virtual TUint16 PeerRetransmissionTimeout();
       
   554 private:
       
   555 	TUint8						iPollSFrameTransmitCount;
       
   556 	TBool						iDeliverOutgoingDataAndSignalToSduQWhenDone;
       
   557 
       
   558 	RL2CapErtmOutgoingQueue		iOutgoingQ;
       
   559 	RL2CapErtmTimerManager		iTimerMan;
       
   560 	CL2CapErtmDataReceiver*		iReceiver;
       
   561 	CL2CapErtmDataTransmitter*	iTransmitter;
       
   562 	};
       
   563 
       
   564 #include "L2CapEnhancedDataController.inl"
       
   565 
       
   566 #endif /*L2CAPENHANCEDDATACONTROLLER_H*/