bluetoothcommsprofiles/btpan/panagt/panagtremdevstates.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 /**
       
    17  @file
       
    18  @note PAN agent remote connection state implementations
       
    19 */
       
    20 
       
    21 #include <bluetooth/logger.h>
       
    22 #include <networking/panuiinterfaces.h>
       
    23 #include "panagtremdevstates.h"
       
    24 #include "panagtpolicy.h"
       
    25 using namespace PanAgent;
       
    26 
       
    27 #ifdef __FLOG_ACTIVE
       
    28 _LIT8(KLogComponent, LOG_COMPONENT_PAN_AGENT);
       
    29 #endif
       
    30 
       
    31 //
       
    32 // CPanRemDevStatePerformingSdpQuery
       
    33 //
       
    34 
       
    35 CPanRemDevStatePerformingSdpQuery::CPanRemDevStatePerformingSdpQuery(MPanRemDevStateMachineNotify& aStateMachine) :
       
    36 	CPanRemDevStateBase(aStateMachine, EPanRemDevStatePerformingSdpQuery), iPanDevRolesListPtr(StateMachine().RemoteRolesList())
       
    37 /**
       
    38 
       
    39 */
       
    40 	{
       
    41 	}
       
    42 
       
    43 void CPanRemDevStatePerformingSdpQuery::OnEntryL()
       
    44 /**
       
    45 Check out roles in commdb, perform SDP query if necessary, then check it's OK
       
    46 @note If SDP queries are inhibited by the setting in commdb, this class will just accept whatever is in there - if there isn't anything then the SDP query will be performed anyway
       
    47 */
       
    48 	{
       
    49 	// perform SDP query to see what the remote device supports
       
    50 	User::LeaveIfError(StateMachine().RemoteSdpQuerier().Query(StateMachine().RemSockAddr().BTAddr(), iPanDevRolesListPtr, StateMachine().Status()));
       
    51 	StateMachine().SetActive();
       
    52 	}
       
    53 
       
    54 void CPanRemDevStatePerformingSdpQuery::AsyncEventCompleteL()
       
    55 /**
       
    56 The SDP query has completed
       
    57 */
       
    58 	{
       
    59 	//The PAN spec says a device supporting PANU does not have to advertise that on SDP.
       
    60 	//But the spec is a bit vague on if such a device is connectable, so we try to connect
       
    61 	//to it anyway to maximise interoperability
       
    62 	if(StateMachine().Status()==KErrNone || StateMachine().Status()==KErrNotFound)
       
    63 		{	
       
    64 		// If remote doesn't support GN, there is no point try it, so set it to Not WorthTrying
       
    65 		if(!StateMachine().RemoteRolesList().SupportsGn())
       
    66 			{
       
    67 			StateMachine().RemoteWorthTryingRolesList().SetWorthTryingGn(EFalse);
       
    68 			}
       
    69 		// If remote doesn't support NAP, there is no point try it, so set it to Not WorthTrying
       
    70 		if(!StateMachine().RemoteRolesList().SupportsNap())
       
    71 			{
       
    72 			StateMachine().RemoteWorthTryingRolesList().SetWorthTryingNap(EFalse);
       
    73 			}
       
    74 			
       
    75 		// check whether FixedRemoteRole is supported by remote according to SDP query result
       
    76 		if(StateMachine().WorthTrying())
       
    77 			{
       
    78 			CPanRemDevStateBase* nextState = new(ELeave) CPanRemDevStateConnectingSocket(StateMachine());
       
    79 			LOG1(_L("RemDevState[%x]: <performing SDP query> - SDP query completed successfully, moving to <connecting socket> state"), &StateMachine());
       
    80 			StateMachine().SetState(*nextState);
       
    81 			delete this;
       
    82 			}
       
    83 		else
       
    84 			{
       
    85 			LOG1(_L("RemDevState[%x]: <performing SDP query> - SDP query completed successfully, but remote doesn't support the Fixed Remote Role we've specified."), &StateMachine());
       
    86 			User::Leave(KErrFixRemoteRoleIsNotSupportedByRemote);
       
    87 			}
       
    88 		}
       
    89 	else // error handling
       
    90 		{
       
    91 		LOG1(_L("RemDevState[%x]: <performing SDP query> - SDP query failed"), &StateMachine());
       
    92 		User::Leave(StateMachine().Status().Int());
       
    93 		}
       
    94 	}
       
    95 
       
    96 void CPanRemDevStatePerformingSdpQuery::AsyncEventCancelL()
       
    97 /**
       
    98 The SDP query has been cancelled
       
    99 */
       
   100 	{
       
   101 	LOG1(_L("RemDevState[%x]: <performing SDP query> - SDP query cancelled"), &StateMachine());
       
   102 
       
   103 	StateMachine().RemoteSdpQuerier().CancelQuery();
       
   104 	}
       
   105 	
       
   106 void CPanRemDevStatePerformingSdpQuery::ShutdownL()
       
   107 /**
       
   108 The local device wants us to disconnect
       
   109 */
       
   110 	{
       
   111 	LOG1(_L("RemDevState[%x]: <performing SDP query> - locally requested disconnect received"), &StateMachine());
       
   112 	
       
   113 	// outstanding async request will be cancelled by state machine when we leave
       
   114 	User::Leave(KErrLocallyInitiatedDisconnect);
       
   115 	}
       
   116 
       
   117 // This returns a distilled (i.e., not the actual remote device state)
       
   118 // version of the current connection status of the remote device
       
   119 TRemoteDeviceState CPanRemDevStatePerformingSdpQuery::GetState() const
       
   120 	{
       
   121 	return EIdle;
       
   122 	}
       
   123 
       
   124 //
       
   125 // CPanRemDevStateConnectingSocket
       
   126 //
       
   127 
       
   128 CPanRemDevStateConnectingSocket::CPanRemDevStateConnectingSocket(MPanRemDevStateMachineNotify& aStateMachine) :
       
   129 	CPanRemDevStateBase(aStateMachine, EPanRemDevStateConnectingSocket)
       
   130 /**
       
   131 
       
   132 */
       
   133 	{	}
       
   134 		
       
   135 void CPanRemDevStateConnectingSocket::OnEntryL()
       
   136 /**
       
   137 
       
   138 */
       
   139 	{
       
   140 	LOG1(_L("RemDevState[%x]: <connecting socket> - entering state"), &StateMachine());
       
   141 
       
   142 	TBTServiceSecurity securitySettings;
       
   143 	// we override whatever security settings that came with the address with our own
       
   144 	securitySettings.SetAuthentication(KPanOutgoignAuthenticationRequired);
       
   145 	securitySettings.SetAuthorisation(KPanOutgoingAuthorisationRequired);
       
   146 	securitySettings.SetEncryption(KPanOutgoingEncryptionRequired);
       
   147 	securitySettings.SetUid(KBTPanAuthorisationUid);
       
   148 
       
   149 	StateMachine().RemSockAddr().SetSecurity(securitySettings);
       
   150 
       
   151 #if defined(_DEBUG) && defined(SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY)
       
   152     TInt err = StateMachine().Socket().Open(KBTAddrFamily, KSockSeqPacket, KL2CAP);
       
   153     __ASSERT_DEBUG(err != KErrBadName, PanicInState(EPanAgtMissingBinding));
       
   154     User::LeaveIfError(err);
       
   155 #else
       
   156 	User::LeaveIfError(StateMachine().Socket().Open(KBTAddrFamily, KSockSeqPacket, KL2CAP));
       
   157 #endif
       
   158 
       
   159 	TUint16 bnepMtu = KBnepMtu;
       
   160 	TPckg<TUint16> mtuBuf(bnepMtu);
       
   161 
       
   162 	User::LeaveIfError(StateMachine().Socket().SetOpt(KL2CAPInboundMTU, KSolBtL2CAP, mtuBuf));
       
   163 	User::LeaveIfError(StateMachine().Socket().SetOpt(KL2CAPNegotiatedOutboundMTU, KSolBtL2CAP, mtuBuf));
       
   164 	// Register the CoD service - Networking bit (especially relevant for WinXP)
       
   165 	User::LeaveIfError(StateMachine().Socket().SetOpt(KBTRegisterCodService, KSolBtSAPBase, EMajorServiceNetworking));
       
   166 
       
   167 	StateMachine().Socket().Connect(StateMachine().RemSockAddr(), StateMachine().Status());
       
   168 	StateMachine().SetActive();
       
   169 	}
       
   170 	
       
   171 void CPanRemDevStateConnectingSocket::AsyncEventCompleteL()
       
   172 /**
       
   173 Called when the new socket is connected
       
   174 */
       
   175 	{
       
   176 	if(StateMachine().Status()==KErrNone)
       
   177 		{
       
   178 		LOG1(_L("RemDevState[%x]: <connecting socket> - async event complete, socket connected successfully"), &StateMachine());
       
   179 
       
   180 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   181         StateMachine().CreateNewBnepConnection(StateMachine().Socket(), TPanMessage::EActivityCreateChannelControllerForOutgoing);
       
   182 #else
       
   183 		StateMachine().CreateNewBnepConnectionL(StateMachine().Socket());
       
   184 #endif
       
   185 
       
   186 		StateMachine().OpenPhysicalLinkAdapterL();
       
   187 
       
   188 		CPanRemDevStateBase* nextState = new(ELeave) CPanRemDevStatePerformingRoleNegotiationForOutgoingConnection(StateMachine());
       
   189 
       
   190 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   191         CleanupStack::PushL(nextState);
       
   192         CPanRemDevStatePaused* pausedState = new(ELeave)CPanRemDevStatePaused(StateMachine(), *nextState);
       
   193         CleanupStack::Pop();
       
   194         nextState = pausedState;
       
   195 #endif
       
   196 
       
   197 		StateMachine().SetState(*nextState);
       
   198 		delete this;
       
   199 		}
       
   200 	else	// did not complete the connection to the remote device...
       
   201 		{
       
   202 		LOG2(_L("RemDevState[%x]: <connecting socket> - socket connect failed with %d"), &StateMachine(), StateMachine().Status().Int());
       
   203 		User::Leave(StateMachine().Status().Int());
       
   204 		}
       
   205 	}	
       
   206 	
       
   207 void CPanRemDevStateConnectingSocket::AsyncEventCancelL()
       
   208 /**
       
   209 Cancel the socket connect
       
   210 */
       
   211 	{
       
   212 	LOG1(_L("RemDevState[%x]: <connecting socket> - async event cancelled"), &StateMachine());
       
   213 	
       
   214 	StateMachine().Socket().CancelConnect();
       
   215 	StateMachine().Socket().Close();
       
   216 	}
       
   217 
       
   218 void CPanRemDevStateConnectingSocket::ShutdownL()
       
   219 /**
       
   220 The local device wants us to disconnect
       
   221 */
       
   222 	{
       
   223 	LOG1(_L("RemDevState[%x]: <connecting socket> - locally requested disconnect received"), &StateMachine());
       
   224 	
       
   225 	// outstanding async request will be cancelled by state machine when we leave
       
   226 	User::Leave(KErrLocallyInitiatedDisconnect);
       
   227 	}
       
   228 
       
   229 // This returns a distilled (i.e., not the actual remote device state)
       
   230 // version of the current connection status of the remote device
       
   231 TRemoteDeviceState CPanRemDevStateConnectingSocket::GetState() const
       
   232 	{
       
   233 	return EIdle;
       
   234 	}
       
   235 
       
   236 //
       
   237 // CPanRemDevStateReconnectingSocket
       
   238 //
       
   239 
       
   240 CPanRemDevStateReconnectingSocket::CPanRemDevStateReconnectingSocket(MPanRemDevStateMachineNotify& aStateMachine) :
       
   241 	CPanRemDevStateBase(aStateMachine, EPanRemDevStateConnectingSocket)
       
   242 	{	}
       
   243 		
       
   244 /**
       
   245 	Disconnect the socket for the case where the remote device doesn't
       
   246 */
       
   247 void CPanRemDevStateReconnectingSocket::OnEntryL()
       
   248 	{
       
   249 	LOG1(_L("RemDevState[%x]: <reconnecting socket> - entering state"), &StateMachine());
       
   250 	StateMachine().Socket().Close();
       
   251 
       
   252 	StateMachine().SetRetryConnect();	
       
   253 	}
       
   254 
       
   255 /**
       
   256 	Wait for device to disconnect before attempting reconnect
       
   257 */
       
   258 void CPanRemDevStateReconnectingSocket::RemoteDeviceDisconnectL(TInt /*aErr*/)
       
   259 	{
       
   260 	LOG1(_L("RemDevState[%x]: <reconnecting socket> - remote device disconnected"), &StateMachine());
       
   261 	StateMachine().DisconnectBnepChannel();
       
   262 	TBTServiceSecurity securitySettings;
       
   263 	// we override whatever security settings that came with the address with our own
       
   264 	securitySettings.SetAuthentication(KPanOutgoignAuthenticationRequired);
       
   265 	securitySettings.SetAuthorisation(KPanOutgoingAuthorisationRequired);
       
   266 	securitySettings.SetEncryption(KPanOutgoingEncryptionRequired);
       
   267 	securitySettings.SetUid(KBTPanAuthorisationUid);
       
   268 
       
   269 	StateMachine().RemSockAddr().SetSecurity(securitySettings);
       
   270 
       
   271 #if defined(_DEBUG) && defined(SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY)
       
   272     TInt err = StateMachine().Socket().Open(KBTAddrFamily, KSockSeqPacket, KL2CAP);
       
   273     __ASSERT_DEBUG(err != KErrBadName, PanicInState(EPanAgtMissingBinding));
       
   274     User::LeaveIfError(err);
       
   275 #else
       
   276 	User::LeaveIfError(StateMachine().Socket().Open(KBTAddrFamily, KSockSeqPacket, KL2CAP));
       
   277 #endif
       
   278 
       
   279 	TUint16 bnepMtu = KBnepMtu;
       
   280 	TPckg<TUint16> mtuBuf(bnepMtu);
       
   281 
       
   282 	User::LeaveIfError(StateMachine().Socket().SetOpt(KL2CAPInboundMTU, KSolBtL2CAP, mtuBuf));
       
   283 	User::LeaveIfError(StateMachine().Socket().SetOpt(KL2CAPNegotiatedOutboundMTU, KSolBtL2CAP, mtuBuf));
       
   284 
       
   285 	StateMachine().Socket().Connect(StateMachine().RemSockAddr(), StateMachine().Status());
       
   286 	StateMachine().SetActive();
       
   287 	}
       
   288 
       
   289 /**
       
   290 Called when the new socket is connected
       
   291 */
       
   292 void CPanRemDevStateReconnectingSocket::AsyncEventCompleteL()
       
   293 	{
       
   294 	if(StateMachine().Status()==KErrNone)
       
   295 		{
       
   296 		LOG1(_L("RemDevState[%x]: <connecting socket> - async event complete, socket connected successfully"), &StateMachine());
       
   297 
       
   298 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   299         StateMachine().CreateNewBnepConnection(StateMachine().Socket(), TPanMessage::EActivityCreateChannelControllerForOutgoing);
       
   300 #else
       
   301 		StateMachine().CreateNewBnepConnectionL(StateMachine().Socket());
       
   302 #endif
       
   303 
       
   304 		StateMachine().OpenPhysicalLinkAdapterL();
       
   305 
       
   306 		CPanRemDevStateBase* nextState = new(ELeave) CPanRemDevStatePerformingRoleNegotiationForOutgoingConnection(StateMachine());
       
   307 
       
   308 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
   309         CleanupStack::PushL(nextState);
       
   310         CPanRemDevStatePaused* pausedState = new(ELeave)CPanRemDevStatePaused(StateMachine(), *nextState);
       
   311         CleanupStack::Pop();
       
   312         nextState = pausedState;
       
   313 #endif
       
   314 
       
   315 		StateMachine().SetState(*nextState);
       
   316 		delete this;
       
   317 		}
       
   318 	else	// did not complete the connection to the remote device...
       
   319 		{
       
   320 		LOG2(_L("RemDevState[%x]: <connecting socket> - socket connect failed with %d"), &StateMachine(), StateMachine().Status().Int());
       
   321 		User::Leave(StateMachine().Status().Int());
       
   322 		}
       
   323 	}	
       
   324 
       
   325 /**
       
   326 Cancel the socket connect
       
   327 */
       
   328 void CPanRemDevStateReconnectingSocket::AsyncEventCancelL()
       
   329 	{
       
   330 	LOG1(_L("RemDevState[%x]: <connecting socket> - async event cancelled"), &StateMachine());
       
   331 	
       
   332 	StateMachine().Socket().CancelConnect();
       
   333 	StateMachine().Socket().Close();
       
   334 	}
       
   335 
       
   336 /**
       
   337 The local device wants us to disconnect
       
   338 */
       
   339 void CPanRemDevStateReconnectingSocket::ShutdownL()
       
   340 	{
       
   341 	LOG1(_L("RemDevState[%x]: <connecting socket> - locally requested disconnect received"), &StateMachine());
       
   342 	
       
   343 	// outstanding async request will be cancelled by state machine when we leave
       
   344 	User::Leave(KErrLocallyInitiatedDisconnect);
       
   345 	}
       
   346 
       
   347 // This returns a distilled (i.e., not the actual remote device state)
       
   348 // version of the current connection status of the remote device
       
   349 TRemoteDeviceState CPanRemDevStateReconnectingSocket::GetState() const
       
   350 	{
       
   351 	return EIdle;
       
   352 	}
       
   353 
       
   354 //
       
   355 // CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForOutgoingConnection
       
   356 //
       
   357 
       
   358 CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForOutgoingConnection::CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForOutgoingConnection(MPanRemDevStateMachineNotify& aStateMachine) :
       
   359 	CPanRemDevStateBase(aStateMachine, EPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForOutgoingConnection)
       
   360 /**
       
   361 
       
   362 */
       
   363 	{	}
       
   364 	
       
   365 void CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForOutgoingConnection::OnEntryL()
       
   366 /**
       
   367 Not much to do here - just waiting for role state machine to become available
       
   368 */
       
   369 	{	
       
   370 	LOG1(_L("RemDevState[%x]: <waiting for role state machine for outgoing connection> - entering state"), &StateMachine());
       
   371 
       
   372 	// do nothing
       
   373 	}
       
   374 	
       
   375 void CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForOutgoingConnection::BnepRoleRequestFromRemoteDeviceL(const TUUID& /*aRequestedLocalRole*/, const TUUID& /*aRequestedRemoteRole*/)
       
   376 /**
       
   377 Oi! We're starting the connection here, so we get to send the role request!
       
   378 */
       
   379 	{
       
   380 	LOG1(_L("RemDevState[%x]: <waiting for role state machine for outgoing connection> - BNEP role request received from remote device - they shouldn't be sending them, we're doing the outgoing connection, disconnecting them"), &StateMachine());
       
   381 
       
   382 	// drop the role request packet that the remote device has incorrectly sent us
       
   383 	}
       
   384 	
       
   385 void CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForOutgoingConnection::BnepRoleResponseFromRemoteDeviceL(TBnepSetupConnectionResponseMessage /*aRoleResponseCode*/)
       
   386 /**
       
   387 Excuse me?  We haven't sent a role request yet, so why are they sending a role response?
       
   388 */
       
   389 	{
       
   390 	LOG1(_L("RemDevState[%x]: <waiting for role state machine for outgoing connection> - BNEP role response received from remote device before we've sent a request - disconnecting them"), &StateMachine());
       
   391 
       
   392 	// drop the role response packet that the remote device has incorrectly sent us
       
   393 	}
       
   394 
       
   395 void CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForOutgoingConnection::RemoteDeviceDisconnectL(TInt aError)
       
   396 /**
       
   397 Remote device has obviously given up waiting for us...
       
   398 */
       
   399 	{
       
   400 	LOG1(_L("RemDevState[%x]: <waiting for role state machine for outgoing connection> - remote device disconnect received, looks like they've given up waiting for us."), &StateMachine());
       
   401 
       
   402 	User::Leave(aError); // will shutdown the connection
       
   403 	}
       
   404 
       
   405 void CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForOutgoingConnection::ReadyForRoleRequestL()
       
   406 /**
       
   407 Ahh, that's the event we've really been waiting for - role state machine has finished dealing with
       
   408 another device and is now ready for our role request
       
   409 */
       
   410 	{
       
   411 	LOG1(_L("RemDevState[%x]: <waiting for role state machine for outgoing connection> - ready for role request received from role state machine"), &StateMachine());
       
   412 
       
   413 	TInt err;
       
   414 	CPanRemDevStateBase* nextState = NULL;
       
   415 	StateMachine().RemoteRole() = EPanRoleUnknown;	// reset this for outgoing connection - we maybe trying a different role now
       
   416 	err = StateMachine().InitiateOutgoingConnection(StateMachine().LocalRole(), StateMachine().RemoteRole(), StateMachine().RemoteWorthTryingRolesList());
       
   417 		
       
   418 	switch(err)
       
   419 		{
       
   420 		case KErrNone:
       
   421 			{
       
   422 			err = PerformMasterSlaveSwitchIfNecessary(StateMachine().LocalRole());
       
   423 			if(err==KErrWaitingForBasebandRoleSwitch)
       
   424 				{
       
   425 				nextState = new(ELeave) CPanRemDevStateWaitingForRoleSwitchForOutgoingConnection(StateMachine());
       
   426 				break;
       
   427 				}
       
   428 			else if(err)
       
   429 				{
       
   430 				LOG1(_L("RemDevState[%x]: <waiting for role state machine for outgoing connection> - ...M/S switch required and failed - disconnecting device."), &StateMachine());
       
   431 				// remote device would not perform role switch (maybe it needs to stay as master for another profile it's using...)
       
   432 				User::Leave(KErrCouldNotBecomePiconetMaster);
       
   433 				return;		
       
   434 				}
       
   435 				
       
   436 			LOG1(_L("RemDevState[%x]: <waiting for role state machine for outgoing connection> - ...M/S switch not required, sending role request."), &StateMachine());
       
   437 
       
   438 			nextState = new(ELeave) CPanRemDevStatePerformingDelayedRoleNegotiationForOutgoingConnection(StateMachine());
       
   439 			break;
       
   440 			}
       
   441 		case KErrLocked:
       
   442 			{
       
   443 			PanicInState(ERoleStateMachineCalledReadyForRoleRequestThenReturnedLocked);
       
   444 			break;
       
   445 			}
       
   446 		case KErrInvalidOrUnacceptableRoleCombination:
       
   447 			{
       
   448 			LOG1(_L("RemDevState[%x]: <waiting for role state machine for outgoing connection> - the roles the remote device proposed were invalid or unacceptable to us, disconnecting them"), &StateMachine());
       
   449 			User::Leave(KErrInvalidOrUnacceptableRoleCombination);
       
   450 			}
       
   451 		default:
       
   452 			{
       
   453 			// if err is something other than KErrNoMemory that might indicate an internal error in the state
       
   454 			// machine, so ASSERT_DEBUG.  We can probably carry on even if the error is unexpected, as leaving
       
   455 			// will cause this connection to shutdown.
       
   456 			__ASSERT_DEBUG(err == KErrNoMemory, PanicInState(EPanAgentRoleStateMachineReturnedUnexpectedErrorCode));
       
   457 			User::Leave(err);
       
   458 			}
       
   459 		}
       
   460 		
       
   461 	__ASSERT_ALWAYS(nextState, PanicInState(ENoNextStateSet));
       
   462 	StateMachine().SetState(*nextState);
       
   463 	delete this;
       
   464 	return;
       
   465 	}
       
   466 
       
   467 void CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForOutgoingConnection::ShutdownL()
       
   468 /**
       
   469 Local device wants us to disconnect
       
   470 */
       
   471 	{
       
   472 	LOG1(_L("RemDevState[%x]: <waiting for role state machine for outgoing connection> - locally requested disconnect received"), &StateMachine());
       
   473 
       
   474 	User::Leave(KErrLocallyInitiatedDisconnect); // disconnect the remote device
       
   475 	}
       
   476 
       
   477 // This returns a distilled (i.e., not the actual remote device state)
       
   478 // version of the current connection status of the remote device
       
   479 TRemoteDeviceState CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForOutgoingConnection::GetState() const
       
   480 	{
       
   481 	return EPendingNegotiation;
       
   482 	}
       
   483 	
       
   484 //
       
   485 // CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingConnection
       
   486 //
       
   487 
       
   488 CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingConnection::CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingConnection(MPanRemDevStateMachineNotify& aStateMachine) :
       
   489 	CPanRemDevStateBase(aStateMachine, EPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingConnection)
       
   490 /**
       
   491 
       
   492 */
       
   493 	{	}
       
   494 
       
   495 CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingConnection::CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingConnection(MPanRemDevStateMachineNotify& aStateMachine, TPanRemDevStates aStateNumber) :
       
   496 	CPanRemDevStateBase(aStateMachine, aStateNumber)
       
   497 /**
       
   498 When implementing a new state that derives from this base class, ensure that
       
   499 it provides a unique number to identify the state from other possible
       
   500 states.  @see PanAgent::TPanAgtStates.
       
   501 */
       
   502 	{	}
       
   503 	
       
   504 void CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingConnection::OnEntryL()
       
   505 /**
       
   506 Not much to do here - just waiting for role state machine to become available
       
   507 */
       
   508 	{	
       
   509 	LOG1(_L("RemDevState[%x]: <waiting for role state machine for incoming connection> - entering state"), &StateMachine());
       
   510 
       
   511 	// do nothing
       
   512 	}
       
   513 	
       
   514 void CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingConnection::BnepRoleRequestFromRemoteDeviceL(const TUUID& /*aRequestedLocalRole*/, const TUUID& /*aRequestedRemoteRole*/)
       
   515 /**
       
   516 
       
   517 */
       
   518 	{
       
   519 	LOG1(_L("RemDevState[%x]: <waiting for role state machine for incoming connection> - BNEP role request received from remote device, still can't do anything with it until we get access to the role state machine"), &StateMachine());
       
   520 
       
   521 	// drop resent role request
       
   522 	}
       
   523 	
       
   524 void CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingConnection::BnepRoleResponseFromRemoteDeviceL(TBnepSetupConnectionResponseMessage /*aRoleResponseCode*/)
       
   525 /**
       
   526 @note Shouldn't be called for incoming connections, as they should be sending requests, not responses
       
   527 */
       
   528 	{
       
   529 	LOG1(_L("RemDevState[%x]: <waiting for role state machine for incoming connection> - BNEP role response received from remote device, what are they up to?  They should be sending requests and we should be sending responses, disconnecting them"), &StateMachine());
       
   530 
       
   531 	// drop the role response packet that the remote device has incorrectly sent us
       
   532 	}
       
   533 
       
   534 void CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingConnection::RemoteDeviceDisconnectL(TInt aError)
       
   535 /**
       
   536 Remote device has obviously given up waiting for us...
       
   537 */
       
   538 	{
       
   539 	LOG1(_L("RemDevState[%x]: <waiting for role state machine for incoming connection> - remote device disconnect received, looks like they've given up waiting for us."), &StateMachine());
       
   540 
       
   541 	User::Leave(aError); // will shutdown the connection
       
   542 	}
       
   543 
       
   544 void CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingConnection::ReadyForRoleRequestL()
       
   545 /**
       
   546 Ahh, that's the event we've really been waiting for - role state machine has finished dealing with
       
   547 another device and is now ready for our role request
       
   548 */
       
   549 	{
       
   550 	LOG1(_L("RemDevState[%x]: <waiting for role state machine for incoming connection> - ready for role request received from role state machine"), &StateMachine());
       
   551 
       
   552 	TInt err;
       
   553 	CPanRemDevStateBase* nextState = NULL;
       
   554 	err = StateMachine().IncomingConnectionFromPeer(StateMachine().LocalRole(), StateMachine().RemoteRole());
       
   555 
       
   556 	switch(err)
       
   557 		{
       
   558 		case KErrNone:
       
   559 			{
       
   560 			err = PerformMasterSlaveSwitchIfNecessary(StateMachine().LocalRole());
       
   561 			if(err==KErrWaitingForBasebandRoleSwitch)
       
   562 				{
       
   563 				nextState = new(ELeave) CPanRemDevStateWaitingForRoleSwitchForIncomingConnection(StateMachine());
       
   564 				break;
       
   565 				}
       
   566 			else if(err)
       
   567 				{
       
   568 				LOG1(_L("RemDevState[%x]: <waiting for role state machine for incoming connection> - ...M/S switch required and failed - disconnecting device."), &StateMachine());
       
   569 				// remote device would not perform role switch (maybe it needs to stay as master for another profile it's using...)
       
   570 				StateMachine().SendRoleResponse(EConnectionNotAllowed);
       
   571 				User::Leave(KErrCouldNotBecomePiconetMaster);
       
   572 				return;		
       
   573 				}
       
   574 				
       
   575 			LOG1(_L("RemDevState[%x]: <waiting for role state machine for incoming connection> - ...M/S switch not required, sending successful connect response."), &StateMachine());
       
   576 			StateMachine().SendRoleResponse(EOperationSuccessful);
       
   577 
       
   578  			nextState = new(ELeave) CPanRemDevStateIncomingNotification(StateMachine());
       
   579 			break;
       
   580 			}
       
   581 		case KErrLocked:
       
   582 			{
       
   583 			PanicInState(ERoleStateMachineCalledReadyForRoleRequestThenReturnedLocked);
       
   584 			break;
       
   585 			}
       
   586 
       
   587 		default:
       
   588 			{
       
   589 			// An error has occured.  Send a -ve role response and disconnect.
       
   590 			LOG2(_L("RemDevState[%x]: <waiting for role state machine for incoming connection> - Fail with error [%d].  Disconnecting peer"), &StateMachine(), err);
       
   591 			StateMachine().SendRoleResponse(EConnectionNotAllowed);
       
   592 			User::Leave(err);
       
   593 			}
       
   594 		}
       
   595 	__ASSERT_ALWAYS(nextState, PanicInState(ENoNextStateSet));
       
   596 	StateMachine().SetState(*nextState);
       
   597 	delete this;
       
   598 	return;
       
   599 	}
       
   600 
       
   601 void CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingConnection::ShutdownL()
       
   602 /**
       
   603 Local device wants us to disconnect
       
   604 */
       
   605 	{
       
   606 	LOG1(_L("RemDevState[%x]: <waiting for role state machine for incoming connection> - locally requested disconnect received"), &StateMachine());
       
   607 
       
   608 	// tell the other end that we're disconnecting
       
   609 	StateMachine().SendRoleResponse(EConnectionNotAllowed);
       
   610 	// and then disconnect the remote device
       
   611 	User::Leave(KErrLocallyInitiatedDisconnect); 
       
   612 	}
       
   613 
       
   614 // This returns a distilled (i.e., not the actual remote device state)
       
   615 // version of the current connection status of the remote device
       
   616 TRemoteDeviceState CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingConnection::GetState() const
       
   617 	{
       
   618 	return EPendingNegotiation;
       
   619 	}
       
   620 
       
   621 //
       
   622 // CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingRoleChangeRequest
       
   623 //
       
   624 
       
   625 CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingRoleChangeRequest::CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingRoleChangeRequest(MPanRemDevStateMachineNotify& aStateMachine, TBluetoothPanRole aPendingLocalRole, TBluetoothPanRole aPendingRemoteRole)
       
   626   : CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingConnection(aStateMachine, EPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingRoleChangeRequest),
       
   627 	iPendingLocalRole(aPendingLocalRole),
       
   628 	iPendingRemoteRole(aPendingRemoteRole)
       
   629 /**
       
   630 
       
   631 */
       
   632 	{	}
       
   633 	
       
   634 void CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingRoleChangeRequest::OnEntryL()
       
   635 /**
       
   636 Not much to do here - just waiting for role state machine to become available
       
   637 */
       
   638 	{	
       
   639 	LOG1(_L("RemDevState[%x]: <waiting for role state machine for incoming role change request> - entering state"), &StateMachine());
       
   640 
       
   641 	// do nothing
       
   642 	}
       
   643 	
       
   644 void CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingRoleChangeRequest::ReadyForRoleRequestL()
       
   645 /**
       
   646 Ahh, that's the event we've really been waiting for - role state machine has finished dealing with
       
   647 another device and is now ready for our role request
       
   648 */
       
   649 	{
       
   650 	LOG1(_L("RemDevState[%x]: <waiting for role state machine for incoming role change request> - ready for role request received from role state machine"), &StateMachine());
       
   651 
       
   652 	TInt err;
       
   653 	CPanRemDevStateBase* nextState = NULL;
       
   654 	err = StateMachine().RoleChangeRequestFromPeer(iPendingLocalRole, iPendingRemoteRole);
       
   655 	switch(err)
       
   656 		{
       
   657 		case KErrNone:
       
   658 			{
       
   659 			err = PerformMasterSlaveSwitchIfNecessary(iPendingLocalRole);
       
   660 			if(err==KErrWaitingForBasebandRoleSwitch)
       
   661 				{
       
   662 				nextState = new(ELeave) CPanRemDevStateWaitingForRoleSwitchForIncomingRoleChangeRequest(StateMachine(), iPendingLocalRole, iPendingRemoteRole);
       
   663 				break;
       
   664 				}
       
   665 			else if(err)
       
   666 				{
       
   667 				LOG1(_L("RemDevState[%x]: <waiting for role state machine for incoming role change request> - ...M/S switch required and failed - disconnecting device."), &StateMachine());
       
   668 				// remote device would not perform role switch (maybe it needs to stay as master for another profile it's using...)
       
   669 				StateMachine().SendRoleResponse(EConnectionNotAllowed);
       
   670 				StateMachine().RoleChangeFailed();
       
   671 				nextState = new(ELeave) CPanRemDevStateActive(StateMachine());
       
   672 				break;
       
   673 				}
       
   674 				
       
   675 			LOG1(_L("RemDevState[%x]: <waiting for role state machine for incoming role change request> - ...M/S switch not required, sending successful connect response."), &StateMachine());
       
   676 			StateMachine().SendRoleResponse(EOperationSuccessful);
       
   677 
       
   678 			// Store the new roles
       
   679 			StateMachine().LocalRole() = iPendingLocalRole;
       
   680 			StateMachine().RemoteRole() = iPendingRemoteRole;
       
   681 
       
   682 			// Changing role from GN/NAP to U.  If this connection previously had access to the
       
   683 			// uplink this should be revoked.
       
   684 			if(StateMachine().LocalRole() == EPanRoleU)
       
   685 				{
       
   686 				StateMachine().SetUplinkAccessAllowed(EFalse);
       
   687 				}
       
   688 
       
   689 			nextState = new(ELeave) CPanRemDevStateActive(StateMachine());
       
   690 			break;
       
   691 			}
       
   692 		case KErrLocked:
       
   693 			{
       
   694 			PanicInState(ERoleStateMachineCalledReadyForRoleRequestThenReturnedLocked);
       
   695 			break;
       
   696 			}
       
   697 		case KErrInvalidOrUnacceptableRoleCombination:
       
   698 			{
       
   699 			LOG1(_L("RemDevState[%x]: <waiting for role state machine for incoming role change request> - the roles the remote device proposed were invalid or unacceptable to us, signalling failure and going to active state"), &StateMachine());
       
   700 			StateMachine().SendRoleResponse(EConnectionNotAllowed);
       
   701 			nextState = new(ELeave) CPanRemDevStateActive(StateMachine());
       
   702 			break;
       
   703 			}
       
   704 		default:
       
   705 			{
       
   706 			// if err is something other than KErrNoMemory that might indicate an internal error in the state
       
   707 			// machine, so ASSERT_DEBUG.  We can probably carry on even if the error is unexpected, as leaving
       
   708 			// will cause this connection to shutdown.
       
   709 			__ASSERT_DEBUG(err == KErrNoMemory, PanicInState(EPanAgentRoleStateMachineReturnedUnexpectedErrorCode));
       
   710 			User::Leave(err);
       
   711 			}
       
   712 		}
       
   713 	__ASSERT_ALWAYS(nextState, PanicInState(ENoNextStateSet));
       
   714 	StateMachine().SetState(*nextState);
       
   715 	delete this;
       
   716 	return;	
       
   717 	}
       
   718 
       
   719 //
       
   720 // CPanRemDevStatePerformingRoleNegotiationForOutgoingBase
       
   721 //
       
   722 
       
   723 CPanRemDevStatePerformingRoleNegotiationForOutgoingBase::CPanRemDevStatePerformingRoleNegotiationForOutgoingBase(MPanRemDevStateMachineNotify& aStateMachine, TPanRemDevStates aStateNumber) :
       
   724 	CPanRemDevStateBase(aStateMachine, aStateNumber), iRetries(KMaxBnepNegotiationCyles)
       
   725 /**
       
   726 
       
   727 */
       
   728 	{	}
       
   729 
       
   730 void CPanRemDevStatePerformingRoleNegotiationForOutgoingBase::BnepRoleRequestFromRemoteDeviceL(const TUUID& /*aRequestedLocalRole*/, const TUUID& /*aRequestedRemoteRole*/)
       
   731 /**
       
   732 Something's gone wrong - we were expecting a response from the remote device - not a request. 
       
   733 Not sure this can/should occur - I think the spec implies that only the initiating device can send role requests.
       
   734 */
       
   735 	{
       
   736 	LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - BNEP role request from remote device received - what are they doing?  We're supposed to be sending the role requests."), &StateMachine());
       
   737 
       
   738 	// drop the role request packet that the remote device has incorrectly sent us
       
   739 	}
       
   740 	
       
   741 void CPanRemDevStatePerformingRoleNegotiationForOutgoingBase::BnepRoleResponseFromRemoteDeviceL(TBnepSetupConnectionResponseMessage aRoleResponseCode)
       
   742 /**
       
   743 Woohoo! Our role response has arrived.
       
   744 */
       
   745 	{
       
   746 	LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - BNEP role response from remote device received, processing response..."), &StateMachine());
       
   747 
       
   748 	StateMachine().Cancel();
       
   749 	
       
   750 	CPanRemDevStateBase* nextState = NULL;
       
   751 	switch(aRoleResponseCode)
       
   752 		{
       
   753 		case EOperationSuccessful:
       
   754 			{
       
   755 			LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - ...operation successful, setting device active."), &StateMachine());
       
   756 			StateMachine().ResetConnectionRetryAttempts(); // reset the connection retry attempts
       
   757 			StateMachine().ResetRetryParameters(); // clears the triedpanu... type flags incase we want to reconnect later
       
   758 			nextState = DoRoleNegotiationSuccessL();
       
   759 			break;
       
   760 			}
       
   761 		case EConnectionNotAllowed:
       
   762 			{	
       
   763 			LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - ...operation failed, connection not allowed"), &StateMachine());
       
   764 			TInt retries = StateMachine().IncrementConnectionRetryAttempts();
       
   765 			// There is a race condition in some PC stacks that can bring us to this point when it shouldn't, so we retry the connection
       
   766 			if (retries<KPanAgtConnectionRetryAttempts) 
       
   767 				{
       
   768 				LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - ...operation failed, connection not allowed - retrying connection"), &StateMachine());
       
   769 				StateMachine().ResetRetryParameters(); // This feeds all the way back so we recalculate the role parameters just the same as we did last time
       
   770 				nextState = new(ELeave) CPanRemDevStateReconnectingSocket(StateMachine());
       
   771 			
       
   772 				// if the state has left, then it won't have performed the setup of the next state correctly
       
   773 				// this code performs the same actions to cleanup the old state and activate the new, but in
       
   774 				// reverse order - otherwise we'd lose the pointer to the old state when we activated the new
       
   775 				}
       
   776 			/* the intention is to allow the retrys required by the PC stacks above
       
   777 			   then if it's worth retrying (we can try new roles) we will
       
   778 			   This is particularly useful when we don't have sdp records to suggest
       
   779 			   what we should do
       
   780 			 */				
       
   781 			else if (StateMachine().WorthTrying())
       
   782 				{
       
   783 				// if we've still not made a successful connection then we can have a quick try
       
   784 				// at connecting using different remote roles
       
   785 				LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - ...operation failed, connection not allowed - retrying connection with different roles"), &StateMachine());
       
   786 				nextState = new(ELeave) CPanRemDevStateReconnectingSocket(StateMachine());
       
   787 			
       
   788 				// if the state has left, then it won't have performed the setup of the next state correctly
       
   789 				// this code performs the same actions to cleanup the old state and activate the new, but in
       
   790 				// reverse order - otherwise we'd lose the pointer to the old state when we activated the new
       
   791 				}
       
   792 			else 
       
   793 				{
       
   794 				LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - ...operation failed, connection not allowed"), &StateMachine());
       
   795 				LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - ...operation failed, unrecognised response code, shutting down"), &StateMachine());
       
   796 				StateMachine().ResetConnectionRetryAttempts(); // reset the connection retry attempts
       
   797 				StateMachine().ResetRetryParameters(); // clears the triedpanu... type flags incase we want to try connect later
       
   798 				nextState = DoRoleNegotiationFailureL(KErrCouldNotConnect);
       
   799 				}
       
   800 			break;
       
   801 			}
       
   802 		default:
       
   803 			{			
       
   804 			// this nested switch avoids the old multiple logging lines which was really nasty
       
   805 			switch(aRoleResponseCode)
       
   806 				{
       
   807 				case EInvalidDestinationServiceUuid:	// we've tried to negotiate roles that are unsuitable
       
   808 					{
       
   809 					LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - ...operation failed, invalid destination service UUID"), &StateMachine());
       
   810 					break;
       
   811 					}
       
   812 				case EInvalidSourceServiceUuid:
       
   813 					{
       
   814 					LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - ...operation failed, invalid source service UUID"), &StateMachine());
       
   815 					break;
       
   816 					}
       
   817 				case EInvalidServiceUuidSize:
       
   818 					{
       
   819 					LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - ...operation failed, invalid UUID size"), &StateMachine());
       
   820 					break;
       
   821 					}
       
   822 				default:
       
   823 					{
       
   824 					LOG2(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - ...operation failed, unrecognised response code (%x),  shutting down"), &StateMachine(),aRoleResponseCode);
       
   825 					break;
       
   826 					}
       
   827 				}
       
   828 			StateMachine().ResetConnectionRetryAttempts(); // reset the connection retry attempts
       
   829 			StateMachine().ResetRetryParameters(); // clears the triedpanu... type flags incase we want to try connect later
       
   830 			nextState = DoRoleNegotiationFailureL(KErrCouldNotConnect);
       
   831 			break;	
       
   832 			}
       
   833 		}
       
   834 	__ASSERT_ALWAYS(nextState, PanicInState(ENoNextStateSet));
       
   835 	StateMachine().SetState(*nextState);
       
   836 	delete this;
       
   837 	return;
       
   838 	}
       
   839 	
       
   840 void CPanRemDevStatePerformingRoleNegotiationForOutgoingBase::RemoteDeviceDisconnectL(TInt aError)
       
   841 /**
       
   842 Remote device has disconnected.
       
   843 */
       
   844 	{
       
   845 	LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - remote device disconnect received, looks like our requests weren't acceptable, or they just gave up"), &StateMachine());
       
   846 
       
   847 	// outstanding async request will be cancelled by state machine when we leave
       
   848 	User::Leave(aError); // will shutdown the connection
       
   849 	}	
       
   850 
       
   851 void CPanRemDevStatePerformingRoleNegotiationForOutgoingBase::ShutdownL()
       
   852 /**
       
   853 Local device wants us to disconnect
       
   854 */
       
   855 	{
       
   856 	LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - locally requested disconnect received"), &StateMachine());
       
   857 	
       
   858 	// outstanding async request will be cancelled by state machine when we leave
       
   859 	User::Leave(KErrLocallyInitiatedDisconnect); // will shutdown the connection
       
   860 	}
       
   861 	
       
   862 void CPanRemDevStatePerformingRoleNegotiationForOutgoingBase::AsyncEventCompleteL()
       
   863 /**
       
   864 Timer completion
       
   865 */
       
   866 	{
       
   867 	--iRetries;
       
   868 
       
   869 	LOG2(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - async event complete, looks like the timer triggered before they responded.  %d retries remaining..."), &StateMachine(), iRetries);
       
   870 
       
   871 	if(iRetries==0)
       
   872 		{
       
   873 		LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - ...disconnecting."), &StateMachine());
       
   874 		CPanRemDevStateBase* nextState = DoRoleNegotiationFailureL(KErrRemoteDeviceFailedToRespondToRoleRequests);
       
   875 		StateMachine().SetState(*nextState);
       
   876 		delete this;
       
   877 		return;
       
   878 		}
       
   879 	else	// resend the role request, and start the timer running again
       
   880 		{
       
   881 		LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - ...retrying."), &StateMachine());
       
   882 		StateMachine().SendRoleRequest(StateMachine().LocalRole(), StateMachine().RemoteRole());
       
   883 		iTimer.After(StateMachine().Status(), KMaxTimeToWaitForRoleResponse);
       
   884 		StateMachine().SetActive();
       
   885 		}
       
   886 	}
       
   887 	
       
   888 void CPanRemDevStatePerformingRoleNegotiationForOutgoingBase::AsyncEventCancelL()
       
   889 /**
       
   890 Timer cancel
       
   891 @note Typically it will be this state that cancels the async event (timer in this case) when we decide we don't need it any longer
       
   892 */
       
   893 	{
       
   894 	LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation [base]> - async event cancelled, cancelling timer"), &StateMachine());
       
   895 
       
   896 	iTimer.Cancel();
       
   897 	iTimer.Close();
       
   898 	}
       
   899 
       
   900 // This returns a distilled (i.e., not the actual remote device state)
       
   901 // version of the current connection status of the remote device
       
   902 TRemoteDeviceState CPanRemDevStatePerformingRoleNegotiationForOutgoingBase::GetState() const
       
   903 	{
       
   904 	return EPerformingNegotiation;
       
   905 	}
       
   906 	
       
   907 //
       
   908 // CPanRemDevStatePerformingRoleNegotiationForOutgoingConnection
       
   909 //
       
   910 
       
   911 CPanRemDevStatePerformingRoleNegotiationForOutgoingConnection::CPanRemDevStatePerformingRoleNegotiationForOutgoingConnection(MPanRemDevStateMachineNotify& aStateMachine) :
       
   912 	CPanRemDevStatePerformingRoleNegotiationForOutgoingBase(aStateMachine, EPanRemDevStatePerformingRoleNegotiationForOutgoingConnection)
       
   913 /**
       
   914 
       
   915 */
       
   916 	{	}
       
   917 
       
   918 CPanRemDevStatePerformingRoleNegotiationForOutgoingConnection::CPanRemDevStatePerformingRoleNegotiationForOutgoingConnection(MPanRemDevStateMachineNotify& aStateMachine, TPanRemDevStates aStateNumber) :
       
   919 	CPanRemDevStatePerformingRoleNegotiationForOutgoingBase(aStateMachine, aStateNumber)
       
   920 /**
       
   921 When implementing a new state that derives from this base class, ensure that
       
   922 it provides a unique number to identify the state from other possible
       
   923 states.  @see PanAgent::TPanAgtStates.
       
   924 */
       
   925 	{	}
       
   926 
       
   927 void CPanRemDevStatePerformingRoleNegotiationForOutgoingConnection::OnEntryL()
       
   928 /**
       
   929 Send the role request to the remote device
       
   930 */
       
   931 	{
       
   932 	LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation> - entering state"), &StateMachine());
       
   933 	
       
   934 	User::LeaveIfError(iTimer.CreateLocal());
       
   935 		
       
   936 	TInt err;	
       
   937 	CPanRemDevStateBase* nextState = NULL;
       
   938 	StateMachine().RemoteRole() = EPanRoleUnknown;	// reset this for outgoing connection - we maybe trying a different role now
       
   939 	err = StateMachine().InitiateOutgoingConnection(StateMachine().LocalRole(), StateMachine().RemoteRole(), StateMachine().RemoteWorthTryingRolesList());
       
   940 
       
   941 	switch(err)
       
   942 		{
       
   943 		case KErrNone:
       
   944 			{
       
   945 			LOG3(_L("RemDevState[%x]: <performing outgoing role negotiation> - role state machine changed our proposed role; now local: %x, remote: %x"), &StateMachine(), StateMachine().LocalRole(), StateMachine().RemoteRole());
       
   946 			err = PerformMasterSlaveSwitchIfNecessary(StateMachine().LocalRole());
       
   947 			
       
   948 			if(err==KErrWaitingForBasebandRoleSwitch)
       
   949 				{
       
   950 				nextState = new(ELeave) CPanRemDevStateWaitingForRoleSwitchForOutgoingConnection(StateMachine());
       
   951 				break;
       
   952 				}
       
   953 			else if(err)
       
   954 				{
       
   955 				LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation> - ...M/S switch required and failed - disconnecting device."), &StateMachine());
       
   956 				// remote device would not perform role switch (maybe it needs to stay as master for another profile it's using...)
       
   957 				User::Leave(KErrCouldNotBecomePiconetMaster);
       
   958 				return;		
       
   959 				}
       
   960 				
       
   961 			StateMachine().SendRoleRequest(StateMachine().LocalRole(), StateMachine().RemoteRole());
       
   962 			iTimer.After(StateMachine().Status(), KMaxTimeToWaitForRoleResponse);
       
   963 			StateMachine().SetActive();
       
   964 			return;
       
   965 			}
       
   966 		case KErrLocked:	// someone else is negotiating, so go to the wait state
       
   967 			{
       
   968 			LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation> - role state machine busy, waiting for notification of its availability"), &StateMachine());
       
   969 			nextState = new(ELeave) CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForOutgoingConnection(StateMachine());
       
   970 			break;
       
   971 			}
       
   972 
       
   973 		case KErrInvalidOrUnacceptableRoleCombination:
       
   974 			LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation> - this state generated and proposed an illegal role combination"), &StateMachine());
       
   975 			// fall through
       
   976 			
       
   977 		default:
       
   978 			LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation> - unexpected response from role state machine"), &StateMachine());
       
   979 			// if err is something other than KErrNoMemory that might indicate an internal error in the state
       
   980 			// machine, so ASSERT_DEBUG.  We can probably carry on even if the error is unexpected, as leaving
       
   981 			// will cause this connection to shutdown.
       
   982 			User::Leave(err);
       
   983 		}
       
   984 		
       
   985 	__ASSERT_ALWAYS(nextState, PanicInState(ENoNextStateSet));
       
   986 	StateMachine().SetState(*nextState);
       
   987 	delete this;
       
   988 	return;
       
   989 	}
       
   990 
       
   991 CPanRemDevStateBase* CPanRemDevStatePerformingRoleNegotiationForOutgoingConnection::DoRoleNegotiationSuccessL()
       
   992 /**
       
   993 Role negotiation succeeded, tell role state machine and go to active state
       
   994 */
       
   995 	{
       
   996 	LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation> - role negotiation succeeded, going to active state"), &StateMachine());
       
   997 
       
   998 	CPanRemDevStateBase* nextState = new(ELeave) CPanRemDevStateActive(StateMachine());
       
   999 	return nextState;
       
  1000 	}
       
  1001 	
       
  1002 CPanRemDevStateBase* CPanRemDevStatePerformingRoleNegotiationForOutgoingConnection::DoRoleNegotiationFailureL(TInt aError)
       
  1003 /**
       
  1004 Role negotiation failed, disconnect
       
  1005 */
       
  1006 	{
       
  1007 	LOG1(_L("RemDevState[%x]: <performing outgoing role negotiation> - role negotiation failed, shutting down connection"), &StateMachine());
       
  1008 	User::Leave(aError);
       
  1009 	return NULL;	// will never be reached	
       
  1010 	}
       
  1011 		
       
  1012 //
       
  1013 // CPanRemDevStatePerformingRoleNegotiationForIncomingConnection
       
  1014 //
       
  1015 
       
  1016 CPanRemDevStatePerformingRoleNegotiationForIncomingConnection::CPanRemDevStatePerformingRoleNegotiationForIncomingConnection(MPanRemDevStateMachineNotify& aStateMachine) :
       
  1017 	CPanRemDevStateBase(aStateMachine, EPanRemDevStatePerformingRoleNegotiationForIncomingConnection)
       
  1018 /**
       
  1019 
       
  1020 */
       
  1021 	{	}
       
  1022 
       
  1023 void CPanRemDevStatePerformingRoleNegotiationForIncomingConnection::OnEntryL()
       
  1024 /**
       
  1025 
       
  1026 */
       
  1027 	{
       
  1028 	LOG1(_L("RemDevState[%x]: <performing incoming role negotiation> - entering state"), &StateMachine());
       
  1029 
       
  1030 	// do nothing - just wait for incoming role request
       
  1031 	}
       
  1032 
       
  1033 void CPanRemDevStatePerformingRoleNegotiationForIncomingConnection::BnepRoleRequestFromRemoteDeviceL(const TUUID& aRequestedLocalRole, const TUUID& aRequestedRemoteRole)
       
  1034 /**
       
  1035 This is what we're waiting for...
       
  1036 */
       
  1037 	{
       
  1038 //	LOG1(_L("RemDevState[%x]: <performing incoming role negotiation> - BNEP role request from remote device, they propose local: %S, remote: %S"), &StateMachine(), (aRequestedLocalRole.ShortestForm()), (aRequestedRemoteRole.ShortestForm()));
       
  1039 
       
  1040 	TInt err;
       
  1041 	CPanRemDevStateBase* nextState = NULL;
       
  1042 	
       
  1043 	TBluetoothPanRole localRole;
       
  1044 	TBluetoothPanRole remoteRole;
       
  1045 	ConvertUuidsToPanRolesL(aRequestedLocalRole, aRequestedRemoteRole, localRole, remoteRole); // will send response to remote device and shutdown the connection if there is an error
       
  1046 
       
  1047 	LOG1(_L("RemDevState[%x]: <performing incoming role negotiation> - checking role request..."), &StateMachine());
       
  1048 
       
  1049 	err = StateMachine().IncomingConnectionFromPeer(localRole, remoteRole);
       
  1050 
       
  1051 	// store the requested roles, so the next state knows what was asked for
       
  1052 	StateMachine().LocalRole() = localRole;
       
  1053 	StateMachine().RemoteRole() = remoteRole;
       
  1054 
       
  1055 	switch(err)
       
  1056 		{
       
  1057 		case KErrNone:
       
  1058 			{
       
  1059 			LOG1(_L("RemDevState[%x]: <performing incoming role negotiation> - ...successful, checking to see if M/S switch necessary..."), &StateMachine());
       
  1060 
       
  1061 			err = PerformMasterSlaveSwitchIfNecessary(localRole);
       
  1062 			if(err==KErrWaitingForBasebandRoleSwitch)
       
  1063 				{
       
  1064 				nextState = new(ELeave) CPanRemDevStateWaitingForRoleSwitchForIncomingConnection(StateMachine());
       
  1065 				break;
       
  1066 				}
       
  1067 			else if(err)
       
  1068 				{
       
  1069 				LOG1(_L("RemDevState[%x]: <performing incoming role negotiation> - ...M/S switch required and failed - disconnecting device."), &StateMachine());
       
  1070 				// remote device would not perform role switch (maybe it needs to stay as master for another profile it's using...)
       
  1071 				StateMachine().SendRoleResponse(EConnectionNotAllowed);
       
  1072 				User::Leave(KErrCouldNotBecomePiconetMaster);
       
  1073 				return;		
       
  1074 				}
       
  1075 				
       
  1076 			LOG1(_L("RemDevState[%x]: <performing incoming role negotiation> - ...M/S switch not required, sending successful connect response."), &StateMachine());
       
  1077 			StateMachine().SendRoleResponse(EOperationSuccessful);
       
  1078 
       
  1079 			// Check if the incoming notifier is required.
       
  1080  			nextState = new(ELeave) CPanRemDevStateIncomingNotification(StateMachine());
       
  1081 			break;
       
  1082 			}
       
  1083 		case KErrLocked:
       
  1084 			{
       
  1085 			LOG1(_L("RemDevState[%x]: <performing incoming role negotiation> - ...role state machine busy, waiting."), &StateMachine());
       
  1086 			// and create the "waiting" state
       
  1087 			nextState = new (ELeave) CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingConnection(StateMachine());
       
  1088 			break;
       
  1089 			}
       
  1090 
       
  1091 		default:
       
  1092 			{
       
  1093 			// An error has occured.  Send a -ve role response and disconnect.
       
  1094 			LOG2(_L("RemDevState[%x]: <CPanRemDevStatePerformingRoleNegotiationForIncomingConnection> - Fail with error [%d].  Disconnecting peer"), &StateMachine(), err);
       
  1095 			StateMachine().SendRoleResponse(EConnectionNotAllowed);
       
  1096 			User::Leave(err);
       
  1097 			}
       
  1098 		}
       
  1099 	
       
  1100 	__ASSERT_ALWAYS(nextState, PanicInState(ENoNextStateSet));
       
  1101 	StateMachine().SetState(*nextState);
       
  1102 	delete this;
       
  1103 	}
       
  1104 	
       
  1105 void CPanRemDevStatePerformingRoleNegotiationForIncomingConnection::BnepRoleResponseFromRemoteDeviceL(TBnepSetupConnectionResponseMessage /*aRoleResponseCode*/)
       
  1106 /**
       
  1107 Something's gone wrong - we were expecting a request from the remote device - not a response.
       
  1108 */
       
  1109 	{
       
  1110 	LOG1(_L("RemDevState[%x]: <performing incoming role negotiation> - BNEP role reponse from remote device - what are they up to?  They're supposed to be sending the role request."), &StateMachine());
       
  1111 	
       
  1112 	// drop the role response packet that the remote device has incorrectly sent us
       
  1113 	}
       
  1114 	
       
  1115 void CPanRemDevStatePerformingRoleNegotiationForIncomingConnection::RemoteDeviceDisconnectL(TInt aError)
       
  1116 /**
       
  1117 Remote device has disconnected
       
  1118 */
       
  1119 	{
       
  1120 	LOG1(_L("RemDevState[%x]: <performing incoming role negotiation> - remote device disconnect received, they've obviously given up talking to us."), &StateMachine());
       
  1121 
       
  1122 	User::Leave(aError); // will shutdown the connection
       
  1123 	}
       
  1124 	
       
  1125 void CPanRemDevStatePerformingRoleNegotiationForIncomingConnection::ShutdownL()
       
  1126 /**
       
  1127 Local device wants us to disconnect
       
  1128 */
       
  1129 	{
       
  1130 	LOG1(_L("RemDevState[%x]: <performing incoming role negotiation> - locally requested disconnect received"), &StateMachine());
       
  1131 
       
  1132 	User::Leave(KErrLocallyInitiatedDisconnect); // will shutdown the connection
       
  1133 	}
       
  1134 
       
  1135 // This returns a distilled (i.e., not the actual remote device state)
       
  1136 // version of the current connection status of the remote device
       
  1137 TRemoteDeviceState CPanRemDevStatePerformingRoleNegotiationForIncomingConnection::GetState() const
       
  1138 	{
       
  1139 	return EPerformingNegotiation;
       
  1140 	}
       
  1141 
       
  1142 //
       
  1143 // CPanRemDevStatePerformingRoleNegotiationForOutgoingRoleChange
       
  1144 //
       
  1145 
       
  1146 CPanRemDevStatePerformingRoleNegotiationForOutgoingRoleChange::CPanRemDevStatePerformingRoleNegotiationForOutgoingRoleChange(MPanRemDevStateMachineNotify& aStateMachine) :
       
  1147 	CPanRemDevStatePerformingRoleNegotiationForOutgoingBase(aStateMachine, EPanRemDevStatePerformingRoleNegotiationForOutgoingRoleChange)
       
  1148 /**
       
  1149 
       
  1150 */
       
  1151 	{	}
       
  1152 
       
  1153 void CPanRemDevStatePerformingRoleNegotiationForOutgoingRoleChange::OnEntryL()
       
  1154 	{
       
  1155 	LOG1(_L("RemDevState[%x]: <performing role negotiation for outgoing role change> - entering state"), &StateMachine());
       
  1156 
       
  1157 	User::LeaveIfError(iTimer.CreateLocal());
       
  1158 
       
  1159 	// It may appear as though we ought to do a new SDP query, rather than relying on a potentially
       
  1160 	// stale one, but in reality if we're being asked to renegotiate, then the roles are pretty much 
       
  1161 	// going to be known by the role state machine, so we just ask it
       
  1162 	TInt err = StateMachine().PerformLocalRoleChangeRequest(StateMachine().LocalRole(), StateMachine().RemoteRole());
       
  1163 	switch(err)
       
  1164 		{
       
  1165 		case KErrNone:
       
  1166 			{
       
  1167 			LOG3(_L("RemDevState[%x]: <performing role negotiation for outgoing role change> - role state machine changed our proposed role; now local: %x, remote: %x"), &StateMachine(), StateMachine().LocalRole(), StateMachine().RemoteRole());
       
  1168 
       
  1169 			// send the role request and wait for a response first, so the remote device 
       
  1170 			// understands that we're trying to role switch the baseband because we want to be GN/NAP,
       
  1171 			// and releases their piconet master lock
       
  1172 			StateMachine().SendRoleRequest(StateMachine().LocalRole(), StateMachine().RemoteRole());
       
  1173 							
       
  1174 			// start waiting for the role response
       
  1175 			iTimer.After(StateMachine().Status(), KMaxTimeToWaitForRoleResponse);
       
  1176 			StateMachine().SetActive();
       
  1177 			return;
       
  1178 			}
       
  1179 		case KErrLocked:
       
  1180 		// this must not happen - if the state machine requests that we renegotiate, then it needs to be ready for us
       
  1181 			{
       
  1182 			PanicInState(ERoleStateMachineRequestedWeRenegotiateRolesThenReturnedLocked);
       
  1183 			}
       
  1184 		case KErrInvalidOrUnacceptableRoleCombination:
       
  1185 			// Unable to find a valid role combination to send to the peer device.  fall through
       
  1186 
       
  1187 		default:
       
  1188 			LOG1(_L("RemDevState[%x]: <performing role negotiation for outgoing role change> - unexpected response from role state machine"), &StateMachine());
       
  1189 			User::Leave(err);
       
  1190 			break;
       
  1191 		}
       
  1192 	}
       
  1193 
       
  1194 void CPanRemDevStatePerformingRoleNegotiationForOutgoingRoleChange::BnepRoleResponseFromRemoteDeviceL(TBnepSetupConnectionResponseMessage aRoleResponseCode)
       
  1195 /**
       
  1196 The role response has arrived from the peer device.
       
  1197 */
       
  1198 	{
       
  1199 	LOG1(_L("RemDevState[%x]: <CPanRemDevStatePerformingRoleNegotiationForOutgoingRoleChange> - BNEP role response from remote device received, processing response..."), &StateMachine());
       
  1200 
       
  1201 	StateMachine().Cancel();
       
  1202 	
       
  1203 	CPanRemDevStateBase* nextState = NULL;
       
  1204 	switch(aRoleResponseCode)
       
  1205 		{
       
  1206 		case EOperationSuccessful:
       
  1207 			{
       
  1208 			LOG1(_L("RemDevState[%x]: <CPanRemDevStatePerformingRoleNegotiationForOutgoingRoleChange> - ...operation successful, setting device active."), &StateMachine());
       
  1209 			nextState = DoRoleNegotiationSuccessL();
       
  1210 			break;
       
  1211 			}
       
  1212 		default:
       
  1213 			{	
       
  1214 			LOG2(_L("RemDevState[%x]: <CPanRemDevStatePerformingRoleNegotiationForOutgoingRoleChange> - ...operation failed [result code = %d], connection not allowed"), &StateMachine(), aRoleResponseCode);
       
  1215 			nextState = DoRoleNegotiationFailureL(KErrCouldNotConnect);
       
  1216 			break;	
       
  1217 			}
       
  1218 		};
       
  1219 		
       
  1220 	__ASSERT_ALWAYS(nextState, PanicInState(ENoNextStateSet));
       
  1221 	StateMachine().SetState(*nextState);
       
  1222 	delete this;
       
  1223 	return;
       
  1224 	}
       
  1225 
       
  1226 CPanRemDevStateBase* CPanRemDevStatePerformingRoleNegotiationForOutgoingRoleChange::DoRoleNegotiationSuccessL()
       
  1227 /**
       
  1228 Role negotiation succeeded, decide whether we need to perform a baseband role switch
       
  1229 */
       
  1230 	{
       
  1231 	LOG1(_L("RemDevState[%x]: <performing role negotiation for outgoing role change> - role negotiation succeeded, deciding whether we need to role switch"), &StateMachine());
       
  1232 
       
  1233 	TInt err;
       
  1234 	// start going through the M/S switch routine
       
  1235 	err = PerformMasterSlaveSwitchIfNecessary(StateMachine().LocalRole());
       
  1236 	
       
  1237 	CPanRemDevStateBase* nextState = NULL;
       
  1238 	if(err==KErrWaitingForBasebandRoleSwitch)
       
  1239 		{
       
  1240 		nextState = new(ELeave) CPanRemDevStateWaitingForRoleSwitchForOutgoingRoleChangeRequest(StateMachine());
       
  1241 		}
       
  1242 	else if(err)
       
  1243 		{
       
  1244 		LOG1(_L("RemDevState[%x]: <performing role negotiation for outgoing role change> - ...M/S switch required and failed - disconnecting device."), &StateMachine());
       
  1245 		// remote device would not perform role switch (maybe it needs to stay as master for another 
       
  1246 		// profile it's using...)
       
  1247 		// Whilst the spec says we should return to previous roles when this role upgrade fails, 
       
  1248 		// we're now in the situation that we're GN/NAP, they're U, and we can't become the piconet 
       
  1249 		// master - so the best/most reliable/only way to recover is to disconnect them.  Not 
       
  1250 		// entirely according-to-spec, but then they shouldn't let us become master then refuse 
       
  1251 		// to role switch!
       
  1252 		User::Leave(KErrCouldNotBecomePiconetMaster);
       
  1253 		}
       
  1254 	else
       
  1255 		{
       
  1256 		nextState = new(ELeave) CPanRemDevStateActive(StateMachine());		
       
  1257 		}
       
  1258 	__ASSERT_ALWAYS(nextState, PanicInState(ENoNextStateSet));
       
  1259 	return nextState;
       
  1260 	}
       
  1261 	
       
  1262 CPanRemDevStateBase* CPanRemDevStatePerformingRoleNegotiationForOutgoingRoleChange::DoRoleNegotiationFailureL(TInt /*aError*/)
       
  1263 /**
       
  1264 Role negotiation failed, return to active state
       
  1265 */
       
  1266 	{
       
  1267 	LOG1(_L("RemDevState[%x]: <performing role negotiation for outgoing role change> - role negotiation failed, returning to active state"), &StateMachine());
       
  1268 
       
  1269 	// let the role state machine know that the role change failed
       
  1270 	StateMachine().RoleChangeFailed();
       
  1271 	CPanRemDevStateBase* nextState = new(ELeave) CPanRemDevStateActive(StateMachine());
       
  1272 	return nextState;
       
  1273 	}
       
  1274 
       
  1275 //
       
  1276 // CPanRemDevStatePerformingDelayedRoleNegotiationForOutgoingConnection
       
  1277 //
       
  1278 
       
  1279 CPanRemDevStatePerformingDelayedRoleNegotiationForOutgoingConnection::CPanRemDevStatePerformingDelayedRoleNegotiationForOutgoingConnection(MPanRemDevStateMachineNotify& aStateMachine) :
       
  1280 	CPanRemDevStatePerformingRoleNegotiationForOutgoingConnection(aStateMachine, EPanRemDevStatePerformingDelayedRoleNegotiationForOutgoingConnection)
       
  1281 /**
       
  1282 
       
  1283 */
       
  1284 	{	}
       
  1285 	
       
  1286 void CPanRemDevStatePerformingDelayedRoleNegotiationForOutgoingConnection::OnEntryL()
       
  1287 /**
       
  1288 Send the role request and start the timer
       
  1289 */
       
  1290 	{
       
  1291 	LOG1(_L("RemDevState[%x]: <performing delayed role negotiation for outgoing connection> - entering state"), &StateMachine());
       
  1292 
       
  1293 	User::LeaveIfError(iTimer.CreateLocal());
       
  1294 	
       
  1295 	// send the role request to the remote device
       
  1296 	StateMachine().SendRoleRequest(StateMachine().LocalRole(), StateMachine().RemoteRole());
       
  1297 	iTimer.After(StateMachine().Status(), KMaxTimeToWaitForRoleResponse);
       
  1298 	StateMachine().SetActive();
       
  1299 	}
       
  1300 	
       
  1301 //
       
  1302 // CPanRemDevStateWaitingForRoleSwitchBase
       
  1303 //
       
  1304 
       
  1305 CPanRemDevStateWaitingForRoleSwitchBase::CPanRemDevStateWaitingForRoleSwitchBase(MPanRemDevStateMachineNotify& aStateMachine, TPanRemDevStates aStateNumber) :
       
  1306 	CPanRemDevStateBase(aStateMachine, aStateNumber)
       
  1307 /**
       
  1308 
       
  1309 */
       
  1310 	{	}
       
  1311 	
       
  1312 CPanRemDevStateWaitingForRoleSwitchBase::~CPanRemDevStateWaitingForRoleSwitchBase()
       
  1313 /**
       
  1314 We own an object, so need our own destructor here to delete it
       
  1315 (this is the only state that does/needs this)
       
  1316 */
       
  1317 	{
       
  1318 	delete iTimerHelper;
       
  1319 	iTimerHelper = NULL;
       
  1320 	}
       
  1321 	
       
  1322 void CPanRemDevStateWaitingForRoleSwitchBase::OnEntryL()
       
  1323 /**
       
  1324 
       
  1325 */
       
  1326 	{
       
  1327 	LOG1(_L("RemDevState[%x]: <waiting for role switch [base]> - entering state"), &StateMachine());
       
  1328 
       
  1329 	//Proceed to the next state if role switch is not required
       
  1330 	TUint32 state;
       
  1331 	StateMachine().PhysicalLinkAdapter().PhysicalLinkState(state);
       
  1332 	if(state & ENotifyMaster)
       
  1333 		{
       
  1334 		CPanRemDevStateBase *nextState = DoRoleSwitchSuccessL();
       
  1335 		__ASSERT_ALWAYS(nextState, PanicInState(ENoNextStateSet));
       
  1336 		StateMachine().SetState(*nextState);
       
  1337 		delete this;
       
  1338 		return;
       
  1339 		}
       
  1340 
       
  1341 	// create and start the timer helper object
       
  1342 	iTimerHelper = CPanAgtTimerHelper::NewL(*this);
       
  1343 	iTimerHelper->SetTimer(KMaxTimeToWaitForBasebandRoleSwitch);
       
  1344 	
       
  1345 	// subscribe to the link status change event notification
       
  1346 	iEventNotification() = ENotifyMaster;	// must set this to the event we're interested in, otherwise we don't see it
       
  1347 	StateMachine().PhysicalLinkAdapter().NotifyNextBasebandChangeEvent(iEventNotification, StateMachine().Status());
       
  1348 	StateMachine().SetActive();
       
  1349 	}
       
  1350 
       
  1351 void CPanRemDevStateWaitingForRoleSwitchBase::RemoteDeviceDisconnectL(TInt aError)
       
  1352 /**
       
  1353 Oh well, they've given up
       
  1354 */
       
  1355 	{
       
  1356 	LOG1(_L("RemDevState[%x]: <waiting for role switch> - remote device disconnect received, they've obviously given up talking to us."), &StateMachine());
       
  1357 	// outstanding async request will be cancelled by state machine when we leave
       
  1358 	User::Leave(aError); // will shutdown the connection
       
  1359 	}
       
  1360 
       
  1361 void CPanRemDevStateWaitingForRoleSwitchBase::ShutdownL()
       
  1362 /**
       
  1363 
       
  1364 */
       
  1365 	{
       
  1366 	LOG1(_L("RemDevState[%x]: <waiting for role switch> - locally requested disconnect received"), &StateMachine());
       
  1367 	// outstanding async request will be cancelled by state machine when we leave
       
  1368 	User::Leave(KErrLocallyInitiatedDisconnect); // will shutdown the connection
       
  1369 	}
       
  1370 
       
  1371 void CPanRemDevStateWaitingForRoleSwitchBase::AsyncEventCompleteL()
       
  1372 /**
       
  1373 Timer or baseband change event notification completion
       
  1374 */
       
  1375 	{
       
  1376 	CPanRemDevStateBase* nextState = NULL;
       
  1377 	if(StateMachine().Status()==KErrNone)
       
  1378 		{
       
  1379 		if(iTimerCompleted)	// work out whether the timer fired or the baseband change event notification completed
       
  1380 			{
       
  1381 			// timer fired
       
  1382 			LOG1(_L("RemDevState[%x]: <waiting for role switch> - timer fired, giving up and disconnecting remote device"), &StateMachine());
       
  1383 			
       
  1384 			// cancel the outstanding request for baseband change event notification
       
  1385 			// need to cancel it directly, as the timer completes the state machine AO (through
       
  1386 			// the TimerComplete() and TimerCancel() methods, so just calling 
       
  1387 			// StateMachine().Cancel() won't have any effect
       
  1388 			StateMachine().PhysicalLinkAdapter().CancelNextBasebandChangeEventNotifier();
       
  1389 
       
  1390 			User::WaitForRequest(StateMachine().Status());	// have to catch the KErrCancel manually, as we're not active at the moment
       
  1391 
       
  1392 			nextState = DoRoleSwitchFailureL(KErrNone);
       
  1393 			}
       
  1394 		else
       
  1395 			{
       
  1396 			// Baseband change event notification completed
       
  1397 			if(iEventNotification().EventType() & ENotifyMaster)
       
  1398 				{
       
  1399 				LOG2(_L("RemDevState[%x]: <waiting for role switch> - received link event %32b, now piconet master - sending role response and going to active state"), &StateMachine(), iEventNotification().EventType());
       
  1400 
       
  1401 				// cancel the timer
       
  1402 				iTimerHelper->Cancel(); // need to cancel it directly, as the state machine AO is
       
  1403 										// no longer active, so just cancelling all async events 
       
  1404 										// through the state machine won't work
       
  1405 
       
  1406 				// success - get this state to do it's stuff
       
  1407 				// they *must* return the next state
       
  1408 				nextState = DoRoleSwitchSuccessL();
       
  1409 				}
       
  1410 			else // event that we're not interested in, repost 'baseband change event notification' request
       
  1411 				{
       
  1412 				iEventNotification() = ENotifyMaster; // must set this to the event we're interested in, otherwise we don't see it
       
  1413 				StateMachine().PhysicalLinkAdapter().NotifyNextBasebandChangeEvent(iEventNotification, StateMachine().Status());
       
  1414 				LOG2(_L("RemDevState[%x]: <waiting for role switch> - received link event %32b, throwing away"), &StateMachine(), iEventNotification().EventType());
       
  1415 				StateMachine().SetActive();
       
  1416 				return;
       
  1417 				}
       
  1418 			}
       
  1419 		}
       
  1420 	else
       
  1421 		{
       
  1422 		StateMachine().Cancel();
       
  1423 		nextState = DoRoleSwitchFailureL(StateMachine().Status().Int());
       
  1424 		}
       
  1425 		
       
  1426 	__ASSERT_ALWAYS(nextState, PanicInState(ENoNextStateSet));
       
  1427 	StateMachine().SetState(*nextState);
       
  1428 	delete this;
       
  1429 	return;
       
  1430 	}
       
  1431 	
       
  1432 void CPanRemDevStateWaitingForRoleSwitchBase::AsyncEventCancelL()
       
  1433 /**
       
  1434 Cancel all outstanding async events
       
  1435 @note This only works when the state machine AO is active - ie. calling StateMachine().Cancel()
       
  1436 from other code is only any good when *both* timer and baseband change event notification are outstanding, because the
       
  1437 completion of either will mark the state machine AO as inactive
       
  1438 */
       
  1439 	{
       
  1440 	iTimerHelper->Cancel();
       
  1441 	StateMachine().PhysicalLinkAdapter().CancelNextBasebandChangeEventNotifier();
       
  1442 	}
       
  1443 	
       
  1444 void CPanRemDevStateWaitingForRoleSwitchBase::TimerComplete()
       
  1445 /**
       
  1446 The timer has completed
       
  1447 */
       
  1448 	{
       
  1449 	iTimerCompleted = ETrue;
       
  1450 	TRequestStatus* status = &StateMachine().Status();
       
  1451 	User::RequestComplete(status, KErrNone);
       
  1452 	}
       
  1453 	
       
  1454 void CPanRemDevStateWaitingForRoleSwitchBase::TimerError(TInt aError)
       
  1455 /**
       
  1456 There was a problem with the timer
       
  1457 */
       
  1458 	{
       
  1459 	iTimerCompleted = ETrue;
       
  1460 	TRequestStatus* status = &StateMachine().Status();
       
  1461 	User::RequestComplete(status, aError);
       
  1462 	}
       
  1463 
       
  1464 // This returns a distilled (i.e., not the actual remote device state)
       
  1465 // version of the current connection status of the remote device
       
  1466 TRemoteDeviceState CPanRemDevStateWaitingForRoleSwitchBase::GetState() const
       
  1467 	{
       
  1468 	return EPerformingNegotiation;
       
  1469 	}
       
  1470 	
       
  1471 //
       
  1472 // CPanRemDevStateWaitingForRoleSwitchForOutgoingConnection
       
  1473 //
       
  1474 
       
  1475 CPanRemDevStateWaitingForRoleSwitchForOutgoingConnection::CPanRemDevStateWaitingForRoleSwitchForOutgoingConnection(MPanRemDevStateMachineNotify& aStateMachine) :
       
  1476 	CPanRemDevStateWaitingForRoleSwitchBase(aStateMachine, EPanRemDevStateWaitingForRoleSwitchForOutgoingConnection)
       
  1477 /**
       
  1478 
       
  1479 */
       
  1480 	{	}
       
  1481 
       
  1482 CPanRemDevStateWaitingForRoleSwitchForOutgoingConnection::CPanRemDevStateWaitingForRoleSwitchForOutgoingConnection(MPanRemDevStateMachineNotify& aStateMachine, TPanRemDevStates aStateNumber) :
       
  1483 	CPanRemDevStateWaitingForRoleSwitchBase(aStateMachine, aStateNumber)
       
  1484 /**
       
  1485 When implementing a new state that derives from this base class, ensure that
       
  1486 it provides a unique number to identify the state from other possible
       
  1487 states.  @see PanAgent::TPanAgtStates.
       
  1488 */
       
  1489 	{	}
       
  1490 		
       
  1491 void CPanRemDevStateWaitingForRoleSwitchForOutgoingConnection::OnEntryL()
       
  1492 /**
       
  1493 
       
  1494 */
       
  1495 	{
       
  1496 	LOG1(_L("RemDevState[%x]: <waiting for role switch for outgoing connection> - entering state"), &StateMachine());
       
  1497 	
       
  1498 	// call base class's method
       
  1499 	CPanRemDevStateWaitingForRoleSwitchBase::OnEntryL();
       
  1500 	}
       
  1501 
       
  1502 void CPanRemDevStateWaitingForRoleSwitchForOutgoingConnection::BnepRoleRequestFromRemoteDeviceL(const TUUID& /*aRequestedLocalRole*/, const TUUID& /*aRequestedRemoteRole*/)
       
  1503 /**
       
  1504 Ignore it, we're waiting for them to role switch
       
  1505 */
       
  1506 	{
       
  1507 	LOG1(_L("RemDevState[%x]: <waiting for role switch for outgoing connection> - BNEP role request from remote device: ignoring, as we're waiting for baseband role switch"), &StateMachine());
       
  1508 
       
  1509 	// do nothing
       
  1510 	}
       
  1511 	
       
  1512 void CPanRemDevStateWaitingForRoleSwitchForOutgoingConnection::BnepRoleResponseFromRemoteDeviceL(TBnepSetupConnectionResponseMessage /*aRoleResponseCode*/)
       
  1513 /**
       
  1514 Err, what's going on?  
       
  1515 */
       
  1516 	{
       
  1517 	LOG1(_L("RemDevState[%x]: <waiting for role switch for outgoing connection> - BNEP role response from remote device: huh?  What are they up to?  This is an incoming connection, so they're supposed to be sending the requests, not the responses"), &StateMachine());
       
  1518 
       
  1519 	// drop the role response packet that the remote device has incorrectly sent us
       
  1520 	}
       
  1521 
       
  1522 CPanRemDevStateBase* CPanRemDevStateWaitingForRoleSwitchForOutgoingConnection::DoRoleSwitchSuccessL()
       
  1523 /**
       
  1524 It worked - now perform the role negotiation
       
  1525 */
       
  1526 	{
       
  1527 	LOG1(_L("RemDevState[%x]: <waiting for role switch for outgoing connection> - role switch succeeded"), &StateMachine());
       
  1528 	CPanRemDevStateBase* nextState = new(ELeave) CPanRemDevStatePerformingDelayedRoleNegotiationForOutgoingConnection(StateMachine());
       
  1529 	return(nextState);
       
  1530 	}
       
  1531 	
       
  1532 CPanRemDevStateBase* CPanRemDevStateWaitingForRoleSwitchForOutgoingConnection::DoRoleSwitchFailureL(TInt aError)	
       
  1533 /**
       
  1534 Shutdown the connection
       
  1535 */
       
  1536 	{
       
  1537 	LOG1(_L("RemDevState[%x]: <waiting for role switch for outgoing connection> - role switch failed, shutting down"), &StateMachine());
       
  1538 	if(aError==KErrNone)	// the timer has fired
       
  1539 		{
       
  1540 		User::Leave(KErrCouldNotBecomePiconetMaster);
       
  1541 		}
       
  1542 	else					// a more general error occured
       
  1543 		{
       
  1544 		User::Leave(aError);
       
  1545 		}
       
  1546 	return NULL; // should never be reached
       
  1547 	}
       
  1548 
       
  1549 
       
  1550 // This returns a distilled (i.e., not the actual remote device state)
       
  1551 // version of the current connection status of the remote device
       
  1552 TRemoteDeviceState CPanRemDevStateWaitingForRoleSwitchForOutgoingConnection::GetState() const
       
  1553 	{
       
  1554 	return EPendingNegotiation;
       
  1555 	}
       
  1556 
       
  1557 //
       
  1558 // CPanRemDevStateWaitingForRoleSwitchForIncomingConnection
       
  1559 //
       
  1560 
       
  1561 CPanRemDevStateWaitingForRoleSwitchForIncomingConnection::CPanRemDevStateWaitingForRoleSwitchForIncomingConnection(MPanRemDevStateMachineNotify& aStateMachine) :
       
  1562 	CPanRemDevStateWaitingForRoleSwitchBase(aStateMachine, EPanRemDevStateWaitingForRoleSwitchForIncomingConnection)
       
  1563 /**
       
  1564 
       
  1565 */
       
  1566 	{	}
       
  1567 
       
  1568 CPanRemDevStateWaitingForRoleSwitchForIncomingConnection::CPanRemDevStateWaitingForRoleSwitchForIncomingConnection(MPanRemDevStateMachineNotify& aStateMachine, TPanRemDevStates aStateNumber) :
       
  1569 	CPanRemDevStateWaitingForRoleSwitchBase(aStateMachine, aStateNumber)
       
  1570 /**
       
  1571 When implementing a new state that derives from this base class, ensure that
       
  1572 it provides a unique number to identify the state from other possible
       
  1573 states.  @see PanAgent::TPanAgtStates.
       
  1574 */
       
  1575 	{	}
       
  1576 		
       
  1577 void CPanRemDevStateWaitingForRoleSwitchForIncomingConnection::OnEntryL()
       
  1578 /**
       
  1579 
       
  1580 */
       
  1581 	{
       
  1582 	LOG1(_L("RemDevState[%x]: <waiting for role switch for incoming connection> - entering state"), &StateMachine());
       
  1583 	
       
  1584 	// call base class's method
       
  1585 	CPanRemDevStateWaitingForRoleSwitchBase::OnEntryL();
       
  1586 	}
       
  1587 
       
  1588 void CPanRemDevStateWaitingForRoleSwitchForIncomingConnection::BnepRoleRequestFromRemoteDeviceL(const TUUID& /*aRequestedLocalRole*/, const TUUID& /*aRequestedRemoteRole*/)
       
  1589 /**
       
  1590 Ignore it, we're waiting for them to role switch
       
  1591 */
       
  1592 	{
       
  1593 	LOG1(_L("RemDevState[%x]: <waiting for role switch for incoming [base]> - BNEP role request from remote device: ignoring, as we're waiting for baseband role switch"), &StateMachine());
       
  1594 
       
  1595 	// ignore resent role request
       
  1596 	}
       
  1597 	
       
  1598 void CPanRemDevStateWaitingForRoleSwitchForIncomingConnection::BnepRoleResponseFromRemoteDeviceL(TBnepSetupConnectionResponseMessage /*aRoleResponseCode*/)
       
  1599 /**
       
  1600 Err, what's going on?  
       
  1601 */
       
  1602 	{
       
  1603 	LOG1(_L("RemDevState[%x]: <waiting for role switch for incoming [base]> - BNEP role response from remote device: huh?  What are they up to?  This is an incoming connection, so they're supposed to be sending the requests, not the responses"), &StateMachine());
       
  1604 
       
  1605 	// drop the role response packet that the remote device has incorrectly sent us
       
  1606 	}
       
  1607 
       
  1608 CPanRemDevStateBase* CPanRemDevStateWaitingForRoleSwitchForIncomingConnection::DoRoleSwitchSuccessL()
       
  1609 /**
       
  1610 It worked - tell the remote device and go to active state
       
  1611 */
       
  1612 	{
       
  1613 	LOG1(_L("RemDevState[%x]: <waiting for role switch for incoming [base]> - role switch succeeded"), &StateMachine());
       
  1614 
       
  1615   	// tell the remote device the connection was successful
       
  1616 	StateMachine().SendRoleResponse(EOperationSuccessful);
       
  1617 	// let the role state machine know that this connection is now active
       
  1618 	CPanRemDevStateBase* nextState = new(ELeave) CPanRemDevStateIncomingNotification(StateMachine());
       
  1619 	return(nextState);
       
  1620 	}
       
  1621 	
       
  1622 CPanRemDevStateBase* CPanRemDevStateWaitingForRoleSwitchForIncomingConnection::DoRoleSwitchFailureL(TInt aError)	
       
  1623 /**
       
  1624 Shutdown the connection
       
  1625 */
       
  1626 	{
       
  1627 	LOG1(_L("RemDevState[%x]: <waiting for role switch for incoming connection> - role switch failed, shutting down"), &StateMachine());
       
  1628 	
       
  1629 	//send response DEF068158
       
  1630  	StateMachine().SendRoleResponse(EConnectionNotAllowed); 	
       
  1631  	//and cancel next base band change event notifier DEF067708 
       
  1632 	
       
  1633 	StateMachine().PhysicalLinkAdapter().CancelNextBasebandChangeEventNotifier();
       
  1634 	
       
  1635 	
       
  1636 	if(aError==KErrNone)	// the timer has fired
       
  1637 		{
       
  1638 		User::Leave(KErrCouldNotBecomePiconetMaster);
       
  1639 		}
       
  1640 	else					// a more general error occured
       
  1641 		{
       
  1642 		User::Leave(aError);
       
  1643 		}
       
  1644 	return NULL; // should never be reached
       
  1645 	}
       
  1646 
       
  1647 //
       
  1648 // CPanRemDevStateWaitingForRoleSwitchForOutgoingRoleChangeRequest
       
  1649 //
       
  1650 
       
  1651 CPanRemDevStateWaitingForRoleSwitchForOutgoingRoleChangeRequest::CPanRemDevStateWaitingForRoleSwitchForOutgoingRoleChangeRequest(MPanRemDevStateMachineNotify& aStateMachine) :
       
  1652 	CPanRemDevStateWaitingForRoleSwitchForOutgoingConnection(aStateMachine, EPanRemDevStateWaitingForRoleSwitchForOutgoingRoleChangeRequest)
       
  1653 /**
       
  1654 
       
  1655 */
       
  1656 	{	}
       
  1657 		
       
  1658 void CPanRemDevStateWaitingForRoleSwitchForOutgoingRoleChangeRequest::OnEntryL()
       
  1659 /**
       
  1660 
       
  1661 */
       
  1662 	{
       
  1663 	LOG1(_L("RemDevState[%x]: <waiting for role switch for outgoing role change request> - entering state"), &StateMachine());
       
  1664 	
       
  1665 	// call base class's method
       
  1666 	CPanRemDevStateWaitingForRoleSwitchBase::OnEntryL();
       
  1667 	}
       
  1668 	
       
  1669 void CPanRemDevStateWaitingForRoleSwitchForOutgoingRoleChangeRequest::BnepRoleResponseFromRemoteDeviceL(TBnepSetupConnectionResponseMessage /*aRoleResponseCode*/)
       
  1670 /**
       
  1671 They've responded to our role request twice!
       
  1672 */
       
  1673 	{
       
  1674 	LOG1(_L("RemDevState[%x]: <waiting for role switch for outgoing role change request> - BNEP role response from remote device, they've already replied once - disconnecting them!"), &StateMachine());
       
  1675 
       
  1676 	// drop the role response packet that the remote device has incorrectly sent us
       
  1677 	}
       
  1678 	
       
  1679 CPanRemDevStateBase* CPanRemDevStateWaitingForRoleSwitchForOutgoingRoleChangeRequest::DoRoleSwitchSuccessL()
       
  1680 /**
       
  1681 We've managed to role switch, so the role upgrade has completed successfully
       
  1682 */
       
  1683 	{
       
  1684 	LOG1(_L("RemDevState[%x]: <waiting for role switch for outgoing role change request> - role switch succeeded, going to active state"), &StateMachine());
       
  1685 
       
  1686 	CPanRemDevStateBase* nextState = new(ELeave) CPanRemDevStateActive(StateMachine());
       
  1687  	return nextState;
       
  1688 	}
       
  1689 
       
  1690 CPanRemDevStateBase* CPanRemDevStateWaitingForRoleSwitchForOutgoingRoleChangeRequest::DoRoleSwitchFailureL(TInt /*aError*/)	
       
  1691 /**
       
  1692 Role switch failed, but this was a role change so return to old role in active state
       
  1693 */
       
  1694 	{
       
  1695 	LOG1(_L("RemDevState[%x]: <waiting for role switch for outgoing role change request> - role change failed, disconnecting remote device"), &StateMachine());
       
  1696 
       
  1697 	// Whilst the spec says we should return to previous roles when this role upgrade fails, 
       
  1698 	// we're now in the situation that we're GN/NAP, they're U, and we can't become the piconet 
       
  1699 	// master - so the best/most reliable/only way to recover is to disconnect them.  Not 
       
  1700 	// entirely according-to-spec, but then they shouldn't let us become master then refuse 
       
  1701 	// to role switch!
       
  1702 	User::Leave(KErrCouldNotBecomePiconetMaster);
       
  1703 	return NULL;	// will never get here
       
  1704 	}
       
  1705 
       
  1706 //
       
  1707 // CPanRemDevStateWaitingForRoleSwitchForIncomingRoleChangeRequest
       
  1708 //
       
  1709 
       
  1710 CPanRemDevStateWaitingForRoleSwitchForIncomingRoleChangeRequest::CPanRemDevStateWaitingForRoleSwitchForIncomingRoleChangeRequest(MPanRemDevStateMachineNotify& aStateMachine, TBluetoothPanRole aPendingLocalRole, TBluetoothPanRole aPendingRemoteRole) 
       
  1711   : CPanRemDevStateWaitingForRoleSwitchForIncomingConnection(aStateMachine, EPanRemDevStateWaitingForRoleSwitchForIncomingRoleChangeRequest),
       
  1712 	iPendingLocalRole(aPendingLocalRole),
       
  1713 	iPendingRemoteRole(aPendingRemoteRole)
       
  1714   
       
  1715 /**
       
  1716 
       
  1717 */
       
  1718 	{	}
       
  1719 		
       
  1720 void CPanRemDevStateWaitingForRoleSwitchForIncomingRoleChangeRequest::OnEntryL()
       
  1721 /**
       
  1722 
       
  1723 */
       
  1724 	{
       
  1725 	LOG1(_L("RemDevState[%x]: <waiting for role switch for incoming role change request> - entering state"), &StateMachine());
       
  1726 	
       
  1727 	// call base class's method
       
  1728 	CPanRemDevStateWaitingForRoleSwitchBase::OnEntryL();
       
  1729 	}
       
  1730 
       
  1731 CPanRemDevStateBase* CPanRemDevStateWaitingForRoleSwitchForIncomingRoleChangeRequest::DoRoleSwitchSuccessL()
       
  1732 	{
       
  1733 	LOG1(_L("RemDevState[%x]: <CPanRemDevStateWaitingForRoleSwitchForIncomingRoleChangeRequest> - role switch succeeded"), &StateMachine());
       
  1734 
       
  1735   	// tell the remote device the connection was successful
       
  1736 	StateMachine().SendRoleResponse(EOperationSuccessful);
       
  1737 
       
  1738 	// Store the new roles
       
  1739 	StateMachine().LocalRole() = iPendingLocalRole;
       
  1740 	StateMachine().RemoteRole() = iPendingRemoteRole;
       
  1741 
       
  1742 	// Changing role from GN/NAP to U.  If this connection previously had access to the
       
  1743 	// uplink this should be revoked.
       
  1744 	if(StateMachine().LocalRole() == EPanRoleU)
       
  1745 		{
       
  1746 		StateMachine().SetUplinkAccessAllowed(EFalse);
       
  1747 		}
       
  1748 
       
  1749 	// let the role state machine know that this connection is now active
       
  1750 	CPanRemDevStateBase* nextState = new(ELeave) CPanRemDevStateIncomingNotification(StateMachine());
       
  1751 	return(nextState);
       
  1752 	}
       
  1753 	
       
  1754 CPanRemDevStateBase* CPanRemDevStateWaitingForRoleSwitchForIncomingRoleChangeRequest::DoRoleSwitchFailureL(TInt /*aError*/)	
       
  1755 /**
       
  1756 Signal the remote device that the role change didn't work, and go back to active state
       
  1757 */
       
  1758 	{
       
  1759 	LOG1(_L("RemDevState[%x]: <waiting for role switch for incoming role change request> - role change failed, signalling remote device and going to active state"), &StateMachine());
       
  1760   	// tell the remote device the connection was unsuccessful
       
  1761 	StateMachine().SendRoleResponse(EConnectionNotAllowed);
       
  1762 	// let the role state machine know that the role change failed
       
  1763 	StateMachine().RoleChangeFailed();
       
  1764 	CPanRemDevStateBase* nextState = new(ELeave) CPanRemDevStateActive(StateMachine());
       
  1765 	return(nextState);
       
  1766 	}
       
  1767 
       
  1768 //
       
  1769 // CPanRemDevStateActive
       
  1770 //
       
  1771 
       
  1772 CPanRemDevStateActive::CPanRemDevStateActive(MPanRemDevStateMachineNotify& aStateMachine) :
       
  1773 	CPanRemDevStateBase(aStateMachine, EPanRemDevStateActive)
       
  1774 /**
       
  1775 
       
  1776 */
       
  1777 	{	}
       
  1778 	
       
  1779 void CPanRemDevStateActive::OnEntryL()
       
  1780 /**
       
  1781 
       
  1782 */ 
       
  1783 	{
       
  1784 	LOG1(_L("RemDevState[%x]: <device active> - entering state"), &StateMachine());
       
  1785 	
       
  1786 	StateMachine().DeviceActive();
       
  1787 	}
       
  1788 	
       
  1789 void CPanRemDevStateActive::BnepRoleRequestFromRemoteDeviceL(const TUUID& aRequestedLocalRole, const TUUID& aRequestedRemoteRole)
       
  1790 /**
       
  1791 Remote device is trying to renegotiate roles with us
       
  1792 @note This may also occur because our role response got lost, so send it again...
       
  1793 */
       
  1794 	{
       
  1795 	LOG1(_L("RemDevState[%x]: <device active> - BNEP role request received from remote device..."), &StateMachine());
       
  1796 
       
  1797 	TInt err;
       
  1798 	TBluetoothPanRole proposedLocalRole;
       
  1799 	TBluetoothPanRole proposedRemoteRole;
       
  1800 	
       
  1801 	// Convert the role from the remote device.  If these are invalid the connection will be terminated.
       
  1802 	ConvertUuidsToPanRolesL(aRequestedLocalRole, aRequestedRemoteRole, proposedLocalRole, proposedRemoteRole);
       
  1803 
       
  1804 	if((StateMachine().LocalRole() == proposedLocalRole) &&	(StateMachine().RemoteRole() == proposedRemoteRole)) // they've lost our response, so resend
       
  1805 		{
       
  1806 		LOG1(_L("RemDevState[%x]: <device active> - ...roles are the same as before, they obviously lost our role response - resending"), &StateMachine());
       
  1807 		StateMachine().SendRoleResponse(EOperationSuccessful);
       
  1808 		}
       
  1809 	else	// it's an attempt to renegotiate roles
       
  1810 		{
       
  1811 		LOG1(_L("RemDevState[%x]: <device active> - ..., they want to renegotiate roles"), &StateMachine());
       
  1812 
       
  1813 		CPanRemDevStateBase* nextState = NULL;
       
  1814 
       
  1815 		LOG1(_L("RemDevState[%x]: <active> - checking role request for incoming role upgrade attempt..."), &StateMachine());
       
  1816 		err = StateMachine().RoleChangeRequestFromPeer(proposedLocalRole, proposedRemoteRole);
       
  1817 		switch(err)
       
  1818 			{
       
  1819 			case KErrNone:
       
  1820 				{
       
  1821 				LOG1(_L("RemDevState[%x]: <active> - ...successful, checking to see if M/S switch necessary..."), &StateMachine());
       
  1822 
       
  1823 				err = PerformMasterSlaveSwitchIfNecessary(proposedLocalRole);
       
  1824 				if(err==KErrWaitingForBasebandRoleSwitch)
       
  1825 					{
       
  1826 					nextState = new(ELeave) CPanRemDevStateWaitingForRoleSwitchForIncomingRoleChangeRequest(StateMachine(), proposedLocalRole, proposedRemoteRole);
       
  1827 					break;
       
  1828 					}
       
  1829 				else if(err)
       
  1830 					{
       
  1831 					LOG1(_L("RemDevState[%x]: <active> - ...M/S switch required and failed - disconnecting device."), &StateMachine());
       
  1832 					// remote device would not perform role switch (maybe it needs to stay as master for another profile it's using...)
       
  1833 					StateMachine().SendRoleResponse(EConnectionNotAllowed);
       
  1834 					StateMachine().RoleChangeFailed();
       
  1835 					break;		
       
  1836 					}
       
  1837 					
       
  1838 				LOG1(_L("RemDevState[%x]: <active> - ...M/S switch not required, sending successful connect response."), &StateMachine());
       
  1839 				StateMachine().SendRoleResponse(EOperationSuccessful);
       
  1840 
       
  1841 				// Store the new roles
       
  1842 				StateMachine().LocalRole() = proposedLocalRole;
       
  1843 				StateMachine().RemoteRole() = proposedRemoteRole;
       
  1844 
       
  1845 				// Changing role from GN/NAP to U.  If this connection previously had access to the
       
  1846 				// uplink this should be revoked.
       
  1847 				if(StateMachine().LocalRole() == EPanRoleU)
       
  1848 					{
       
  1849 					StateMachine().SetUplinkAccessAllowed(EFalse);
       
  1850 					}
       
  1851 
       
  1852 				// remain in active state
       
  1853 				StateMachine().DeviceActive();
       
  1854 				break;
       
  1855 				}
       
  1856 			case KErrLocked:
       
  1857 				{
       
  1858 				LOG1(_L("RemDevState[%x]: <active> - ...role state machine busy, waiting."), &StateMachine());
       
  1859 
       
  1860 				// Create the "waiting" state
       
  1861 				nextState = new(ELeave) CPanRemDevStateWaitingForLocalRoleStateMachineAvailabilityForIncomingRoleChangeRequest(StateMachine(), proposedLocalRole, proposedRemoteRole);
       
  1862 				break;
       
  1863 				}
       
  1864 
       
  1865 			case KErrInvalidOrUnacceptableRoleCombination:
       
  1866 				LOG1(_L("RemDevState[%x]: <active> - ...Role change request can't be processed."), &StateMachine());		
       
  1867 				StateMachine().SendRoleResponse(EConnectionNotAllowed);
       
  1868 				// We don't want to change state or inform the state machine as it returned the error.
       
  1869 				break;
       
  1870 
       
  1871 			default:
       
  1872 				// if err is something other than KErrNoMemory that might indicate an internal error in the state
       
  1873 				// machine, so ASSERT_DEBUG.  We can probably carry on even if the error is unexpected, as leaving
       
  1874 				// will cause this connection to shutdown.
       
  1875 				__ASSERT_DEBUG(err == KErrNoMemory, PanicInState(EPanAgentRoleStateMachineReturnedUnexpectedErrorCode));
       
  1876 				User::Leave(err);
       
  1877 				break;
       
  1878 			};
       
  1879 		
       
  1880 		if(nextState)	// we've decided we need to go to another state to continue
       
  1881 			{
       
  1882 			StateMachine().SetState(*nextState);
       
  1883 			delete this;
       
  1884 			return;
       
  1885 			}
       
  1886 		}
       
  1887 	}
       
  1888 	
       
  1889 void CPanRemDevStateActive::BnepRoleResponseFromRemoteDeviceL(TBnepSetupConnectionResponseMessage aRoleResponseCode)
       
  1890 /**
       
  1891 Something's gone very wrong - what is the other device doing?
       
  1892 */
       
  1893 	{
       
  1894 	LOG1(_L("RemDevState[%x]: <device active> - BNEP role response received from remote device, what are they up to?  We haven't got an outstanding role request (this might change after a refactoring of the remote device states though)"), &StateMachine());
       
  1895 
       
  1896 	// for robustness sake, accept a successful role response, but disconnect them otherwise
       
  1897 	if(aRoleResponseCode!=EOperationSuccessful)
       
  1898 		{
       
  1899 		User::Leave(KErrDodgyResponseFromRemoteDevice);
       
  1900 		}
       
  1901 	}
       
  1902 
       
  1903 void CPanRemDevStateActive::RemoteDeviceDisconnectL(TInt aError)
       
  1904 /**
       
  1905 Remote device has disconnected
       
  1906 @param aError The reason for the remote device disconnect
       
  1907 */
       
  1908 	{
       
  1909 	LOG1(_L("RemDevState[%x]: <device active> - remote device disconnect received, they've obviously given up talking to us."), &StateMachine());
       
  1910 
       
  1911 	StateMachine().ResetConnectionRetryAttempts(); // reset the connection retry attempts
       
  1912 
       
  1913 	User::Leave(aError); // will shutdown the connection	
       
  1914 	}
       
  1915 	
       
  1916 void CPanRemDevStateActive::ReadyForRoleRequestL()
       
  1917 /**
       
  1918 Indication that the main state machine wants us to renegotiate our roles
       
  1919 @note According to the spec, if we fail to negotiate a new role we remain connected and in our old roles
       
  1920 */
       
  1921 	{
       
  1922 	LOG1(_L("RemDevState[%x]: <device active> - ready for role request received from role state machine - it obviously wants us to renegotiate our roles."), &StateMachine());	
       
  1923 
       
  1924 	CPanRemDevStateBase* nextState = new(ELeave) CPanRemDevStatePerformingRoleNegotiationForOutgoingRoleChange(StateMachine());
       
  1925 	StateMachine().SetState(*nextState);
       
  1926 	delete this;
       
  1927 	return;
       
  1928 	}
       
  1929 
       
  1930 void CPanRemDevStateActive::ShutdownL()
       
  1931 /**
       
  1932 Disconnect command from local device
       
  1933 */
       
  1934 	{
       
  1935 	LOG1(_L("RemDevState[%x]: <device active> - locally requested disconnect received."), &StateMachine());
       
  1936 
       
  1937 	User::Leave(KErrLocallyInitiatedDisconnect); // will shutdown the connection
       
  1938 	}
       
  1939 
       
  1940 // This returns a distilled (i.e., not the actual remote device state)
       
  1941 // version of the current connection status of the remote device
       
  1942 TRemoteDeviceState CPanRemDevStateActive::GetState() const
       
  1943 	{
       
  1944 	return EActive;
       
  1945 	}
       
  1946 		
       
  1947 //
       
  1948 // CPanRemDevStateShutdown
       
  1949 //
       
  1950 
       
  1951 CPanRemDevStateShutdown::CPanRemDevStateShutdown(MPanRemDevStateMachineNotify& aStateMachine) :
       
  1952 	CPanRemDevStateBase(aStateMachine, EPanRemDevStateShutdown)
       
  1953 /**
       
  1954 
       
  1955 */
       
  1956 	{	}
       
  1957 	
       
  1958 void CPanRemDevStateShutdown::OnEntryL()
       
  1959 /**
       
  1960 
       
  1961 */
       
  1962 	{
       
  1963 	LOG1(_L("RemDevState[%x]: <shutting down connection> - entering state"), &StateMachine());
       
  1964 	// put an async break in here to ensure that if we arrive here synchronously from
       
  1965 	// the initialising state in the role state machine, that we give the role state
       
  1966 	// machine chance to transition to a new state before telling it we're shutting down
       
  1967 	TRequestStatus* status = &StateMachine().Status();
       
  1968 	User::RequestComplete(status, KErrNone);
       
  1969 	StateMachine().SetActive();
       
  1970 	}
       
  1971 
       
  1972 void CPanRemDevStateShutdown::BnepRoleRequestFromRemoteDeviceL(const TUUID& /*aRequestedLocalRole*/, const TUUID& /*aRequestedRemoteRole*/)
       
  1973 /**
       
  1974 Shouldn't receive this (the remote device should be disconnected) but just in case...
       
  1975 @note *Must not* leave from here, otherwise we're in an endless loop
       
  1976 */
       
  1977 	{
       
  1978 	LOG1(_L("RemDevState[%x]: <shutting down connection> - BNEP role request received from remote device, but we're shutting down so just ignore it."), &StateMachine());
       
  1979 
       
  1980 	// better tell them that we're not going to do anything
       
  1981 	StateMachine().SendRoleResponse(EConnectionNotAllowed);
       
  1982 	}
       
  1983 	
       
  1984 void CPanRemDevStateShutdown::BnepRoleResponseFromRemoteDeviceL(TBnepSetupConnectionResponseMessage /*aRoleResponseCode*/)
       
  1985 /**
       
  1986 Shouldn't receive this (the remote device should be disconnected) but just in case...
       
  1987 @note *Must not* leave from here, otherwise we're in an endless loop
       
  1988 */
       
  1989 	{
       
  1990 	LOG1(_L("RemDevState[%x]: <shutting down connection> - BNEP role response received from remote device, but we're shutting down so just ignore it."), &StateMachine());
       
  1991 
       
  1992 	// We're disconnecting, so we don't care, just bin it (ie. do nothing...)
       
  1993 	}
       
  1994 	
       
  1995 void CPanRemDevStateShutdown::RemoteDeviceDisconnectL(TInt /*aError*/)
       
  1996 /**
       
  1997 Shouldn't receive this (the remote device should be disconnected) but just in case...
       
  1998 @note *Must not* leave from here, otherwise we're in an endless loop
       
  1999 */
       
  2000 	{
       
  2001 	LOG1(_L("RemDevState[%x]: <shutting down connection> - remote device disconnect received; odd, they should already be disconnected."), &StateMachine());
       
  2002 
       
  2003 	// Again, we're disconnecting, so we don't care, just bin it (ie. do nothing...)
       
  2004 	}
       
  2005 	
       
  2006 void CPanRemDevStateShutdown::ShutdownL()
       
  2007 /**
       
  2008 Whoops - double disconnect from local device...
       
  2009 @note *Must not* leave from here, otherwise we're in an endless loop
       
  2010 */
       
  2011 	{
       
  2012 	// It is possible to request a shutdown of a remote device when it is already in
       
  2013 	// the shutdown state, so don't panic. This occurs when the last remote device receives a
       
  2014 	// disconnect and places itself in the shutdown state but only removes itself from the agent 
       
  2015 	// after an async event.
       
  2016 	// As it was the last remote device this cause LinkLayerDown() to be called on Nifman which
       
  2017 	// shuts down the agent. The agent then disconnects all remote devices. If the async event
       
  2018 	// has not occured for the last remote device shutdown then the agent calls shutdown on the 
       
  2019 	// remote device again. This is ok as the async event completing will inform the agent and then
       
  2020 	// the agent will do a full shutdown.
       
  2021 
       
  2022 	LOG1(_L("RemDevState[%x]: <shutting down connection> - remote device disconnect request received, already shutting down so nothing to do."), &StateMachine());
       
  2023 	}
       
  2024 	
       
  2025 void CPanRemDevStateShutdown::AsyncEventCompleteL()
       
  2026 /**
       
  2027 Async callback to tell us to shutdown the state machine
       
  2028 @note *Must not* leave from here, otherwise we're in an endless loop
       
  2029 */
       
  2030 	{
       
  2031 	LOG1(_L("RemDevState[%x]: <shutting down connection> - async event complete, shutting down"), &StateMachine());
       
  2032 	
       
  2033 	if(StateMachine().HasBnepChannel())
       
  2034 		{
       
  2035 		StateMachine().DisconnectBnepChannel();
       
  2036 		}
       
  2037 	
       
  2038 	StateMachine().ShutdownComplete();
       
  2039 	// don't "delete this" - this is the terminal state, so the state machine has to delete us	
       
  2040 	}
       
  2041 	
       
  2042 void CPanRemDevStateShutdown::AsyncEventCancelL()
       
  2043 /**
       
  2044 
       
  2045 @note *Must not* leave from here, otherwise we're in an endless loop
       
  2046 */
       
  2047 	{
       
  2048 	TRequestStatus* status = &StateMachine().Status();
       
  2049 	User::RequestComplete(status, KErrCancel); // to keep CActive::Cancel() happy
       
  2050 	}
       
  2051 
       
  2052 // This returns a distilled (i.e., not the actual remote device state)
       
  2053 // version of the current connection status of the remote device
       
  2054 TRemoteDeviceState CPanRemDevStateShutdown::GetState() const
       
  2055 	{
       
  2056 	return EDisconnecting;
       
  2057 	}
       
  2058 
       
  2059 //
       
  2060 // CPanRemDevStateIncomingNotification
       
  2061 //
       
  2062 
       
  2063 CPanRemDevStateIncomingNotification::CPanRemDevStateIncomingNotification(MPanRemDevStateMachineNotify& aStateMachine) :
       
  2064 	CPanRemDevStateBase(aStateMachine, EPanRemDevStateIncomingNotification)
       
  2065 /**
       
  2066 This state manages the incoming uplink access allowed for local NAP role notifier
       
  2067 */
       
  2068 	{	}
       
  2069 	
       
  2070 CPanRemDevStateIncomingNotification::~CPanRemDevStateIncomingNotification()
       
  2071 	{
       
  2072 	delete iNapUplinkAuthorisationHelper;
       
  2073 	}
       
  2074 	
       
  2075 void CPanRemDevStateIncomingNotification::OnEntryL()
       
  2076 	{
       
  2077 	if(StateMachine().LocalRole() == EPanRoleNap)
       
  2078 		{
       
  2079 		iNapUplinkAuthorisationHelper = new(ELeave) CNapUplinkAuthorisationHelper(*this);
       
  2080 		
       
  2081 		// Set requested connection address.
       
  2082 		TBTDevAddr requestingDeviceAddr = StateMachine().RemSockAddr().BTAddr();		
       
  2083 		iNapUplinkAuthorisationHelper->PanConnectionList().SetRequestedConnectionAddr(requestingDeviceAddr);
       
  2084 
       
  2085 		// Get current connection information.
       
  2086 		StateMachine().GetExistingConnections(iNapUplinkAuthorisationHelper->PanConnectionList());
       
  2087 		
       
  2088 		iNapUplinkAuthorisationHelper->PerformNapUplinkAuthorisationL();
       
  2089 		}
       
  2090 	else
       
  2091 		{
       
  2092 		// Notifier not required - go to active state.
       
  2093 		CPanRemDevStateBase* nextState = new(ELeave) CPanRemDevStateActive(StateMachine());		
       
  2094 		StateMachine().SetState(*nextState);
       
  2095 		delete this;
       
  2096 		return;		// Just to be safe after 'delete this'
       
  2097 		}
       
  2098 	}
       
  2099 
       
  2100 // From MNapUplinkAuthorisationRequester
       
  2101 void CPanRemDevStateIncomingNotification::MnuarNapUplinkAuthorisationHelperComplete(TInt aError, TNapConnectionResult aResult)
       
  2102 	{
       
  2103 	if(aError == KErrNone)
       
  2104 		{
       
  2105 		switch(aResult)
       
  2106 			{
       
  2107 			case EDisallowNewNapConnection:
       
  2108 				// Disconnect this connection by moving into the shutdown state.
       
  2109 				ShutdownConnection(KErrAccessDenied);
       
  2110 				break;
       
  2111 				
       
  2112 			case EAcceptNapConnectionAllowUplinkAccess:
       
  2113 				// Inform the packet driver that this connection should have access to the NAP service and
       
  2114 				// close any connection that currently has access to the uplink.
       
  2115 				StateMachine().SetUplinkAccessAllowed(ETrue);
       
  2116 		
       
  2117 				// Fall onto next case...
       
  2118 						
       
  2119 			case EAcceptNapConnectionDisallowUplinkAccess:
       
  2120 				{
       
  2121 				CPanRemDevStateBase* nextState = NULL;
       
  2122 				TRAPD(err, nextState = new(ELeave) CPanRemDevStateActive(StateMachine()));
       
  2123 				if(err == KErrNone)
       
  2124 					{
       
  2125 					StateMachine().SetState(*nextState);
       
  2126 					delete this;
       
  2127 					return;
       
  2128 					}
       
  2129 				else
       
  2130 					{
       
  2131 					ShutdownConnection(err);
       
  2132 					}
       
  2133 				}
       
  2134 				break;
       
  2135 				
       
  2136 			default:
       
  2137 				PanicInState(EInvalidResultCodeFromNapUplinkAuthorisationNotifier);
       
  2138 				break;
       
  2139 			};
       
  2140 		}
       
  2141 	else
       
  2142 		{
       
  2143 		// Disconnect this connection by moving into the shutdown state.
       
  2144 		ShutdownConnection(aError);
       
  2145 		}
       
  2146 	}
       
  2147 	
       
  2148 void CPanRemDevStateIncomingNotification::BnepRoleRequestFromRemoteDeviceL(const TUUID& /*aRequestedLocalRole*/, const TUUID& /*aRequestedRemoteRole*/)
       
  2149 /**
       
  2150 A role request from the remote device can't be handled at this time
       
  2151 */
       
  2152 	{
       
  2153 	LOG1(_L("RemDevState[%x]: <Waiting for incoming notification> - BNEP role reponse from remote device."), &StateMachine());
       
  2154 	
       
  2155 	// drop the role request packet that the remote device has sent us
       
  2156 	}
       
  2157 	
       
  2158 void CPanRemDevStateIncomingNotification::BnepRoleResponseFromRemoteDeviceL(TBnepSetupConnectionResponseMessage /*aRoleResponseCode*/)
       
  2159 /**
       
  2160 A role request has not been sent by this device.  This is unexpected behaviour by the remote.
       
  2161 */
       
  2162 	{
       
  2163 	LOG1(_L("RemDevState[%x]: <Waiting for incoming notification> - BNEP role reponse from remote device."), &StateMachine());
       
  2164 	
       
  2165 	// drop the role response packet that the remote device has incorrectly sent us
       
  2166 	}
       
  2167 	
       
  2168 void CPanRemDevStateIncomingNotification::RemoteDeviceDisconnectL(TInt aError)
       
  2169 	{
       
  2170 	LOG1(_L("RemDevState[%x]: <Waiting for incoming notification> - remote device disconnect received; odd, they should already be disconnected."), &StateMachine());
       
  2171 
       
  2172 	// Shutdown the connection.
       
  2173 	ShutdownConnection(aError);
       
  2174 	}
       
  2175 	
       
  2176 void CPanRemDevStateIncomingNotification::ShutdownL()
       
  2177 	{
       
  2178 	LOG1(_L("RemDevState[%x]: <CPanRemDevStateIncomingNotification> - locally requested disconnect received"), &StateMachine());
       
  2179 	
       
  2180 	// outstanding async request will be cancelled by state machine when we leave
       
  2181 	User::Leave(KErrLocallyInitiatedDisconnect);
       
  2182 	}
       
  2183 	
       
  2184 // This returns a distilled (i.e., not the actual remote device state)
       
  2185 // version of the current connection status of the remote device
       
  2186 TRemoteDeviceState CPanRemDevStateIncomingNotification::GetState() const
       
  2187 	{
       
  2188 	return EPerformingNegotiation;
       
  2189 	}
       
  2190 
       
  2191 void CPanRemDevStateIncomingNotification::ShutdownConnection(TInt aError)
       
  2192 	{
       
  2193 	if(!iShutdownCalled)
       
  2194 		{
       
  2195 		// Shutdown the connection.
       
  2196 		iShutdownCalled = ETrue;
       
  2197 		StateMachine().Shutdown(aError);
       
  2198 		}
       
  2199 	}
       
  2200 
       
  2201 	
       
  2202 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
       
  2203 CPanRemDevStatePaused::CPanRemDevStatePaused(MPanRemDevStateMachineNotify& aStateMachine, CPanRemDevStateBase& aNextState)
       
  2204     : CPanRemDevStateBase(aStateMachine, EPanRemDevStatePaused), iNextState(&aNextState)
       
  2205     {
       
  2206     }
       
  2207     
       
  2208 CPanRemDevStatePaused::~CPanRemDevStatePaused()
       
  2209     {
       
  2210     delete iNextState;
       
  2211     }
       
  2212 
       
  2213 void CPanRemDevStatePaused::OnEntryL()
       
  2214     {
       
  2215     // Does nothing
       
  2216     }
       
  2217     
       
  2218 void CPanRemDevStatePaused::ShutdownL()
       
  2219     {
       
  2220     // We don't know the appropriate action so allow the next states
       
  2221     // ShutdownL to execute. We'll cleanup the next state when the 
       
  2222     // RemDevStateMachine deletes us
       
  2223     iNextState->ShutdownL();
       
  2224     }
       
  2225     
       
  2226 TRemoteDeviceState CPanRemDevStatePaused::GetState() const
       
  2227     {
       
  2228     return iNextState->GetState();
       
  2229     }
       
  2230 
       
  2231 void CPanRemDevStatePaused::AsyncEventCancelL()
       
  2232     {
       
  2233     // Next state hasn't started yet so no need to cancel it
       
  2234     }
       
  2235     
       
  2236 void CPanRemDevStatePaused::AsyncEventCompleteL()
       
  2237     {
       
  2238     StateMachine().SetState(*iNextState);
       
  2239     
       
  2240     // We no longer own the next state
       
  2241     iNextState = NULL;
       
  2242     delete this;
       
  2243     }
       
  2244     
       
  2245 #endif
       
  2246 // SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY