bluetooth/btstack/linkmgr/physicallinks.cpp
branchRCL_3
changeset 12 8a27654f7b62
parent 8 2b6718f05bdb
child 13 20fda83a6398
--- a/bluetooth/btstack/linkmgr/physicallinks.cpp	Fri Feb 19 23:56:55 2010 +0200
+++ b/bluetooth/btstack/linkmgr/physicallinks.cpp	Fri Mar 12 15:49:00 2010 +0200
@@ -384,49 +384,12 @@
 	// Store the result of the retrieval for usage later.
 	iDeviceResult = aResult;
 
-	// the HW asked earlier for a link key - we can respond now
-	__ASSERT_DEBUG(iDevice.IsValidAddress(), Panic(EBTPhysicalLinksInvalidAddress));
-	if(iWaitingForLinkKeyFromRegistry)
+	if (iLinkKeyRequestOutstanding)
 		{
-		if (aResult == KErrNone && iDevice.IsValidLinkKey())
-			{
-			if ( iDevice.LinkKeyType() != ELinkKeyCombination)
-				{
-				if (iLinksMan.SecMan().DebugMode() && iDevice.LinkKeyType() != ELinkKeyDebug)
-					{
-					LOG(_L("CPhysicalLink: Debug mode - Link to debug link key"))
-					iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address());
-					}
-				else
-				if (iRequireAuthenticatedLinkKey && iDevice.LinkKeyType() == ELinkKeyUnauthenticatedUpgradable && IsPairable())
-					{
-					LOG(_L("CPhysicalLink: Requiring Authenticated link key but currently only have unauthenticated"))
-					iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address());
-					}
-				else
-					{
-					LOG(_L("CPhysicalLink: Issuing link key to HC now"))
-					iAuthenticationCtrl.LinkKeyRequestReply(iDevice.Address(), iDevice.LinkKey());
-					}
-				}
-			else if(IsPasskeyMinLengthOK() && SimplePairingMode() != EPhySimplePairingEnabled)
-				{
-				LOG(_L("CPhysicalLink: Issuing link key to HC now"))
-				iAuthenticationCtrl.LinkKeyRequestReply(iDevice.Address(), iDevice.LinkKey());
-				}
-			else
-				{
-				LOG(_L("CPhysicalLink: Current PIN code too short!"))
-				iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address());
-				}
-			}
-		else
-			{
-			iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address());
-			}	
+		// the HW asked earlier for a link key - we can respond now
+		__ASSERT_DEBUG(iDevice.IsValidAddress(), Panic(EBTPhysicalLinksInvalidAddress));
+		LinkKeyRequestResponseAttempt(ETrue);
 		}
-	iRequireAuthenticatedLinkKey = EFalse;
-	iWaitingForLinkKeyFromRegistry = EFalse;
 
 	RegistryTaskComplete(aHelper, aResult);	 // cleans up our helper
 	}
@@ -708,15 +671,9 @@
 			}
 		else
 			{
-			// If the remote doesn't support extended features, then neither they support SSP
-			// (no way to indicate the host supported bit).  So set it as disabled.
-			TPhysicalLinkSimplePairingMode previousSetting = SimplePairingMode();
-			__ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingDisabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection));
-			iSimplePairingMode = EPhySimplePairingDisabled;
-			if(SimplePairingMode() != previousSetting)
-				{
-				iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr());
-				}
+			// If the remote doesn't support extended features, then they cannot support SSP
+			// (no way to indicate the host supported bit).  So set feature as disabled.
+			RemoteSimplePairingModeDetermined(EPhySimplePairingDisabled);
 			}
 		}
 	else
@@ -740,18 +697,12 @@
 
 			if (aErr == EOK && aBitMask & (1 << ESecureSimplePairingHostSupportBit) && iLinksMan.SecMan().LocalSimplePairingMode())
 				{
-				__ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingEnabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection));
-				iSimplePairingMode = EPhySimplePairingEnabled;
+				RemoteSimplePairingModeDetermined(EPhySimplePairingEnabled);
 				}
 			else
 				{
-				__ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingDisabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection));
-				iSimplePairingMode = EPhySimplePairingDisabled;
+				RemoteSimplePairingModeDetermined(EPhySimplePairingDisabled);
 				}
