bluetooth/btstack/linkmgr/physicallinks.cpp
changeset 0 29b1cd4cb562
child 3 4e39398d58ed
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implementation of physical links
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <bluetooth/logger.h>
       
    19 #include "physicallinksmanager.h"
       
    20 #include "physicallinks.h"
       
    21 #include "AclDataQController.h"
       
    22 #include "ACLSAP.h"
       
    23 #include "SCOSAP.h"
       
    24 #include "ProxySAP.h"
       
    25 #include "linkconsts.h"
       
    26 #include "hcifacade.h"
       
    27 #include "hostresolver.h"
       
    28 #include "PhysicalLinkHelper.h"
       
    29 #include "pairingscache.h"
       
    30 #include "oobdata.h"
       
    31 #include "pairingserver.h"
       
    32 
       
    33 #include <bt_sock.h>
       
    34 
       
    35 #include <bluetooth/hci/commandstatusevent.h>
       
    36 #include <bluetooth/hci/sniffmodecommand.h>
       
    37 #include <bluetooth/hci/exitsniffmodecommand.h>
       
    38 #include <bluetooth/hci/holdmodecommand.h>
       
    39 #include <bluetooth/hci/parkmodecommand.h>
       
    40 #include <bluetooth/hci/exitparkmodecommand.h>
       
    41 #include <bluetooth/hci/modechangeevent.h>
       
    42 #include <bluetooth/hci/disconnectcommand.h>
       
    43 #include <bluetooth/hci/disconnectioncompleteevent.h>
       
    44 #include <bluetooth/hci/hciconsts.h>
       
    45 
       
    46 #include <bluetooth/hci/linkkeyrequestreplycommand.h>
       
    47 #include <bluetooth/hci/linkkeyrequestreplynegativecommand.h>
       
    48 #include <btextnotifierspartner.h>
       
    49 
       
    50 #ifdef __FLOG_ACTIVE
       
    51 _LIT8(KLogComponent, LOG_COMPONENT_LINKMGR);
       
    52 #endif
       
    53 
       
    54 #ifdef _DEBUG
       
    55 PANICCATEGORY("plink");
       
    56 #endif
       
    57 
       
    58 static const THCIErrorCode KDefaultRejectReason = EHostSecurityRejection; // see spec Error Codes
       
    59 
       
    60 #ifdef _DEBUG
       
    61 #define __CHECK_CONNECTION_HANDLE(aHandle) __ASSERT_DEBUG(aHandle==iHandle, Panic(EBTLinkMgrConnectionEventInWrongSAP));
       
    62 #else
       
    63 #define __CHECK_CONNECTION_HANDLE(aHandle) aHandle=aHandle; // to suppress warnings
       
    64 #endif
       
    65 
       
    66 CPhysicalLink* CPhysicalLink::NewLC(CPhysicalLinksManager& aConnectionMan, CRegistrySession& aRegSess, const TBTNamelessDevice& aDevice)
       
    67 	{
       
    68 	LOG_STATIC_FUNC
       
    69 	CPhysicalLink* s = new(ELeave) CPhysicalLink(aConnectionMan, aRegSess, aDevice);
       
    70 	CleanupStack::PushL(s);
       
    71 	s->ConstructL();
       
    72 	return s;
       
    73 	}
       
    74 
       
    75 CPhysicalLink* CPhysicalLink::NewL(CPhysicalLinksManager& aConnectionMan, CRegistrySession& aRegSess, const TBTNamelessDevice& aDevice)
       
    76 	{
       
    77 	LOG_STATIC_FUNC
       
    78 	CPhysicalLink* s = NewLC(aConnectionMan, aRegSess, aDevice);
       
    79 	CleanupStack::Pop(s);
       
    80 	return s;
       
    81 	}
       
    82 
       
    83 CPhysicalLink::CPhysicalLink(CPhysicalLinksManager& aConnectionMan, CRegistrySession& aRegSess, const TBTNamelessDevice& aDevice)
       
    84 	: iLinksMan(aConnectionMan)
       
    85 	, iRegSess(aRegSess)
       
    86 	, iDevice(aDevice)
       
    87 	, iHandle(KHCIBroadcastHandle)
       
    88 	, iRemoteFeatures(KInvalidRemoteFeatures)
       
    89 	, iDeviceResult(KDeviceNotObtained)
       
    90 	, iRegistryHelpers(_FOFF(CBTRegistryHelperBase,iLink))
       
    91 	, iProxySAPs(_FOFF(CBTProxySAP, iQueueLink))
       
    92 	, iOverrideParkRequests(EFalse)
       
    93 	, iOverrideLPMRequests(EFalse)
       
    94 	, iLPMOverrideTimerQueued(EFalse)
       
    95 	, iConnectionPacketTypeChanged(EFalse)
       
    96 	, iLowPowModeCtrl(*this, iLinksMan.HCIFacade().CommandQController())
       
    97 	, iDisconnectCtrl(*this, iLinksMan.HCIFacade().CommandQController())
       
    98 	, iAuthenticationCtrl(*this, iLinksMan.HCIFacade().CommandQController())
       
    99 	, iLSTO(0)
       
   100 	, iAutoKeyRefreshQue(_FOFF(XAutoKeyRefreshToken, iQueLink))
       
   101 	, iRemoteDeviceRecordedByStack(ENull)
       
   102 	{
       
   103 	LOG_FUNC
       
   104 	// don't initialise physical link policy just yet - wait until connection completes
       
   105 	// by then we'll have best information to go on
       
   106 	LOG1(_L("New CPhysicalLink [0x%08x]"), this);
       
   107 	}
       
   108 
       
   109 CPhysicalLink::~CPhysicalLink()
       
   110 	{
       
   111 	LOG_FUNC
       
   112 	__ASSERT_DEBUG(iACLLogicalLinks.Count()==0, Panic(EBTACLLogicalLinkBadDebind));
       
   113 	__ASSERT_DEBUG(iSyncLogicalLink == NULL, Panic(EBTSCOLogicalLinkBadDebind));
       
   114 
       
   115 	LOG1(_L("CPhysicalLink Destructing this = 0x%08x"), this);
       
   116 
       
   117 	// tell ConnectionsManager...
       
   118 	iLinksMan.RemovePhysicalLink(*this);
       
   119 	iACLLogicalLinks.Close();
       
   120 
       
   121 	RemoveIdleTimer();
       
   122 	if (iLPMOverrideTimerQueued)
       
   123 		{
       
   124 		BTSocketTimer::Remove(iOverrideLPMTimerEntry);
       
   125 		iLPMOverrideTimerQueued = EFalse;
       
   126 		}
       
   127 
       
   128 	LOG(_L("sec\tClosing subscribers..."))
       
   129 
       
   130 	LOG(_L("sec\tClosing helpers..."))
       
   131 	TSglQueIter<CBTRegistryHelperBase> iter(iRegistryHelpers);
       
   132 	CBTRegistryHelperBase* helper;
       
   133 	// Detach from any Registry Helpers for which this object
       
   134 	// is the parent.
       
   135 	while(iter)
       
   136 		{
       
   137 		helper = iter++;
       
   138 		helper->DetachParent();
       
   139 		}
       
   140 
       
   141 	iLowPowModeCtrl.Abort();
       
   142 	iDisconnectCtrl.Abort();
       
   143 	iAuthenticationCtrl.Abort();
       
   144 
       
   145 	delete iPhysicalLinkMetrics;
       
   146 	delete iPinRequester;
       
   147 	delete iNumericComparator;
       
   148 	delete iPasskeyEntry;
       
   149 	delete iArbitrationDelay;
       
   150 	delete iRoleSwitchCompleteCallBack;
       
   151 	delete iEncryptionEnforcer;
       
   152 
       
   153 	DeleteRoleSwitcher();
       
   154 	}
       
   155 
       
   156 void CPhysicalLink::ConstructL()
       
   157 	{
       
   158 	LOG_FUNC
       
   159 	LOG1(_L("CPhysicalLink::ConstructL() this = 0x%08x"), this);
       
   160 	GetDeviceFromRegistryL();
       
   161 	iArbitrationDelay = CArbitrationDelayTimer::NewL(this);
       
   162 
       
   163 	TCallBack cb1(RoleSwitchCompleteCallBack, this);
       
   164 	iRoleSwitchCompleteCallBack = new (ELeave)CAsyncCallBack(cb1, EActiveHighPriority);
       
   165 
       
   166 	TCallBack cb2(OverrideLPMTimeoutCallback, this);
       
   167 	iOverrideLPMTimerEntry.Set(cb2);
       
   168 
       
   169 	iPhysicalLinkMetrics = CPhysicalLinkMetrics::NewL(*this, iLinksMan.HCIFacade().CommandQController());
       
   170 	}
       
   171 
       
   172 TBool CPhysicalLink::HasHandle(THCIConnHandle aHandle) const
       
   173 	{
       
   174 	LOG_FUNC
       
   175 	if (iHandle == aHandle)
       
   176 		return ETrue;	// Only one ACL handle is available.
       
   177 	if (iSyncLogicalLink && iSyncLogicalLink->Handle() == aHandle)
       
   178 		return ETrue;
       
   179 	return EFalse;
       
   180 	}
       
   181 
       
   182 TBool CPhysicalLink::HasSyncLink() const
       
   183 	{
       
   184 	LOG_FUNC
       
   185 	return (iSyncLogicalLink != NULL);
       
   186 	}
       
   187 
       
   188 void CPhysicalLink::SubscribeLinkObserver(MPhysicalLinkObserver& aObserver)
       
   189 /**
       
   190 The subscribed object will be notified whenever a link state change occurs.
       
   191 **/
       
   192 	{
       
   193 	LOG_FUNC
       
   194 #ifdef _DEBUG
       
   195 	//ensure the subscriber isn't already subscribed...
       
   196 	TInt found = 0;
       
   197 	TDblQueIter<MPhysicalLinkObserver> iter(iBasebandSubscribers);
       
   198 	while (iter)
       
   199 		{
       
   200 		if (iter++ == &aObserver)
       
   201 			{
       
   202 			found++;
       
   203 			}
       
   204 		}
       
   205 
       
   206 	__ASSERT_DEBUG(found==0, Panic(ELinkMgrBadBasebandArray));
       
   207 #endif	//_DEBUG
       
   208 
       
   209 	iBasebandSubscribers.AddFirst(aObserver.ObserverQLink());
       
   210 	}
       
   211 
       
   212 void CPhysicalLink::UnsubscribeLinkObserver(MPhysicalLinkObserver& aObserver)
       
   213 /**
       
   214 aSubscriber will no longer be notified of state changes.
       
   215 **/
       
   216 	{
       
   217 	LOG_FUNC
       
   218 	aObserver.ObserverQLink().Deque();
       
   219 	}
       
   220 
       
   221 TInt CPhysicalLink::TryToAndThenPreventHostEncryptionKeyRefresh(TAny* aOutToken)
       
   222 	{
       
   223 	LOG_FUNC
       
   224 	TInt err = KErrNone;
       
   225 	// The handling of the TAny* parameter seems a bit wacky - but it makes sense as follows
       
   226 	// this call handles a call from the bluetooth control plane (which passes
       
   227 	// only a TAny* as a parameter).  We need to return a value back through as well, so we need
       
   228 	// a pointer to a pointer (so after using the input it can be modified to point to the
       
   229 	// output).  We need a Bluetooth device address so a pointer to a pointer to a TBTDevAddr 
       
   230 	// is passed down. Then the pointer to a pointer is used to update the pointer to a control
       
   231 	// plane token (which represents a handle preventing host encryption key refreshes).
       
   232 	if (!IsEncryptionPauseResumeSupported())
       
   233 		{
       
   234 		err = KErrNotSupported;
       
   235 		*reinterpret_cast<MBluetoothControlPlaneToken**>(aOutToken) = NULL;
       
   236 		}
       
   237 	else
       
   238 		{
       
   239 		if (iAutoKeyRefreshQue.IsEmpty())
       
   240 			{
       
   241 			TRAP_IGNORE(iLinksMan.HCIFacade().RefreshEncryptionKeyL(iHandle));
       
   242 			// If we can't refresh the encryption key, there's not much we can do
       
   243 			}
       
   244 		XAutoKeyRefreshToken* token = new XAutoKeyRefreshToken();
       
   245 		if (token)
       
   246 			{
       
   247 			iAutoKeyRefreshQue.AddLast(*token);
       
   248 			}
       
   249 		else
       
   250 			{
       
   251 			err = KErrNoMemory;
       
   252 			}
       
   253 		*reinterpret_cast<MBluetoothControlPlaneToken**>(aOutToken) = token;
       
   254 		}
       
   255 	return err;
       
   256 	}
       
   257 
       
   258 void CPhysicalLink::RegistryTaskComplete(CBTRegistryHelperBase* aHelper, TInt /*aResult*/)
       
   259 /**
       
   260 	A task has completed where we don't expect a response - just cleanup helper
       
   261 **/
       
   262 	{
       
   263 	LOG_FUNC
       
   264 	// remove from array
       
   265 	iRegistryHelpers.Remove(*aHelper);
       
   266 	// delete
       
   267 	delete aHelper;
       
   268 	}
       
   269 
       
   270 /**
       
   271 The completion function of a registry helper returning a remote device entry.
       
   272 */
       
   273 void CPhysicalLink::RegistryTaskComplete(CBTRegistryHelperBase* aHelper,
       
   274 										 const TBTNamelessDevice& aDevice,
       
   275 										 TInt aResult)
       
   276 /**
       
   277 	A registry task has completed where we expect a device to be returned
       
   278 **/
       
   279 	{
       
   280 	LOG_FUNC
       
   281 	LOG1(_L("CPhysicalLink: Registry task complete; result %d"), aResult);
       
   282 
       
   283 	// The TBTNamelessDevice assignment operator only performs an update on valid
       
   284 	// entries, as we need a bitwise copy (since we want to mirror what is in the registry)
       
   285 	// we need to go to these extras steps.
       
   286 	TPckg<TBTNamelessDevice> cachedVersion(iRegistryDevice);
       
   287 	cachedVersion.Copy(TPckg<TBTNamelessDevice>(aDevice));
       
   288 
       
   289 	// We have to be careful about information flow from the registry to the actual representation (iDevice).
       
   290 	// Although the values in the returned entry are useful if the stack has not yet got the information,
       
   291 	// if the stack has already gathered values then they will be more up-to-date.  Therefore we need to
       
   292 	// assign the current values first if they are valid to build up the latest representation.
       
   293 	TBTNamelessDevice device = aDevice; // Take a local copy to work on.
       
   294 	if(iDevice.IsValidDeviceClass())
       
   295 		{
       
   296 		device.SetDeviceClass(iDevice.DeviceClass());
       
   297 		}
       
   298 	if(iDevice.IsValidPageScanRepMode())
       
   299 		{
       
   300 		device.SetPageScanRepMode(iDevice.PageScanRepMode());
       
   301 		}
       
   302 	if(iDevice.IsValidPageScanPeriodMode())
       
   303 		{
       
   304 		device.SetPageScanPeriodMode(iDevice.PageScanPeriodMode());
       
   305 		}
       
   306 	if(iDevice.IsValidPageScanMode())
       
   307 		{
       
   308 		device.SetPageScanMode(iDevice.PageScanMode());
       
   309 		}
       
   310 	if(iDevice.IsValidClockOffset())
       
   311 		{
       
   312 		device.SetClockOffset(iDevice.ClockOffset());
       
   313 		}
       
   314 	if(iDevice.IsValidUsed())
       
   315 		{
       
   316 		device.SetUsed(iDevice.Used());
       
   317 		}
       
   318 	if(iDevice.IsValidSeen())
       
   319 		{
       
   320 		device.SetSeen(iDevice.Seen());
       
   321 		}
       
   322 
       
   323 	// With the link key (and friends) we need to be even more careful, as there is effectively
       
   324 	// two-way flow of information:
       
   325 	// 1) Link key storage from the stack.
       
   326 	// 2) Unbonding from the clients of the registry.
       
   327 	// Further to this, if the registry entry does not have a link key, it can mean one of several
       
   328 	// things:
       
   329 	// a) No link key has been generated with the remote device yet.
       
   330 	// b) A client of the registry has unbonded the remote device.
       
   331 	// c) The current link key is not to form a bond.
       
   332 	// Taking this into account we make a suitable choice about what to do.
       
   333 	if(!iDevice.IsValidLinkKey())
       
   334 		{
       
   335 		// If there isn't any link key in the system yet - and so it is safe to update the representation
       
   336 		// to use the value from the registry.
       
   337 		// <NOP> - see the global update below.
       
   338 		}
       
   339 	else
       
   340 		{
       
   341 		// We currently have a link key....
       
   342 		if(device.IsValidLinkKey() || iRegistryDevBeingMod.InUse())
       
   343 			{
       
   344 			// Even if the linkkey in registry is valid, it must be older or same as the current
       
   345 			// link key (as the stack is the only one who should be adding keys). Also, if we are in the
       
   346 			// middle of updating the registry (for any purpose) then we can ignore the registry value as it
       
   347 			// may not be up-to date. So, for both the cases just update with the latest.
       
   348 			// There is an interesting case if client modifies the registry by unpairing/or deleting the device
       
   349 			// and stack also tries to updates the link key in registry at the same time. We will give priority
       
   350 			// to stack's updations by keeping the latest copy as it is.
       
   351 			device.SetLinkKey(iDevice.LinkKey(), iDevice.LinkKeyType());
       
   352 			if(iDevice.IsValidPassKey())
       
   353 				{
       
   354 				device.SetPassKey(iDevice.PassKey());
       
   355 				}
       
   356 			}
       
   357 		else
       
   358 			{
       
   359 			// This is the interesting case where a client has unbonded, but we already have a link
       
   360 			// key.  What we do here is interesting.
       
   361 			if(IsAuthenticationPending() || LinkState().Authenticated() || SimplePairingMode() == EPhySimplePairingEnabled)
       
   362 
       
   363 				{
       
   364 				// If we're already authenticated / authenticating then we're already using our link
       
   365 				// key.  As such we need to continue using it, but we don't want to update
       
   366 				// Also if the link is SSP enabled then we can re-authenticate - this removes any chance of a
       
   367  				// race condition with the registry.
       
   368 				iPreventLinkKeyUpdateReg = ETrue; // prevent locally cached link key being given back to the registry
       
   369 				}
       
   370 			else
       
   371 				{
       
   372 				// The link key hasn't been used yet - so we can update the representation to not
       
   373 				// have a link key (as requested by the user).
       
   374 				// Currently there is no chance of a race with the registry as combination link keys are
       
   375  				// always form a bond.
       
   376 				iDevice.DeleteLinkKey(); // delete locally cached link key
       
   377 				}
       
   378 			}
       
   379 		}
       
   380 
       
   381 	// Finally update the representation - we should have manipulated it correctly.
       
   382 	iDevice = device;
       
   383 
       
   384 	// Store the result of the retrieval for usage later.
       
   385 	iDeviceResult = aResult;
       
   386 
       
   387 	// the HW asked earlier for a link key - we can respond now
       
   388 	__ASSERT_DEBUG(iDevice.IsValidAddress(), Panic(EBTPhysicalLinksInvalidAddress));
       
   389 	if(iWaitingForLinkKeyFromRegistry)
       
   390 		{
       
   391 		if (aResult == KErrNone && iDevice.IsValidLinkKey())
       
   392 			{
       
   393 			if ( iDevice.LinkKeyType() != ELinkKeyCombination)
       
   394 				{
       
   395 				if (iLinksMan.SecMan().DebugMode() && iDevice.LinkKeyType() != ELinkKeyDebug)
       
   396 					{
       
   397 					LOG(_L("CPhysicalLink: Debug mode - Link to debug link key"))
       
   398 					iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address());
       
   399 					}
       
   400 				else
       
   401 				if (iRequireAuthenticatedLinkKey && iDevice.LinkKeyType() == ELinkKeyUnauthenticatedUpgradable && IsPairable())
       
   402 					{
       
   403 					LOG(_L("CPhysicalLink: Requiring Authenticated link key but currently only have unauthenticated"))
       
   404 					iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address());
       
   405 					}
       
   406 				else
       
   407 					{
       
   408 					LOG(_L("CPhysicalLink: Issuing link key to HC now"))
       
   409 					iAuthenticationCtrl.LinkKeyRequestReply(iDevice.Address(), iDevice.LinkKey());
       
   410 					}
       
   411 				}
       
   412 			else if(IsPasskeyMinLengthOK() && SimplePairingMode() != EPhySimplePairingEnabled)
       
   413 				{
       
   414 				LOG(_L("CPhysicalLink: Issuing link key to HC now"))
       
   415 				iAuthenticationCtrl.LinkKeyRequestReply(iDevice.Address(), iDevice.LinkKey());
       
   416 				}
       
   417 			else
       
   418 				{
       
   419 				LOG(_L("CPhysicalLink: Current PIN code too short!"))
       
   420 				iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address());
       
   421 				}
       
   422 			}
       
   423 		else
       
   424 			{
       
   425 			iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address());
       
   426 			}	
       
   427 		}
       
   428 	iRequireAuthenticatedLinkKey = EFalse;
       
   429 	iWaitingForLinkKeyFromRegistry = EFalse;
       
   430 
       
   431 	RegistryTaskComplete(aHelper, aResult);	 // cleans up our helper
       
   432 	}
       
   433 
       
   434 void CPhysicalLink::RegistryTaskComplete(CBTRegistryHelperBase* aHelper, TRegistryUpdateStatus aRegUpdateStatus, TInt aResult)
       
   435 	{
       
   436 /**
       
   437 	This method allows the RegistryHelpers to indicate the registry action taking place
       
   438 
       
   439 **/
       
   440 	LOG_FUNC
       
   441 	if(iRemoteDeviceRecordedByStack == EPending && aRegUpdateStatus != ENoChange)
       
   442 		{
       
   443 		if (aResult == KErrNone)
       
   444 			{
       
   445 			iRemoteDeviceRecordedByStack = EComplete;
       
   446 			}
       
   447 		else
       
   448 			{
       
   449 			iRemoteDeviceRecordedByStack = ENull;
       
   450 			}
       
   451 		}
       
   452 
       
   453 	iRegistryDevBeingMod.RequestCompleted();
       
   454 	RegistryTaskComplete(aHelper, aResult);	 // cleans up our helper
       
   455 	}
       
   456 
       
   457 void CPhysicalLink::CompletedPackets(THCIConnHandle aConnH, TUint16 aNumPackets)
       
   458 /**
       
   459 	In this domain we are happy that a valid event has come in telling us that
       
   460 	the buffers in the local controller have been freed
       
   461 
       
   462 	Since this reflects both local hardware features (buffers) and flow control
       
   463 	we treat them separately
       
   464 
       
   465 **/
       
   466 	{
       
   467 	LOG_FUNC
       
   468 	// firstly report that local hardware buffers free (via inlines!)
       
   469 	iLinksMan.LinkManagerProtocol().LinkMuxer().DataQController().CompletedPackets(aConnH, aNumPackets);
       
   470 
       
   471 	// we forward this to the thing that sends the packets so that they can do Flow Control
       
   472 
       
   473 	// could speed up - already done this handle test to get into *this* object
       
   474 	if (iSyncLogicalLink && iSyncLogicalLink->Handle() == aConnH)
       
   475 		{
       
   476 		iSyncLogicalLink->PacketsSent(aConnH, aNumPackets);
       
   477 		}
       
   478 	else
       
   479 		{
       
   480 		for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--)
       
   481 			{
       
   482 			iACLLogicalLinks[i]->PacketsSent(aConnH, aNumPackets);
       
   483 			}
       
   484 		}
       
   485 	}
       
   486 
       
   487 void CPhysicalLink::TryToSend()
       
   488 	{
       
   489 	LOG_FUNC
       
   490 	for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--)
       
   491 		{
       
   492 		iACLLogicalLinks[i]->TryToSend();
       
   493 		}
       
   494 	}
       
   495 
       
   496 void CPhysicalLink::NewLinkKey(const TBTDevAddr& /*aAddr*/, const TBTLinkKey& aLinkKey, THCILinkKeyType aLinkKeyType)
       
   497 	{
       
   498 	LOG_FUNC
       
   499 	if(iLinkKeyPending)
       
   500 		//user has entered a PIN and a new link key has come in.
       
   501 		{
       
   502 		iLinkKeyPending = EFalse;
       
   503 		iPreventLinkKeyUpdateReg = EFalse; //override previous unpair so that link key will be stored in the registry.
       
   504 		}
       
   505 
       
   506 	TBTLinkKeyType linkKeyType = ELinkKeyCombination;
       
   507 
       
   508 	switch (aLinkKeyType)
       
   509 		{
       
   510 	case ECombinationKey:
       
   511 		linkKeyType = ELinkKeyCombination;
       
   512 		break;
       
   513 	case EDebugCombinationKey:
       
   514 		linkKeyType = ELinkKeyDebug;
       
   515 		break;
       
   516 	case EAuthenticatedCombinationKey:
       
   517 		linkKeyType = ELinkKeyAuthenticated;
       
   518 		break;
       
   519 	case EUnauthenticatedCombinationKey:
       
   520 		if (iLocalMITM || (iAuthenticationRequirement & KAuthenticationMitmReqMask) ||
       
   521 			(iIOCapability == EIOCapsDisplayOnly) || (iIOCapability == EIOCapsNoInputNoOutput))
       
   522 			{
       
   523 			linkKeyType = ELinkKeyUnauthenticatedNonUpgradable;
       
   524 			}
       
   525 		else
       
   526 			{
       
   527 			linkKeyType = ELinkKeyUnauthenticatedUpgradable;
       
   528 			}
       
   529 		break;
       
   530 	case EChangedCombinationKey:
       
   531 		linkKeyType = iDevice.LinkKeyType(); // The link key type hasn't changed
       
   532 		break;
       
   533 
       
   534 	case ELocalUnitKey:
       
   535 	case ERemoteUnitKey:
       
   536 	default:
       
   537 		LOG1(_L("CPhysicalLink: Unexpected link key type (%d)"), aLinkKeyType);
       
   538 		__ASSERT_DEBUG(EFalse, Panic(EBTUnexpectedLinkKeyType));
       
   539 		break;
       
   540 		}
       
   541 
       
   542 	if (linkKeyType == ELinkKeyCombination && iNewPinCodeValid)
       
   543 		{
       
   544 		// Only bind a PIN code to the device if we receive a link key based on it.
       
   545 		iNewPinCodeValid = EFalse;
       
   546 		iDevice.SetPassKey(iNewPinCode);
       
   547 		}
       
   548 
       
   549 
       
   550 	SetLinkKey(aLinkKey, linkKeyType);	// keeps a copy in our 'cache', updates paired list in PHYs mananger
       
   551 
       
   552 	TRAP_IGNORE(StoreDeviceL(EFalse)); //EFalse: new meaning - do not prevent addition
       
   553 	// if that errored we just have to keep it here - but it won't be in registry
       
   554 	// so it'll be a transient pairing
       
   555 	}
       
   556 
       
   557 void CPhysicalLink::UpdateFromInquiryCache()
       
   558 	{
       
   559 	LOG_FUNC
       
   560 	CBTInqResultRecord* juice = NULL; //juice is data from remote which can help/speed up a connection
       
   561 	// see if we can speed up the connection - the inquiry cache may have some juice
       
   562 	juice = iLinksMan.LinkManagerProtocol().InquiryMgr().BasebandParametersFromCache(iDevice.Address());
       
   563 	if(!juice)
       
   564 	//no juice in inquiry manager
       
   565 		{
       
   566 		return;
       
   567 		}
       
   568 
       
   569 	TInquiryLogEntry& jle = juice->LogEntry();
       
   570 	// Inquiry cache may have useful info we can use: put them in our device
       
   571 	// so that we can use this, and update this into the Registry later.
       
   572 	// This will allow Apps to get this to initiate faster connections.
       
   573 	// The update to the Registry doesn't happen here, but at other interesting times
       
   574 	ASSERT_DEBUG(jle.iBdaddr == iDevice.Address());
       
   575 	//Only update with juice values from inquiry manager if they are have come from HCI
       
   576 	//(i.e. from remote) - records in the inquiry manager are filled with default
       
   577 	//values and then fields are updated as relevant HCI events occur.
       
   578 	// - iDevice may already contain values found in the registry which are
       
   579 	//not default and therefore should have come themselves from the HCI
       
   580 	if(juice->IsPageScanModeFromHCI())
       
   581 		{
       
   582 		iDevice.SetPageScanMode(jle.iPageScanMode);
       
   583 		}
       
   584 	if(juice->IsPageScanRepModeFromHCI())
       
   585 		{
       
   586 		iDevice.SetPageScanRepMode(jle.iPageScanRepetitionMode);
       
   587 		}
       
   588 	if(juice->IsClockOffsetFromHCI())
       
   589 		{
       
   590 		iDevice.SetClockOffset(jle.iClockOffset);
       
   591 		}
       
   592 	}
       
   593 
       
   594 void CPhysicalLink::StoreDeviceL( TBool aPreventDeviceAddition )
       
   595 	{
       
   596 	LOG_FUNC
       
   597 
       
   598 	UpdateFromInquiryCache(); //check juice has not just come in - update iDevice if so
       
   599 
       
   600 	//only write back the necessary attributes
       
   601 	TBTNamelessDevice device;
       
   602 	if(iDevice.IsValidAddress())
       
   603 		{
       
   604 		device.SetAddress(iDevice.Address());
       
   605 		}
       
   606 	if(iDevice.IsValidDeviceClass())
       
   607 		{
       
   608 		device.SetDeviceClass(iDevice.DeviceClass());
       
   609 		}
       
   610 	if(iDevice.IsValidLinkKey() && !iPreventLinkKeyUpdateReg)
       
   611 		{
       
   612 		if(!(iIOCapsReceived && (iAuthenticationRequirement == EMitmNotReqNoBonding || iAuthenticationRequirement == EMitmReqNoBonding)))
       
   613 			{
       
   614 			LOG(_L("!!! Storing Link Key in Registry"));
       
   615 			device.SetLinkKey(iDevice.LinkKey(), iDevice.LinkKeyType());
       
   616 			}
       
   617 		}
       
   618 	if(iDevice.IsValidPageScanRepMode())
       
   619 		{
       
   620 		device.SetPageScanRepMode(iDevice.PageScanRepMode());
       
   621 		}
       
   622 	if(iDevice.IsValidPageScanPeriodMode())
       
   623 		{
       
   624 		device.SetPageScanPeriodMode(iDevice.PageScanPeriodMode());
       
   625 		}
       
   626 	if(iDevice.IsValidPageScanMode())
       
   627 		{
       
   628 		device.SetPageScanMode(iDevice.PageScanMode());
       
   629 		}
       
   630 	if(iDevice.IsValidClockOffset())
       
   631 		{
       
   632 		device.SetClockOffset(iDevice.ClockOffset());
       
   633 		}
       
   634 	if(iDevice.IsValidUsed())
       
   635 		{
       
   636 		device.SetUsed(iDevice.Used());
       
   637 		}
       
   638 	if(iDevice.IsValidSeen())
       
   639 		{
       
   640 		device.SetSeen(iDevice.Seen());
       
   641 		}
       
   642 	if(iDevice.IsValidPassKey())
       
   643 		{
       
   644 		device.SetPassKey(iDevice.PassKey());
       
   645 		}
       
   646 
       
   647 	// if already exists an outstanding request with the same device info
       
   648 	// is useless to store it again. Just return doing nothing.
       
   649 	if (iRegistryDevBeingMod.InUse() && iRegistryDevBeingMod.IsEqual(device))
       
   650 		{
       
   651 		return;	// do nothing
       
   652 		}
       
   653 
       
   654 	CBTDeviceModifier* modifier = CBTDeviceModifier::NewL(iRegSess, *this, iLinksMan.LinkManagerProtocol().InquiryMgr());
       
   655 	iRegistryHelpers.AddLast(*modifier);
       
   656 	TBool allowAdd = EFalse;
       
   657 
       
   658 	if(!aPreventDeviceAddition && iRemoteDeviceRecordedByStack == ENull)
       
   659 		//Only allow the device to be added to the registry if
       
   660 		// 1) this StoreDeviceL function has not been called
       
   661 		//	  with its "prevent device addition" parameter set to true
       
   662 		// 2) we believe the cached remote device details have not yet
       
   663 		//    been recorded in the registry.
       
   664 		//    (If they have and if they are no longer there it is
       
   665 		// 	   because an app has deleted them from the registry...
       
   666 		//	   so we should not re-add them )
       
   667 		{
       
   668 		allowAdd = ETrue;
       
   669 		}
       
   670 	modifier->Start(device, allowAdd);
       
   671 	iRegistryDevBeingMod.Begin(device);
       
   672 
       
   673 	if(allowAdd)
       
   674 		//The physical link object has now made its attempt to add its cached
       
   675 		//remote device details to the registry.
       
   676 		{
       
   677 		iRemoteDeviceRecordedByStack = EPending;
       
   678 		}
       
   679 
       
   680 	}
       
   681 
       
   682 void CPhysicalLink::SetLinkKey(const TBTLinkKey& aLinkKey, TBTLinkKeyType aLinkKeyType)
       
   683 	{
       
   684 	LOG_FUNC
       
   685 	iDevice.SetLinkKey(aLinkKey, aLinkKeyType); // keeps a copy in our 'cache'
       
   686 	}
       
   687 
       
   688 void CPhysicalLink::ReadRemoteSupportedFeaturesComplete(THCIErrorCode aErr, THCIConnHandle aConnH, const TBTFeatures& aBitMask)
       
   689 	{
       
   690 	LOG_FUNC
       
   691 	__CHECK_CONNECTION_HANDLE(aConnH);
       
   692 
       
   693 	if (aErr == KErrNone)
       
   694 		{
       
   695 		iRemoteFeatures = aBitMask;
       
   696 
       
   697 		if(!iConnectionPacketTypeChanged)
       
   698 			{
       
   699 			//Send change connection packet type HCI command if application hasn't, we have to do this
       
   700 			//because some hardware defaults to using 1-slot packets unless told otherwise by the host.
       
   701 			ChangeConnectionPacketType(EAnyACLPacket);
       
   702 			}
       
   703 
       
   704 		//If remote host supports extended features, then send request to read these.
       
   705 		if (iRemoteFeatures[ESupportedExtendedFeaturesBit])
       
   706 			{
       
   707 			TRAP_IGNORE(iLinksMan.HCIFacade().ReadRemoteExtendedFeaturesL(iHandle, KRemoteExtendedFeaturesPage1));
       
   708 			}
       
   709 		else
       
   710 			{
       
   711 			// If the remote doesn't support extended features, then neither they support SSP
       
   712 			// (no way to indicate the host supported bit).  So set it as disabled.
       
   713 			TPhysicalLinkSimplePairingMode previousSetting = SimplePairingMode();
       
   714 			__ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingDisabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection));
       
   715 			iSimplePairingMode = EPhySimplePairingDisabled;
       
   716 			if(SimplePairingMode() != previousSetting)
       
   717 				{
       
   718 				iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr());
       
   719 				}
       
   720 			}
       
   721 		}
       
   722 	else
       
   723 		{
       
   724 		iRemoteFeatures = TBTFeatures(KInvalidRemoteFeatures);
       
   725 		}
       
   726 	}
       
   727 
       
   728 void CPhysicalLink::ReadRemoteExtendedFeaturesComplete(THCIErrorCode aErr, THCIConnHandle aConnH, TUint64 aBitMask, TUint8 aPageNumber, TUint8 /* aMaximumPageNumber */)
       
   729 	{
       
   730 	LOG_FUNC
       
   731 	__CHECK_CONNECTION_HANDLE(aConnH);
       
   732 
       
   733 	LOG1(_L("CPhysicalLink: ReadRemoteExtendedFeaturesComplete; result %d"), aErr);
       
   734 
       
   735 	switch (aPageNumber)
       
   736 		{
       
   737 		case KRemoteExtendedFeaturesPage1:
       
   738 			{
       
   739 			TPhysicalLinkSimplePairingMode currentSetting = SimplePairingMode();
       
   740 
       
   741 			if (aErr == EOK && aBitMask & (1 << ESecureSimplePairingHostSupportBit) && iLinksMan.SecMan().LocalSimplePairingMode())
       
   742 				{
       
   743 				__ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingEnabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection));
       
   744 				iSimplePairingMode = EPhySimplePairingEnabled;
       
   745 				}
       
   746 			else
       
   747 				{
       
   748 				__ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingDisabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection));
       
   749 				iSimplePairingMode = EPhySimplePairingDisabled;
       
   750 				}
       
   751 			if(SimplePairingMode()!=currentSetting)
       
   752 				{
       
   753 				iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr());
       
   754 				}			
       
   755 			break;
       
   756 			}
       
   757 		default:
       
   758 			{
       
   759 			// Ignore
       
   760 			}
       
   761 		}
       
   762 	}
       
   763 
       
   764 void CPhysicalLink::ReadRemoteVersionInfoComplete(THCIErrorCode aErr, THCIConnHandle aConnH, const TBTDevRemoteHwVersion& aVer)
       
   765 	{
       
   766 	LOG_FUNC
       
   767 	__CHECK_CONNECTION_HANDLE(aConnH);
       
   768 	if (aErr == KErrNone)
       
   769 		{
       
   770 		iRemoteVersion = aVer;
       
   771 		}
       
   772 	else
       
   773 		{
       
   774 		iRemoteVersion = KInvalidRemoteHwVersion;
       
   775 		}
       
   776 	}
       
   777 
       
   778 void CPhysicalLink::AuthenticationComplete(THCIErrorCode aErr, THCIConnHandle aConnH)
       
   779 	{
       
   780 	LOG_FUNC
       
   781 	__CHECK_CONNECTION_HANDLE(aConnH);
       
   782 	iLinkState.SetAuthenticated(aErr == EOK);
       
   783 	//__ASSERT_DEBUG(iAuthStateMask == EAuthenticationRequestPending,Panic(EUnexpectedAuthenticationState));
       
   784 	AuthenticationComplete(EAuthenticationRequestPending);
       
   785 
       
   786 	if (aErr!=EOK)
       
   787 		{
       
   788 		if(aErr == ERemoteUserEndedConnection)
       
   789 			{
       
   790 			HandlePrefetch();
       
   791 			}
       
   792 		iNewPinCodeValid = EFalse;
       
   793 		delete iPinRequester;
       
   794 		iPinRequester = NULL;
       
   795 		iPinHandler = NULL;
       
   796 		}
       
   797 	else
       
   798 		{
       
   799 		__ASSERT_DEBUG(!iPinHandler, Panic(EBTPhysicalLinkPinHandlerStillPresent));
       
   800 		}
       
   801 
       
   802 	iLinksMan.SecMan().AuthenticationComplete(BDAddr(), aErr);
       
   803 
       
   804 	TBTBasebandEventNotification event(ENotifyAuthenticationComplete, aErr);
       
   805 	NotifyStateChange(event);
       
   806 	}
       
   807 
       
   808 void CPhysicalLink::HandlePrefetch()
       
   809 	{
       
   810 	// Here we determine whether we need to handle a pre-fetch case.  If there is an
       
   811 	// outbound authentication attempt and we have a PIN notifier we need to hand it
       
   812 	// over to the pre-fetch manager.
       
   813 	// We also note the fact that we've done this for any access requester to know whether
       
   814 	// it should indicate to defer.
       
   815 	if(iPinRequester && iLinksMan.SecMan().IsOutboundAccessRequest(BDAddr()) && iSimplePairingMode != EPhySimplePairingEnabled)
       
   816 		{
       
   817 		TInt err = iLinksMan.PrefetchMan().HandleOverPinRequester(BDAddr(), iPinRequester);
       
   818 		if(err == KErrNone)
       
   819 			{
       
   820 			iPinRequester = NULL; // As far as phys links is concerned the pin requester doesn't exist anymore.
       
   821 			iPinHandler = NULL; // So the handler is also not needed.
       
   822 			}
       
   823 		}
       
   824 	}
       
   825 
       
   826 void CPhysicalLink::EncryptionChange(THCIErrorCode aErr, THCIConnHandle aConnH, TBool aEncrypted)
       
   827 	{
       
   828 	LOG_FUNC
       
   829 	__CHECK_CONNECTION_HANDLE(aConnH);
       
   830 
       
   831 	if(aErr == EOK)
       
   832 		{
       
   833 		// Only change state if it's an actual encryption change - not an error (because if an error
       
   834 		// we should presumably stay the same).
       
   835 		if(aEncrypted)
       
   836 			{
       
   837 			iLinkState.SetEncrypted(ETrue);
       
   838 			if(!iLinkState.Authenticated())
       
   839 				{
       
   840 				// If a link is encrypted then we know that the link is also authenticated.
       
   841 				iLinkState.SetAuthenticated(ETrue);
       
   842 				}
       
   843 			}
       
   844 		else
       
   845 			{
       
   846 			iLinkState.SetEncrypted(EFalse);
       
   847 			}
       
   848 		}
       
   849 
       
   850 	TBTBasebandEventNotification event(aEncrypted ? ENotifyEncryptionChangeOn : ENotifyEncryptionChangeOff, aErr);
       
   851 	NotifyStateChange(event);
       
   852 
       
   853 	// Having the encryption enforcer present means that we have asked for encryption.
       
   854 	// But we should only act if this is a valid encryption change event.
       
   855 	if (iEncryptionEnforcer && aErr == EOK)
       
   856 		{
       
   857 		// if the roleswitch has been requested by us then CRoleSwitcher has already parked / unparked
       
   858 		// the ACL controller. That means that the request is submitted twice.
       
   859 		// This is not supposed to be a problem, but we need to be aware of it.
       
   860 		if (!aEncrypted)
       
   861 			{
       
   862 			iLinksMan.LinkManagerProtocol().ACLController().SetParked(iHandle, ETrue);
       
   863 			iEncryptionEnforcer->EncryptionDisabled(SimplePairingMode()== EPhySimplePairingEnabled);
       
   864 			}
       
   865 		else
       
   866 			{
       
   867 			iLinksMan.LinkManagerProtocol().ACLController().SetParked(iHandle, EFalse);
       
   868 			iEncryptionEnforcer->EncryptionEnabled();
       
   869 			}
       
   870 		}
       
   871 	}
       
   872 
       
   873 TInt CPhysicalLink::ChangeEncryption(THCIEncryptModeFlag aEnable)
       
   874 	{
       
   875 	LOG_FUNC
       
   876 	// no policy to adjust, but test local & remote features
       
   877 	if (!IsEncryptionSupported())
       
   878 		{
       
   879 		return KErrNotSupported;
       
   880 		}
       
   881 
       
   882 	TRAPD(err, iLinksMan.HCIFacade().SetEncryptL(Handle(), aEnable));
       
   883 	if (err == KErrNone)
       
   884 		{
       
   885 		err = ManageEncryptionEnforcement(aEnable);
       
   886 		}
       
   887 
       
   888 	return err;
       
   889 	}
       
   890 
       
   891 TInt CPhysicalLink::Authenticate(TBool aRequireAuthenticatedLinkKey)
       
   892 	{
       
   893 	LOG_FUNC
       
   894 	// no policy to adjust, just check to see if the link is already authenticated
       
   895 	TInt err = KErrNone;
       
   896 	__ASSERT_DEBUG(iSimplePairingMode != EPhySimplePairingUndefined, Panic(EBTPhysicalLinksInvalidArgument));
       
   897 
       
   898 	/* If its a dedicated bonding attempt, then we always want to authenticate again in order to generate
       
   899 	 * a stronger linkkey if possible
       
   900 	 */
       
   901 	if (!iLinksMan.SecMan().IsDedicatedBondingAttempted(iDevice.Address()) && iLinkState.Authenticated() && !iLinksMan.LinkManagerProtocol().IsSecureSimplePairingSupportedLocally())
       
   902 		{
       
   903 		err = KErrAlreadyExists;
       
   904 		}
       
   905 	else
       
   906 		{
       
   907 		iRequireAuthenticatedLinkKey = aRequireAuthenticatedLinkKey;
       
   908 		TRAP(err, iLinksMan.HCIFacade().AuthenticateL(Handle()));
       
   909 		if(err == KErrNone)
       
   910 			{
       
   911 			SetAuthenticationPending(EAuthenticationRequestPending);
       
   912 			}
       
   913 		}
       
   914 	return err;
       
   915 	}
       
   916 
       
   917 TInt CPhysicalLink::ChangeLinkKey()
       
   918 	{
       
   919 	LOG_FUNC
       
   920 	__ASSERT_DEBUG(iLinkState.Authenticated(), Panic(EBTPhysicalLinkNotAuthenticated));
       
   921 
       
   922 	// Check if the peer device can support the link key regeneration procedure.
       
   923 	if(PeerSupportsLinkKeyRegeneration())
       
   924 		{
       
   925 		return iLinksMan.HCIFacade().ChangeConnectionLinkKey(Handle());
       
   926 		}
       
   927 	return KErrNone;
       
   928 	}
       
   929 
       
   930 TBool CPhysicalLink::PeerSupportsLinkKeyRegeneration() const
       
   931 	{
       
   932 	LOG_FUNC
       
   933 	// Any future manufacturers or manufacturer versions that do not support
       
   934 	// link key re-generation should be added to this method.
       
   935 
       
   936 	// See Bluetooth assigned numbers for an explanation of this value.
       
   937 	return (iRemoteVersion.iManufacturerID != 0x000a);
       
   938 	}
       
   939 
       
   940 void CPhysicalLink::ACLDataReceived(THCIConnHandle aConnH, TUint8 aFlag, const TDesC8& aData)
       
   941 	{
       
   942 	LOG_FUNC
       
   943 	__CHECK_CONNECTION_HANDLE(aConnH);
       
   944 
       
   945 	// there may be a race condition in that we have got ACL data but just started
       
   946 	// shutdown procedures...
       
   947 
       
   948 	// find the ACL wanting this type of data...
       
   949 	for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--)
       
   950 		{
       
   951 		iACLLogicalLinks[i]->DataReceived(aConnH, aFlag, aData);
       
   952 		}
       
   953 	// else just dump
       
   954 	}
       
   955 
       
   956 void CPhysicalLink::SCODataReceived(THCIConnHandle aConnH, const TDesC8& aData)
       
   957 	{
       
   958 	LOG_FUNC
       
   959 	if (iSyncLogicalLink)
       
   960 		iSyncLogicalLink->DataReceived(aConnH, 0, aData);	// flags ignored
       
   961 
       
   962 	}
       
   963 
       
   964 void CPhysicalLink::ConnectionComplete(THCIErrorCode aErr, const TBTConnect& aConn)
       
   965 	{
       
   966 	LOG_FUNC
       
   967 	if (aErr == KErrNone)
       
   968 		{
       
   969 		if(aConn.iLinkType == ESCOLink && !iSyncLogicalLink)
       
   970 			{
       
   971 			LOG(_L("Got a ConnectionComplete for a non-existant SCO link"))
       
   972 			//This situation can occur if ESock deletes the iSyncLogicalLink whilst it is waiting for
       
   973 			//a remote device to respond to a connection request.
       
   974 			iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType);
       
   975 
       
   976 			if(aErr==EOK) // if error, aConn.iConnH will refer to the ACL link used to initialise the SCO link, so dont disconnect that
       
   977 				{
       
   978 				//The baseband might actually have established a SCO link, so send a Disconnect.
       
   979 				//If no SCO link exists the command will fail gracefully.
       
   980 				TRAP_IGNORE(iLinksMan.HCIFacade().DisconnectL(aConn.iConnH, ERemoteUserEndedConnection));
       
   981 				}
       
   982 
       
   983 			return;
       
   984 			}
       
   985 
       
   986 		// update bb model
       
   987 		iLinksMan.Baseband().UpdateModel(aConn);
       
   988 		if (aConn.iLinkType == EACLLink)
       
   989 			{
       
   990 			// we need to store the physical handle we're on - in BT1.2 this is also taken to be
       
   991 			// the ACL Link handle too...
       
   992 			// do the PHY stuff first
       
   993 			LOG(_L("CPhysicalLink: PHY ready"))
       
   994 
       
   995 			iHandle = aConn.iConnH;
       
   996 			iDevice.SetAddress(aConn.iBdaddr);
       
   997 
       
   998 			//Set Default Local Link Policy;
       
   999 			//Get this in early to try and avoid conditions where remote requests
       
  1000 			//something we haven't told the controller we allow yet.
       
  1001 			SetModesAllowed(iLinksMan.LinkManagerProtocol().ModesSupportedLocally(),
       
  1002 							iLinksMan.RoleSwitchAllowed());
       
  1003 
       
  1004 			// try to get details of remote device
       
  1005 			TRAP_IGNORE(GetRemoteDetailsL(aConn));
       
  1006 			// ignore error - only optimisations
       
  1007 
       
  1008 			// assume we are going with 1 slot packets until notified otherwise, and in activemode
       
  1009 			iLinkState.SetLinkState(TBTBasebandLinkState::ELinkUp);
       
  1010 			iLinkState.SetMaxSlots(1);
       
  1011 			iLinkState.SetLinkMode(EActiveMode);
       
  1012 
       
  1013 			// If the peer is in security mode 3 then authenication has completed.
       
  1014 			if(iPeerInSecurityMode3)
       
  1015 				{
       
  1016 				iLinkState.SetAuthenticated(ETrue);
       
  1017 				AuthenticationComplete(EAuthenticationRequestPending);
       
  1018 				}
       
  1019 
       
  1020 			// update bb model for max slots
       
  1021 			iLinksMan.Baseband().UpdateModel(aConn.iConnH, 1);
       
  1022 
       
  1023 			TBTBasebandEventNotification event(ENotifyPhysicalLinkUp);
       
  1024 			NotifyStateChange(event);
       
  1025 
       
  1026 			if (aConn.iEncryptMode)
       
  1027 				{
       
  1028 				// pretend there's been an encryption event
       
  1029 				EncryptionChange(aErr, aConn.iConnH, aConn.iEncryptMode);
       
  1030 				}
       
  1031 			}
       
  1032 
       
  1033 		// This is assuming that our stack only allows one synchronous link per phy link.
       
  1034  		// SCO (not eSCO) Link getting notified here.
       
  1035  		else if(aConn.iLinkType == ESCOLink)
       
  1036  			{
       
  1037  			TBTBasebandEventNotification event(ENotifySynchronousLinkUp);
       
  1038  			NotifyStateChange(event);
       
  1039  			}
       
  1040 
       
  1041 		// tell the logical links
       
  1042 		NotifyLogicalLinkUp(aConn);
       
  1043 		iLinksMan.ArbitrateAllPhysicalLinks();
       
  1044 
       
  1045 		// Check to see if we got a disconnect request during the period before the link was
       
  1046 		// fully established.
       
  1047 		if (iDisconnectRequested)
       
  1048 			{
       
  1049 			__ASSERT_DEBUG(aConn.iLinkType == EACLLink, Panic(EDisconnectRequestedNotOnACLLink));
       
  1050 
       
  1051 			// We allow the link to come up fully so that the link is not in a strange state between
       
  1052 			// pending and up. This also means that the notifications to the logical links all work
       
  1053 			// correctly, they just see a link come up and then go down again straight away.
       
  1054 			TRAP_IGNORE(iLinksMan.HCIFacade().DisconnectL(aConn.iConnH, ERemoteUserEndedConnection));
       
  1055 			}
       
  1056 		else
       
  1057 			{
       
  1058 			TTime t;
       
  1059 			t.UniversalTime();
       
  1060 			iDevice.SetUsed(t);
       
  1061 			TRAP_IGNORE(StoreDeviceL(EFalse));
       
  1062 			}
       
  1063 		}
       
  1064 	else
       
  1065 		{
       
  1066 		// error occurred - need to see if it's PHY(and so ACL) or SCO that failed
       
  1067 		// tell logical links
       
  1068 		LOG2(_L("Physical link: connection complete returned an error on handle %d, type %d"), aConn.iConnH, aConn.iLinkType);
       
  1069 
       
  1070 		if(((aConn.iLinkType == ESCOLink)||(aConn.iLinkType == EeSCOLink)) && iSyncLogicalLink &&
       
  1071 		iSyncLogicalLink->Handle() != KInvalidConnectionHandle && iSyncLogicalLink->Handle() != aConn.iConnH)
       
  1072 			{
       
  1073 			// This is a secondary SCO link we just rejected or something - don't mess with our own
       
  1074 			// The KInvalidConnectionHandle test ensures that we ignore errored outgoing SCO connects.
       
  1075 			return;
       
  1076 			}
       
  1077 
       
  1078 		iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType);
       
  1079 		NotifyLogicalLinkError(aConn.iLinkType, CHciUtil::SymbianErrorCode(aErr));
       
  1080 		if (aConn.iLinkType == EACLLink)
       
  1081 			{
       
  1082 			// BT 1.2 says that as the ACL Link goes up and down, so does the physical link
       
  1083 			// so if the ACL Link has gone, so has this
       
  1084 			// for SCO we remain in place.
       
  1085 			TBTBasebandEventNotification event(ENotifyPhysicalLinkError, CHciUtil::SymbianErrorCode(aErr));
       
  1086 			NotifyStateChange(event);
       
  1087 			delete this;
       
  1088 			}
       
  1089 		}
       
  1090 	// ***Watchout*** delete this above: careful about code here
       
  1091 	}
       
  1092 
       
  1093 
       
  1094 void CPhysicalLink::SynchronousConnectionComplete(THCIErrorCode aErr,
       
  1095 													const TBTConnect& aConn,
       
  1096 													const TBTSyncConnectOpts& aSyncOpts)
       
  1097 	{
       
  1098 	LOG_FUNC
       
  1099 	__ASSERT_DEBUG(((aConn.iLinkType == ESCOLink) || (aConn.iLinkType == EeSCOLink)), Panic(EBTNonSyncConnectInSyncConnectFunc));
       
  1100 
       
  1101 	if(!iSyncLogicalLink)
       
  1102 		{
       
  1103 		LOG(_L("Got a SynchronousConnectionComplete when no SCO link is bound"))
       
  1104 		//This situation can occur if ESock deletes the iSyncLogicalLink whilst it is waiting for
       
  1105 		//a remote device to respond to a connection request.
       
  1106 		iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType);
       
  1107 
       
  1108 		if(aErr==EOK) // if error, aConn.iConnH will refer to the ACL link used to initialise the SCO link, so dont disconnect that
       
  1109 			{
       
  1110 			//The baseband might actually have established a SCO link, so send a Disconnect.
       
  1111 			//If no SCO link exists the command will fail gracefully.
       
  1112 			TRAP_IGNORE(iLinksMan.HCIFacade().DisconnectL(aConn.iConnH, ERemoteUserEndedConnection));
       
  1113 			}
       
  1114 
       
  1115 		return;
       
  1116 		}
       
  1117 
       
  1118 	if (aErr == KErrNone)
       
  1119 		{
       
  1120 		// update bb model
       
  1121 		iLinksMan.Baseband().UpdateModel(aConn);
       
  1122 
       
  1123  		// This is assuming that our stack only allows one synchronous link per phy link.
       
  1124  		// eSCO (not SCO) Link getting notified here.
       
  1125  		TBTBasebandEventNotification event(ENotifySynchronousLinkUp);
       
  1126  		NotifyStateChange(event);
       
  1127 
       
  1128 		// tell the logical links
       
  1129 		NotifyLogicalSyncLinkUp(aConn, aSyncOpts);
       
  1130 		iLinksMan.ArbitrateAllPhysicalLinks();
       
  1131 		}
       
  1132 	else
       
  1133 		{
       
  1134 		// error occurred - need to see if it's PHY(and so ACL) or SCO that failed
       
  1135 		// tell logical links
       
  1136 		LOG2(_L("Physical link: connection complete returned an error on handle %d, type %d"), aConn.iConnH, aConn.iLinkType);
       
  1137 		iLinksMan.Baseband().UpdateModelForConnectionError(aConn.iBdaddr, aConn.iLinkType);
       
  1138 
       
  1139 		// Before passing error around, check if it's actually for this link...
       
  1140 		// A listening link will have a NULL handle, otherwise the handle should match.
       
  1141 		// If the eSCO connection fails, the handle is KInvalidConnectionHandle (as initialised in CBTBasebandSAP)
       
  1142 		// This avoids the situation where we get notified of a rejection.
       
  1143 		if (iSyncLogicalLink &&
       
  1144 			(iSyncLogicalLink->Handle() == 0 || iSyncLogicalLink->Handle() == KInvalidConnectionHandle || iSyncLogicalLink->Handle() == aConn.iConnH))
       
  1145 			{
       
  1146 			NotifyLogicalLinkError(aConn.iLinkType, CHciUtil::SymbianErrorCode(aErr));
       
  1147 			}
       
  1148 		}
       
  1149 	}
       
  1150 
       
  1151 
       
  1152 void CPhysicalLink::GetRemoteDetailsL(const TBTConnect& aConn)
       
  1153 	{
       
  1154 	LOG_FUNC
       
  1155 	GetDeviceFromRegistryL();
       
  1156 	iLinksMan.HCIFacade().ReadClockOffsetL(aConn.iConnH);
       
  1157 	iLinksMan.HCIFacade().ReadRemoteSupportedFeaturesL(aConn.iConnH);
       
  1158 	iLinksMan.HCIFacade().ReadRemoteVersionL(aConn.iConnH);
       
  1159 	iLinksMan.LinkManagerProtocol().InquiryMgr().ReadRemoteNameL(aConn.iBdaddr);
       
  1160 	}
       
  1161 
       
  1162 void CPhysicalLink::LinkSupervisionTimeoutChange(THCIErrorCode aErr, THCIConnHandle aConnH, TUint16 aNewTimeout)
       
  1163 	{
       
  1164 	LOG_FUNC
       
  1165 	__CHECK_CONNECTION_HANDLE(aConnH);
       
  1166 
       
  1167 	if(aErr == EOK)
       
  1168 		{
       
  1169 		iLSTO = aNewTimeout;
       
  1170 		}
       
  1171 	}
       
  1172 
       
  1173 void CPhysicalLink::PacketTypeChange(THCIErrorCode aErr, THCIConnHandle aConnH, TUint16 aNewPacket)
       
  1174 	{
       
  1175 	LOG_FUNC
       
  1176 	__CHECK_CONNECTION_HANDLE(aConnH);
       
  1177 
       
  1178 	if(aErr==EOK)
       
  1179 		{
       
  1180 		iLinksMan.Baseband().UpdateModelIfRecordExists(aConnH, aNewPacket);
       
  1181 		iLinkState.SetPacketTypes(aNewPacket);
       
  1182 		}
       
  1183 
       
  1184 	TUint32 eventType = 0;
       
  1185 
       
  1186 	if(aNewPacket & EPacketsDM1)
       
  1187 		eventType |= ENotifyPacketsDM1;
       
  1188 	if(aNewPacket & EPacketsDH1)
       
  1189 		eventType |= ENotifyPacketsDH1;
       
  1190 	if(aNewPacket & EPacketsDM3)
       
  1191 		eventType |= ENotifyPacketsDM3;
       
  1192 	if(aNewPacket & EPacketsDH3)
       
  1193 		eventType |= ENotifyPacketsDH3;
       
  1194 	if(aNewPacket & EPacketsDM5)
       
  1195 		eventType |= ENotifyPacketsDM5;
       
  1196 	if(aNewPacket & EPacketsDH5)
       
  1197 		eventType |= ENotifyPacketsDH5;
       
  1198 
       
  1199 	if(aNewPacket & EPacketsHV1)
       
  1200 		eventType |= ENotifyPacketsHV1;
       
  1201 	if(aNewPacket & EPacketsHV2)
       
  1202 		eventType |= ENotifyPacketsHV2;
       
  1203 	if(aNewPacket & EPacketsHV3)
       
  1204 		eventType |= ENotifyPacketsHV3;
       
  1205 
       
  1206 	TBTBasebandEventNotification event(eventType, aErr);
       
  1207 	NotifyStateChange(event);
       
  1208 	}
       
  1209 
       
  1210 void CPhysicalLink::MaxSlotsChange(THCIConnHandle aConnH, TUint8 aSlots)
       
  1211 	{
       
  1212 	LOG_FUNC
       
  1213 	__CHECK_CONNECTION_HANDLE(aConnH);
       
  1214 	LOG2(_L("Connection Handle 0x%04x, using %d slots"), aConnH, aSlots);
       
  1215 	iLinksMan.Baseband().UpdateModel(aConnH, aSlots);	//event only for ACL
       
  1216 	iLinkState.SetMaxSlots(aSlots);
       
  1217 
       
  1218 	TBTBasebandEventNotification event;
       
  1219 	switch(aSlots)
       
  1220 		{
       
  1221 		case 1:
       
  1222 			event.SetEventType(ENotifyMaxSlots1);
       
  1223 			break;
       
  1224 		case 3:
       
  1225 			event.SetEventType(ENotifyMaxSlots3);
       
  1226 			break;
       
  1227 		case 5:
       
  1228 			event.SetEventType(ENotifyMaxSlots5);
       
  1229 			break;
       
  1230 		};
       
  1231 	NotifyStateChange(event);
       
  1232 	}
       
  1233 
       
  1234 void CPhysicalLink::ModeChange(THCIErrorCode aErr, THCIConnHandle aConnH, TBTLinkMode aMode, TBasebandTime aInterval)
       
  1235 	{
       
  1236 	LOG_FUNC
       
  1237 	__CHECK_CONNECTION_HANDLE(aConnH);
       
  1238 	LOG3(_L("Connection Handle 0x%04x: ModeChange event %d->%d"), aConnH, iLinkState.LinkMode(), aMode);
       
  1239 
       
  1240 	TBTLinkMode oldMode = iLinkState.LinkMode();
       
  1241 
       
  1242 	iLinkState.SetLinkMode(aMode);	// remember the state for ourselves
       
  1243 
       
  1244 	if (aErr == EOK)
       
  1245 		{
       
  1246 		if (aMode == EParkMode)
       
  1247 			{
       
  1248 			iLinksMan.Baseband().ParkLink(aConnH);	//remove from model whilst parked
       
  1249 			}
       
  1250 
       
  1251 		if (aMode == EActiveMode && oldMode==EParkMode)
       
  1252 			{
       
  1253 			// unparking we must tell the DataQ - we could always get the dataQ to ask us before sending of course
       
  1254 			// but that might be performance harming
       
  1255 			iLinksMan.Baseband().UnParkLink(aConnH); //NB Max Slots = 1 default
       
  1256 			}
       
  1257 
       
  1258 		if (aMode == ESniffMode )
       
  1259 			{
       
  1260 			// Store the Sniff Interval
       
  1261 			iSniffInterval = aInterval;
       
  1262 			}
       
  1263 
       
  1264 		if (aMode == EActiveMode && iSniffInterval)
       
  1265 			{
       
  1266 			//Active mode enable and SniffInterval is set.
       
  1267 			//Therefore must be leaving sniff mode.
       
  1268 			__ASSERT_DEBUG(oldMode==ESniffMode, Panic(EBTPhysicalLinkModeChangeErrorLeavingSniffMode));
       
  1269 
       
  1270 			//When not in sniff mode, sniff interval is obviously 0!
       
  1271 			iSniffInterval = 0;
       
  1272 			}
       
  1273 		}
       
  1274 
       
  1275 	// Generate a baseband event, and offer it to the proxySAP's associated
       
  1276 	// with this link.
       
  1277 	TBTBasebandEventNotification event;
       
  1278 	switch(aMode)
       
  1279 		{
       
  1280 		case EActiveMode:
       
  1281 			event.SetEventType(ENotifyActiveMode);
       
  1282 			break;
       
  1283 		case ESniffMode:
       
  1284 			event.SetEventType(ENotifySniffMode);
       
  1285 			break;
       
  1286 		case EHoldMode:
       
  1287 			event.SetEventType(ENotifyHoldMode);
       
  1288 			break;
       
  1289 		case EParkMode:
       
  1290 			event.SetEventType(ENotifyParkMode);
       
  1291 			break;
       
  1292 		case EScatterMode:
       
  1293 			break; // shouldnt be seen yet - if so, ignore for now
       
  1294 		};
       
  1295 	event.SetErrorCode(aErr);
       
  1296 	NotifyStateChange(event);
       
  1297 	}
       
  1298 
       
  1299 void CPhysicalLink::RoleChange(THCIErrorCode aErr, const TBTDevAddr& /*aAddr*/, TBTBasebandRole aRole)
       
  1300 	{
       
  1301 	LOG_FUNC
       
  1302 	LOG1(_L("CPhysicalLink: Role change - new role %S"), aRole == EMaster ? _S("Master") : _S("Slave"));
       
  1303 
       
  1304 	if (aErr == EOK)
       
  1305 		{
       
  1306 		iLinkState.SetLinkRole(aRole);
       
  1307 		}
       
  1308 
       
  1309 	// Generate a baseband event, and offer it to the proxySAP's associated
       
  1310 	// with this link.
       
  1311 	TBTBasebandEventNotification event;
       
  1312 	if(aRole == EMaster)
       
  1313 		{
       
  1314 		event.SetEventType(ENotifyMaster);
       
  1315 		}
       
  1316 	else
       
  1317 		{
       
  1318 		event.SetEventType(ENotifySlave);
       
  1319 		}
       
  1320 	event.SetErrorCode(aErr);
       
  1321 	NotifyStateChange(event);
       
  1322 
       
  1323 	// if iEncryptionEnforcer is present it means we asked for encryption, so we inform it
       
  1324 	// about the roleswitch
       
  1325 	if (iEncryptionEnforcer)
       
  1326 		{
       
  1327 		iEncryptionEnforcer->RoleSwitchEvent();
       
  1328 		}
       
  1329 	}
       
  1330 
       
  1331 void CPhysicalLink::WriteLinkPolicySettingsCompleteEvent(THCIErrorCode aErr, THCIConnHandle aConnH)
       
  1332 	{
       
  1333 	LOG_FUNC
       
  1334 	__CHECK_CONNECTION_HANDLE(aConnH);
       
  1335 	// we don't get the things back we set...
       
  1336 	if (aErr != EOK)
       
  1337 		{
       
  1338 		// The command has failed.	Clear the cached values and re-arbitrate.
       
  1339 		iLinkPolicy.SetModesAllowed(0);
       
  1340 		iLinkPolicy.SetSwitchAllowed(EFalse);
       
  1341 		Arbitrate();
       
  1342 		}
       
  1343 	}
       
  1344 
       
  1345 void CPhysicalLink::ClockOffset(THCIErrorCode aErr, THCIConnHandle aConnH, TBasebandTime aClockOffset)
       
  1346 	{
       
  1347 	LOG_FUNC
       
  1348 	__CHECK_CONNECTION_HANDLE(aConnH);
       
  1349 	if (aErr==EOK)
       
  1350 		{
       
  1351 		// tell inquiry manager - we found this information to help it
       
  1352 		iLinksMan.LinkManagerProtocol().InquiryMgr().ClockOffsetResult(BDAddr(), aClockOffset);
       
  1353 		}
       
  1354 	// we don't do anything more useful knowing this information
       
  1355 	}
       
  1356 
       
  1357 void CPhysicalLink::RemoteName(THCIErrorCode aErr, const TBTDevAddr& /*aAddr*/, const TBTDeviceName8& aName)
       
  1358 /**
       
  1359 	We don't keep this, but we're interested in persisting it in el Reg
       
  1360 	By receiving this we now our attempts have completed in getting name
       
  1361 */
       
  1362 	{
       
  1363 	LOG_FUNC
       
  1364 	if (aErr==EOK)
       
  1365 		{
       
  1366 		// slam it into the Registry - this will be useful to UIs if not us
       
  1367 		TRAP_IGNORE(DoUpdateNameL(aName));
       
  1368 		}
       
  1369 	}
       
  1370 
       
  1371 void CPhysicalLink::DoUpdateNameL(const TBTDeviceName8& aName)
       
  1372 	{
       
  1373 	LOG_FUNC
       
  1374 	CBTDeviceNameChanger* nameChanger = CBTDeviceNameChanger::NewL(iRegSess, *this);
       
  1375 	iRegistryHelpers.AddLast(*nameChanger);
       
  1376 	nameChanger->Start(BDAddr(), aName);
       
  1377 	}
       
  1378 
       
  1379 void CPhysicalLink::Disconnection(THCIErrorCode aErr, THCIConnHandle aConnH, THCIErrorCode aResult)
       
  1380 	{
       
  1381 	LOG_FUNC
       
  1382 	// tell our socket if it's our handle - otherwise the SCO SAP
       
  1383 
       
  1384 	LOG1(_L("Physical link: disconnection on handle %d"), aConnH);
       
  1385 	LOG1(_L(" ACL link handle:	 %d"), Handle());
       
  1386 #ifdef __FLOG_ACTIVE
       
  1387 	if (iSyncLogicalLink) LOG1(_L(" Sync link handle: %d"), iSyncLogicalLink->Handle());
       
  1388 #endif
       
  1389 
       
  1390 	//no matter if it is the socket or SCO SAP the ui dialogs will be cancelled
       
  1391 	if (iNumericComparator && iNumericComparator->IsActive())
       
  1392 		{
       
  1393 		iNumericComparator->Cancel();
       
  1394 		}
       
  1395 	if (iPasskeyEntry && iPasskeyEntry->IsActive())
       
  1396 		{
       
  1397 		iPasskeyEntry->Cancel();
       
  1398 		}
       
  1399 
       
  1400 	if (aConnH == Handle())
       
  1401 		{
       
  1402 		TBTBasebandEventNotification event;
       
  1403 		switch(aErr)
       
  1404 			{
       
  1405 			case EHardwareFail:
       
  1406 				{
       
  1407 
       
  1408 				if(iLinkState.LinkState() == TBTBasebandLinkState::ELinkUp ||
       
  1409 				   iLinkState.LinkState() == TBTBasebandLinkState::ELinkPending)
       
  1410 					{
       
  1411 					//Only propagate if link is up or pending, otherwise
       
  1412 					//we may get disconnection in unexpected states
       
  1413 
       
  1414 					//Fall through
       
  1415 					}
       
  1416 				else
       
  1417 					{
       
  1418 					// this object must go when no link
       
  1419 					delete this;
       
  1420 					break;
       
  1421 					}
       
  1422 				}
       
  1423 			case EOK:
       
  1424 				{
       
  1425 				iLinkState.SetLinkState(TBTBasebandLinkState::ELinkDown);
       
  1426 
       
  1427 				// PHY went down - so have logical links then
       
  1428 				NotifyLogicalLinkDown(EACLLink);
       
  1429 				NotifyLogicalLinkDown(ESCOLink);
       
  1430 
       
  1431 				event.SetEventType(ENotifyPhysicalLinkDown);
       
  1432 				event.SetErrorCode(aResult);
       
  1433 				iLinksMan.Baseband().UpdateModelForDisconnection(aConnH, EACLLink);
       
  1434 				HandlePrefetch();
       
  1435 				NotifyStateChange(event);
       
  1436 				// this object must go when no link
       
  1437 				delete this;
       
  1438 				break;
       
  1439 				}
       
  1440 			case ECommandDisallowed:
       
  1441 				{
       
  1442 				// The connection is still up, so do nothing, and wait for the next idle timer to fire
       
  1443 				break;
       
  1444 				}
       
  1445 			default:
       
  1446 				{
       
  1447 				iLinkState.SetLinkState(TBTBasebandLinkState::ELinkDown);
       
  1448 
       
  1449 				// there's an error
       
  1450 				NotifyLogicalLinkError(EACLLink, aErr);
       
  1451 				NotifyLogicalLinkError(ESCOLink, aErr);
       
  1452 				event.SetEventType(ENotifyPhysicalLinkError);
       
  1453 				event.SetErrorCode(aErr);
       
  1454 				// baseband model needs to err on the side of least bandwidth usage -
       
  1455 				// a link COULD have come down
       
  1456 				iLinksMan.Baseband().UpdateModelForDisconnection(aConnH, EACLLink);
       
  1457 				HandlePrefetch();
       
  1458 				NotifyStateChange(event);
       
  1459 				// this object must go when no link
       
  1460 				delete this;
       
  1461 				break;
       
  1462 				}
       
  1463 			}
       
  1464 		}
       
  1465 
       
  1466 	else if (iSyncLogicalLink && aConnH == iSyncLogicalLink->Handle())
       
  1467 		{
       
  1468 		TBTBasebandEventNotification event;
       
  1469 		// just the SCO link is down so we'd better notify
       
  1470 		if (aErr)
       
  1471 			{
       
  1472 			LOG(_L("Physical link: error disconnection on sync link"));
       
  1473 			TLinkType type = iSyncLogicalLink->LinkType();
       
  1474 			iSyncLogicalLink->Error(CHciUtil::SymbianErrorCode(aErr));
       
  1475 			event.SetEventType(ENotifySynchronousLinkError);
       
  1476 			event.SetErrorCode(aErr);
       
  1477 			// baseband model needs to err on the side of least bandwidth usage -
       
  1478 			// a sync link COULD have come down
       
  1479 			iLinksMan.Baseband().UpdateModelForDisconnection(aConnH, type);
       
  1480 			}
       
  1481 		else
       
  1482 			{
       
  1483 			LOG(_L("Physical link: normal disconnection on sync link"));
       
  1484 			TLinkType type = iSyncLogicalLink->LinkType();
       
  1485 			iSyncLogicalLink->Disconnection();
       
  1486 			event.SetEventType(ENotifySynchronousLinkDown);
       
  1487 			event.SetErrorCode(aResult);
       
  1488 			iLinksMan.Baseband().UpdateModelForDisconnection(aConnH, type);
       
  1489 			}
       
  1490 
       
  1491 		NotifyStateChange(event);
       
  1492 		}
       
  1493 	// NOTE!! delete this above - careful about adding code
       
  1494 	}
       
  1495 
       
  1496 void CPhysicalLink::ConnectionRequest(const TBTConnect& aConn)
       
  1497 	{
       
  1498 	LOG_FUNC
       
  1499 	// we must be page scan enable for this to come in
       
  1500 	// but still need to see if it got routed a listening SAP
       
  1501 	TBool accept = EFalse;
       
  1502 	TLogicalLinkListener* listener = NULL;
       
  1503 
       
  1504 	__ASSERT_DEBUG(iPendingConnection == EFalse, Panic(EPendingConnectionNotCleared));
       
  1505 
       
  1506 	switch (aConn.iLinkType)
       
  1507 		{
       
  1508 		case ESCOLink:
       
  1509 		case EeSCOLink:
       
  1510 			if (!iSyncLogicalLink)
       
  1511 				{
       
  1512 				// If we already have a sync link active, reject request.
       
  1513 				LOG(_L("No current link, checking for listener"));
       
  1514 				listener = iLinksMan.FindListener(aConn.iLinkType);
       
  1515 				}
       
  1516 			break;
       
  1517 
       
  1518 		default:
       
  1519 			listener = iLinksMan.FindListener(aConn.iLinkType);
       
  1520 			break;
       
  1521 		}
       
  1522 
       
  1523 	if (listener)
       
  1524 		{
       
  1525 		accept = ETrue;
       
  1526 		if (iLinksMan.IsAcceptPairedOnlyMode())
       
  1527 			{
       
  1528 			// do not accept if we are only accepting connection
       
  1529 			// requests from paired devices and we are not already
       
  1530 			// paired with the remote
       
  1531 			CBTPairingsCache::TPairingState pairingState = iLinksMan.PairingsCache().IsPaired(aConn.iBdaddr);
       
  1532 
       
  1533 			if(pairingState == CBTPairingsCache::EDeferred)
       
  1534 				{
       
  1535 				// We're still waiting for the Pairing Caches paired device list to be filled.
       
  1536  				// We'll respond when this is complete, so store details away for then.
       
  1537 				LOG(_L("CPhysicalLink: Waiting for physical link manager's paired device list from Registry!"))
       
  1538 				iPendingConnection = ETrue;
       
  1539     			iLastPendingConnection.iConnH = aConn.iConnH;
       
  1540 			    iLastPendingConnection.iBdaddr = aConn.iBdaddr;
       
  1541 			    iLastPendingConnection.iCoD = aConn.iCoD;
       
  1542 			    iLastPendingConnection.iLinkType = aConn.iLinkType;
       
  1543 			    iLastPendingConnection.iEncryptMode = aConn.iEncryptMode;
       
  1544 			    // Return now as we are waiting and don't want to 'RejectConnection'
       
  1545 				return;
       
  1546 				}
       
  1547 
       
  1548 			// If here then the cache has either informed us that the device is paired
       
  1549  			// or not.  We only accept paired connections.
       
  1550  			accept = (pairingState == CBTPairingsCache::EPaired) ? ETrue : EFalse;
       
  1551 			}
       
  1552 		if (accept)
       
  1553 			{
       
  1554 			// this may mean the physical link's acceptance is determined by the
       
  1555 			// ACL Logical link - but that's what the spec implies :-)
       
  1556 			accept = static_cast<MLogicalLink*>(listener->iObserver)->ConnectRequest(aConn, *this);
       
  1557 			// since we only support one SCO listener at present we dont need to mark it as the acceptor
       
  1558 			// or indeed find a specific one: later we could choose via CoD
       
  1559 			}
       
  1560 		}
       
  1561 
       
  1562 	if (accept)
       
  1563 		{
       
  1564 
       
  1565 		// store CoD now, not told it ever again! if connection fails this object will go
       
  1566 		// Don't update CoD if it is 0 (NULL) as this is the default.
       
  1567 		// This also prevents a valid CoD being overwritten.
       
  1568 		if (aConn.iCoD != 0)
       
  1569 			{
       
  1570 			iDevice.SetDeviceClass(aConn.iCoD);
       
  1571 			}
       
  1572 
       
  1573 		TUint8 roleSwitch = static_cast<TUint8>(iLinksMan.PassiveConnectBecomeMaster() ? 0x00 : 0x01);
       
  1574 
       
  1575 		TInt err;
       
  1576 		if (aConn.iLinkType == EeSCOLink)
       
  1577 			{
       
  1578 			TBTeSCOLinkParams options;
       
  1579 
       
  1580 			CeSCOLink* eSCO = static_cast<CeSCOLink*>(listener->iObserver);
       
  1581 			TUint16 packetMask = eSCO->GetPacketMask();
       
  1582 			eSCO->GetExtOptions(options);
       
  1583 
       
  1584 			TRAP(err, iLinksMan.HCIFacade().AcceptSynchronousConnectionL(aConn.iBdaddr,
       
  1585 				options.iBandwidth.iTransmit, options.iBandwidth.iReceive,
       
  1586 				options.iLatency, options.iCoding, options.iRetransmissionEffort,
       
  1587 				packetMask
       
  1588 				));
       
  1589 			}
       
  1590 		else
       
  1591 			{
       
  1592 			TRAP(err, iLinksMan.HCIFacade().AcceptConnectionRequestL(aConn.iBdaddr, roleSwitch));
       
  1593 			}
       
  1594 
       
  1595 		if (err == KErrNone)
       
  1596 			{
       
  1597 			// assume we're slave until told otherwise on ACL(=PHY) links
       
  1598 			if (aConn.iLinkType == EACLLink)
       
  1599 				{
       
  1600 				// this is a PHY connect request too, so we should store our role
       
  1601 				//The handle in 'aConn' is bogus, so..
       
  1602 				iLinkState.SetLinkState(TBTBasebandLinkState::ELinkPending);
       
  1603 				iLinksMan.Baseband().UpdateModel(aConn.iBdaddr, KHCIDefaultPacketType, aConn.iLinkType);
       
  1604 				iLinkState.SetLinkRole((roleSwitch == 0x01) ? ESlave : EMaster);
       
  1605 
       
  1606 				// have to store it now, since the complete wont tell us anything!
       
  1607 				}
       
  1608 			else
       
  1609 				{
       
  1610 				//The handle in 'aConn' is bogus, so..
       
  1611 				iLinksMan.Baseband().UpdateModel(aConn.iBdaddr, KHCIDefaultSCOPacketType, aConn.iLinkType);
       
  1612 				}
       
  1613 			}
       
  1614 		else
       
  1615 			{
       
  1616 			// Out of memory:
       
  1617 			// Cause newly created spawned SAP (whether ACL or SCO)
       
  1618 			// to die.
       
  1619 			// Attempt to reject connection with newly freed memory...
       
  1620 			// ...this of course may fail in which case we have
       
  1621 			// to rely on supervison timeouts.
       
  1622 			if (aConn.iLinkType == EACLLink)
       
  1623 				{
       
  1624 				TInt last = iACLLogicalLinks.Count() - 1;
       
  1625 				if(last>=0)
       
  1626 					{
       
  1627 					iACLLogicalLinks[last]->Error(err);
       
  1628 					}
       
  1629 				}
       
  1630 			else
       
  1631 				{
       
  1632 				if(iSyncLogicalLink)
       
  1633 					{
       
  1634 					iSyncLogicalLink->Error(err);
       
  1635 					}
       
  1636 				}
       
  1637 			RejectConnection(aConn);
       
  1638 			}
       
  1639 		}
       
  1640 	else
       
  1641 		{
       
  1642 		// reject
       
  1643 		RejectConnection(aConn);
       
  1644 		}
       
  1645 
       
  1646 	// Tell inquiry manager - should have a valid CoD within 'aConn'
       
  1647 	// Don't update CoD if it is 0 (NULL) as this is the default.
       
  1648 	// This also prevents a valid CoD being overwritten.
       
  1649 	if (aConn.iCoD != 0)
       
  1650 		{
       
  1651 		iLinksMan.LinkManagerProtocol().InquiryMgr().CoDResult(aConn.iBdaddr, aConn.iCoD);
       
  1652 		}
       
  1653 	}
       
  1654 
       
  1655 void CPhysicalLink::RejectConnection(const TBTConnect& aConn)
       
  1656 	{
       
  1657 	LOG_FUNC
       
  1658 	if (aConn.iLinkType == EeSCOLink)
       
  1659 		{
       
  1660 		TRAP_IGNORE(iLinksMan.HCIFacade().RejectSynchronousConnectionL(aConn.iBdaddr, KDefaultRejectReason));
       
  1661 		}
       
  1662 	else
       
  1663 		{
       
  1664 		TRAP_IGNORE(iLinksMan.HCIFacade().RejectConnectionRequestL(aConn, KDefaultRejectReason));
       
  1665 		}
       
  1666 	}
       
  1667 
       
  1668 
       
  1669 void CPhysicalLink::GetDeviceFromRegistryL()
       
  1670 	{
       
  1671 	LOG_FUNC
       
  1672 	CBTDeviceGetter* getter = CBTDeviceGetter::NewL(iRegSess, *this);
       
  1673 	iRegistryHelpers.AddLast(*getter);
       
  1674 	getter->Start(BDAddr());		// now get the rest of the details
       
  1675 	// just BDAddr?
       
  1676 	}
       
  1677 
       
  1678 TInt CPhysicalLink::GetOption(TUint aLevel,TUint aName,TDes8& aOption) const
       
  1679 	{
       
  1680 	LOG_FUNC
       
  1681 	// good stuff here!
       
  1682 	if (aLevel == KSolBtLM)
       
  1683 		{
       
  1684 		switch (aName)
       
  1685 			{
       
  1686 			case KLMGetBasebandHandle:
       
  1687 				{
       
  1688 				if (aOption.Length() != sizeof(THCIConnHandle))
       
  1689 					{
       
  1690 					return KErrArgument;
       
  1691 					}
       
  1692 				aOption = TPtrC8(reinterpret_cast<const TUint8*>(&iHandle), sizeof(THCIConnHandle));
       
  1693 				return KErrNone;
       
  1694 				}
       
  1695 
       
  1696 			case EBBGetSniffInterval:
       
  1697 				if (aOption.Length() != sizeof(TBasebandTime))
       
  1698 					{
       
  1699 					return KErrArgument;
       
  1700 					}
       
  1701 				aOption = TPtrC8(reinterpret_cast<const TUint8*>(&iSniffInterval), sizeof(TBasebandTime));
       
  1702 			    return KErrNone;
       
  1703 
       
  1704 			default:
       
  1705 				return KErrNotSupported;
       
  1706 			}
       
  1707 		}
       
  1708 	else
       
  1709 		{
       
  1710 		return KErrNotSupported;
       
  1711 		}
       
  1712 	}
       
  1713 
       
  1714 TInt CPhysicalLink::Arbitrate(const TBool aImmediately, const TBool aLocalPriority)
       
  1715 	{
       
  1716 	LOG_FUNC
       
  1717 	if (!IsConnected())
       
  1718 		return KErrDisconnected;
       
  1719 
       
  1720 	if ( aImmediately )
       
  1721 		{
       
  1722 		iArbitrationDelay->Cancel();
       
  1723 		}
       
  1724 	else if (iArbitrationDelay->IsActive())
       
  1725 		{
       
  1726 		return KErrNone;
       
  1727 		}
       
  1728 
       
  1729 	//start arbitrate process with what our local controller supports
       
  1730 	TUint8 allowedModesMask = EHoldMode | EParkMode | ESniffMode; // local features sorted out later
       
  1731 	TBool roleSwitchAllowed = EFalse;
       
  1732 
       
  1733  	if (iLinksMan.LinkManagerProtocol().IsRoleSwitchSupportedLocally() && iLinksMan.RoleSwitchAllowed())
       
  1734  		{
       
  1735  		roleSwitchAllowed = ETrue;
       
  1736  		}
       
  1737 
       
  1738 	// ask proxies what they want from the PHY
       
  1739  	TUint8 requestedModeMask = 0;
       
  1740  	TUint8 requestedMode = 0;
       
  1741  	TBool activeModeIsRequested = EFalse;
       
  1742 	TSglQueIter<CBTProxySAP> iter(iProxySAPs);
       
  1743 	while (iter)
       
  1744 		{
       
  1745 		CBTProxySAP* proxy = iter++;
       
  1746 
       
  1747  		requestedMode = proxy->GetRequestedModes();
       
  1748  		requestedModeMask |= requestedMode;
       
  1749 
       
  1750 		if (requestedMode == EActiveMode && proxy->RequestedActiveMode())
       
  1751  			{
       
  1752  			// An Active Mode request will override all other local low power mode requests
       
  1753  			// but continue to collect the requirement from the other proxies..
       
  1754  			activeModeIsRequested = ETrue;
       
  1755  			}
       
  1756 
       
  1757 		allowedModesMask &= proxy->GetAllowedModes();
       
  1758 		roleSwitchAllowed &= proxy->IsRoleSwitchAllowed();
       
  1759 		}
       
  1760 
       
  1761  	if (activeModeIsRequested)
       
  1762  		{
       
  1763  		// Any Active Mode request will override all other low power mode requests,
       
  1764  		// so overwrite the requestedModeMask but keep allowedModesMask and roleSwitchAllowed
       
  1765  		// as specified by all the local proxies
       
  1766  		requestedModeMask = EActiveMode;
       
  1767  		}
       
  1768 
       
  1769 	// clear out modes not supported by local Controller
       
  1770 	allowedModesMask &= iLinksMan.LinkManagerProtocol().ModesSupportedLocally();
       
  1771 
       
  1772 	if(iOverrideParkRequests)
       
  1773 		{
       
  1774 		// We wish to ensure the physical link is not in PARK mode.
       
  1775 		// The only way to guarantee this is to disallow PARK via the link policy settings.
       
  1776 		allowedModesMask &= ~EParkMode;
       
  1777 		}
       
  1778 
       
  1779 	if(allowedModesMask != iLinkPolicy.LowPowerModePolicy()
       
  1780 		|| roleSwitchAllowed != iLinkPolicy.IsSwitchAllowed())
       
  1781 		{
       
  1782 		// Controller policy for the connection needs updating
       
  1783 		SetModesAllowed(allowedModesMask, roleSwitchAllowed);
       
  1784 		}
       
  1785 
       
  1786 	//If OverrideLPM flag is set, we do not disable LP modes via the link policy settings
       
  1787 	//This is done because OverrideLPM should not prevent remotes putting us into an LPM
       
  1788 	//Later on, when OverrideLPM flag is cancelled, it would allow us to enforce requested LPM
       
  1789 	if(iOverrideLPMRequests)
       
  1790 		{
       
  1791 		// We need to ensure the physical link is in active mode.
       
  1792 		allowedModesMask = EActiveMode;
       
  1793 		}
       
  1794 
       
  1795 	TUint8 modeChangeMask = static_cast<TUint8>(requestedModeMask & allowedModesMask);
       
  1796 	TUint8 modeCompareMask = 0;
       
  1797 
       
  1798 	if(aLocalPriority)
       
  1799 		{
       
  1800 		// If we want local priority, we go with what we want to do
       
  1801 		// irrespective of what the remote may have previously requested.
       
  1802 		modeCompareMask = modeChangeMask;
       
  1803 		}
       
  1804 	else
       
  1805 		{
       
  1806  		// This logic allows us to see if the current low power mode has recently
       
  1807  		// changed NOT because of a change in the local proxies' requests, but (probably)
       
  1808  		// because a remote device has changed it..
       
  1809 
       
  1810 		// modeCompareMask should start only having zero bits where
       
  1811 		// requestedModeMask has a zero bit and iPreviousRequestedModeMask does not
       
  1812 		// i.e. a mode is newly no longer requested.
       
  1813 		modeCompareMask = requestedModeMask | ~iPreviousRequestedModeMask;
       
  1814 
       
  1815 		// Remove bits from modeCompareMask that are not in allowedModesMask
       
  1816 		// We cannot stay in a power mode that we do not allow.
       
  1817 		modeCompareMask &= allowedModesMask;
       
  1818 		}
       
  1819 
       
  1820 	iPreviousRequestedModeMask = requestedModeMask; // Update previous requested to current value.
       
  1821 
       
  1822 	TUint8 currentModeMask = static_cast<TUint8>(iLinkState.LinkMode());
       
  1823 	if(modeCompareMask & currentModeMask)
       
  1824 		{
       
  1825 		// The current state is the same as the permitted required role(s).
       
  1826 		return KErrNone;
       
  1827 		}
       
  1828 
       
  1829 	if(modeChangeMask == EActiveMode && currentModeMask != EActiveMode)
       
  1830 		{
       
  1831 		// The current low power mode should be exited.
       
  1832 		return RequestActive();
       
  1833 		}
       
  1834 
       
  1835 	if(modeChangeMask != EActiveMode)
       
  1836 		{
       
  1837 		if(currentModeMask != EActiveMode)
       
  1838 			{
       
  1839 			// The system is currently in a low power mode.  Exit this before
       
  1840 			// entering the new mode.
       
  1841 			TInt rerr = RequestActive();
       
  1842 			if(rerr != KErrNone)
       
  1843 				{
       
  1844 				return rerr;
       
  1845 				}
       
  1846 			}
       
  1847 
       
  1848 		if(modeChangeMask & EHoldMode)
       
  1849 			{
       
  1850 			return RequestHold();
       
  1851 			}
       
  1852 		if(modeChangeMask & ESniffMode)
       
  1853 			{
       
  1854 			return RequestSniff();
       
  1855 			}
       
  1856 		if(modeChangeMask & EParkMode)
       
  1857 			{
       
  1858 			return RequestPark();
       
  1859 			}
       
  1860 		}
       
  1861 
       
  1862 	// This point in the code is reached if the Link Policy settings are
       
  1863 	// changed but the mode is not.	 Return OK error code.
       
  1864 	return KErrNone;
       
  1865 	}
       
  1866 
       
  1867 void CPhysicalLink::SetPassKey(const TDesC8& aPassKey)
       
  1868 	{
       
  1869 	LOG_FUNC
       
  1870 	// We store the key for use if it succeeds.
       
  1871 	iNewPinCode.Copy(aPassKey);
       
  1872 	iNewPinCodeValid = ETrue;
       
  1873 	}
       
  1874 
       
  1875 const TBTPinCode& CPhysicalLink::PassKey() const
       
  1876 	{
       
  1877 	LOG_FUNC
       
  1878 	return iDevice.PassKey();
       
  1879 	}
       
  1880 
       
  1881 void CPhysicalLink::StartArbitrationTimer() const
       
  1882 	{
       
  1883 	LOG_FUNC
       
  1884 	iArbitrationDelay->Start();
       
  1885 	}
       
  1886 
       
  1887 TInt CPhysicalLink::Connect(TBasebandPageTimePolicy aPolicy)
       
  1888 	{
       
  1889 	LOG_FUNC
       
  1890 	// assume that we will be master until told otherwise
       
  1891 	ASSERT_DEBUG(!IsConnected());
       
  1892 
       
  1893 	UpdateFromInquiryCache();
       
  1894 
       
  1895 	TUint8 psrm = iDevice.IsValidPageScanRepMode() ? iDevice.PageScanRepMode() : TUint8(KDefaultBluetoothPageScanRepMode);
       
  1896 	TUint8 psm = iDevice.IsValidPageScanMode() ? iDevice.PageScanMode() : TUint8(KDefaultBluetoothPageScanMode);
       
  1897 	TUint16 clockOffset = iDevice.IsValidClockOffset() ? iDevice.ClockOffset() : TUint16(KDefaultBluetoothClockOffset);
       
  1898 
       
  1899 	TUint8 allowRoleSwitch = static_cast<TUint8>(iLinksMan.ActiveConnectRoleSwitchAllowed());
       
  1900 
       
  1901 	TUint16 pkt = KHCIDefaultPacketType;
       
  1902 
       
  1903 	// optimise paging (as a best-effort attempt).
       
  1904 	TBasebandTime pagetimeout = CalculatePageTimeout(aPolicy, psrm, clockOffset & KHCIClockOffsetValidBit);
       
  1905 	iLinksMan.TryToChangePageTimeout(pagetimeout);
       
  1906 
       
  1907 	TRAPD(ret, iLinksMan.HCIFacade().ConnectL(iDevice.Address(), pkt, psrm, psm, clockOffset, allowRoleSwitch));
       
  1908 	if(ret==KErrNone)
       
  1909 		{
       
  1910 		iLinkState.SetLinkState(TBTBasebandLinkState::ELinkPending);
       
  1911 		iLinksMan.Baseband().UpdateModel(iDevice.Address(), pkt, EACLLink);
       
  1912 		iLinkState.SetLinkRole(EMaster);
       
  1913 		}
       
  1914 
       
  1915 	return ret;
       
  1916 	}
       
  1917 
       
  1918 TInt CPhysicalLink::SCOConnect()
       
  1919 /**
       
  1920 	A utility service provided to the SCO transport
       
  1921 	We bring up a "default" SCO link, choosing the packet based on what we
       
  1922 	know the controllers can support
       
  1923 */
       
  1924 	{
       
  1925 	LOG_FUNC
       
  1926 	return SCOConnect(EAnySCOPacket);
       
  1927 	}
       
  1928 
       
  1929 TInt CPhysicalLink::SCOConnect(const TUint16 aUserHVPacketTypes)
       
  1930 /**
       
  1931 	A utility service provided to the SCO transport
       
  1932 	We bring up a SCO link which allows only the user specified packet types
       
  1933 	Implementation of SCOSAP::SetOption guarantees aUserHVPacketTypes contains at
       
  1934 	least one valid SCO packet type
       
  1935 */
       
  1936 	{
       
  1937 	LOG_FUNC
       
  1938 	TBTSCOPackets scoPackets = iLinksMan.LinkManagerProtocol().PacketsSupportedLocally().SCOPackets();
       
  1939 
       
  1940 	scoPackets &= aUserHVPacketTypes;
       
  1941 	// combine with remote supported packets
       
  1942 	scoPackets &= iRemoteFeatures.SCOPackets();
       
  1943 
       
  1944 	TInt ret;
       
  1945 
       
  1946 	if (!scoPackets)
       
  1947 		ret = KErrNotSupported;
       
  1948 	else
       
  1949 		{
       
  1950 		// we put all in for now - if HW doesn't support that, the HCI can be changed
       
  1951 		OverridePark();
       
  1952 
       
  1953 		TRAP(ret, iLinksMan.HCIFacade().SCOConnectL(Handle(), scoPackets, BDAddr()));
       
  1954 		if(ret==KErrNone)
       
  1955 			{
       
  1956 			iLinksMan.Baseband().UpdateModel(Handle(), EACLLink, scoPackets, ESCOLink);
       
  1957 			}
       
  1958 		}
       
  1959 	return ret;
       
  1960 	}
       
  1961 
       
  1962 TInt CPhysicalLink::SynchronousConnect(TUint aTransmitBandwidth, TUint aReceiveBandwidth,
       
  1963 		TUint16 aMaxLatency, TUint16 aVoiceSettings,
       
  1964 		TUint8 aRetransmissionEffort, const TBTSyncPacketTypes aUserPacketTypes)
       
  1965 /**
       
  1966 	A utility service provided to the eSCO transport
       
  1967 	We bring up a eSCO link which allows only the user specified packet types
       
  1968 	Implementation of SCOSAP::SetOption guarantees aUserPacketTypes contains at
       
  1969 	least one valid SCO packet type
       
  1970 */
       
  1971 	{
       
  1972 	LOG_FUNC
       
  1973 	TBTSyncPacketTypes escoPackets = iLinksMan.LinkManagerProtocol().PacketsSupportedLocally().SyncPackets();
       
  1974 
       
  1975 	escoPackets &= aUserPacketTypes;
       
  1976 	// combine with remote supported packets
       
  1977 	escoPackets &= iRemoteFeatures.SyncPackets();
       
  1978 
       
  1979 	TInt ret;
       
  1980 
       
  1981 	if (!escoPackets)
       
  1982 		ret = KErrNotSupported;
       
  1983 	else
       
  1984 		{
       
  1985 		// we put all in for now - if HW doesn't support that, the HCI can be changed
       
  1986 		// THCIConnHandle aACLHandle, TUint aTransmitBandwidth, TUint aReceiveBandwidth,
       
  1987 		//	TUint16 aMaxLatency, TUint16 aVoiceSettings, TUint8	 aRetransmissionEffort,
       
  1988 		//	TUint16 aPacketTypeMask
       
  1989 		TRAP(ret, iLinksMan.HCIFacade().SetupSynchronousConnectionCommandL(
       
  1990 			Handle(),
       
  1991 			aTransmitBandwidth, aReceiveBandwidth,
       
  1992 			aMaxLatency, aVoiceSettings, aRetransmissionEffort,
       
  1993 			escoPackets,
       
  1994 			BDAddr()
       
  1995 			));
       
  1996 		if(ret==KErrNone)
       
  1997 			{
       
  1998 			iLinksMan.Baseband().UpdateModel(Handle(), EACLLink, escoPackets, EeSCOLink);
       
  1999 			}
       
  2000 		}
       
  2001 	return ret;
       
  2002 	}
       
  2003 
       
  2004 TInt CPhysicalLink::SubscribeProxySAP(CBTProxySAP& aProxySAP)
       
  2005 	{
       
  2006 	LOG_FUNC
       
  2007 	// a new Proxy SAP wishes to attach to this physical SAP
       
  2008 #ifdef _DEBUG
       
  2009 	// check to see if the same proxy is already there
       
  2010 	TSglQueIter<CBTProxySAP> iter(iProxySAPs);
       
  2011 	while (iter)
       
  2012 		{
       
  2013 		ASSERT_DEBUG(iter++!=&aProxySAP);
       
  2014 		}
       
  2015 #endif
       
  2016 	SubscribeLinkObserver(aProxySAP);
       
  2017 	iProxySAPs.AddLast(aProxySAP);
       
  2018 	Arbitrate();
       
  2019 	return KErrNone;
       
  2020 	}
       
  2021 
       
  2022 void CPhysicalLink::UnsubscribeProxySAP(CBTProxySAP& aProxySAP)
       
  2023 	{
       
  2024 	LOG_FUNC
       
  2025 	ASSERT_DEBUG(!iProxySAPs.IsEmpty());
       
  2026 	iProxySAPs.Remove(aProxySAP);
       
  2027 	UnsubscribeLinkObserver(aProxySAP);
       
  2028 	Arbitrate(); // good time to see what phy properties should be used
       
  2029 	PhysicalLinkUserIdle();
       
  2030 	}
       
  2031 
       
  2032 
       
  2033 TInt CPhysicalLink::AttachLogicalLink(TLinkType aLink, CBTBasebandSAP& aSAP)
       
  2034 	{
       
  2035 	// effectively this part of this class encapsulates the Logical Transports
       
  2036 	// but they're not really worthy of a class - just some understanding that they're
       
  2037 	// not ignored
       
  2038 	LOG_FUNC
       
  2039 	TInt retVal = KErrNone;
       
  2040 
       
  2041 	switch (aLink)
       
  2042 		{
       
  2043 		case EACLLink:
       
  2044 			{
       
  2045 			// it is important for error handling at the end of
       
  2046 			// CPhysicalLink::ConnectionRequest that this remains an
       
  2047 			// append i.e. 'aSAP' is added to the end of the queue
       
  2048 			retVal = iACLLogicalLinks.Append(static_cast<CACLLink*>(&aSAP));
       
  2049 			break;
       
  2050 			}
       
  2051 
       
  2052 		case ESCOLink:
       
  2053 			{
       
  2054 			if (!(iRemoteFeatures.IsSCOLinkSupported()))
       
  2055 				retVal = KErrNotSupported;
       
  2056 			else
       
  2057 				{
       
  2058 				// Don't attach SCO if already exists, avoids confusion with some h/w.
       
  2059 				// .....return the outcome, higher levels depend on this action
       
  2060 				if (iSyncLogicalLink)
       
  2061 					{
       
  2062 					retVal = KErrInUse;
       
  2063 					}
       
  2064 				else
       
  2065 					{
       
  2066 					iSyncLogicalLink = static_cast<CSCOLink*>(&aSAP);
       
  2067 					}
       
  2068 				}
       
  2069 			break;
       
  2070 			}
       
  2071 
       
  2072 		case EeSCOLink:
       
  2073 			{
       
  2074 			if (!(iRemoteFeatures.IsExtendedSCOLinkSupported()))
       
  2075 				retVal = KErrNotSupported;
       
  2076 			else
       
  2077 				{
       
  2078 				if (iSyncLogicalLink)
       
  2079 					{
       
  2080 					retVal = KErrInUse;
       
  2081 					}
       
  2082 				else
       
  2083 					{
       
  2084 					iSyncLogicalLink = static_cast<CeSCOLink*>(&aSAP);
       
  2085 					}
       
  2086 				}
       
  2087 			break;
       
  2088 			}
       
  2089 
       
  2090 		default:
       
  2091 			Panic(EBTUnknownLogicalLink);
       
  2092 		}
       
  2093 
       
  2094 	if (retVal == KErrNone)
       
  2095 		{
       
  2096 		RemoveIdleTimer();
       
  2097 		}
       
  2098 
       
  2099 	return retVal;
       
  2100 	}
       
  2101 
       
  2102 void CPhysicalLink::DetachLogicalLink(TLinkType aLink, CBTBasebandSAP& aSAP)
       
  2103 	{
       
  2104 	LOG_FUNC
       
  2105 	LOG3(_L("CPhysicalLink: Logical Link type %d, 0x%08x detaching from PHY 0x%08x"), aLink, &aSAP, this);
       
  2106 	switch (aLink)
       
  2107 		{
       
  2108 		case EACLLink:
       
  2109 			{
       
  2110 #ifdef _DEBUG
       
  2111 			TInt numFound = 0;
       
  2112 #endif
       
  2113 			for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--)
       
  2114 				{
       
  2115 				if (iACLLogicalLinks[i] == &aSAP)
       
  2116 					{
       
  2117 #ifdef _DEBUG
       
  2118 					numFound++;
       
  2119 #endif
       
  2120 					iACLLogicalLinks.Remove(i); // don't delete - it's not ours!
       
  2121 					}
       
  2122 				}
       
  2123 			__ASSERT_DEBUG(numFound==1, Panic(EBTACLLogicalLinkBadDebind));
       
  2124 			break;
       
  2125 			}
       
  2126 
       
  2127 		case ESCOLink:
       
  2128 		case EeSCOLink:
       
  2129 			{
       
  2130 			__ASSERT_DEBUG(iSyncLogicalLink==&aSAP, Panic(EBTSCOLogicalLinkBadDebind));
       
  2131 			iSyncLogicalLink = NULL;
       
  2132 			break;
       
  2133 			}
       
  2134 
       
  2135 		default:
       
  2136 			Panic(EBTUnknownLogicalLink);
       
  2137 		}
       
  2138 	}
       
  2139 
       
  2140 void CPhysicalLink::PhysicalLinkUserIdle()
       
  2141 	{
       
  2142 	LOG_FUNC
       
  2143 	if(IsPhysicalLinkIdle() && iLinkState.LinkState() == TBTBasebandLinkState::ELinkUp)
       
  2144 		{
       
  2145 		// try to stash device details - juice and last used date
       
  2146 		TTime t;
       
  2147 		t.UniversalTime();
       
  2148 		iDevice.SetUsed(t);
       
  2149 		TRAPD(ignore, StoreDeviceL(ETrue)); //ETrue: new meaning - prevent addition of device in registry
       
  2150 
       
  2151 		if (!iIdleTimerQueued)
       
  2152 			// we don't want to send the read clock offset command more than one
       
  2153 			// here, so just check if we already passed from here.
       
  2154 			{
       
  2155 			// Take this opportunity to get latest info on clock offset
       
  2156 			// so that we can stash it in HR - subsequent connections may then be quicker
       
  2157 			TRAP(ignore, iLinksMan.HCIFacade().ReadClockOffsetL(iHandle));
       
  2158 			// ignore error - was an optimisation
       
  2159 
       
  2160 			// Disconnect the PHY, it is no longer required.
       
  2161 			QueueIdleTimer(KPhysicalLinkIdleTimeout);
       
  2162 			}
       
  2163 		}
       
  2164 	}
       
  2165 
       
  2166 
       
  2167 TBool CPhysicalLink::IsPhysicalLinkIdle() const
       
  2168 	{
       
  2169 	LOG_FUNC
       
  2170 	TBool physicalLinkIdle = ETrue;
       
  2171 	// Check ACL and SCO links.	 If any link is not idle, then the PHY remains
       
  2172 	// active.
       
  2173 	for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--)
       
  2174 		{
       
  2175 		physicalLinkIdle &= iACLLogicalLinks[i]->IsIdle();
       
  2176 		}
       
  2177 
       
  2178 	if(iSyncLogicalLink)
       
  2179 		{
       
  2180 		physicalLinkIdle &= iSyncLogicalLink->IsIdle();
       
  2181 		}
       
  2182 
       
  2183  	if (iPinRequester)
       
  2184  		{
       
  2185  		physicalLinkIdle = EFalse;
       
  2186  		}
       
  2187 
       
  2188  	if (IsAuthenticationPending())
       
  2189  		{
       
  2190  		physicalLinkIdle = EFalse;
       
  2191  		}
       
  2192 
       
  2193 	return physicalLinkIdle;
       
  2194 	}
       
  2195 
       
  2196 
       
  2197 void CPhysicalLink::QueueIdleTimer(TInt aTime)
       
  2198 /**
       
  2199 	Queue idle timer entry.
       
  2200 	When this timer expires, it'll call TryToClose, which actually
       
  2201 	causes the thing to finally close down.
       
  2202 **/
       
  2203 	{
       
  2204 	LOG_FUNC
       
  2205 	if (!iIdleTimerQueued)
       
  2206 		{
       
  2207 		TCallBack cb(TerminateCallback, this);
       
  2208 		iIdleTimerEntry.Set(cb);
       
  2209 		iIdleTimeout = aTime;
       
  2210 		BTSocketTimer::Queue(iIdleTimeout * 1000000, iIdleTimerEntry);
       
  2211 		iIdleTimerQueued = ETrue;
       
  2212 		}
       
  2213 	}
       
  2214 
       
  2215 
       
  2216 void CPhysicalLink::RemoveIdleTimer()
       
  2217 /**
       
  2218 	Called whenever we're opened.
       
  2219 	Checks there are no idle timer entries queued.
       
  2220 **/
       
  2221 	{
       
  2222 	LOG_FUNC
       
  2223 	if (!iIdleTimerQueued)
       
  2224 		{
       
  2225 		// it's fine for callers to just try to remove the timer
       
  2226 		return;
       
  2227 		}
       
  2228 	BTSocketTimer::Remove(iIdleTimerEntry);
       
  2229 	iIdleTimerQueued = EFalse;
       
  2230 	}
       
  2231 
       
  2232 void CPhysicalLink::QueueLPMOverrideTimer(TInt aTimeout)
       
  2233 /**
       
  2234 	Queue LPM Override timer entry.
       
  2235 	When this timer expires, it'll call UndoLPMOverride.
       
  2236 **/
       
  2237 	{
       
  2238 	LOG_FUNC
       
  2239 	__ASSERT_DEBUG(aTimeout!=0, Panic(EBTPhysicalLinksInvalidArgument));
       
  2240 	if (iLPMOverrideTimerQueued)
       
  2241 		{
       
  2242 		BTSocketTimer::Remove(iOverrideLPMTimerEntry);
       
  2243 		}
       
  2244 	BTSocketTimer::Queue(aTimeout, iOverrideLPMTimerEntry);
       
  2245 	iLPMOverrideTimerQueued = ETrue;
       
  2246 	}
       
  2247 
       
  2248 void CPhysicalLink::NotifyStateChange(TBTBasebandEventNotification& aEvent)
       
  2249 	{
       
  2250 	LOG_FUNC
       
  2251 	// If this event is 'physical link down' / 'physical link error' then any ProxySAP
       
  2252 	// subscribers will unsubscribe as a result of PhysicalLinkChange being called.
       
  2253 	// This will result in the entry being removed from the iBasebandSubscribers array.
       
  2254 	// Consequently the array must be traversed from end to start.
       
  2255 	TDblQueIter<TPhysicalLinkObserverQLink> iter(iBasebandSubscribers);
       
  2256 	TPhysicalLinkObserverQLink* l;
       
  2257 	while ((l=iter++)!=NULL)
       
  2258 		{
       
  2259 		l->Item()->PhysicalLinkChange(aEvent, *this);
       
  2260 		}
       
  2261 
       
  2262 	if(((aEvent.EventType() & ENotifyActiveMode) ||
       
  2263 		(aEvent.EventType() & ENotifySniffMode)||
       
  2264 		(aEvent.EventType() & ENotifyParkMode)||
       
  2265 		(aEvent.EventType() & ENotifyHoldMode)) &&
       
  2266 		(aEvent.ErrorCode() == KErrNone))
       
  2267 		{
       
  2268 		iArbitrationDelay->Start();
       
  2269 		}
       
  2270 	}
       
  2271 
       
  2272 /*static*/ TInt CPhysicalLink::TerminateCallback(TAny* aCPhysicalLink)
       
  2273 	{
       
  2274 	LOG_STATIC_FUNC
       
  2275 	CPhysicalLink* c = reinterpret_cast<CPhysicalLink*>(aCPhysicalLink);
       
  2276 	c->iIdleTimerQueued = EFalse;
       
  2277 
       
  2278 	TInt retVal = EFalse;
       
  2279 	
       
  2280 	// Queue another idle timer in case this disconnect fails
       
  2281 	
       
  2282 	// Check if the physical link is still idle after the timer.
       
  2283 	if(c->IsPhysicalLinkIdle() && c->iLinkState.LinkState() == TBTBasebandLinkState::ELinkUp)
       
  2284 		{
       
  2285 		// Increase the idle time for the next callback by just over 50%
       
  2286 		TInt newIdleTime = (c->iIdleTimeout * 3)/2 + 1;
       
  2287 		if (newIdleTime > KMaxPhysicalLinkIdleTimeout)
       
  2288 			{
       
  2289 			newIdleTime = KMaxPhysicalLinkIdleTimeout;
       
  2290 			}
       
  2291 
       
  2292 		c->QueueIdleTimer(newIdleTime);
       
  2293 		if (c->Terminate(ERemoteUserEndedConnection) == KErrNone)
       
  2294 			{
       
  2295 			retVal = EFalse;
       
  2296 			}
       
  2297 		else
       
  2298 			{
       
  2299 			retVal = ETrue;
       
  2300 			}
       
  2301 		}
       
  2302 	return retVal;
       
  2303 	}
       
  2304 
       
  2305 TInt CPhysicalLink::Terminate(THCIErrorCode aReason)
       
  2306 	{
       
  2307 	LOG_FUNC
       
  2308 	TInt err = KErrNone;
       
  2309 
       
  2310 	if (iLinkState.LinkState() == TBTBasebandLinkState::ELinkPending)
       
  2311 		{
       
  2312 		// If the Link is not yet up then we cannot know the correct connection handle
       
  2313 		// to disconnect so remember the request so we disconnect the link straight away
       
  2314 		// after it does come up.
       
  2315 		iDisconnectRequested = ETrue;
       
  2316 		}
       
  2317 	else
       
  2318 		{
       
  2319 		__ASSERT_DEBUG(iLinkState.LinkState() == TBTBasebandLinkState::ELinkUp, Panic(EInvalidLinkStateDuringDisconnect));
       
  2320 
       
  2321 		TRAP(err, iDisconnectCtrl.Disconnect(aReason));
       
  2322 		}
       
  2323 
       
  2324 	return err;
       
  2325 	}
       
  2326 
       
  2327 void CPhysicalLink::SetModesAllowed(TUint8 aModesAllowed, TBool aRoleSwitchAllowed)
       
  2328 	{
       
  2329 	LOG_FUNC
       
  2330 	TBTLinkModeSet supportedModes = iRemoteFeatures.LinkModes();
       
  2331 	aModesAllowed &= supportedModes;
       
  2332 	aRoleSwitchAllowed &= IsRoleSwitchSupported();
       
  2333 
       
  2334 	if(aModesAllowed != iLinkPolicy.LowPowerModePolicy() ||
       
  2335 	   aRoleSwitchAllowed != iLinkPolicy.IsSwitchAllowed())
       
  2336 		{
       
  2337 		TLinkPolicy tempPolicy;
       
  2338 		tempPolicy.SetModesAllowed(aModesAllowed);
       
  2339 		tempPolicy.SetSwitchAllowed(aRoleSwitchAllowed);
       
  2340 
       
  2341 		TRAPD(err, iLinksMan.HCIFacade().WriteLinkPolicySettingsL(Handle(), tempPolicy.LinkPolicy()));
       
  2342 
       
  2343 		if (err==KErrNone)
       
  2344 			{
       
  2345 			iLinkPolicy = tempPolicy;
       
  2346 			}
       
  2347 		}
       
  2348 	}
       
  2349 
       
  2350 void CPhysicalLink::NotifyLogicalLinkDown(TPhysicalLinkPort aPort)
       
  2351 	{
       
  2352 	LOG_FUNC
       
  2353 	switch (aPort)
       
  2354 		{
       
  2355 		case EACLLink:
       
  2356 			{
       
  2357 			for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--)
       
  2358 				{
       
  2359 				// subscribers will unsubscribe as a result of this
       
  2360 				// This will result in the entry being removed from the iACLLogicalLinks array.
       
  2361 				// Consequently the array must be traversed from end to start.
       
  2362 				iACLLogicalLinks[i]->Disconnection();
       
  2363 				}
       
  2364 			break;
       
  2365 			}
       
  2366 		case ESCOLink:
       
  2367 		case EeSCOLink:
       
  2368 			{
       
  2369 			if (iSyncLogicalLink)
       
  2370 				{
       
  2371 				iSyncLogicalLink->Disconnection();
       
  2372 				}
       
  2373 			break;
       
  2374 			}
       
  2375 
       
  2376 		default:
       
  2377 			Panic(EBTPhysicalLinkBadPort);
       
  2378 		}
       
  2379 	}
       
  2380 
       
  2381 void CPhysicalLink::NotifyLogicalLinkUp(const TBTConnect& aConnect)
       
  2382 	{
       
  2383 	LOG_FUNC
       
  2384 	switch (aConnect.iLinkType)
       
  2385 		{
       
  2386 		case EACLLink:
       
  2387 			{
       
  2388 			for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--)
       
  2389 				{
       
  2390 				// all of them are open
       
  2391 				iACLLogicalLinks[i]->ConnectComplete(aConnect);
       
  2392 				}
       
  2393 			break;
       
  2394 			}
       
  2395 
       
  2396 		case ESCOLink:
       
  2397 		case EeSCOLink:
       
  2398 			{
       
  2399 			if (iSyncLogicalLink)
       
  2400 				{
       
  2401 				iSyncLogicalLink->ConnectComplete(aConnect);
       
  2402 				}
       
  2403 			break;
       
  2404 			}
       
  2405 
       
  2406 		default:
       
  2407 			Panic(EBTPhysicalLinkBadPort);
       
  2408 		}
       
  2409 	}
       
  2410 
       
  2411 void CPhysicalLink::NotifyLogicalSyncLinkUp(const TBTConnect& aConnect, const TBTSyncConnectOpts& aSyncOpts)
       
  2412 	{
       
  2413 	LOG_FUNC
       
  2414 	switch (aConnect.iLinkType)
       
  2415 		{
       
  2416 		case ESCOLink:
       
  2417 		case EeSCOLink:
       
  2418 			{
       
  2419 			if (iSyncLogicalLink)
       
  2420 				{
       
  2421 				iSyncLogicalLink->SyncConnectComplete(aConnect, aSyncOpts);
       
  2422 				}
       
  2423 			break;
       
  2424 			}
       
  2425 
       
  2426 		default:
       
  2427 			Panic(EBTPhysicalLinkBadPort);
       
  2428 		}
       
  2429 	}
       
  2430 
       
  2431 
       
  2432 void CPhysicalLink::NotifyLogicalLinkError(TPhysicalLinkPort aPort, TInt aError)
       
  2433 	{
       
  2434 	LOG_FUNC
       
  2435 	switch (aPort)
       
  2436 		{
       
  2437 		case EACLLink:
       
  2438 			{
       
  2439 			for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--)
       
  2440 				{
       
  2441 				// all of them are open
       
  2442 				iACLLogicalLinks[i]->Error(aError);
       
  2443 				}
       
  2444 			break;
       
  2445 			}
       
  2446 
       
  2447 		case ESCOLink:
       
  2448 		case EeSCOLink:
       
  2449 			{
       
  2450 			if (iSyncLogicalLink)
       
  2451 				{
       
  2452 				iSyncLogicalLink->Error(aError);
       
  2453 				}
       
  2454 			break;
       
  2455 			}
       
  2456 
       
  2457 		default:
       
  2458 			Panic(EBTPhysicalLinkBadPort);
       
  2459 		}
       
  2460 	}
       
  2461 
       
  2462 
       
  2463 TBool CPhysicalLink::IsModeSupportedRemotely(TBTLinkMode aMode) const
       
  2464 	{
       
  2465 	LOG_FUNC
       
  2466 	return iRemoteFeatures.LinkModes() & aMode;
       
  2467 	}
       
  2468 
       
  2469 TBool CPhysicalLink::IsEncryptionPauseResumeSupported() const
       
  2470 	{
       
  2471 	LOG_FUNC
       
  2472 	return (iLinksMan.LinkManagerProtocol().IsEncryptionPauseResumeSupportedLocally() && iRemoteFeatures.IsEncryptionPauseResumeSupported());
       
  2473 	}
       
  2474 
       
  2475 TBool CPhysicalLink::IsEncryptionSupported() const
       
  2476 	{
       
  2477 	LOG_FUNC
       
  2478 	return (iRemoteFeatures.IsEncryptionSupported() && iLinksMan.LinkManagerProtocol().IsEncryptionSupportedLocally());
       
  2479 	}
       
  2480 
       
  2481 TBool CPhysicalLink::IsRoleSwitchSupported() const
       
  2482 	{
       
  2483 	LOG_FUNC
       
  2484 	// the physical link _can_ switch when encryption is on - see RequestChangeRole
       
  2485 	return (iRemoteFeatures.IsRoleSwitchSupported() && iLinksMan.RoleSwitchAllowed());
       
  2486 	}
       
  2487 
       
  2488 
       
  2489 //
       
  2490 // Change the packet types allowed on the link.
       
  2491 // Note that this is only suitable for use on ACL and old-style (pre eSCO) SCO links.
       
  2492 //
       
  2493 TInt CPhysicalLink::ChangeConnectionPacketType(TUint16 aType)
       
  2494 	{
       
  2495 	LOG_FUNC
       
  2496 	TInt rerr = KErrNone;
       
  2497 
       
  2498 	// Build a mask of locally supported packet types (we shouldn't care about
       
  2499 	// what the remote supports (this is alluded to in the spec) probably
       
  2500 	// because they can change too.
       
  2501 
       
  2502 	// DM1, DH1 and HV1 packets are always supported.
       
  2503 	TUint16 supportedTypes = EPacketsDM1 | EPacketsDH1 | EPacketsHV1;
       
  2504 
       
  2505 	// get extra locally-supported packets (our controller may not support things)
       
  2506 	TBTFeatures localPackets = iLinksMan.LinkManagerProtocol().PacketsSupportedLocally();
       
  2507 
       
  2508 	// 3 slot ACL packets
       
  2509 	if (localPackets[ESupportedThreeSlotPacketsBit])
       
  2510 		{
       
  2511 		supportedTypes |= (EPacketsDM3 | EPacketsDH3);
       
  2512 		}
       
  2513 
       
  2514 	// 5 slot ACL packets
       
  2515 	if (localPackets[ESupportedFiveSlotPacketsBit])
       
  2516 		{
       
  2517 		supportedTypes |= (EPacketsDM5 | EPacketsDH5);
       
  2518 		}
       
  2519 
       
  2520 	// HV2 single-slot packets
       
  2521 	if (localPackets[ESupportedHV2PacketsBit])
       
  2522 		{
       
  2523 		supportedTypes |= EPacketsHV2;
       
  2524 		}
       
  2525 
       
  2526 	// HV3 single-slot packets
       
  2527 	if (localPackets[ESupportedHV3PacketsBit])
       
  2528 		{
       
  2529 		supportedTypes |= EPacketsHV3;
       
  2530 		}
       
  2531 
       
  2532 	// Note: If one of the following EDR bits is set it indicates that the EDR
       
  2533 	// packet type shall NOT be used on this physical link. However, we must
       
  2534 	// not set any packet types that are not supported, so check first.
       
  2535 
       
  2536 	// EDR 2Mbps
       
  2537 	if (localPackets[EEDR_ACL_2MbpsModeBit])
       
  2538 		{
       
  2539 		supportedTypes |= EPackets2_DH1;
       
  2540 		// EDR 3 slot ACL packets
       
  2541 		if (localPackets[ESupportedEDRThreeSlotPacketsBit])
       
  2542 			{
       
  2543 			supportedTypes |= EPackets2_DH3;
       
  2544 			}
       
  2545 		// EDR 5 slot ACL packets
       
  2546 		if (localPackets[ESupportedEDRFiveSlotPacketsBit])
       
  2547 			{
       
  2548 			supportedTypes |= EPackets2_DH5;
       
  2549 			}
       
  2550 
       
  2551 		// EDR 3Mbps - Have to have 2Mbps to have 3Mbps
       
  2552 		if (localPackets[EEDR_ACL_3MbpsModeBit])
       
  2553 			{
       
  2554 			supportedTypes |= EPackets3_DH1;
       
  2555 			// EDR 3 slot ACL packets
       
  2556 			if (localPackets[ESupportedEDRThreeSlotPacketsBit])
       
  2557 				{
       
  2558 				supportedTypes |= EPackets3_DH3;
       
  2559 				}
       
  2560 			// EDR 5 slot ACL packets
       
  2561 			if (localPackets[ESupportedEDRFiveSlotPacketsBit])
       
  2562 				{
       
  2563 				supportedTypes |= EPackets3_DH5;
       
  2564 				}
       
  2565 			}
       
  2566 		}
       
  2567 
       
  2568 	supportedTypes &= aType;
       
  2569 	// Check if the new supported types differ from the current configuration.
       
  2570 	if(supportedTypes != iLinkState.PacketTypes())
       
  2571 		{
       
  2572 		rerr = iLinksMan.HCIFacade().ChangeConnectionPacketType(iHandle, supportedTypes);
       
  2573 		}
       
  2574 
       
  2575 	if(rerr == KErrNone)
       
  2576 		{
       
  2577 		iConnectionPacketTypeChanged = ETrue;
       
  2578 		}
       
  2579 
       
  2580 	return rerr;
       
  2581 	}
       
  2582 
       
  2583 TInt CPhysicalLink::ExitMode(TBTLinkMode aMode)
       
  2584 	{
       
  2585 	LOG_FUNC
       
  2586 	return iLowPowModeCtrl.ExitMode(aMode, iHandle);
       
  2587 	}
       
  2588 
       
  2589 TInt CPhysicalLink::RequestMode(TBTLinkMode aMode)
       
  2590 	{
       
  2591 	LOG_FUNC
       
  2592 	if (!IsConnected())
       
  2593 		return KErrDisconnected;
       
  2594 
       
  2595 	// if active mode is required, try to exit whatever Low Power mode we are in -
       
  2596 	// if neither sniff nor park nothing will happen.
       
  2597 	if(aMode == EActiveMode)
       
  2598 		{
       
  2599 		return ExitMode(iLinkState.LinkMode());
       
  2600 		}
       
  2601 
       
  2602 	// now request this connection goes to requested mode
       
  2603 	return iLowPowModeCtrl.ChangeMode(aMode, iHandle);
       
  2604 	}
       
  2605 
       
  2606 TInt CPhysicalLink::RequestChangeRole(TBTBasebandRole aRole)
       
  2607 	{
       
  2608 	LOG_FUNC
       
  2609 	TInt err = KErrNone;
       
  2610 
       
  2611 	// Check that the requested role is not the current role.
       
  2612 	if(iLinkState.LinkRole() != aRole)
       
  2613 		{
       
  2614 		if(!iLinkPolicy.IsSwitchAllowed())
       
  2615 			{
       
  2616 			err = KErrNotSupported;
       
  2617 			}
       
  2618 
       
  2619 		// 1) Role switch is not allowed if there is a sync connection
       
  2620 		//    (or there is a sync connection negotiation in progress)
       
  2621 		else if (HasSyncLink() || SyncConnectPending())
       
  2622 			{
       
  2623 			err = KErrNotReady;
       
  2624 			}
       
  2625 
       
  2626 		// 2) Check if role switch is supported on the remote device
       
  2627 		else if (!IsRoleSwitchSupported())
       
  2628 			{
       
  2629  			err = KErrNotSupported;
       
  2630 			}
       
  2631 
       
  2632 		// 3) Check if role switch is supported locally
       
  2633  		else if (!iLinksMan.LinkManagerProtocol().IsRoleSwitchSupportedLocally())
       
  2634  			{
       
  2635  			err = KErrNotSupported;
       
  2636  			}
       
  2637 
       
  2638 		// Same role request is already with LinkMgr, or most probably running just now
       
  2639 		else if (iRoleSwitcher)
       
  2640 			{
       
  2641 			LOG(_L("CPhysicalLink - Same role change in progress!"))
       
  2642 			err = KErrNone;
       
  2643 			}
       
  2644 
       
  2645 		// ok to change role
       
  2646 		// we kick off a role switcher state machine, to remove LPM and encryption, prior to
       
  2647 		// role switch
       
  2648 		else
       
  2649 			{
       
  2650 			TRAP(err, iRoleSwitcher = CRoleSwitcher::NewL(iLinksMan, *this, aRole));
       
  2651 			}
       
  2652 		}
       
  2653 #ifdef _DEBUG
       
  2654 	else
       
  2655 		{
       
  2656 		LOG(_L("CPhysicalLink We are in requested role!!!"))		
       
  2657 		}
       
  2658 #endif
       
  2659 
       
  2660 	return err;
       
  2661 	}
       
  2662 
       
  2663 void CPhysicalLink::AsyncDeleteRoleSwitcher()
       
  2664 	{
       
  2665 	LOG_FUNC
       
  2666 	iRoleSwitchCompleteCallBack->CallBack();
       
  2667 	}
       
  2668 
       
  2669 /*static*/ TInt CPhysicalLink::RoleSwitchCompleteCallBack(TAny* aPhysicalLink)
       
  2670 	{
       
  2671 	LOG_STATIC_FUNC
       
  2672 	CPhysicalLink* physicalLink = static_cast<CPhysicalLink*>(aPhysicalLink);
       
  2673 	physicalLink->DeleteRoleSwitcher();
       
  2674 	return EFalse;
       
  2675 	}
       
  2676 
       
  2677 void CPhysicalLink::DeleteRoleSwitcher()
       
  2678 	{
       
  2679 	LOG_FUNC
       
  2680 	delete iRoleSwitcher;
       
  2681 	iRoleSwitcher = NULL;
       
  2682 	}
       
  2683 
       
  2684 TBool CPhysicalLink::IsEncryptionDisabledForRoleSwitch() const
       
  2685 /**
       
  2686 	If link is encrypted, but role switcher temporarily disabled encryption, returns true.
       
  2687 **/
       
  2688 	{
       
  2689 	LOG_FUNC
       
  2690 	if (iRoleSwitcher)
       
  2691 		{
       
  2692 		return iRoleSwitcher->IsEncryptionDisabledForRoleSwitch();
       
  2693 		}
       
  2694 	return EFalse;
       
  2695 	}
       
  2696 
       
  2697 TInt CPhysicalLink::OverridePark()
       
  2698 /**
       
  2699 	A request has come in that requires us to ensure we are not parked.
       
  2700 
       
  2701 	Try to make it happen
       
  2702 **/
       
  2703 	{
       
  2704 	LOG_FUNC
       
  2705 	iOverrideParkRequests = ETrue;
       
  2706 
       
  2707 	// Only arbitrate if Park mode is currently active.
       
  2708 	TInt rerr = KErrNone;
       
  2709 	if(iLinkState.LinkMode() & EParkMode)
       
  2710 		{
       
  2711 		rerr = Arbitrate();
       
  2712 		}
       
  2713 	return rerr;
       
  2714 	}
       
  2715 
       
  2716 TInt CPhysicalLink::UndoOverridePark()
       
  2717 /**
       
  2718 	A need to ensure we are not parked has gone.
       
  2719 
       
  2720 	Try to go back to power mode resulting from an unoverriden Arbitrate
       
  2721 **/
       
  2722 	{
       
  2723 	LOG_FUNC
       
  2724 	iOverrideParkRequests = EFalse;
       
  2725 
       
  2726 	//Arbitrate even if there isn't an outstanding local park mode request beacuse
       
  2727 	//the remote device may be requesting park mode.
       
  2728 	return Arbitrate();
       
  2729 	}
       
  2730 
       
  2731 TInt CPhysicalLink::OverrideLPMWithTimeout(TUint aTimeout)
       
  2732 	{
       
  2733 	LOG_FUNC
       
  2734 	if(aTimeout == 0)
       
  2735 		{
       
  2736 		return KErrNone; //facility not wanted
       
  2737 		}
       
  2738 
       
  2739 	TInt rerr = OverrideLPM();
       
  2740 	QueueLPMOverrideTimer(aTimeout);
       
  2741 
       
  2742 	return rerr;
       
  2743 	}
       
  2744 
       
  2745 TInt CPhysicalLink::OverrideLPM()
       
  2746 /**
       
  2747 	A request has come in that requires us to ensure we are not using
       
  2748 	an LPM (low power mode).
       
  2749 
       
  2750 	Try to make it happen
       
  2751 **/
       
  2752 	{
       
  2753 	LOG_FUNC
       
  2754 	iOverrideLPMRequests = ETrue;
       
  2755 
       
  2756 	return Arbitrate();
       
  2757 	}
       
  2758 
       
  2759 /*static*/ TInt CPhysicalLink::OverrideLPMTimeoutCallback(TAny* aCPhysicalLink)
       
  2760 	{
       
  2761 	LOG_STATIC_FUNC	
       
  2762 	CPhysicalLink* c = reinterpret_cast<CPhysicalLink*>(aCPhysicalLink);
       
  2763 	TInt err = c->UndoOverrideLPM();
       
  2764 	//we deliberately ignore this return value because we can't do anything to correct the error situation
       
  2765 	if (KErrNone != err)
       
  2766 		{
       
  2767 		LOG2(_L("Physical link: UndoOverrideLPM returned an error %d on the connection 0x%08x"), err, c);
       
  2768 		}
       
  2769 	c->iLPMOverrideTimerQueued = EFalse;
       
  2770 	return KErrNone;
       
  2771 	}
       
  2772 
       
  2773 TInt CPhysicalLink::UndoOverrideLPM()
       
  2774 /**
       
  2775 	A need to ensure we are not in LPM has gone.
       
  2776 
       
  2777 	Try to go back to power mode resulting from an unoverriden Arbitrate
       
  2778 **/
       
  2779 	{
       
  2780 	LOG_FUNC
       
  2781 	iOverrideLPMRequests = EFalse;
       
  2782 
       
  2783 	// Call Arbitrate(...) to determine if removing the override requires any change to
       
  2784 	// the physical link state.
       
  2785 	return Arbitrate();
       
  2786 	}
       
  2787 
       
  2788 // security stuff
       
  2789 // connection looks after this as it may be passively initiated and there wont
       
  2790 // be a accessrequester in those situations
       
  2791 
       
  2792 void CPhysicalLink::PinRequest(const TBTDevAddr& aAddr, MPINCodeResponseHandler& aRequester)
       
  2793 	{
       
  2794 	LOG_FUNC
       
  2795 	// If we receive a Pin_Request while another is outstanding then the controller is faulty. 
       
  2796 	// So we just ignore any multiple requests, as they do not make sense.
       
  2797 	// However, in UDEB we panic to raise awareness that the hardware is behaving incorrectly.
       
  2798 	__ASSERT_DEBUG(!iPinRequester, Panic(EBTConnectionPINRequestedTwice));
       
  2799 
       
  2800 	SetAuthenticationPending(EPinRequestPending); // if not already set (because the remote initiated authentication).
       
  2801 
       
  2802 	if (iPinRequester)
       
  2803 		{
       
  2804 		return;
       
  2805 		}
       
  2806 
       
  2807 	__ASSERT_DEBUG(aAddr == BDAddr(), Panic(EBTConnectionBadDeviceAddress));
       
  2808 	
       
  2809 	if(!IsPairable())
       
  2810 		{
       
  2811 		aRequester.PINCodeRequestNegativeReply(aAddr);
       
  2812 		return;
       
  2813 		}
       
  2814 
       
  2815 	TBTPinCode pinCode;
       
  2816 	if(iLinksMan.PrefetchMan().IsPrefetchAvailable(aAddr, pinCode))
       
  2817 		{
       
  2818 		aRequester.PINCodeRequestReply(aAddr, pinCode);
       
  2819 		return;
       
  2820 		}
       
  2821 
       
  2822 	iPinHandler = &aRequester;
       
  2823 
       
  2824 	TRAPD(err, DoPinRequestL(aAddr, *this)); // physical links will proxy a request.
       
  2825 
       
  2826 	// if there is an error we should reply PIN negative...
       
  2827 	if (err)
       
  2828 		{
       
  2829 		iPinHandler->PINCodeRequestNegativeReply(aAddr);
       
  2830 		iPinHandler = NULL;
       
  2831 		}
       
  2832 	}
       
  2833 
       
  2834 void CPhysicalLink::DoPinRequestL(const TBTDevAddr& aAddr, MPINCodeResponseHandler& aResponseHandler)
       
  2835 	{
       
  2836 	LOG_FUNC
       
  2837 	// Bluetooth is fairly poor at allowing name requests on partially connected links
       
  2838 	// this typically occurs in security mode 3
       
  2839 
       
  2840 	// find out is it locally or remotley initiated authentication ...
       
  2841 	TBool locallyInitiated; //Authentication
       
  2842 	TBool strongKeyRequired;
       
  2843 	TUint minPasskeyLength=0;
       
  2844 	TUint recommendedPasskeyLength=0;
       
  2845 
       
  2846 	iLinksMan.SecMan().GetPassKeyLengthAndOriginator(aAddr, minPasskeyLength, locallyInitiated, strongKeyRequired);
       
  2847 
       
  2848 	/* If we have an activeAccessRequester and authentication was not actually required,
       
  2849 	 * this is a speculative authentication.
       
  2850 	 * In that case we did not expect to get a PinRequest. 
       
  2851 	 * We leave as the link already exists, causing the PinRequest to get a negative reply.
       
  2852 	 */
       
  2853 	if(iDevice.IsValidLinkKey())
       
  2854 		{
       
  2855 		CBTAccessRequester* activeAccessRequester = iLinksMan.SecMan().FindActiveAccessRequester(aAddr);
       
  2856 		if (activeAccessRequester)
       
  2857 			{
       
  2858 			if (!activeAccessRequester->AuthenticationRequired())
       
  2859 				{
       
  2860 				User::Leave(KErrAlreadyExists);
       
  2861 				}
       
  2862 			}
       
  2863 		}
       
  2864 
       
  2865 	/* If link is already authenticated with a link key greater than the currently required minimum key length, then store 
       
  2866 	 * the current passkey length as a recommended length. If this recommendation is followed, then the strength of 
       
  2867 	 * the current link key will be maintained. This recommended length is made available via 
       
  2868 	 * TBTPinCodeEntryNotifierParams::RecommendedPinCodeMinLength().
       
  2869 	 */
       
  2870 	TUint devicePasskeyLength = iDevice.PassKeyLength();
       
  2871 	if(iDevice.IsValidLinkKey()&&devicePasskeyLength>minPasskeyLength)
       
  2872 		{
       
  2873 		//Ignore the previous link key length if it is not at least the minimum we require now anyway.
       
  2874 		recommendedPasskeyLength=devicePasskeyLength;
       
  2875 		}
       
  2876 	else
       
  2877 		{
       
  2878 		//Recommend the currently required minimum length.
       
  2879 		recommendedPasskeyLength=minPasskeyLength;
       
  2880 		}
       
  2881 
       
  2882 	iPinRequester = CBTPinRequester::NewL(BDAddr(), aResponseHandler, iLinksMan.SecMan(),
       
  2883 										  minPasskeyLength, locallyInitiated, strongKeyRequired, recommendedPasskeyLength);
       
  2884 	}
       
  2885 
       
  2886 TBool CPhysicalLink::LinkKeyRequestPending()
       
  2887 	{
       
  2888 	LOG_FUNC
       
  2889 	return iAuthStateMask & ELinkKeyRequestPending;
       
  2890 	}
       
  2891 
       
  2892 void CPhysicalLink::SetAuthenticationPending(TUint8 aState)
       
  2893 	{
       
  2894 	LOG_FUNC
       
  2895 	iAuthStateMask |= aState;
       
  2896 	LOG1(_L("SetAuthenticationPending: set state [%d] in an authentication state mask"), aState);
       
  2897 	}
       
  2898 
       
  2899 void CPhysicalLink::AuthenticationComplete(TUint8 aState)
       
  2900 	{
       
  2901 	LOG_FUNC
       
  2902 	iAuthStateMask &= ~aState;
       
  2903 	LOG1(_L("AuthenticationComplete: reset state [%d] in an authentication state mask"), aState);
       
  2904 	PhysicalLinkUserIdle();
       
  2905 	}
       
  2906 
       
  2907 TBool CPhysicalLink::IsPairable() const
       
  2908 	{
       
  2909 	// Determines if pairing can be performed on the physical link;
       
  2910 	// it previously was determined by the PIN code notifier, but with
       
  2911 	// 2.1 pairable mode has been replaced with bondable mode and
       
  2912 	// so being pairable is now a function of the security level
       
  2913 	// the device is operating under.
       
  2914 	// Here the policy is as follows:
       
  2915 	//
       
  2916 	// Pairable if...
       
  2917 	// 1) Not in paired only connections mode
       
  2918 	// OR 
       
  2919 	// 2) The link is already authenticated
       
  2920 	// OR
       
  2921 	// 3) A logical link was locally initiated
       
  2922 	// OR
       
  2923 	// 4) A dedicated bonding attempt is in progress
       
  2924 	// (it might be better to migrate dedicated bonding above the logical
       
  2925 	// link to remove this special case...)
       
  2926 	//
       
  2927 	// This policy provides strong security for while not applying
       
  2928 	// blanket restricts on explicit user requests (i.e. outgoing
       
  2929 	// connections).
       
  2930 	TBool locallyInitiatedLogicalLink = EFalse;
       
  2931 	for (TInt i=iACLLogicalLinks.Count()-1; i>=0; i--)
       
  2932 		{
       
  2933 		if(iACLLogicalLinks[i]->IsLocallyInitiated())
       
  2934 			{
       
  2935 			locallyInitiatedLogicalLink = ETrue;
       
  2936 			}
       
  2937 		}
       
  2938 	return (!iLinksMan.IsAcceptPairedOnlyMode()) 
       
  2939 		|| iLinkState.Authenticated() 
       
  2940 		|| locallyInitiatedLogicalLink
       
  2941 		|| iLinksMan.SecMan().IsDedicatedBondingAttempted(iDevice.Address());
       
  2942 	}
       
  2943 
       
  2944 void CPhysicalLink::DeleteLinkKeyL()
       
  2945 /**
       
  2946 ensure that the LinkKey is removed from the device in the registry
       
  2947 **/
       
  2948 	{
       
  2949 	LOG_FUNC
       
  2950 	CBTLinkKeyDeleter* deleter = CBTLinkKeyDeleter::NewL(iRegSess, *this);
       
  2951 	iRegistryHelpers.AddLast(*deleter);
       
  2952 	deleter->Start(BDAddr());
       
  2953 	}
       
  2954 
       
  2955 TBool CPhysicalLink::IsConnectionRequestPending() const
       
  2956 	{
       
  2957 	LOG_FUNC
       
  2958 	return iPendingConnection;
       
  2959 	}
       
  2960 
       
  2961 void CPhysicalLink::PendingConnectionRequest(TInt /*aError*/)
       
  2962 	{
       
  2963 	LOG_FUNC
       
  2964  	__ASSERT_DEBUG(iPendingConnection, Panic(EPhysicalLinkNoConnectionPending));
       
  2965 
       
  2966  	// Note: We could do something clever with the error code returned
       
  2967  	// to prevent us thrashing in OOM situations, but it is complicated.
       
  2968  	// We want to try again as now the pending connection address may
       
  2969  	// now be in the cache even if we have a non-KErrNone error code,
       
  2970  	// and so with that we will proceed sucessfully.  But if we are
       
  2971  	// deferred we may end up here again and again with, perhaps with a
       
  2972  	// KErrNoMemory for example ... which is how the thrashing will occur.
       
  2973  	// This thrashing will be limited however by the "Connection Accept
       
  2974  	// Timeout" imposed by the controller on the host, and for this
       
  2975  	// reason we live with it.
       
  2976 	iPendingConnection = EFalse;
       
  2977 	ConnectionRequest(iLastPendingConnection);
       
  2978 	}
       
  2979 
       
  2980 TBool CPhysicalLink::IsPasskeyMinLengthOK()
       
  2981 	{
       
  2982 	LOG_FUNC
       
  2983 /**
       
  2984 	check whether current passkey (retrieved from BTRegistry) is long enough to fulfill user passkey requirement
       
  2985 	It must be called only when iDevice is ready and has LinkKey
       
  2986 **/
       
  2987 	__ASSERT_DEBUG(iDeviceResult==KErrNone && iDevice.IsValidLinkKey(),
       
  2988 		 Panic(EBTPhysicalLinkNotAuthenticated));
       
  2989 
       
  2990 	TUint newMinPasskeyLength=0;
       
  2991 	TBool isPasskeyMinLengthOK = ETrue;
       
  2992 
       
  2993 	TBool locInit, strongKey;
       
  2994 	iLinksMan.SecMan().GetPassKeyLengthAndOriginator( iDevice.Address(), newMinPasskeyLength, locInit, strongKey);
       
  2995 
       
  2996 	TBTPinCode currentPassKey = iDevice.PassKey();
       
  2997 
       
  2998 	// check current PIN code length against user requirement
       
  2999 	if ( newMinPasskeyLength )
       
  3000 		{
       
  3001 		 if ( newMinPasskeyLength > currentPassKey().iLength )
       
  3002 			{
       
  3003 			// longer PIN code is requested
       
  3004 			isPasskeyMinLengthOK = EFalse;
       
  3005 			}
       
  3006 		}
       
  3007 
       
  3008 	return isPasskeyMinLengthOK;
       
  3009 	}
       
  3010 
       
  3011 void CPhysicalLink::LinkKeyRequest(const TBTDevAddr& aAddr, MLinkKeyResponseHandler& /*aRequester*/)
       
  3012 	{
       
  3013 	LOG_FUNC
       
  3014 	// we don't keep a copy of the device record - we just leave the one copy with
       
  3015 	// the baseband - it can tell us if there's a link key
       
  3016 	// we can tell if the baseband has the device record or not
       
  3017 
       
  3018 	SetAuthenticationPending(ELinkKeyRequestPending); //authentication process started by remote
       
  3019 
       
  3020 	// If the ACL to the peer device is not yet connected, and the peer has initiated
       
  3021 	// authentication then it must be in security mode 3.  This information is stored and
       
  3022 	// if the connection completes the link will be set as authenticated.
       
  3023 	if (!IsConnected())
       
  3024 		{
       
  3025 		iPeerInSecurityMode3 = ETrue;
       
  3026 		}
       
  3027 
       
  3028 	if(!iPeerInSecurityMode3 && iLinksMan.SecMan().IsDedicatedBondingAttempted(iDevice.Address()))
       
  3029 		{
       
  3030 		// If we are doing DedicatedBonding then we should ignore the existing linkkey
       
  3031 		// in an attempt to generate a stronger one if possible.
       
  3032 		// Security mode 3 is a odd case - because we get what looks like double pairing (the remote
       
  3033 		// initiated pairing on connection, then the dedicated bonding pairing).  So we have removed
       
  3034 		// this feature for security mode 3 devices...they will have to suffer for their transgressions
       
  3035 		LOG(_L("CPhysicalLink: Dedicated bonding attempt - Sending link key request negative reply"));
       
  3036 		iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr);
       
  3037 		iRequireAuthenticatedLinkKey = EFalse;
       
  3038 		}
       
  3039 	else if (iDeviceResult==KErrNone && iDevice.IsValidLinkKey())
       
  3040 		{
       
  3041 		if (iLinksMan.SecMan().DebugMode() && iDevice.LinkKeyType() != ELinkKeyDebug)
       
  3042 			{
       
  3043 			LOG(_L("CPhysicalLink: Debug mode - Link to debug link key"))
       
  3044 			iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr);
       
  3045 			}
       
  3046 		else
       
  3047 			{
       
  3048 			if (iDevice.LinkKeyType() != ELinkKeyCombination)
       
  3049 				{
       
  3050 				if (iRequireAuthenticatedLinkKey && iDevice.LinkKeyType() == ELinkKeyUnauthenticatedUpgradable && IsPairable())
       
  3051 					{
       
  3052 					LOG(_L("CPhysicalLink: Requiring Authenticated link key but currently only have unauthenticated"))
       
  3053 					iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr);
       
  3054 					}
       
  3055 				else
       
  3056 					{
       
  3057 					LOG(_L("CPhysicalLink: Issuing link key to HC now"))
       
  3058 					iAuthenticationCtrl.LinkKeyRequestReply(aAddr, iDevice.LinkKey());
       
  3059 					}
       
  3060 				}
       
  3061 			else if(IsPasskeyMinLengthOK() && SimplePairingMode() != EPhySimplePairingEnabled)
       
  3062 				{
       
  3063 				LOG(_L("CPhysicalLink: Issuing link key to HC now"))
       
  3064 				iAuthenticationCtrl.LinkKeyRequestReply(aAddr, iDevice.LinkKey());
       
  3065 				}
       
  3066 			else
       
  3067 				{
       
  3068 				LOG(_L("CPhysicalLink: Current PIN code too short!"))
       
  3069 				iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr);
       
  3070 				}
       
  3071 			}
       
  3072 		iRequireAuthenticatedLinkKey = EFalse;
       
  3073 		}
       
  3074 	else if (iDeviceResult==KErrNone && !iDevice.IsValidLinkKey() || iDeviceResult==KErrNotFound)
       
  3075 		{
       
  3076 		LOG(_L("CPhysicalLink: No Link key available for the device"));
       
  3077 		iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr);
       
  3078 		iRequireAuthenticatedLinkKey = EFalse;
       
  3079 		}
       
  3080 	else
       
  3081 		{
       
  3082 		LOG(_L("CPhysicalLink: Waiting for link key from Registry!"))
       
  3083 		// we're still waiting for the device....we'll respond when it turns up
       
  3084 		iWaitingForLinkKeyFromRegistry = ETrue;
       
  3085 		}
       
  3086 
       
  3087 	}
       
  3088 
       
  3089 TInt CPhysicalLink::PINCodeRequestReply(const TBTDevAddr& aDevAddr, const TDesC8& aPin) const
       
  3090 	{
       
  3091 	ASSERT_DEBUG(aDevAddr == this->BDAddr());
       
  3092 	const_cast<CPhysicalLink*>(this)->PINCodeRequestReply(aDevAddr, aPin);
       
  3093 	return KErrNone;
       
  3094 	}
       
  3095 
       
  3096 TInt CPhysicalLink::PINCodeRequestNegativeReply(const TBTDevAddr& aDevAddr) const
       
  3097 	{
       
  3098 	ASSERT_DEBUG(aDevAddr == this->BDAddr());
       
  3099 	const_cast<CPhysicalLink*>(this)->PINCodeRequestNegativeReply(aDevAddr);
       
  3100 	return KErrNone;
       
  3101 	}
       
  3102 
       
  3103 void CPhysicalLink::PINCodeRequestReply(const TBTDevAddr& aDevAddr, const TDesC8& aPin)
       
  3104 	{
       
  3105 	SetPassKey(aPin);
       
  3106 	PinRequestSent();
       
  3107 	iPinHandler->PINCodeRequestReply(aDevAddr, aPin);
       
  3108 	PinRequestComplete();
       
  3109 	}
       
  3110 
       
  3111 void CPhysicalLink::PINCodeRequestNegativeReply(const TBTDevAddr& aDevAddr)
       
  3112 	{
       
  3113 	iPinHandler->PINCodeRequestNegativeReply(aDevAddr);
       
  3114 	PinRequestComplete();
       
  3115 	}
       
  3116 
       
  3117 
       
  3118 void CPhysicalLink::PinRequestSent()
       
  3119 	{
       
  3120 	LOG_FUNC
       
  3121 	iLinkKeyPending = ETrue;
       
  3122 	}
       
  3123 
       
  3124 void CPhysicalLink::PinRequestComplete()
       
  3125 /**
       
  3126 	Just clean up now that PIN request has completed
       
  3127 **/
       
  3128 	{
       
  3129 	LOG_FUNC
       
  3130 	delete iPinRequester;
       
  3131 	iPinRequester = NULL;
       
  3132 	iPinHandler = NULL;
       
  3133 	AuthenticationComplete(EPinRequestPending);
       
  3134 	}
       
  3135 
       
  3136 
       
  3137 TInt CPhysicalLink::RequestHold()
       
  3138 	{
       
  3139 	LOG_FUNC
       
  3140 	return RequestMode(EHoldMode);
       
  3141 	}
       
  3142 
       
  3143 TInt CPhysicalLink::RequestSniff()
       
  3144 	{
       
  3145 	LOG_FUNC
       
  3146 	return RequestMode(ESniffMode);
       
  3147 	}
       
  3148 
       
  3149 TInt CPhysicalLink::RequestPark()
       
  3150 	{
       
  3151 	LOG_FUNC
       
  3152 	return RequestMode(EParkMode);
       
  3153 	}
       
  3154 
       
  3155 TInt CPhysicalLink::RequestActive()
       
  3156 	{
       
  3157 	LOG_FUNC
       
  3158 	return RequestMode(EActiveMode);
       
  3159 	}
       
  3160 
       
  3161 void CPhysicalLink::ReadNewPhysicalLinkMetricValue(TUint aIoctlName, CBTProxySAP& aSAP, TInt aCurrentValue)
       
  3162 	{
       
  3163 	LOG_FUNC
       
  3164 	iPhysicalLinkMetrics->ReadNewPhysicalLinkMetricValue(aIoctlName, aSAP, aCurrentValue);
       
  3165 	}
       
  3166 
       
  3167 void CPhysicalLink::GetCurrentBasebandState(TBTBasebandEventNotification & aEvent)
       
  3168 	{
       
  3169 	LOG_FUNC
       
  3170 	// Populate the event with the current baseband state.
       
  3171 	TUint32 events = 0;
       
  3172 	switch(iLinkState.LinkRole())
       
  3173 		{
       
  3174 		case EMaster:
       
  3175 			events |= ENotifyMaster;
       
  3176 			break;
       
  3177 		case ESlave:
       
  3178 			events |= ENotifySlave;
       
  3179 			break;
       
  3180 		case ERoleUnknown:
       
  3181 		default:
       
  3182 			break;
       
  3183 		};
       
  3184 
       
  3185 	switch(iLinkState.LinkMode())
       
  3186 		{
       
  3187 		case EActiveMode:
       
  3188 			events |= ENotifyActiveMode;
       
  3189 			break;
       
  3190 		case ESniffMode:
       
  3191 			events |= ENotifySniffMode;
       
  3192 			break;
       
  3193 		case EParkMode:
       
  3194 			events |= ENotifyParkMode;
       
  3195 			break;
       
  3196 		case EHoldMode:
       
  3197 			events |= ENotifyHoldMode;
       
  3198 			break;
       
  3199 		case EScatterMode:
       
  3200 		default:
       
  3201 			break;
       
  3202 		};
       
  3203 
       
  3204 	switch(iLinkState.MaxSlots())
       
  3205 		{
       
  3206 		case 1:
       
  3207 			events |= ENotifyMaxSlots1;
       
  3208 			break;
       
  3209 		case 3:
       
  3210 			events |= ENotifyMaxSlots3;
       
  3211 			break;
       
  3212 		case 5:
       
  3213 			events |= ENotifyMaxSlots5;
       
  3214 			break;
       
  3215 		default:
       
  3216 			break;
       
  3217 		};
       
  3218 
       
  3219 	TUint16 packetTypes = iLinkState.PacketTypes();
       
  3220 	if(packetTypes & EPacketsDM1)
       
  3221 		{
       
  3222 		events |= ENotifyPacketsDM1;
       
  3223 		}
       
  3224 	if(packetTypes & EPacketsDM3)
       
  3225 		{
       
  3226 		events |= ENotifyPacketsDM3;
       
  3227 		}
       
  3228 	if(packetTypes & EPacketsDM5)
       
  3229 		{
       
  3230 		events |= ENotifyPacketsDM5;
       
  3231 		}
       
  3232 	if(packetTypes & EPacketsDH1)
       
  3233 		{
       
  3234 		events |= ENotifyPacketsDH1;
       
  3235 		}
       
  3236 	if(packetTypes & EPacketsDH3)
       
  3237 		{
       
  3238 		events |= ENotifyPacketsDH3;
       
  3239 		}
       
  3240 	if(packetTypes & EPacketsDH5)
       
  3241 		{
       
  3242 		events |= ENotifyPacketsDH5;
       
  3243 		}
       
  3244 	if(packetTypes & EPacketsHV1)
       
  3245 		{
       
  3246 		events |= ENotifyPacketsHV1;
       
  3247 		}
       
  3248 	if(packetTypes & EPacketsHV2)
       
  3249 		{
       
  3250 		events |= ENotifyPacketsHV2;
       
  3251 		}
       
  3252 	if(packetTypes & EPacketsHV3)
       
  3253 		{
       
  3254 		events |= ENotifyPacketsHV3;
       
  3255 		}
       
  3256 
       
  3257 	if(iLinkState.Authenticated())
       
  3258 		{
       
  3259 		events |= ENotifyAuthenticationComplete;
       
  3260 		}
       
  3261 
       
  3262 	if(iLinkState.Encrypted())
       
  3263 		{
       
  3264 		events |= ENotifyEncryptionChangeOn;
       
  3265 		}
       
  3266 	else
       
  3267 		{
       
  3268 		events |= ENotifyEncryptionChangeOff;
       
  3269 		}
       
  3270 
       
  3271 	switch(iLinkState.LinkState())
       
  3272 		{
       
  3273 		case TBTBasebandLinkState::ELinkUp:
       
  3274 			events |= ENotifyPhysicalLinkUp;
       
  3275 
       
  3276 			if (iSyncLogicalLink)
       
  3277 				{
       
  3278 				if (iSyncLogicalLink->IsOpen())
       
  3279 					{
       
  3280 					events |= ENotifySynchronousLinkUp;
       
  3281 					}
       
  3282 				else
       
  3283 					{
       
  3284 					events |= ENotifySynchronousLinkDown;
       
  3285 					}
       
  3286 				}
       
  3287 			break;
       
  3288 		case TBTBasebandLinkState::ELinkDown:
       
  3289 			events |= ENotifyPhysicalLinkDown;
       
  3290 			break;
       
  3291 		default:
       
  3292 			break;
       
  3293 		};
       
  3294 
       
  3295 	aEvent.SetEventType(events);
       
  3296 	aEvent.SetErrorCode(0);
       
  3297 	}
       
  3298 
       
  3299 TBool CPhysicalLink::ACLConnectPending() const
       
  3300 	{
       
  3301 	LOG_FUNC
       
  3302 	return !IsConnected();
       
  3303 	}
       
  3304 
       
  3305 TBool CPhysicalLink::SyncConnectPending() const
       
  3306 	{
       
  3307 	LOG_FUNC
       
  3308 	if (!iSyncLogicalLink)
       
  3309 		{
       
  3310 		return EFalse;
       
  3311 		}
       
  3312 
       
  3313 	return iSyncLogicalLink->ConnectPending();
       
  3314 	}
       
  3315 
       
  3316 TInt CPhysicalLink::ManageEncryptionEnforcement(THCIEncryptModeFlag aEnable)
       
  3317 	{
       
  3318 	LOG_FUNC
       
  3319 	// Although this code has been written as if this method could be called more then once,
       
  3320 	// with different argument values:
       
  3321 	// ChangeEncryption() (and then ManageEncryptionEnforcement()) is called only
       
  3322 	// once and only with aEnable = EPointToPointEncryption.
       
  3323 	// It's called if during the physical link creation the encryption is requested.
       
  3324 	// That is because the assertion below.
       
  3325 	__ASSERT_DEBUG(aEnable != EEncryptionDisabled, Panic(EBTInvalidEncryptionDisableRequest));
       
  3326 
       
  3327 	// although "&& (iEncryptionEnforcer)" is not necessary, we leave it because
       
  3328 	// clarify that we had asked for the encryption, so it's our responsability to
       
  3329 	// delete iEncryptionEnforcer.
       
  3330 	if ((aEnable == EEncryptionDisabled) && (iEncryptionEnforcer))
       
  3331 		{
       
  3332 		delete iEncryptionEnforcer;
       
  3333 		iEncryptionEnforcer = NULL;
       
  3334 		}
       
  3335 	else if ((aEnable != EEncryptionDisabled) && (!iEncryptionEnforcer))
       
  3336 		{
       
  3337 		TRAPD(err, iEncryptionEnforcer = CEncryptionEnforcer::NewL(*this, aEnable));
       
  3338 		return err;
       
  3339 		}
       
  3340 	return KErrNone;
       
  3341 	}
       
  3342 
       
  3343 TBasebandTime CPhysicalLink::CalculatePageTimeout(TBasebandPageTimePolicy aPolicy, TUint8 aRepMode, TBool aValidClockOffset)
       
  3344 	{
       
  3345 	LOG_FUNC
       
  3346 	TBasebandTime pageTimeout = TBasebandPolicy::KPageTimeoutR0;
       
  3347 
       
  3348 	switch (aRepMode)
       
  3349 		{
       
  3350 		// PSRM defined in spec
       
  3351 		case 0x00:
       
  3352 			// already set
       
  3353 			break;
       
  3354 
       
  3355 		case 0x01:
       
  3356 			pageTimeout = TBasebandPolicy::KPageTimeoutR1;
       
  3357 			break;
       
  3358 
       
  3359 		case 0x02:
       
  3360 			// fallthrough
       
  3361 		default:
       
  3362 			pageTimeout = TBasebandPolicy::KPageTimeoutR2;
       
  3363 			break;
       
  3364 		}
       
  3365 
       
  3366 	if (!aValidClockOffset)
       
  3367 		{
       
  3368 		pageTimeout*=2;
       
  3369 		}
       
  3370 	else
       
  3371 		{
       
  3372 //		normalPageTimeout+=5; //slots
       
  3373 		}
       
  3374 
       
  3375 	// policy may not be valid - or dontcare/normal
       
  3376 	switch (aPolicy)
       
  3377 		{
       
  3378 		case EPagingBestEffort:
       
  3379 			pageTimeout = static_cast<TBasebandTime>(TBasebandPolicy::KBestEffortTimeMultiplier * pageTimeout);
       
  3380 			break;
       
  3381 
       
  3382 		case EPagingQuick:
       
  3383 			pageTimeout = static_cast<TBasebandTime>(TBasebandPolicy::KQuickTimeMultiplier * pageTimeout);
       
  3384 			break;
       
  3385 
       
  3386 		default:
       
  3387 			break;
       
  3388 			// leave as is
       
  3389 
       
  3390 		}
       
  3391 	return pageTimeout;
       
  3392 	}
       
  3393 
       
  3394 // CArbitrationDelayTimer
       
  3395 
       
  3396 CArbitrationDelayTimer::CArbitrationDelayTimer(CPhysicalLink* aParent)
       
  3397 	:CTimer(CActive::EPriorityStandard),
       
  3398 	iParent(aParent)
       
  3399 	{
       
  3400 	LOG_FUNC
       
  3401 	}
       
  3402 
       
  3403 void CArbitrationDelayTimer::ConstructL()
       
  3404 	{
       
  3405 	LOG_FUNC
       
  3406 	CTimer::ConstructL();
       
  3407 	CActiveScheduler::Add(this);
       
  3408 	}
       
  3409 
       
  3410 CArbitrationDelayTimer* CArbitrationDelayTimer::NewL(CPhysicalLink* aParent)
       
  3411 	{
       
  3412 	LOG_STATIC_FUNC
       
  3413 	CArbitrationDelayTimer* self = new (ELeave) CArbitrationDelayTimer(aParent);
       
  3414 	CleanupStack::PushL(self);
       
  3415 	self->ConstructL();
       
  3416 	CleanupStack::Pop(self);
       
  3417 	return self;
       
  3418 	}
       
  3419 
       
  3420 void CArbitrationDelayTimer::Start()
       
  3421 	{
       
  3422 	LOG_FUNC
       
  3423 	if (IsActive())
       
  3424 		{
       
  3425 		Cancel();
       
  3426 		}
       
  3427 	After(KBTArbitrationDelay);
       
  3428 	}
       
  3429 
       
  3430 
       
  3431 void CArbitrationDelayTimer::RunL()
       
  3432 /**
       
  3433 Allow arbitration of low power modes when the timer expires
       
  3434 **/
       
  3435 	{
       
  3436 	LOG_FUNC
       
  3437 	if (iParent)
       
  3438 		{
       
  3439 		iParent->Arbitrate();
       
  3440 		}
       
  3441 	}
       
  3442 
       
  3443 TInt CPhysicalLink::GetNumPendingHandles(TInt& aConnectionHandles, TLinkType aLinkType) const
       
  3444 	{
       
  3445 	LOG_FUNC
       
  3446 	aConnectionHandles = 0;
       
  3447 
       
  3448 	switch(aLinkType)
       
  3449 		{
       
  3450 	case EeSCOLink:
       
  3451 
       
  3452 		if (iSyncLogicalLink && iSyncLogicalLink->ConnectPending())
       
  3453 			{
       
  3454 			// Currently there is a maximum of one synclink per
       
  3455 			// physical link
       
  3456 
       
  3457 			++aConnectionHandles;
       
  3458 			}
       
  3459 
       
  3460 		break;
       
  3461 
       
  3462 	case ESCOLink:
       
  3463 
       
  3464 		if (iSyncLogicalLink && iSyncLogicalLink->ConnectPending())
       
  3465 			{
       
  3466 			// Currently there is a maximum of one synclink per
       
  3467 			// physical link
       
  3468 
       
  3469 			++aConnectionHandles;
       
  3470 			}
       
  3471 
       
  3472 		break;
       
  3473 
       
  3474 	case EACLLink:
       
  3475 
       
  3476 		if (!IsConnected())
       
  3477 			{
       
  3478 			// Currently there is a maximum of one asynclink per
       
  3479 			// physical link
       
  3480 			++aConnectionHandles;
       
  3481 			}
       
  3482 
       
  3483 		break;
       
  3484 
       
  3485 	default:
       
  3486 		return KErrUnknown;
       
  3487 		}
       
  3488 
       
  3489 	return KErrNone;
       
  3490 	}
       
  3491 
       
  3492 TInt CPhysicalLink::GetConnectionHandles(RHCIConnHandleArray& aConnectionHandles,
       
  3493 					 TLinkType aLinkType) const
       
  3494 	{
       
  3495 	LOG_FUNC
       
  3496 	// Always append to client supplied array - do not clear the
       
  3497 	// contents.  Only return connected handles.
       
  3498 
       
  3499 	switch(aLinkType)
       
  3500 		{
       
  3501 	case EeSCOLink:
       
  3502 
       
  3503 		if (!iSyncLogicalLink || iSyncLogicalLink->ConnectPending())
       
  3504 			{
       
  3505 			return KErrNone;
       
  3506 			}
       
  3507 
       
  3508 		if (iSyncLogicalLink->LinkType() == EeSCOLink)
       
  3509 			{
       
  3510 			// Currently there is a maximum of one synclink per
       
  3511 			// physical link
       
  3512 			aConnectionHandles.Append(iSyncLogicalLink->Handle());
       
  3513 			}
       
  3514 
       
  3515 		break;
       
  3516 
       
  3517 	case ESCOLink:
       
  3518 
       
  3519 		if (!iSyncLogicalLink || iSyncLogicalLink->ConnectPending())
       
  3520 			{
       
  3521 			return KErrNone;
       
  3522 			}
       
  3523 
       
  3524 		if (iSyncLogicalLink->LinkType() == ESCOLink)
       
  3525 			{
       
  3526 			// Currently there is a maximum of one synclink per
       
  3527 			// physical link
       
  3528 			aConnectionHandles.Append(iSyncLogicalLink->Handle());
       
  3529 			}
       
  3530 
       
  3531 		break;
       
  3532 
       
  3533 	case EACLLink:
       
  3534 		// Currently there is a maximum of one asynclink per physical
       
  3535 		// link and they share the same handle - this may change in
       
  3536 		// the future for QoS.
       
  3537 
       
  3538 		if (!IsConnected())
       
  3539 			{
       
  3540 			return KErrNone;
       
  3541 			}
       
  3542 
       
  3543 		aConnectionHandles.Append(iHandle);
       
  3544 		break;
       
  3545 
       
  3546 	default:
       
  3547 		return KErrUnknown;
       
  3548 		}
       
  3549 
       
  3550 	return KErrNone;
       
  3551 	}
       
  3552 
       
  3553 void CPhysicalLink::IOCapabilityAskForResponse(THCIIoCapability aIOCapability, THCIOobDataPresence aOOBDataPresence, THCIAuthenticationRequirement aAuthenticationRequirement)
       
  3554 	{
       
  3555 	LOG_FUNC
       
  3556 	iIOCapsReceived = ETrue;
       
  3557 	iIOCapability = aIOCapability;
       
  3558 	iOOBDataPresence = aOOBDataPresence;
       
  3559 	iAuthenticationRequirement = aAuthenticationRequirement;
       
  3560 	
       
  3561 	//If we haven't determined the SSP pairing mode till now then enable it and notify the state m/c.
       
  3562 	//This condition is to cater the fast remote device which responds very quickly,  
       
  3563 	//even before we determine whether it supports simple pairing!*/ 
       
  3564 	__ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingEnabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection));
       
  3565 	if(SimplePairingMode() == EPhySimplePairingUndefined)
       
  3566 		{
       
  3567 		//Since we have received a I/O cap response the simple pairing must be enabled
       
  3568 		iSimplePairingMode = EPhySimplePairingEnabled;
       
  3569 		iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr());
       
  3570 		}
       
  3571 	}
       
  3572 
       
  3573 
       
  3574 TBool CPhysicalLink::AuthWithMITM() const
       
  3575 	{
       
  3576 	LOG_FUNC
       
  3577    	return (iLocalMITM || (iAuthenticationRequirement & KAuthenticationMitmReqMask))
       
  3578   			&& (iIOCapability != EIOCapsNoInputNoOutput);
       
  3579 	}
       
  3580 
       
  3581 void CPhysicalLink::SetLocalMITM(TBool aLocalMITM)
       
  3582 	{
       
  3583 	LOG_FUNC
       
  3584 	iLocalMITM = aLocalMITM;
       
  3585 	}
       
  3586 
       
  3587 TPhysicalLinkSimplePairingMode CPhysicalLink::SimplePairingMode() const
       
  3588 	{
       
  3589 	LOG_FUNC
       
  3590 	return iSimplePairingMode;
       
  3591 	}
       
  3592 
       
  3593 TBool CPhysicalLink::HasRemoteOobData() const
       
  3594 	{
       
  3595 	LOG_FUNC
       
  3596 	return iLinksMan.SecMan().OobDataManager().HasRemoteOobData(BDAddr());
       
  3597 	}
       
  3598 
       
  3599 THCIAuthenticationRequirement CPhysicalLink::AuthenticationRequirement() const
       
  3600 	{
       
  3601 	LOG_FUNC
       
  3602 	return iAuthenticationRequirement;
       
  3603 	}
       
  3604 
       
  3605 void CPhysicalLink::NewNumericComparatorL(const TBTDevAddr aAddr,
       
  3606  										  CBTSecMan& aSecMan,
       
  3607  										  TUint32 aNumericValue,
       
  3608  										  TBool	aInternallyInitiated)
       
  3609    	{
       
  3610 	LOG_FUNC
       
  3611  	__ASSERT_DEBUG(aAddr == BDAddr(), Panic(EBTConnectionBadDeviceAddress));
       
  3612  	
       
  3613  	// Check remote IO capabilities so that the BTNumericComparator can tell the user
       
  3614  	TBTNumericComparisonParams::TComparisonScenario compScenario = TBTNumericComparisonParams::ERemoteCanConfirm;
       
  3615  	if(iIOCapsReceived)
       
  3616  		{
       
  3617  		switch(iIOCapability)
       
  3618  			{
       
  3619  			case EIOCapsDisplayOnly:
       
  3620  				compScenario = TBTNumericComparisonParams::ERemoteCannotConfirm;
       
  3621  				break;
       
  3622  			case EIOCapsDisplayYesNo:
       
  3623  				compScenario = TBTNumericComparisonParams::ERemoteCanConfirm;
       
  3624  				break;
       
  3625  			default:
       
  3626  				// If iIOCapability = EIOCapsKeyboardOnly or EIOCapsNoInputNoOutput 
       
  3627  				// we should not be using a Numeric Comparitor
       
  3628  				__ASSERT_DEBUG(EFalse, Panic(EUnexpectedIOCapability));
       
  3629  				break;
       
  3630  			}
       
  3631  		}
       
  3632  	iNumericComparator = CBTNumericComparator::NewL(aAddr, aSecMan, aNumericValue, compScenario, aInternallyInitiated);
       
  3633    	}
       
  3634 
       
  3635 CBTNumericComparator* CPhysicalLink::InstanceNumericComparator() const
       
  3636 	{
       
  3637 	LOG_FUNC
       
  3638 	return iNumericComparator;
       
  3639 	}
       
  3640 
       
  3641 TBool CPhysicalLink::IsNumericComparatorActive()const
       
  3642 	{
       
  3643 	LOG_FUNC
       
  3644 	return iNumericComparator->IsActive();
       
  3645 	}
       
  3646 
       
  3647 void CPhysicalLink::DeleteNumericComparator()
       
  3648 	{
       
  3649 	LOG_FUNC
       
  3650 	delete iNumericComparator;
       
  3651 	iNumericComparator = NULL;
       
  3652 	}
       
  3653 void CPhysicalLink::CancelNumericComparator()
       
  3654 	{
       
  3655 	LOG_FUNC
       
  3656 	iNumericComparator->Cancel();
       
  3657 	}
       
  3658 
       
  3659 void CPhysicalLink::NewPasskeyEntryL(const TBTDevAddr aAddr,
       
  3660 												CBTSecMan& aSecMan,
       
  3661 												TUint32 aNumericValue,
       
  3662 												TBool aInternallyInitiated)
       
  3663 	{
       
  3664 	LOG_FUNC
       
  3665 	iPasskeyEntry = CBTPasskeyEntry::NewL(aAddr, aSecMan, aNumericValue, aInternallyInitiated);
       
  3666 	}
       
  3667 
       
  3668 CBTPasskeyEntry* CPhysicalLink::InstancePasskeyEntry() const
       
  3669 	{
       
  3670 	LOG_FUNC
       
  3671 	return iPasskeyEntry;
       
  3672 	}
       
  3673 
       
  3674 TBool CPhysicalLink::IsPasskeyEntryActive()const
       
  3675 	{
       
  3676 	LOG_FUNC
       
  3677 	return iPasskeyEntry->IsActive();
       
  3678 	}
       
  3679 
       
  3680 void CPhysicalLink::DeletePasskeyEntry()
       
  3681 	{
       
  3682 	LOG_FUNC
       
  3683 	delete iPasskeyEntry;
       
  3684 	iPasskeyEntry = NULL;
       
  3685 	}
       
  3686 
       
  3687 void CPhysicalLink::CancelPasskeyEntry()
       
  3688 	{
       
  3689 	LOG_FUNC
       
  3690 	iPasskeyEntry->Cancel();
       
  3691 	}
       
  3692 
       
  3693 void CPhysicalLink::PasskeyEntryKeyPressed(THCIPasskeyEntryNotificationType aKey)
       
  3694 	{
       
  3695 	LOG_FUNC
       
  3696 	iPasskeyEntry->KeyPressed(aKey);
       
  3697 	}
       
  3698 
       
  3699 
       
  3700 TBasebandTime CPhysicalLink::GetSniffInterval() const
       
  3701 	{
       
  3702 	return iSniffInterval;
       
  3703 	}
       
  3704 
       
  3705 //
       
  3706 // TLowPowModeCmdController
       
  3707 //
       
  3708 
       
  3709 TLowPowModeCmdController::TLowPowModeCmdController(CPhysicalLink& aLink, MHCICommandQueue& aCmdController) : 	
       
  3710 	iParent(aLink),
       
  3711 	iCmdController(aCmdController),
       
  3712 	iOutstandingCmd(EFalse)
       
  3713 	{
       
  3714 	LOG_FUNC
       
  3715 	}
       
  3716 
       
  3717 void TLowPowModeCmdController::Abort()
       
  3718 	{
       
  3719 	LOG_FUNC
       
  3720 	LOG(_L("TLowPowModeCmdController::Abort"));
       
  3721 	iCmdController.MhcqRemoveAllCommands(*this);
       
  3722 	}
       
  3723 
       
  3724 void TLowPowModeCmdController::DoExitModeL(TBTLinkMode aMode, THCIConnHandle aConnHandle)
       
  3725 	{
       
  3726 	LOG_FUNC
       
  3727 	LOG2(_L("TLowPowModeCmdController::DoExitModeL: mode:%d iOutstandingCmd:%d"), aMode, iOutstandingCmd);
       
  3728 	if (!iOutstandingCmd)
       
  3729 		{
       
  3730 		switch (aMode)
       
  3731 			{
       
  3732 			case ESniffMode:
       
  3733 				{
       
  3734 				ExitSniffL(aConnHandle);
       
  3735 				break;
       
  3736 				}
       
  3737 			case EParkMode:
       
  3738 				{
       
  3739 				ExitParkL(aConnHandle);
       
  3740 				break;
       
  3741 				}
       
  3742 			// Not possile to prematurely exit hold mode
       
  3743 			default:
       
  3744 				break;
       
  3745 			}
       
  3746 		iOutstandingCmd = ETrue;
       
  3747 		}
       
  3748 	else
       
  3749 		{
       
  3750 		LOG1(_L("TLowPowModeCmdController::DoExitModeL: cannot exit from mode:%d due to an outstanding command"), aMode);
       
  3751 		}
       
  3752 	}
       
  3753 
       
  3754 TInt TLowPowModeCmdController::ExitMode(TBTLinkMode aMode, THCIConnHandle aHandle)
       
  3755 	{
       
  3756 	LOG_FUNC
       
  3757 	TRAPD(err, DoExitModeL(aMode, aHandle));
       
  3758 	return err;
       
  3759 	}
       
  3760 
       
  3761 void TLowPowModeCmdController::DoChangeModeL(TBTLinkMode aMode, THCIConnHandle aConnHandle)
       
  3762 	{
       
  3763 	LOG_FUNC
       
  3764 	LOG2(_L("TLowPowModeCmdController::DoChangeModeL: mode:%d iOutstandingCmd:%d"), aMode, iOutstandingCmd);
       
  3765 	if (!iOutstandingCmd)
       
  3766 		{
       
  3767 		switch (aMode)
       
  3768 			{
       
  3769 			case ESniffMode:
       
  3770 				{
       
  3771 				SniffL(aConnHandle);
       
  3772 				break;
       
  3773 				}
       
  3774 			case EParkMode:
       
  3775 				{
       
  3776 				ParkL(aConnHandle);
       
  3777 				break;
       
  3778 				}
       
  3779 			case EHoldMode:
       
  3780 				{
       
  3781 				HoldL(aConnHandle);
       
  3782 				break;
       
  3783 				}
       
  3784 			case EScatterMode:
       
  3785 			case EActiveMode:
       
  3786 				__ASSERT_DEBUG(0, Panic(EHCICommandBadArgument));
       
  3787 				break;
       
  3788 			}
       
  3789 		iOutstandingCmd = ETrue;
       
  3790 		}
       
  3791 	else
       
  3792 		{
       
  3793 		LOG1(_L("TLowPowModeCmdController::DoChangeModeL: cannot change to mode:%d due to an outstanding command"), aMode);
       
  3794 		}
       
  3795 	}
       
  3796 
       
  3797 TInt TLowPowModeCmdController::ChangeMode(TBTLinkMode aMode, THCIConnHandle aHandle)
       
  3798 	{
       
  3799 	LOG_FUNC
       
  3800 	TRAPD(err, DoChangeModeL(aMode, aHandle));
       
  3801 	return err;
       
  3802 	}
       
  3803 
       
  3804 void TLowPowModeCmdController::SniffL(THCIConnHandle aHandleToRemote)
       
  3805 	{
       
  3806 	LOG_FUNC
       
  3807 	CSniffModeCommand* cmd = CSniffModeCommand::NewL(aHandleToRemote, KBTSniffModeMaxInterval, KBTSniffModeMinInterval, KBTSniffModeAttempt, KBTSniffModeTimeout);
       
  3808 
       
  3809 	// Ownership of cmd transfered even if MhcqAddCommandL leaves
       
  3810 	iCmdController.MhcqAddCommandL(cmd, *this);
       
  3811 	}
       
  3812 
       
  3813 void TLowPowModeCmdController::ExitSniffL(THCIConnHandle aHandleToRemote)
       
  3814 	{
       
  3815 	LOG_FUNC
       
  3816 	CExitSniffModeCommand* cmd = CExitSniffModeCommand::NewL(aHandleToRemote);
       
  3817 
       
  3818 	// Ownership of cmd transfered even if MhcqAddCommandL leaves
       
  3819 	iCmdController.MhcqAddCommandL(cmd, *this);
       
  3820 	}
       
  3821 
       
  3822 void TLowPowModeCmdController::HoldL(THCIConnHandle aHandle)
       
  3823 	{
       
  3824 	LOG_FUNC
       
  3825 	CHoldModeCommand* cmd = CHoldModeCommand::NewL(aHandle, KBTHoldModeMaxInterval, KBTHoldModeMinInterval);
       
  3826 
       
  3827 	// Ownership of cmd transfered even if MhcqAddCommandL leaves
       
  3828 	iCmdController.MhcqAddCommandL(cmd, *this);
       
  3829 	}
       
  3830 
       
  3831 void TLowPowModeCmdController::ParkL(THCIConnHandle aHandle)
       
  3832 	{
       
  3833 	LOG_FUNC
       
  3834 	CParkModeCommand* cmd = CParkModeCommand::NewL(aHandle, KBTParkModeBeaconMaxInterval, KBTParkModeBeaconMinInterval);
       
  3835 
       
  3836 	// Ownership of cmd transfered even if MhcqAddCommandL leaves
       
  3837 	iCmdController.MhcqAddCommandL(cmd, *this);
       
  3838 	}
       
  3839 
       
  3840 void TLowPowModeCmdController::ExitParkL(THCIConnHandle aHandle)
       
  3841 	{
       
  3842 	LOG_FUNC
       
  3843 	CExitParkModeCommand* cmd = CExitParkModeCommand::NewL(aHandle);
       
  3844 
       
  3845 	// Ownership of cmd transfered even if MhcqAddCommandL leaves
       
  3846 	iCmdController.MhcqAddCommandL(cmd, *this);
       
  3847 	}
       
  3848 
       
  3849 void TLowPowModeCmdController::MhcqcCommandEventReceived(const THCIEventBase& aEvent, const CHCICommandBase* aRelatedCommand)
       
  3850 	{
       
  3851 	LOG_FUNC
       
  3852 	THCIEventCode code = aEvent.EventCode();
       
  3853 
       
  3854 	__ASSERT_DEBUG(!(code != EModeChangeEvent && code != ECommandStatusEvent), Panic(EHCIUnknownCommandEvent));	// this should never happen
       
  3855 	__ASSERT_DEBUG(aRelatedCommand != NULL, Panic(EHCIUnknownCommandEvent));	// this should never happen
       
  3856 
       
  3857 	if (!aRelatedCommand)	// it is not the response to our command - should never happen
       
  3858 		return;
       
  3859 
       
  3860 	if ((code == ECommandStatusEvent) && (aEvent.ErrorCode() != EOK))
       
  3861 		{
       
  3862 		LOG3(_L("TLowPowModeCmdController::MhcqcCommandEventReceived: event:%d opcode:0x%x error:0x%x"), code, aRelatedCommand->Opcode(), aEvent.ErrorCode());
       
  3863 		iOutstandingCmd = EFalse;	// reset the outstanding flag
       
  3864 		iParent.StartArbitrationTimer();
       
  3865 		}
       
  3866 	else if (code == EModeChangeEvent)
       
  3867 		{
       
  3868 		iOutstandingCmd = EFalse;	// reset the outstanding flag
       
  3869 
       
  3870 		LOG2(_L("TLowPowModeCmdController::MhcqcCommandEventReceived: event:%d opcode:0x%x"), code, aRelatedCommand->Opcode());
       
  3871 
       
  3872 		const TModeChangeEvent& modeChangeEvent = TModeChangeEvent::Cast(aEvent);
       
  3873 		TBTLinkMode mode = EActiveMode;
       
  3874 		switch(modeChangeEvent.CurrentMode())
       
  3875 			{
       
  3876 			// Mode 0, as defined for the Mode Change Event, is Active Mode
       
  3877 			case 0:
       
  3878 				break;
       
  3879 			case 1:
       
  3880 				mode = EHoldMode;
       
  3881 				break;
       
  3882 			case 2:
       
  3883 				mode = ESniffMode;
       
  3884 				break;
       
  3885 			case 3:
       
  3886 				mode = EParkMode;
       
  3887 				break;
       
  3888 			default:
       
  3889 				__ASSERT_ALWAYS(EFalse, Panic(EHCICommandBadArgument));
       
  3890 				break;
       
  3891 			}
       
  3892 			// In the HCI_Facade, in this situation, CPhysicalLinksManager::ModeChanged() is called.
       
  3893 			// Since this methods find the CPhysicalLink object (that is iParent) and then call its
       
  3894 			// ModeChange method, we can call it directly.
       
  3895 			iParent.ModeChange(aEvent.ErrorCode(), modeChangeEvent.ConnectionHandle(), mode, modeChangeEvent.Interval());
       
  3896 		}
       
  3897 	}
       
  3898 
       
  3899 void TLowPowModeCmdController::MhcqcCommandErrored(TInt __DEBUG_ONLY(aErrorCode), const CHCICommandBase* __DEBUG_ONLY(aCommand))
       
  3900 	{
       
  3901 	LOG_FUNC
       
  3902 	__ASSERT_DEBUG(aCommand, Panic(EHCIUnknownCommandEvent));	// this should never happen
       
  3903 	#ifdef _DEBUG
       
  3904 	LOG2(_L("MhcqcCommandErrored: error code:%d opcode:0x%x"), aErrorCode, aCommand->Opcode());
       
  3905 	#endif
       
  3906 	iOutstandingCmd = EFalse;	// reset the outstanding flag
       
  3907 	iParent.StartArbitrationTimer();
       
  3908 	}
       
  3909 
       
  3910 
       
  3911 
       
  3912 
       
  3913 //
       
  3914 // CEncryptionEnforcer
       
  3915 //
       
  3916 
       
  3917 CEncryptionEnforcer::CEncryptionEnforcer (CPhysicalLink& aLink, THCIEncryptModeFlag aEncryptionMode) :
       
  3918 	CActive(EPriorityStandard), // Standard priority
       
  3919 	iLink(aLink),
       
  3920 	iEncryptionMode(aEncryptionMode),
       
  3921 	iState(EInactive)
       
  3922 	{
       
  3923 	LOG_FUNC
       
  3924 	}
       
  3925 
       
  3926 CEncryptionEnforcer* CEncryptionEnforcer::NewLC(CPhysicalLink& aLink, THCIEncryptModeFlag aEncryptionMode)
       
  3927 	{
       
  3928 	LOG_STATIC_FUNC
       
  3929 	CEncryptionEnforcer* self = new ( ELeave ) CEncryptionEnforcer(aLink, aEncryptionMode);
       
  3930 	CleanupStack::PushL (self);
       
  3931 	self->ConstructL ();
       
  3932 	return self;
       
  3933 	}
       
  3934 
       
  3935 CEncryptionEnforcer* CEncryptionEnforcer::NewL(CPhysicalLink& aLink, THCIEncryptModeFlag aEncryptionMode)
       
  3936 	{
       
  3937 	LOG_STATIC_FUNC
       
  3938 	CEncryptionEnforcer* self = CEncryptionEnforcer::NewLC (aLink, aEncryptionMode);
       
  3939 	CleanupStack::Pop(self);
       
  3940 	return self;
       
  3941 	}
       
  3942 
       
  3943 void CEncryptionEnforcer::ConstructL()
       
  3944 	{
       
  3945 	LOG_FUNC
       
  3946 	User::LeaveIfError (iTimer.CreateLocal () ); // Initialize timer
       
  3947 	CActiveScheduler::Add (this); // Add to scheduler
       
  3948 	}
       
  3949 
       
  3950 CEncryptionEnforcer::~CEncryptionEnforcer()
       
  3951 	{
       
  3952 	LOG_FUNC
       
  3953 	Cancel (); // Cancel any request, if outstanding
       
  3954 	iTimer.Close (); // Destroy the RTimer object
       
  3955 	}
       
  3956 
       
  3957 void CEncryptionEnforcer::DoCancel ()
       
  3958 	{
       
  3959 	LOG_FUNC
       
  3960 	iTimer.Cancel ();
       
  3961 	ChangeState(EInactive);
       
  3962 	}
       
  3963 
       
  3964 void CEncryptionEnforcer::Start(TInt delay)
       
  3965 	{
       
  3966 	LOG_FUNC
       
  3967 	Cancel (); // Cancel any request, just to be sure
       
  3968 	LOG(_L("CEncryptionEnforcer activate timer"))
       
  3969 	iTimer.After (iStatus, delay); // Set for later
       
  3970 	SetActive (); // Tell scheduler a request is active
       
  3971 	}
       
  3972 
       
  3973 void CEncryptionEnforcer::Stop()
       
  3974 	{
       
  3975 	LOG_FUNC
       
  3976 	Cancel();
       
  3977 	}
       
  3978 
       
  3979 void CEncryptionEnforcer::RunL ()
       
  3980 	{
       
  3981 	LOG_FUNC
       
  3982 	switch(iState)
       
  3983 		{
       
  3984 		case ERoleSwitchTimerInProgress:
       
  3985 			LOG(_L("CEncryptionEnforcer::RunL() : timer expired after a roleswitch, enforce encryption"))
       
  3986 			ChangeState(EForcingInProgress);
       
  3987 			User::LeaveIfError(iLink.ChangeEncryption(iEncryptionMode));
       
  3988 			break;
       
  3989 		case ENoRoleSwitchTimerInProgress:
       
  3990 			LOG(_L("CEncryptionEnforcer::RunL() : timer expired and no roleswitch performed, terminate the link"))
       
  3991 			iLink.Terminate(ERemoteUserEndedConnection);
       
  3992 			break;
       
  3993 		default:
       
  3994 			// this should never happen, so we assert in debug so to raise the problem.
       
  3995 			// however it doesn't break our behaviour, so we don't care in release.
       
  3996 			LOG(_L("CEncryptionEnforcer::RunL() : bad state"))
       
  3997 			__ASSERT_DEBUG(EFalse, Panic(EEncryptionEnforcerBadState));
       
  3998 			break;
       
  3999 		}
       
  4000 	}
       
  4001 
       
  4002 TInt CEncryptionEnforcer::RunError(TInt IF_FLOGGING(aError))
       
  4003 	{
       
  4004 	LOG_FUNC
       
  4005 	LOG1(_L("CEncryptionEnforcer::RunError() : error = %d"), aError);
       
  4006 	LOG(_L("CEncryptionEnforcer::RunError() : try to terminate the link"));
       
  4007 	return iLink.Terminate(ERemoteUserEndedConnection);
       
  4008 	}
       
  4009 
       
  4010 void CEncryptionEnforcer::ChangeState(TState aState)
       
  4011 	{
       
  4012 	LOG_FUNC
       
  4013 	LOG2(_L("CEncryptionEnforcer::ChangeState(): old state = %d; new state = %d"), iState, aState);
       
  4014 	iState = aState;
       
  4015 	}
       
  4016 
       
  4017 void CEncryptionEnforcer::EncryptionEnabled()
       
  4018 	{
       
  4019 	LOG_FUNC
       
  4020 	LOG1(_L("CEncryptionEnforcer::EncryptionEnabled() : current status = %d"), iState);
       
  4021 	switch(iState)
       
  4022 		{
       
  4023 		case EInactive:
       
  4024 			// do nothing, it means is the first encryption event as reply to our ChangeEncryption cmd.
       
  4025 			break;
       
  4026 		case EForcingInProgress:
       
  4027 			ChangeState(EInactive);
       
  4028 			break;
       
  4029 		case ENoRoleSwitchTimerInProgress:
       
  4030 		case ERoleSwitchTimerInProgress:
       
  4031 			Stop();
       
  4032 			break;
       
  4033 		}
       
  4034 	}
       
  4035 
       
  4036 void CEncryptionEnforcer::EncryptionDisabled(TBool aSecurityModeFour)
       
  4037 	{
       
  4038 	LOG_FUNC
       
  4039 	LOG1(_L("CEncryptionEnforcer::EncryptionDisabled() : current status = %d"), iState);
       
  4040 
       
  4041 	if(aSecurityModeFour)
       
  4042 		{
       
  4043 		Stop();
       
  4044 		ChangeState(EForcingInProgress);
       
  4045 		}
       
  4046 
       
  4047 	switch(iState)
       
  4048 		{
       
  4049 		case EInactive:
       
  4050 			LOG(_L("CEncryptionEnforcer::EncryptionDisabled() : start timer"))
       
  4051 			ChangeState(ENoRoleSwitchTimerInProgress);
       
  4052 			Start(KTimeOutDelay);
       
  4053 			break;
       
  4054 		case EForcingInProgress:
       
  4055 			LOG(_L("CEncryptionEnforcer::EncryptionDisabled() : disconnect the link"))
       
  4056 			iLink.Terminate(ERemoteUserEndedConnection);
       
  4057 			break;
       
  4058 		default:
       
  4059 			// this should never happen, so we assert in debug so to raise the problem.
       
  4060 			// however it doesn't break our behaviour, so we don't care in release.
       
  4061 			LOG(_L("CEncryptionEnforcer::EncryptionDisabled() : bad state"))
       
  4062 			__ASSERT_DEBUG(EFalse, Panic(EEncryptionEnforcerBadState));
       
  4063 			break;
       
  4064 		}
       
  4065 	}
       
  4066 
       
  4067 void CEncryptionEnforcer::RoleSwitchEvent()
       
  4068 	{
       
  4069 	LOG_FUNC
       
  4070 
       
  4071 	switch(iState)
       
  4072 		{
       
  4073 		case EInactive:
       
  4074 			// This is possible with EPR support - we don't need to do anything in this case.
       
  4075 			break;
       
  4076 		case ENoRoleSwitchTimerInProgress:
       
  4077 			ChangeState(ERoleSwitchTimerInProgress);
       
  4078 			break;
       
  4079 		default:
       
  4080 			// this should never happen, so we assert in debug so to raise the problem.
       
  4081 			// however it doesn't break our behaviour, so we don't care in release.
       
  4082 			LOG(_L("CEncryptionEnforcer::EncryptionDisabled() : bad state"))
       
  4083 			__ASSERT_DEBUG(EFalse, Panic(EEncryptionEnforcerBadState));
       
  4084 			break;
       
  4085 		}
       
  4086 	}
       
  4087 
       
  4088 void XAutoKeyRefreshToken::Release()
       
  4089 	{
       
  4090 	LOG_FUNC
       
  4091 	iQueLink.Deque();
       
  4092 	delete this;
       
  4093 	}
       
  4094 
       
  4095 //
       
  4096 // TRegistryDeviceOutChecker
       
  4097 //
       
  4098 TRegistryDeviceBeingModified::TRegistryDeviceBeingModified() :
       
  4099 	iReferenceCount(0)
       
  4100 	{
       
  4101 	LOG_FUNC
       
  4102 	}
       
  4103 
       
  4104 TBool TRegistryDeviceBeingModified::InUse() const
       
  4105 	{
       
  4106 	LOG_FUNC
       
  4107 		return iReferenceCount > 0;
       
  4108 	}
       
  4109 
       
  4110 TBool TRegistryDeviceBeingModified::IsEqual(const TBTNamelessDevice& aDevice) const
       
  4111 	{
       
  4112 	LOG_FUNC
       
  4113 	return (iDevice == aDevice);
       
  4114 	}
       
  4115 
       
  4116 void TRegistryDeviceBeingModified::Begin(const TBTNamelessDevice& aDevice)
       
  4117 	{
       
  4118 	LOG_FUNC
       
  4119 	iDevice = aDevice;
       
  4120 	iReferenceCount++;
       
  4121 	}
       
  4122 
       
  4123 void TRegistryDeviceBeingModified::RequestCompleted()
       
  4124 	{
       
  4125 	LOG_FUNC
       
  4126 	iReferenceCount--;
       
  4127 	__ASSERT_DEBUG(iReferenceCount >= 0, Panic(ETRegistryDevBeingModUnexpectedCompleted));
       
  4128 	}
       
  4129 
       
  4130 //
       
  4131 // TDisconnectCmdController
       
  4132 // HCI Command Queue Interface for Disconnect Commands
       
  4133 //
       
  4134 
       
  4135 TDisconnectCmdController::TDisconnectCmdController(CPhysicalLink& aLink, MHCICommandQueue& aCmdController) : 	
       
  4136 	iParent(aLink),
       
  4137 	iCmdController(aCmdController)
       
  4138 	{
       
  4139 	LOG_FUNC
       
  4140 	}
       
  4141 
       
  4142 void TDisconnectCmdController::Abort()
       
  4143 	{
       
  4144 	LOG_FUNC
       
  4145 	iCmdController.MhcqRemoveAllCommands(*this);
       
  4146 	}
       
  4147 
       
  4148 TInt TDisconnectCmdController::Disconnect(THCIErrorCode aReason)
       
  4149 	{
       
  4150 	LOG_FUNC
       
  4151 	TRAPD(err, DoDisconnectL(aReason));
       
  4152 	return err;
       
  4153 	}
       
  4154 
       
  4155 void TDisconnectCmdController::DoDisconnectL(THCIErrorCode aReason)
       
  4156 	{
       
  4157 	LOG_FUNC
       
  4158 	CDisconnectCommand* cmd = CDisconnectCommand::NewL(iParent.Handle(), aReason);
       
  4159 
       
  4160 	// Ownership of cmd transfered even if MhcqAddCommandL leaves
       
  4161 	iCmdController.MhcqAddCommandL(cmd, *this);
       
  4162 	}
       
  4163 
       
  4164 void TDisconnectCmdController::MhcqcCommandEventReceived(const THCIEventBase& aEvent, const CHCICommandBase* aRelatedCommand)
       
  4165 	{
       
  4166 	LOG_FUNC
       
  4167 	THCIEventCode code = aEvent.EventCode();
       
  4168 	
       
  4169 	__ASSERT_DEBUG(!(code != EDisconnectionCompleteEvent && code != ECommandStatusEvent), Panic(EDiscCtrlUnexpectedCommandEvent));	// this should never happen
       
  4170 	__ASSERT_DEBUG(aRelatedCommand != NULL, Panic(EDiscCtrlUnmatchedCommandEvent));	// this should never happen
       
  4171 	
       
  4172 	if (!aRelatedCommand)	// it is not the response to our command - should never happen
       
  4173 		return;
       
  4174 	
       
  4175 	if ((code == ECommandStatusEvent) && (aEvent.ErrorCode() != EOK))
       
  4176 		{
       
  4177 		iParent.Disconnection(aEvent.ErrorCode(), iParent.Handle(), aEvent.ErrorCode());
       
  4178 		}
       
  4179 	else if (code == EDisconnectionCompleteEvent)
       
  4180 		{
       
  4181 		const TDisconnectionCompleteEvent& disconnectionCompleteEvent = TDisconnectionCompleteEvent::Cast(aEvent);
       
  4182 		// The connection handle in the disconnect complete event should be the same as the physical link's connection handle
       
  4183 		__ASSERT_DEBUG(disconnectionCompleteEvent.ConnectionHandle() == iParent.Handle(), Panic(EDiscCtrlUnexpectedConnectionHandle));
       
  4184 		iParent.Disconnection(aEvent.ErrorCode(), disconnectionCompleteEvent.ConnectionHandle(), static_cast<THCIErrorCode>(disconnectionCompleteEvent.Reason()));
       
  4185 		}
       
  4186 	}
       
  4187 
       
  4188 void TDisconnectCmdController::MhcqcCommandErrored(TInt __DEBUG_ONLY(aErrorCode), const CHCICommandBase* __DEBUG_ONLY(aCommand))
       
  4189 	{
       
  4190 	LOG_FUNC
       
  4191 	__ASSERT_DEBUG(aCommand, Panic(EDiscCtrlUnmatchedCommandEvent));	// this should never happen
       
  4192 	#ifdef _DEBUG
       
  4193 	LOG2(_L("MhcqcCommandErrored: error code:%d opcode:0x%x"), aErrorCode, aCommand->Opcode());
       
  4194 	#endif
       
  4195 	// Pass this to the physical link as Command Disallowed
       
  4196 	iParent.Disconnection(ECommandDisallowed, iParent.Handle(), ECommandDisallowed);
       
  4197 	}
       
  4198 
       
  4199 
       
  4200 //
       
  4201 // TAuthenticationCmdController
       
  4202 //
       
  4203 
       
  4204 TAuthenticationCmdController::TAuthenticationCmdController(CPhysicalLink& aLink, MHCICommandQueue& aCmdController) : 	
       
  4205 	iParent(aLink),
       
  4206 	iCmdController(aCmdController)
       
  4207 	{
       
  4208 	LOG_FUNC
       
  4209 	}
       
  4210 
       
  4211 void TAuthenticationCmdController::Abort()
       
  4212 	{
       
  4213 	LOG_FUNC
       
  4214 	iCmdController.MhcqRemoveAllCommands(*this);
       
  4215 	}
       
  4216 
       
  4217 TInt TAuthenticationCmdController::LinkKeyRequestReply(const TBTDevAddr& aBdaddr, const TDesC8& aLinkKey) const
       
  4218 /**
       
  4219 	We have obtained a linkkey, tell HC
       
  4220 **/
       
  4221 	{
       
  4222 	CLinkKeyRequestReplyCommand* cmd = NULL;
       
  4223 	TBTLinkKey linkkey;
       
  4224 	linkkey.Copy(aLinkKey);
       
  4225 
       
  4226 	TRAPD(err, cmd = CLinkKeyRequestReplyCommand::NewL(aBdaddr, linkkey));
       
  4227 	if (err == KErrNone)
       
  4228 		{
       
  4229 		// Ownership of cmd transfered even if MhcqAddCommandL leaves
       
  4230 		TRAP(err,iCmdController.MhcqAddCommandL(cmd, (MHCICommandQueueClient&)(*this)));
       
  4231 		}
       
  4232 	if(err != KErrNone)
       
  4233 		{
       
  4234 		iParent.AuthenticationComplete(ELinkKeyRequestPending);
       
  4235 		}
       
  4236 	return err;
       
  4237 	}
       
  4238 	
       
  4239 TInt TAuthenticationCmdController::LinkKeyRequestNegativeReply(const TBTDevAddr& aBdaddr) const
       
  4240 /**
       
  4241 	We have not obtained a linkkey, tell HC
       
  4242 **/
       
  4243 	{
       
  4244 	CLinkKeyRequestReplyNegativeCommand* cmd = NULL;
       
  4245 
       
  4246 	TRAPD(err, cmd = CLinkKeyRequestReplyNegativeCommand::NewL(aBdaddr));
       
  4247 	if (err == KErrNone)
       
  4248 		{
       
  4249 		// Ownership of cmd transfered even if MhcqAddCommandL leaves
       
  4250 		TRAP(err, iCmdController.MhcqAddCommandL(cmd, (MHCICommandQueueClient&)(*this)));
       
  4251 		}
       
  4252 	
       
  4253 	if(err != KErrNone)
       
  4254 		{
       
  4255 		iParent.AuthenticationComplete(ELinkKeyRequestPending);
       
  4256 		}
       
  4257 	return err;
       
  4258 	}
       
  4259 
       
  4260 void TAuthenticationCmdController::MhcqcCommandEventReceived(const THCIEventBase& aEvent, const CHCICommandBase* aRelatedCommand)
       
  4261 	{
       
  4262 	LOG_FUNC
       
  4263 	THCIEventCode code = aEvent.EventCode();
       
  4264 
       
  4265 	__ASSERT_DEBUG(!(code != ECommandCompleteEvent && code != ECommandStatusEvent), Panic(EHCIUnknownCommandEvent));	// this should never happen
       
  4266 	__ASSERT_DEBUG(aRelatedCommand != NULL, Panic(EHCIUnknownCommandEvent));	// this should never happen
       
  4267 
       
  4268 	if (!aRelatedCommand)	// it is not the response to our command - should never happen
       
  4269 		return;
       
  4270 
       
  4271 	if ((code == ECommandStatusEvent) && (aEvent.ErrorCode() != EOK))
       
  4272 		{
       
  4273 		LOG3(_L("TAuthenticationCmdController::MhcqcCommandEventReceived: event:%d opcode:0x%x error:0x%x"), code, aRelatedCommand->Opcode(), aEvent.ErrorCode());
       
  4274 		}
       
  4275 	else if (code == ECommandCompleteEvent)
       
  4276 		{
       
  4277 		LOG2(_L("TAuthenticationCmdController::MhcqcCommandEventReceived: event:%d opcode:0x%x"), code, aRelatedCommand->Opcode());
       
  4278 		iParent.AuthenticationComplete(ELinkKeyRequestPending);
       
  4279 		}
       
  4280 	}
       
  4281 
       
  4282 void TAuthenticationCmdController::MhcqcCommandErrored(TInt __DEBUG_ONLY(aErrorCode), const CHCICommandBase* __DEBUG_ONLY(aCommand))
       
  4283 	{
       
  4284 	LOG_FUNC
       
  4285 	__ASSERT_DEBUG(aCommand, Panic(EHCIUnknownCommandEvent));	// this should never happen
       
  4286 	#ifdef _DEBUG
       
  4287 	LOG2(_L("MhcqcCommandErrored: error code:%d opcode:0x%x"), aErrorCode, aCommand->Opcode());
       
  4288 	#endif
       
  4289 	iParent.AuthenticationComplete(ELinkKeyRequestPending);
       
  4290 	}
       
  4291