--- a/bluetooth/btstack/linkmgr/physicallinks.cpp Tue May 11 17:15:36 2010 +0300
+++ b/bluetooth/btstack/linkmgr/physicallinks.cpp Tue May 25 13:54:55 2010 +0300
@@ -927,7 +927,12 @@
void CPhysicalLink::ConnectionComplete(THCIErrorCode aErr, const TBTConnect& aConn)
{
LOG_FUNC
- if (aErr == KErrNone)
+ ConnectionComplete(CHciUtil::SymbianErrorCode(aErr), aConn);
+ }
+
+void CPhysicalLink::ConnectionComplete(TInt aResult, const TBTConnect& aConn)
+ {
+ if (aResult == KErrNone)
{
if(aConn.iLinkType == ESCOLink && !iSyncLogicalLink)
{
@@ -936,12 +941,9 @@
//a remote device to respond to a connection request.
iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType);
- if(aErr==EOK) // if error, aConn.iConnH will refer to the ACL link used to initialise the SCO link, so dont disconnect that
- {
- //The baseband might actually have established a SCO link, so send a Disconnect.
- //If no SCO link exists the command will fail gracefully.
- TRAP_IGNORE(iLinksMan.HCIFacade().DisconnectL(aConn.iConnH, ERemoteUserEndedConnection));
- }
+ //The baseband might actually have established a SCO link, so send a Disconnect.
+ //If no SCO link exists the command will fail gracefully.
+ TRAP_IGNORE(iLinksMan.HCIFacade().DisconnectL(aConn.iConnH, ERemoteUserEndedConnection));
return;
}
@@ -989,7 +991,7 @@
if (aConn.iEncryptMode)
{
// pretend there's been an encryption event
- EncryptionChange(aErr, aConn.iConnH, aConn.iEncryptMode);
+ EncryptionChange(EOK, aConn.iConnH, aConn.iEncryptMode);
}
}
@@ -1061,13 +1063,13 @@
}
iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType);
- NotifyLogicalLinkError(aConn.iLinkType, CHciUtil::SymbianErrorCode(aErr));
+ NotifyLogicalLinkError(aConn.iLinkType, aResult);
if (aConn.iLinkType == EACLLink)
{
// BT 1.2 says that as the ACL Link goes up and down, so does the physical link
// so if the ACL Link has gone, so has this
// for SCO we remain in place.
- TBTBasebandEventNotification event(ENotifyPhysicalLinkError, CHciUtil::SymbianErrorCode(aErr));
+ TBTBasebandEventNotification event(ENotifyPhysicalLinkError, aResult);
NotifyStateChange(event);
delete this;
}
@@ -1700,73 +1702,60 @@
{
LOG_FUNC
if (!IsConnected())
+ {
+ LOG(_L8("Physical link not connected, no arbitration executed"));
return KErrDisconnected;
-
- if ( aImmediately )
- {
- iArbitrationDelay->Cancel();
- return DoArbitrate(aLocalPriority);
}
- else if (iArbitrationDelay->IsActive())
- {
- return KErrNone;
- }
- else
- {
- iArbitrationDelay->Start(aLocalPriority);
- return KErrNone;
- }
+ // The arbitration delay object will decide how much delay
+ return iArbitrationDelay->Start(aImmediately, aLocalPriority);
}
TInt CPhysicalLink::DoArbitrate(TBool aLocalPriority)
{
+ LOG_FUNC
if (!IsConnected())
{
+ LOG(_L8("Physical link not connected, no arbitration executed"));
return KErrDisconnected;
}
//start arbitrate process with what our local controller supports
TUint8 allowedModesMask = EHoldMode | EParkMode | ESniffMode; // local features sorted out later
- TBool roleSwitchAllowed = EFalse;
-
- if (iLinksMan.LinkManagerProtocol().IsRoleSwitchSupportedLocally() && iLinksMan.RoleSwitchAllowed())
- {
- roleSwitchAllowed = ETrue;
- }
-
+ TBool roleSwitchAllowed = iLinksMan.LinkManagerProtocol().IsRoleSwitchSupportedLocally() && iLinksMan.RoleSwitchAllowed();
+ LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - Prior to proxies"), allowedModesMask, roleSwitchAllowed);
+
// ask proxies what they want from the PHY
- TUint8 requestedModeMask = 0;
- TUint8 requestedMode = 0;
- TBool activeModeIsRequested = EFalse;
+ TUint16 requestedModeMask = 0; // mask of current LPM requests from proxy's
+ static const TUint16 KExplicitActiveMode = 0x0100; // special bit for explicit active mode requests
+
TSglQueIter<CBTProxySAP> iter(iProxySAPs);
while (iter)
{
CBTProxySAP* proxy = iter++;
- requestedMode = proxy->GetRequestedModes();
- requestedModeMask |= requestedMode;
-
- if (requestedMode == EActiveMode && proxy->RequestedActiveMode())
- {
- // An Active Mode request will override all other local low power mode requests
- // but continue to collect the requirement from the other proxies..
- activeModeIsRequested = ETrue;
- }
-
- allowedModesMask &= proxy->GetAllowedModes();
- roleSwitchAllowed &= proxy->IsRoleSwitchAllowed();
+ TUint8 requestedMode = proxy->GetRequestedModes();
+ requestedModeMask |= requestedMode;
+
+ TBool explicitActiveModeRequest = proxy->RequestedActiveMode();
+ if (requestedMode == EActiveMode && explicitActiveModeRequest)
+ {
+ requestedModeMask |= KExplicitActiveMode;
+ }
+
+ TUint8 allowedModes = proxy->GetAllowedModes();
+ allowedModesMask &= allowedModes;
+
+ TBool roleSwitchAllowedByProxy = proxy->IsRoleSwitchAllowed();
+ roleSwitchAllowed = roleSwitchAllowed && roleSwitchAllowedByProxy;
+
+ LOG4(_L8("Arbitration: Proxy(0x%08x) - requested mode = 0x%04x, link policy (LPM:0x%02x, Role:0x%x)"), proxy, requestedMode, allowedModes, roleSwitchAllowedByProxy);
}
-
- if (activeModeIsRequested)
- {
- // Any Active Mode request will override all other low power mode requests,
- // so overwrite the requestedModeMask but keep allowedModesMask and roleSwitchAllowed
- // as specified by all the local proxies
- requestedModeMask = EActiveMode;
- }
+ LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - after proxies"), allowedModesMask, roleSwitchAllowed);
// clear out modes not supported by local Controller
+ // Future improvement - what about modes supported by the remote device?
allowedModesMask &= iLinksMan.LinkManagerProtocol().ModesSupportedLocally();
+ LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - only supported modes"), allowedModesMask, roleSwitchAllowed);
if(iOverrideParkRequests)
{
@@ -1774,13 +1763,11 @@
// The only way to guarantee this is to disallow PARK via the link policy settings.
allowedModesMask &= ~EParkMode;
}
-
- if(allowedModesMask != iLinkPolicy.LowPowerModePolicy()
- || roleSwitchAllowed != iLinkPolicy.IsSwitchAllowed())
- {
- // Controller policy for the connection needs updating
- SetModesAllowed(allowedModesMask, roleSwitchAllowed);
- }
+ LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - overrides applied"), allowedModesMask, roleSwitchAllowed);
+
+ // Controller policy for the connection may need updating
+ SetModesAllowed(allowedModesMask, roleSwitchAllowed);
+ LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - submitted"), allowedModesMask, roleSwitchAllowed);
//If OverrideLPM flag is set, we do not disable LP modes via the link policy settings
//This is done because OverrideLPM should not prevent remotes putting us into an LPM
@@ -1790,9 +1777,11 @@
// We need to ensure the physical link is in active mode.
allowedModesMask = EActiveMode;
}
-
- TUint8 modeChangeMask = static_cast<TUint8>(requestedModeMask & allowedModesMask);
- TUint8 modeCompareMask = 0;
+ LOG2(_L8("Arbitration: link policy (LPM:0x%02x, Role:0x%x) - post setting overrides applied"), allowedModesMask, roleSwitchAllowed);
+
+ TUint16 modeChangeMask = requestedModeMask & (static_cast<TUint16>(allowedModesMask)|KExplicitActiveMode);
+ TUint16 modeCompareMask = 0;
+ LOG2(_L8("Arbitration: mode change mask = 0x%04x, local priority = 0x%x"), modeChangeMask, aLocalPriority);
if(aLocalPriority)
{
@@ -1809,57 +1798,89 @@
// modeCompareMask should start only having zero bits where
// requestedModeMask has a zero bit and iPreviousRequestedModeMask does not
// i.e. a mode is newly no longer requested.
- modeCompareMask = requestedModeMask | ~iPreviousRequestedModeMask;
+ modeCompareMask = ~((requestedModeMask ^ iPreviousRequestedModeMask) & iPreviousRequestedModeMask);
// Remove bits from modeCompareMask that are not in allowedModesMask
// We cannot stay in a power mode that we do not allow.
- modeCompareMask &= allowedModesMask;
+ modeCompareMask &= (static_cast<TUint16>(allowedModesMask)|KExplicitActiveMode);
}
+ LOG1(_L8("Arbitration: Comparison mask = 0x%04x"), modeCompareMask);
iPreviousRequestedModeMask = requestedModeMask; // Update previous requested to current value.
- TUint8 currentModeMask = static_cast<TUint8>(iLinkState.LinkMode());
+ // get the current mode.
+ TBTLinkMode currentMode = iLinkState.LinkMode();
+ TUint16 currentModeMask = static_cast<TUint16>(currentMode);
+ if(currentModeMask == EActiveMode)
+ {
+ // if in active mode then could have been because of an explicit active mode request
+ currentModeMask |= KExplicitActiveMode;
+ }
+ LOG1(_L8("Arbitration: Current mode mask = 0x%04x"), currentModeMask);
+
if(modeCompareMask & currentModeMask)
{
+ LOG2(_L8("Arbitration: Comparison mask (0x%04x) matched, so staying in current mode (0x%04x)"), modeCompareMask, currentModeMask);
// The current state is the same as the permitted required role(s).
return KErrNone;
}
-
- if(modeChangeMask == EActiveMode && currentModeMask != EActiveMode)
+
+ TBTLinkMode nextMode = EActiveMode;
+ // Determine which LPM we should be in (if any)
+ if(modeChangeMask & KExplicitActiveMode)
{
- // The current low power mode should be exited.
- return RequestActive();
+ nextMode = EActiveMode;
}
-
- if(modeChangeMask != EActiveMode)
+ else if(modeChangeMask & EHoldMode)
+ {
+ nextMode = EHoldMode;
+ }
+ else if(modeChangeMask & ESniffMode)
{
- if(currentModeMask != EActiveMode)
+ nextMode = ESniffMode;
+ }
+ else if(modeChangeMask & EParkMode)
+ {
+ nextMode = EParkMode;
+ }
+ LOG2(_L8("Arbitration: Arbitrating mode 0x%02x -> 0x%02x"), currentMode, nextMode);
+
+ if(nextMode != currentMode)
+ {
+ if(currentMode != EActiveMode)
{
- // The system is currently in a low power mode. Exit this before
- // entering the new mode.
- TInt rerr = RequestActive();
- if(rerr != KErrNone)
+ LOG(_L8("Arbitration: Exiting existing LPM mode..."));
+ TInt err = RequestActive();
+ if(err != KErrNone)
{
- return rerr;
+ return err;
}
}
-
- if(modeChangeMask & EHoldMode)
+ if(nextMode == EHoldMode)
{
+ LOG(_L8("Arbitration: Entering Hold mode..."));
return RequestHold();
}
- if(modeChangeMask & ESniffMode)
+ else if(nextMode == ESniffMode)
{
+ LOG(_L8("Arbitration: Entering Sniff mode..."));
return RequestSniff();
}
- if(modeChangeMask & EParkMode)
+ else if(nextMode == EParkMode)
{
+ LOG(_L8("Arbitration: Entering Park mode..."));
return RequestPark();
}
+ else if(nextMode == EActiveMode)
+ {
+ LOG(_L8("Arbitration: Staying in Active mode..."));
+ return KErrNone;
+ }
+ // Shouldn't reach here, we have a strange mode
+ DEBUG_PANIC_LINENUM;
}
- // This point in the code is reached if the Link Policy settings are
- // changed but the mode is not. Return OK error code.
+ LOG(_L8("Arbitration: Already in correct LPM, not doing anything"));
return KErrNone;
}
@@ -1880,10 +1901,10 @@
void CPhysicalLink::StartArbitrationTimer() const
{
LOG_FUNC
- iArbitrationDelay->Start();
+ iArbitrationDelay->Restart();
}
-TInt CPhysicalLink::Connect(TBasebandPageTimePolicy aPolicy)
+void CPhysicalLink::Connect(TBasebandPageTimePolicy aPolicy)
{
LOG_FUNC
// assume that we will be master until told otherwise
@@ -1902,16 +1923,20 @@
// optimise paging (as a best-effort attempt).
TBasebandTime pagetimeout = CalculatePageTimeout(aPolicy, psrm, clockOffset & KHCIClockOffsetValidBit);
iLinksMan.TryToChangePageTimeout(pagetimeout);
+
+ // Set state in anticipation of the connection
+ iLinkState.SetLinkState(TBTBasebandLinkState::ELinkPending);
+ iLinksMan.Baseband().UpdateModel(iDevice.Address(), pkt, EACLLink);
+ iLinkState.SetLinkRole(EMaster);
TRAPD(ret, iLinksMan.HCIFacade().ConnectL(iDevice.Address(), pkt, psrm, psm, clockOffset, allowRoleSwitch));
- if(ret==KErrNone)
+ if(ret != KErrNone) // a physical link is in charge of it's own destiny.
{
- iLinkState.SetLinkState(TBTBasebandLinkState::ELinkPending);
- iLinksMan.Baseband().UpdateModel(iDevice.Address(), pkt, EACLLink);
- iLinkState.SetLinkRole(EMaster);
+ TBTConnect conn;
+ conn.iBdaddr = BDAddr();
+ conn.iLinkType = EACLLink;
+ ConnectionComplete(ret, conn);
}
-
- return ret;
}
TInt CPhysicalLink::SCOConnect()
@@ -2264,7 +2289,7 @@
(aEvent.EventType() & ENotifyHoldMode)) &&
(aEvent.ErrorCode() == KErrNone))
{
- iArbitrationDelay->Start();
+ iArbitrationDelay->Restart();
}
}
@@ -3378,17 +3403,18 @@
// CArbitrationDelayTimer
CArbitrationDelayTimer::CArbitrationDelayTimer(CPhysicalLink* aParent)
- :CTimer(CActive::EPriorityStandard),
- iParent(aParent)
+ : CTimer(CActive::EPriorityStandard)
+ , iParent(aParent)
{
LOG_FUNC
+ ASSERT_DEBUG(iParent);
+ CActiveScheduler::Add(this);
}
void CArbitrationDelayTimer::ConstructL()
{
LOG_FUNC
CTimer::ConstructL();
- CActiveScheduler::Add(this);
}
CArbitrationDelayTimer* CArbitrationDelayTimer::NewL(CPhysicalLink* aParent)
@@ -3401,16 +3427,46 @@
return self;
}
-void CArbitrationDelayTimer::Start(TBool aLocalPriority)
+TInt CArbitrationDelayTimer::Start(TBool aImmediate, TBool aLocalPriority)
{
LOG_FUNC
// Work out what the local priority will be now
- TBool localPriority = iLocalPriority || aLocalPriority;
- Cancel(); // cancel current timer (will also reset priority so ...
- iLocalPriority = localPriority; // set the new priority)
+ iLocalPriority = iLocalPriority || aLocalPriority;
+ LOG1(_L8("Arbitraion: Local Priority now %d"), iLocalPriority);
+ if(aImmediate)
+ {
+ LOG(_L8("Arbitraion: Immediate Arbitration Requested..."));
+ CancelButPreserveLocalPriority();
+ return DoArbitrate();
+ }
+ else if(!IsActive())
+ {
+ LOG(_L8("Arbitraion: Arbitration requested, will execute after delay timer..."));
+ After(KBTArbitrationDelay);
+ }
+ else // timer is already on its way
+ {
+ LOG(_L8("Arbitraion: Arbitration delay timer still pending..."));
+ }
+ return KErrNone;
+ }
+
+void CArbitrationDelayTimer::Restart()
+ {
+ LOG_FUNC
+ LOG(_L8("Arbitraion: Arbitration timer restarted..."));
+ CancelButPreserveLocalPriority();
After(KBTArbitrationDelay);
}
+void CArbitrationDelayTimer::CancelButPreserveLocalPriority()
+ {
+ LOG_FUNC
+ TBool localPriority = iLocalPriority;
+ Cancel();
+ iLocalPriority = localPriority;
+ }
+
void CArbitrationDelayTimer::RunL()
/**
@@ -3418,10 +3474,16 @@
**/
{
LOG_FUNC
- if (iParent)
- {
- iParent->DoArbitrate(iLocalPriority);
- }
+ LOG(_L8("Arbitraion: Delayed Arbitration executing..."));
+ static_cast<void>(DoArbitrate()); // ignore the error (always has been...)
+ }
+
+TInt CArbitrationDelayTimer::DoArbitrate()
+ {
+ LOG_FUNC
+ TBool localPriority = iLocalPriority;
+ iLocalPriority = EFalse;
+ return iParent->DoArbitrate(localPriority);
}
void CArbitrationDelayTimer::DoCancel()