bluetooth/btstack/linkmgr/linkmgr.cpp
changeset 0 29b1cd4cb562
child 13 20fda83a6398
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 1999-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 // This implements the CLinkMgrProtocol object that is the contact point from
       
    15 // BT PRT to the LinkMgr stack
       
    16 // At present this class also remembers the configuration of the controller
       
    17 // -- no particular reason - could be encapsulated in a class that the facade
       
    18 // knows about.
       
    19 // 
       
    20 //
       
    21 
       
    22 #include <bt_sock.h>
       
    23 #include <bluetooth/logger.h>
       
    24 #include "debug.h"
       
    25 #include <utf.h>
       
    26 #include <bluetooth/hci/hciframe.h>
       
    27 #include <bluetooth/aclsockaddr.h>
       
    28 
       
    29 #include "linkmgr.h"
       
    30 #include "hcifacade.h"
       
    31 #include "bt.h"
       
    32 #include "hostresolver.h"
       
    33 #include "linkmuxer.h"
       
    34 #include "physicallinksmanager.h"
       
    35 #include "linkconsts.h"
       
    36 #include "eirmanserver.h"
       
    37 #include "eirmanager.h"
       
    38 #include "eirpublisherlocalname.h"
       
    39 #include "eirpublishertxpowerlevel.h"
       
    40 
       
    41 
       
    42 #include "ProxySAP.h"
       
    43 #include "SCOSAP.h"
       
    44 #include "ACLSAP.h"
       
    45 #include "VendorSAP.h"
       
    46 #include "vendorspecific.h"
       
    47 
       
    48 #include "Subscribers.h"
       
    49 #include "BTSec.h"
       
    50 
       
    51 #ifdef __FLOG_ACTIVE
       
    52 _LIT8(KLogComponent, LOG_COMPONENT_LINKMGR);
       
    53 #endif
       
    54 
       
    55 #ifdef _DEBUG
       
    56 PANICCATEGORY("linkmgr");
       
    57 #endif
       
    58 
       
    59 const TInt KLengthOfDeviceClass = 11;			// 11 bits in the device class portion of the CoD
       
    60 const TInt KStartingOffsetOfDeviceClass = 2;	// 2 LSB bits for format type
       
    61 const TUint32 KDeviceClassReset = 0;			// used to reset persistent data
       
    62 
       
    63 // Constant which can be ANDed with a complete CoD bitmask to extract the device class portion.
       
    64 const TInt KDeviceClassBitMask = ((1 << KLengthOfDeviceClass) - 1) << KStartingOffsetOfDeviceClass;
       
    65 
       
    66 
       
    67 enum TLinkMgrPanic
       
    68 	{
       
    69 	ELinkMgrProtocolOpenedAfterClose,
       
    70 	ELinkMgrProtocolBadAFHHostChannelClassification,
       
    71 	EUnknownFatalError,
       
    72 	ELocalDeviceBadHandle,
       
    73 	ERegistrySessionClosedTooManyTimes,
       
    74 	ERegistrySessionDeletedWhenOpen,
       
    75 	};
       
    76 
       
    77 void Panic(TLinkMgrPanic aPanic)
       
    78 // Panic L2CAP due to stack bug.
       
    79 	{
       
    80 	LOG_STATIC_FUNC
       
    81 	_LIT(KL2CAPPanicName, "BTLinkMgr");
       
    82 	User::Panic(KL2CAPPanicName, aPanic);
       
    83 	}
       
    84 
       
    85 // Construction & Initialisation
       
    86 
       
    87 CLinkMgrProtocol::CLinkMgrProtocol(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan)
       
    88 : CBluetoothProtocolBase(aSecMan, aControlPlane, aCodMan)
       
    89 , iDebugModeDefinitionResult(KErrGeneral)
       
    90 	{
       
    91 	LOG_FUNC
       
    92 	TCallBack cb(TryToClose, this);
       
    93 	iIdleTimerEntry.Set(cb);
       
    94 	}
       
    95 
       
    96 CLinkMgrProtocol::~CLinkMgrProtocol()
       
    97 /**
       
    98 	Delete all our stuff
       
    99 **/
       
   100    
       
   101 	{
       
   102 	LOG_FUNC
       
   103 	RemoveIdleTimerEntry();
       
   104 	
       
   105 	// Delete setter P&S values
       
   106 	iProperty.Delete(KPropertyUidBluetoothCategory,	KPropertyKeyBluetoothSetScanningStatus);
       
   107 	iProperty.Delete(KPropertyUidBluetoothCategory,	KPropertyKeyBluetoothSetLimitedDiscoverableStatus);
       
   108 	iProperty.Delete(KPropertyUidBluetoothCategory,	KPropertyKeyBluetoothSetDeviceClass);
       
   109 	iProperty.Delete(KPropertyUidBluetoothCategory,	KPropertyKeyBluetoothSetAFHHostChannelClassification);
       
   110 	iProperty.Delete(KPropertyUidBluetoothCategory,	KPropertyKeyBluetoothSetAFHChannelAssessmentMode);
       
   111 	iProperty.Delete(KPropertyUidBluetoothCategory,	KPropertyKeyBluetoothSetDeviceName);
       
   112 	iProperty.Delete(KPropertyUidBluetoothCategory,	KPropertyKeyBluetoothSetAcceptPairedOnlyMode);
       
   113 
       
   114 	// Delete standard P&S values (possibly trying to delete already deleted shared set+get values)
       
   115 	iProperty.Delete(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothGetLocalDeviceAddress);
       
   116 	iProperty.Delete(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothGetPHYCount);
       
   117 	iProperty.Delete(KPropertyUidBluetoothCategory,	KPropertyKeyBluetoothGetConnectingStatus);
       
   118 	iProperty.Delete(KPropertyUidBluetoothCategory,	KPropertyKeyBluetoothGetScanningStatus);
       
   119 	iProperty.Delete(KPropertyUidBluetoothCategory,	KPropertyKeyBluetoothGetLimitedDiscoverableStatus);
       
   120 	iProperty.Delete(KPropertyUidBluetoothCategory,	KPropertyKeyBluetoothGetDeviceClass);
       
   121 	iProperty.Delete(KPropertyUidBluetoothCategory,	KPropertyKeyBluetoothGetDeviceName);
       
   122 	iProperty.Delete(KPropertyUidBluetoothCategory,	KPropertyKeyBluetoothGetAcceptPairedOnlyMode);
       
   123 	iProperty.Delete(KPropertyUidBluetoothCategory,	KPropertyKeyBluetoothHostResolverActive);
       
   124 	iProperty.Delete(KPropertyUidBluetoothCategory,	KPropertyKeyBluetoothSetSimplePairingDebugMode);
       
   125 
       
   126 	delete iPhysicalLinksMgr;
       
   127 	delete iInquiryMgr;
       
   128 	delete iEirManServer;
       
   129 	delete iACLStateFactory;
       
   130 	delete iSCOStateFactory;
       
   131 
       
   132 	SecMan().ClearHCICommandQueue(); // clears up the commands
       
   133 	SecMan().ClearLinksMgrProtocol();
       
   134 	SecMan().ClearPhysicalLinksMgr();
       
   135 	
       
   136 	delete iLinkMuxer;
       
   137 	delete iHCIFacade;
       
   138 	
       
   139 	delete iRegistryUpdater;
       
   140 
       
   141 	DeletePublications();
       
   142 	iSubscribers.ResetAndDestroy();
       
   143 
       
   144 	iLocalDevice.Close();
       
   145 	delete iRegSess;
       
   146 	}
       
   147 
       
   148 CLinkMgrProtocol* CLinkMgrProtocol::NewL(CBTSecMan& aSecMan, RBTControlPlane& aControlPlane, CBTCodServiceMan& aCodMan)
       
   149 	{
       
   150 	LOG_STATIC_FUNC
       
   151 	CLinkMgrProtocol* i=new (ELeave) CLinkMgrProtocol(aSecMan, aControlPlane, aCodMan);
       
   152 	return i;
       
   153 	}
       
   154 
       
   155 void CLinkMgrProtocol::InitL(TDesC& /*aTag*/)
       
   156 /**
       
   157 	Pre-binding initialise.
       
   158 	Allocate any objects we need here.
       
   159 	ESOCK ensures that this function will only be called once per
       
   160 	object of this class, regardless of how long it hangs around.
       
   161 **/
       
   162 	{
       
   163 	LOG_FUNC
       
   164 
       
   165 	__ASSERT_DEBUG(!iClosePending, Panic(ELinkMgrProtocolOpenedAfterClose));
       
   166 	__ASSERT_DEBUG(!iIdleEntryQueued, Panic(ELinkMgrProtocolOpenedAfterClose));
       
   167 	__ASSERT_DEBUG(!iHCIFacade, Panic(ELinkMgrProtocolOpenedAfterClose));
       
   168 
       
   169 	// Get the local device settings from persistent store
       
   170 	// By keeping a session open for the lifetime of this protocol
       
   171 	// we prevent RegServ being created during connection time.
       
   172 	LOG(_L("LinkMgr : Initialising RegistryServer"));
       
   173 	iRegSess = CRegistrySession::NewL(*this);
       
   174 	TInt err = iLocalDevice.Open(iRegSess->RegServ());
       
   175 	
       
   176 	if (err ==KErrNone)
       
   177 		{
       
   178 		// read local device settings (e.g page scan\inquiry scan) from registry
       
   179 		err = iLocalDevice.Get(iLocalDeviceSettings);	// ignore error - can continue
       
   180 		__ASSERT_DEBUG(err==KErrNone, Panic(EUnknownFatalError));		
       
   181 		
       
   182 		
       
   183 		//
       
   184 		// Mask off the service class bits from the CoD -- we're not interested in the
       
   185 		// registry's values for anything other than the device class part.
       
   186 		// There's a nice terminology overload here, as the 'Class of Device' contains
       
   187 		// both a device class and a service class.  It might have been nice if the
       
   188 		// getter and setter methods were 'ClassOfDevice', but even that wouldn't help
       
   189 		// much...
       
   190 		//
       
   191 		iLocalDeviceSettings.SetDeviceClass(iLocalDeviceSettings.DeviceClass() & KDeviceClassBitMask);
       
   192 		
       
   193 		
       
   194 		//NB - no (ELeave) here - in OOM we'd rather continue and not update the registry
       
   195 		//than Leave.  All calls to methods are guarded by "if (iRegistryUpdater)"
       
   196 		iRegistryUpdater = new CRegistryUpdater(iLocalDevice, iLocalDeviceSettings);
       
   197 		}
       
   198 
       
   199 	LOG(_L("LinkMgr : Creating HCIFacade (and HCI)"));
       
   200 	iHCIFacade = CHCIFacade::NewL(*this); 	// Create HCI/HCIFacade first
       
   201 	iPhysicalLinksMgr = CPhysicalLinksManager::NewL(*this, *iHCIFacade, *iRegSess, SecMan(), CodMan());
       
   202 	iPhysicalLinksMgr->SetAcceptPairedOnlyMode(iLocalDeviceSettings.AcceptPairedOnlyMode()); // Tell the physical links manager the persisted value for the accept paired only mode
       
   203 	iHCIFacade->SetPhysicalLinksMgr(*iPhysicalLinksMgr); 	// Tell HCIFacade of ConnMgr
       
   204 
       
   205 	SecMan().SetPhysicalLinksMgr(*iPhysicalLinksMgr);
       
   206 	SecMan().SetLinksMgrProtocol(*this);
       
   207 	SecMan().SetHCICommandQueue(iHCIFacade->CommandQController());
       
   208 
       
   209 	LOG(_L("LinkMgr : Initialising Link Muxer"));
       
   210 	iLinkMuxer=CLinkMuxer::NewL(*this, *iHCIFacade);
       
   211 	iHCIFacade->SetLinkMuxer(*iLinkMuxer);
       
   212 
       
   213 	iACLStateFactory = CACLLinkStateFactory::NewL();
       
   214 	iSCOStateFactory = CSyncLinkStateFactory::NewL();
       
   215 				
       
   216 	LOG(_L("LinkMgr : Initialising EirManServer"));
       
   217 	iEirManServer = CEirManServer::NewL(iHCIFacade->CommandQController(), *this);
       
   218 
       
   219 	LOG(_L("LinkMgr : Initialising InquiryMgr"));
       
   220 	iInquiryMgr = CBTInquiryMgr::NewL(*this);
       
   221 	iInquiryMgr->SetHCICommandQueue(iHCIFacade->CommandQController());
       
   222 
       
   223 
       
   224 	LOG(_L("LinkMgr : Configuring HCIFacade)"));
       
   225 	iHCIFacade->InitL(iLocalDeviceSettings);// passes ownership of device
       
   226 	
       
   227 	// Inquiry and page scan is read from BT Registry and set it to P&S
       
   228 	// As there is no listening socket, they are set to OFF on HW yet!
       
   229 	// P&S value is taken to account as soon we open the first listening socket!
       
   230 	DefinePublications(iLocalDeviceSettings.ScanEnable());
       
   231 	
       
   232 	// set up subscribers
       
   233 	CSubscriber* subscriber;
       
   234 	
       
   235 	subscriber = CDiscoverabilitySubscriber::NewL(*this);
       
   236 	CleanupStack::PushL(subscriber);
       
   237 	User::LeaveIfError(iSubscribers.Append(subscriber));
       
   238 	CleanupStack::Pop(subscriber);
       
   239 
       
   240 	subscriber = CLimitedSubscriber::NewL(*this);
       
   241 	CleanupStack::PushL(subscriber);
       
   242 	User::LeaveIfError(iSubscribers.Append(subscriber));
       
   243 	CleanupStack::Pop(subscriber);
       
   244 
       
   245 	subscriber = CDeviceClassSubscriber::NewL(*this);
       
   246 	CleanupStack::PushL(subscriber);
       
   247 	User::LeaveIfError(iSubscribers.Append(subscriber));
       
   248 	CleanupStack::Pop(subscriber);
       
   249 	
       
   250 	subscriber = CAFHHostChannelClassificationSubscriber::NewL(*this);
       
   251 	CleanupStack::PushL(subscriber);
       
   252 	User::LeaveIfError(iSubscribers.Append(subscriber));
       
   253 	CleanupStack::Pop(subscriber);
       
   254 	
       
   255 	subscriber = CDeviceNameSubscriber::NewL(*this);
       
   256 	CleanupStack::PushL(subscriber);
       
   257 	User::LeaveIfError(iSubscribers.Append(subscriber));
       
   258 	CleanupStack::Pop(subscriber);
       
   259 
       
   260 	subscriber = CRegistryRemoteTableSubscriber::NewL(*this);
       
   261 	CleanupStack::PushL(subscriber);
       
   262 	User::LeaveIfError(iSubscribers.Append(subscriber));
       
   263 	CleanupStack::Pop(subscriber);
       
   264 	
       
   265 	subscriber = CAcceptPairedOnlySubscriber::NewL(*this);
       
   266 	CleanupStack::PushL(subscriber);
       
   267 	User::LeaveIfError(iSubscribers.Append(subscriber));
       
   268 	CleanupStack::Pop(subscriber);
       
   269 	
       
   270 	subscriber = CAFHChannelAssessmentModeSubscriber::NewL(*this);
       
   271 	CleanupStack::PushL(subscriber);
       
   272 	User::LeaveIfError(iSubscribers.Append(subscriber));
       
   273 	CleanupStack::Pop(subscriber);
       
   274 	
       
   275 	if(iDebugModeDefinitionResult == KErrNone)
       
   276 		{
       
   277 		// Only subscribe on debug mode if we have managed to successfully define
       
   278 		// the key ourselves (this is because it needs to be protected with the very 
       
   279 		// strong CommDD capability).
       
   280 		subscriber = CDebugModeSubscriber::NewL(*this);
       
   281 		CleanupStack::PushL(subscriber);
       
   282 		User::LeaveIfError(iSubscribers.Append(subscriber));
       
   283 		CleanupStack::Pop(subscriber);
       
   284 		}
       
   285 
       
   286 	// set CoD - leave if goes wrong, user's device will be "unknown" otherwise
       
   287 	// NB - In future we should tie this to the SDP Server...(or someother higher API...)
       
   288 	
       
   289 	if (iLocalDeviceSettings.DeviceClass() && iLocalDeviceSettings.IsValidDeviceClass())
       
   290 	// Some phones never set their CoD in s/w, we don't want to blat
       
   291 	// over their h/w settings
       
   292 		{
       
   293 		iPendingLocalDeviceSettings.SetDeviceClass(iLocalDeviceSettings.DeviceClass()); //we expect this after power on
       
   294 		}
       
   295 
       
   296 	CodMan().Initialise();	// Cod Service Manager can now get a valid CoD
       
   297 
       
   298 	if(iLocalDeviceSettings.AFHChannelAssessmentMode() == EFalse)
       
   299 	// If this feature is supported it will start off switched on
       
   300 		{
       
   301 		SetAFHChannelAssessmentModeL(iLocalDeviceSettings.AFHChannelAssessmentMode());
       
   302 		}
       
   303 
       
   304 	//Attempt to make sure that controller has the same value as the registry
       
   305 	//and that the P&S key 'KPropertyKeyBluetoothGetLimitedDiscoverableStatus'
       
   306 	//is, as a consequence, 'Set' appropriately (when the associated controller 
       
   307 	//event arrives).
       
   308 	DoSetLimitedDiscoverableL(iLocalDeviceSettings.LimitedDiscoverable());
       
   309 	
       
   310 	LOG(_L("LinkMgr : Initialising complete"));
       
   311 	}
       
   312 
       
   313 void CLinkMgrProtocol::DefinePublications(THCIScanEnable aHCIScanEnable)
       
   314 	{
       
   315 	LOG_FUNC
       
   316 	
       
   317 	// 6 properties for setting.
       
   318 	// Its possible that these are re-defined below, but we are discarding any KErrAlreadyExists.
       
   319 	// As the setters require more capabilities we ensure that they get defined first.
       
   320 
       
   321 	(void)(iProperty.Define(KPropertyUidBluetoothCategory,
       
   322 							KPropertyKeyBluetoothSetScanningStatus,
       
   323 							RProperty::EInt,
       
   324 							KLOCAL_SERVICES_AND_NETWORK_CONTROL,
       
   325 							KLOCAL_SERVICES_AND_NETWORK_CONTROL
       
   326 							));
       
   327 	
       
   328 	// Even if we initialise KPropertyKeyBluetoothSetScanningStatus to Inquiry & 
       
   329 	// Page scanning enabled, it's not turned on at this point. Only when first
       
   330 	// listening socket is opened, this value will control the inquiry scan & page scan
       
   331 
       
   332 	(void)(iProperty.Set(KPropertyUidBluetoothCategory,
       
   333 						 KPropertyKeyBluetoothSetScanningStatus,
       
   334 						 aHCIScanEnable));
       
   335 						 
       
   336 	(void)(iProperty.Define(KPropertyUidBluetoothCategory,
       
   337 							KPropertyKeyBluetoothSetLimitedDiscoverableStatus,
       
   338 							RProperty::EInt,
       
   339 							KLOCAL_SERVICES_AND_NETWORK_CONTROL,
       
   340 							KLOCAL_SERVICES_AND_NETWORK_CONTROL
       
   341 							));
       
   342 
       
   343 	(void)(iProperty.Define(KPropertyUidBluetoothCategory,
       
   344 							KPropertyKeyBluetoothSetDeviceClass,
       
   345 							RProperty::EInt,
       
   346 							KLOCAL_SERVICES_AND_NETWORK_CONTROL,
       
   347 							KLOCAL_SERVICES_AND_NETWORK_CONTROL
       
   348 							));
       
   349 
       
   350 	(void)(iProperty.Define(KPropertyUidBluetoothCategory,
       
   351 							KPropertyKeyBluetoothSetAFHHostChannelClassification,
       
   352 							RProperty::EByteArray,
       
   353 							KLOCAL_SERVICES_AND_NETWORK_CONTROL,
       
   354 							KLOCAL_SERVICES_AND_NETWORK_CONTROL
       
   355 							));
       
   356 
       
   357 	(void)(iProperty.Define(KPropertyUidBluetoothCategory,
       
   358 							KPropertyKeyBluetoothSetAFHChannelAssessmentMode,
       
   359 							RProperty::EInt,
       
   360 							KLOCAL_SERVICES_AND_NETWORK_CONTROL,
       
   361 							KLOCAL_SERVICES_AND_NETWORK_CONTROL
       
   362 							));
       
   363 
       
   364 	(void)(iProperty.Define(KPropertyUidBluetoothCategory,
       
   365 							KPropertyKeyBluetoothSetDeviceName,
       
   366 							RProperty::EText,
       
   367 							KLOCAL_SERVICES_AND_NETWORK_CONTROL,
       
   368 							KLOCAL_SERVICES_AND_NETWORK_CONTROL
       
   369 							));
       
   370 
       
   371 	(void)(iProperty.Define(KPropertyUidBluetoothCategory,
       
   372 							KPropertyKeyBluetoothSetAcceptPairedOnlyMode,
       
   373 							RProperty::EInt,
       
   374 							KLOCAL_SERVICES_AND_NETWORK_CONTROL,
       
   375 							KLOCAL_SERVICES_AND_NETWORK_CONTROL
       
   376 							));
       
   377 	
       
   378 	iDebugModeDefinitionResult = (iProperty.Define(KPropertyUidBluetoothCategory,
       
   379 							KPropertyKeyBluetoothSetSimplePairingDebugMode,
       
   380 							RProperty::EInt,
       
   381 							KLOCAL_SERVICES,
       
   382 							KCOMMDD
       
   383 							));
       
   384 
       
   385 
       
   386 	// Original Get P&S value definitions.
       
   387 
       
   388 	(void)(iProperty.Define(KPropertyUidBluetoothCategory,
       
   389 							KPropertyKeyBluetoothGetLocalDeviceAddress,
       
   390 							RProperty::EByteArray,
       
   391 							KLOCAL_SERVICES,
       
   392 						   	KLOCAL_SERVICES_AND_NETWORK_CONTROL
       
   393 							));
       
   394 
       
   395 	(void)(iProperty.Define(KPropertyUidBluetoothCategory,
       
   396 							KPropertyKeyBluetoothGetPHYCount,
       
   397 							RProperty::EInt,
       
   398 							KLOCAL_SERVICES,
       
   399 						   	KLOCAL_SERVICES_AND_NETWORK_CONTROL
       
   400 							));
       
   401 
       
   402 	(void)(iProperty.Define(KPropertyUidBluetoothCategory,
       
   403 							KPropertyKeyBluetoothGetConnectingStatus,
       
   404 							RProperty::EInt,
       
   405 							KLOCAL_SERVICES,
       
   406 						   	KLOCAL_SERVICES_AND_NETWORK_CONTROL
       
   407 							));
       
   408 
       
   409 	(void)(iProperty.Define(KPropertyUidBluetoothCategory,
       
   410 							KPropertyKeyBluetoothGetScanningStatus,
       
   411 							RProperty::EInt,
       
   412 							KLOCAL_SERVICES,
       
   413 						   	KLOCAL_SERVICES_AND_NETWORK_CONTROL
       
   414 							));
       
   415 
       
   416 	(void)(iProperty.Define(KPropertyUidBluetoothCategory,
       
   417 							KPropertyKeyBluetoothGetLimitedDiscoverableStatus,
       
   418 							RProperty::EInt,
       
   419 							KLOCAL_SERVICES,
       
   420 						   	KLOCAL_SERVICES_AND_NETWORK_CONTROL
       
   421 							));
       
   422 
       
   423 	(void)(iProperty.Define(KPropertyUidBluetoothCategory,
       
   424 							KPropertyKeyBluetoothGetDeviceClass,
       
   425 							RProperty::EInt,
       
   426 							KLOCAL_SERVICES,
       
   427 						   	KLOCAL_SERVICES_AND_NETWORK_CONTROL
       
   428 							));
       
   429 
       
   430 	(void)(iProperty.Define(KPropertyUidBluetoothCategory,
       
   431 							KPropertyKeyBluetoothGetDeviceName,
       
   432 							RProperty::EText,
       
   433 							KLOCAL_SERVICES,
       
   434 						   	KLOCAL_SERVICES_AND_NETWORK_CONTROL
       
   435 							));
       
   436 							
       
   437 	(void)(iProperty.Define(KPropertyUidBluetoothCategory,
       
   438 							KPropertyKeyBluetoothGetAcceptPairedOnlyMode,
       
   439 							RProperty::EInt,
       
   440 							KLOCAL_SERVICES,
       
   441 						   	KLOCAL_SERVICES_AND_NETWORK_CONTROL
       
   442 							));
       
   443 							
       
   444  	(void) (iProperty.Define(KPropertyUidBluetoothCategory,
       
   445  							KPropertyKeyBluetoothHostResolverActive,
       
   446  							RProperty::EInt,
       
   447  							KLOCAL_SERVICES,
       
   448  						   	KLOCAL_SERVICES_AND_NETWORK_CONTROL
       
   449  							));
       
   450  	
       
   451 	(void)(iProperty.Define(KPropertyUidBluetoothCategory,
       
   452 							KPropertyKeyBluetoothGetSimplePairingDebugMode,
       
   453 							RProperty::EInt,
       
   454 							KLOCAL_SERVICES,
       
   455 						   	KLOCAL_SERVICES_AND_NETWORK_CONTROL
       
   456 							));
       
   457 	}
       
   458 
       
   459 void CLinkMgrProtocol::DeletePublications()
       
   460 	{
       
   461 	LOG_FUNC
       
   462 	//we own them, so they'll get deleted
       
   463 	iProperty.Close();
       
   464 	}
       
   465 
       
   466 void CLinkMgrProtocol::StartL()
       
   467 /**
       
   468 	Binding complete.
       
   469 	Startup call from esock.  Do nothing
       
   470 	If HCI needs any start-up, do it here.
       
   471 **/
       
   472 	{
       
   473 	LOG_FUNC
       
   474 	}
       
   475 
       
   476 // From higher protocol
       
   477 void CLinkMgrProtocol::BindL(CProtocolBase* protocol, TUint /* id*/)
       
   478 	{
       
   479 	LOG_FUNC
       
   480 	TServerProtocolDesc prtDesc;
       
   481 	protocol->Identify(&prtDesc);
       
   482 
       
   483 #ifdef TCI
       
   484 	if(prtDesc.iAddrFamily!=KBTAddrFamily || prtDesc.iProtocol!=KTCIL2CAP)
       
   485 #else
       
   486 	if(prtDesc.iAddrFamily!=KBTAddrFamily || prtDesc.iProtocol!=KL2CAP)
       
   487 #endif
       
   488 		{
       
   489 		User::Leave(KErrBtEskError);
       
   490 		}
       
   491 	// Store this for error propogation
       
   492 	//
       
   493 	iUpperProtocol = protocol;
       
   494 	}
       
   495 
       
   496 // Factory functions
       
   497 
       
   498 CHostResolvProvdBase* CLinkMgrProtocol::NewHostResolverL()
       
   499 	{
       
   500 	LOG_FUNC
       
   501 	return iInquiryMgr->NewHostResolverL();
       
   502 	}
       
   503 
       
   504 // Query functions
       
   505 
       
   506 void CLinkMgrProtocol::Identify(TServerProtocolDesc* aDesc) const
       
   507 //
       
   508 // Identify request from SOCKET server
       
   509 //
       
   510 	{
       
   511 	LOG_FUNC
       
   512 	CLinkMgrProtocol::ProtocolIdentity(aDesc);
       
   513 	}
       
   514 
       
   515 void CLinkMgrProtocol::ProtocolIdentity(TServerProtocolDesc* aDesc)
       
   516 	{
       
   517 	LOG_STATIC_FUNC
       
   518 	_LIT(name,"BTLinkManager");
       
   519 	aDesc->iProtocol=KBTLinkManager;
       
   520 
       
   521 	aDesc->iName=name;
       
   522 	aDesc->iAddrFamily=KBTAddrFamily;
       
   523 	aDesc->iSockType=KUndefinedSockType;	// various!
       
   524 	
       
   525 	aDesc->iVersion=TVersion(KBTMajor,KBTMinor,KBTBuild);
       
   526 	aDesc->iByteOrder=ELittleEndian;
       
   527 
       
   528 /*
       
   529 	The following sockets are exposed as RSockets
       
   530 
       
   531 	'Proxy' = a SAP attached to a baseband connection that can influence it
       
   532 	'SCO'	= a SAP providing SCO services
       
   533 
       
   534 	Higher protocols can additionally ask for ACL SAPs, but these are not 
       
   535 	available as RSockets
       
   536 
       
   537 	This guides the direction of the ServiceInfo below
       
   538 
       
   539 */
       
   540 
       
   541 	aDesc->iServiceInfo=KSIDatagram|KSIGracefulClose|KSIBroadcast|KSIQOS|KSICanReconnect|KSIConnectData|KSIDisconnectData; // slightly hijacked connectData
       
   542 	aDesc->iNamingServices=KNSNameResolution;
       
   543 	aDesc->iSecurity=KSocketNoSecurity;
       
   544 	aDesc->iMessageSize=Max(CHctlSynchronousDataFrame::KHCTLMaxSynchronousDataSize, CHctlAclDataFrame::KHCTLMaxACLDataSize);
       
   545 	aDesc->iServiceTypeInfo=ESocketSupport|ECantProcessMBufChains|ENeedMBufs|ETransport
       
   546 							|EPreferDescriptors|EUseCanSend;
       
   547 	aDesc->iNumSockets=100;	// one per baseband - including many parked!
       
   548 	}
       
   549 
       
   550 void CLinkMgrProtocol::Error(TInt aErr, CProtocolBase* /*aProt*/)
       
   551 	{
       
   552 	LOG_FUNC
       
   553 	// A fatal error has occurred (Power off hopefully!). Notify the upper protocol
       
   554 	// (of there is one) and the inquiry manager. 
       
   555 	__ASSERT_DEBUG(aErr==KErrHardwareNotAvailable, Panic(EUnknownFatalError));
       
   556 	iInquiryMgr->CompleteCommands(aErr);
       
   557 	iPhysicalLinksMgr->FatalError(aErr);
       
   558 	}
       
   559 
       
   560 void CLinkMgrProtocol::CloseNow()
       
   561 /**
       
   562 	Close command from base class.
       
   563 	Called when ref count reaches 0.
       
   564 	We don't actually have to close now, but when we finally
       
   565 	do, we must call CanClose (done within TryToClose). That'll
       
   566 	actually delete us. In the mean time, if a new client tries
       
   567 	to connect to LinkMgr, ESOCK will use this existing one and just
       
   568 	call Open on it.
       
   569 	What we do here, is queue an idle timer entry. It's expiry will
       
   570 	call TryToClose, which'll actually do the close.
       
   571 **/
       
   572 	{
       
   573 	LOG_FUNC
       
   574 	// synchronously update stack state in Registry
       
   575 	iLocalDevice.Modify(iLocalDeviceSettings); //ignore error		
       
   576 	
       
   577 	iClosePending = ETrue;
       
   578 	QueIdleTimerEntry();
       
   579 	}
       
   580 
       
   581 void CLinkMgrProtocol::Open()
       
   582 /**
       
   583 	Open LinkMgr protocol.
       
   584 	Called everytime a new client (of LinkMgr) wants to use it.
       
   585 **/
       
   586 	{
       
   587 	LOG_FUNC
       
   588 	LocalOpen();
       
   589 	if(iExternalRef++ == 0)
       
   590 		{
       
   591 		ExternalOpenInit();
       
   592 		}
       
   593 	}
       
   594 
       
   595 void CLinkMgrProtocol::Close()
       
   596 	{
       
   597 	LOG_FUNC
       
   598 	if(--iExternalRef == 0)
       
   599 		{
       
   600 		ExternalCloseCleanup();
       
   601 		}
       
   602 	LocalClose();
       
   603 	}
       
   604 
       
   605 void CLinkMgrProtocol::LocalOpen()
       
   606 	{
       
   607 	LOG_FUNC
       
   608 	iClosePending = EFalse;
       
   609 	RemoveIdleTimerEntry();
       
   610 	CProtocolBase::Open();
       
   611 	}
       
   612 
       
   613 void CLinkMgrProtocol::LocalClose()
       
   614 	{
       
   615 	LOG_FUNC
       
   616 	CProtocolBase::Close();
       
   617 	}
       
   618 
       
   619 void CLinkMgrProtocol::ExternalOpenInit()
       
   620 	{
       
   621 	LOG_FUNC
       
   622 	TRAP_IGNORE(iLocalNamePublisher = CEirPublisherLocalName::NewL());
       
   623 	TRAP_IGNORE(iTxPowerLevelPublisher = CEirPublisherTxPowerLevel::NewL());
       
   624 	if(iLocalNamePublisher)
       
   625 		{
       
   626 		// Publish the initial name.
       
   627 		iLocalNamePublisher->UpdateName(iLocalDeviceSettings.DeviceName());
       
   628 		}
       
   629 	}
       
   630 
       
   631 void CLinkMgrProtocol::ExternalCloseCleanup()
       
   632 	{
       
   633 	LOG_FUNC
       
   634 	// Currently just the internal publishers
       
   635 	delete iLocalNamePublisher;
       
   636 	iLocalNamePublisher = NULL;
       
   637 	delete iTxPowerLevelPublisher;
       
   638 	iTxPowerLevelPublisher = NULL;
       
   639 	}
       
   640 
       
   641 void CLinkMgrProtocol::QueIdleTimerEntry()
       
   642 /**
       
   643 	Queue idle timer entry.
       
   644 	When this timer expires, it'll call TryToClose, which actually
       
   645 	causes the thing to finally close down.
       
   646 **/
       
   647 	{
       
   648 	LOG_FUNC
       
   649 	RemoveIdleTimerEntry();
       
   650 	iIdleEntryQueued = ETrue;
       
   651 	BTSocketTimer::Queue(KLinkMgrProtocolIdleTimer, iIdleTimerEntry);
       
   652 	}
       
   653 
       
   654 void CLinkMgrProtocol::RemoveIdleTimerEntry()
       
   655 /**
       
   656 	Called whenever we're opened.
       
   657 	Checks there are no idle timer entries queued.
       
   658 **/
       
   659 	{
       
   660 	LOG_FUNC
       
   661 	if (!iIdleEntryQueued)
       
   662 		return;
       
   663 	BTSocketTimer::Remove(iIdleTimerEntry);
       
   664 	iIdleEntryQueued = EFalse;
       
   665 	}
       
   666 
       
   667  /*static*/ TInt CLinkMgrProtocol::TryToClose(TAny* aProtocol)
       
   668 /**
       
   669 	Actually try to close the protocol.
       
   670 	Called after the idle timeout period by the BTSocketTimer. If
       
   671 	we're all set to close down, the thing is closed.
       
   672 **/
       
   673 	{
       
   674 	LOG_STATIC_FUNC
       
   675 	CLinkMgrProtocol* p=static_cast<CLinkMgrProtocol*>(aProtocol);
       
   676 	p->iIdleEntryQueued = EFalse;
       
   677 	if (p->iClosePending)
       
   678 		{
       
   679 		p->CanClose();	// deletes this
       
   680 		}
       
   681 	return EFalse;
       
   682 	}
       
   683 
       
   684 CServProviderBase* CLinkMgrProtocol::NewSAPL(TUint aSockType)
       
   685 /** 
       
   686 	Create a new SAP.
       
   687 	The SAP returned is owned by the caller -- this protocol will not clean it up.
       
   688 	esock uses this function to create a new SAP, and esock will delete when it
       
   689 	is finished with it.
       
   690 **/
       
   691 	{
       
   692 	LOG_FUNC
       
   693 
       
   694 	CServProviderBase* sap = NULL;
       
   695 	
       
   696 	switch (aSockType)
       
   697 		{
       
   698 		case KSockBluetoothTypeESCO:
       
   699 			{
       
   700 			sap = CeSCOLink::NewL(*iPhysicalLinksMgr, NULL);
       
   701 			break;
       
   702 			}
       
   703 
       
   704 		case KSockBluetoothTypeSCO:
       
   705 			{
       
   706 			sap = CSCOLink::NewL(*iPhysicalLinksMgr, NULL);
       
   707 			break;
       
   708 			}
       
   709 
       
   710 		case KSockBluetoothTypeACL:
       
   711 			{
       
   712 			// an explicit ACL link has been asked for (by L2CAP)
       
   713 			sap = CACLLink::NewL(*iPhysicalLinksMgr, NULL, *this); // don't know for which PHY at this stage
       
   714 			break;
       
   715 			}
       
   716 
       
   717 		case KSockBluetoothTypeVendorSpecific:
       
   718 			{
       
   719 			if (!iVendorSpecificSAP)
       
   720 				{
       
   721 				sap = CVendorSAP::NewL(*this);
       
   722 				}
       
   723 			else
       
   724 				{
       
   725 				User::Leave(KErrInUse); // only support one :o)
       
   726 				}
       
   727 			break;
       
   728 			}
       
   729 
       
   730 		case KSockBluetoothTypeRawBroadcast:
       
   731 		default:
       
   732 			{
       
   733 			__ASSERT_DEBUG((aSockType > KHCIMinimumHandle && aSockType < KHCIMaximumHandle)||(aSockType==KSockBluetoothTypeRawBroadcast), Panic(EBTProxySAPInvalidCreate));
       
   734 			// if the connection handle has been specified - find the connection: aSockType *is* a ConnectionHandle in this case
       
   735 			CPhysicalLink* phySAP = NULL;
       
   736 
       
   737 			if (aSockType!=KSockBluetoothTypeRawBroadcast)
       
   738 				{
       
   739 				// it's a proxy sap which we should try to bind to the PHY
       
   740 				// 
       
   741 				phySAP = iPhysicalLinksMgr->FindPhysicalLink(static_cast<THCIConnHandle>(aSockType));
       
   742 				}
       
   743 			// create Proxy telling it the possible PHY
       
   744 			CBTProxySAP* proxySAP = CBTProxySAP::NewLC(*iPhysicalLinksMgr, phySAP);
       
   745 			CleanupStack::Pop(proxySAP);
       
   746 			sap = proxySAP;
       
   747 			}
       
   748 		}
       
   749 	ASSERT_DEBUG(sap);
       
   750 	return sap;
       
   751 	}
       
   752 
       
   753 TBTDevHCIVersion CLinkMgrProtocol::GetHWHCIVersion() const
       
   754 	{
       
   755 	LOG_FUNC
       
   756 	return iHWHCIVersion;
       
   757 	}
       
   758 
       
   759 void CLinkMgrProtocol::SetLocalVersion(THCIErrorCode aErr, TBTDevHCIVersion aHCIVersion, TBTDevLMPVersion aLMPVersion)
       
   760 	{
       
   761 	LOG_FUNC
       
   762 	// we store this for possibly useful later use :-)
       
   763 	if (aErr == EOK)
       
   764 		{
       
   765 		iHWHCIVersion = aHCIVersion; // not especially useful for us: but maybe to exploit >BT1.1
       
   766 		iHWLMPVersion = aLMPVersion; // the LM in the HC ;-)
       
   767 		}
       
   768 	}
       
   769 
       
   770 void CLinkMgrProtocol::SetOverrideLPMTimeout(TUint aOverrideLPMTimeout)
       
   771 	{
       
   772 	LOG_FUNC
       
   773 	iOverrideLPMTimeout =aOverrideLPMTimeout;
       
   774 	}
       
   775 
       
   776 TInt CLinkMgrProtocol::StartProtocolListening()
       
   777 	{
       
   778 	LOG_FUNC
       
   779 	return KickDiscoverabilitySubscriber();
       
   780 	}
       
   781 
       
   782 // oh Dear! void again, how to report failure...
       
   783 void CLinkMgrProtocol::StopProtocolListening()
       
   784 	{
       
   785 	LOG_FUNC
       
   786 
       
   787 	// NB. If 'KickDiscoverabilitySubscriber' returns an error, then
       
   788 	// we've tried to get the value for ScanStatus, but we've failed.
       
   789 	// Not a lot we can do about it.  This means that we may be 
       
   790 	// leaving inquiry and page scan enabled with no listeners.
       
   791 	(void)KickDiscoverabilitySubscriber();
       
   792 	}
       
   793 
       
   794 TInt CLinkMgrProtocol::KickDiscoverabilitySubscriber()
       
   795 	{
       
   796 	/*
       
   797 	 Reset P&S with its current value. This will kick
       
   798 	 CDiscoverabilitySubscriber's RunL which calls 
       
   799 	 SetInquiryAndPageScanningL to check for the current 
       
   800 	 user wishes AND the existance of listeners before 
       
   801 	 sending the appropriate WriteScanEnable command to 
       
   802 	 the controller.
       
   803 	*/
       
   804 	LOG_FUNC
       
   805 
       
   806 	TInt scanVal;
       
   807 	TInt err = iProperty.Get(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothSetScanningStatus, scanVal);
       
   808 	
       
   809 	if (err != KErrNone)
       
   810 		{
       
   811 		return err;
       
   812 		}
       
   813 
       
   814 	THCIScanEnable scan = static_cast<THCIScanEnable>(scanVal);
       
   815 
       
   816 	// force CDiscoverabilitySubscriber to try to enable Page and Inquiry scan to HW, when set
       
   817 	(void)(iProperty.Set(KPropertyUidBluetoothCategory,
       
   818 						 KPropertyKeyBluetoothSetScanningStatus,
       
   819 						 scan));
       
   820 
       
   821 	return err;
       
   822 	}
       
   823 	
       
   824 void CLinkMgrProtocol::LocalSupportedFeaturesAvailable()
       
   825 	{
       
   826 	// Set options based on the features
       
   827 	iInquiryMgr->SetInquiryMode();
       
   828 	iEirManServer->NotifyFeaturesReady();
       
   829 	}
       
   830 	
       
   831 void CLinkMgrProtocol::SetLocalFeatures(THCIErrorCode aErr, const TBTFeatures& aMask)
       
   832 	{
       
   833 	LOG_FUNC
       
   834 	if (aErr == EOK)
       
   835 		{
       
   836 		// we store this for possibly useful later use :-)
       
   837 		iHWFeatures = aMask;
       
   838 		}
       
   839 	// else ignore for now...
       
   840 	iEirManServer->NotifyFeaturesReady();
       
   841 	}
       
   842 
       
   843 void CLinkMgrProtocol::SetLocalCommands(THCIErrorCode aErr, const TBluetoothHciCommands& aMask)
       
   844 	{
       
   845 	LOG_FUNC
       
   846 	if (aErr == EOK)
       
   847 		{
       
   848 		// we store this for possibly useful later use :-)
       
   849 		iHWCommands = aMask;
       
   850 		
       
   851 		}
       
   852 	// else ignore for now...
       
   853 	}
       
   854 
       
   855 void CLinkMgrProtocol::SetInquiryAndPageScanningL()
       
   856 	{
       
   857 	LOG_FUNC
       
   858 	
       
   859 	TInt requestedScanVal = 0; // no Inquiry or Page Scanning as default
       
   860 	
       
   861 	TInt err = iProperty.Get(KPropertyUidBluetoothCategory,
       
   862 						KPropertyKeyBluetoothSetScanningStatus,
       
   863 						requestedScanVal
       
   864 						);
       
   865 
       
   866 	THCIScanEnable requestedScanSetting;						
       
   867 	if (!err) 
       
   868 		{
       
   869 		requestedScanSetting = static_cast<THCIScanEnable>(requestedScanVal);
       
   870 		}
       
   871 	else
       
   872 		{
       
   873 		
       
   874 		// If err == KErrNotFound, we have not published this property yet, but in all error cases
       
   875 		// we will use the current device setting to define the scanning requirements instead.
       
   876 		requestedScanSetting = iLocalDeviceSettings.ScanEnable();
       
   877 		}
       
   878 
       
   879 	// we need to check to see if we have any listeners before we can enable page & inquiry scan
       
   880 	THCIScanEnable validScanSetting;
       
   881 	if(!IsListening() || (requestedScanSetting == EInquiryScanOnly))
       
   882 		{
       
   883 		validScanSetting = ENoScansEnabled;
       
   884 		}
       
   885 	else 
       
   886 		{
       
   887 		validScanSetting = requestedScanSetting;
       
   888 		}
       
   889 	
       
   890 	iPendingLocalDeviceSettings.SetScanEnable(validScanSetting);
       
   891 	
       
   892 	iHCIFacade->WriteScanEnableL(iPendingLocalDeviceSettings.ScanEnable());
       
   893 		
       
   894 	if (!err) 
       
   895 		{
       
   896 		// Update registry with the requested settings from the _set_ key
       
   897 		iLocalDeviceSettings.SetScanEnable(static_cast<THCIScanEnable>(requestedScanVal));			
       
   898 		UpdateSettings();
       
   899 		}		
       
   900 	}
       
   901 
       
   902 void CLinkMgrProtocol::SetAcceptPairedOnlyMode(TBool aOn)
       
   903 /*
       
   904 THIS WORKS DIFFERENTLY: It does not involve the controller - it is
       
   905 purely a stack setting. It is called directly when the user requests
       
   906 the stack value to be reset.
       
   907 */
       
   908 	{
       
   909 	LOG_FUNC
       
   910 	iLocalDeviceSettings.SetAcceptPairedOnlyMode(aOn);
       
   911 	
       
   912 	//update UI
       
   913 	(void)iProperty.Set(KPropertyUidBluetoothCategory,
       
   914 						KPropertyKeyBluetoothGetAcceptPairedOnlyMode,
       
   915 						iLocalDeviceSettings.AcceptPairedOnlyMode()
       
   916 						);
       
   917 
       
   918 	UpdateSettings();
       
   919 	}
       
   920 
       
   921 void CLinkMgrProtocol::SetSimplePairingDebugMode(TBool aOn)
       
   922 /*
       
   923 THIS WORKS DIFFERENTLY: It does not involve the controller - it is
       
   924 purely a stack setting.
       
   925 */
       
   926 	{
       
   927 	LOG_FUNC
       
   928 	//update UI
       
   929 	(void)iProperty.Set(KPropertyUidBluetoothCategory,
       
   930 						KPropertyKeyBluetoothGetSimplePairingDebugMode,
       
   931 						aOn
       
   932 						);
       
   933 	}
       
   934 
       
   935 void CLinkMgrProtocol::SetDeviceClassL(TUint32 aCoD)
       
   936 	{
       
   937 	LOG_FUNC
       
   938 	// This method is called from Subscribers when the P&S is used to write a new CoD
       
   939 	TInt err = KErrNone;
       
   940 	err = CodMan().PandSCodHandler(aCoD);	// Cod Service Manager will decide what gets written
       
   941 		 
       
   942 	User::LeaveIfError(err);	// P&S CoD failed to write, but at least Codman has a record of it
       
   943 	}
       
   944 
       
   945 void CLinkMgrProtocol::WriteClassOfDeviceL(TUint32 aCoD)
       
   946 	{
       
   947 	LOG_FUNC
       
   948 	// Only write the CoD bits if they have changed from the existing setting
       
   949 	if (iPendingLocalDeviceSettings.DeviceClass() != aCoD)
       
   950 		{
       
   951 		iPendingLocalDeviceSettings.SetDeviceClass(aCoD);
       
   952 		iHCIFacade->WriteDeviceClassL(aCoD);
       
   953 		}
       
   954 	}
       
   955 
       
   956 TInt CLinkMgrProtocol::SetLocalDeviceName(const TDesC8& aName)
       
   957 	{
       
   958 	LOG_FUNC
       
   959 	// We trap this HCI command and not the others in Set... to keep the 
       
   960 	// error path up to CBTHostResolver::SetHostName
       
   961 	TRAPD(err, iHCIFacade->WriteLocalNameL(aName));
       
   962 	if (err == KErrNone)
       
   963 		{
       
   964 		iPendingLocalDeviceSettings.SetDeviceName(aName);
       
   965 		}
       
   966 	return err;
       
   967 	}
       
   968 
       
   969 void CLinkMgrProtocol::SetAFHHostChannelClassificationL(const TBTAFHHostChannelClassification& aChannelClassification)
       
   970 	{
       
   971 	LOG_FUNC
       
   972 	iHCIFacade->SetAFHHostChannelClassificationL(aChannelClassification);
       
   973 	}
       
   974 	
       
   975 void CLinkMgrProtocol::SetAFHChannelAssessmentModeL(TBool aMode)
       
   976 	{
       
   977 	LOG_FUNC
       
   978 	iPendingLocalDeviceSettings.SetAFHChannelAssessmentMode(aMode);
       
   979 	iHCIFacade->WriteAFHChannelAssessmentModeL(aMode);
       
   980 	}
       
   981 
       
   982 void CLinkMgrProtocol::SetLimitedDiscoverableIfChangedL(TBool aOn)
       
   983 	{
       
   984 	LOG_FUNC
       
   985 	// Set limited discoverable if value differs from cached (= registry) value
       
   986 	// and previous change going the opposite way is not pending completion
       
   987 	// See also DoSetLimitedDiscoverableL
       
   988 	if ((aOn == iLocalDeviceSettings.LimitedDiscoverable()) &&
       
   989 		(iPendingLocalDeviceSettings.LimitedDiscoverable() == iLocalDeviceSettings.LimitedDiscoverable()))
       
   990 		return;
       
   991 
       
   992 	DoSetLimitedDiscoverableL(aOn);
       
   993 	}
       
   994 
       
   995 void CLinkMgrProtocol::DoSetLimitedDiscoverableL(TBool aOn)
       
   996 	{
       
   997 	LOG_FUNC
       
   998 	// HCI spec says we can always send >1 IAC! Controllers will take first
       
   999 	// so we can do what GAP says easily
       
  1000 
       
  1001 	TUint8 numIACs =0;
       
  1002 	TUint iacs[2];
       
  1003 
       
  1004 	if (aOn)
       
  1005 		{
       
  1006 		// turn on LIAC
       
  1007 		iPendingLocalDeviceSettings.SetLimitedDiscoverable(ETrue);
       
  1008 		WriteClassOfDeviceL(iPendingLocalDeviceSettings.DeviceClass() | (EMajorServiceLimitedDiscoverableMode << 
       
  1009 				(KLengthOfDeviceClass+KStartingOffsetOfDeviceClass))); 
       
  1010 		numIACs = 2;
       
  1011 		iacs[0] = KLIAC;
       
  1012 		iacs[1] = KGIAC;
       
  1013 		}
       
  1014 	else
       
  1015 		{
       
  1016 		// turn off LIAC - could do the 1 minute GAP timer?
       
  1017 		iPendingLocalDeviceSettings.SetLimitedDiscoverable(EFalse);
       
  1018 		WriteClassOfDeviceL(iPendingLocalDeviceSettings.DeviceClass() & ~(EMajorServiceLimitedDiscoverableMode << 
       
  1019 				(KLengthOfDeviceClass+KStartingOffsetOfDeviceClass))); 
       
  1020 		numIACs = 1;
       
  1021 		iacs[0] = KGIAC;
       
  1022 		}
       
  1023 	
       
  1024 	iHCIFacade->WriteIACLAPL(numIACs, iacs);
       
  1025 	}
       
  1026 
       
  1027 void CLinkMgrProtocol::UpdateLocalDevicePower(TBTPowerState aState)
       
  1028 	{
       
  1029 	LOG_FUNC
       
  1030 	iLocalDeviceSettings.SetPowerSetting(static_cast<TUint8>(aState));
       
  1031 	UpdateSettings();
       
  1032 	}
       
  1033 	
       
  1034 // This is an update method for dealing with the result of asking what the device
       
  1035 // name is. It is used to keep iLocalDeviceSettings.DeviceName(), the P&S device 
       
  1036 // name value and the h/w value in sync
       
  1037 void CLinkMgrProtocol::UpdateLocalDeviceName(const TDesC8& aName)
       
  1038    	{
       
  1039 	LOG_FUNC
       
  1040   	iLocalDeviceSettings.SetDeviceName(aName);
       
  1041 
       
  1042 	// Update the UI with the unicode DeviceName
       
  1043 	TBuf16<KHCILocalDeviceNameMaxLength> unicodeName;
       
  1044 	(void) CnvUtfConverter::ConvertToUnicodeFromUtf8(unicodeName, iLocalDeviceSettings.DeviceName());
       
  1045 	// The return from the above should never be > 0 since aName should have a length <= KHCILocalDeviceNameMaxLength
       
  1046 	// hence we shouldn't have any unconverted chars left over. If we get another error then we just have to publish  
       
  1047 	// the resulting unicode name anyway.
       
  1048 		
       
  1049 	(void)iProperty.Set(KPropertyUidBluetoothCategory,
       
  1050 				    	KPropertyKeyBluetoothGetDeviceName,
       
  1051 				    	unicodeName
       
  1052 						);
       
  1053   	UpdateSettings();					
       
  1054    	}
       
  1055    	
       
  1056 // This is an update method for dealing with the result of telling the h/w what the device
       
  1057 // name should be. It is used to keep iLocalDeviceSettings.DeviceName(), the P&S device 
       
  1058 // name value and the h/w value in sync
       
  1059 void CLinkMgrProtocol::UpdateLocalDeviceName(TBool aSucceeded)
       
  1060 	{
       
  1061 	LOG_FUNC
       
  1062 	if (aSucceeded)
       
  1063 		{
       
  1064 		TBool isDifferentName = 
       
  1065 				(iLocalDeviceSettings.DeviceName() != iPendingLocalDeviceSettings.DeviceName());
       
  1066 		iLocalDeviceSettings.SetDeviceName(iPendingLocalDeviceSettings.DeviceName());
       
  1067 		if(iLocalNamePublisher && isDifferentName)
       
  1068 			{
       
  1069 			iLocalNamePublisher->UpdateName(iLocalDeviceSettings.DeviceName());
       
  1070 			}
       
  1071 		}
       
  1072 		
       
  1073 	// Update the UI with the unicode DeviceName
       
  1074 	TBuf16<KHCILocalDeviceNameMaxLength> unicodeName;
       
  1075 	(void) CnvUtfConverter::ConvertToUnicodeFromUtf8(unicodeName, iLocalDeviceSettings.DeviceName());
       
  1076 	// The return from the above should never be > 0 since unicodeName is the same size as utf8Name 
       
  1077 	// hence we shouldn't have any unconverted chars left over. Similarly ret should not be < 0 
       
  1078 	// because when we received DeviceName in Unicode we where able to convert it to UTF-8
       
  1079 	// without a problem so reversing the conversion should be okay.
       
  1080 	
       
  1081 	(void)iProperty.Set(KPropertyUidBluetoothCategory,
       
  1082 				    	KPropertyKeyBluetoothGetDeviceName,
       
  1083 				    	unicodeName
       
  1084 						);
       
  1085 	UpdateSettings();
       
  1086 	}
       
  1087 
       
  1088 void CLinkMgrProtocol::UpdateLocalDeviceScanEnable(TBool aSucceeded)
       
  1089 	{
       
  1090 	LOG_FUNC
       
  1091 	TInt scan;
       
  1092 	TInt err = KErrNone;
       
  1093 	
       
  1094 	// Set scan to be the actual scan enable state of the hardware
       
  1095 	if(aSucceeded)
       
  1096 		{
       
  1097 		// We've set it to the value in iLocalDeviceSettings
       
  1098 		scan = iPendingLocalDeviceSettings.ScanEnable();
       
  1099 		}
       
  1100 	else
       
  1101 		{
       
  1102 		// We haven't changed it, current value is in the _get_ key
       
  1103 		err = iProperty.Get(KPropertyUidBluetoothCategory,
       
  1104 							KPropertyKeyBluetoothGetScanningStatus,
       
  1105 							scan);
       
  1106 		}
       
  1107 	
       
  1108 	if(!err)
       
  1109 		{	
       
  1110 		//update UI with the hardware's settings using the _get_ key
       
  1111 		(void)iProperty.Set(KPropertyUidBluetoothCategory,
       
  1112 							KPropertyKeyBluetoothGetScanningStatus,
       
  1113 							scan
       
  1114 							);	
       
  1115 		}					
       
  1116 	}
       
  1117 
       
  1118 void CLinkMgrProtocol::UpdateLimitedDiscoverable(TBool aSucceeded)
       
  1119 	{
       
  1120 	LOG_FUNC
       
  1121 	if (aSucceeded)
       
  1122 		{
       
  1123 		iLocalDeviceSettings.SetLimitedDiscoverable(
       
  1124 			iPendingLocalDeviceSettings.LimitedDiscoverable());
       
  1125 		}
       
  1126 	
       
  1127 	//update UI
       
  1128 	(void)iProperty.Set(KPropertyUidBluetoothCategory,
       
  1129 						KPropertyKeyBluetoothGetLimitedDiscoverableStatus,
       
  1130 						iLocalDeviceSettings.LimitedDiscoverable()
       
  1131 						);
       
  1132 
       
  1133 	UpdateSettings();
       
  1134 	}
       
  1135 
       
  1136 void CLinkMgrProtocol::UpdateDeviceClass(TBool aSucceeded)
       
  1137 	{
       
  1138 	LOG_FUNC
       
  1139 	if (aSucceeded)
       
  1140 		{
       
  1141 		iLocalDeviceSettings.SetDeviceClass(
       
  1142 			iPendingLocalDeviceSettings.DeviceClass());
       
  1143 		}
       
  1144 	
       
  1145 	//update UI
       
  1146 	(void)iProperty.Set(KPropertyUidBluetoothCategory,
       
  1147 						KPropertyKeyBluetoothGetDeviceClass,
       
  1148 						iLocalDeviceSettings.DeviceClass()
       
  1149 						);
       
  1150 
       
  1151 	UpdateSettings();
       
  1152 	}
       
  1153 	
       
  1154 void CLinkMgrProtocol::UpdateDeviceClass(TBool aSucceeded, TUint aCoD)
       
  1155 	{
       
  1156 	LOG_FUNC
       
  1157 	if (aSucceeded)
       
  1158 		{
       
  1159 		iLocalDeviceSettings.SetDeviceClass(aCoD);
       
  1160 		
       
  1161 		//update UI
       
  1162 		(void)iProperty.Set(KPropertyUidBluetoothCategory,
       
  1163 							KPropertyKeyBluetoothGetDeviceClass,
       
  1164 							aCoD
       
  1165 							);
       
  1166 							
       
  1167 		UpdateSettings();							
       
  1168 		}
       
  1169 	}
       
  1170 
       
  1171 void CLinkMgrProtocol::UpdateAFHChannelAssessmentMode(TBool aSucceeded)
       
  1172 	{
       
  1173 	LOG_FUNC
       
  1174 	if (aSucceeded)
       
  1175 		{
       
  1176 		iLocalDeviceSettings.SetAFHChannelAssessmentMode(
       
  1177 			iPendingLocalDeviceSettings.AFHChannelAssessmentMode());
       
  1178 		}
       
  1179 
       
  1180 	UpdateSettings();
       
  1181 	}
       
  1182 
       
  1183 void CLinkMgrProtocol::UpdateSettings()
       
  1184 	{
       
  1185 	LOG_FUNC
       
  1186 	//Careful! - we new'd it without ELeave
       
  1187 	if (iRegistryUpdater)
       
  1188 		{
       
  1189 		iRegistryUpdater->Update();
       
  1190 		}
       
  1191 	}
       
  1192 
       
  1193 void CLinkMgrProtocol::UpdateInquiryResponseTxPowerLevel(TInt8 aTxPowerLevel)
       
  1194 	{
       
  1195 	LOG_FUNC
       
  1196 	if(iTxPowerLevelPublisher)
       
  1197 		{
       
  1198 		iTxPowerLevelPublisher->UpdateTxPowerLevel(aTxPowerLevel);
       
  1199 		}
       
  1200 	}
       
  1201 
       
  1202 
       
  1203 void CLinkMgrProtocol::SetUIConnecting(TBool aConnecting)
       
  1204 	{
       
  1205 	LOG_FUNC
       
  1206 	(void)iProperty.Set(KPropertyUidBluetoothCategory,
       
  1207 						KPropertyKeyBluetoothGetConnectingStatus,
       
  1208 						aConnecting);
       
  1209 	}
       
  1210 
       
  1211 
       
  1212 void CLinkMgrProtocol::SetUINumPhysicalLinks(TUint aNum)
       
  1213 	{
       
  1214 	LOG_FUNC
       
  1215 	(void)iProperty.Set(KPropertyUidBluetoothCategory,
       
  1216 						KPropertyKeyBluetoothGetPHYCount,
       
  1217 						aNum);
       
  1218 	}
       
  1219 
       
  1220 
       
  1221 void CLinkMgrProtocol::SetLocalBTAddress(const TBTDevAddr& aAddr)
       
  1222 	{
       
  1223 	LOG_FUNC
       
  1224 	iLocalDeviceAddress = aAddr;
       
  1225 
       
  1226 	// publish this number - might be useful
       
  1227 	const TDesC8& des = aAddr.Des();
       
  1228 	(void)iProperty.Set(KPropertyUidBluetoothCategory,
       
  1229 						KPropertyKeyBluetoothGetLocalDeviceAddress,
       
  1230 						des);
       
  1231 	}
       
  1232 
       
  1233 void CLinkMgrProtocol::SetUIDiscovering(TInt aDiscoveringState)
       
  1234  	{
       
  1235 	LOG_FUNC
       
  1236  	(void)iProperty.Set(KPropertyUidBluetoothCategory,
       
  1237  						KPropertyKeyBluetoothHostResolverActive,
       
  1238  						aDiscoveringState);
       
  1239  	}
       
  1240  
       
  1241 TInt CLinkMgrProtocol::ACLPacketMTU() const
       
  1242 	{
       
  1243 	LOG_FUNC
       
  1244 	return iLinkMuxer->ACLPacketMTU();
       
  1245 	}
       
  1246 
       
  1247 TInt CLinkMgrProtocol::ControlPlaneMessage(TBTControlPlaneMessage aMessage, TAny* aParam)
       
  1248 	{
       
  1249 	LOG_FUNC
       
  1250 	TInt rerr = KErrNotFound;
       
  1251 	CPhysicalLink* con = NULL;
       
  1252 	
       
  1253 	if ((aMessage == ESubscribePhysicalLink) || (aMessage == EUnsubscribePhysicalLink)) 
       
  1254 		{
       
  1255 		TPhysicalLinkSubscriptionInfo& subscriptionInfo = *reinterpret_cast<TPhysicalLinkSubscriptionInfo*>(aParam);
       
  1256 		con = iPhysicalLinksMgr->FindPhysicalLink(subscriptionInfo.iAddr);
       
  1257 		}
       
  1258 	else if ((aMessage == ETryToAndThenPreventHostEncryptionKeyRefresh))
       
  1259 		{
       
  1260 		// For EPreventAutoEncryptionKeyRefresh we pass the address as a TBTDevAddr**
       
  1261 		const TBTDevAddr& addr = **reinterpret_cast<const TBTDevAddr**>(aParam);
       
  1262 		con = iPhysicalLinksMgr->FindPhysicalLink(addr);
       
  1263 		}
       
  1264 	else
       
  1265 		{
       
  1266 		const TBTDevAddr& addr = *reinterpret_cast<const TBTDevAddr*>(aParam);
       
  1267 		con = iPhysicalLinksMgr->FindPhysicalLink(addr);
       
  1268 		}
       
  1269 
       
  1270 	if (con)
       
  1271 		{
       
  1272 		switch (aMessage)
       
  1273 			{
       
  1274 			case EOverridePark:
       
  1275 				rerr = con->OverridePark();
       
  1276 				break;
       
  1277 			case EUndoOverridePark:
       
  1278 				rerr = con->UndoOverridePark();
       
  1279 				break;
       
  1280 			case EOverrideLPMWithTimeout:
       
  1281 				rerr = con->OverrideLPMWithTimeout(iOverrideLPMTimeout);
       
  1282 				break;
       
  1283 			case EOverrideLPM:
       
  1284 				rerr = con->OverrideLPM();
       
  1285 				break;
       
  1286 			case EUndoOverrideLPM:
       
  1287 				rerr = con->UndoOverrideLPM();
       
  1288 				break;
       
  1289 			case ESubscribePhysicalLink:
       
  1290 				{
       
  1291 				const TPhysicalLinkSubscriptionInfo& subscriptionInfo = *reinterpret_cast<TPhysicalLinkSubscriptionInfo*>(aParam);
       
  1292 				con->SubscribeLinkObserver(subscriptionInfo.iMPhysicalLinkObserver);
       
  1293 				break;
       
  1294 				}
       
  1295 			case EUnsubscribePhysicalLink:
       
  1296 				{
       
  1297 				const TPhysicalLinkSubscriptionInfo& subscriptionInfo = *reinterpret_cast<TPhysicalLinkSubscriptionInfo*>(aParam);				
       
  1298 				con->UnsubscribeLinkObserver(subscriptionInfo.iMPhysicalLinkObserver);
       
  1299 				break;
       
  1300 				}
       
  1301 			case ETryToAndThenPreventHostEncryptionKeyRefresh:
       
  1302 				{
       
  1303 				rerr = con->TryToAndThenPreventHostEncryptionKeyRefresh(aParam);
       
  1304 				break;
       
  1305 				}
       
  1306 			default:
       
  1307 				rerr = KErrNotSupported;
       
  1308 				break;
       
  1309 			};
       
  1310 		}
       
  1311 	return rerr;
       
  1312 	}
       
  1313 	
       
  1314 	
       
  1315 void CLinkMgrProtocol::ClearPendingLocalDeviceSettingsCod()
       
  1316 	{
       
  1317 	LOG_FUNC
       
  1318 	// If we know that the h/w has been reset, then we need to ensure that our persistent
       
  1319 	// value reflects this. That way we will force the CoD re-write to the hardware.
       
  1320 	iPendingLocalDeviceSettings.SetDeviceClass(KDeviceClassReset);
       
  1321 	}
       
  1322 
       
  1323 
       
  1324 
       
  1325 //
       
  1326 // CRegistrySession
       
  1327 //
       
  1328 
       
  1329 CRegistrySession* CRegistrySession::NewL(CLinkMgrProtocol& aLinkMgrProtocol)
       
  1330 	{
       
  1331 	LOG_STATIC_FUNC
       
  1332 	CRegistrySession* self = new(ELeave) CRegistrySession(aLinkMgrProtocol);
       
  1333 	CleanupStack::PushL(self);
       
  1334 	self->ConstructL();
       
  1335 	CleanupStack::Pop(self);
       
  1336 	return self;
       
  1337 	}
       
  1338 
       
  1339 void CRegistrySession::Open()
       
  1340 	{
       
  1341 	LOG_FUNC
       
  1342 	if(iAccessCount++ == 0)
       
  1343 		{
       
  1344 		iLinkMgrProtocol.LocalOpen();
       
  1345 		}
       
  1346 	}
       
  1347 
       
  1348 void CRegistrySession::Close()
       
  1349 	{
       
  1350 	LOG_FUNC
       
  1351 	__ASSERT_DEBUG(iAccessCount > 0, Panic(ERegistrySessionClosedTooManyTimes));
       
  1352 	if(--iAccessCount == 0)
       
  1353 		{
       
  1354 		iLinkMgrProtocol.LocalClose();
       
  1355 		}
       
  1356 	}
       
  1357 	
       
  1358 CRegistrySession::CRegistrySession(CLinkMgrProtocol& aLinkMgrProtocol)
       
  1359 	: CBase()
       
  1360 	, iAccessCount(0)
       
  1361 	, iLinkMgrProtocol(aLinkMgrProtocol)
       
  1362 	{
       
  1363 	LOG_FUNC
       
  1364 	}
       
  1365 
       
  1366 void CRegistrySession::ConstructL()
       
  1367 	{
       
  1368 	LOG_FUNC
       
  1369 	User::LeaveIfError(iRegServ.Connect());
       
  1370 	}
       
  1371 
       
  1372 CRegistrySession::~CRegistrySession()
       
  1373 	{
       
  1374 	LOG_FUNC
       
  1375 	__ASSERT_DEBUG(iAccessCount == 0, Panic(ERegistrySessionDeletedWhenOpen));
       
  1376 	iRegServ.Close();
       
  1377 	}
       
  1378 
       
  1379 RBTRegServ& CRegistrySession::RegServ()
       
  1380 	{
       
  1381 	LOG_FUNC
       
  1382 	return iRegServ;
       
  1383 	}
       
  1384 
       
  1385 
       
  1386 
       
  1387 //class CRegistryUpdater
       
  1388 CRegistryUpdater::~CRegistryUpdater()
       
  1389 	{
       
  1390 	LOG_FUNC
       
  1391 	Cancel();
       
  1392 	}
       
  1393 	
       
  1394 
       
  1395 CRegistryUpdater::CRegistryUpdater(RBTLocalDevice& aLocalDevice,TBTTrackedLocalDevice& aSettings) :
       
  1396 CActive(CActive::EPriorityStandard),iLocalDevice(aLocalDevice),iStackSettings(aSettings),iRepeatUpdate(EFalse)
       
  1397 	{
       
  1398 	LOG_FUNC
       
  1399 	CActiveScheduler::Add(this);
       
  1400 	}
       
  1401 
       
  1402 void CRegistryUpdater::Update()
       
  1403 	{
       
  1404 	LOG_FUNC
       
  1405 	__ASSERT_DEBUG(iLocalDevice.SubSessionHandle(), Panic(ELocalDeviceBadHandle));
       
  1406 	
       
  1407 	if (!IsActive())
       
  1408 		{
       
  1409 		TInt err;
       
  1410 		err = iLocalDevice.Get(iRegistrySettings); 
       
  1411 		
       
  1412 		// if we can't get settings from registry, we won't be able to update them
       
  1413 		if ( err == KErrNone )
       
  1414 			{
       
  1415 			iStackSettings.Modify(iRegistrySettings);
       
  1416 			iStackSettings.ResetChangesMask();
       
  1417 			iLocalDevice.Modify(iRegistrySettings,iStatus);
       
  1418 			SetActive();
       
  1419 			iRepeatUpdate = EFalse;	
       
  1420 			}
       
  1421 		}
       
  1422 	else
       
  1423 		{
       
  1424 		// Even if multiple requests come in while this object is active we only need to
       
  1425 		// perform one update since iLocalDevice will accumulated required new settings.
       
  1426 		LOG(_L(" -- CRegistryUpdaterAO already active so will repeat the update later."));
       
  1427 		iRepeatUpdate = ETrue;
       
  1428 		}
       
  1429 	}
       
  1430 
       
  1431 void CRegistryUpdater::RunL()
       
  1432 	{
       
  1433 	LOG_FUNC
       
  1434 	if (iRepeatUpdate)
       
  1435 		{
       
  1436 		Update();
       
  1437 		}		
       
  1438 	}
       
  1439 	
       
  1440 void CRegistryUpdater::DoCancel()
       
  1441 	{
       
  1442 	LOG_FUNC
       
  1443 	iLocalDevice.CancelRequest(iStatus);
       
  1444 	iRepeatUpdate = EFalse;	
       
  1445 	}
       
  1446 	
       
  1447 
       
  1448 //class TBTTrackedLocalDevice
       
  1449 void TBTTrackedLocalDevice::SetAddress(const TBTDevAddr& aAddr)
       
  1450 	{
       
  1451 	LOG_FUNC
       
  1452 	TBTLocalDevice::SetAddress(aAddr);
       
  1453 	StoreChange(EAddress);
       
  1454 	}
       
  1455 	
       
  1456 void TBTTrackedLocalDevice::SetDeviceClass(TUint32 aCod)
       
  1457 	{
       
  1458 	LOG_FUNC
       
  1459 	TBTLocalDevice::SetDeviceClass(aCod);
       
  1460 	StoreChange(ECoD);
       
  1461 	}
       
  1462 
       
  1463 void TBTTrackedLocalDevice::SetDeviceName(const TDesC8& aName)
       
  1464 	{
       
  1465 	LOG_FUNC
       
  1466 	TBTLocalDevice::SetDeviceName(aName);
       
  1467 	StoreChange(EDeviceName);
       
  1468 	}
       
  1469 
       
  1470 void TBTTrackedLocalDevice::SetScanEnable(THCIScanEnable aEnable)
       
  1471 	{
       
  1472 	LOG_FUNC
       
  1473 	TBTLocalDevice::SetScanEnable(aEnable);
       
  1474 	StoreChange(EScanEnable);
       
  1475 	}
       
  1476 
       
  1477 void TBTTrackedLocalDevice::SetLimitedDiscoverable(TBool aOn)
       
  1478 	{
       
  1479 	LOG_FUNC
       
  1480 	TBTLocalDevice::SetLimitedDiscoverable(aOn);
       
  1481 	StoreChange(ELimitedDiscoverable);
       
  1482 	}
       
  1483 
       
  1484 void TBTTrackedLocalDevice::SetPowerSetting(TUint8 aPowerSetting)
       
  1485 	{
       
  1486 	LOG_FUNC
       
  1487 	TBTLocalDevice::SetPowerSetting(aPowerSetting);
       
  1488 	StoreChange(EPowerSetting);
       
  1489 	}
       
  1490 
       
  1491 void TBTTrackedLocalDevice::SetAFHChannelAssessmentMode(TBool aOn)
       
  1492 	{
       
  1493 	LOG_FUNC
       
  1494 	TBTLocalDevice::SetAFHChannelAssessmentMode(aOn);
       
  1495 	StoreChange(EAFHChannelAssessmentMode);
       
  1496 	}
       
  1497 
       
  1498 void TBTTrackedLocalDevice::SetAcceptPairedOnlyMode(TBool aOn)
       
  1499 	{
       
  1500 	LOG_FUNC
       
  1501 	TBTLocalDevice::SetAcceptPairedOnlyMode(aOn);
       
  1502 	StoreChange(EAcceptPairedOnlyMode);
       
  1503 	}
       
  1504 
       
  1505 void TBTTrackedLocalDevice::StoreChange(TUint8 aChange)
       
  1506 	{
       
  1507 	LOG_FUNC
       
  1508 	iChangedSettings |= aChange;
       
  1509 	}
       
  1510 	
       
  1511 void TBTTrackedLocalDevice::ResetChangesMask()
       
  1512 	{
       
  1513 	LOG_FUNC
       
  1514 	iChangedSettings = 0;
       
  1515 	}
       
  1516 	
       
  1517 void TBTTrackedLocalDevice::Modify(TBTLocalDevice& aLocalDeviceSettings)
       
  1518 	{
       
  1519 	LOG_FUNC
       
  1520 	if ( iChangedSettings & EAddress )
       
  1521 		{
       
  1522 		aLocalDeviceSettings.SetAddress(Address());
       
  1523 		}
       
  1524 
       
  1525 	if ( iChangedSettings & ECoD )
       
  1526 		{
       
  1527 		aLocalDeviceSettings.SetDeviceClass(DeviceClass());
       
  1528 		}
       
  1529 
       
  1530 	if ( iChangedSettings & EDeviceName )
       
  1531 		{
       
  1532 		aLocalDeviceSettings.SetDeviceName(DeviceName());
       
  1533 		}
       
  1534 
       
  1535 	if ( iChangedSettings & EPowerSetting )
       
  1536 		{
       
  1537 		aLocalDeviceSettings.SetPowerSetting(PowerSetting());
       
  1538 		}
       
  1539 
       
  1540 	if ( iChangedSettings & EScanEnable )
       
  1541 		{
       
  1542 		aLocalDeviceSettings.SetScanEnable(ScanEnable());
       
  1543 		}
       
  1544 
       
  1545 	if ( iChangedSettings & ELimitedDiscoverable )
       
  1546 		{
       
  1547 		aLocalDeviceSettings.SetLimitedDiscoverable(LimitedDiscoverable());
       
  1548 		}
       
  1549 
       
  1550 	if ( iChangedSettings & EAFHChannelAssessmentMode )
       
  1551 		{
       
  1552 		aLocalDeviceSettings.SetAFHChannelAssessmentMode(AFHChannelAssessmentMode());
       
  1553 		}
       
  1554 
       
  1555 	if ( iChangedSettings & EAcceptPairedOnlyMode )
       
  1556 		{
       
  1557 		aLocalDeviceSettings.SetAcceptPairedOnlyMode(AcceptPairedOnlyMode());
       
  1558 		}
       
  1559 	}
       
  1560