diff -r 000000000000 -r 29b1cd4cb562 bluetooth/btstack/l2cap/L2CapSDUQueue.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btstack/l2cap/L2CapSDUQueue.h Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,254 @@ +// 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 L2CAPSDUQUEUE_H_ +#define L2CAPSDUQUEUE_H_ + +#include + +#include "L2CapSDU.h" + + +class TL2CapDataControllerConfig; +class CL2CapBasicDataController; +class CL2CAPMux; +class CL2CAPConnectionSAP; + +NONSHARABLE_CLASS(CL2CapSDUQueue) : public CBase, + public ML2CapSDUHandler + { +public: + // Can buffer this many outgoing SDUs. + const static TUint8 KDefaultOutboundQueueSize = 2; + + // Can buffer this many incoming SDUs. That's after reassembly, doesn't + // include I-Frames that a data controller can buffer on its own. + // Note: leaving this at 5 until the problem with legacy data controllers putting + // frames on the Q even when they've been told not to is fixed - then should probably + // decrease to 2. + const static TUint8 KInboundQueueFlowCtrlThreshold = 5; + + // During normal shutdown initiated by our upper layer we try to deliver + // all outstanding data, but kill it brutally if this time is exceeded. + const static TUint8 KOutgoingQueueClosingTimer = 60; + + enum TIncomingSDUQueueCloseAction + { + EDrainIncomingQueue, + EImmediatelyCloseIncomingQueue, + }; + + enum TOutgoingSDUQueueCloseAction + { + EDrainOutgoingQueue, + EImmediatelyCloseOutgoingQueue, + }; + + static CL2CapSDUQueue* NewLC(CL2CAPConnectionSAP& aL2CapSap, + TL2CAPPort aLocalCID, + TL2CAPPort aRemoteCID, + CL2CAPMux& aMuxer, + TUint16 aPDUSize, + TUint8 aOutboundQueueSize, + TL2CapDataControllerConfig* aConfig, + TUint16 aFlushTimeout, + TUint16 aMaxOutgoingMTU, + TUint16 aMaxIncomingMTU, + TBool aCanDropSdus); + static CL2CapSDUQueue* NewL(CL2CAPConnectionSAP& aL2CapSap, + TL2CAPPort aLocalCID, + TL2CAPPort aRemoteCID, + CL2CAPMux& aMuxer, + TUint16 aPDUSize, + TUint8 aOutboundQueueSize, + TL2CapDataControllerConfig* aConfig, + TUint16 aFlushTimeout, + TUint16 aMaxOutgoingMTU, + TUint16 aMaxIncomingMTU, + TBool aCanDropSdus); + + ~CL2CapSDUQueue(); + + static TInt CanSendAsyncCallBack(TAny *aSDUQueue); + static TInt SDUsSentAsyncCallBack(TAny *aSDUQueue); + static TInt QueueClosingAsyncCallBack(TAny *aSDUQueue); + + static TInt OutgoingQueueClosingTimerExpired(TAny *aSDUQueue); + + void ProcessFlushTimerExpiry(CL2CapSDU& aL2CapSDU); + + HL2CapPDU* GetPDU(); + inline TBool HavePDUToSend() const; + + TInt PutIFramePDU(RMBufChain& dataFrame); + void PutBFramePDU(RMBufChain& dataFrame); + + void FlushCurrentlyAssembledSdu(); + void FlushOldestIncomingSdu(); + inline TBool IsIncomingQueueFull() const; + + + TInt Write(RMBufChain& aSDUData); + void Read(RMBufChain& readData); + + void CloseSDUQueue(TIncomingSDUQueueCloseAction aIncomingQueueAction = EImmediatelyCloseIncomingQueue, + TOutgoingSDUQueueCloseAction aOutgoingQueueAction = EImmediatelyCloseOutgoingQueue); + + void DataControllerDeliveredOutgoingData(); + + inline void SuspendSDUQueue(); + void ResumeSDUQueue(TL2CapDataControllerConfig* aConfig, + TUint16 aFlushTimeout, + TUint16 aPDUSize, + TUint16 aMaxOutgoingMTU, + TUint16 aMaxIncomingMTU); + void UpdateChannelPriority(TUint8 aNewPriority); + void ErrorD(TInt aErrorCode); + +#ifdef _DEBUG + TInt GetDataPlaneConfig(TL2DataPlaneConfig& conf) const; + void PretendIncomingSduQFull(TBool aIncomingSduQFull); +#endif + + inline TUint16 MaxOutgoingMTU() const; + inline TUint16 MaxIncomingMTU() const; + + inline TUint16 MaximumPDUSize() const; + inline TUint16 OptimalPDUSize() const; + inline void SetOptimalPDUSize(TUint16 aPDUSize); + + TBool IsBasicDataVersion() const; + +private: + void ConstructL(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, TL2CapDataControllerConfig* aConfig); + + CL2CapSDUQueue(CL2CAPConnectionSAP& aL2CapSap, + TUint8 aOutboundQueueSize, + TUint16 aPDUSize, + TUint16 aFlushTimeout, + TUint16 aMaxOutgoingMTU, + TUint16 aMaxIncomingMTU, + TBool aCanDropSdus); + + + void SDURemovedFromOutboundQueue(); + void CanSend(); + void SDUsSent(); + + TInt HandleIncompleteSDU(RMBufChain& aIncompleteSDU); + + void TryToCloseQueue(); + void SDUQueueClosed(); + + void StartOutgoingQueueClosingTimer(); + void CancelOutgoingQueueClosingTimer(); + void HandleOutgoingQueueClosingTimerExpired(); + +private: + CL2CAPConnectionSAP& iL2CapSap; + TUint8 iOutboundQueueSize; + + CL2CapBasicDataController* iDataController; + + TDblQue iOutgoingSDUs; + TDblQue iOutgoingPulledSDUs; + + RMBufPktQ iIncomingSDUs; + RMBufChain iCurrentIncomingSDU; + TUint16 iCurrentIncomingSDULength; + + TUint16 iFlushTimeout; + TUint16 iCurrentPDUSize; + TUint16 iMaximumPDUSize; + TUint16 iNegotiatedPDUSize; + + TUint8 iCurrentOutboundQueueLength; + TUint16 iCurrentInboundQueueLength; + TBool iOutboundSendingBlocked; + TBool iOutboundQueueSuspended; + + CAsyncCallBack* iCanSendAsyncCallBack; + CAsyncCallBack* iSDUSentAsyncCallBack; + CAsyncCallBack* iQueueClosingCallBack; + + TBool iSDUQueuesClosing; + TBool iIncomingQueueClosed; + TBool iOutgoingQueueClosed; + + TDeltaTimerEntry iOutgoingQueueClosingTimer; + TBool iOutgoingQueueClosingTimerRunning; + + TUint16 iMaxOutgoingMTU; + TUint16 iMaxIncomingMTU; + + TBool iCanDropSdus; + }; + + +inline TBool CL2CapSDUQueue::IsIncomingQueueFull() const + { + return iCurrentInboundQueueLength >= KInboundQueueFlowCtrlThreshold; + } + +inline TUint16 CL2CapSDUQueue::MaxOutgoingMTU() const + { + return iMaxOutgoingMTU; + } + +inline TUint16 CL2CapSDUQueue::MaxIncomingMTU() const + { + return iMaxIncomingMTU; + } + +inline TUint16 CL2CapSDUQueue::MaximumPDUSize() const + { + return iMaximumPDUSize; + } + +inline TUint16 CL2CapSDUQueue::OptimalPDUSize() const + { + return iCurrentPDUSize; + } + +inline void CL2CapSDUQueue::SetOptimalPDUSize(TUint16 aPDUSize) + { + iCurrentPDUSize = aPDUSize; + } + +inline void CL2CapSDUQueue::SuspendSDUQueue() + { + iOutboundQueueSuspended = ETrue; + } + +inline TBool CL2CapSDUQueue::HavePDUToSend() const + { + TBool havePDU = EFalse; + if(!iOutgoingSDUs.IsEmpty()) + { + CL2CapSDU* sdu = iOutgoingSDUs.First(); + // If the outbound queue is suspended, and this is the start + // of a new SDU. Then don't send a PDU. + if(!(iOutboundQueueSuspended && sdu->CurrentPDUIsFirstPDU())) + { + if (!sdu->IsSDUEmpty()) + { + havePDU = ETrue; + } + } + } + return havePDU; + } + +#endif