diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/linkmgr/encryptionkeyrefreshhelper.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btstack/linkmgr/encryptionkeyrefreshhelper.cpp Tue Sep 14 23:28:24 2010 +0300 @@ -0,0 +1,311 @@ +// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Symbian Foundation License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include + +#include "encryptionkeyrefreshhelper.h" +#include "hcifacade.h" +#include "linkmgr.h" + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, LOG_COMPONENT_LINKMGR); +#endif + +CEncryptionKeyRefresher::CEncryptionKeyRefresher(CPhysicalLinksManager& aLinkMgr, CPhysicalLink& aLink) + : CPhysicalLinkHelper(aLinkMgr, aLink) + { + LOG_FUNC + } + +CEncryptionKeyRefresher* CEncryptionKeyRefresher::NewL(CPhysicalLinksManager& aLinkMgr, CPhysicalLink& aLink) + { + LOG_STATIC_FUNC + CEncryptionKeyRefresher* self = new(ELeave) CEncryptionKeyRefresher(aLinkMgr, aLink); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +void CEncryptionKeyRefresher::ConstructL() + { + LOG_FUNC + + BaseConstructL(); + + iStateFactory = CEncryptionKeyRefresherStateFactory::NewL(); + iState = &(iStateFactory->GetState(CEncryptionKeyRefresherStateFactory::EIdle)); + } + +CEncryptionKeyRefresher::~CEncryptionKeyRefresher() + { + LOG_FUNC + } + +void CEncryptionKeyRefresher::EncryptionKeyRefreshComplete(TInt aError) + { + LOG_FUNC + iState->EncryptionKeyRefreshComplete(*this, aError); + } + +void CEncryptionKeyRefresher::TimerExpired() + { + LOG_FUNC + iState->TimerExpired(*this); + } + +void CEncryptionKeyRefresher::HandleError( TInt aError) + { + LOG_FUNC + iState->Error(*this, aError); + } + +void CEncryptionKeyRefresher::StartHelper() + { + LOG_FUNC + iState->Start(*this); + } + +void CEncryptionKeyRefresher::EventReceived(TBTBasebandEventNotification& aEvent) + { + LOG_FUNC + iState->EventReceived(*this, aEvent); + } + + +//---------------------------------------------------------------------------------- +// STATE FACTORY +//---------------------------------------------------------------------------------- + +CEncryptionKeyRefresherStateFactory* CEncryptionKeyRefresherStateFactory::NewL() + { + LOG_STATIC_FUNC + CEncryptionKeyRefresherStateFactory* ret=new (ELeave) CEncryptionKeyRefresherStateFactory(); + CleanupStack::PushL(ret); + ret->ConstructL(); + CleanupStack::Pop(ret); + return ret; + } + +void CEncryptionKeyRefresherStateFactory::ConstructL() + { + LOG_FUNC + iStates[EIdle] =new (ELeave) TEkrStateIdle(*this); + iStates[EDisablingLPM] =new (ELeave) TEkrStateDisablingLPM(*this); + iStates[ERefreshingKey] =new (ELeave) TEkrStateRefreshingKey(*this); + } + +CEncryptionKeyRefresherStateFactory::CEncryptionKeyRefresherStateFactory() + { + LOG_FUNC + iStates.DeleteAll(); + } + +const TEncryptionKeyRefresherState& CEncryptionKeyRefresherStateFactory::GetState(CEncryptionKeyRefresherStateFactory::TEncryptionKeyRefresherStates aState) const + { + LOG_FUNC + __ASSERT_DEBUG(iStates[aState], Panic(EEncryptionKeyRefresherInvalidState)); + return *iStates[aState]; + } + +TInt CEncryptionKeyRefresherStateFactory::StateIndex(const TEncryptionKeyRefresherState* aState) const + { + LOG_FUNC + TInt state; + for (state = 0; state < EEncryptionKeyRefresherMaxState; state++) + { + if (iStates[state] == aState) + { + return state; + } + } + + return KUnknownState; + } + + +//---------------------------------------------------------------------------------- +// STATES +//---------------------------------------------------------------------------------- + +TEncryptionKeyRefresherState::TEncryptionKeyRefresherState(CEncryptionKeyRefresherStateFactory& aFactory) +: iFactory(aFactory) + { + LOG_FUNC + } + +void TEncryptionKeyRefresherState::PanicInState(TLinkPanic aPanic) const + { + LOG_FUNC + Panic(aPanic, iFactory.StateIndex(this)); + } + +void TEncryptionKeyRefresherState::ChangeState(CEncryptionKeyRefresher& aContext, CEncryptionKeyRefresherStateFactory::TEncryptionKeyRefresherStates aState) const + { + LOG_FUNC + + aContext.iState->Exit(aContext); + +#ifdef __FLOG_ACTIVE + const TEncryptionKeyRefresherState* state=&iFactory.GetState(aState); + LOG2(_L("EncryptionKeyRefresher: State %S -> %S"), &aContext.iState->iName, &state->iName); +#endif //__FLOG_ACTIVE + aContext.iState=&iFactory.GetState(aState); + + aContext.iState->Enter(aContext); + } + +void TEncryptionKeyRefresherState::Enter(CEncryptionKeyRefresher& /*aContext*/) const + { + LOG_FUNC + // do nothing + } + +void TEncryptionKeyRefresherState::Exit(CEncryptionKeyRefresher& /*aContext*/) const + { + LOG_FUNC + // do nothing + } + +void TEncryptionKeyRefresherState::Start(CEncryptionKeyRefresher& /*aContext*/) const + { + LOG_FUNC + PanicInState(EEncryptionKeyRefresherStateMachineInvalidEvent); + } + +void TEncryptionKeyRefresherState::Error(CEncryptionKeyRefresher& aContext, TInt /*aErr*/) const + { + LOG_FUNC + aContext.CancelNotify(); + aContext.RemoveTimer(); + ChangeState(aContext, CEncryptionKeyRefresherStateFactory::EIdle); + } + +void TEncryptionKeyRefresherState::EventReceived(CEncryptionKeyRefresher& /*aContext*/, TBTBasebandEventNotification& /*aEvent*/) const + { + LOG_FUNC + // do nothing + } + +void TEncryptionKeyRefresherState::TimerExpired(CEncryptionKeyRefresher& aContext) const + { + LOG_FUNC + aContext.CancelNotify(); + ChangeState(aContext, CEncryptionKeyRefresherStateFactory::EIdle); + } + +void TEncryptionKeyRefresherState::EncryptionKeyRefreshComplete(CEncryptionKeyRefresher& /*aContext*/, TInt /*aError*/) const + { + LOG_FUNC + // do nothing + } + +//---------------------------------------------------------------------------------- + +TEkrStateIdle::TEkrStateIdle(CEncryptionKeyRefresherStateFactory& aFactory) +: TEncryptionKeyRefresherState(aFactory) + { + LOG_FUNC + STATENAME("TEkrStateIdle"); + } + +void TEkrStateIdle::Start(CEncryptionKeyRefresher& aContext) const + { + LOG_FUNC + aContext.QueueTimer(KTimeoutEncryptionKeyRefresh); // watchdog timer + ChangeState(aContext, CEncryptionKeyRefresherStateFactory::EDisablingLPM); + } + +void TEkrStateIdle::Enter(CEncryptionKeyRefresher& aContext) const + { + LOG_FUNC + // async call to delete the helper + aContext.iLink.AsyncDeleteKeyRefresher(); + } + +//---------------------------------------------------------------------------------- + +TEkrStateDisablingLPM::TEkrStateDisablingLPM(CEncryptionKeyRefresherStateFactory& aFactory) +: TEncryptionKeyRefresherState(aFactory) + { + LOG_FUNC + STATENAME("TEkrStateDisablingLPM"); + } + +void TEkrStateDisablingLPM::Enter(CEncryptionKeyRefresher& aContext) const + { + LOG_FUNC + + if (aContext.iLink.LinkMode() == EActiveMode) + { + // Skip straight on to refresh the key + ChangeState(aContext, CEncryptionKeyRefresherStateFactory::ERefreshingKey); + } + else + { + aContext.NotifyBasebandEvent(ENotifyActiveMode); + } + + // DisableLPM even if link is active to prevent possible LPM requests during key refresh + aContext.DisableLPM(); + } + +void TEkrStateDisablingLPM::EventReceived(CEncryptionKeyRefresher& aContext, TBTBasebandEventNotification& aEvent) const + { + LOG_FUNC + if (aEvent.EventType()==ENotifyActiveMode && aEvent.ErrorCode()==KErrNone) + { + ChangeState(aContext, CEncryptionKeyRefresherStateFactory::ERefreshingKey); + } + else + { + LOG(_L("CEncryptionKeyRefresher failed in DisableLPM")); + // If we can't put ourselves into active mode then don't bother with + // refresh, it'll probably cause more problems than it would solve + // we can quit SM, don't need to rewind + ChangeState(aContext, CEncryptionKeyRefresherStateFactory::EIdle); + } + } + +//---------------------------------------------------------------------------------- +TEkrStateRefreshingKey::TEkrStateRefreshingKey(CEncryptionKeyRefresherStateFactory& aFactory) +: TEncryptionKeyRefresherState(aFactory) + { + LOG_FUNC + STATENAME("TEkrStateRefreshingKey"); + } + +void TEkrStateRefreshingKey::Enter(CEncryptionKeyRefresher& aContext) const + { + LOG_FUNC + + TRAPD(err, aContext.iLinkMgr.HCIFacade().RefreshEncryptionKeyL(aContext.iLink.Handle())); + + if(err) + { + ChangeState(aContext, CEncryptionKeyRefresherStateFactory::EIdle); + } + } + +void TEkrStateRefreshingKey::EncryptionKeyRefreshComplete(CEncryptionKeyRefresher& aContext, TInt __DEBUG_ONLY(aError)) const + { + LOG_FUNC + LOG1(_L("EncryptionKeyRefresh completed with error %d"), aError); + + // Don't really care what the error is, this is just a best effort service + // anyway + ChangeState(aContext, CEncryptionKeyRefresherStateFactory::EIdle); + } +