bluetooth/btstack/l2cap/L2CapSDUQueue.cpp
changeset 51 20ac952a623c
parent 0 29b1cd4cb562
--- a/bluetooth/btstack/l2cap/L2CapSDUQueue.cpp	Thu Sep 23 17:06:47 2010 +0300
+++ b/bluetooth/btstack/l2cap/L2CapSDUQueue.cpp	Wed Oct 13 16:20:29 2010 +0300
@@ -39,12 +39,13 @@
 	                                  TUint16 aFlushTimeout, 
 		                              TUint16 aMaxOutgoingMTU,
                                		  TUint16 aMaxIncomingMTU,
+                               		  TUint16 aAclBufSize,
                                		  TBool aCanDropSdus)
 	{
 	LOG_STATIC_FUNC
 	CL2CapSDUQueue* self = new(ELeave) CL2CapSDUQueue(aL2CapSap, aOutboundQueueSize, aPDUSize, aFlushTimeout, aMaxOutgoingMTU, aMaxIncomingMTU, aCanDropSdus);
 	CleanupStack::PushL(self);
-	self->ConstructL(aLocalCID, aRemoteCID, aMuxer, aConfig);
+	self->ConstructL(aLocalCID, aRemoteCID, aMuxer, aConfig, aAclBufSize);
 	return self;
 	}
 		                                  
@@ -58,15 +59,17 @@
 	                                 TUint16 aFlushTimeout, 
 		                             TUint16 aMaxOutgoingMTU,
                                		 TUint16 aMaxIncomingMTU,
+                               		 TUint16 aAclBufSize,
                                		 TBool aCanDropSdus)
 	{
 	LOG_STATIC_FUNC
-	CL2CapSDUQueue* self = NewLC(aL2CapSap, aLocalCID, aRemoteCID, aMuxer, aPDUSize, aOutboundQueueSize, aConfig, aFlushTimeout, aMaxOutgoingMTU, aMaxIncomingMTU, aCanDropSdus);
+	CL2CapSDUQueue* self = NewLC(aL2CapSap, aLocalCID, aRemoteCID, aMuxer, aPDUSize, aOutboundQueueSize, aConfig, aFlushTimeout,
+								 aMaxOutgoingMTU, aMaxIncomingMTU, aAclBufSize, aCanDropSdus);
 	CleanupStack::Pop();
 	return self;
 	}	                                 
  
-void CL2CapSDUQueue::ConstructL(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, TL2CapDataControllerConfig* aConfig)
+void CL2CapSDUQueue::ConstructL(TL2CAPPort aLocalCID, TL2CAPPort aRemoteCID, CL2CAPMux& aMuxer, TL2CapDataControllerConfig* aConfig, TUint16 aAclBufSize)
 	{
 	LOG_FUNC
 	iDataController = CL2CapBasicDataController::NewL(aLocalCID, aRemoteCID, aMuxer, *this, aConfig);
@@ -77,6 +80,8 @@
 	iSDUSentAsyncCallBack = new (ELeave)CAsyncCallBack(sdusSentCB, EActiveLowPriority);
 	TCallBack qClosingCB(QueueClosingAsyncCallBack, this);
 	iQueueClosingCallBack = new (ELeave)CAsyncCallBack(qClosingCB, EActiveHighPriority);
+
+	iCurrentPDUSize = HL2CapPDU::GetPDUOrFragmentSize(iMaxOutgoingMTU, iMaximumPDUSize, aAclBufSize, iDataController->IsBasicDataVersion());
 	}
 	
 
@@ -665,7 +670,8 @@
                     				TUint16 aFlushTimeout,
                     				TUint16 aPDUSize,
                     				TUint16 aMaxOutgoingMTU,
-                    				TUint16 aMaxIncomingMTU)
+                    				TUint16 aMaxIncomingMTU,
+                    				TUint16 aAclBufSize)
 	{
 	LOG_FUNC
 	// Update the data controller.
@@ -709,7 +715,7 @@
 		}
 	if (err == KErrNone)
 		{
-		iCurrentPDUSize = iNegotiatedPDUSize;
+		iCurrentPDUSize = HL2CapPDU::GetPDUOrFragmentSize(iMaxOutgoingMTU, iMaximumPDUSize, aAclBufSize, iDataController->IsBasicDataVersion());
 	
 		// Allow the outbound queue to send again, and tell the data
 		// plane if SDU's are available.
@@ -737,17 +743,56 @@
 		}
 	}
 
-TBool CL2CapSDUQueue::IsBasicDataVersion() const
+TUint CL2CapSDUQueue::GetOptimalMTUSizeL(TUint aMtuRestriction, TUint16 aAclBufSize)
 	{
 	LOG_FUNC
-	TBool rValue = EFalse;
-	if (iDataController)
+
+	if (!iDataController)
+		{
+		// Can happen if we're being shut down quickly due to an error and the upper layer
+		// still hasn't reacted to that.
+		LEAVEL(KErrNotReady);
+		}
+
+	// Ensure that the restriction is less then the current MTU.
+	if (aMtuRestriction < iMaxOutgoingMTU)
+		{
+		// We now need to recalculate the optimal PDU size for the restricted MTU as
+		// this is used in the calculation of the optimal MTU
+
+		iCurrentPDUSize = HL2CapPDU::GetPDUOrFragmentSize(aMtuRestriction, iMaximumPDUSize,
+                                                          aAclBufSize, iDataController->IsBasicDataVersion());
+		}
+	else
 		{
-		rValue = iDataController->IsBasicDataVersion();
+		// can't increase the MTU at this stage so just use the existing MTU
+		aMtuRestriction = iMaxOutgoingMTU;
 		}
-	return rValue;
+
+	// If the negotiated MTU minus any overhead will fit into the optimal PDU then that
+	// is the optimal MTU. The overhead will differ for basic and non-basic mode, for basic mode
+	// we have to consider the SDU overhead as there is no fragment overhead and for non-basic we 
+	// consider the PDU overhead only (the additional SDU overhead is taken account of later if 
+	// more than one PDU is required for the optimal MTU).
+	TUint optimalMTU = aMtuRestriction;
+
+	// Calculate the size of the MTU + any overhead assuming that the MTU is not segmented
+	TUint singlePduSize = iDataController->IsBasicDataVersion() ?
+						  (aMtuRestriction + CL2CapSDU::GetSDUOverhead(iDataController->IsBasicDataVersion())) : aMtuRestriction;
+
+	// If the unsegmented MTU + overhead can fit into the optimal PDU size then no 
+	// further calculation is required
+	if(singlePduSize > iCurrentPDUSize)
+		{
+		// The MTU will need to be segmented / fragmented (depending on L2CAP mode).
+		// Calculate an MTU size that will be a factor of the PDU size.
+		optimalMTU = aMtuRestriction - ((aMtuRestriction + CL2CapSDU::GetSDUOverhead(iDataController->IsBasicDataVersion())) % iCurrentPDUSize); 
+		}
+
+	return optimalMTU;
 	}
 
+
 #ifdef _DEBUG
 TInt CL2CapSDUQueue::GetDataPlaneConfig(TL2DataPlaneConfig& conf) const
 	{