diff -r 22de2e391156 -r 20ac952a623c bluetooth/btstack/l2cap/L2CapSDUQueue.cpp --- 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 {