diff -r 000000000000 -r 29b1cd4cb562 bluetooth/btstack/l2cap/L2CapDataController.h --- /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 +#include + +#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 iPendingSentPDUs; + // Completed by HCI and awaiting acknowledgement. + TDblQue 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(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