-			if(SimplePairingMode()!=currentSetting)
-				{
-				iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr());
-				}			
 			break;
 			}
 		default:
@@ -2835,18 +2786,19 @@
 
 	SetAuthenticationPending(EPinRequestPending); // if not already set (because the remote initiated authentication).
 
-	__ASSERT_DEBUG(iSimplePairingMode != EPhySimplePairingEnabled, Panic(EBTSSPModeChangedDuringConnection));
-	if (iSimplePairingMode == EPhySimplePairingUndefined)
-		{
-		iSimplePairingMode = EPhySimplePairingDisabled;
-		}
-	
 	if (!IsConnected())
 		{
-		iPeerInSecurityMode3 = ETrue;
+		// If the ACL to the peer device is not yet connected, and the peer has initiated
+		// authentication then it must be in security mode 3.  This information is stored and
+		// if the connection completes the link will be set as authenticated.
+		SetPeerInSecurityMode3();
 		}
 
-	
+	// We can receive "fast" PIN requests if the remote device initiates pairing and indicates
+	// it doesn't have a link key.  If we see this then we know that we are not engaging in 
+	// simple pairing on this particular link.
+	RemoteSimplePairingModeDetermined(EPhySimplePairingDisabled);
+
 	if (iPinRequester)
 		{
 		return;
@@ -3056,9 +3008,14 @@
 	return isPasskeyMinLengthOK;
 	}
 
-void CPhysicalLink::LinkKeyRequest(const TBTDevAddr& aAddr, MLinkKeyResponseHandler& /*aRequester*/)
+void CPhysicalLink::LinkKeyRequest(const TBTDevAddr& __DEBUG_ONLY(aAddr), MLinkKeyResponseHandler& /*aRequester*/)
 	{
 	LOG_FUNC
+	__ASSERT_DEBUG(aAddr == BDAddr(), Panic(EBTConnectionBadDeviceAddress));
+	ASSERT_DEBUG(!iLinkKeyRequestOutstanding);
+
+	iLinkKeyRequestOutstanding = ETrue;
+
 	// we don't keep a copy of the device record - we just leave the one copy with
 	// the baseband - it can tell us if there's a link key
 	// we can tell if the baseband has the device record or not
@@ -3070,68 +3027,13 @@
 	// if the connection completes the link will be set as authenticated.
 	if (!IsConnected())
 		{
-		iPeerInSecurityMode3 = ETrue;
-		}
-
-	if(!iPeerInSecurityMode3 && iLinksMan.SecMan().IsDedicatedBondingAttempted(iDevice.Address()))
-		{
-		// If we are doing DedicatedBonding then we should ignore the existing linkkey
-		// in an attempt to generate a stronger one if possible.
-		// Security mode 3 is a odd case - because we get what looks like double pairing (the remote
-		// initiated pairing on connection, then the dedicated bonding pairing).  So we have removed
-		// this feature for security mode 3 devices...they will have to suffer for their transgressions
-		LOG(_L("CPhysicalLink: Dedicated bonding attempt - Sending link key request negative reply"));
-		iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr);
-		iRequireAuthenticatedLinkKey = EFalse;
+		SetPeerInSecurityMode3();
 		}
-	else if (iDeviceResult==KErrNone && iDevice.IsValidLinkKey())
-		{
-		if (iLinksMan.SecMan().DebugMode() && iDevice.LinkKeyType() != ELinkKeyDebug)
-			{
-			LOG(_L("CPhysicalLink: Debug mode - Link to debug link key"))
-			iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr);
-			}
-		else
-			{
-			if (iDevice.LinkKeyType() != ELinkKeyCombination)
-				{
-				if (iRequireAuthenticatedLinkKey && iDevice.LinkKeyType() == ELinkKeyUnauthenticatedUpgradable && IsPairable())
-					{
-					LOG(_L("CPhysicalLink: Requiring Authenticated link key but currently only have unauthenticated"))
-					iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr);
-					}
-				else
-					{
-					LOG(_L("CPhysicalLink: Issuing link key to HC now"))
-					iAuthenticationCtrl.LinkKeyRequestReply(aAddr, iDevice.LinkKey());
-					}
-				}
-			else if(IsPasskeyMinLengthOK() && SimplePairingMode() != EPhySimplePairingEnabled)
-				{
-				LOG(_L("CPhysicalLink: Issuing link key to HC now"))
-				iAuthenticationCtrl.LinkKeyRequestReply(aAddr, iDevice.LinkKey());
-				}
-			else
-				{
-				LOG(_L("CPhysicalLink: Current PIN code too short!"))
-				iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr);
-				}
-			}
-		iRequireAuthenticatedLinkKey = EFalse;
+
+	if (iLinkKeyRequestOutstanding)
+		{ // might have already been called via SetPeerInSecurityMode3()
+		LinkKeyRequestResponseAttempt();
 		}
