bluetooth/btstack/linkmgr/roleswitchhelper.cpp
branchRCL_3
changeset 25 99439b07e980
equal deleted inserted replaced
24:e9b924a62a66 25:99439b07e980
       
     1 // Copyright (c) 2010 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 the License "Symbian Foundation License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 
       
    17 #include <bluetooth/logger.h>
       
    18 #include "roleswitchhelper.h"
       
    19 #include "physicallinksmanager.h"
       
    20 #include "AclDataQController.h"
       
    21 #include "ProxySAP.h"
       
    22 #include "linkmgr.h"
       
    23 
       
    24 #ifdef __FLOG_ACTIVE
       
    25 _LIT8(KLogComponent, LOG_COMPONENT_LINKMGR);
       
    26 #endif
       
    27 
       
    28 CRoleSwitcher::CRoleSwitcher(CPhysicalLinksManager& aLinkMgr, CPhysicalLink& aLink, TBTBasebandRole aRole)
       
    29 	: CPhysicalLinkHelper(aLinkMgr, aLink)
       
    30 	, iRole(aRole)
       
    31 	, iIsEncryptionDisabledForRoleSwitch(EFalse)
       
    32 	{
       
    33 	LOG_FUNC
       
    34 	iState = &iLinkMgr.RoleSwitcherStateFactory().GetState(CRoleSwitcherStateFactory::EIdle);
       
    35 	}
       
    36 
       
    37 CRoleSwitcher* CRoleSwitcher::NewL(CPhysicalLinksManager& aLinkMgr, CPhysicalLink& aLink, TBTBasebandRole aRole)
       
    38 	{
       
    39 	LOG_STATIC_FUNC
       
    40 	CRoleSwitcher* self = new(ELeave) CRoleSwitcher(aLinkMgr, aLink, aRole);
       
    41 	CleanupStack::PushL(self);
       
    42 	self->ConstructL();
       
    43 	CleanupStack::Pop(self);
       
    44 	return self;
       
    45 	}
       
    46 	
       
    47 void CRoleSwitcher::ConstructL()
       
    48 	{
       
    49 	LOG_FUNC
       
    50 	
       
    51 	BaseConstructL();
       
    52 	
       
    53 	// add ourselves to the list in LinkMgr, LinkMgr will kick off the role change state machine 	
       
    54 	iLinkMgr.AddRoleSwitcher(*this);
       
    55 	iAddedToLinkMgr = ETrue;
       
    56 	}
       
    57 	
       
    58 CRoleSwitcher::~CRoleSwitcher()
       
    59 	{
       
    60 	LOG_FUNC
       
    61 	if (iAddedToLinkMgr)
       
    62 		{
       
    63 		iLinkMgr.RemoveRoleSwitcher(*this);
       
    64 		}
       
    65 	}
       
    66 
       
    67 void CRoleSwitcher::TimerExpired()
       
    68 	{
       
    69 	LOG_FUNC
       
    70 	
       
    71 	iState->TimerExpired(*this);
       
    72 	}
       
    73 
       
    74 void CRoleSwitcher::HandleError( TInt aError)
       
    75 	{
       
    76 	LOG_FUNC
       
    77 	
       
    78 	iState->Error(*this, aError);
       
    79 	}
       
    80 
       
    81 void CRoleSwitcher::DisableEncryption()
       
    82   	{
       
    83 	LOG_FUNC
       
    84  	// data traffic suspended
       
    85 	iLinkMgr.LinkManagerProtocol().ACLController().SetParked(iLink.Handle(), ETrue);
       
    86 	NotifyBasebandEvent(ENotifyEncryptionChangeOff);
       
    87 	iLinkMgr.Encrypt(EFalse, iLink);
       
    88 
       
    89 	// set flag here, it's too late when we receive the event as AccessReqester
       
    90 	// might receive the baseband notification earlier then the flag is set!	
       
    91 	iIsEncryptionDisabledForRoleSwitch = ETrue;
       
    92   	}
       
    93 
       
    94 void CRoleSwitcher::EnableEncryption()
       
    95   	{
       
    96 	LOG_FUNC  	
       
    97 	NotifyBasebandEvent(ENotifyEncryptionChangeOn);
       
    98 	iLinkMgr.Encrypt(ETrue, iLink);	
       
    99 	// data traffic is enabled in IoctlComplete
       
   100   	}
       
   101    	
       
   102 void CRoleSwitcher::ChangeRole()
       
   103 	{
       
   104 	LOG_FUNC
       
   105 	NotifyBasebandEvent(ENotifyAnyRole);
       
   106 	iLinkMgr.ChangeRole(iRole, iLink);
       
   107 	}
       
   108 
       
   109 void CRoleSwitcher::StartHelper()
       
   110 	{
       
   111 	LOG_FUNC
       
   112 	iState->Start(*this);
       
   113 	}
       
   114 		
       
   115 void CRoleSwitcher::SaveEncryption()
       
   116 	{
       
   117 	LOG_FUNC
       
   118 	iIsEncrypted = iLink.Encrypted();
       
   119 	}
       
   120 
       
   121 void CRoleSwitcher::LogRoleSwitchSuccessful(TBTBasebandEventNotification& aEvent) const
       
   122 	{
       
   123 	LOG_FUNC
       
   124 	TInt eventType;
       
   125 	eventType = (iRole == EMaster ? ENotifyMaster :ENotifySlave);
       
   126 	
       
   127 	if (aEvent.EventType()==eventType && aEvent.ErrorCode()==KErrNone)
       
   128 		{
       
   129 		LOG(_L("CRoleSwitcher RoleSwitch OK"));	
       
   130 		}
       
   131 	else 
       
   132 		{
       
   133 		LOG(_L("CRoleSwitcher RoleSwitch failed"));
       
   134 		}
       
   135 	}
       
   136 	
       
   137 void CRoleSwitcher::EventReceived(TBTBasebandEventNotification& aEvent)
       
   138 	{
       
   139 	LOG_FUNC
       
   140 	iState->EventReceived(*this, aEvent);
       
   141 	}
       
   142 		
       
   143 
       
   144 //----------------------------------------------------------------------------------
       
   145 // STATE FACTORY
       
   146 //----------------------------------------------------------------------------------
       
   147 
       
   148 CRoleSwitcherStateFactory* CRoleSwitcherStateFactory::NewL()
       
   149 	{
       
   150 	LOG_STATIC_FUNC
       
   151 	CRoleSwitcherStateFactory* ret=new (ELeave) CRoleSwitcherStateFactory();
       
   152 	CleanupStack::PushL(ret);
       
   153 	ret->ConstructL();
       
   154 	CleanupStack::Pop(ret);
       
   155 	return ret;
       
   156 	}
       
   157 
       
   158 void CRoleSwitcherStateFactory::ConstructL()
       
   159 	{
       
   160 	LOG_FUNC	
       
   161 	iStates[EIdle]					=new (ELeave) TRSStateIdle(*this);
       
   162 	iStates[EDisablingLPM]			=new (ELeave) TRSStateDisablingLPM(*this);
       
   163 	iStates[EDisablingEncryption]	=new (ELeave) TRSStateDisablingEncryption(*this);
       
   164 	iStates[EChangingRole]			=new (ELeave) TRSStateChangingRole(*this);
       
   165 	iStates[EChangingRoleWithEPR]	=new (ELeave) TRSStateChangingRoleWithEPR(*this);
       
   166 	iStates[EEnablingEncryption]	=new (ELeave) TRSStateEnablingEncryption(*this);
       
   167 	}
       
   168 
       
   169 CRoleSwitcherStateFactory::CRoleSwitcherStateFactory()
       
   170 	{
       
   171 	LOG_FUNC
       
   172 	iStates.DeleteAll();
       
   173 	}
       
   174 
       
   175 TRoleSwitcherState& CRoleSwitcherStateFactory::GetState(CRoleSwitcherStateFactory::TRoleSwitcherStates aState)
       
   176 	{
       
   177 	LOG_FUNC
       
   178 	__ASSERT_DEBUG(iStates[aState],  Panic(ERoleSwitcherInvalidState));
       
   179 	return *iStates[aState];
       
   180 	}
       
   181 
       
   182 TInt CRoleSwitcherStateFactory::StateIndex(const TRoleSwitcherState* aState) const
       
   183 	{
       
   184 	LOG_FUNC
       
   185 	TInt state;
       
   186 	for (state = 0; state < ERoleSwitcherMaxState; state++)
       
   187 		{
       
   188 		if (iStates[state] == aState)
       
   189 			{
       
   190 			return state;
       
   191 			}
       
   192 		}
       
   193 	
       
   194 	return KUnknownState;
       
   195 	}
       
   196 
       
   197 
       
   198 //----------------------------------------------------------------------------------
       
   199 // STATES
       
   200 //----------------------------------------------------------------------------------
       
   201 
       
   202 TRoleSwitcherState::TRoleSwitcherState(CRoleSwitcherStateFactory& aFactory)
       
   203 : iFactory(aFactory)
       
   204 	{
       
   205 	LOG_FUNC
       
   206 	}
       
   207 
       
   208 void TRoleSwitcherState::PanicInState(TLinkPanic aPanic) const
       
   209 	{
       
   210 	LOG_FUNC
       
   211 	Panic(aPanic, iFactory.StateIndex(this));
       
   212 	}
       
   213 
       
   214 void TRoleSwitcherState::ChangeState(CRoleSwitcher& aContext, CRoleSwitcherStateFactory::TRoleSwitcherStates aState) const
       
   215 	{
       
   216 	LOG_FUNC
       
   217 	
       
   218 	aContext.iState->Exit(aContext);
       
   219 
       
   220 #ifdef __FLOG_ACTIVE
       
   221 	TRoleSwitcherState* state=&iFactory.GetState(aState);
       
   222 	LOG2(_L("RoleSwitcher: State %S -> %S"), &aContext.iState->iName, &state->iName);
       
   223 #endif //__FLOG_ACTIVE
       
   224 	aContext.iState=&iFactory.GetState(aState);
       
   225 
       
   226 	aContext.iState->Enter(aContext);
       
   227 	}
       
   228 
       
   229 void TRoleSwitcherState::Enter(CRoleSwitcher& /*aContext*/) const
       
   230 	{
       
   231 	LOG_FUNC
       
   232 	// do nothing
       
   233 	}
       
   234 
       
   235 void TRoleSwitcherState::Exit(CRoleSwitcher& /*aContext*/) const
       
   236 	{
       
   237 	LOG_FUNC
       
   238 	// do nothing
       
   239 	}
       
   240 
       
   241 void TRoleSwitcherState::Start(CRoleSwitcher& /*aContext*/) const
       
   242 	{
       
   243 	LOG_FUNC
       
   244 	PanicInState(ERoleSwitcherStateMachineInvalidEvent);
       
   245 	}
       
   246 
       
   247 void TRoleSwitcherState::Error(CRoleSwitcher& aContext, TInt /*aErr*/) const
       
   248 	{
       
   249 	LOG_FUNC
       
   250 	aContext.CancelNotify();
       
   251 	aContext.RemoveTimer();
       
   252 	ChangeState(aContext, CRoleSwitcherStateFactory::EIdle);
       
   253 	}
       
   254 
       
   255 void TRoleSwitcherState::EventReceived(CRoleSwitcher& /*aContext*/, TBTBasebandEventNotification& /*aEvent*/) const
       
   256 	{
       
   257 	LOG_FUNC
       
   258 	// do nothing
       
   259 	}
       
   260 
       
   261 void TRoleSwitcherState::TimerExpired(CRoleSwitcher& aContext) const
       
   262 	{
       
   263 	LOG_FUNC
       
   264 	ChangeState(aContext, CRoleSwitcherStateFactory::EIdle);
       
   265 	}
       
   266 
       
   267 //----------------------------------------------------------------------------------
       
   268 
       
   269 TRSStateIdle::TRSStateIdle(CRoleSwitcherStateFactory& aFactory)
       
   270 : TRoleSwitcherState(aFactory)
       
   271 	{
       
   272 	LOG_FUNC
       
   273 	STATENAME("TRSStateIdle");
       
   274 	}
       
   275 
       
   276 void TRSStateIdle::Start(CRoleSwitcher& aContext) const
       
   277 	{
       
   278 	LOG_FUNC
       
   279 	aContext.QueueTimer(KTimeoutRoleSwitch);	// watchdog timer
       
   280 	ChangeState(aContext, CRoleSwitcherStateFactory::EDisablingLPM);
       
   281 	}	
       
   282 
       
   283 void TRSStateIdle::Enter(CRoleSwitcher& aContext) const
       
   284 	{
       
   285 	LOG_FUNC
       
   286 	// async call to delete the helper
       
   287 	aContext.iLink.AsyncDeleteRoleSwitcher();
       
   288 	}	
       
   289 
       
   290 //----------------------------------------------------------------------------------
       
   291 
       
   292 TRSStateDisablingLPM::TRSStateDisablingLPM(CRoleSwitcherStateFactory& aFactory)
       
   293 : TRoleSwitcherState(aFactory)
       
   294 	{
       
   295 	LOG_FUNC
       
   296 	STATENAME("TRSStateDisablingLPM");
       
   297 	}
       
   298 
       
   299 void TRSStateDisablingLPM::Enter(CRoleSwitcher& aContext) const
       
   300 	{
       
   301 	LOG_FUNC
       
   302 	// DisableLPM even if link is active to prevent possible LPM requests during encryption disabling
       
   303 
       
   304 	if (aContext.iLink.LinkMode() == EActiveMode)
       
   305 		{
       
   306 		aContext.DisableLPM();
       
   307 		if (aContext.IsEPRSupported())
       
   308 			{
       
   309 			ChangeState(aContext, CRoleSwitcherStateFactory::EChangingRoleWithEPR);
       
   310 			}
       
   311 		else
       
   312 			{
       
   313 			ChangeState(aContext, CRoleSwitcherStateFactory::EDisablingEncryption);
       
   314 			}
       
   315 		// don't wait for notification
       
   316 		}
       
   317 	else
       
   318 		{
       
   319 		aContext.NotifyBasebandEvent(ENotifyActiveMode);
       
   320 		aContext.DisableLPM();
       
   321 		}
       
   322 	}
       
   323 
       
   324 void TRSStateDisablingLPM::EventReceived(CRoleSwitcher& aContext, TBTBasebandEventNotification& aEvent) const
       
   325 	{
       
   326 	LOG_FUNC
       
   327 	if (aEvent.EventType()==ENotifyActiveMode && aEvent.ErrorCode()==KErrNone)
       
   328 		{
       
   329 		if (aContext.IsEPRSupported())
       
   330 			{
       
   331 			ChangeState(aContext, CRoleSwitcherStateFactory::EChangingRoleWithEPR);
       
   332 			}
       
   333 		else
       
   334 			{
       
   335 			ChangeState(aContext, CRoleSwitcherStateFactory::EDisablingEncryption);
       
   336 			}
       
   337 		}
       
   338 	else 
       
   339 		{
       
   340 		LOG(_L("CRoleSwitcher RoleSwitch failed in DisableLPM"));
       
   341 		// we can quit SM, don't need to rewind
       
   342 		ChangeState(aContext, CRoleSwitcherStateFactory::EIdle);
       
   343 		}
       
   344 	}
       
   345 
       
   346 //----------------------------------------------------------------------------------
       
   347 TRSStateDisablingEncryption::TRSStateDisablingEncryption(CRoleSwitcherStateFactory& aFactory)
       
   348 : TRoleSwitcherState(aFactory)
       
   349 	{
       
   350 	LOG_FUNC
       
   351 	STATENAME("TRSStateDisablingEncryption");
       
   352 	}
       
   353 
       
   354 void TRSStateDisablingEncryption::Enter(CRoleSwitcher& aContext) const
       
   355 	{
       
   356 	LOG_FUNC
       
   357 	aContext.SaveEncryption();
       
   358 	if (aContext.iIsEncrypted)
       
   359 		{
       
   360 		aContext.DisableEncryption();
       
   361 		}
       
   362 	else
       
   363 		{
       
   364 		ChangeState(aContext, CRoleSwitcherStateFactory::EChangingRole);
       
   365 		}
       
   366 	}
       
   367 
       
   368 void TRSStateDisablingEncryption::EventReceived(CRoleSwitcher& aContext, TBTBasebandEventNotification& aEvent) const
       
   369 	{
       
   370 	LOG_FUNC
       
   371 	if (aEvent.EventType()==ENotifyEncryptionChangeOff && aEvent.ErrorCode()==KErrNone)
       
   372 		{
       
   373 		ChangeState(aContext, CRoleSwitcherStateFactory::EChangingRole);
       
   374 		}
       
   375 	else 
       
   376 		{
       
   377 		LOG(_L("CRoleSwitcher RoleSwitch failed in DisableEncryption"));
       
   378 		// before quiting SM , try to enable LPM
       
   379 		ChangeState(aContext, CRoleSwitcherStateFactory::EIdle);
       
   380 		}
       
   381 	}
       
   382 
       
   383 void TRSStateDisablingEncryption::TimerExpired(CRoleSwitcher& aContext) const
       
   384 	{
       
   385 	LOG_FUNC
       
   386 	aContext.CancelNotify();
       
   387 	ChangeState(aContext, CRoleSwitcherStateFactory::EEnablingEncryption);
       
   388 	}
       
   389 
       
   390 //----------------------------------------------------------------------------------
       
   391 TRSStateChangingRole::TRSStateChangingRole(CRoleSwitcherStateFactory& aFactory)
       
   392 : TRoleSwitcherState(aFactory)
       
   393 	{
       
   394 	LOG_FUNC
       
   395 	STATENAME("TRSStateChangingRole");
       
   396 	}
       
   397 
       
   398 void TRSStateChangingRole::Enter(CRoleSwitcher& aContext) const
       
   399 	{
       
   400 	LOG_FUNC
       
   401 	aContext.ChangeRole();
       
   402 	}
       
   403 
       
   404 void TRSStateChangingRole::EventReceived(CRoleSwitcher& aContext, TBTBasebandEventNotification& __DEBUG_ONLY(aEvent)) const
       
   405 	{
       
   406 	LOG_FUNC
       
   407 	aContext.RemoveTimer();	// cancel watchdog timer
       
   408 
       
   409 	FTRACE(aContext.LogRoleSwitchSuccessful(aEvent));
       
   410 	
       
   411 
       
   412 	ChangeState(aContext, CRoleSwitcherStateFactory::EEnablingEncryption);
       
   413 	}
       
   414 
       
   415 void TRSStateChangingRole::TimerExpired(CRoleSwitcher& aContext) const
       
   416 	{
       
   417 	LOG_FUNC
       
   418 	aContext.CancelNotify();
       
   419 	ChangeState(aContext, CRoleSwitcherStateFactory::EEnablingEncryption);
       
   420 	}
       
   421 
       
   422 //----------------------------------------------------------------------------------
       
   423 TRSStateChangingRoleWithEPR::TRSStateChangingRoleWithEPR(CRoleSwitcherStateFactory& aFactory)
       
   424 : TRoleSwitcherState(aFactory)
       
   425 	{
       
   426 	LOG_FUNC
       
   427 	STATENAME("TRSStateChangingRoleWithEPR");
       
   428 	}
       
   429 
       
   430 void TRSStateChangingRoleWithEPR::Enter(CRoleSwitcher& aContext) const
       
   431 	{
       
   432 	LOG_FUNC
       
   433 	aContext.ChangeRole();
       
   434 	}
       
   435 
       
   436 void TRSStateChangingRoleWithEPR::EventReceived(CRoleSwitcher& aContext, TBTBasebandEventNotification& __DEBUG_ONLY(aEvent)) const
       
   437 	{
       
   438 	LOG_FUNC
       
   439 	aContext.RemoveTimer();	// cancel watchdog timer
       
   440 
       
   441 	FTRACE(aContext.LogRoleSwitchSuccessful(aEvent));
       
   442 		
       
   443 	ChangeState(aContext, CRoleSwitcherStateFactory::EIdle);
       
   444 	}
       
   445 
       
   446 void TRSStateChangingRoleWithEPR::TimerExpired(CRoleSwitcher& aContext) const
       
   447 	{
       
   448 	LOG_FUNC
       
   449 	aContext.CancelNotify();
       
   450 	ChangeState(aContext, CRoleSwitcherStateFactory::EIdle);
       
   451 	}
       
   452 
       
   453 //----------------------------------------------------------------------------------
       
   454 TRSStateEnablingEncryption::TRSStateEnablingEncryption(CRoleSwitcherStateFactory& aFactory)
       
   455 : TRoleSwitcherState(aFactory)
       
   456 	{
       
   457 	LOG_FUNC
       
   458 	STATENAME("TRSStateEnablingEncryption");
       
   459 	}
       
   460 
       
   461 void TRSStateEnablingEncryption::Enter(CRoleSwitcher& aContext) const
       
   462 	{
       
   463 	LOG_FUNC
       
   464 	if (aContext.iIsEncrypted)
       
   465 		{
       
   466 		aContext.QueueTimer(KTimeoutOneCommand);
       
   467 		aContext.EnableEncryption();
       
   468 		}
       
   469 	else
       
   470 		{
       
   471 		ChangeState(aContext, CRoleSwitcherStateFactory::EIdle);
       
   472 		}
       
   473 	}
       
   474 	
       
   475 void TRSStateEnablingEncryption::Exit(CRoleSwitcher& aContext) const
       
   476 	{
       
   477 	LOG_FUNC
       
   478 	if (aContext.iIsEncrypted)
       
   479 		{
       
   480 		// enable data traffic
       
   481 		aContext.iLinkMgr.LinkManagerProtocol().ACLController().SetParked(aContext.iLink.Handle(), EFalse);
       
   482 		}
       
   483 	}
       
   484 
       
   485 void TRSStateEnablingEncryption::EventReceived(CRoleSwitcher& aContext, TBTBasebandEventNotification& aEvent) const
       
   486 	{
       
   487 	LOG_FUNC
       
   488 	aContext.RemoveTimer(); // watchdog timer
       
   489 	if (aEvent.EventType()==ENotifyEncryptionChangeOn && aEvent.ErrorCode()==KErrNone)
       
   490 		{	
       
   491 		ChangeState(aContext, CRoleSwitcherStateFactory::EIdle);
       
   492 		aContext.iIsEncryptionDisabledForRoleSwitch = EFalse;
       
   493 		}
       
   494 	else 
       
   495 		{
       
   496 		LOG(_L("CRoleSwitcher SetEncryption failed, disconnect link"));
       
   497 		if (aContext.iLink.Terminate(ERemoteUserEndedConnection) != KErrNone) 
       
   498 			{
       
   499 			LOG(_L("CRoleSwitcher OOM"));
       
   500 			}
       
   501 		ChangeState(aContext, CRoleSwitcherStateFactory::EIdle);
       
   502 		}
       
   503 	}
       
   504 
       
   505 void TRSStateEnablingEncryption::TimerExpired(CRoleSwitcher& aContext) const
       
   506 	{
       
   507 	LOG_FUNC
       
   508 	LOG(_L("CRoleSwitcher Timeout in EncryptionEnable, disconnect"));
       
   509 	aContext.CancelNotify();			
       
   510 	if (aContext.iLink.Terminate(ERemoteUserEndedConnection) != KErrNone)
       
   511 			{
       
   512 			LOG(_L("CRoleSwitcher OOM"));
       
   513 			}
       
   514 	ChangeState(aContext, CRoleSwitcherStateFactory::EIdle);
       
   515 	}
       
   516 
       
   517 
       
   518