--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btstack/l2cap/L2CapFecNegotiator.inl Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,389 @@
+// Copyright (c) 2006-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:
+//
+
+
+
+/**
+ @file
+ @internalComponent
+*/
+
+#ifndef L2CAPFECNEGOTIATOR_INL
+#define L2CAPFECNEGOTIATOR_INL
+
+// Not needed, but keeps Carbide's semantic analyzer a bit happier.
+#include "L2CapFecNegotiator.h"
+
+//
+// TFecOptionHandlerDelegator inlines
+//
+inline TBool TFecOptionHandlerDelegator::IsOptionValid(const TRetransmissionAndFlowControlOption& aFecOption) const
+ {
+ const TModeSpecificFecOptionHandlerBase* handler = ModeToHandler(aFecOption.LinkMode());
+ // handler == NULL means invalid mode field
+ return handler && handler->IsOptionValid(aFecOption);
+ }
+
+inline TBool TFecOptionHandlerDelegator::IsPeerResponseAcceptable(const TRetransmissionAndFlowControlOption& aPreferred,
+ const TRetransmissionAndFlowControlOption& aPeer) const
+ {
+#ifdef __FLOG_ACTIVE
+ LogCurrentValues(aPreferred, aPeer);
+#endif
+ __ASSERT_DEBUG(aPeer.LinkMode() == aPreferred.LinkMode(), Panic(EL2CAPPeerAndPreferredChannelModesNotEqual));
+
+ // Logically it's Preferred checking whether Peer is acceptable, so dispatch on preferred.
+ // (If we're here then both modes are equal though, so it doesn't really matter, but just
+ // sayin' in case it changes).
+ return Handler(aPreferred).IsPeerResponseAcceptable(aPreferred, aPeer);
+ }
+
+inline TBool TFecOptionHandlerDelegator::BuildPositiveResponse(TRetransmissionAndFlowControlOption& aPreferred,
+ const TRetransmissionAndFlowControlOption& aPeer) const
+ {
+#ifdef __FLOG_ACTIVE
+ LogCurrentValues(aPreferred, aPeer);
+#endif
+
+ // Response will have peer - proposed mode so dispatch on peer.
+ return Handler(aPeer).BuildPositiveResponse(aPreferred, aPeer);
+ }
+
+inline void TFecOptionHandlerDelegator::BuildNegativeResponse(TRetransmissionAndFlowControlOption& aPreferred,
+ const TRetransmissionAndFlowControlOption& aPeer) const
+ {
+#ifdef __FLOG_ACTIVE
+ LogCurrentValues(aPreferred, aPeer);
+#endif
+
+ // Response will have our preferred mode so dispatch on preferred.
+ Handler(aPreferred).BuildNegativeResponse(aPreferred, aPeer);
+ }
+
+inline void TFecOptionHandlerDelegator::PrepareImplicitPeerResponse(TRetransmissionAndFlowControlOption& aImplicitResponse,
+ const TRetransmissionAndFlowControlOption& aPreferred) const
+ {
+ // Response will have our preferred mode so dispatch on preferred.
+ Handler(aPreferred).PrepareImplicitPeerResponse(aImplicitResponse, aPreferred);
+ }
+
+inline void TFecOptionHandlerDelegator::SetMaxTransmit(TRetransmissionAndFlowControlOption& aFecOption, TUint8 aMaxTransmit) const
+ {
+ Handler(aFecOption).SetMaxTransmit(aFecOption, aMaxTransmit);
+ }
+
+inline void TFecOptionHandlerDelegator::ZeroUnspecifiedRequestFields(TRetransmissionAndFlowControlOption& aFecOption) const
+ {
+ Handler(aFecOption).ZeroUnspecifiedRequestFields(aFecOption);
+ }
+
+inline void TFecOptionHandlerDelegator::ZeroUnspecifiedResponseFields(TRetransmissionAndFlowControlOption& aFecOption) const
+ {
+ Handler(aFecOption).ZeroUnspecifiedResponseFields(aFecOption);
+ }
+
+
+//
+// TL2CapSingleDirectionFecNegotiatorBase inlines
+//
+inline TL2CapSingleDirectionFecNegotiatorBase::TL2CapSingleDirectionFecNegotiatorBase(const TL2CapFecNegotiator& aFecNegotiator)
+ : iFecNegotiator(aFecNegotiator),
+ iConfigStatus(EOptionConfigOutstanding)
+ {}
+
+inline TL2CapConfigurationOptionGroupBase::TOptionConfigStatus TL2CapSingleDirectionFecNegotiatorBase::ConfigOptionStatus() const
+ {
+ return iConfigStatus;
+ }
+
+inline void TL2CapSingleDirectionFecNegotiatorBase::SetPeer(const TRetransmissionAndFlowControlOption& aFec)
+ {
+ iPeer = aFec;
+ }
+
+inline void TL2CapSingleDirectionFecNegotiatorBase::SetPreferred(const TRetransmissionAndFlowControlOption& aFec)
+ {
+ iPreferred = aFec;
+ }
+
+inline const TRetransmissionAndFlowControlOption& TL2CapSingleDirectionFecNegotiatorBase::Peer() const
+ {
+ return iPeer;
+ }
+
+inline const TRetransmissionAndFlowControlOption& TL2CapSingleDirectionFecNegotiatorBase::Preferred() const
+ {
+ return iPreferred;
+ }
+
+
+inline TL2CapIncomingFecNegotiator::TL2CapIncomingFecNegotiator(const TL2CapFecNegotiator& aFecNegotiator)
+ : TL2CapSingleDirectionFecNegotiatorBase(aFecNegotiator)
+ {}
+
+inline TL2CapOutgoingFecNegotiator::TL2CapOutgoingFecNegotiator(const TL2CapFecNegotiator& aFecNegotiator)
+ : TL2CapSingleDirectionFecNegotiatorBase(aFecNegotiator),
+ iIncludeValueInPositiveConfigResponse(EFalse)
+ {}
+
+inline TBool TL2CapOutgoingFecNegotiator::NeedToIncludeInPositiveConfigResponse()
+ {
+ return iIncludeValueInPositiveConfigResponse;
+ }
+
+inline void TL2CapOutgoingFecNegotiator::SetIncludeInPositiveConfigResponse(TBool aVal)
+ {
+ iIncludeValueInPositiveConfigResponse = aVal;
+ }
+
+
+//
+// TL2CapFecNegotiator inlines
+//
+
+inline TL2CapFecNegotiator::TL2CapFecNegotiator()
+ : iIncomingNegotiator(*this),
+ iOutgoingNegotiator(*this),
+ iNegotiationBehavior(EState1),
+ iDesiredMode(EL2CAPBasicMode)
+ {}
+
+inline TInt TL2CapFecNegotiator::PeerRequestsOption(const TRetransmissionAndFlowControlOption& aFecOption)
+ {
+ if (iModeSpecificHandlers.IsOptionValid(aFecOption))
+ {
+ return iOutgoingNegotiator.ProcessPeerValue(aFecOption);
+ }
+ else
+ {
+ return KErrBadPacketReceived;
+ }
+ }
+
+inline TInt TL2CapFecNegotiator::PeerRequestsLastAcceptedValue()
+ {
+ TInt err = iOutgoingNegotiator.ProcessPeerValue(iOutgoingNegotiator.Peer());
+ iOutgoingNegotiator.SetIncludeInPositiveConfigResponse(EFalse);
+ return err;
+ }
+
+inline TInt TL2CapFecNegotiator::PeerRejectsOption(const TRetransmissionAndFlowControlOption& aFecOption)
+ {
+ TInt err = KErrNone;
+
+ // Peer has sent us an Unacceptable Parameters response with a Retransmission And Flow Control
+ // option in it. The only useful information there is the Channel Mode field - this is the one
+ // actually being rejected, all the rest of them are non-negotiable (informational).
+ // Some implementations send their default values for those informational parameters, others
+ // just set them to 0 (that's what we do). Whatever their values are, we don't use them - we
+ // use our own based on the mode suggested by the remote.
+ // This is why we don't (and can't - they may be 0) check all the parameters with IsOptionValid
+ // - channel mode is all we're interested in.
+
+ if (TRetransmissionAndFlowControlOption::IsModeValid(aFecOption.LinkMode()))
+ {
+ iIncomingNegotiator.ProcessPeerValue(aFecOption, ETrue);
+ }
+ else
+ {
+ err = KErrBadPacketReceived;
+ }
+ return err;
+ }
+
+inline TInt TL2CapFecNegotiator::PeerAcceptsOption(const TRetransmissionAndFlowControlOption& aFecOption)
+ {
+ TInt err = KErrNone;
+ if (iModeSpecificHandlers.IsOptionValid(aFecOption))
+ {
+ iIncomingNegotiator.ProcessPeerValue(aFecOption, EFalse);
+ }
+ else
+ {
+ err = KErrBadPacketReceived;
+ }
+ return err;
+ }
+
+inline void TL2CapFecNegotiator::PeerAcceptsOption()
+ {
+ iIncomingNegotiator.ProcessImplicitPeerValue();
+ }
+
+inline TBool TL2CapFecNegotiator::NeedToIncludeInPositiveConfigResponse()
+ {
+ return iOutgoingNegotiator.NeedToIncludeInPositiveConfigResponse();
+ }
+
+inline const TL2CapEntityInfo& TL2CapFecNegotiator::PeerSupportedModes() const
+ {
+ return iPeerSupportedModes;
+ }
+
+inline TL2CapFecNegotiator::TNegotiationBehavior TL2CapFecNegotiator::NegotiationBehavior() const
+ {
+ return iNegotiationBehavior;
+ }
+
+inline TL2CapChannelMode TL2CapFecNegotiator::DesiredMode() const
+ {
+ return iDesiredMode;
+ }
+
+inline TUint8 TL2CapFecNegotiator::MaxTransmit() const
+ {
+ return iMaxTransmit;
+ }
+
+inline const TFecOptionHandlerDelegator& TL2CapFecNegotiator::ModeSpecificHandlers() const
+ {
+ return iModeSpecificHandlers;
+ }
+
+inline const TRetransmissionAndFlowControlOption& TL2CapFecNegotiator::IncomingPreferred() const
+ {
+ return iIncomingNegotiator.Preferred();
+ }
+
+inline const TRetransmissionAndFlowControlOption& TL2CapFecNegotiator::OutgoingPreferred() const
+ {
+ return iOutgoingNegotiator.Preferred();
+ }
+
+inline TL2CapConfigurationOptionGroupBase::TOptionConfigStatus TL2CapFecNegotiator::IncomingConfigOptionStatus() const
+ {
+ return iIncomingNegotiator.ConfigOptionStatus();
+ }
+
+inline TL2CapConfigurationOptionGroupBase::TOptionConfigStatus TL2CapFecNegotiator::OutgoingConfigOptionStatus() const
+ {
+ return iOutgoingNegotiator.ConfigOptionStatus();
+ }
+
+inline TL2CapDataControllerConfig TL2CapFecNegotiator::DataControllerConfig() const
+ {
+ return TL2CapDataControllerConfig(OutgoingLinkMode(),
+ OutgoingTxWindowSize(),
+ OutgoingMaxTransmit(),
+ OutgoingRetransmissionTimeout(),
+ IncomingMonitorTimeout(),
+ IncomingTxWindowSize(),
+ IncomingRetransmissionTimeout(),
+ IncomingMaximumPDUSize());
+ }
+
+
+// The general rule for methods below is that for the Outgoing direction we get the parameters
+// from the Preferred fields since in case of wildcard params (TxWin, MPS), these fields contain
+// the correct minimized values. For the same reason the Incoming direction parameters are fetched
+// from the Peer values.
+// Note that it's not always that simple in case of non-negotiated parameters like MaxTransmit,
+// Retransmission & Monitor TO, which is the reason these methods exist.
+
+inline TL2CapChannelMode TL2CapFecNegotiator::OutgoingLinkMode() const
+ {
+ return iOutgoingNegotiator.Preferred().LinkMode();
+ }
+
+inline TL2CapChannelMode TL2CapFecNegotiator::IncomingLinkMode() const
+ {
+ return iIncomingNegotiator.Peer().LinkMode();
+ }
+
+inline TUint8 TL2CapFecNegotiator::OutgoingLinkModeAsUnsignedByte() const
+ {
+ return iOutgoingNegotiator.Preferred().LinkModeAsUnsignedByte();
+ }
+
+inline TUint8 TL2CapFecNegotiator::IncomingLinkModeAsUnsignedByte() const
+ {
+ return iIncomingNegotiator.Peer().LinkModeAsUnsignedByte();
+ }
+
+inline TUint8 TL2CapFecNegotiator::OutgoingTxWindowSize() const
+ {
+ return iOutgoingNegotiator.Preferred().TxWindowSize();
+ }
+
+inline TUint8 TL2CapFecNegotiator::IncomingTxWindowSize() const
+ {
+ return iIncomingNegotiator.Peer().TxWindowSize();
+ }
+
+inline TUint8 TL2CapFecNegotiator::OutgoingMaxTransmit() const
+ {
+ // Peer sends us the value to use in its Config Request.
+ return iOutgoingNegotiator.Peer().MaxTransmit();
+ }
+
+inline TUint8 TL2CapFecNegotiator::IncomingMaxTransmit() const
+ {
+ // We send the peer the value to use in our Config Request.
+ return iIncomingNegotiator.Preferred().MaxTransmit();
+ }
+
+inline TUint16 TL2CapFecNegotiator::OutgoingRetransmissionTimeout() const
+ {
+ return iOutgoingNegotiator.Preferred().RetransmissionTimeout();
+ }
+
+inline TUint16 TL2CapFecNegotiator::IncomingRetransmissionTimeout() const
+ {
+ return iIncomingNegotiator.Peer().RetransmissionTimeout();
+ }
+
+// Outgoing traffic -> Incoming S-Frames -> Monitor TO that our peer will use.
+inline TUint16 TL2CapFecNegotiator::OutgoingMonitorTimeout() const
+ {
+ if (iIncomingNegotiator.Preferred().LinkMode() == EL2CAPEnhancedRetransmissionMode ||
+ iIncomingNegotiator.Preferred().LinkMode() == EL2CAPStreamingMode)
+ {
+ // Peer sends the time-outs it'll use in its Config Response.
+ return iIncomingNegotiator.Peer().MonitorTimeout();
+ }
+ else
+ {
+ // Negotiated in the direction it relates to.
+ return iOutgoingNegotiator.Preferred().MonitorTimeout();
+ }
+ }
+
+// Incoming traffic -> Outgoing S-Frames -> Monitor TO that we will use.
+inline TUint16 TL2CapFecNegotiator::IncomingMonitorTimeout() const
+ {
+ if (iIncomingNegotiator.Preferred().LinkMode() == EL2CAPEnhancedRetransmissionMode ||
+ iIncomingNegotiator.Preferred().LinkMode() == EL2CAPStreamingMode)
+ {
+ // We send the time-outs we'll use in our Config Response.
+ return iOutgoingNegotiator.Preferred().MonitorTimeout();
+ }
+ else
+ {
+ // Negotiated in the direction it relates to.
+ return iIncomingNegotiator.Peer().MonitorTimeout();
+ }
+ }
+
+inline TUint16 TL2CapFecNegotiator::OutgoingMaximumPDUSize() const
+ {
+ return iOutgoingNegotiator.Preferred().MaximumPDUSize();
+ }
+
+inline TUint16 TL2CapFecNegotiator::IncomingMaximumPDUSize() const
+ {
+ return iIncomingNegotiator.Peer().MaximumPDUSize();
+ }
+
+#endif /*L2CAPFECNEGOTIATOR_INL*/