-	else if (iDeviceResult==KErrNone && !iDevice.IsValidLinkKey() || iDeviceResult==KErrNotFound)
-		{
-		LOG(_L("CPhysicalLink: No Link key available for the device"));
-		iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr);
-		iRequireAuthenticatedLinkKey = EFalse;
-		}
-	else
-		{
-		LOG(_L("CPhysicalLink: Waiting for link key from Registry!"))
-		// we're still waiting for the device....we'll respond when it turns up
-		iWaitingForLinkKeyFromRegistry = ETrue;
-		}
-
 	}
 
 TInt CPhysicalLink::PINCodeRequestReply(const TBTDevAddr& aDevAddr, const TDesC8& aPin) const
@@ -3613,16 +3515,11 @@
 	iOOBDataPresence = aOOBDataPresence;
 	iAuthenticationRequirement = aAuthenticationRequirement;
 	
-	//If we haven't determined the SSP pairing mode till now then enable it and notify the state m/c.
-	//This condition is to cater the fast remote device which responds very quickly,  
-	//even before we determine whether it supports simple pairing!*/ 
-	__ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingEnabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection));
-	if(SimplePairingMode() == EPhySimplePairingUndefined)
-		{
-		//Since we have received a I/O cap response the simple pairing must be enabled
-		iSimplePairingMode = EPhySimplePairingEnabled;
-		iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr());
-		}
+	// If we haven't determined the SSP pairing mode the link is operating in yet then enable it,
+	// since we have received a I/O cap response the simple pairing must be enabled.
+	// This condition is to cater the fast remote device which responds very quickly,
+	// even before we determine whether it supports simple pairing!
+	RemoteSimplePairingModeDetermined(EPhySimplePairingEnabled);
 	}
 
 
@@ -3757,6 +3654,131 @@
 	return iSniffInterval;
 	}
 
