bluetooth/btstack/l2cap/L2CapDataController.h
changeset 0 29b1cd4cb562
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btstack/l2cap/L2CapDataController.h	Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,352 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#ifndef L2CAPDATACONTROLLER_H_
+#define L2CAPDATACONTROLLER_H_
+
+#include <e32std.h>
+#include <bt_sock.h>
+
+#include "L2CapPDU.h"
+#include "L2CapSDUQueue.h"
+
+namespace L2CapDataUtils
+	{
+	// Helper function used for transmit and receive sequence numbers which are 6 bits long.
+	inline TUint8 Mod64(TInt aValue);
+	// Helper function for checking whether a sequence number is within a given window.
+	// Handles both Start <= End and Start > End.
+	inline TBool InWindow(TInt aTxSeq, TInt aStart, TInt aEnd);
+	}
+
+class CL2CapSDUQueue;
+class CL2CAPMux;
+class CL2CapSDU;
+
+NONSHARABLE_CLASS(CL2CapBasicDataController) : public CBase, public MOutgoingPDUHandler
+	{
+public:
+	static CL2CapBasicDataController* NewL(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, CL2CapSDUQueue& aSDUQueue, TL2CapDataControllerConfig* aConfig);
+
+	CL2CapBasicDataController(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, CL2CapSDUQueue& aSDUQueue, TL2CapDataControllerConfig* aConfig, TBool aIsBasicDataVersion);
+	virtual ~CL2CapBasicDataController();
+	
+	virtual void ProcessFlushTimerExpiry();
+
+	void UpdateConfig(TL2CapDataControllerConfig* aConfig);
+	void UpdateChannelPriority(TUint8 aNewPriority);
+	
+	void DeregisterFromMuxer();
+
+	// These two are the main input/output interface to the data controller, lots of interesting
+	// stuff happens in their context.
+	// Input - called by the muxer when a data frame is received.
+	TBool HandleIncomingDataFrame(RMBufChain& aDataFrame);
+	// Output - called by the muxer when it wants some data to send out.
+	HL2CapPDU* GetPdu();
+
+	// Outgoing PDU handler.
+	virtual TInt HandleOutgoingIFrame(HIFramePDU* aIFrame);
+	virtual TInt HandleOutgoingBFrame(HBFramePDU* aBFrame);
+	virtual TInt HandleOutgoingGFrame(HGFramePDU* aGFrame);
+	virtual TInt HandleOutgoingCFrame(HCFramePDU* aCFrame);
+	virtual TInt HandleOutgoingSFrame(HSFramePDU* aSFrame);
+
+	virtual void OutgoingPduAvailableOnSduQ();
+
+	virtual void ErrorD(TInt aError);
+
+	virtual void SetIncomingSduQFull(TBool aIncomingSduQFull);
+
+	// Signal from the SDU Q that we need to send remaining data and call the SDU Q back
+	// when it's been sent & acknowledged by the peer. Returning True means it's already
+	// been done and we can be synchronously deleted.
+	virtual TBool DeliverOutgoingDataAndSignalToSduQWhenDone();
+
+	inline CL2CapSDUQueue& SDUQueue() const;
+	inline CL2CAPMux& Muxer() const;
+	inline TL2CAPPort LocalCID() const;
+	inline TL2CAPPort RemoteCID() const;
+	inline TL2CapDataControllerConfig& Config() const;
+
+	inline TBool IsBasicDataVersion() const;
+
+protected:
+	// Note: leaving functions need to be trapped within this class, all public
+	// functions are non-leaving.
+
+	// Dispatches incoming data frames to appropriate frame-type handlers below.
+	// Leaves are trapped by HandleIncomingDataFrame, which will close the connection.
+	TBool HandleIncomingDataFrameL(RMBufChain& aDataFrame);
+	// These need to be overridden by deriving controllers.
+	virtual void HandleIncomingIFrameL(RMBufChain& aDataFrame);
+	virtual void HandleIncomingBFrameL(RMBufChain& aDataFrame);
+	virtual void HandleIncomingSFrameL(RMBufChain& aDataFrame);
+
+	// Needs to be overridden by deriving controllers.
+	// Leaves are trapped by GetPdu, which will close the connection. 
+	virtual HL2CapPDU* GetPduL();
+
+#ifdef _DEBUG
+public:
+	TInt GetDataPlaneConfig(TL2DataPlaneConfig& conf) const;
+#endif	
+
+public:
+	TDblQueLink iLink;	
+				
+protected:
+	CL2CapSDUQueue& iSDUQueue;
+	CL2CAPMux& iMuxer;
+	TL2CAPPort iLocalCID; 
+	TL2CAPPort iRemoteCID;
+	TL2CapDataControllerConfig* iConfig;
+
+	TBool iDataPlaneErrored;
+	TBool iIsBasicDataVersion;
+	};
+
+
+NONSHARABLE_CLASS(MRetransmissionModeTimerClient)
+	{
+public:
+	virtual void MonitorTimerExpired() = 0;
+	virtual void AckTimerExpired() = 0;
+	virtual void SendPeerAckTimerExpired() = 0;
+	virtual TUint16 MonitorTimeout() = 0;
+	virtual TUint16 RetransmissionTimeout() = 0;
+	virtual TUint16 PeerRetransmissionTimeout() = 0;
+	};
+
+NONSHARABLE_CLASS(RL2CapRetransmissionModeTimerManager)
+	{
+public:
+	RL2CapRetransmissionModeTimerManager(MRetransmissionModeTimerClient& aClient);
+	void Close();
+
+	void StartMonitorTimer();
+	void StartAckTimer();
+	void StopMonitorTimer();
+	void StopAckTimer();
+
+	TBool StartSendPeerAckTimer();
+	void StopSendPeerAckTimer();
+
+	void HandleFECTimerExpired();
+	void HandleSendPeerAckTimerExpired();
+	static TInt FECTimerExpired(TAny* aTimerMan);
+	static TInt SendPeerAckTimerExpired(TAny* aTimerMan);
+
+	inline TBool IsAckTimerRunning() const;
+	inline TBool IsMonitorTimerRunning() const;
+	inline TBool IsSendPeerAckTimerRunning() const;
+
+protected:
+	MRetransmissionModeTimerClient& iClient;
+
+private:
+	void CancelFECTimer();
+
+	// Both of these values are in milliseconds.
+	const static TUint16 KAveTimeToTransmitAckToPeer 		= 800;
+	const static TUint16 KMinimumPeerAckTimeout				= 800;
+
+	enum TFECTimerState
+		{
+		EFECTimerIdle,
+		EMonitorTimerRunning,
+		EAckTimerRunning,
+		};
+
+	// Timer for outgoing data.  Used for both Monitor and RTx timers.
+	// Note that only one of them can be outstanding at any time (as per the spec).
+	TFECTimerState		iFECTimerState;
+	TDeltaTimerEntry	iFECTimerEntry;
+
+	// Timer for incoming data.  Send ack. to peer timer.
+	TBool				iSendPeerAckTimerRunning;
+	TDeltaTimerEntry	iSendPeerAckTimerEntry;
+	};
+
+
+NONSHARABLE_CLASS(CL2CapDataFlowController)
+	: public CL2CapBasicDataController, public MPduOwner, public MRetransmissionModeTimerClient
+	{
+public:
+	CL2CapDataFlowController(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, CL2CapSDUQueue& aSDUQueue, TL2CapDataControllerConfig* aConfig);
+	virtual ~CL2CapDataFlowController();
+	
+	virtual void ProcessFlushTimerExpiry();
+
+	// MPduOwner
+	virtual void HandlePduSendComplete(HL2CapPDU& aPdu);
+	virtual void HandlePduSendError(HL2CapPDU& aPdu);
+
+	virtual HL2CapPDU* GetPduL();
+
+	virtual TInt HandleOutgoingIFrame(HIFramePDU* aIFrame);
+	virtual TInt HandleOutgoingSFrame(HSFramePDU* aSFrame);
+
+	virtual void SetIncomingSduQFull(TBool aIncomingSduQFull);
+
+protected:
+	virtual void HandleIncomingIFrameL(RMBufChain& aDataFrame);
+	virtual void HandleIncomingSFrameL(RMBufChain& aDataFrame);
+
+	virtual void PDUAvailable();
+	TBool CanSendPDU();
+	virtual void RemoveAckedPDUsFromSentQueue();
+	void ProcessIFrameL(RMBufChain& aDataFrame);
+
+	// MRetransmissionModeTimerClient
+	virtual void MonitorTimerExpired();
+	virtual void AckTimerExpired();
+	virtual void SendPeerAckTimerExpired();
+	virtual TUint16 MonitorTimeout();
+	virtual TUint16 RetransmissionTimeout();
+	virtual TUint16 PeerRetransmissionTimeout();
+
+protected:
+	// This value represents the number of frames the peer can still send prior 
+	// to the local device sending an ack.  ie, if the peer TxWindow is 20 then
+	// (20 - KTxWinAckThresholdOffset) frames can be received before an ack is 
+	// sent.  NB.  This does not affect the operation of the SendPeerAckTimer.
+	const static TUint8 KTxWinAckThresholdOffset 			= 3;
+
+	// Window related information, as defined in the spec (chapter "Variables and sequence numbers").
+	TUint8 iNextTxSeq;
+	TUint8 iExpectedAckSeq;
+	
+	TUint8 iExpectedTxSeq;
+	// Stores the acknowledgment number most recently sent to the peer.
+	// Used to detect that we're reaching the end of peer's send window and hence should
+	// send an ack.
+	TUint8 iLastAckSentRxSeqNum;
+
+	// PDUs being sent, not yet completed by HCI.
+	TDblQue<HIFramePDU> iPendingSentPDUs;
+	// Completed by HCI and awaiting acknowledgement.
+	TDblQue<HIFramePDU> iSentPDUs;
+	
+	RL2CapRetransmissionModeTimerManager iTimerMan;
+
+	TBool iIncomingSduQFull;
+	
+	TBool iSendAckToPeer;
+	TBool iSenderTxWindowClosed;
+	};
+
+NONSHARABLE_CLASS(CL2CapDataReTxController) : public CL2CapDataFlowController
+	{
+public:
+	CL2CapDataReTxController(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, CL2CapSDUQueue& aSDUQueue, TL2CapDataControllerConfig* aConfig);
+
+	// MPduOwner
+	virtual void HandlePduSendComplete(HL2CapPDU& aPdu);
+
+	virtual TInt HandleOutgoingIFrame(HIFramePDU* aIFrame);
+
+	virtual TBool DeliverOutgoingDataAndSignalToSduQWhenDone();
+
+protected:
+	virtual void HandleIncomingIFrameL(RMBufChain& aDataFrame);
+	virtual void HandleIncomingSFrameL(RMBufChain& aDataFrame);
+
+	virtual void PDUAvailable();
+
+	virtual HL2CapPDU* GetPduL();
+
+	virtual void RemoveAckedPDUsFromSentQueue();
+
+	virtual void AckTimerExpired();
+private:
+	HL2CapPDU* RetransmitSentPDU();
+
+private:
+	HSFramePDU* iRejectPDU;
+	TBool iRetransmitSentPDUs;
+	TBool iRejectSent;
+	TBool iRetransmissionDisabled;
+	TBool iRestartAckTimer;
+	TInt iRetransTxVal;		// This variable is used to store the Tx Seq number of the next PDU to be retransmitted.  This keeps this value separate from the one used for new I-Frames.
+	TBool iDeliverOutgoingDataAndSignalToSduQWhenDone;
+	};
+
+
+inline TUint8 L2CapDataUtils::Mod64(TInt aValue)
+	{
+	return static_cast<TUint8>(aValue & 0x3f);
+	}
+
+inline TBool L2CapDataUtils::InWindow(TInt aTxSeq, TInt aStart, TInt aEnd)
+	{
+	if (aStart <= aEnd)
+		{
+		return aStart <= aTxSeq && aTxSeq <= aEnd;
+		}
+	else
+		{
+		return aStart <= aTxSeq || aTxSeq <= aEnd;
+		}
+	}
+
+
+inline CL2CapSDUQueue& CL2CapBasicDataController::SDUQueue() const
+	{
+	return iSDUQueue;
+	}
+	
+inline CL2CAPMux& CL2CapBasicDataController::Muxer() const
+	{
+	return iMuxer;
+	}
+	
+inline TL2CAPPort CL2CapBasicDataController::LocalCID() const
+	{
+	return iLocalCID;
+	}
+	
+inline TL2CAPPort CL2CapBasicDataController::RemoteCID() const
+	{
+	return iRemoteCID;
+	}
+
+inline TL2CapDataControllerConfig& CL2CapBasicDataController::Config() const
+	{
+	return *iConfig;
+	}
+
+inline TBool CL2CapBasicDataController::IsBasicDataVersion() const
+	{
+	return iIsBasicDataVersion;
+	}
+
+
+inline TBool RL2CapRetransmissionModeTimerManager::IsAckTimerRunning() const
+	{
+	return iFECTimerState == EAckTimerRunning;
+	}
+
+inline TBool RL2CapRetransmissionModeTimerManager::IsMonitorTimerRunning() const
+	{
+	return iFECTimerState == EMonitorTimerRunning;
+	}
+
+inline TBool RL2CapRetransmissionModeTimerManager::IsSendPeerAckTimerRunning() const
+	{
+	return iSendPeerAckTimerRunning;
+	}
+
+#endif