bluetoothcommsprofiles/btpan/panagt/panagt.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2004-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 //
       
    15 
       
    16 #include <bluetooth/logger.h>
       
    17 #include <bt_sock.h>
       
    18 #include <comms-infras/nifif.h> // should be removed once KCOGetAgentEMIPtr is defined in nifagt.h
       
    19 #include <elements/nm_interfaces.h>
       
    20 #include "panagtlog.h"
       
    21 #include "panagt.h"
       
    22 #include "panagtremdev.h"
       
    23 #include "panagtstates.h"
       
    24 #include "panlocalsdphelper.h"
       
    25 #include <comms-infras/nifagt_internal.h>
       
    26 #include <panctrl.h>
       
    27 #include <btextnotifierspartner.h>
       
    28 
       
    29 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
    30 #include "panprovisioninfo.h" 
       
    31 #include "panmessages.h"
       
    32 
       
    33 #ifdef ESOCK_EXTLOG_ACTIVE
       
    34 _LIT8(KPanAgtSubTag, "panagt");
       
    35 #endif
       
    36 
       
    37 #endif
       
    38 // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
    39 
       
    40 #ifdef __FLOG_ACTIVE
       
    41 _LIT8(KLogComponent, LOG_COMPONENT_PAN_AGENT);
       
    42 #endif
       
    43 
       
    44 using namespace PanAgent;
       
    45 using namespace Messages;
       
    46 
       
    47 extern "C" EXPORT_C CNifAgentFactory* NewAgentFactoryL()
       
    48 /**
       
    49 Pan agent factory
       
    50 */
       
    51 	{	
       
    52 	return new(ELeave) CPanAgentFactory();
       
    53 	}
       
    54 	
       
    55 //
       
    56 // PAN agent factory
       
    57 //
       
    58 
       
    59 void CPanAgentFactory::InstallL() 
       
    60 /**
       
    61  * Perform any agent factory initialisation
       
    62  */
       
    63 	{
       
    64 	LOG_FUNC
       
    65 	}
       
    66  
       
    67 CNifAgentBase* CPanAgentFactory::NewAgentL(const TDesC& /*aName*/)
       
    68 /**
       
    69  * Create a new PAN agent
       
    70  */
       
    71 	{
       
    72 	LOG_FUNC
       
    73 	return CPanAgent::NewL();
       
    74 	}
       
    75 
       
    76 TInt CPanAgentFactory::Info(TNifAgentInfo& aInfo, TInt /*aIndex*/) const
       
    77 /**
       
    78  * Retrieve information about this agent
       
    79  * @param aInfo 
       
    80  * @param aIndex
       
    81  */
       
    82 	{
       
    83 	LOG_FUNC
       
    84 	aInfo.iName = KPanAgentName;
       
    85 	aInfo.iVersion = TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber);
       
    86 	return KErrNone;
       
    87 	}
       
    88 
       
    89 //
       
    90 // PAN agent
       
    91 //
       
    92 
       
    93 CPanAgent* CPanAgent::NewL()
       
    94 /**
       
    95 Return a newly constuct PAN agent
       
    96 */
       
    97 	{
       
    98 	LOG_STATIC_FUNC
       
    99 	CPanAgent* self = new(ELeave) CPanAgent();
       
   100 	CleanupStack::PushL(self);
       
   101 	self->ConstructL();
       
   102 	CleanupStack::Pop(self);
       
   103 	return(self);
       
   104 	}
       
   105 
       
   106 CPanAgent::CPanAgent()
       
   107 /**
       
   108 Do nothing
       
   109 */
       
   110 	{
       
   111 	CONNECT_LOGGER
       
   112 	LOG_FUNC
       
   113 
       
   114 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   115     NM_LOG_NODE_CREATE(KPanAgtSubTag, CPanAgent);
       
   116 #endif
       
   117 	}
       
   118 
       
   119 void CPanAgent::ConstructL()
       
   120 /**
       
   121 
       
   122 */
       
   123 	{
       
   124 	LOG_FUNC
       
   125 	CAgentBase::ConstructL();
       
   126 	
       
   127 	iDeviceSelector = new (ELeave) CPanRemoteDeviceSelector(*this, *iDatabase);
       
   128 	
       
   129 	iInitiateDisconnectCallback = new (ELeave) CAsyncCallBack(KPanAgtAoPriority);
       
   130 
       
   131 	TCallBack initiateDisconnectCallback(InitiateDisconnectCb, this);
       
   132 	iInitiateDisconnectCallback->Set(initiateDisconnectCallback);
       
   133 
       
   134 	// Create local SDP helper instance.
       
   135 	iPanLocalSdpRegistrar = CPanHelperLocalSdpRegistrar::NewL();
       
   136 
       
   137 	iState = CPanAgtStateUninitialised::NewL(*this);
       
   138 	iShutdownState = CPanAgtStateShutdown::NewL(*this);
       
   139 
       
   140 	//If CPanCoexistenceConnectionController::NewL leaves, PAN still can be started as usual
       
   141 	TRAP_IGNORE(iPanCoexistenceConnectionController = CPanCoexistenceConnectionController::NewL(*this));
       
   142 	__ASSERT_DEBUG(iPanCoexistenceConnectionController, PanAgentPanic(ECreatePanCoexistenceConnectionControllerFailed));
       
   143 
       
   144 
       
   145 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   146 	// Register with comms transport to be able to receive our
       
   147 	// custom PAN/BNEP messages
       
   148 	TPanMessage::RegisterL();
       
   149 #endif
       
   150 	}
       
   151 
       
   152 CPanAgent::~CPanAgent()
       
   153 /**
       
   154 Tidy up after ourselves
       
   155 */
       
   156 	{
       
   157 	LOG_FUNC
       
   158 
       
   159 	__ASSERT_DEBUG(Devices().Count()==0, PanAgentPanic(EPanAgentDeletedWithDevicesStillAttached));
       
   160 	
       
   161 	delete iPanLocalSdpRegistrar;
       
   162 	
       
   163 	iRemoteDevices.ResetAndDestroy();
       
   164 	
       
   165 	if (iShutdownState != iState)
       
   166 		{	
       
   167 		// something strange happened here, shutdown state not the last used state
       
   168 		__ASSERT_DEBUG(EFalse, PanAgentPanic(EShutdownStateNotLastState));
       
   169 		
       
   170 		delete iShutdownState;
       
   171 		iShutdownState = NULL;
       
   172 		}
       
   173 		
       
   174 	delete iState;
       
   175 	iState = NULL;
       
   176 	
       
   177 	if(iDeviceSelector)
       
   178 		{
       
   179 		iDeviceSelector->Cancel();
       
   180 		delete iDeviceSelector;
       
   181 		iDeviceSelector = NULL;
       
   182 		}
       
   183 	
       
   184 	if(iPanCoexistenceConnectionController)
       
   185 		{
       
   186 		delete iPanCoexistenceConnectionController;
       
   187 		iPanCoexistenceConnectionController = NULL;
       
   188 		}
       
   189 	
       
   190 	if(iIncomingConnectionListener)	// if we haven't deleted it already...
       
   191 		{
       
   192 		// make sure we stopped it
       
   193 		__ASSERT_DEBUG(!(iIncomingConnectionListener->IsActive()), PanAgentPanic(EIncomingConnectionListenerStillActiveAtShutdown));
       
   194 		iIncomingConnectionListener->Cancel();	// recover in release builds
       
   195 		delete iIncomingConnectionListener;
       
   196 		iIncomingConnectionListener = NULL;	
       
   197 		}
       
   198 	
       
   199 	iInitiateDisconnectCallback->Cancel();
       
   200 	delete iInitiateDisconnectCallback;
       
   201 	iInitiateDisconnectCallback = NULL;
       
   202 	
       
   203 	delete iDeviceSelector;
       
   204 	iDeviceSelector = NULL;
       
   205 	
       
   206 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   207 	// De-register with the comms transport
       
   208 	TPanMessage::DeRegister();
       
   209     NM_LOG_NODE_DESTROY(KPanAgtSubTag, CPanAgent);
       
   210 #endif
       
   211 	CLOSE_LOGGER
       
   212 	}
       
   213 
       
   214 void CPanAgent::Connect(TAgentConnectType aType)
       
   215 /**
       
   216 Start the connection in an appropriate mode, depending on the settings in commdb
       
   217 */
       
   218 	{
       
   219 	LOG_FUNC
       
   220 	LOG1(_L("CPanAgent::Connect(TAgentConnectType[%d])"), aType);
       
   221 
       
   222 	//The IAP must be incoming if we get a reconnect
       
   223 	if(aType==EAgentStartDialIn || aType==EAgentReconnect)
       
   224 		{
       
   225 		SetSuppressOutgoing();
       
   226 		}
       
   227 		
       
   228 	iError = KErrNone; // make sure iError is reset before entering ConnectComplete
       
   229 	iState->Connect();
       
   230 	}
       
   231 
       
   232 void CPanAgent::Connect(TAgentConnectType aType, CStoreableOverrideSettings* aOverrideSettings)
       
   233 /**
       
   234 Pass the override settings to base class, and perform a normal start
       
   235 */
       
   236 	{
       
   237 	LOG_FUNC
       
   238 	LOG1(_L("CPanAgent::Connect(TAgentConnectType[%d] + CStoreableOverrideSettings)"), aType);
       
   239 
       
   240 	TRAPD(err, SetOverridesL(aOverrideSettings));
       
   241 	if(err) // if we can't store the overrides, then tell nifman and abort the connect
       
   242 		{
       
   243 		iError = err;
       
   244 		iState->Connect();
       
   245 		return;
       
   246 		}
       
   247 	Connect(aType);
       
   248 	}
       
   249 
       
   250 void CPanAgent::CancelConnect()
       
   251 /**
       
   252 Cancel the ServiceStarted callback - this will prevent the agent starting
       
   253 */
       
   254 	{
       
   255 	LOG_FUNC
       
   256 	iState->CancelConnect();
       
   257 	}
       
   258 	
       
   259 void CPanAgent::ServiceStarted()
       
   260 /**
       
   261 @note We can't handle any error conditions here, as nifman doesn't allow us to signal them until
       
   262 we call ConnectComplete
       
   263 */
       
   264 	{
       
   265 	LOG_FUNC
       
   266 	__ASSERT_ALWAYS(iNotify, PanAgentPanic(ENullNifmanNotifyPointer));
       
   267 	LOG1(_L("CPanAgent: Service started with error %d"), iError);
       
   268 	iNotify->ServiceStarted(); // trigger loading of nif and packet driver
       
   269 	}
       
   270 
       
   271 void CPanAgent::ConnectComplete()
       
   272 /**
       
   273 Get the BNEP control interface handle, and create the initial state
       
   274 */
       
   275 	{
       
   276 	LOG_FUNC
       
   277 	__ASSERT_ALWAYS(iNotify, PanAgentPanic(ENullNifmanNotifyPointer));
       
   278 	LOG1(_L("CPanAgent: entered ConnectComplete with error %d"), iError);
       
   279 
       
   280 	if(!iError) // if everything's OK, then get the handle to the BNEP control interface
       
   281 		{
       
   282 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   283         CPanProvisionInfo* provisionInfo=NULL; 
       
   284 		iError = iNotify->Notification((TAgentToNifEventType)EPanAgentToNifGetPanProvisionInfo, static_cast<TAny*>(&provisionInfo));
       
   285 		
       
   286 		// If this assert fails check your commdb. It probably means that a non-399 commdb
       
   287 		// has been imported and is using the basic Ethernet MCPR rather than the Pan
       
   288 		// Ethernet MCPR
       
   289     	__ASSERT_ALWAYS(provisionInfo && provisionInfo->BnepConnectionMgr() != Messages::TNodeId::NullId(), PanAgentPanic(ENullBnepConnectionManager));
       
   290     	iBnepConnectionManager = provisionInfo->BnepConnectionMgr();
       
   291 		
       
   292 #else
       
   293 // !SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   294 
       
   295 		// Get the handle to the nif's connection manager
       
   296 		LOG(_L("CPanAgent: Getting handle to BNEP control interface..."));
       
   297 		TBnepConnectionManager bnepConnectionManager;
       
   298 		iError = iNotify->Notification((TAgentToNifEventType)EPanAgentToNifGetConnectionManager, static_cast<TAny*>(&bnepConnectionManager));
       
   299 		if(iError == KErrNone)
       
   300 			{
       
   301 			iBnepConnectionManager = bnepConnectionManager.iBnepConnectionManager;
       
   302 			__ASSERT_ALWAYS(iBnepConnectionManager, PanAgentPanic(ENullBnepConnectionManager));
       
   303 			}
       
   304 #endif
       
   305 // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   306 		}
       
   307 
       
   308 	if (iError == KErrNone)
       
   309 		{
       
   310 		LOG(_L("CPanAgent: ...got handle successfully"));
       
   311 		delete iState;
       
   312 		iState = NULL;
       
   313 		CPanAgtStateBase* initialState = NULL;
       
   314 		TRAP(iError, initialState = CPanAgentStateInitialising::NewL(*this));
       
   315 		if(!iError)
       
   316 			{
       
   317 			SetState(*initialState); // this may set iError if there is a problem during initialising		
       
   318 			}
       
   319 		}
       
   320 
       
   321 	if(iError)
       
   322 		{
       
   323 		iNotify->AgentProgress(EPanAgtIdle, iError);
       
   324 		}
       
   325 	else
       
   326 		{
       
   327 		iNifmanConnected = ETrue;
       
   328 		iNotify->AgentProgress(EPanAgtConnected, KErrNone);
       
   329 		}
       
   330 
       
   331 	LOG1(_L("CPanAgent: calling nifman ConnectComplete with error %d)"), iError);
       
   332 	iNotify->ConnectComplete(iError);
       
   333 	}
       
   334 
       
   335 void CPanAgent::Reconnect()
       
   336 /**
       
   337 Reset state and asynchronously send reconnect complete back, if 
       
   338 the IAP is incoming
       
   339 */
       
   340 	{
       
   341 	LOG_FUNC
       
   342 	if(AllowIncoming())
       
   343 		{
       
   344 		delete iState;
       
   345 		iState = NULL;
       
   346 		CPanAgtStateBase* reconState = NULL;
       
   347 		TRAP(iError, reconState= CPanAgtStateReconnect::NewL(*this));
       
   348 		if(!iError)
       
   349 			{
       
   350 			SetState(*reconState);
       
   351 			}
       
   352 		}
       
   353 	}
       
   354 
       
   355 void CPanAgent::ReconnectComplete(TInt aErr)
       
   356 	{
       
   357 	LOG_FUNC
       
   358 	iNotify->ReconnectComplete(aErr);
       
   359 	}
       
   360 
       
   361 void CPanAgent::CancelReconnect()
       
   362 /**
       
   363 
       
   364 */
       
   365 	{
       
   366 	LOG_FUNC
       
   367 	iState->CancelReconnect();
       
   368 	}
       
   369 	
       
   370 void CPanAgent::InitiateDisconnect()
       
   371 /**
       
   372 Perform an agent initiated disconnect
       
   373 @note Any code in the agent that wants to trigger a disconnect should call RequestDisconnect(),
       
   374 which will call this method via an async callback.
       
   375 @note This call will loop back into the agent because nifman will call the Disconnect() method itself.
       
   376 */
       
   377 	{
       
   378 	LOG_FUNC
       
   379 	__ASSERT_DEBUG(iNifmanConnected, PanAgentPanic(EAttemptToDisconnectBeforeConnectComplete));
       
   380 	LOG1(_L("CPanAgent: InitiateDisconnect with error %d"), iError);
       
   381 	
       
   382 	iNotify->AgentProgress(EPanAgtDisconnecting, iError);
       
   383 	iNotify->AgentEvent(EAgentOriginatedConnectionCommand, EAgentConnectionCommandStop, TPckg<TInt>(KErrDisconnected));
       
   384 	}
       
   385 	
       
   386 void CPanAgent::Disconnect(TInt aReason)
       
   387 /**
       
   388 Disconnect called from nifman (this can be triggered by the idle timers, the client, or us 
       
   389 requesting a disconnect using RequestDisconnect()).
       
   390 This method will cause us to go to the shutdown state in the role state machine, which will
       
   391 shut everything else down (ie. the remote device state machines).
       
   392 @note This is the one case where a state transition can occur that is not triggered by a state
       
   393 itself (because two of the three reasons for this method being called are events external to 
       
   394 PAN agent, and those events turn up here first, and are not passed to a state; instead they 
       
   395 trigger the state transition directly)
       
   396 */
       
   397 	{
       
   398 	LOG_FUNC
       
   399 	LOG1(_L("CPanAgent: Disconnect with error %d"), aReason);
       
   400 
       
   401 	iError = aReason;
       
   402 	
       
   403 	// now make shutdown the active state
       
   404 	delete iState; // we have to do this now, otherwise we lose the pointer
       
   405 	iState = NULL; // to prevent any mistakes being made...
       
   406 	SetState(*iShutdownState); // shutdown is complete when ShutdownComplete() is called by the shutdown state	
       
   407 	}
       
   408 	
       
   409 void CPanAgent::FullShutdownComplete()
       
   410 /**
       
   411 Once all devices have reported to the shutdown state that they are disconnected, this method
       
   412 is called and the agent can disconnect
       
   413 */
       
   414 	{
       
   415 	LOG_FUNC
       
   416 	LOG(_L("CPanAgent: Shutdown complete, signalling nifman with DisconnectComplete()"));
       
   417 
       
   418 	// then tell nifman we've disconnected
       
   419 	iNotify->AgentProgress(EPanAgtDisconnected, KErrNone);
       
   420 	iNifmanConnected = EFalse;
       
   421 	iNotify->DisconnectComplete();
       
   422 	}
       
   423 		
       
   424 TInt CPanAgent::InitiateDisconnectCb(TAny* aThisPtr)
       
   425 /**
       
   426 Initiate disconnect callback static method
       
   427 */
       
   428 	{
       
   429 	LOG_STATIC_FUNC
       
   430 	__ASSERT_DEBUG(aThisPtr, PanAgentPanic(ENullTAnyPointer));
       
   431 
       
   432 	CPanAgent* self = static_cast<CPanAgent*>(aThisPtr);
       
   433 	self->InitiateDisconnect();
       
   434 	return KErrNone;
       
   435 	}
       
   436 	
       
   437 void CPanAgent::Info(TNifAgentInfo& aInfo) const
       
   438 /**
       
   439  * Information about this Agent
       
   440  *
       
   441  * @param aInfo on return contains information about the agent
       
   442  */
       
   443 	{
       
   444 	LOG_FUNC
       
   445 	aInfo.iName = KPanAgentName;
       
   446 	aInfo.iName.AppendFormat(_L("-AgentFactory[0x%08x]"), this);
       
   447 	aInfo.iVersion = TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
       
   448 	}
       
   449 
       
   450 TInt CPanAgent::Control(TUint aOptionLevel, TUint aOptionName, TDes8& aOption)
       
   451 /**
       
   452 Various agent specific options
       
   453 */
       
   454 	{
       
   455 	LOG_FUNC
       
   456 	if(aOptionLevel==KCOLAgent)
       
   457 		{
       
   458 		TBool listUplinkAccessDev = EFalse;
       
   459 		
       
   460 		switch(aOptionName)
       
   461 			{
       
   462 			case KCOGetAgentEMIPtr:	// agent extended management interface getter
       
   463 				{
       
   464 				if(aOption.Length()!=sizeof(MNifAgentExtendedManagementInterface*))
       
   465 					{
       
   466 					return KErrArgument;
       
   467 					}
       
   468 				aOption = TPckg<MNifAgentExtendedManagementInterface*>(this);
       
   469 				return KErrNone;
       
   470 				}
       
   471 				
       
   472 			case KCOAgentNotifyClientAttach:
       
   473 				{
       
   474 				TRAPD(err, SetupOutgoingConnectionsL()); //<@note This ignores the value of the iSuppressOutgoing flag and triggers the outgoing connections directly
       
   475 														 // as the outgoing connection suppression is only intended to be used when the agent is first told to Connect()
       
   476 														 // and not when the 2nd and subsequent clients attach to this connection
       
   477 				return err;
       
   478 				}
       
   479 				
       
   480 			case KCOAgentPanConnectDevice:
       
   481 				{
       
   482 				if(aOption.Length() != KBTDevAddrSize)
       
   483 					{
       
   484 					return KErrArgument;
       
   485 					}
       
   486 				
       
   487 				TBTDevAddr remoteDeviceAddress(aOption);
       
   488 				TRAPD(err, CreateNewConnectionForOutgoingL(remoteDeviceAddress));
       
   489 				return err;
       
   490 				}
       
   491 				
       
   492 			case KCOAgentPanDisconnectDevice:
       
   493 				{
       
   494 				if(aOption.Length() != KBTDevAddrSize)
       
   495 					{
       
   496 					return KErrArgument;
       
   497 					}
       
   498 				
       
   499 				TBTDevAddr remoteDeviceAddress(aOption);
       
   500 				CPanRemoteDeviceStateMachine* remoteDevice = FindRemoteDeviceByAddress(remoteDeviceAddress);
       
   501 				if(remoteDevice)
       
   502 					{
       
   503 					remoteDevice->Disconnect();
       
   504 					}
       
   505 				else
       
   506 					{
       
   507 					return KErrNotFound;
       
   508 					}
       
   509 					
       
   510 				return KErrNone;
       
   511 				}
       
   512 				
       
   513 			case KCOAgentPanEnumerateUplinkAccessDevices: 
       
   514 				{
       
   515 				//set the listing uplink access devices boolean to ETrue
       
   516 				listUplinkAccessDev = ETrue;
       
   517 				//the following code will branch based on the value of listUplinkAccessDev
       
   518 				//fall through
       
   519 				}
       
   520 				
       
   521 			case KCOAgentPanEnumerateDevices:
       
   522 				{
       
   523 				// Because the array passed to us here may be smaller than the number of active links
       
   524 				// at this point, we shall return as much as possible in the array.
       
   525 
       
   526 				// Also if the array has enough space for more addresses than we currently have, the
       
   527 				// descriptor size will be changed to reflect reality.
       
   528 
       
   529 				aOption.Zero();
       
   530 
       
   531 				TInt maxDevices = Min ( iRemoteDevices.Count(),
       
   532 										aOption.MaxLength() / sizeof(TBTDevAddr));
       
   533 				
       
   534 				TInt currentDevice = 0;
       
   535 				TInt devicesStored = 0; // We only enumerate fully connected devices, so we need a separate counter
       
   536 								
       
   537 				while ((currentDevice < iRemoteDevices.Count()) && (devicesStored < maxDevices))
       
   538 					{
       
   539 					TRemoteDeviceState state = iRemoteDevices[currentDevice]->GetState();
       
   540 					
       
   541 					if(!listUplinkAccessDev && state != EIdle && state != EDisconnecting || 
       
   542 						iRemoteDevices[currentDevice]->UplinkAccessAllowed())
       
   543 						{
       
   544 						TBTDevAddr devAddr = iRemoteDevices[currentDevice]->DevAddr();
       
   545 						TPckg<TBTDevAddr> pckg(devAddr);
       
   546 						aOption.Append(pckg);
       
   547 						devicesStored++;
       
   548 						}
       
   549 					
       
   550 					currentDevice++;
       
   551 					}
       
   552 				
       
   553 				return KErrNone;
       
   554 				}
       
   555 							
       
   556 			default:
       
   557 				{
       
   558 				return KErrNotSupported;
       
   559 				}
       
   560 			}
       
   561 		}
       
   562 	return KErrNotSupported;
       
   563 	}
       
   564 
       
   565 TInt CPanAgent::Notification(TNifToAgentEventType /*aEvent*/, TAny* /*aInfo*/)
       
   566 /**
       
   567 
       
   568 */
       
   569 	{
       
   570 	LOG_FUNC
       
   571 	return KErrNotSupported;
       
   572 	}
       
   573 
       
   574 TInt CPanAgent::GetExcessData(TDes8& /*aDes*/)
       
   575 /**
       
   576 Unused in PAN profile
       
   577 */
       
   578 	{
       
   579 	LOG_FUNC
       
   580 	return KErrNotSupported;
       
   581 	}
       
   582 
       
   583 TInt CPanAgent::IncomingConnectionReceived()
       
   584 /**
       
   585 Don't need to support this - it's for an older nif/agent model where incoming and outgoing connections can't be supported at the same time.  This isn't the case in PAN profile.
       
   586 */
       
   587 	{
       
   588 	LOG_FUNC
       
   589 	return KErrNotSupported;
       
   590 	}
       
   591 
       
   592 void CPanAgent::GetLastError(TInt& aError)
       
   593 	{
       
   594 	LOG_FUNC
       
   595 	aError = KErrNotSupported; 
       
   596 	}
       
   597 
       
   598 TBool CPanAgent::IsReconnect() const
       
   599 	{
       
   600 	LOG_FUNC
       
   601 	//Return false for now because it hasn't been used. We will only expose this information from 
       
   602 	//statemachine when there is a good reason.
       
   603 	__DEBUGGER();
       
   604 	return EFalse; 	
       
   605 	}
       
   606 
       
   607 void CPanAgent::MpccoPanCoexistenceConnectionUpdated(TIPBearerCoexistenceStatus aStatus)
       
   608 	{
       
   609 	LOG_FUNC
       
   610 	
       
   611 	switch (aStatus)
       
   612 		{
       
   613 		case ENoneIsActive:
       
   614 			{
       
   615 			// We will not register the sdp and open listen socket in shutdown state
       
   616 			// Also check that we are not already listening
       
   617 			if (iShutdownState != iState && !IsIncomingConnectionListenerEnabled())
       
   618 				{
       
   619 				TRAPD(err, iState->StartListenerL());
       
   620 				if(err)
       
   621 					{
       
   622 					LOG1(_L("CPanAgent: MpccoPanCoexistenceConnectionUpdated open listener left with %d, shutting down all connections"), err);
       
   623 					// If open listener failed, request to disconnect
       
   624 					RequestDisconnect(err);
       
   625 					}
       
   626 				}
       
   627 			}
       
   628 			break;
       
   629 
       
   630 		case ERndisIsActive:
       
   631 			// Close listener and unregister SDP record since RNDIS is active
       
   632 			iState->StopListener();
       
   633 			break;
       
   634 
       
   635 		case EBTPanIsActive:
       
   636 			// It maybe some funny things happened here
       
   637 			__ASSERT_DEBUG(EFalse, PanAgentPanic(EIPBearerCoexistancePropertyShouldnotBePanIsActive));
       
   638 			break;
       
   639 
       
   640 		default:
       
   641 			__ASSERT_DEBUG(EFalse, PanAgentPanic(EInvalidIPBearerCoexistanceProperty));
       
   642 			break;
       
   643 		}
       
   644 	}
       
   645 //
       
   646 // PAN agent accessor methods
       
   647 //
       
   648 
       
   649 RPointerArray<CPanRemoteDeviceStateMachine>& CPanAgent::Devices()
       
   650 /**
       
   651 Return a handle to the connection array
       
   652 @return A reference to the device array held by the state machine
       
   653 */
       
   654 	{
       
   655 	LOG_FUNC
       
   656 	return(iRemoteDevices);
       
   657 	}
       
   658 
       
   659 const RPointerArray<CPanRemoteDeviceStateMachine>& CPanAgent::Devices() const
       
   660 /**
       
   661 Return a const handle to the connection array
       
   662 @return A const reference to the device array held by the state machine
       
   663 */
       
   664 	{
       
   665 	LOG_FUNC
       
   666 	return(iRemoteDevices);
       
   667 	}
       
   668 	
       
   669 TBluetoothPanRole& CPanAgent::FixedLocalRole()
       
   670 /**
       
   671 Return a handle to the fixed local role field
       
   672 @return A reference to the fixed local role field in the state machine
       
   673 */
       
   674 	{
       
   675 	LOG_FUNC
       
   676 	return(iFixedLocalRole);
       
   677 	}
       
   678 
       
   679 TBluetoothPanRole& CPanAgent::FixedRemoteRole()
       
   680 /**
       
   681 Return a handle to the fixed remote role field
       
   682 @return A reference to the fixed remote role field in the state machine
       
   683 */
       
   684 	{
       
   685 	LOG_FUNC
       
   686 	return(iFixedRemoteRole);
       
   687 	}
       
   688 		
       
   689 CCommsDbAccess& CPanAgent::Database()
       
   690 /**
       
   691 Return a handle to commdb
       
   692 @return A handle to commdb, with overrides masking the appropriate fields
       
   693 */
       
   694 	{
       
   695 	LOG_FUNC
       
   696 	__ASSERT_ALWAYS(iDatabase, PanAgentPanic(ENullCommdbHandle));
       
   697 	
       
   698 	return(*iDatabase);
       
   699 	}
       
   700 
       
   701 CPanHelperLocalSdpRegistrar& CPanAgent::PanLocalSdpRegistrar()
       
   702 /**
       
   703 
       
   704 */
       
   705 	{
       
   706 	LOG_FUNC
       
   707 	return *iPanLocalSdpRegistrar;
       
   708 	}
       
   709 	
       
   710 TInt CPanAgent::IapId()
       
   711 /**
       
   712 Return the IAP ID of this connection
       
   713 */
       
   714 	{
       
   715 	LOG_FUNC
       
   716 	TUint32 iapId = 0;	// initialise to zero to keep VC6 compiler happy...
       
   717 	TRAPD(err, Database().GetIntL(TPtrC(IAP), TPtrC(COMMDB_ID), iapId));
       
   718 	if(err)
       
   719 		{
       
   720 		LOG1(_L("CPanAgent: could not retrieve IAP ID, error %d"), err);
       
   721 		return err;
       
   722 		}
       
   723 	else
       
   724 		{
       
   725 		return iapId;
       
   726 		}
       
   727 	}
       
   728 
       
   729 TBool CPanAgent::SuppressOutgoing() const
       
   730 /**
       
   731 Find out if outgoing connections are suppressed
       
   732 */
       
   733 	{
       
   734 	LOG_FUNC
       
   735 	return(iSuppressOutgoing);
       
   736 	}
       
   737 	
       
   738 
       
   739 //
       
   740 // PAN agent do-er methods
       
   741 //
       
   742 
       
   743 void CPanAgent::SetSuppressOutgoing()
       
   744 /**
       
   745 Suppress outgoing connections
       
   746 */
       
   747 	{
       
   748 	LOG_FUNC
       
   749 	iSuppressOutgoing = ETrue;
       
   750 	}
       
   751 
       
   752 void CPanAgent::ResetSuppressOutgoing()
       
   753 /**
       
   754 Stop outgoing connections being suppressed
       
   755 */
       
   756 	{
       
   757 	LOG_FUNC
       
   758 	iSuppressOutgoing = EFalse;
       
   759 	}
       
   760 
       
   761 void CPanAgent::SendProgress(TInt aProgress, TInt aError)
       
   762 /**
       
   763 Send progress values to nifman
       
   764 NOTE nifman will ditch duplicate notifications, same progress, same error
       
   765 We can't change this so to avoid this for connection and disconnection progress notifications
       
   766 we will send a role notification after the connect/disconnect
       
   767 */
       
   768 	{
       
   769 	LOG_FUNC
       
   770 	__ASSERT_ALWAYS(iNotify, PanAgentPanic(ENullNifmanNotifyPointer));
       
   771 
       
   772 	LOG2(_L("CPanAgent: sending progress value to connection; stage %d, error %d"), aProgress, aError);
       
   773 	iNotify->AgentProgress(aProgress, aError);
       
   774 
       
   775 	switch (aProgress)
       
   776 	{
       
   777 	case EPanAgtInitialising:
       
   778 		{
       
   779 		LOG(_L("CPanAgent: Progress value EPanAgtInitialising"));
       
   780 		break;
       
   781 		}
       
   782 	case EPanAgtConnected:
       
   783 		{
       
   784 		LOG(_L("CPanAgent: Progress value EPanAgtConnected"));
       
   785 		break;
       
   786 		}
       
   787 	case EPanAgtIdle:
       
   788 		{
       
   789 		LOG(_L("CPanAgent: Progress value EPanAgtIdle"));
       
   790 		break;
       
   791 		}
       
   792 	case EPanAgtListening:
       
   793 		{
       
   794 		LOG(_L("CPanAgent: Progress value EPanAgtListening"));
       
   795 		break;
       
   796 		}
       
   797 	case EPanAgtURole:
       
   798 		{
       
   799 		// DANGER Don't EVER put StateSendRoleNotification in here - endless loop
       
   800 		LOG(_L("CPanAgent: Progress value EPanAgtURole"));
       
   801 		break;
       
   802 		}
       
   803 	case EPanAgtGnRole:
       
   804 		{
       
   805 		// DANGER Don't EVER put StateSendRoleNotification in here - endless loop
       
   806 		LOG(_L("CPanAgent: Progress value EPanAgtGnRole"));
       
   807 		break;
       
   808 		}
       
   809 	case EPanAgtNapRole:
       
   810 		{
       
   811 		// DANGER Don't EVER put StateSendRoleNotification in here - endless loop
       
   812 		LOG(_L("CPanAgent: Progress value EPanAgtNapRole"));
       
   813 		break;
       
   814 		}
       
   815 	case EPanAgtConnectedNewDevice:
       
   816 		{
       
   817 		LOG(_L("CPanAgent: Progress value EPanAgtConnectedNewDevice"));
       
   818 		// Get the state to send a role notification if its in a sensible state
       
   819 		// This has 2 beneficial effects.
       
   820 		// a) We send the role to the layers above so they know
       
   821 		// b) We never have the situation where we are sending 2 connects or 2 disconnects
       
   822 		//	   one after the other, this stops comms filtering the notification out
       
   823 		iState->StateSendRoleNotification();
       
   824 		
       
   825 		break;
       
   826 		}
       
   827 	case EPanAgtDisconnectedDevice:
       
   828 		{
       
   829 		LOG(_L("CPanAgent: Progress value EPanAgtDisconnectedDevice"));
       
   830 		// Get the state to send a role notification if its in a sensible state
       
   831 		// This has 2 beneficial effects.
       
   832 		// a) We send the role to the layers above so they know
       
   833 		// b) We never have the situation where we are sending 2 connects or 2 disconnects
       
   834 		//	   one after the other, this stops comms filtering the notification out
       
   835 		iState->StateSendRoleNotification();
       
   836 		
       
   837 		break;
       
   838 		}
       
   839 	case EPanAgtReconfiguringPiconet:
       
   840 		{
       
   841 		LOG(_L("CPanAgent: Progress value EPanAgtReconfiguringPiconet"));
       
   842 		break;
       
   843 		}
       
   844 	case EPanAgtUplinkRequired:
       
   845 		{
       
   846 		LOG(_L("CPanAgent: Progress value EPanAgtUplinkRequired"));
       
   847 		break;
       
   848 		}
       
   849 	case EPanAgtUplinkNotRequired:
       
   850 		{
       
   851 		LOG(_L("CPanAgent: Progress value EPanAgtUplinkNotRequired"));
       
   852 		break;
       
   853 		}
       
   854 	case EPanAgtDisconnecting:
       
   855 		{
       
   856 		LOG(_L("CPanAgent: Progress value EPanAgtDisconnecting"));
       
   857 		break;
       
   858 		}
       
   859 	case EPanAgtDisconnected:
       
   860 		{
       
   861 		LOG(_L("CPanAgent: Progress value EPanAgtDisconnected"));
       
   862 		break;
       
   863 		}
       
   864 	case EPanAgtNoResourceForPanConnection:
       
   865 		{
       
   866 		LOG(_L("CPanAgent: Progress value EPanAgtNoResourceForPanConnection"));
       
   867 		// We are lack of the network resource to setup the PAN connection, mainly caused by the RNDIS which
       
   868 		// is already occupied the IP resource
       
   869 		break;
       
   870 		}
       
   871 	default:
       
   872 		{
       
   873 		LOG(_L("CPanAgent: Progress value UNKNOWN"));
       
   874 		break;
       
   875 		}			
       
   876 	}
       
   877 
       
   878 	LOG(_L("CPanAgent: <<Progress SENT"));
       
   879 	}
       
   880 	
       
   881 
       
   882 TInt CPanAgent::StartIncomingConnectionListener()
       
   883 /**
       
   884 Start the incoming connection listener
       
   885 @return KErrNone if successful; otherwise one of the Symbian standard error codes
       
   886 */
       
   887 	{
       
   888 	LOG_FUNC
       
   889 	TInt rerr = KErrNone;
       
   890 	if(!iIncomingConnectionListener)
       
   891 		{
       
   892 		TRAP(rerr, iIncomingConnectionListener = CPanIncomingConnectionListener::NewL(*this));
       
   893 		}
       
   894 	return rerr;
       
   895 	}
       
   896 	
       
   897 void CPanAgent::CloseIncomingConnectionListener()
       
   898 /**
       
   899 Stop and delete the incoming connection listener
       
   900 */
       
   901 	{
       
   902 	LOG_FUNC
       
   903 	if(!iIncomingConnectionListener)	// if the incoming connection listener isn't active, then return immediately
       
   904 		{
       
   905 		return;
       
   906 		}
       
   907 		
       
   908 	iIncomingConnectionListener->Cancel();	// cancel outstanding accept
       
   909 	delete iIncomingConnectionListener;
       
   910 	iIncomingConnectionListener = NULL;
       
   911 	}
       
   912 	
       
   913 void CPanAgent::SetupOutgoingConnectionsL()
       
   914 /**
       
   915 Begin the process of setting up any outgoing connections that we need
       
   916 */
       
   917 	{
       
   918 	LOG_FUNC
       
   919 	__ASSERT_ALWAYS(iDeviceSelector, PanAgentPanic(ENullDeviceSelector));
       
   920 	
       
   921 	LOG(_L("Agent: Asked to bring new device(s) into the PAN"));
       
   922 	if (iRemoteDevices.Count())
       
   923 		{
       
   924 		TBluetoothPanRole remoteRole = iRemoteDevices[0]->RemoteRole();
       
   925 		if (remoteRole == EPanRoleNap)
       
   926 			{
       
   927 			LOG(_L("Agent: Already connected to a NAP, aborting."));
       
   928 			return;
       
   929 			}
       
   930 		}
       
   931 
       
   932 	// start the process of connecting any remote devices
       
   933 	iDeviceSelector->PerformRemoteDeviceSelectionL();
       
   934 	}
       
   935 		
       
   936 //
       
   937 // PAN agent getter methods
       
   938 //
       
   939 
       
   940 TBool CPanAgent::IsIncomingConnectionListenerEnabled() const
       
   941 /**
       
   942 Is the incoming connection listener active?
       
   943 @return Whether the listener is active or not
       
   944 */
       
   945 	{
       
   946 	LOG_FUNC
       
   947 	return (iIncomingConnectionListener ? ETrue : EFalse);
       
   948 	}
       
   949 
       
   950 TBool CPanAgent::IsPromptingUserForDeviceSelection() const
       
   951 /**
       
   952 Is the user being shown the device selection notifier?
       
   953 */
       
   954 	{
       
   955 	LOG_FUNC
       
   956 	return (iDeviceSelector ? iDeviceSelector->IsPrompting() : EFalse);
       
   957 	}
       
   958 
       
   959 TBool CPanAgent::IsUAllowedByFixedLocalRole() const
       
   960 /**
       
   961 Is U role allowed by settings in commdb?
       
   962 */
       
   963 	{
       
   964 	LOG_FUNC
       
   965 	return ((iFixedLocalRole==EPanRoleUnknown) || (iFixedLocalRole==EPanRoleU));
       
   966 	}
       
   967 	
       
   968 TBool CPanAgent::IsGnAllowedByFixedLocalRole() const
       
   969 /**
       
   970 Is GN role allowed by settings in commdb?
       
   971 */
       
   972 	{
       
   973 	LOG_FUNC
       
   974 	return ((iFixedLocalRole==EPanRoleUnknown) || (iFixedLocalRole==EPanRoleGn));
       
   975 	}
       
   976 	
       
   977 TBool CPanAgent::IsNapAllowedByFixedLocalRole() const
       
   978 /**
       
   979 Is NAP role allowed by settings in commdb?
       
   980 @note For now, because we don't support NAP, we're just going to return false here
       
   981 */
       
   982 	{
       
   983 	LOG_FUNC
       
   984 	return EFalse;
       
   985 	}
       
   986 
       
   987 //
       
   988 // PAN agent setter methods	
       
   989 //
       
   990 
       
   991 void CPanAgent::SetState(CPanAgtStateBase& aState)
       
   992 /**
       
   993 Set the current state in the state machine
       
   994 */
       
   995 	{
       
   996 	LOG_FUNC
       
   997 	iState = &aState;
       
   998 	TRAPD(err, iState->OnEntryL());
       
   999 	if(err)
       
  1000 		{
       
  1001 		LOG1(_L("CPanAgent: OnEntry to a state left with %d, shutting down all connections"), err);
       
  1002 		RequestDisconnect(err);
       
  1003 		}
       
  1004 	}
       
  1005 
       
  1006 //
       
  1007 // Connection creator methods
       
  1008 //
       
  1009 
       
  1010 void CPanAgent::CreateNewConnectionFromIncomingL(RInternalSocket& aConnectedSocket)
       
  1011 /**
       
  1012 Create a new connection from an incoming socket
       
  1013 @note All the role negotiation for this new connection is handled by the PAN remote connection class
       
  1014 @param aConnectedSocket A connected L2CAP socket, ready for hand off to BNEP
       
  1015 @return KErrNone if successful; otherwise one of the Symbian standard error codes
       
  1016 */
       
  1017 	{
       
  1018 	LOG_FUNC
       
  1019 	__ASSERT_ALWAYS(iDatabase, PanAgentPanic(ENullCommdbHandle));
       
  1020 	
       
  1021 	TBTSockAddr sockAddr;
       
  1022 	aConnectedSocket.RemoteName(sockAddr);
       
  1023 	CheckDeviceIsNotAlreadyAttachedL(sockAddr.BTAddr());
       
  1024 	CPanRemoteDeviceStateMachine* newRemDev = CPanRemoteDeviceStateMachine::NewL(aConnectedSocket, *this, *iDatabase);
       
  1025 	CleanupStack::PushL(newRemDev);
       
  1026 	User::LeaveIfError(iRemoteDevices.Append(newRemDev));
       
  1027 	CleanupStack::Pop(newRemDev);
       
  1028 	}
       
  1029 	
       
  1030 void CPanAgent::CreateNewConnectionForOutgoingL(const TBTDevAddr& aRemDevAddr)
       
  1031 /**
       
  1032 Create a new connection to a remote device
       
  1033 @note Can be called from outgoing connection creator, or from Control() call
       
  1034 @param aRemDevAddr The address of the remote device to connect to
       
  1035 */
       
  1036 	{	
       
  1037 	LOG_FUNC
       
  1038 
       
  1039 	// Check that a new PAN connection can be established at this time.
       
  1040 	TInt err = TryToCreateNewPanConnection(); 
       
  1041 	
       
  1042 	if (err != KErrNone)
       
  1043 		{
       
  1044         LOG1(_L("CPanAgent::CreateNewConnectionForOutgoingL - TryToCreateNewPanConnection returns %d"), err);
       
  1045 		
       
  1046 		// No resource is available and send a progress notification
       
  1047 		SendProgress(EPanAgtNoResourceForPanConnection, err);
       
  1048 		User::Leave(err);
       
  1049 		}
       
  1050 	
       
  1051 	CheckDeviceIsNotAlreadyAttachedL(aRemDevAddr);
       
  1052 	CPanRemoteDeviceStateMachine* newRemDev = CPanRemoteDeviceStateMachine::NewL(aRemDevAddr, *this, *iDatabase);	
       
  1053 	CleanupStack::PushL(newRemDev);
       
  1054 	User::LeaveIfError(iRemoteDevices.Append(newRemDev));
       
  1055 	CleanupStack::Pop(newRemDev);
       
  1056 	}
       
  1057 
       
  1058 TInt CPanAgent::DeviceSelectionError(TInt aErr)
       
  1059 /**
       
  1060 There has been an error during remote device selection
       
  1061 @note This might break if the first device from set of devices causes an error, but the rest
       
  1062 would start correctly if given a chance. However, it's unlikely - any error affecting one device
       
  1063 is likely to affect them all
       
  1064 */
       
  1065 	{
       
  1066 	LOG_FUNC
       
  1067 	LOG1(_L("CPanAgent: outgoing connection starter signalled error %d..."), aErr);	
       
  1068 	// should this be passed on to the state?
       
  1069 	// Maybe, it depends on how complicated we want to make the logic - currently states
       
  1070 	// have very limited knowledge of the connection starter (only in the state base class) - 
       
  1071 	// perhaps we should keep it that way?
       
  1072 	if(iRemoteDevices.Count())	// there are other devices in the array, so carry on
       
  1073 		{
       
  1074 		LOG(_L("CPanAgent: ...devices in array, ignoring error"));
       
  1075 		return KErrNone;	
       
  1076 		}
       
  1077 	else					// no other devices in the array, so check we're not listening, then shutdown
       
  1078 		{
       
  1079 		if(IsIncomingConnectionListenerEnabled())	// do nothing
       
  1080 			{
       
  1081 			LOG(_L("CPanAgent: ...no devices in array, but incoming connection listener active, ignoring error"));
       
  1082 			return KErrNone;
       
  1083 			}
       
  1084 		else
       
  1085 			{
       
  1086 			LOG(_L("CPanAgent: ...no devices in array and no incoming connection listener active, shutting down"));
       
  1087 			RequestDisconnect(aErr);
       
  1088 			return KErrDisconnected;
       
  1089 			}
       
  1090 		}
       
  1091 	}
       
  1092 
       
  1093 //
       
  1094 // Methods handled by each state
       
  1095 //
       
  1096 
       
  1097 
       
  1098 TInt CPanAgent::InitiateOutgoingConnection(TBluetoothPanRole& aLocalRole, TBluetoothPanRole& aRemoteRole, TPanDeviceWorthTryingRolesList& aWorthTryingRemoteRoles)
       
  1099 	{
       
  1100 	LOG_FUNC
       
  1101 	__ASSERT_ALWAYS(iState, PanAgentPanic(ENoState));
       
  1102 
       
  1103 	TRAPD(err, iState->InitiateOutgoingConnectionL(aLocalRole, aRemoteRole, aWorthTryingRemoteRoles));
       
  1104 	return err;
       
  1105 	}
       
  1106 	
       
  1107 TInt CPanAgent::PerformLocalRoleChangeRequest(TBluetoothPanRole& aLocalRole, TBluetoothPanRole& aRemoteRole)
       
  1108 	{
       
  1109 	LOG_FUNC
       
  1110 	__ASSERT_ALWAYS(iState, PanAgentPanic(ENoState));
       
  1111 
       
  1112 	TRAPD(err, iState->PerformLocalRoleChangeRequestL(aLocalRole, aRemoteRole));
       
  1113 	return err;
       
  1114 	}
       
  1115 
       
  1116 TInt CPanAgent::RoleChangeRequestFromPeer(TBluetoothPanRole aLocalRole, TBluetoothPanRole aRemoteRole)
       
  1117 	{
       
  1118 	LOG_FUNC
       
  1119 	__ASSERT_ALWAYS(iState, PanAgentPanic(ENoState));
       
  1120 	
       
  1121 	TInt ret = iState->IsRoleRequestValid(aLocalRole, aRemoteRole);
       
  1122 	if(ret == KErrNone)
       
  1123 		{
       
  1124 		// Check that the local service requested is currently supported.
       
  1125 		if((iNapEnabled && aLocalRole == EPanRoleGn) ||
       
  1126 		   (!iNapEnabled && aLocalRole == EPanRoleNap) )
       
  1127 			{
       
  1128 			ret = KErrInvalidOrUnacceptableRoleCombination;
       
  1129 			}
       
  1130 		// Check that the request is permitted by the fixed roles
       
  1131 		else if((FixedLocalRole() != EPanRoleUnknown &&
       
  1132 		         FixedLocalRole() != aLocalRole) ||
       
  1133 		        (FixedRemoteRole() != EPanRoleUnknown &&
       
  1134 		         FixedRemoteRole() != aRemoteRole))
       
  1135 			{
       
  1136 			ret = KErrInvalidOrUnacceptableRoleCombination;
       
  1137 			}
       
  1138 		else
       
  1139 			{
       
  1140 			// Check that the connection can co-exist with current connections and that the
       
  1141 			// state machine can accept the conection at this time.
       
  1142 			TRAP(ret, iState->RoleChangeRequestFromPeerL(aLocalRole));
       
  1143 			}
       
  1144 		}
       
  1145 	return ret;					
       
  1146 	}
       
  1147 
       
  1148 TInt CPanAgent::IncomingConnectionFromPeer(TBluetoothPanRole aLocalRole, TBluetoothPanRole aRemoteRole)
       
  1149 	{
       
  1150 	LOG_FUNC
       
  1151 	__ASSERT_ALWAYS(iState, PanAgentPanic(ENoState));
       
  1152 	
       
  1153 	// Check that a new PAN connection can be established at this time.
       
  1154 	TInt ret = TryToCreateNewPanConnection(); 
       
  1155 	
       
  1156 	if (ret != KErrNone)
       
  1157 		{
       
  1158 		LOG1(_L("CPanAgent::IncomingConnectionFromPeer - TryToCreateNewPanConnection returns %d"), ret);
       
  1159 		
       
  1160 		// No resource is available and send a progress notification
       
  1161 		SendProgress(EPanAgtNoResourceForPanConnection, ret);
       
  1162 		}
       
  1163 	else
       
  1164 		{
       
  1165 		ret = iState->IsRoleRequestValid(aLocalRole, aRemoteRole);
       
  1166 		
       
  1167 		if(ret == KErrNone)
       
  1168 			{
       
  1169 			// Check that the local service requested is currently supported.
       
  1170 			if((iNapEnabled && aLocalRole == EPanRoleGn) ||
       
  1171 			   (!iNapEnabled && aLocalRole == EPanRoleNap) )
       
  1172 				{
       
  1173 				ret = KErrInvalidOrUnacceptableRoleCombination;
       
  1174 				}
       
  1175 			// Check that the request is permitted by the fixed roles
       
  1176 			else if((FixedLocalRole() != EPanRoleUnknown &&
       
  1177 			         FixedLocalRole() != aLocalRole) ||
       
  1178 			        (FixedRemoteRole() != EPanRoleUnknown &&
       
  1179 			         FixedRemoteRole() != aLocalRole))
       
  1180 				{
       
  1181 				ret = KErrInvalidOrUnacceptableRoleCombination;
       
  1182 				}
       
  1183 			else
       
  1184 				{
       
  1185 				// Check that the connection can co-exist with current connections and that the
       
  1186 				// state machine can accept the conection at this time.
       
  1187 				TRAP(ret, iState->IncomingConnectionFromPeerL(aLocalRole));
       
  1188 				}
       
  1189 			}
       
  1190 		}
       
  1191 	return ret;					
       
  1192 	}
       
  1193 	
       
  1194 void CPanAgent::DeviceActive(CPanRemoteDeviceStateMachine& aNewConnection)
       
  1195 /**
       
  1196 Indicates that the given device has transitioned to the active state
       
  1197 */
       
  1198 	{
       
  1199 	LOG_FUNC
       
  1200 	__ASSERT_ALWAYS(iState, PanAgentPanic(ENoState));
       
  1201 
       
  1202 	TRAPD(err, iState->DeviceActiveL(aNewConnection));	
       
  1203 	if(err)
       
  1204 		{
       
  1205 		LOG1(_L("CPanAgent: DeviceActive left with %d"), err);
       
  1206 		RequestDisconnect(err);
       
  1207 		}
       
  1208 	else
       
  1209 		{
       
  1210 		// If this is a new device that has become active send a progress notification.
       
  1211 		if(!aNewConnection.NewConnectedDeviceProgressSent())
       
  1212 			{
       
  1213 			SendProgress(EPanAgtConnectedNewDevice, KErrNone);
       
  1214 			aNewConnection.SetNewConnectedDeviceProgressSent(ETrue);
       
  1215 			}
       
  1216 			
       
  1217 		// Check to see if an uplink access progress notification needs to be sent
       
  1218 		SendUplinkAccessRequiredProgressNotification();
       
  1219 		}
       
  1220 	iDeviceSelector->Reset();
       
  1221 	}
       
  1222 
       
  1223 void CPanAgent::DeviceRoleChangeFailed(CPanRemoteDeviceStateMachine& aDevice)
       
  1224 /**
       
  1225 Indicates that the given device failed to change role
       
  1226 @pre The device has been in the active state and is now renegotiating roles
       
  1227 */
       
  1228 	{
       
  1229 	LOG_FUNC
       
  1230 	__ASSERT_ALWAYS(iState, PanAgentPanic(ENoState));
       
  1231 
       
  1232 	TRAPD(err, iState->DeviceRoleChangeFailedL(aDevice));	
       
  1233 	if(err)
       
  1234 		{
       
  1235 		LOG1(_L("CPanAgent: DeviceRoleChangeFailed left with %d"), err);
       
  1236 		RequestDisconnect(err);
       
  1237 		}	
       
  1238 	}
       
  1239 
       
  1240 void CPanAgent::DeviceDisconnected(CPanRemoteDeviceStateMachine& aDevice)
       
  1241 /**
       
  1242 Indicates that the remote device has disconnected, and should be deleted from the device array
       
  1243 */
       
  1244 	{
       
  1245 	LOG_FUNC
       
  1246 	__ASSERT_ALWAYS(iState, PanAgentPanic(ENoState));
       
  1247 
       
  1248 #ifdef __FLOG_ACTIVE
       
  1249 	TBuf<KMaxBtAddrSize> devaddr;
       
  1250 	aDevice.DevAddr().GetReadable(devaddr, KNullDesC, KBtAddrSeparator, KNullDesC);
       
  1251 	LOG1(_L("Remote device %S disconnected"), &devaddr);
       
  1252 #endif
       
  1253 		
       
  1254 	if(aDevice.NewConnectedDeviceProgressSent())
       
  1255 		{
       
  1256 		SendProgress(EPanAgtDisconnectedDevice, KErrNone);
       
  1257 		aDevice.SetNewConnectedDeviceProgressSent(EFalse);
       
  1258 		}
       
  1259 
       
  1260 	// Check if any remaining active devices require the uplink.
       
  1261 	SendUplinkAccessRequiredProgressNotification();
       
  1262 
       
  1263 	TRAPD(err, iState->DeviceDisconnectedL(aDevice));	// if this leaves, then shutdown everything
       
  1264 	
       
  1265 	//check if there are more devices we want to connect to
       
  1266 	TInt errNewConnection = KErrNone;
       
  1267 	while (iDeviceSelector->HasMoreDevices())
       
  1268 		{
       
  1269 		LOG(_L("More devices available, trying to establish connection"));
       
  1270 		TRAP(errNewConnection, iDeviceSelector->CreateNextConnectionL());
       
  1271 		if (errNewConnection == KErrNone ) 
       
  1272 			{
       
  1273 			LOG(_L("Created new connection to next available device"));
       
  1274 			return;
       
  1275 			}
       
  1276 		else
       
  1277 			{
       
  1278 			LOG1(_L("Failed to create new connection, error=%d"), errNewConnection);
       
  1279 			}
       
  1280 		}
       
  1281 	
       
  1282 	if( err != KErrNone || errNewConnection != KErrNone )
       
  1283 		{
       
  1284 		LOG(_L("...no more active devices, shutting down"));
       
  1285 		RequestDisconnect(err);
       
  1286 		}
       
  1287 	}
       
  1288 	
       
  1289 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
  1290 /**
       
  1291 Return pointer to the main BNEP connection manager class
       
  1292 */
       
  1293 const Messages::TNodeId& CPanAgent::BnepConnectionManager()
       
  1294 	{
       
  1295 	LOG_FUNC
       
  1296 	return iBnepConnectionManager;
       
  1297 	}
       
  1298 
       
  1299 /**
       
  1300 Restarts the incoming connection listener when it has been waiting
       
  1301 for a response from BNEP
       
  1302 */
       
  1303 void CPanAgent::RestartIncomingConnectionListener(TInt aError)
       
  1304     {
       
  1305 	LOG_FUNC
       
  1306     iIncomingConnectionListener->RestartIncomingConnectionListener(aError);
       
  1307     }
       
  1308 
       
  1309 void CPanAgent::SetRetryConnect(CPanRemoteDeviceStateMachine& /*aDevice*/) 
       
  1310 	{
       
  1311 	LOG_FUNC
       
  1312     CPanAgtStateBase* nextState = NULL;
       
  1313     TInt err = KErrNone;
       
  1314 	TRAP(err, nextState = CPanAgtStateIdle::NewL(*this));
       
  1315 	if(err != KErrNone) 
       
  1316 		{
       
  1317 		if(iShutdownState)
       
  1318 			{
       
  1319 			SetState(*iShutdownState);
       
  1320 			}
       
  1321 		return;
       
  1322 		}
       
  1323 	
       
  1324 	CPanAgtStatePaused* pausedState = NULL;
       
  1325 	TRAP(err,
       
  1326 	    CleanupStack::PushL(nextState);
       
  1327 	    pausedState = CPanAgtStatePaused::NewL(*this, *nextState);
       
  1328 	    CleanupStack::Pop();
       
  1329 	    );
       
  1330 
       
  1331     if (err != KErrNone)
       
  1332         {
       
  1333 		if(iShutdownState)
       
  1334 			{
       
  1335 			SetState(*iShutdownState);
       
  1336 			}
       
  1337 		return;
       
  1338         }
       
  1339 
       
  1340 	delete iState;
       
  1341 	SetState(*pausedState);
       
  1342 
       
  1343     // Only if all the above worked do we send the message to BNEP
       
  1344 	TPanMessage::TSetRetryConnect msg;
       
  1345     RClientInterface::OpenPostMessageClose(Id(),BnepConnectionManager(),msg);
       
  1346 	}
       
  1347 	
       
  1348 #else
       
  1349 // !SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
  1350 
       
  1351 /**
       
  1352 Return pointer to the main BNEP connection manager class
       
  1353 */
       
  1354 MBnepConnectionManager& CPanAgent::BnepConnectionManager()
       
  1355 	{
       
  1356 	LOG_FUNC
       
  1357 	__ASSERT_ALWAYS(iBnepConnectionManager, PanAgentPanic(ENullBnepConnectionManager));
       
  1358 	
       
  1359 	return(*iBnepConnectionManager);
       
  1360 	}
       
  1361 
       
  1362 void CPanAgent::SetRetryConnect(CPanRemoteDeviceStateMachine& /*aDevice*/) 
       
  1363 	{
       
  1364 	LOG_FUNC
       
  1365 	iBnepConnectionManager->SetRetryConnect();
       
  1366 	
       
  1367 	CPanAgtStateBase* nextState = NULL;
       
  1368 	TRAPD(err, nextState = CPanAgtStateIdle::NewL(*this));
       
  1369 	if(err == KErrNone) 
       
  1370 		{
       
  1371 		delete iState;
       
  1372 		SetState(*nextState);
       
  1373 		}
       
  1374 	else
       
  1375 		{
       
  1376 		if(iShutdownState)
       
  1377 			{
       
  1378 			SetState(*iShutdownState);
       
  1379 			}
       
  1380 		}
       
  1381 	}
       
  1382 #endif
       
  1383 // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
  1384 
       
  1385 
       
  1386 
       
  1387 void CPanAgent::CloseExistingConnectionWithUplinkAccess()
       
  1388 	{
       
  1389 	LOG_FUNC
       
  1390 	TInt count = iRemoteDevices.Count();
       
  1391 	for(TInt i=0;i<count;i++)
       
  1392 		{
       
  1393 		if(iRemoteDevices[i]->UplinkAccessAllowed())
       
  1394 			{
       
  1395 			// Close this connection.
       
  1396 			iRemoteDevices[i]->Disconnect();
       
  1397 			break;
       
  1398 			}
       
  1399 		}
       
  1400 	}
       
  1401 
       
  1402 void CPanAgent::GetExistingConnections(TPanConnectionList& aPanConnectionList)
       
  1403 	{
       
  1404 	LOG_FUNC
       
  1405 	TBool localRoleSet = EFalse;
       
  1406 	TInt count = iRemoteDevices.Count();
       
  1407 	for(TInt i=0;i<count;i++)
       
  1408 		{
       
  1409 		if(iRemoteDevices[i]->GetState() == EActive)
       
  1410 			{
       
  1411 			if(!localRoleSet)
       
  1412 				{
       
  1413 				// Set the local role.
       
  1414 				aPanConnectionList.SetCurrentLocalRole(TUUID(iRemoteDevices[i]->LocalRole()));
       
  1415 				localRoleSet = ETrue;
       
  1416 				}
       
  1417 				
       
  1418 			TBTDevAddr deviceAddr = iRemoteDevices[i]->DevAddr();
       
  1419 			TPanConnection requestedConn(deviceAddr, iRemoteDevices[i]->UplinkAccessAllowed());
       
  1420 
       
  1421 			TRAPD(err, aPanConnectionList.AddRemoteConnectionL(requestedConn));
       
  1422 			if(err != KErrNone)
       
  1423 				{
       
  1424 				LOG1(_L("CPanAgent::GetExistingConnections - Failed to add existing connection [%d]"), i);
       
  1425 				break;
       
  1426 				}
       
  1427 			}
       
  1428 		}
       
  1429 	
       
  1430 	if(!localRoleSet)
       
  1431 		{
       
  1432 		aPanConnectionList.SetCurrentLocalRole(TUUID(0));
       
  1433 		}
       
  1434 	}
       
  1435 	
       
  1436 	
       
  1437 TBool CPanAgent::WorthTrying(const TPanDeviceWorthTryingRolesList& aRemoteWorthTryingRoles) const
       
  1438 	{
       
  1439 	LOG_FUNC
       
  1440 	TBool ret = ETrue;	
       
  1441 	if(iFixedRemoteRole != EPanRoleUnknown) // check for fixed remote role
       
  1442 		{
       
  1443 		ret = aRemoteWorthTryingRoles.IsWorthTryingARole(iFixedRemoteRole); // check if it is worth trying
       
  1444 		}
       
  1445 	return ret;
       
  1446 	}
       
  1447 
       
  1448 
       
  1449 #ifndef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
  1450 MPanLinkControlBase& CPanAgent::BnepConnectionController()
       
  1451 	{
       
  1452 	LOG_FUNC
       
  1453 	return *this;
       
  1454 	}
       
  1455 
       
  1456 
       
  1457 TAny* CPanAgent::MplcbGetInterface(const TUid & aInterface) 
       
  1458 	{
       
  1459 	LOG_FUNC
       
  1460 	if (aInterface ==KUidPanLinkControlV1) 
       
  1461 		{
       
  1462 		return PanLinkControlInterface();
       
  1463 		}
       
  1464 	return NULL;
       
  1465 	}
       
  1466 	
       
  1467 MPanLinkControl* CPanAgent::PanLinkControlInterface()
       
  1468 	{
       
  1469 	LOG_FUNC
       
  1470 	return this;
       
  1471 	}
       
  1472 
       
  1473 TInt CPanAgent::MplcRequestSniff(const TBTDevAddr & aAddr)
       
  1474 	{
       
  1475 	LOG_FUNC
       
  1476 	CPanRemoteDeviceStateMachine* dev=FindRemoteDeviceByAddress(aAddr);
       
  1477 	if (dev) 
       
  1478 		{
       
  1479 		return dev->PhysicalLinkAdapter().ActivateSniffRequester();
       
  1480 		}
       
  1481 	else 
       
  1482 		{
       
  1483 		return KErrNotFound;
       
  1484 		}
       
  1485 	}
       
  1486 
       
  1487 TInt CPanAgent::MplcRequestActive(const TBTDevAddr & aAddr)
       
  1488 	{
       
  1489 	LOG_FUNC
       
  1490 	CPanRemoteDeviceStateMachine* dev=FindRemoteDeviceByAddress(aAddr);
       
  1491 	if (dev) 
       
  1492 		{
       
  1493 		return dev->PhysicalLinkAdapter().ActivateActiveRequester();
       
  1494 		}
       
  1495 	else 
       
  1496 		{
       
  1497 		return KErrNotFound;
       
  1498 		}
       
  1499 
       
  1500 	}
       
  1501 #endif
       
  1502 // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
  1503 	
       
  1504 //
       
  1505 // PAN agent helper methods
       
  1506 //
       
  1507 
       
  1508 CPanRemoteDeviceStateMachine* CPanAgent::FindRemoteDeviceByAddress(const TBTDevAddr& remoteDeviceAddress)
       
  1509 /**
       
  1510 Find the remote device with the specified address
       
  1511 @note Simple linear search (the array size is small) - easier than constructing a temporary to use
       
  1512 with RPointerArray::Find()
       
  1513 */
       
  1514 	{
       
  1515 	LOG_FUNC
       
  1516 	for(TInt i=0; i < iRemoteDevices.Count(); ++i)
       
  1517 		{
       
  1518 		if(iRemoteDevices[i]->DevAddr() == remoteDeviceAddress)
       
  1519 			{
       
  1520 			return (iRemoteDevices[i]);
       
  1521 			}
       
  1522 		}
       
  1523 	return NULL;
       
  1524 	}
       
  1525 	
       
  1526 void CPanAgent::CheckDeviceIsNotAlreadyAttachedL(const TBTDevAddr& aDevAddr)
       
  1527 /**
       
  1528 Ensure the remote device is not already a member of the PAN network
       
  1529 (PAN profile only allows one BNEP connection between devices)
       
  1530 */
       
  1531 	{
       
  1532 	LOG_FUNC
       
  1533 
       
  1534 	if(FindRemoteDeviceByAddress(aDevAddr))
       
  1535 		{
       
  1536 		LOG(_L("CPanAgent: ...it is - disconnecting it"));
       
  1537 
       
  1538 		User::Leave(KErrAlreadyExists);
       
  1539 		}
       
  1540 		
       
  1541 	LOG(_L("CPanAgent: ...it isn't - creating new connection"));
       
  1542 	}
       
  1543 
       
  1544 void CPanAgent::RequestDisconnect(TInt aError)
       
  1545 /**
       
  1546 Request from role state machine to disconnect
       
  1547 @note Any code in this class that wants to trigger a disconnect should call this method.
       
  1548 @note This is designed to be called only from the role state machine - states can trigger
       
  1549 a shutdown by leaving from within their state
       
  1550 @param aError The error code that occurred, or KErrNone if the shutdown state does not know
       
  1551 what the error is
       
  1552 */
       
  1553 	{
       
  1554 	LOG_FUNC
       
  1555 	LOG1(_L("CPanAgent: request disconnect from state with error %d"), aError);
       
  1556 	
       
  1557 	if(aError!=KErrNone) // shutdown state may not know what the error is, in which case it will
       
  1558 						 // pass KErrNone, and we should preserve the previous value of iError
       
  1559 		{
       
  1560 		iError = aError;
       
  1561 		}
       
  1562 
       
  1563 	if(iNifmanConnected) // once connected, we need to disconnect when there's an error
       
  1564 		{
       
  1565 		iInitiateDisconnectCallback->CallBack();
       
  1566 		}
       
  1567 	else // we haven't actually brought the connection up properly yet, so rather than issuing 
       
  1568 		 //a Stop() we should just pass an error code back to nifman in ConnectComplete()
       
  1569 		{
       
  1570 		__ASSERT_DEBUG(iError!=KErrNone, PanAgentPanic(ESomeoneLeftWithoutGivingAReason)); // there's a problem, but no-one's set an error code to say what it is!
       
  1571 		}
       
  1572 	}
       
  1573 
       
  1574 //
       
  1575 // Agent extended management interface methods
       
  1576 //
       
  1577 
       
  1578 TInt CPanAgent::GetInterfaceType(TConnectionType& aConnectionType)
       
  1579 /**
       
  1580 Return the type of this interface
       
  1581 */
       
  1582 	{
       
  1583 	LOG_FUNC
       
  1584 	aConnectionType = EConnectionBTPAN;
       
  1585 	return KErrNone;
       
  1586 	}
       
  1587 
       
  1588 TInt CPanAgent::EnumerateSubConnections(TUint& aCount)
       
  1589 /**
       
  1590 Return the number of subconnections
       
  1591 @note Connections to a device are not treated as subconnections, as subconnections are reserved
       
  1592 currently reserved to refer to QoS channels - since BT PAN profile does not support QoS at the 
       
  1593 moment, there are no subconnections to expose
       
  1594 */
       
  1595 	{
       
  1596 	LOG_FUNC
       
  1597 	aCount = 1; // the "whole connection" subconnection
       
  1598 	return KErrNone;
       
  1599 	}
       
  1600 	
       
  1601 TInt CPanAgent::GetSubConnectionInfo(TUint /*aIndex*/, TDes8& /*aSubConnectionInfo*/)
       
  1602 	{
       
  1603 	LOG_FUNC
       
  1604 	return KErrNotSupported;
       
  1605 	}
       
  1606 	
       
  1607 TInt CPanAgent::GetSubConnectionInfo(TDes8& /*aSubConnectionInfo*/)
       
  1608 	{
       
  1609 	LOG_FUNC
       
  1610 	return KErrNotSupported;
       
  1611 	}
       
  1612 
       
  1613 TBool CPanAgent::AllowIncoming() const
       
  1614 	{
       
  1615 	LOG_FUNC
       
  1616 	return iAllowIncoming;
       
  1617 	}
       
  1618 	
       
  1619 void CPanAgent::SetAllowIncoming(TBool aAllowIncoming)
       
  1620 	{
       
  1621 	LOG_FUNC
       
  1622 	iAllowIncoming = aAllowIncoming;
       
  1623 	}
       
  1624 
       
  1625 TBool CPanAgent::NapEnabled() const
       
  1626 	{
       
  1627 	LOG_FUNC
       
  1628 	return iNapEnabled;
       
  1629 	}
       
  1630 
       
  1631 void CPanAgent::SetNapEnabled(TBool aNapEnabled)	
       
  1632 	{
       
  1633 	LOG_FUNC
       
  1634 	iNapEnabled = aNapEnabled;
       
  1635 	}
       
  1636 
       
  1637 TInt CPanAgent::TryToCreateNewPanConnection()
       
  1638 	{
       
  1639 	LOG_FUNC
       
  1640 	if (iPanCoexistenceConnectionController)
       
  1641 		{
       
  1642 		return iPanCoexistenceConnectionController->TryToCreateNewPanConnection();
       
  1643 		}
       
  1644 	else
       
  1645 		{
       
  1646 		// Make sure the release build works fine if iPanCoexistenceConnectionController is null
       
  1647 		LOG(_L("CPanAgent::TryToCreateNewPanConnection - iPanCoexistenceConnectionController is NULL"));
       
  1648 		return KErrNone;
       
  1649 		}
       
  1650 	}
       
  1651 
       
  1652 void CPanAgent::HandleAllPanConnectionsClosed()
       
  1653 	{
       
  1654 	LOG_FUNC
       
  1655 	if (iPanCoexistenceConnectionController)
       
  1656 		{
       
  1657 		iPanCoexistenceConnectionController->HandleAllPanConnectionsClosed();
       
  1658 		}
       
  1659 	else
       
  1660 		{
       
  1661 		// Log it when iPanCoexistenceConnectionController is null
       
  1662 		LOG(_L("CPanAgent::HandleAllPanConnectionsClosed - iPanCoexistenceConnectionController is NULL"));
       
  1663 		}
       
  1664 	}
       
  1665 
       
  1666 TBool CPanAgent::IsNewPanConnectionAllowed() const
       
  1667 	{
       
  1668 	LOG_FUNC
       
  1669 	TBool rValue = EFalse;
       
  1670 	
       
  1671 	if(iPanCoexistenceConnectionController)
       
  1672 		{
       
  1673 		TIPBearerCoexistenceStatus status = iPanCoexistenceConnectionController->ReadStatus();
       
  1674 		if(status == EBTPanIsActive || status == ENoneIsActive)
       
  1675 			{
       
  1676 			__ASSERT_DEBUG(status != EBTPanIsActive, PanAgentPanic(EImproperSituationToSetPropertyToBTPanIsActive));
       
  1677 			rValue = ETrue;
       
  1678 			}
       
  1679 		}
       
  1680 	else
       
  1681 		{
       
  1682 		LOG(_L("CPanAgent::IsNewPanConnectionAllowed - iPanCoexistenceConnectionController is NULL"));
       
  1683 		//Make sure the release build works fine if iPanCoexistenceConnectionController is null
       
  1684 		rValue = ETrue;
       
  1685 		}
       
  1686 
       
  1687 	return rValue;
       
  1688 	}
       
  1689 
       
  1690 void CPanAgent::SendUplinkAccessRequiredProgressNotification()
       
  1691 	{
       
  1692 	LOG_FUNC
       
  1693 	// Check if any active devices require the uplink.
       
  1694 	TBool uplinkRequired = EFalse;
       
  1695 	TInt count = iRemoteDevices.Count();
       
  1696 	for(TInt i=0;i<count;i++)
       
  1697 		{
       
  1698 		if(iRemoteDevices[i]->GetState() == EActive && iRemoteDevices[i]->UplinkAccessAllowed())
       
  1699 			{
       
  1700 			uplinkRequired = ETrue;
       
  1701 			break;
       
  1702 			}
       
  1703 		}
       
  1704 
       
  1705 	if(iUplinkRequiredProgressSent && !uplinkRequired)
       
  1706 		{
       
  1707 		// The uplink is no longer required send a progress notification
       
  1708 		iUplinkRequiredProgressSent = EFalse;
       
  1709 		SendProgress(EPanAgtUplinkNotRequired, KErrNone);
       
  1710 		}
       
  1711 	else if(!iUplinkRequiredProgressSent && uplinkRequired)
       
  1712 		{
       
  1713 		// The uplink is now required, send a progress notification
       
  1714 		iUplinkRequiredProgressSent = ETrue;
       
  1715 		SendProgress(EPanAgtUplinkRequired, KErrNone);
       
  1716 		}
       
  1717 	}
       
  1718 
       
  1719 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
  1720 /**
       
  1721 */
       
  1722 void CPanAgent::ReceivedL(const Messages::TRuntimeCtxId& /* aSender */, const Messages::TNodeId& /* aRecipient */, Messages::TSignatureBase& aCFMessage)
       
  1723     {
       
  1724 	LOG_FUNC
       
  1725 	if (aCFMessage.MessageId().Realm() == TPanMessage::ERealmId)
       
  1726     	{
       
  1727         switch (aCFMessage.MessageId().MessageId())
       
  1728             {
       
  1729             case TPanMessage::TSetRetryConnectComplete::EId:
       
  1730                 {
       
  1731                 // We would expect that iState should always be the paused state when
       
  1732                 // we get here. We assert it in debug builds in case something we
       
  1733                 // haven't accounted for changes it unexpectedly
       
  1734                 __ASSERT_DEBUG(iState->iStateNumber == CPanAgtStateBase::EPanAgtStatePaused, PanAgentPanic(EPanAgtUnexpectedStateChange));
       
  1735                 if (iState->iStateNumber == CPanAgtStateBase::EPanAgtStatePaused)
       
  1736                     {
       
  1737                     static_cast<CPanAgtStatePaused*>(iState)->TransitionToNextState();
       
  1738                     }
       
  1739                 }
       
  1740                 break;
       
  1741             
       
  1742             default:
       
  1743                 __ASSERT_DEBUG(EFalse, PanAgentPanic(EPanAgtUnexpectedMessage));
       
  1744                 break;
       
  1745             }
       
  1746     	}
       
  1747     else
       
  1748         {
       
  1749         __ASSERT_DEBUG(EFalse, PanAgentPanic(EPanAgtUnexpectedMessage));
       
  1750         }
       
  1751     
       
  1752     // Absorb messages
       
  1753     aCFMessage.ClearMessageId();
       
  1754     }
       
  1755 #endif
       
  1756 
       
  1757 
       
  1758 
       
  1759 
       
  1760 
       
  1761 	
       
  1762 //
       
  1763 // State base class implementations
       
  1764 //
       
  1765 
       
  1766 void CPanAgtStateBase::DeviceActiveL(CPanRemoteDeviceStateMachine& /*aDevice*/)
       
  1767 /**
       
  1768 Base class implementation - should never be called
       
  1769 */
       
  1770 	{
       
  1771 	LOG_FUNC
       
  1772 	PanicInState(EUnexpectedDeviceActiveReceivedByState);	
       
  1773 	}
       
  1774 
       
  1775 void CPanAgtStateBase::DeviceRoleChangeFailedL(CPanRemoteDeviceStateMachine& /*aDevice*/)
       
  1776 /**
       
  1777 Base class implementation - should never be called
       
  1778 */
       
  1779 	{
       
  1780 	LOG_FUNC
       
  1781 	PanicInState(EUnexpectedDeviceRoleChangeFailedReceivedByState);
       
  1782 	}
       
  1783 			
       
  1784 void CPanAgtStateBase::DeviceDisconnectedL(CPanRemoteDeviceStateMachine& /*aDevice*/)
       
  1785 /**
       
  1786 Base class implementation - should never be called
       
  1787 */
       
  1788 	{
       
  1789 	LOG_FUNC
       
  1790 	PanicInState(EUnexpectedDeviceDisconnectedReceivedByState);
       
  1791 	}
       
  1792 
       
  1793 void CPanAgtStateBase::StateSendRoleNotification()
       
  1794 /**
       
  1795 Base class implementation - will be called but should need to do nothing, just log
       
  1796 overridden for states EPanAgtStateURole and EPanAgtStateGnRole	
       
  1797 */
       
  1798 	{
       
  1799 	LOG_FUNC
       
  1800 	LOG1(_L("PanAgtSB - CPanAgtStateBase::StateSendRoleNotification() called for state %d"),iStateNumber);
       
  1801 	}
       
  1802 	
       
  1803 void CPanAgtStateBase::IncomingConnectionFromPeerL(TBluetoothPanRole /*aLocalRole*/)
       
  1804 /**
       
  1805 Base class implementation - should never be called
       
  1806 */
       
  1807 	{
       
  1808 	LOG_FUNC
       
  1809 	PanicInState(EUnexpectedIncomingConnectionFromPeerReceivedByState);
       
  1810 	}
       
  1811 
       
  1812 void CPanAgtStateBase::RoleChangeRequestFromPeerL(TBluetoothPanRole /*aLocalRole*/)
       
  1813 /**
       
  1814 Base class implementation - should never be called
       
  1815 */
       
  1816 	{
       
  1817 	LOG_FUNC
       
  1818 	PanicInState(EUnexpectedRoleChangeRequestFromPeerReceivedByState);	
       
  1819 	}
       
  1820 
       
  1821 void CPanAgtStateBase::InitiateOutgoingConnectionL(TBluetoothPanRole& /*aLocalRole*/, TBluetoothPanRole& /*aRemoteRole*/, TPanDeviceWorthTryingRolesList& /*aWorthTryingRemoteRoles*/)
       
  1822 /**
       
  1823 Base class implementation - should never be called
       
  1824 */
       
  1825 	{
       
  1826 	LOG_FUNC
       
  1827 	PanicInState(EUnexpectedInitiateOutgoingConnectionReceivedByState);	
       
  1828 	}
       
  1829 
       
  1830 void CPanAgtStateBase::PerformLocalRoleChangeRequestL(TBluetoothPanRole& /*aLocalRole*/, TBluetoothPanRole& /*aRemoteRole*/)
       
  1831 /**
       
  1832 Base class implementation - should never be called
       
  1833 */
       
  1834 	{
       
  1835 	LOG_FUNC
       
  1836 	PanicInState(EUnexpectedPerformLocalRoleChangeRequestReceivedByState);	
       
  1837 	}
       
  1838 
       
  1839 CPanAgtStateBase::CPanAgtStateBase(MPanAgtStateMachineNotify& aStateMachine, TPanAgtStates aStateNumber) :
       
  1840 	iStateMachine(aStateMachine), iStateNumber(aStateNumber)
       
  1841 /**
       
  1842 When implementing a new state that derives from this base class, ensure that
       
  1843 it provides a unique number to identify the state from other possible
       
  1844 states.  @see PanAgent::TPanAgtStates.
       
  1845 */
       
  1846 	{
       
  1847 	LOG_FUNC
       
  1848 
       
  1849 	}
       
  1850 
       
  1851 void CPanAgtStateBase::StartNegotiationWithFirstPendingDevice()
       
  1852 /**
       
  1853 Check for any idle devices in the device array, and trigger negotiation on the first one; if there are no idle devices this method returns without doing anything.
       
  1854 @note Device negotiation is performed in the order that devices are held in the array - new devices should be inserted at the end of the array
       
  1855 */
       
  1856 	{
       
  1857 	LOG_FUNC
       
  1858 	
       
  1859 	// find first pending device in array and call ReadyForRoleRequest
       
  1860 	for(TInt i=0;i<StateMachine().Devices().Count();++i)
       
  1861 		{
       
  1862 		CPanRemoteDeviceStateMachine& device = *StateMachine().Devices()[i];
       
  1863 
       
  1864 		if(device.GetState() == EPendingNegotiation)
       
  1865 			{
       
  1866 			LOG(_L("PanAgtSB - ...device with negotiation pending found - calling ReadyForRoleRequest"));
       
  1867 			device.ReadyForRoleRequest();
       
  1868 			return;
       
  1869 			}
       
  1870 		}
       
  1871 	LOG(_L("PanAgtSB - ...no pending devices found"));
       
  1872 	}
       
  1873 
       
  1874 TInt CPanAgtStateBase::IsRoleRequestValid(TBluetoothPanRole aRequestedLocalRole, TBluetoothPanRole aRequestedRemoteRole) const
       
  1875 /**
       
  1876 Check the role request is legal according to the PAN profile spec
       
  1877 @param aRequestedLocalRole The requested local role
       
  1878 @param aRequestedRemoteRole The requested remote role
       
  1879 @return KErrNone if role request is OK, KErrArgument if the role combination was illegal
       
  1880 @note Not a bug as such, but just a convenient way to get doxygen to record that this method embeds knowledge 
       
  1881 of legal PAN role combinations, and allows EPanRoleUnknown as a valid local role.  Later code must decide on 
       
  1882 a concrete local role if this is the case.
       
  1883 */
       
  1884 	{
       
  1885 	LOG_FUNC
       
  1886 	// check for invalid role combinations
       
  1887 	if((aRequestedLocalRole==EPanRoleGn || aRequestedLocalRole==EPanRoleNap) && (aRequestedRemoteRole==EPanRoleGn || aRequestedRemoteRole==EPanRoleNap))
       
  1888 		{
       
  1889 		LOG2(_L("PanAgtSB - CheckRoleRequest: invalid role combination received (%x, %x)"), aRequestedLocalRole, aRequestedRemoteRole);
       
  1890 		return KErrArgument;		
       
  1891 		}
       
  1892 	else
       
  1893 		{
       
  1894 		return KErrNone;
       
  1895 		}
       
  1896 	}
       
  1897 
       
  1898 TInt CPanAgtStateBase::SelectRemoteRoleBasedOnLocalRole(TBluetoothPanRole aSelectedLocalRole, TBluetoothPanRole& aRemoteRole, TPanDeviceWorthTryingRolesList& aWorthTryingRemoteRoles)
       
  1899 /**
       
  1900 Given a selected local role, check what role has been proposed for the remote device and alter it accordingly
       
  1901 @note This handles setting the remote role if it is fixed in commdb
       
  1902 @param aSelectedLocalRole The local role that has been selected by the role state machine
       
  1903 @param aRemoteRole On entry, the role that was proposed by the remote device state machine. On return, the 
       
  1904 remote role that will be requested
       
  1905 @return The same error codes and meanings as MRemoteDeviceNotify::RoleRequest()
       
  1906 @note Embeds knowledge of valid PAN profile role combinations
       
  1907 */
       
  1908 	{
       
  1909 	LOG_FUNC
       
  1910 	TBluetoothPanRole fixedRemoteRole = StateMachine().FixedRemoteRole();
       
  1911 	
       
  1912 	// Check to see if there's a fixed remote role first...
       
  1913 	if(fixedRemoteRole != EPanRoleUnknown) // check for fixed remote role
       
  1914 		{
       
  1915 		LOG1(_L("PanAgtSB - SelectRemoteRole: ...remote role is fixed as %x..."), StateMachine().FixedRemoteRole());
       
  1916 		
       
  1917 		if(aWorthTryingRemoteRoles.IsWorthTryingARole(fixedRemoteRole) || fixedRemoteRole == EPanRoleU)
       
  1918 			{
       
  1919 			// if the remote device doesn't support the role (and it's not U role, which isn't 
       
  1920 			// necessarily advertised in SDP (see PAN profile spec v1.0, section 8.1.3)
       
  1921 			// then return an error
       
  1922 			aRemoteRole = fixedRemoteRole;
       
  1923 			aWorthTryingRemoteRoles.SetWorthTrying(fixedRemoteRole, EFalse);
       
  1924 			}
       
  1925 		else
       
  1926 			{
       
  1927 			LOG(_L("PanAgtSB - SelectRemoteRole: ...fixed remote role is not supported! (not included in SDP)"));
       
  1928 			return KErrInvalidOrUnacceptableRoleCombination;
       
  1929 			}
       
  1930 		}
       
  1931 	else
       
  1932 		{
       
  1933 		// ...otherwise use dynamic role selection
       
  1934 		switch(aSelectedLocalRole)
       
  1935 			{
       
  1936 			case EPanRoleU:
       
  1937 				{
       
  1938 				LOG(_L("PanAgtSB - CheckAndAdjustRemoteRole: no SDP query to use for remote role selection, making a guess and trying U role - there's not much else we can do"));
       
  1939 				// see PAN profile spec v1.0, section 8.1.3 for reasoning
       
  1940 				
       
  1941 				/* now if we don't know what they do support
       
  1942 				   and the other side has refused us, or we didn't ask
       
  1943 				   then we might ask for something else
       
  1944 				 */
       
  1945 				// lets decide what we'll try this time
       
  1946 				if (aWorthTryingRemoteRoles.IsWorthTryingU())
       
  1947 					{
       
  1948 					aRemoteRole = EPanRoleU;
       
  1949 					}
       
  1950 				else if (aWorthTryingRemoteRoles.IsWorthTryingGn())
       
  1951 					{
       
  1952 					aRemoteRole = EPanRoleGn;
       
  1953 					}
       
  1954 				else if (aWorthTryingRemoteRoles.IsWorthTryingNap())
       
  1955 					{
       
  1956 					aRemoteRole = EPanRoleNap;
       
  1957 					}
       
  1958 
       
  1959 				aWorthTryingRemoteRoles.SetWorthTrying(aRemoteRole, EFalse);
       
  1960 				}
       
  1961 			 	break;	// RVCT detects this as dead code - if you change the logic above, *beware*
       
  1962 						// you may need this!
       
  1963 			case EPanRoleGn:
       
  1964 			case EPanRoleNap:
       
  1965 				aRemoteRole = EPanRoleU;
       
  1966 				break;
       
  1967 
       
  1968 			default:
       
  1969 				PanicInState(EPanAgentRoleStateMachineSelectedUnknownAsLocalRole);
       
  1970 			};
       
  1971 		}
       
  1972 
       
  1973 	return KErrNone;
       
  1974 	}
       
  1975 
       
  1976 void CPanAgtStateBase::DoDeviceDisconnectL(CPanRemoteDeviceStateMachine& aDevice)
       
  1977 /**
       
  1978 Delete the disconnected device from the array, and check if it was the last device. If it was, and we're
       
  1979 not allowing incoming connections, then shutdown.
       
  1980 */
       
  1981 	{
       
  1982 	LOG_FUNC
       
  1983 	__ASSERT_DEBUG(FindDeviceInArray(aDevice)>=0, PanicInState(EDeviceDisconnectedThatWasNotInArray));
       
  1984 
       
  1985 	TInt index = FindDeviceInArray(aDevice);
       
  1986 	if(index>=0) // ie. the device is in the array
       
  1987 		{
       
  1988 		LOG(_L("RoleState: <[base]> - device disconnected"));
       
  1989 		delete StateMachine().Devices()[index];
       
  1990 		StateMachine().Devices().Remove(index);
       
  1991 		}
       
  1992 		
       
  1993 	if (StateMachine().Devices().Count()==0)
       
  1994 		{
       
  1995 		StateMachine().HandleAllPanConnectionsClosed();
       
  1996 		
       
  1997 		// see if this was the last device, and if we're not listening for incoming connections
       
  1998 		if (!(StateMachine().AllowIncoming()) && !(StateMachine().IsPromptingUserForDeviceSelection()))
       
  1999 			{
       
  2000 			User::Leave(KErrAllDevicesDisconnected);
       
  2001 			}
       
  2002 		
       
  2003 		}
       
  2004 	}
       
  2005 
       
  2006 TInt CPanAgtStateBase::NegotiatingDeviceCount() const
       
  2007 /**
       
  2008 The number of devices in the device array in negotiating state
       
  2009 @return The number of devices in the device array in negotiating state
       
  2010 */
       
  2011 	{
       
  2012 	LOG_FUNC
       
  2013 	return(DeviceCountInState(EPerformingNegotiation));	
       
  2014 	}
       
  2015 
       
  2016 
       
  2017 TInt CPanAgtStateBase::ActiveDeviceCount() const
       
  2018 /**
       
  2019 The number of devices in the device array in active state
       
  2020 @return The number of devices in the device array in active state
       
  2021 */
       
  2022 	{
       
  2023 	LOG_FUNC
       
  2024 	return(DeviceCountInState(EActive));	
       
  2025 	}
       
  2026 
       
  2027 MPanAgtStateMachineNotify& CPanAgtStateBase::StateMachine()
       
  2028 /**
       
  2029 Return a handle to the state machine
       
  2030 */
       
  2031 	{
       
  2032 	LOG_FUNC
       
  2033 	return(iStateMachine);
       
  2034 	}
       
  2035 	
       
  2036 const MPanAgtStateMachineNotify& CPanAgtStateBase::StateMachine() const
       
  2037 /**
       
  2038 Return a const handle to the state machine
       
  2039 */
       
  2040 	{
       
  2041 	LOG_FUNC
       
  2042 	return(iStateMachine);
       
  2043 	}
       
  2044 
       
  2045 TInt CPanAgtStateBase::FindDeviceInArray(const CPanRemoteDeviceStateMachine& aDevice) const
       
  2046 /**
       
  2047 Find a given device in the array
       
  2048 @param aRequestingConnection The connection handle to find
       
  2049 @return Either the position of the device in the array, or KErrNotFound
       
  2050 */
       
  2051 	{
       
  2052 	LOG_FUNC
       
  2053 	for(TInt i=0; i<StateMachine().Devices().Count(); i++)
       
  2054 		{
       
  2055 		if(StateMachine().Devices()[i] == &aDevice)
       
  2056 			{
       
  2057 			return i;	
       
  2058 			}
       
  2059 		}
       
  2060 	return KErrNotFound;	
       
  2061 	}
       
  2062 
       
  2063 TInt CPanAgtStateBase::DeviceCountInState(TRemoteDeviceState aState) const
       
  2064 /**
       
  2065 The number of devices in the given state
       
  2066 @param aState Devices in this state should be counted
       
  2067 @return The number of devices in the given state
       
  2068 */
       
  2069 	{
       
  2070 	LOG_FUNC
       
  2071 #ifdef _DEBUG
       
  2072 	DumpDeviceArray();
       
  2073 #endif
       
  2074 	TInt devCountInState = 0;
       
  2075 	
       
  2076 	for(TInt i=0; i<StateMachine().Devices().Count(); i++)
       
  2077 		{
       
  2078 		if((StateMachine().Devices()[i]->GetState()) == aState)
       
  2079 			{
       
  2080 			++devCountInState;
       
  2081 			}
       
  2082 		}
       
  2083 		
       
  2084 	return(devCountInState);
       
  2085 	}
       
  2086 
       
  2087 void CPanAgtStateBase::LockDeviceAsPiconetMasterL()
       
  2088 /**
       
  2089 Set link policy to stop other devices changing the baseband role, once we are in the master role
       
  2090 @note The ASSERT to ensure that we are in the master role is performed in the remote device state machines
       
  2091 in debug mode only
       
  2092 */
       
  2093 	{
       
  2094 	LOG_FUNC
       
  2095 	__ASSERT_DEBUG(NegotiatingDeviceCount()==0, PanicInState(ETryingToLockBasebandRolesWhenDevicesAreNegotiating));
       
  2096 
       
  2097 	for(TInt i=0; i < StateMachine().Devices().Count(); ++i)
       
  2098 		{
       
  2099 		// lock any device that is active into it's current baseband role (which should be master)
       
  2100 		// can't lock other devices, because in hardware that supports scatternetting, they
       
  2101 		// might still be in slave role, because we haven't gone through the role negotiation
       
  2102 		// process with them yet, which is where we do baseband role switches
       
  2103 		if(StateMachine().Devices()[i]->GetState() == EActive)
       
  2104 			{
       
  2105 			User::LeaveIfError(StateMachine().Devices()[i]->DisallowRoleSwitch());
       
  2106 			}
       
  2107 		}
       
  2108 	}
       
  2109 	
       
  2110 TInt CPanAgtStateBase::ReleasePiconetMasterLock()
       
  2111 /**
       
  2112 Set link policy to allow other devices to change the baseband role
       
  2113 */
       
  2114 	{
       
  2115 	LOG_FUNC
       
  2116 	TInt count;
       
  2117 	TInt err;
       
  2118 	for(count=0; count < StateMachine().Devices().Count(); ++count)
       
  2119 		{
       
  2120 		err = StateMachine().Devices()[count]->AllowRoleSwitch();
       
  2121 		if(!err)
       
  2122 			{
       
  2123 			continue;
       
  2124 			}
       
  2125 		else	// go back through the devices resetting the link policy to lock us as master
       
  2126 			{
       
  2127 			for(--count; count >= 0; --count)	// decrement before starting so we only reset role switching for the ones that we have previously set 
       
  2128 				{
       
  2129 				if(StateMachine().Devices()[count]->GetState() == EActive)
       
  2130 					{
       
  2131 					// ignore errors - if we don't then the only other choice is to shut down everything!
       
  2132 					StateMachine().Devices()[count]->DisallowRoleSwitch();
       
  2133 					}
       
  2134 				}
       
  2135 			}
       
  2136 		break;
       
  2137 		}
       
  2138 	return KErrNone;
       
  2139 	}
       
  2140 
       
  2141 void CPanAgtStateBase::StartListenerL()
       
  2142 /**
       
  2143 Work out which local roles we support and register the appropriate records
       
  2144 */
       
  2145 	{
       
  2146 	LOG_FUNC
       
  2147 	
       
  2148 	if(StateMachine().AllowIncoming())
       
  2149 		{
       
  2150 		__ASSERT_DEBUG(StateMachine().FixedLocalRole() != EPanRoleU, PanAgentPanic(EFixedLocalRoleUForListeningIap));
       
  2151 
       
  2152 		// Register U role if fixed local role is not specified.
       
  2153 		if(StateMachine().FixedLocalRole() == EPanRoleUnknown)
       
  2154 			{
       
  2155 			StateMachine().PanLocalSdpRegistrar().RegisterLocalSdpRecordL(EPanRoleU, StateMachine().IapId());
       
  2156 			}
       
  2157 		
       
  2158 		// Register either GN or NAP	
       
  2159 		if(StateMachine().NapEnabled())
       
  2160 			{				
       
  2161 			StateMachine().PanLocalSdpRegistrar().RegisterLocalSdpRecordL(EPanRoleNap, StateMachine().IapId());
       
  2162 			}
       
  2163 		else
       
  2164 			{
       
  2165 			StateMachine().PanLocalSdpRegistrar().RegisterLocalSdpRecordL(EPanRoleGn, StateMachine().IapId());
       
  2166 			}
       
  2167 
       
  2168 		User::LeaveIfError(StateMachine().StartIncomingConnectionListener());
       
  2169 		}
       
  2170 	}
       
  2171 
       
  2172 void CPanAgtStateBase::StopListener()
       
  2173 	{
       
  2174 	LOG(_L("StopListener - remove local SDP registation and close listener."));
       
  2175 		
       
  2176 	//check that listerner is started
       
  2177 	if(StateMachine().IsIncomingConnectionListenerEnabled())
       
  2178 		{
       
  2179 		__ASSERT_DEBUG(StateMachine().FixedLocalRole() != EPanRoleU, PanAgentPanic(EFixedLocalRoleUForListeningIap));
       
  2180 
       
  2181 		// Unregister U role if fixed local role is not specified.
       
  2182 		if(StateMachine().FixedLocalRole() == EPanRoleUnknown)
       
  2183 			{
       
  2184 			StateMachine().PanLocalSdpRegistrar().UnregisterLocalSdpRecord(EPanRoleU);
       
  2185 			}
       
  2186 		
       
  2187 		// Unregister either GN or NAP	
       
  2188 		if(StateMachine().NapEnabled())
       
  2189 			{				
       
  2190 			StateMachine().PanLocalSdpRegistrar().UnregisterLocalSdpRecord(EPanRoleNap);
       
  2191 			}
       
  2192 		else
       
  2193 			{
       
  2194 			StateMachine().PanLocalSdpRegistrar().UnregisterLocalSdpRecord(EPanRoleGn);
       
  2195 			}
       
  2196 		
       
  2197 		StateMachine().CloseIncomingConnectionListener();
       
  2198 		}
       
  2199 	}
       
  2200 
       
  2201 void CPanAgtStateBase::Connect()
       
  2202 	{
       
  2203 	LOG_FUNC
       
  2204 	iServiceStartedCallback->CallBack();
       
  2205 	}
       
  2206 
       
  2207 void CPanAgtStateBase::CancelConnect()
       
  2208 	{
       
  2209 	LOG_FUNC
       
  2210 	iServiceStartedCallback->Cancel();
       
  2211 	}
       
  2212 
       
  2213 void CPanAgtStateBase::ServiceStarted()
       
  2214 	{
       
  2215 	LOG_FUNC
       
  2216 
       
  2217 	StateMachine().SendProgress(EPanAgtInitialising, KErrNone);
       
  2218 	iConnectCompleteCallback->CallBack(); // Queued here before ServiceStarted as ServiceStarted can delete iConnectCompleteCallback, causing a null pointer exception 
       
  2219 	StateMachine().ServiceStarted(); 
       
  2220 	
       
  2221 	}
       
  2222 
       
  2223 TInt CPanAgtStateBase::ServiceStartedCb(TAny* aThisPtr)
       
  2224 /**
       
  2225 Connection Callback static function 
       
  2226 */
       
  2227 	{
       
  2228 	LOG_STATIC_FUNC
       
  2229 	__ASSERT_DEBUG(aThisPtr, PanAgentPanic(ENullTAnyPointer));
       
  2230 
       
  2231 	CPanAgtStateBase* self = static_cast<CPanAgtStateBase*>(aThisPtr);
       
  2232 	self->ServiceStarted();
       
  2233 	return KErrNone;
       
  2234 	}
       
  2235 
       
  2236 TInt CPanAgtStateBase::ConnectCompleteCb(TAny* aThisPtr)
       
  2237 /**
       
  2238 Second callback used during connection creation
       
  2239 */
       
  2240 	{
       
  2241 	LOG_STATIC_FUNC
       
  2242 	__ASSERT_DEBUG(aThisPtr, PanAgentPanic(ENullTAnyPointer));
       
  2243 
       
  2244 	CPanAgtStateBase* self = static_cast<CPanAgtStateBase*>(aThisPtr);
       
  2245 	self->StateMachine().ConnectComplete();
       
  2246 	return KErrNone;
       
  2247 	}
       
  2248 	
       
  2249 void CPanAgtStateBase::BaseConstructL()
       
  2250 	{
       
  2251 	LOG_FUNC
       
  2252 	iConnectCompleteCallback = new (ELeave) CAsyncCallBack(KPanAgtAoPriority);	
       
  2253 	TCallBack connectCompleteCallback(ConnectCompleteCb, this);
       
  2254 	iConnectCompleteCallback->Set(connectCompleteCallback);
       
  2255 	
       
  2256 	iServiceStartedCallback = new (ELeave) CAsyncCallBack(KPanAgtAoPriority);
       
  2257 	TCallBack serviceStartedCallback(ServiceStartedCb, this);
       
  2258 	iServiceStartedCallback->Set(serviceStartedCallback);
       
  2259 	}
       
  2260 	
       
  2261 CPanAgtStateBase::~CPanAgtStateBase()
       
  2262 	{
       
  2263 	LOG_FUNC
       
  2264 	iServiceStartedCallback->Cancel();
       
  2265 	delete iServiceStartedCallback;
       
  2266 	iServiceStartedCallback = NULL;
       
  2267 	
       
  2268 	iConnectCompleteCallback->Cancel();
       
  2269 	delete iConnectCompleteCallback;
       
  2270 	iConnectCompleteCallback = NULL;
       
  2271 	}
       
  2272 
       
  2273 void CPanAgtStateBase::CancelReconnect()
       
  2274 	{
       
  2275 	LOG_FUNC
       
  2276 	//do nothing
       
  2277 	}
       
  2278 /**
       
  2279 Calls the appropriate panic function to encode the panic
       
  2280 code with the current state identifier.
       
  2281 @param aPanic The panic code that the state is panicking with.
       
  2282 */
       
  2283 void CPanAgtStateBase::PanicInState(TPanAgentPanic aPanic) const
       
  2284 	{
       
  2285 	LOG_FUNC
       
  2286 	PanAgentPanic(aPanic, iStateNumber);
       
  2287 	}
       
  2288 
       
  2289 #ifdef _DEBUG
       
  2290 void CPanAgtStateBase::DumpDeviceArray() const
       
  2291 /**
       
  2292 Dump the device array to the logs
       
  2293 */	
       
  2294 	{
       
  2295 	LOG_FUNC
       
  2296 	const RPointerArray<CPanRemoteDeviceStateMachine>& deviceArray(StateMachine().Devices());																					
       
  2297 	
       
  2298 	for(TInt i=0; i<deviceArray.Count(); i++)
       
  2299 		{
       
  2300 		LOG2(_L("Device: %x, state: %d"), deviceArray[i], deviceArray[i]->GetState());
       
  2301 		}
       
  2302 	}
       
  2303 #endif // _DEBUG	
       
  2304 
       
  2305