+void CPhysicalLink::LinkKeyRequestResponseAttempt(TBool aForceResponse)
+	{
+	ASSERT_DEBUG(iLinkKeyRequestOutstanding);
+
+	if(!iPeerInSecurityMode3 && iLinksMan.SecMan().IsDedicatedBondingAttempted(iDevice.Address()))
+		{
+		// If we are doing DedicatedBonding then we should ignore the existing linkkey
+		// in an attempt to generate a stronger one if possible.
+		// Security mode 3 is a odd case - because we get what looks like double pairing (the remote
+		// initiated pairing on connection, then the dedicated bonding pairing).  So we have removed
+		// this feature for security mode 3 devices...they will have to suffer for their transgressions
+		LOG(_L("CPhysicalLink: Dedicated bonding attempt - Sending link key request negative reply"));
+		DoLinkKeyResponse(EFalse);
+		iRequireAuthenticatedLinkKey = EFalse;
+		}
+	else if (iDeviceResult==KErrNone && iDevice.IsValidLinkKey())
+		{
+		if (iLinksMan.SecMan().DebugMode() && iDevice.LinkKeyType() != ELinkKeyDebug)
+			{
+			LOG(_L("CPhysicalLink: Debug mode - Link to debug link key"))
+			DoLinkKeyResponse(EFalse);
+			}
+		else if (iDevice.LinkKeyType() != ELinkKeyCombination)
+			{
+			if (iRequireAuthenticatedLinkKey && iDevice.LinkKeyType() == ELinkKeyUnauthenticatedUpgradable && IsPairable())
+				{
+				LOG(_L("CPhysicalLink: Requiring Authenticated link key but currently only have unauthenticated"))
+				DoLinkKeyResponse(EFalse);
+				}
+			else
+				{
+				LOG(_L("CPhysicalLink: non - combination key, auth OK"))
+				DoLinkKeyResponse(ETrue);
+				}
+			}
+		else // Standard (legacy) Combination Key
+			{
+			if (SimplePairingMode() == EPhySimplePairingUndefined)
+				{
+				LOG(_L("CPhysicalLink: Waiting for Secure Simple Pairing mode to be determined"));
+				// wait for ssp mode to be determined...then try again
+				}
+			else if (IsPasskeyMinLengthOK() && SimplePairingMode() == EPhySimplePairingDisabled)
+				{
+				LOG(_L("CPhysicalLink: Combination key, Passkey len OK, no SSP"));
+				DoLinkKeyResponse(ETrue);
+				}
+			else
+				{
+				LOG(_L("CPhysicalLink: Current link key is not sufficient!"))
+				DoLinkKeyResponse(EFalse);
+				}
+			}
+		iRequireAuthenticatedLinkKey = EFalse;
+		}
+	else if (iDeviceResult==KErrNone && !iDevice.IsValidLinkKey() || iDeviceResult==KErrNotFound)
+		{
+		LOG(_L("CPhysicalLink: No Link key available for the device"));
+		DoLinkKeyResponse(EFalse);
+		iRequireAuthenticatedLinkKey = EFalse;
+		}
+	else if (aForceResponse)
+		{
+		LOG(_L("CPhysicalLink: Forcing a link key response (-ve as we don't have a link key yet)"));
+		DoLinkKeyResponse(EFalse);
+		}
+	else
+		{
+		LOG(_L("CPhysicalLink: Waiting for link key from Registry!"))
+		// we're still waiting for the device....we'll respond when it turns up
+		}
+	}
+
+/**
+Send a link key response for an outstanding request, assumes that all details
+have be validated.
+*/
+void CPhysicalLink::DoLinkKeyResponse(TBool aPositive)
+	{
+	LOG_FUNC
+	ASSERT_DEBUG(iLinkKeyRequestOutstanding);
+
+	if(aPositive)
+		{
+		LOG(_L("CPhysicalLink: Providing link key to HC..."))
+		ASSERT_DEBUG(iDevice.IsValidLinkKey());
+		iAuthenticationCtrl.LinkKeyRequestReply(iDevice.Address(), iDevice.LinkKey());
+		}
+	else
+		{
+		LOG(_L("CPhysicalLink: Indicating no link key to HC..."));
+		iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address());
+		}
+	iLinkKeyRequestOutstanding = EFalse;
+	}
+
+void CPhysicalLink::RemoteSimplePairingModeDetermined(TPhysicalLinkSimplePairingMode aSimplePairingMode)
+	{
+	LOG2(_L8("Current SimplePairingMode = %d, aSimplePairingMode = %d"), SimplePairingMode(), aSimplePairingMode);
+	ASSERT_DEBUG(aSimplePairingMode != EPhySimplePairingUndefined); // must be a definite value
+	__ASSERT_DEBUG(SimplePairingMode() == aSimplePairingMode || SimplePairingMode() == EPhySimplePairingUndefined, Panic(EBTSSPModeChangedDuringConnection));
+
+	const TPhysicalLinkSimplePairingMode previousSetting = iSimplePairingMode;
+	iSimplePairingMode = aSimplePairingMode;
+	if (previousSetting != iSimplePairingMode)
+		{
+		iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr());
+
+		// Also we may be waiting to respond to a link key request.
+		if (iLinkKeyRequestOutstanding)
+			{
+			LinkKeyRequestResponseAttempt();
+			}
+		}
+	}
+
+void CPhysicalLink::SetPeerInSecurityMode3()
+	{
+	iPeerInSecurityMode3 = ETrue;
+
+	// We also now know that the remote cannot possibly do SSP, *and* the LMP will
+	// likely lock our finding if the remote does SSP anyway while we do SM3.
+	RemoteSimplePairingModeDetermined(EPhySimplePairingDisabled);
+	}
+
 //
 // TLowPowModeCmdController
 //