# HG changeset patch # User Dremov Kirill (Nokia-D-MSW/Tampere) # Date 1284496104 -10800 # Node ID 99439b07e98035fa931a3ef44ce3180d936787a9 # Parent e9b924a62a66a50c6d24fa0bba0f07d09b4dd5df Revision: 201031 Kit: 201035 diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btextnotifiers/inc/BTExtNotifiers.h --- a/bluetooth/btextnotifiers/inc/BTExtNotifiers.h Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btextnotifiers/inc/BTExtNotifiers.h Tue Sep 14 23:28:24 2010 +0300 @@ -128,8 +128,8 @@ IMPORT_C TBool UplinkAccessAllowed() const; IMPORT_C TBool IsValid() const; - // Non-exported constructor. Allows creation of default NULL instance - TPanConnection(); + // Allows creation of default NULL instance + IMPORT_C TPanConnection(); private: TBTDevAddr iRemoteDeviceAddress; diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/bluetooth_stack.ini --- a/bluetooth/btstack/bluetooth_stack.ini Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/bluetooth_stack.ini Tue Sep 14 23:28:24 2010 +0300 @@ -19,6 +19,4 @@ [CoreHci] EcomUid= 0x102736DE -[lowpowermodeconfiguration] -overridelpmtimeout_microseconds= 0 diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/common/bt.h --- a/bluetooth/btstack/common/bt.h Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/common/bt.h Tue Sep 14 23:28:24 2010 +0300 @@ -44,7 +44,6 @@ EPreauthoriseDevice, // used for multiple SAPs operating in one usecase (eg AVRCP and GAVDP); ESubscribePhysicalLink, EUnsubscribePhysicalLink, - EOverrideLPMWithTimeout, EOverrideLPM, EUndoOverrideLPM, ETryToAndThenPreventHostEncryptionKeyRefresh, diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/common/bt_v2.mmp --- a/bluetooth/btstack/common/bt_v2.mmp Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/common/bt_v2.mmp Tue Sep 14 23:28:24 2010 +0300 @@ -78,6 +78,8 @@ SOURCE hcifacade_events.cpp SOURCE physicallinks.cpp SOURCE PhysicalLinkHelper.cpp +SOURCE roleswitchhelper.cpp +SOURCE encryptionkeyrefreshhelper.cpp SOURCE basebandsap.cpp SOURCE physicallinksmanager.cpp SOURCE physicallinkmetrics.cpp diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/l2cap/l2capSAPSignalHandler.cpp --- a/bluetooth/btstack/l2cap/l2capSAPSignalHandler.cpp Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/l2cap/l2capSAPSignalHandler.cpp Tue Sep 14 23:28:24 2010 +0300 @@ -813,8 +813,9 @@ { LOG_FUNC // The SAP is about to be detached from this signal handler. - // Ensure no park overrides are active. + // Ensure no overrides are active. UndoOverrideParkMode(); + UndoOverrideLPM(); // Check if this SH has any unsent commands // outstanding. @@ -916,15 +917,26 @@ iSAP->Protocol().ControlPlane().ModifyPhysicalLink(EUndoOverridePark, iSAP->RemoteDev()); } } - -void CL2CapSAPSignalHandler::OverrideLPMWithTimeout() + +void CL2CapSAPSignalHandler::OverrideLPM() { LOG_FUNC // Temporarily override all low power modes. A reference to the SAP is required // to get the remote device address. if(iSAP) { - iSAP->Protocol().ControlPlane().ModifyPhysicalLink(EOverrideLPMWithTimeout, iSAP->RemoteDev()); + iSAP->Protocol().ControlPlane().ModifyPhysicalLink(EOverrideLPM, iSAP->RemoteDev()); } } - + +void CL2CapSAPSignalHandler::UndoOverrideLPM() + { + LOG_FUNC + // Remove the temporary override of all low power modes. A reference to the SAP is + // required to get the remote device address. + if(iSAP) + { + iSAP->Protocol().ControlPlane().ModifyPhysicalLink(EUndoOverrideLPM, iSAP->RemoteDev()); + } + } + diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/l2cap/l2capSAPSignalHandler.h --- a/bluetooth/btstack/l2cap/l2capSAPSignalHandler.h Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/l2cap/l2capSAPSignalHandler.h Tue Sep 14 23:28:24 2010 +0300 @@ -141,7 +141,8 @@ void OverrideParkMode(); void UndoOverrideParkMode(); - void OverrideLPMWithTimeout(); + void OverrideLPM(); + void UndoOverrideLPM(); inline TInt SignalHandlerErrorCode() const; inline MSocketNotify::TOperationBitmasks SignalHandlerErrorAction() const; diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/l2cap/l2capSigStates.cpp --- a/bluetooth/btstack/l2cap/l2capSigStates.cpp Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/l2cap/l2capSigStates.cpp Tue Sep 14 23:28:24 2010 +0300 @@ -286,6 +286,8 @@ { LOG_FUNC // The SAP has requested a channel be opened. + // Override all LPMs to try and avoid signalling timeouts + aSignalHandler.OverrideLPM(); TInt err = aSignalHandler.ChannelConfig().UpdateLocalConfigWithEntityCapabilities(); if (err == KErrNone) @@ -298,9 +300,6 @@ // Update local Port. aSignalHandler.SetLocalPort(port); - // Override park to allow the connection to be made. - aSignalHandler.OverrideParkMode(); - // Active connection. Send a Connect Request command. err = aSignalHandler.ConstructConnectionRequest(); if(err == KErrNone) @@ -330,10 +329,8 @@ // Update local Port. aSignalHandler.SetLocalPort(port); - // Override park to allow the connection to be made. - aSignalHandler.OverrideParkMode(); - // Override all LPMs (if timeout not set to zero) - aSignalHandler.OverrideLPMWithTimeout(); + // Override all LPMs to try and avoid signalling timeouts + aSignalHandler.OverrideLPM(); // Send a response with a 'pending' result and start security procedure. err = aSignalHandler.ConstructConnectionResponse(aSignalHandler.GetOutstandingRequestID(), @@ -384,10 +381,16 @@ aSignalHandler.iOpenChannelRequestAwaitingPeerEntityConfig = EFalse; - // If Park mode has been overridden during either channel establishment or - // channel disconnect, remove the override. - // NB It is safe to call this method multiple times. + // Depending where we came from we may have applied either a + // park override or an all LPM override. We remove both these + // overrides because it's safe to remove an override that + // hasn't been applied. + // Note that although park is one of the LPMs the different + // levels of override are managed separately, so an + // UndoOverrideLPM does not remove an explicit park only + // override. aSignalHandler.UndoOverrideParkMode(); + aSignalHandler.UndoOverrideLPM(); // If the signal handler has left the closed state, it will have been added // to the SH list in the Muxer. Now that the closed state is being @@ -1091,8 +1094,16 @@ } else { - // Remove and park override. + // Depending where we came from we may have applied either a + // park override or an all LPM override. We remove both these + // overrides because it's safe to remove an override that + // hasn't been applied. + // Note that although park is one of the LPMs the different + // levels of override are managed separately, so an + // UndoOverrideLPM does not remove an explicit park only + // override. aSignalHandler.UndoOverrideParkMode(); + aSignalHandler.UndoOverrideLPM(); // Cancel the configuration timer. aSignalHandler.CancelTimer(); @@ -1149,7 +1160,23 @@ void TL2CAPSigStateWaitDisconnect::DisconnectResponse(CL2CapSAPSignalHandler& aSignalHandler) const { LOG_FUNC - aSignalHandler.DrainPendingCommands(); + // We've got a disconnect response, we're done. Any remaing stuff on the queue + // is redundant, so ditch it and close synchronously. + aSignalHandler.FlushAllQueues(); + + // If an error condition has been recorded forward the error + // to the SAP. + if(aSignalHandler.SignalHandlerErrorCode() != KErrNone) + { + Error(aSignalHandler, aSignalHandler.SignalHandlerErrorCode(), aSignalHandler.SignalHandlerErrorAction()); + } + else + { + // This will delete the signal handler if the SAP has detached. + aSignalHandler.SetState(iFactory.GetState(CL2CAPSignalStateFactory::EClosed)); + aSignalHandler.SignalHandlerDisconnectedCanClose(); + } + } // "Artificial" state events @@ -1173,7 +1200,9 @@ void TL2CAPSigStateWaitDisconnect::Enter(CL2CapSAPSignalHandler& aSignalHandler) const { LOG_FUNC - // Override park to allow the disconnect to continue. + // Only override park for disconnect. We need to be able + // to send the signalling, but we don't care if it takes + // ages. No point starting a sniff bun-fight. aSignalHandler.OverrideParkMode(); // Cancel the configuration timer. diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/linkmgr/MBtHostControllerEventInternalNotifier.h --- a/bluetooth/btstack/linkmgr/MBtHostControllerEventInternalNotifier.h Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/linkmgr/MBtHostControllerEventInternalNotifier.h Tue Sep 14 23:28:24 2010 +0300 @@ -67,6 +67,8 @@ virtual void RemoteName(THCIErrorCode /*aErr*/, const TBTDevAddr& /*aAddr*/, const TBTDeviceName8& /*aName*/) {}; virtual void SimplePairingComplete(const TBTDevAddr& /*aBDAddr*/, THCIErrorCode /*aErr*/) {}; + + virtual void EncryptionKeyRefreshComplete(THCIErrorCode /*aErr*/, THCIConnHandle /*aConnH*/) {}; }; #endif //_MBTHOSTCONTROLEREVENTINTERNALNOTIFIER_H_ diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/linkmgr/PhysicalLinkHelper.cpp --- a/bluetooth/btstack/linkmgr/PhysicalLinkHelper.cpp Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/linkmgr/PhysicalLinkHelper.cpp Tue Sep 14 23:28:24 2010 +0300 @@ -22,60 +22,37 @@ #include "ProxySAP.h" #include "linkmgr.h" + #ifdef __FLOG_ACTIVE _LIT8(KLogComponent, LOG_COMPONENT_LINKMGR); #endif -CRoleSwitcher::CRoleSwitcher(CPhysicalLinksManager& aLinkMgr, CPhysicalLink& aLink, TBTBasebandRole aRole) - : CTimer(CActive::EPriorityStandard) - , iLinkMgr(aLinkMgr) +CPhysicalLinkHelper::CPhysicalLinkHelper(CPhysicalLinksManager& aLinkMgr, CPhysicalLink& aLink) + : iLinkMgr(aLinkMgr) , iLink(aLink) - , iRole(aRole) - , iIsEncryptionDisabledForRoleSwitch(EFalse) { LOG_FUNC - iState = &iLinkMgr.RoleSwitcherStateFactory().GetState(CRoleSwitcherStateFactory::EIdle); - } - -CRoleSwitcher* CRoleSwitcher::NewL(CPhysicalLinksManager& aLinkMgr, CPhysicalLink& aLink, TBTBasebandRole aRole) - { - LOG_STATIC_FUNC - CRoleSwitcher* self = new(ELeave) CRoleSwitcher(aLinkMgr, aLink, aRole); - CleanupStack::PushL(self); - self->ConstructL(); - CleanupStack::Pop(self); - return self; } -void CRoleSwitcher::ConstructL() +void CPhysicalLinkHelper::BaseConstructL() { LOG_FUNC // create Proxy telling it the possible PHY iBTProxySAP = CBTProxySAP::NewL(iLinkMgr, &iLink); iBTProxySAP->SetNotify(this); - - TCallBack cb(EventReceivedCallBack, this); - iEventReceivedCallBack = new (ELeave)CAsyncCallBack(cb, EActiveHighPriority); - - CTimer::ConstructL(); - CActiveScheduler::Add(this); - - // add ourselves to the list in LinkMgr, LinkMgr will kick off the role change state machine - iLinkMgr.AddRoleSwitcher(*this); - iAddedToLinkMgr = ETrue; + + TCallBack ecb(EventReceivedCallBack, this); + iEventReceivedCallBack = new (ELeave)CAsyncCallBack(ecb, EActiveHighPriority); } -CRoleSwitcher::~CRoleSwitcher() +CPhysicalLinkHelper::~CPhysicalLinkHelper() { LOG_FUNC - if (iAddedToLinkMgr) - { - iLinkMgr.RemoveRoleSwitcher(*this); - } - - Cancel(); // watchdog timer + + RemoveTimer(); delete iBTProxySAP; + if (iEventReceivedCallBack) { iEventReceivedCallBack->Cancel(); @@ -83,158 +60,14 @@ } } -void CRoleSwitcher::DisableLPM() +void CPhysicalLinkHelper::DisableLPM() { LOG_FUNC TPckgBuf optionBuf; iBTProxySAP->SAPSetOption(KSolBtLMProxy, EBBRequestPreventAllLowPowerModes, optionBuf); } -void CRoleSwitcher::EnableLPM() - { - LOG_FUNC - TPckgBuf optionBuf; - iBTProxySAP->SAPSetOption(KSolBtLMProxy, EBBRequestAllowAllLowPowerModes, optionBuf); - } - -void CRoleSwitcher::DisableEncryption() - { - LOG_FUNC - // data traffic suspended - iLinkMgr.LinkManagerProtocol().ACLController().SetParked(iLink.Handle(), ETrue); - TBTBasebandEvent event(ENotifyEncryptionChangeOff); - iBTProxySAP->Ioctl(KSolBtLMProxy, KLMBasebandEventOneShotNotificationIoctl, &event); - iLinkMgr.Encrypt(EFalse, iLink); - - // set flag here, it's too late when we receive the event as AccessReqester - // might receive the baseband notification earlier then the flag is set! - iIsEncryptionDisabledForRoleSwitch = ETrue; - } - -void CRoleSwitcher::EnableEncryption() - { - LOG_FUNC - TBTBasebandEvent event(ENotifyEncryptionChangeOn); - iBTProxySAP->Ioctl(KSolBtLMProxy, KLMBasebandEventOneShotNotificationIoctl, &event); - iLinkMgr.Encrypt(ETrue, iLink); - // data traffic is enabled in IoctlComplete - } - -void CRoleSwitcher::ChangeRole() - { - LOG_FUNC - TBTBasebandEvent event(ENotifyAnyRole); - iBTProxySAP->Ioctl(KSolBtLMProxy, KLMBasebandEventOneShotNotificationIoctl, &event); - iLinkMgr.ChangeRole(iRole, iLink); - } - -void CRoleSwitcher::CancelIoctl() - { - LOG_FUNC - iBTProxySAP->CancelIoctl(KSolBtLMProxy, KLMBasebandEventOneShotNotificationIoctl); - } - -// Timer -void CRoleSwitcher::RunL() - { - LOG_FUNC - iState->TimerExpired(*this); - } - -TInt CRoleSwitcher::RunError(TInt aError) - { - LOG_FUNC - iState->Error(*this, aError); - return KErrNone; - } - -// From MSocketNotify -void CRoleSwitcher::NewData(TUint /*aCount*/) - { - LOG_FUNC - - } - -void CRoleSwitcher::CanSend() - { - LOG_FUNC - - } - -void CRoleSwitcher::ConnectComplete() - { - LOG_FUNC - - } - -void CRoleSwitcher::ConnectComplete(const TDesC8& /*aConnectData*/) - { - LOG_FUNC - - } - -void CRoleSwitcher::ConnectComplete(CServProviderBase& /*aSSP*/) - { - LOG_FUNC - - } - -void CRoleSwitcher::ConnectComplete(CServProviderBase& /*aSSP*/,const TDesC8& /*aConnectData*/) - { - LOG_FUNC - - } - -void CRoleSwitcher::CanClose(TDelete /*aDelete*/) - { - LOG_FUNC - - } - -void CRoleSwitcher::CanClose(const TDesC8& /*aDisconnectData*/,TDelete /*aDelete*/) - { - LOG_FUNC - - } - -void CRoleSwitcher::Error(TInt /*aError*/,TUint /*aOperationMask*/) - { - LOG_FUNC - - } - -void CRoleSwitcher::Disconnect(void) - { - LOG_FUNC - iState->Error(*this, KErrDisconnected); - } - -void CRoleSwitcher::Disconnect(TDesC8& /*aDisconnectData*/) - { - LOG_FUNC - iState->Error(*this, KErrDisconnected); - } - -void CRoleSwitcher::Start() - { - LOG_FUNC - iState->Start(*this); - } - -void CRoleSwitcher::Finish() - { - LOG_FUNC - // async call to delete this class - iLink.AsyncDeleteRoleSwitcher(); - } - -void CRoleSwitcher::SaveEncryption() - { - LOG_FUNC - iIsEncrypted = iLink.Encrypted(); - } - -TBool CRoleSwitcher::IsEPRSupported() const +TBool CPhysicalLinkHelper::IsEPRSupported() const { LOG_FUNC // For Lisbon (Bluetooth 2.1), if EPR is supported both locally and remotely, @@ -243,418 +76,144 @@ return iLink.IsEncryptionPauseResumeSupported(); } -void CRoleSwitcher::LogRoleSwitchSuccessful() const +void CPhysicalLinkHelper::NotifyBasebandEvent(TNotifyEvent aEvent) + { + LOG_FUNC + TBTBasebandEvent event(aEvent.NotifyEvent()); + iBTProxySAP->Ioctl(KSolBtLMProxy, KLMBasebandEventOneShotNotificationIoctl, &event); + } + +void CPhysicalLinkHelper::CancelNotify() + { + LOG_FUNC + iBTProxySAP->CancelIoctl(KSolBtLMProxy, KLMBasebandEventOneShotNotificationIoctl); + } + +void CPhysicalLinkHelper::QueueTimer(TTimeIntervalMicroSeconds32 aTimerVal) + { + LOG_FUNC + + TCallBack cb(TimerExpiredCallBack, this); + iTimerEntry.Set(cb); + BTSocketTimer::Queue(aTimerVal, iTimerEntry); + } + + +void CPhysicalLinkHelper::RemoveTimer() + { + LOG_FUNC + + BTSocketTimer::Remove(iTimerEntry); + } + +// From MSocketNotify +void CPhysicalLinkHelper::NewData(TUint /*aCount*/) + { + LOG_FUNC + + } + +void CPhysicalLinkHelper::CanSend() + { + LOG_FUNC + + } + +void CPhysicalLinkHelper::ConnectComplete() { LOG_FUNC - TInt eventType; - eventType = (iRole == EMaster ? ENotifyMaster :ENotifySlave); + + } + +void CPhysicalLinkHelper::ConnectComplete(const TDesC8& /*aConnectData*/) + { + LOG_FUNC + + } + +void CPhysicalLinkHelper::ConnectComplete(CServProviderBase& /*aSSP*/) + { + LOG_FUNC - if (iBasebandEvent.EventType()==eventType && - iBasebandEvent.ErrorCode()==KErrNone) - { - LOG(_L("CRoleSwitcher RoleSwitch OK")); - } - else - { - LOG(_L("CRoleSwitcher RoleSwitch failed")); - } + } + +void CPhysicalLinkHelper::ConnectComplete(CServProviderBase& /*aSSP*/,const TDesC8& /*aConnectData*/) + { + LOG_FUNC + + } + +void CPhysicalLinkHelper::CanClose(TDelete /*aDelete*/) + { + LOG_FUNC + } -void CRoleSwitcher::IoctlComplete(TDesC8 *aBuf) +void CPhysicalLinkHelper::CanClose(const TDesC8& /*aDisconnectData*/,TDelete /*aDelete*/) + { + LOG_FUNC + + } + +void CPhysicalLinkHelper::Error(TInt /*aError*/,TUint /*aOperationMask*/) + { + LOG_FUNC + + } + +void CPhysicalLinkHelper::Disconnect(void) + { + LOG_FUNC + Error(KErrDisconnected); + } + +void CPhysicalLinkHelper::Disconnect(TDesC8& /*aDisconnectData*/) + { + LOG_FUNC + Error(KErrDisconnected); + } + +void CPhysicalLinkHelper::IoctlComplete(TDesC8 *aBuf) { LOG_FUNC const TBTBasebandEventNotification* event = reinterpret_cast(aBuf->Ptr()); iBasebandEvent = *event; iEventReceivedCallBack->CallBack(); } - -/*static*/ TInt CRoleSwitcher::EventReceivedCallBack(TAny* aRoleSwitcher) - { - LOG_STATIC_FUNC - CRoleSwitcher* roleSwitcher = static_cast(aRoleSwitcher); - roleSwitcher->iState->EventReceived(*roleSwitcher); - return EFalse; - } - -//---------------------------------------------------------------------------------- -// STATE FACTORY -//---------------------------------------------------------------------------------- - -CRoleSwitcherStateFactory* CRoleSwitcherStateFactory::NewL() +/*static*/ TInt CPhysicalLinkHelper::EventReceivedCallBack(TAny* aThis) { LOG_STATIC_FUNC - CRoleSwitcherStateFactory* ret=new (ELeave) CRoleSwitcherStateFactory(); - CleanupStack::PushL(ret); - ret->ConstructL(); - CleanupStack::Pop(ret); - return ret; - } - -void CRoleSwitcherStateFactory::ConstructL() - { - LOG_FUNC - iStates[EIdle] =new (ELeave) TRSStateIdle(*this); - iStates[EDisablingLPM] =new (ELeave) TRSStateDisablingLPM(*this); - iStates[EDisablingEncryption] =new (ELeave) TRSStateDisablingEncryption(*this); - iStates[EChangingRole] =new (ELeave) TRSStateChangingRole(*this); - iStates[EChangingRoleWithEPR] =new (ELeave) TRSStateChangingRoleWithEPR(*this); - iStates[EEnablingEncryption] =new (ELeave) TRSStateEnablingEncryption(*this); - } - -CRoleSwitcherStateFactory::CRoleSwitcherStateFactory() - { - LOG_FUNC - iStates.DeleteAll(); - } - -TRoleSwitcherState& CRoleSwitcherStateFactory::GetState(CRoleSwitcherStateFactory::TRoleSwitcherStates aState) - { - LOG_FUNC - __ASSERT_DEBUG(iStates[aState], Panic(ERoleSwitcherInvalidState)); - return *iStates[aState]; - } - -TInt CRoleSwitcherStateFactory::StateIndex(const TRoleSwitcherState* aState) const - { - LOG_FUNC - TInt state; - for (state = 0; state < ERoleSwitcherMaxState; state++) - { - if (iStates[state] == aState) - { - return state; - } - } - - return KUnknownState; - } - - -//---------------------------------------------------------------------------------- -// STATES -//---------------------------------------------------------------------------------- - -TRoleSwitcherState::TRoleSwitcherState(CRoleSwitcherStateFactory& aFactory) -: iFactory(aFactory) - { - LOG_FUNC - } - -void TRoleSwitcherState::PanicInState(TLinkPanic aPanic) const - { - LOG_FUNC - Panic(aPanic, iFactory.StateIndex(this)); - } - -void TRoleSwitcherState::ChangeState(CRoleSwitcher& aContext, CRoleSwitcherStateFactory::TRoleSwitcherStates aState) const - { - LOG_FUNC - - aContext.iState->Exit(aContext); - -#ifdef __FLOG_ACTIVE - TRoleSwitcherState* state=&iFactory.GetState(aState); - LOG2(_L("RoleSwitcher: State %S -> %S"), &aContext.iState->iName, &state->iName); -#endif //__FLOG_ACTIVE - aContext.iState=&iFactory.GetState(aState); - - aContext.iState->Enter(aContext); + CPhysicalLinkHelper* helper = static_cast(aThis); + helper->DoEventReceivedCallBack(); + return EFalse; } -void TRoleSwitcherState::Enter(CRoleSwitcher& /*aContext*/) const - { - LOG_FUNC - // do nothing - } - -void TRoleSwitcherState::Exit(CRoleSwitcher& /*aContext*/) const - { - LOG_FUNC - // do nothing - } - -void TRoleSwitcherState::Start(CRoleSwitcher& /*aContext*/) const - { - LOG_FUNC - PanicInState(ERoleSwitcherStateMachineInvalidEvent); - } - -void TRoleSwitcherState::Error(CRoleSwitcher& aContext, TInt /*aErr*/) const - { - LOG_FUNC - aContext.CancelIoctl(); - aContext.Cancel(); - ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); - } - -void TRoleSwitcherState::EventReceived(CRoleSwitcher& /*aContext*/) const - { - LOG_FUNC - // do nothing - } - -void TRoleSwitcherState::TimerExpired(CRoleSwitcher& aContext) const - { - LOG_FUNC - ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); - } - -//---------------------------------------------------------------------------------- - -TRSStateIdle::TRSStateIdle(CRoleSwitcherStateFactory& aFactory) -: TRoleSwitcherState(aFactory) - { - LOG_FUNC - STATENAME("TRSStateIdle"); - } - -void TRSStateIdle::Start(CRoleSwitcher& aContext) const - { - LOG_FUNC - aContext.After(KTimeoutRoleSwitch); // watchdog timer - ChangeState(aContext, CRoleSwitcherStateFactory::EDisablingLPM); - } - -void TRSStateIdle::Enter(CRoleSwitcher& aContext) const - { - LOG_FUNC - aContext.Finish(); - } - -//---------------------------------------------------------------------------------- - -TRSStateDisablingLPM::TRSStateDisablingLPM(CRoleSwitcherStateFactory& aFactory) -: TRoleSwitcherState(aFactory) - { - LOG_FUNC - STATENAME("TRSStateDisablingLPM"); - } - -void TRSStateDisablingLPM::Enter(CRoleSwitcher& aContext) const - { - LOG_FUNC - // DisableLPM even if link is active to prevent possible LPM requests during encryption disabling - - if (aContext.iLink.LinkMode() == EActiveMode) - { - aContext.DisableLPM(); - if (aContext.IsEPRSupported()) - { - ChangeState(aContext, CRoleSwitcherStateFactory::EChangingRoleWithEPR); - } - else - { - ChangeState(aContext, CRoleSwitcherStateFactory::EDisablingEncryption); - } - // don't wait for notification - } - else - { - TBTBasebandEvent event(ENotifyActiveMode); - aContext.iBTProxySAP->Ioctl(KSolBtLMProxy, KLMBasebandEventOneShotNotificationIoctl, &event); - aContext.DisableLPM(); - } - } - -void TRSStateDisablingLPM::EventReceived(CRoleSwitcher& aContext) const +void CPhysicalLinkHelper::DoEventReceivedCallBack() { LOG_FUNC - if (aContext.iBasebandEvent.EventType()==ENotifyActiveMode && - aContext.iBasebandEvent.ErrorCode()==KErrNone) - { - if (aContext.IsEPRSupported()) - { - ChangeState(aContext, CRoleSwitcherStateFactory::EChangingRoleWithEPR); - } - else - { - ChangeState(aContext, CRoleSwitcherStateFactory::EDisablingEncryption); - } - } - else - { - LOG(_L("CRoleSwitcher RoleSwitch failed in DisableLPM")); - // we can quit SM, don't need to rewind - ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); - } - } - -//---------------------------------------------------------------------------------- -TRSStateDisablingEncryption::TRSStateDisablingEncryption(CRoleSwitcherStateFactory& aFactory) -: TRoleSwitcherState(aFactory) - { - LOG_FUNC - STATENAME("TRSStateDisablingEncryption"); - } - -void TRSStateDisablingEncryption::Enter(CRoleSwitcher& aContext) const - { - LOG_FUNC - aContext.SaveEncryption(); - if (aContext.iIsEncrypted) - { - aContext.DisableEncryption(); - } - else - { - ChangeState(aContext, CRoleSwitcherStateFactory::EChangingRole); - } - } - -void TRSStateDisablingEncryption::EventReceived(CRoleSwitcher& aContext) const - { - LOG_FUNC - if (aContext.iBasebandEvent.EventType()==ENotifyEncryptionChangeOff && - aContext.iBasebandEvent.ErrorCode()==KErrNone) - { - ChangeState(aContext, CRoleSwitcherStateFactory::EChangingRole); - } - else - { - LOG(_L("CRoleSwitcher RoleSwitch failed in DisableEncryption")); - // before quiting SM , try to enable LPM - aContext.EnableLPM(); - ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); - } - } - -void TRSStateDisablingEncryption::TimerExpired(CRoleSwitcher& aContext) const - { - LOG_FUNC - aContext.CancelIoctl(); - ChangeState(aContext, CRoleSwitcherStateFactory::EEnablingEncryption); - } - -//---------------------------------------------------------------------------------- -TRSStateChangingRole::TRSStateChangingRole(CRoleSwitcherStateFactory& aFactory) -: TRoleSwitcherState(aFactory) - { - LOG_FUNC - STATENAME("TRSStateChangingRole"); - } - -void TRSStateChangingRole::Enter(CRoleSwitcher& aContext) const - { - LOG_FUNC - aContext.ChangeRole(); - } - -void TRSStateChangingRole::EventReceived(CRoleSwitcher& aContext) const - { - LOG_FUNC - aContext.Cancel(); // cancel watchdog timer - - FTRACE(aContext.LogRoleSwitchSuccessful()); - - - ChangeState(aContext, CRoleSwitcherStateFactory::EEnablingEncryption); - } - -void TRSStateChangingRole::TimerExpired(CRoleSwitcher& aContext) const - { - LOG_FUNC - aContext.CancelIoctl(); - ChangeState(aContext, CRoleSwitcherStateFactory::EEnablingEncryption); + EventReceived(iBasebandEvent); } -//---------------------------------------------------------------------------------- -TRSStateChangingRoleWithEPR::TRSStateChangingRoleWithEPR(CRoleSwitcherStateFactory& aFactory) -: TRoleSwitcherState(aFactory) +/*static*/ TInt CPhysicalLinkHelper::TimerExpiredCallBack(TAny* aThis) { - LOG_FUNC - STATENAME("TRSStateChangingRoleWithEPR"); - } - -void TRSStateChangingRoleWithEPR::Enter(CRoleSwitcher& aContext) const - { - LOG_FUNC - aContext.ChangeRole(); + LOG_STATIC_FUNC + CPhysicalLinkHelper* helper = static_cast(aThis); + helper->DoTimerExpiredCallBack(); + return EFalse; } -void TRSStateChangingRoleWithEPR::EventReceived(CRoleSwitcher& aContext) const - { - LOG_FUNC - aContext.Cancel(); // cancel watchdog timer - - FTRACE(aContext.LogRoleSwitchSuccessful()); - - ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); - } - -void TRSStateChangingRoleWithEPR::TimerExpired(CRoleSwitcher& aContext) const - { - LOG_FUNC - aContext.CancelIoctl(); - ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); - } - -//---------------------------------------------------------------------------------- -TRSStateEnablingEncryption::TRSStateEnablingEncryption(CRoleSwitcherStateFactory& aFactory) -: TRoleSwitcherState(aFactory) - { - LOG_FUNC - STATENAME("TRSStateEnablingEncryption"); - } - -void TRSStateEnablingEncryption::Enter(CRoleSwitcher& aContext) const +void CPhysicalLinkHelper::DoTimerExpiredCallBack() { LOG_FUNC - if (aContext.iIsEncrypted) - { - aContext.After(KTimeoutOneCommand); - aContext.EnableEncryption(); - } - else - { - aContext.EnableLPM(); - ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); - } - } - -void TRSStateEnablingEncryption::Exit(CRoleSwitcher& aContext) const - { - LOG_FUNC - if (aContext.iIsEncrypted) - { - // enable data traffic - aContext.iLinkMgr.LinkManagerProtocol().ACLController().SetParked(aContext.iLink.Handle(), EFalse); - } + TimerExpired(); } -void TRSStateEnablingEncryption::EventReceived(CRoleSwitcher& aContext) const - { - LOG_FUNC - aContext.Cancel(); // watchdog timer - if (aContext.iBasebandEvent.EventType()==ENotifyEncryptionChangeOn && - aContext.iBasebandEvent.ErrorCode()==KErrNone) - { - aContext.EnableLPM(); - ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); - aContext.iIsEncryptionDisabledForRoleSwitch = EFalse; - } - else - { - LOG(_L("CRoleSwitcher SetEncryption failed, disconnect link")); - if (aContext.iLink.Terminate(ERemoteUserEndedConnection) != KErrNone) - { - LOG(_L("CRoleSwitcher OOM")); - } - ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); - } - } - -void TRSStateEnablingEncryption::TimerExpired(CRoleSwitcher& aContext) const - { - LOG_FUNC - LOG(_L("CRoleSwitcher Timeout in EncryptionEnable, disconnect")); - aContext.CancelIoctl(); - if (aContext.iLink.Terminate(ERemoteUserEndedConnection) != KErrNone) - { - LOG(_L("CRoleSwitcher OOM")); - } - ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); - } + + + + + diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/linkmgr/PhysicalLinkHelper.h --- a/bluetooth/btstack/linkmgr/PhysicalLinkHelper.h Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/linkmgr/PhysicalLinkHelper.h Tue Sep 14 23:28:24 2010 +0300 @@ -22,28 +22,25 @@ #include "linkutil.h" #include -// watchdog for first half of the SM including: -// DisablingLPM, DisablingEncryption, RoleSwitch -const TUint KTimeoutRoleSwitch = 3000000; // 3 s; - -// watchdog for EnablingEncryption -const TUint KTimeoutOneCommand = 2000000; // 2 s; - -class TRoleSwitcherState; - -NONSHARABLE_CLASS(CRoleSwitcher) : public CTimer, public MSocketNotify +// A struct to allow both single event and combination events to be passed for requesting +// notification. This effectively moves the cast to a TInt to below the API rather than +// being required by the client. +struct TNotifyEvent { - friend class TRoleSwitcherState; - friend class TRSStateDisablingLPM; - friend class TRSStateDisablingEncryption; - friend class TRSStateChangingRole; - friend class TRSStateChangingRoleWithEPR; - friend class TRSStateEnablingEncryption; +public: + TNotifyEvent(TBTPhysicalLinkStateNotifier aSingleEvent) : iEvent(aSingleEvent) {}; + TNotifyEvent(TBTPhysicalLinkStateNotifierCombinations aComboEvent) : iEvent(aComboEvent) {}; -public: + TInt NotifyEvent() const {return iEvent;}; +private: + TInt iEvent; + }; - static CRoleSwitcher* NewL(CPhysicalLinksManager& aLinkMgr, CPhysicalLink& aLink, TBTBasebandRole aRole); - ~CRoleSwitcher(); + +NONSHARABLE_CLASS(CPhysicalLinkHelper) : public CBase, public MSocketNotify + { +public: + ~CPhysicalLinkHelper(); // From MSocketNotify void NewData(TUint aCount); @@ -61,196 +58,50 @@ void NoBearer(const TDesC8& /*aConnectionInf*/) {}; void Bearer(const TDesC8& /*aConnectionInf*/) {}; - void Start(); - void Finish(); + virtual void StartHelper() = 0; + inline const TBTDevAddr& BDAddr() const; - inline TBTBasebandRole RequestedRole() const; - inline TBool IsEncryptionDisabledForRoleSwitch() const; - TBool IsEPRSupported() const; - void LogRoleSwitchSuccessful() const; - TSglQueLink iQLink; -private: - CRoleSwitcher(CPhysicalLinksManager& aLinkMgr, CPhysicalLink& aLink, TBTBasebandRole aRole); - void ConstructL(); +protected: + CPhysicalLinkHelper(CPhysicalLinksManager& aLinkMgr, CPhysicalLink& aLink); + void BaseConstructL(); void DisableLPM(); - void DisableEncryption(); - void ChangeRole(); - void EnableEncryption(); - void EnableLPM(); - void CancelIoctl(); - void SaveEncryption(); - // CTimer - void RunL(); - TInt RunError(TInt aError); + void QueueTimer(TTimeIntervalMicroSeconds32 aTimerVal); + void RemoveTimer(); + void NotifyBasebandEvent(TNotifyEvent aEvent); + void CancelNotify(); - static TInt EventReceivedCallBack(TAny* aRoleSwitcher); - // Async Callback to notify baseband event received. - CAsyncCallBack* iEventReceivedCallBack; - TBTBasebandEventNotification iBasebandEvent; - TBool iIsEncrypted; - TBool iIsActive; // LinkMode - TBool iAddedToLinkMgr; - CPhysicalLinksManager& iLinkMgr; - CPhysicalLink& iLink; - TBTBasebandRole iRole; // Requested role - CBTProxySAP* iBTProxySAP; - TRoleSwitcherState* iState; - TBool iIsEncryptionDisabledForRoleSwitch; - }; - -//-------------------------------------------------- -// STATE FACTORY -//-------------------------------------------------- - -/** - Factory for the RoleSwitcher states - - The states are flyweight classes -**/ -NONSHARABLE_CLASS(CRoleSwitcherStateFactory) : public CBase - { -public: - static CRoleSwitcherStateFactory* NewL(); - - enum TRoleSwitcherStates - { - EIdle, - EDisablingLPM, - EDisablingEncryption, - EChangingRole, - EChangingRoleWithEPR, - EEnablingEncryption, - // *** keep next one last *** - ERoleSwitcherMaxState, - }; + TBool IsEPRSupported() const; - TRoleSwitcherState& GetState(TRoleSwitcherStates aState); - TInt StateIndex(const TRoleSwitcherState* aState) const; + virtual void TimerExpired() = 0; + virtual void HandleError(TInt aError) = 0; + virtual void EventReceived(TBTBasebandEventNotification& aEvent) = 0; private: - CRoleSwitcherStateFactory(); - void ConstructL(); - TFixedArray iStates; + static TInt EventReceivedCallBack(TAny* aThis); + void DoEventReceivedCallBack(); + + static TInt TimerExpiredCallBack(TAny* aThis); + void DoTimerExpiredCallBack(); + +protected: + CPhysicalLinksManager& iLinkMgr; + CPhysicalLink& iLink; + +private: + // Async Callback to notify baseband event received. + CAsyncCallBack* iEventReceivedCallBack; + TBTBasebandEventNotification iBasebandEvent; + CBTProxySAP* iBTProxySAP; + + TDeltaTimerEntry iTimerEntry; }; - - -//-------------------------------------------------- -// STATES, base -//-------------------------------------------------- - -NONSHARABLE_CLASS(TRoleSwitcherState) - { -public: - TRoleSwitcherState(CRoleSwitcherStateFactory& aFactory); - - virtual void Enter(CRoleSwitcher& aContext) const; - virtual void Exit(CRoleSwitcher& aContext) const; - - virtual void Start(CRoleSwitcher& aContext) const; - virtual void EventReceived(CRoleSwitcher& aContext) const; - virtual void Error(CRoleSwitcher& aContext, TInt aErr) const; - virtual void TimerExpired(CRoleSwitcher& aContext) const; - -protected: - // Exits old state, sets the new state, and enters it. - void ChangeState(CRoleSwitcher& aContext, CRoleSwitcherStateFactory::TRoleSwitcherStates aState) const; - void PanicInState(TLinkPanic aPanic) const; - -protected: - CRoleSwitcherStateFactory& iFactory; -#ifdef __FLOG_ACTIVE - TBuf<48> iName; -#endif - }; - - -//-------------------------------------------------- -// STATES -//-------------------------------------------------- - -NONSHARABLE_CLASS(TRSStateIdle) : public TRoleSwitcherState - { -public: - TRSStateIdle(CRoleSwitcherStateFactory& aFactory); - - virtual void Enter(CRoleSwitcher& aContext) const; - virtual void Start(CRoleSwitcher& aContext) const; - }; - - -NONSHARABLE_CLASS(TRSStateDisablingLPM) : public TRoleSwitcherState - { -public: - TRSStateDisablingLPM(CRoleSwitcherStateFactory& aFactory); - - virtual void Enter(CRoleSwitcher& aContext) const; - virtual void EventReceived(CRoleSwitcher& aContext) const; - }; - -NONSHARABLE_CLASS(TRSStateDisablingEncryption) : public TRoleSwitcherState - { -public: - TRSStateDisablingEncryption(CRoleSwitcherStateFactory& aFactory); - - virtual void Enter(CRoleSwitcher& aContext) const; - virtual void EventReceived(CRoleSwitcher& aContext) const; - virtual void TimerExpired(CRoleSwitcher& aContext) const; - }; - -NONSHARABLE_CLASS(TRSStateChangingRole) : public TRoleSwitcherState - { -public: - TRSStateChangingRole(CRoleSwitcherStateFactory& aFactory); - - virtual void Enter(CRoleSwitcher& aContext) const; - virtual void EventReceived(CRoleSwitcher& aContext) const; - virtual void TimerExpired(CRoleSwitcher& aContext) const; - }; - -NONSHARABLE_CLASS(TRSStateChangingRoleWithEPR) : public TRoleSwitcherState - { -public: - TRSStateChangingRoleWithEPR(CRoleSwitcherStateFactory& aFactory); - - virtual void Enter(CRoleSwitcher& aContext) const; - virtual void EventReceived(CRoleSwitcher& aContext) const; - virtual void TimerExpired(CRoleSwitcher& aContext) const; - }; - -NONSHARABLE_CLASS(TRSStateEnablingEncryption) : public TRoleSwitcherState - { -public: - TRSStateEnablingEncryption(CRoleSwitcherStateFactory& aFactory); - - virtual void Enter(CRoleSwitcher& aContext) const; - virtual void Exit(CRoleSwitcher& aContext) const; - virtual void EventReceived(CRoleSwitcher& aContext) const; - virtual void TimerExpired(CRoleSwitcher& aContext) const; - }; - -#ifdef __FLOG_ACTIVE -#define STATENAME(x) iName=_L(x) -#else -#define STATENAME(x) -#endif - -inline const TBTDevAddr& CRoleSwitcher::BDAddr() const +inline const TBTDevAddr& CPhysicalLinkHelper::BDAddr() const { return iLink.BDAddr(); } -inline TBTBasebandRole CRoleSwitcher::RequestedRole() const - { - return iRole; - } - -inline TBool CRoleSwitcher::IsEncryptionDisabledForRoleSwitch() const - { - return iIsEncryptionDisabledForRoleSwitch; - } - #endif //PHYSICALLINKHELPER_H_ 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); + } + diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/linkmgr/encryptionkeyrefreshhelper.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btstack/linkmgr/encryptionkeyrefreshhelper.h Tue Sep 14 23:28:24 2010 +0300 @@ -0,0 +1,169 @@ +// 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: +// + +#ifndef ENCRYPTIONKEYREFRESHHELPER_H +#define ENCRYPTIONKEYREFRESHHELPER_H + + +#include +#include + +#include "debug.h" +#include "linkutil.h" +#include "physicallinkhelper.h" +#include "physicallinks.h" + +// watchdog +const TUint KTimeoutEncryptionKeyRefresh = 3000000; // 3 s; + +class TEncryptionKeyRefresherState; +class CEncryptionKeyRefresherStateFactory; +NONSHARABLE_CLASS(CEncryptionKeyRefresher) : public CPhysicalLinkHelper + { + friend class TEncryptionKeyRefresherState; + friend class TEkrStateIdle; + friend class TEkrStateDisablingLPM; + friend class TEkrStateRefreshingKey; + +public: + static CEncryptionKeyRefresher* NewL(CPhysicalLinksManager& aLinkMgr, CPhysicalLink& aLink); + ~CEncryptionKeyRefresher(); + + virtual void StartHelper(); + + void EncryptionKeyRefreshComplete(TInt aError); + +private: + CEncryptionKeyRefresher(CPhysicalLinksManager& aLinkMgr, CPhysicalLink& aLink); + void ConstructL(); + + virtual void TimerExpired(); + virtual void HandleError(TInt aError); + virtual void EventReceived(TBTBasebandEventNotification& aEvent); + +private: + CEncryptionKeyRefresherStateFactory* iStateFactory; + const TEncryptionKeyRefresherState* iState; + }; + +//-------------------------------------------------- +// STATE FACTORY +//-------------------------------------------------- + +/** + Factory for the EncryptionKeyRefresher states + + The states are flyweight classes +**/ +NONSHARABLE_CLASS(CEncryptionKeyRefresherStateFactory) : public CBase + { +public: + static CEncryptionKeyRefresherStateFactory* NewL(); + + enum TEncryptionKeyRefresherStates + { + EIdle, + EDisablingLPM, + ERefreshingKey, + // Note that we don't need a state to enable LPM again + // as this will happen implicitly when we close our + // proxy SAP. + // *** keep next one last *** + EEncryptionKeyRefresherMaxState, + }; + + const TEncryptionKeyRefresherState& GetState(TEncryptionKeyRefresherStates aState) const; + TInt StateIndex(const TEncryptionKeyRefresherState* aState) const; + +private: + CEncryptionKeyRefresherStateFactory(); + void ConstructL(); + TFixedArray iStates; + }; + + + +//-------------------------------------------------- +// STATES, base +//-------------------------------------------------- + +NONSHARABLE_CLASS(TEncryptionKeyRefresherState) + { +public: + TEncryptionKeyRefresherState(CEncryptionKeyRefresherStateFactory& aFactory); + + virtual void Enter(CEncryptionKeyRefresher& aContext) const; + virtual void Exit(CEncryptionKeyRefresher& aContext) const; + + virtual void Start(CEncryptionKeyRefresher& aContext) const; + virtual void EventReceived(CEncryptionKeyRefresher& aContext, TBTBasebandEventNotification& aEvent) const; + virtual void Error(CEncryptionKeyRefresher& aContext, TInt aErr) const; + virtual void TimerExpired(CEncryptionKeyRefresher& aContext) const; + virtual void EncryptionKeyRefreshComplete(CEncryptionKeyRefresher& aContext, TInt aError) const; + +protected: + // Exits old state, sets the new state, and enters it. + void ChangeState(CEncryptionKeyRefresher& aContext, CEncryptionKeyRefresherStateFactory::TEncryptionKeyRefresherStates aState) const; + void PanicInState(TLinkPanic aPanic) const; + +protected: + CEncryptionKeyRefresherStateFactory& iFactory; +#ifdef __FLOG_ACTIVE + TBuf<48> iName; +#endif + }; + + +//-------------------------------------------------- +// STATES +//-------------------------------------------------- + +NONSHARABLE_CLASS(TEkrStateIdle) : public TEncryptionKeyRefresherState + { +public: + TEkrStateIdle(CEncryptionKeyRefresherStateFactory& aFactory); + + virtual void Enter(CEncryptionKeyRefresher& aContext) const; + virtual void Start(CEncryptionKeyRefresher& aContext) const; + }; + + +NONSHARABLE_CLASS(TEkrStateDisablingLPM) : public TEncryptionKeyRefresherState + { +public: + TEkrStateDisablingLPM(CEncryptionKeyRefresherStateFactory& aFactory); + + virtual void Enter(CEncryptionKeyRefresher& aContext) const; + virtual void EventReceived(CEncryptionKeyRefresher& aContext, TBTBasebandEventNotification& aEvent) const; + }; + +NONSHARABLE_CLASS(TEkrStateRefreshingKey) : public TEncryptionKeyRefresherState + { +public: + TEkrStateRefreshingKey(CEncryptionKeyRefresherStateFactory& aFactory); + + virtual void Enter(CEncryptionKeyRefresher& aContext) const; + virtual void EncryptionKeyRefreshComplete(CEncryptionKeyRefresher& aContext, TInt aError) const; + }; + + +#ifdef __FLOG_ACTIVE +#define STATENAME(x) iName=_L(x) +#else +#define STATENAME(x) +#endif + + +#endif /* ENCRYPTIONKEYREFRESHHELPER_H */ diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/linkmgr/hcifacade.cpp --- a/bluetooth/btstack/linkmgr/hcifacade.cpp Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/linkmgr/hcifacade.cpp Tue Sep 14 23:28:24 2010 +0300 @@ -175,19 +175,6 @@ iAFHTimer=CAFHTimer::NewL(*this); - // Read low power mode override timeout from the configuration file - _LIT(KLPMSection, "lowpowermodeconfiguration"); - _LIT(KLPMTag, "overridelpmtimeout_microseconds"); - - TUint overrideLPMTimeout = 0; - TRAP(err, overrideLPMTimeout = iHciUtil->GetValueFromFileL(KLPMSection, KLPMTag)); - - if (err == KErrNone) - { - // LPM override timeout found, pass the value into link manager - iLinkMgrProtocol.SetOverrideLPMTimeout(overrideLPMTimeout); - } - iLastPowerState = EBTOn; // used later to ensure that we have enough data to call SetEventMask diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/linkmgr/hcifacade.h --- a/bluetooth/btstack/linkmgr/hcifacade.h Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/linkmgr/hcifacade.h Tue Sep 14 23:28:24 2010 +0300 @@ -310,6 +310,7 @@ void LinkKeyRequestEvent(const THCIEventBase& aEvent, const CHCICommandBase* aRelatedCommand); void LinkKeyNotificationEvent(const THCIEventBase& aEvent, const CHCICommandBase* aRelatedCommand); void MaxSlotsChangeEvent(const THCIEventBase& aEvent, const CHCICommandBase* aRelatedCommand); + void EncryptionKeyRefreshCompleteEvent(const THCIEventBase& aEvent, const CHCICommandBase* aRelatedCommand); // Data event processing functions void NumberOfCompletedPacketsEvent(THCIEventBase& aEvent); diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/linkmgr/hcifacade_events.cpp --- a/bluetooth/btstack/linkmgr/hcifacade_events.cpp Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/linkmgr/hcifacade_events.cpp Tue Sep 14 23:28:24 2010 +0300 @@ -80,6 +80,7 @@ #include #include #include +#include // Command Complete Events @@ -1220,6 +1221,14 @@ iLinksMgr->MaxSlotsChange(maxSlotsChangeEvent.ConnectionHandle(), maxSlotsChangeEvent.LMPMaxSlots()); } +void CHCIFacade::EncryptionKeyRefreshCompleteEvent(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/) + { + LOG_FUNC + const TEncryptionKeyRefreshCompleteEvent& refreshCompleteEvent = TEncryptionKeyRefreshCompleteEvent::Cast(aEvent); + + iLinksMgr->EncryptionKeyRefreshComplete(aEvent.ErrorCode(), refreshCompleteEvent.ConnectionHandle()); + } + // ---------------------------------------------------------------------------- // Data event processing functions // ---------------------------------------------------------------------------- @@ -1347,6 +1356,10 @@ case EVendorDebugEvent: VendorDebugEvent(aEvent, aRelatedCommand); break; + + case EEncryptionKeyRefreshCompleteEvent: + EncryptionKeyRefreshCompleteEvent(aEvent, aRelatedCommand); + break; // Inquiry based events. // By default these should be caused by the inquiry manager and so be returned to it. @@ -1382,7 +1395,6 @@ case EPageScanModeChangeEvent: case EPageScanRepetitionModeChangeEvent: case EUserPasskeyRequestEvent: - case EEncryptionKeyRefreshCompleteEvent: LOG1(_L("Warning!! Unhandled Command Event (event code:%d)"), aEvent.EventCode()); break; diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/linkmgr/linkmgr.cpp --- a/bluetooth/btstack/linkmgr/linkmgr.cpp Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/linkmgr/linkmgr.cpp Tue Sep 14 23:28:24 2010 +0300 @@ -800,12 +800,6 @@ } } -void CLinkMgrProtocol::SetOverrideLPMTimeout(TUint aOverrideLPMTimeout) - { - LOG_FUNC - iOverrideLPMTimeout =aOverrideLPMTimeout; - } - TInt CLinkMgrProtocol::StartProtocolListening() { LOG_FUNC @@ -1365,9 +1359,6 @@ case EUndoOverridePark: rerr = con->UndoOverridePark(); break; - case EOverrideLPMWithTimeout: - rerr = con->OverrideLPMWithTimeout(iOverrideLPMTimeout); - break; case EOverrideLPM: rerr = con->OverrideLPM(); break; diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/linkmgr/linkmgr.h --- a/bluetooth/btstack/linkmgr/linkmgr.h Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/linkmgr/linkmgr.h Tue Sep 14 23:28:24 2010 +0300 @@ -182,7 +182,6 @@ void SetLimitedDiscoverableIfChangedL(TBool aOn); void SetLocalVersion(THCIErrorCode aErr, TBTDevHCIVersion aHCIVersion, TBTDevLMPVersion aLMPVersion); - void SetOverrideLPMTimeout(TUint aOverrideLPMTimeout); void SetLocalFeatures(THCIErrorCode aErr, const TBTFeatures& aMask); void SetLocalCommands(THCIErrorCode aErr, const TBluetoothHciCommands& aMask); void SetDeviceClassL(TUint32 aCod); @@ -267,8 +266,6 @@ RPointerArray iSubscribers; - TUint iOverrideLPMTimeout; - // protocol state objects TBool iClosePending; // the protocol is closing TDeltaTimerEntry iIdleTimerEntry; diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/linkmgr/linkutil.h --- a/bluetooth/btstack/linkmgr/linkutil.h Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/linkmgr/linkutil.h Tue Sep 14 23:28:24 2010 +0300 @@ -193,6 +193,8 @@ EBTACLSAPUnexpectedSecurityResult =252, ELinkMgrFlowControlUnexpectedUpdate =253, ELinkMgrFlowControlChangeOfMind =254, + EEncryptionKeyRefresherInvalidState =255, + EEncryptionKeyRefresherStateMachineInvalidEvent = 256, }; /** diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/linkmgr/physicallinks.cpp --- a/bluetooth/btstack/linkmgr/physicallinks.cpp Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/linkmgr/physicallinks.cpp Tue Sep 14 23:28:24 2010 +0300 @@ -25,10 +25,11 @@ #include "linkconsts.h" #include "hcifacade.h" #include "hostresolver.h" -#include "PhysicalLinkHelper.h" +#include "roleswitchhelper.h" #include "pairingscache.h" #include "oobdata.h" #include "pairingserver.h" +#include "encryptionkeyrefreshhelper.h" #include @@ -91,7 +92,6 @@ , iProxySAPs(_FOFF(CBTProxySAP, iQueueLink)) , iOverrideParkRequests(EFalse) , iOverrideLPMRequests(EFalse) - , iLPMOverrideTimerQueued(EFalse) , iConnectionPacketTypeChanged(EFalse) , iLowPowModeCtrl(*this, iLinksMan.HCIFacade().CommandQController()) , iDisconnectCtrl(*this, iLinksMan.HCIFacade().CommandQController()) @@ -119,11 +119,6 @@ iACLLogicalLinks.Close(); RemoveIdleTimer(); - if (iLPMOverrideTimerQueued) - { - BTSocketTimer::Remove(iOverrideLPMTimerEntry); - iLPMOverrideTimerQueued = EFalse; - } LOG(_L("sec\tClosing subscribers...")) @@ -149,9 +144,11 @@ delete iPasskeyEntry; delete iArbitrationDelay; delete iRoleSwitchCompleteCallBack; + delete iKeyRefreshCompleteCallBack; delete iEncryptionEnforcer; DeleteRoleSwitcher(); + DeleteKeyRefresher(); } void CPhysicalLink::ConstructL() @@ -164,9 +161,9 @@ TCallBack cb1(RoleSwitchCompleteCallBack, this); iRoleSwitchCompleteCallBack = new (ELeave)CAsyncCallBack(cb1, EActiveHighPriority); - TCallBack cb2(OverrideLPMTimeoutCallback, this); - iOverrideLPMTimerEntry.Set(cb2); - + TCallBack cb2(KeyRefreshCompleteCallBack, this); + iKeyRefreshCompleteCallBack = new (ELeave)CAsyncCallBack(cb2, EActiveHighPriority); + iPhysicalLinkMetrics = CPhysicalLinkMetrics::NewL(*this, iLinksMan.HCIFacade().CommandQController()); } @@ -237,9 +234,19 @@ } else { - if (iAutoKeyRefreshQue.IsEmpty()) + // Only refresh the key if no-one is preventing it and we aren't still + // refreshing the key from a previous request. Note that although + // the previous key refresh may actually have finished if the key + // refresher is waiting for async delete we have only just refreshed + // the key and there's no point doing it again. + if (iAutoKeyRefreshQue.IsEmpty() && !iKeyRefresher) { - TRAP_IGNORE(iLinksMan.HCIFacade().RefreshEncryptionKeyL(iHandle)); + TRAPD(err, iKeyRefresher = CEncryptionKeyRefresher::NewL(iLinksMan, *this)); + if(!err) + { + // Kick off the helper state machine + iKeyRefresher->StartHelper(); + } // If we can't refresh the encryption key, there's not much we can do } XAutoKeyRefreshToken* token = new XAutoKeyRefreshToken(); @@ -1364,6 +1371,17 @@ nameChanger->Start(BDAddr(), aName); } +void CPhysicalLink::EncryptionKeyRefreshComplete(THCIErrorCode aErr, THCIConnHandle aConnH) + { + LOG_FUNC + __CHECK_CONNECTION_HANDLE(aConnH); + + if(iKeyRefresher) + { + iKeyRefresher->EncryptionKeyRefreshComplete(aErr); + } + } + void CPhysicalLink::Disconnection(THCIErrorCode aErr, THCIConnHandle aConnH, THCIErrorCode aResult) { LOG_FUNC @@ -2227,22 +2245,6 @@ iIdleTimerQueued = EFalse; } -void CPhysicalLink::QueueLPMOverrideTimer(TInt aTimeout) -/** - Queue LPM Override timer entry. - When this timer expires, it'll call UndoLPMOverride. -**/ - { - LOG_FUNC - __ASSERT_DEBUG(aTimeout!=0, Panic(EBTPhysicalLinksInvalidArgument)); - if (iLPMOverrideTimerQueued) - { - BTSocketTimer::Remove(iOverrideLPMTimerEntry); - } - BTSocketTimer::Queue(aTimeout, iOverrideLPMTimerEntry); - iLPMOverrideTimerQueued = ETrue; - } - void CPhysicalLink::NotifyStateChange(TBTBasebandEventNotification& aEvent) { LOG_FUNC @@ -2664,6 +2666,27 @@ iRoleSwitcher = NULL; } +void CPhysicalLink::AsyncDeleteKeyRefresher() + { + LOG_FUNC + iKeyRefreshCompleteCallBack->CallBack(); + } + +/*static*/ TInt CPhysicalLink::KeyRefreshCompleteCallBack(TAny* aPhysicalLink) + { + LOG_STATIC_FUNC + CPhysicalLink* physicalLink = static_cast(aPhysicalLink); + physicalLink->DeleteKeyRefresher(); + return EFalse; + } + +void CPhysicalLink::DeleteKeyRefresher() + { + LOG_FUNC + delete iKeyRefresher; + iKeyRefresher = NULL; + } + TBool CPhysicalLink::IsEncryptionDisabledForRoleSwitch() const /** If link is encrypted, but role switcher temporarily disabled encryption, returns true. @@ -2711,20 +2734,6 @@ return Arbitrate(); } -TInt CPhysicalLink::OverrideLPMWithTimeout(TUint aTimeout) - { - LOG_FUNC - if(aTimeout == 0) - { - return KErrNone; //facility not wanted - } - - TInt rerr = OverrideLPM(); - QueueLPMOverrideTimer(aTimeout); - - return rerr; - } - TInt CPhysicalLink::OverrideLPM() /** A request has come in that requires us to ensure we are not using @@ -2739,20 +2748,6 @@ return Arbitrate(); } -/*static*/ TInt CPhysicalLink::OverrideLPMTimeoutCallback(TAny* aCPhysicalLink) - { - LOG_STATIC_FUNC - CPhysicalLink* c = reinterpret_cast(aCPhysicalLink); - TInt err = c->UndoOverrideLPM(); - //we deliberately ignore this return value because we can't do anything to correct the error situation - if (KErrNone != err) - { - LOG2(_L("Physical link: UndoOverrideLPM returned an error %d on the connection 0x%08x"), err, c); - } - c->iLPMOverrideTimerQueued = EFalse; - return KErrNone; - } - TInt CPhysicalLink::UndoOverrideLPM() /** A need to ensure we are not in LPM has gone. diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/linkmgr/physicallinks.h --- a/bluetooth/btstack/linkmgr/physicallinks.h Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/linkmgr/physicallinks.h Tue Sep 14 23:28:24 2010 +0300 @@ -46,6 +46,7 @@ class CRoleSwitcher; class CBTNumericComparator; class CBTPasskeyEntry; +class CEncryptionKeyRefresher; enum TPhysicalLinkSimplePairingMode { @@ -342,7 +343,6 @@ TInt OverridePark(); TInt UndoOverridePark(); - TInt OverrideLPMWithTimeout(TUint aTimeout); TInt OverrideLPM(); TInt UndoOverrideLPM(); inline TBool IsParked() const; @@ -375,7 +375,8 @@ virtual void RoleChange(THCIErrorCode aErr, const TBTDevAddr& aAddr, TBTBasebandRole aRole); virtual void ClockOffset(THCIErrorCode aErr, THCIConnHandle aConnH, TBasebandTime aClockOffset); virtual void RemoteName(THCIErrorCode aErr, const TBTDevAddr& aAddr, const TBTDeviceName8& aName); - + virtual void EncryptionKeyRefreshComplete(THCIErrorCode aErr, THCIConnHandle aConnH); + void ConnectionComplete(TInt aResult, const TBTConnect& aConn); TBool LinkKeyRequestPending(); @@ -412,6 +413,7 @@ TBTLinkMode LinkMode() const; void AsyncDeleteRoleSwitcher(); + void AsyncDeleteKeyRefresher(); inline const TLinkPolicy& LinkPolicy() const; inline const TBTFeatures& RemoteFeatures() const; @@ -485,7 +487,6 @@ void QueueIdleTimer(TInt aTime); void RemoveIdleTimer(); - void QueueLPMOverrideTimer(TInt aTimeout); void NotifyStateChange(TBTBasebandEventNotification & aEvent); TBool IsPhysicalLinkIdle() const; @@ -496,6 +497,9 @@ void DeleteRoleSwitcher(); static TInt RoleSwitchCompleteCallBack(TAny* CPhysicalLink); TInt ManageEncryptionEnforcement(THCIEncryptModeFlag aEnable); + + void DeleteKeyRefresher(); + static TInt KeyRefreshCompleteCallBack(TAny* CPhysicalLink); void HandlePrefetch(); void PINCodeRequestReply(const TBTDevAddr& aDevAddr,const TDesC8& aPin); @@ -552,13 +556,11 @@ TSglQue iProxySAPs; // the proxies bound to us TDeltaTimerEntry iIdleTimerEntry; TBool iIdleTimerQueued; - TDeltaTimerEntry iOverrideLPMTimerEntry; TLinkPolicy iLinkPolicy; TUint16 iPreviousRequestedModeMask; TBool iOverrideParkRequests; //for maybe temporary unpark TBool iOverrideLPMRequests; //for maybe temporary force active - TBool iLPMOverrideTimerQueued; TBool iConnectionPacketTypeChanged; //for triggering h/w TBool iPreventLinkKeyUpdateReg; //for case e.g. user has called unpair when there is a paired logical channel @@ -570,6 +572,8 @@ CArbitrationDelayTimer* iArbitrationDelay; //for lower power modes CRoleSwitcher* iRoleSwitcher; //class handles role switch, prevents LPM, removes encryption CAsyncCallBack* iRoleSwitchCompleteCallBack;// Async Callback to delete role swticher class. + CEncryptionKeyRefresher* iKeyRefresher; //class handles key refresh + CAsyncCallBack* iKeyRefreshCompleteCallBack;// Async Callback to delete key refresher class. TLowPowModeCmdController iLowPowModeCtrl; CPhysicalLinkMetrics* iPhysicalLinkMetrics; diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/linkmgr/physicallinksmanager.cpp --- a/bluetooth/btstack/linkmgr/physicallinksmanager.cpp Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/linkmgr/physicallinksmanager.cpp Tue Sep 14 23:28:24 2010 +0300 @@ -23,7 +23,7 @@ #include "ProxySAP.h" #include -#include "PhysicalLinkHelper.h" +#include "roleswitchhelper.h" #include "hostresolver.h" #include @@ -583,6 +583,13 @@ found->MaxSlotsChange(aConnH, aSlots); } +void CPhysicalLinksManager::EncryptionKeyRefreshComplete(THCIErrorCode aErr, THCIConnHandle aConnH) + { + CPhysicalLink* found = FindPhysicalLink(aConnH); + RETURN_IF_NULL_CONNECTION(found); + found->EncryptionKeyRefreshComplete(aErr, aConnH); + } + void CPhysicalLinksManager::ModeChange(THCIErrorCode aErr, THCIConnHandle aConnH, TBTLinkMode aMode, TBasebandTime aInterval) { CPhysicalLink* found = FindPhysicalLink(aConnH); @@ -996,7 +1003,7 @@ // this the only role request, it's safe to kick off the state machine // first suspend host resolver LinkManagerProtocol().InquiryMgr().Suspend(); - aRoleSwitcher.Start(); + aRoleSwitcher.StartHelper(); } } @@ -1016,7 +1023,7 @@ if (startNextRoleSwitcher && !iRoleSwitchersQ.IsEmpty()) { - iRoleSwitchersQ.First()->Start(); + iRoleSwitchersQ.First()->StartHelper(); } else { diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/linkmgr/physicallinksmanager.h --- a/bluetooth/btstack/linkmgr/physicallinksmanager.h Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/linkmgr/physicallinksmanager.h Tue Sep 14 23:28:24 2010 +0300 @@ -204,6 +204,8 @@ virtual void ClockOffset(THCIErrorCode aErr, THCIConnHandle aConnH, TBasebandTime aClockOffset); virtual void RemoteName(THCIErrorCode aErr, const TBTDevAddr& aAddr, const TBTDeviceName8& aName); virtual void SimplePairingComplete(const TBTDevAddr& aBDAddr, THCIErrorCode aErr); + virtual void EncryptionKeyRefreshComplete(THCIErrorCode aErr, THCIConnHandle aConnH); + // events from MBTPairingsCacheObserver virtual void MbpcoDeferredDecisionResolved(TInt aError); diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/linkmgr/roleswitchhelper.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btstack/linkmgr/roleswitchhelper.cpp Tue Sep 14 23:28:24 2010 +0300 @@ -0,0 +1,518 @@ +// 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 "roleswitchhelper.h" +#include "physicallinksmanager.h" +#include "AclDataQController.h" +#include "ProxySAP.h" +#include "linkmgr.h" + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, LOG_COMPONENT_LINKMGR); +#endif + +CRoleSwitcher::CRoleSwitcher(CPhysicalLinksManager& aLinkMgr, CPhysicalLink& aLink, TBTBasebandRole aRole) + : CPhysicalLinkHelper(aLinkMgr, aLink) + , iRole(aRole) + , iIsEncryptionDisabledForRoleSwitch(EFalse) + { + LOG_FUNC + iState = &iLinkMgr.RoleSwitcherStateFactory().GetState(CRoleSwitcherStateFactory::EIdle); + } + +CRoleSwitcher* CRoleSwitcher::NewL(CPhysicalLinksManager& aLinkMgr, CPhysicalLink& aLink, TBTBasebandRole aRole) + { + LOG_STATIC_FUNC + CRoleSwitcher* self = new(ELeave) CRoleSwitcher(aLinkMgr, aLink, aRole); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +void CRoleSwitcher::ConstructL() + { + LOG_FUNC + + BaseConstructL(); + + // add ourselves to the list in LinkMgr, LinkMgr will kick off the role change state machine + iLinkMgr.AddRoleSwitcher(*this); + iAddedToLinkMgr = ETrue; + } + +CRoleSwitcher::~CRoleSwitcher() + { + LOG_FUNC + if (iAddedToLinkMgr) + { + iLinkMgr.RemoveRoleSwitcher(*this); + } + } + +void CRoleSwitcher::TimerExpired() + { + LOG_FUNC + + iState->TimerExpired(*this); + } + +void CRoleSwitcher::HandleError( TInt aError) + { + LOG_FUNC + + iState->Error(*this, aError); + } + +void CRoleSwitcher::DisableEncryption() + { + LOG_FUNC + // data traffic suspended + iLinkMgr.LinkManagerProtocol().ACLController().SetParked(iLink.Handle(), ETrue); + NotifyBasebandEvent(ENotifyEncryptionChangeOff); + iLinkMgr.Encrypt(EFalse, iLink); + + // set flag here, it's too late when we receive the event as AccessReqester + // might receive the baseband notification earlier then the flag is set! + iIsEncryptionDisabledForRoleSwitch = ETrue; + } + +void CRoleSwitcher::EnableEncryption() + { + LOG_FUNC + NotifyBasebandEvent(ENotifyEncryptionChangeOn); + iLinkMgr.Encrypt(ETrue, iLink); + // data traffic is enabled in IoctlComplete + } + +void CRoleSwitcher::ChangeRole() + { + LOG_FUNC + NotifyBasebandEvent(ENotifyAnyRole); + iLinkMgr.ChangeRole(iRole, iLink); + } + +void CRoleSwitcher::StartHelper() + { + LOG_FUNC + iState->Start(*this); + } + +void CRoleSwitcher::SaveEncryption() + { + LOG_FUNC + iIsEncrypted = iLink.Encrypted(); + } + +void CRoleSwitcher::LogRoleSwitchSuccessful(TBTBasebandEventNotification& aEvent) const + { + LOG_FUNC + TInt eventType; + eventType = (iRole == EMaster ? ENotifyMaster :ENotifySlave); + + if (aEvent.EventType()==eventType && aEvent.ErrorCode()==KErrNone) + { + LOG(_L("CRoleSwitcher RoleSwitch OK")); + } + else + { + LOG(_L("CRoleSwitcher RoleSwitch failed")); + } + } + +void CRoleSwitcher::EventReceived(TBTBasebandEventNotification& aEvent) + { + LOG_FUNC + iState->EventReceived(*this, aEvent); + } + + +//---------------------------------------------------------------------------------- +// STATE FACTORY +//---------------------------------------------------------------------------------- + +CRoleSwitcherStateFactory* CRoleSwitcherStateFactory::NewL() + { + LOG_STATIC_FUNC + CRoleSwitcherStateFactory* ret=new (ELeave) CRoleSwitcherStateFactory(); + CleanupStack::PushL(ret); + ret->ConstructL(); + CleanupStack::Pop(ret); + return ret; + } + +void CRoleSwitcherStateFactory::ConstructL() + { + LOG_FUNC + iStates[EIdle] =new (ELeave) TRSStateIdle(*this); + iStates[EDisablingLPM] =new (ELeave) TRSStateDisablingLPM(*this); + iStates[EDisablingEncryption] =new (ELeave) TRSStateDisablingEncryption(*this); + iStates[EChangingRole] =new (ELeave) TRSStateChangingRole(*this); + iStates[EChangingRoleWithEPR] =new (ELeave) TRSStateChangingRoleWithEPR(*this); + iStates[EEnablingEncryption] =new (ELeave) TRSStateEnablingEncryption(*this); + } + +CRoleSwitcherStateFactory::CRoleSwitcherStateFactory() + { + LOG_FUNC + iStates.DeleteAll(); + } + +TRoleSwitcherState& CRoleSwitcherStateFactory::GetState(CRoleSwitcherStateFactory::TRoleSwitcherStates aState) + { + LOG_FUNC + __ASSERT_DEBUG(iStates[aState], Panic(ERoleSwitcherInvalidState)); + return *iStates[aState]; + } + +TInt CRoleSwitcherStateFactory::StateIndex(const TRoleSwitcherState* aState) const + { + LOG_FUNC + TInt state; + for (state = 0; state < ERoleSwitcherMaxState; state++) + { + if (iStates[state] == aState) + { + return state; + } + } + + return KUnknownState; + } + + +//---------------------------------------------------------------------------------- +// STATES +//---------------------------------------------------------------------------------- + +TRoleSwitcherState::TRoleSwitcherState(CRoleSwitcherStateFactory& aFactory) +: iFactory(aFactory) + { + LOG_FUNC + } + +void TRoleSwitcherState::PanicInState(TLinkPanic aPanic) const + { + LOG_FUNC + Panic(aPanic, iFactory.StateIndex(this)); + } + +void TRoleSwitcherState::ChangeState(CRoleSwitcher& aContext, CRoleSwitcherStateFactory::TRoleSwitcherStates aState) const + { + LOG_FUNC + + aContext.iState->Exit(aContext); + +#ifdef __FLOG_ACTIVE + TRoleSwitcherState* state=&iFactory.GetState(aState); + LOG2(_L("RoleSwitcher: State %S -> %S"), &aContext.iState->iName, &state->iName); +#endif //__FLOG_ACTIVE + aContext.iState=&iFactory.GetState(aState); + + aContext.iState->Enter(aContext); + } + +void TRoleSwitcherState::Enter(CRoleSwitcher& /*aContext*/) const + { + LOG_FUNC + // do nothing + } + +void TRoleSwitcherState::Exit(CRoleSwitcher& /*aContext*/) const + { + LOG_FUNC + // do nothing + } + +void TRoleSwitcherState::Start(CRoleSwitcher& /*aContext*/) const + { + LOG_FUNC + PanicInState(ERoleSwitcherStateMachineInvalidEvent); + } + +void TRoleSwitcherState::Error(CRoleSwitcher& aContext, TInt /*aErr*/) const + { + LOG_FUNC + aContext.CancelNotify(); + aContext.RemoveTimer(); + ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); + } + +void TRoleSwitcherState::EventReceived(CRoleSwitcher& /*aContext*/, TBTBasebandEventNotification& /*aEvent*/) const + { + LOG_FUNC + // do nothing + } + +void TRoleSwitcherState::TimerExpired(CRoleSwitcher& aContext) const + { + LOG_FUNC + ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); + } + +//---------------------------------------------------------------------------------- + +TRSStateIdle::TRSStateIdle(CRoleSwitcherStateFactory& aFactory) +: TRoleSwitcherState(aFactory) + { + LOG_FUNC + STATENAME("TRSStateIdle"); + } + +void TRSStateIdle::Start(CRoleSwitcher& aContext) const + { + LOG_FUNC + aContext.QueueTimer(KTimeoutRoleSwitch); // watchdog timer + ChangeState(aContext, CRoleSwitcherStateFactory::EDisablingLPM); + } + +void TRSStateIdle::Enter(CRoleSwitcher& aContext) const + { + LOG_FUNC + // async call to delete the helper + aContext.iLink.AsyncDeleteRoleSwitcher(); + } + +//---------------------------------------------------------------------------------- + +TRSStateDisablingLPM::TRSStateDisablingLPM(CRoleSwitcherStateFactory& aFactory) +: TRoleSwitcherState(aFactory) + { + LOG_FUNC + STATENAME("TRSStateDisablingLPM"); + } + +void TRSStateDisablingLPM::Enter(CRoleSwitcher& aContext) const + { + LOG_FUNC + // DisableLPM even if link is active to prevent possible LPM requests during encryption disabling + + if (aContext.iLink.LinkMode() == EActiveMode) + { + aContext.DisableLPM(); + if (aContext.IsEPRSupported()) + { + ChangeState(aContext, CRoleSwitcherStateFactory::EChangingRoleWithEPR); + } + else + { + ChangeState(aContext, CRoleSwitcherStateFactory::EDisablingEncryption); + } + // don't wait for notification + } + else + { + aContext.NotifyBasebandEvent(ENotifyActiveMode); + aContext.DisableLPM(); + } + } + +void TRSStateDisablingLPM::EventReceived(CRoleSwitcher& aContext, TBTBasebandEventNotification& aEvent) const + { + LOG_FUNC + if (aEvent.EventType()==ENotifyActiveMode && aEvent.ErrorCode()==KErrNone) + { + if (aContext.IsEPRSupported()) + { + ChangeState(aContext, CRoleSwitcherStateFactory::EChangingRoleWithEPR); + } + else + { + ChangeState(aContext, CRoleSwitcherStateFactory::EDisablingEncryption); + } + } + else + { + LOG(_L("CRoleSwitcher RoleSwitch failed in DisableLPM")); + // we can quit SM, don't need to rewind + ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); + } + } + +//---------------------------------------------------------------------------------- +TRSStateDisablingEncryption::TRSStateDisablingEncryption(CRoleSwitcherStateFactory& aFactory) +: TRoleSwitcherState(aFactory) + { + LOG_FUNC + STATENAME("TRSStateDisablingEncryption"); + } + +void TRSStateDisablingEncryption::Enter(CRoleSwitcher& aContext) const + { + LOG_FUNC + aContext.SaveEncryption(); + if (aContext.iIsEncrypted) + { + aContext.DisableEncryption(); + } + else + { + ChangeState(aContext, CRoleSwitcherStateFactory::EChangingRole); + } + } + +void TRSStateDisablingEncryption::EventReceived(CRoleSwitcher& aContext, TBTBasebandEventNotification& aEvent) const + { + LOG_FUNC + if (aEvent.EventType()==ENotifyEncryptionChangeOff && aEvent.ErrorCode()==KErrNone) + { + ChangeState(aContext, CRoleSwitcherStateFactory::EChangingRole); + } + else + { + LOG(_L("CRoleSwitcher RoleSwitch failed in DisableEncryption")); + // before quiting SM , try to enable LPM + ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); + } + } + +void TRSStateDisablingEncryption::TimerExpired(CRoleSwitcher& aContext) const + { + LOG_FUNC + aContext.CancelNotify(); + ChangeState(aContext, CRoleSwitcherStateFactory::EEnablingEncryption); + } + +//---------------------------------------------------------------------------------- +TRSStateChangingRole::TRSStateChangingRole(CRoleSwitcherStateFactory& aFactory) +: TRoleSwitcherState(aFactory) + { + LOG_FUNC + STATENAME("TRSStateChangingRole"); + } + +void TRSStateChangingRole::Enter(CRoleSwitcher& aContext) const + { + LOG_FUNC + aContext.ChangeRole(); + } + +void TRSStateChangingRole::EventReceived(CRoleSwitcher& aContext, TBTBasebandEventNotification& __DEBUG_ONLY(aEvent)) const + { + LOG_FUNC + aContext.RemoveTimer(); // cancel watchdog timer + + FTRACE(aContext.LogRoleSwitchSuccessful(aEvent)); + + + ChangeState(aContext, CRoleSwitcherStateFactory::EEnablingEncryption); + } + +void TRSStateChangingRole::TimerExpired(CRoleSwitcher& aContext) const + { + LOG_FUNC + aContext.CancelNotify(); + ChangeState(aContext, CRoleSwitcherStateFactory::EEnablingEncryption); + } + +//---------------------------------------------------------------------------------- +TRSStateChangingRoleWithEPR::TRSStateChangingRoleWithEPR(CRoleSwitcherStateFactory& aFactory) +: TRoleSwitcherState(aFactory) + { + LOG_FUNC + STATENAME("TRSStateChangingRoleWithEPR"); + } + +void TRSStateChangingRoleWithEPR::Enter(CRoleSwitcher& aContext) const + { + LOG_FUNC + aContext.ChangeRole(); + } + +void TRSStateChangingRoleWithEPR::EventReceived(CRoleSwitcher& aContext, TBTBasebandEventNotification& __DEBUG_ONLY(aEvent)) const + { + LOG_FUNC + aContext.RemoveTimer(); // cancel watchdog timer + + FTRACE(aContext.LogRoleSwitchSuccessful(aEvent)); + + ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); + } + +void TRSStateChangingRoleWithEPR::TimerExpired(CRoleSwitcher& aContext) const + { + LOG_FUNC + aContext.CancelNotify(); + ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); + } + +//---------------------------------------------------------------------------------- +TRSStateEnablingEncryption::TRSStateEnablingEncryption(CRoleSwitcherStateFactory& aFactory) +: TRoleSwitcherState(aFactory) + { + LOG_FUNC + STATENAME("TRSStateEnablingEncryption"); + } + +void TRSStateEnablingEncryption::Enter(CRoleSwitcher& aContext) const + { + LOG_FUNC + if (aContext.iIsEncrypted) + { + aContext.QueueTimer(KTimeoutOneCommand); + aContext.EnableEncryption(); + } + else + { + ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); + } + } + +void TRSStateEnablingEncryption::Exit(CRoleSwitcher& aContext) const + { + LOG_FUNC + if (aContext.iIsEncrypted) + { + // enable data traffic + aContext.iLinkMgr.LinkManagerProtocol().ACLController().SetParked(aContext.iLink.Handle(), EFalse); + } + } + +void TRSStateEnablingEncryption::EventReceived(CRoleSwitcher& aContext, TBTBasebandEventNotification& aEvent) const + { + LOG_FUNC + aContext.RemoveTimer(); // watchdog timer + if (aEvent.EventType()==ENotifyEncryptionChangeOn && aEvent.ErrorCode()==KErrNone) + { + ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); + aContext.iIsEncryptionDisabledForRoleSwitch = EFalse; + } + else + { + LOG(_L("CRoleSwitcher SetEncryption failed, disconnect link")); + if (aContext.iLink.Terminate(ERemoteUserEndedConnection) != KErrNone) + { + LOG(_L("CRoleSwitcher OOM")); + } + ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); + } + } + +void TRSStateEnablingEncryption::TimerExpired(CRoleSwitcher& aContext) const + { + LOG_FUNC + LOG(_L("CRoleSwitcher Timeout in EncryptionEnable, disconnect")); + aContext.CancelNotify(); + if (aContext.iLink.Terminate(ERemoteUserEndedConnection) != KErrNone) + { + LOG(_L("CRoleSwitcher OOM")); + } + ChangeState(aContext, CRoleSwitcherStateFactory::EIdle); + } + + + diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/linkmgr/roleswitchhelper.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btstack/linkmgr/roleswitchhelper.h Tue Sep 14 23:28:24 2010 +0300 @@ -0,0 +1,230 @@ +// 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: +// + +#ifndef ROLESWITCHHELPER_H +#define ROLESWITCHHELPER_H + +#include +#include + +#include "debug.h" +#include "linkutil.h" +#include "physicallinkhelper.h" +#include "physicallinks.h" + +// watchdog for first half of the SM including: +// DisablingLPM, DisablingEncryption, RoleSwitch +const TUint KTimeoutRoleSwitch = 3000000; // 3 s; + +// watchdog for EnablingEncryption +const TUint KTimeoutOneCommand = 2000000; // 2 s; + +class TRoleSwitcherState; + +NONSHARABLE_CLASS(CRoleSwitcher) : public CPhysicalLinkHelper + { + friend class TRoleSwitcherState; + friend class TRSStateIdle; + friend class TRSStateDisablingLPM; + friend class TRSStateDisablingEncryption; + friend class TRSStateChangingRole; + friend class TRSStateChangingRoleWithEPR; + friend class TRSStateEnablingEncryption; + +public: + static CRoleSwitcher* NewL(CPhysicalLinksManager& aLinkMgr, CPhysicalLink& aLink, TBTBasebandRole aRole); + ~CRoleSwitcher(); + + virtual void StartHelper(); + + inline TBool IsEncryptionDisabledForRoleSwitch() const; + inline TBTBasebandRole RequestedRole() const; + + TSglQueLink iQLink; + +private: + CRoleSwitcher(CPhysicalLinksManager& aLinkMgr, CPhysicalLink& aLink, TBTBasebandRole aRole); + void ConstructL(); + + virtual void TimerExpired(); + virtual void HandleError(TInt aError); + virtual void EventReceived(TBTBasebandEventNotification& aEvent); + + void DisableEncryption(); + void ChangeRole(); + void EnableEncryption(); + void SaveEncryption(); + + void LogRoleSwitchSuccessful(TBTBasebandEventNotification& aEvent) const; + + TBool iIsEncrypted; + TBool iIsActive; // LinkMode + TBool iAddedToLinkMgr; + TBTBasebandRole iRole; // Requested role + TRoleSwitcherState* iState; + TBool iIsEncryptionDisabledForRoleSwitch; + }; + +//-------------------------------------------------- +// STATE FACTORY +//-------------------------------------------------- + +/** + Factory for the RoleSwitcher states + + The states are flyweight classes +**/ +NONSHARABLE_CLASS(CRoleSwitcherStateFactory) : public CBase + { +public: + static CRoleSwitcherStateFactory* NewL(); + + enum TRoleSwitcherStates + { + EIdle, + EDisablingLPM, + EDisablingEncryption, + EChangingRole, + EChangingRoleWithEPR, + EEnablingEncryption, + // Note that we don't need a state to enable LPM again + // as this will happen implicitly when we close our + // proxy SAP. + // *** keep next one last *** + ERoleSwitcherMaxState, + }; + + TRoleSwitcherState& GetState(TRoleSwitcherStates aState); + TInt StateIndex(const TRoleSwitcherState* aState) const; + +private: + CRoleSwitcherStateFactory(); + void ConstructL(); + TFixedArray iStates; + }; + + + +//-------------------------------------------------- +// STATES, base +//-------------------------------------------------- + +NONSHARABLE_CLASS(TRoleSwitcherState) + { +public: + TRoleSwitcherState(CRoleSwitcherStateFactory& aFactory); + + virtual void Enter(CRoleSwitcher& aContext) const; + virtual void Exit(CRoleSwitcher& aContext) const; + + virtual void Start(CRoleSwitcher& aContext) const; + virtual void EventReceived(CRoleSwitcher& aContext, TBTBasebandEventNotification& aEvent) const; + virtual void Error(CRoleSwitcher& aContext, TInt aErr) const; + virtual void TimerExpired(CRoleSwitcher& aContext) const; + +protected: + // Exits old state, sets the new state, and enters it. + void ChangeState(CRoleSwitcher& aContext, CRoleSwitcherStateFactory::TRoleSwitcherStates aState) const; + void PanicInState(TLinkPanic aPanic) const; + +protected: + CRoleSwitcherStateFactory& iFactory; +#ifdef __FLOG_ACTIVE + TBuf<48> iName; +#endif + }; + + +//-------------------------------------------------- +// STATES +//-------------------------------------------------- + +NONSHARABLE_CLASS(TRSStateIdle) : public TRoleSwitcherState + { +public: + TRSStateIdle(CRoleSwitcherStateFactory& aFactory); + + virtual void Enter(CRoleSwitcher& aContext) const; + virtual void Start(CRoleSwitcher& aContext) const; + }; + + +NONSHARABLE_CLASS(TRSStateDisablingLPM) : public TRoleSwitcherState + { +public: + TRSStateDisablingLPM(CRoleSwitcherStateFactory& aFactory); + + virtual void Enter(CRoleSwitcher& aContext) const; + virtual void EventReceived(CRoleSwitcher& aContext, TBTBasebandEventNotification& aEvent) const; + }; + +NONSHARABLE_CLASS(TRSStateDisablingEncryption) : public TRoleSwitcherState + { +public: + TRSStateDisablingEncryption(CRoleSwitcherStateFactory& aFactory); + + virtual void Enter(CRoleSwitcher& aContext) const; + virtual void EventReceived(CRoleSwitcher& aContext, TBTBasebandEventNotification& aEvent) const; + virtual void TimerExpired(CRoleSwitcher& aContext) const; + }; + +NONSHARABLE_CLASS(TRSStateChangingRole) : public TRoleSwitcherState + { +public: + TRSStateChangingRole(CRoleSwitcherStateFactory& aFactory); + + virtual void Enter(CRoleSwitcher& aContext) const; + virtual void EventReceived(CRoleSwitcher& aContext, TBTBasebandEventNotification& aEvent) const; + virtual void TimerExpired(CRoleSwitcher& aContext) const; + }; + +NONSHARABLE_CLASS(TRSStateChangingRoleWithEPR) : public TRoleSwitcherState + { +public: + TRSStateChangingRoleWithEPR(CRoleSwitcherStateFactory& aFactory); + + virtual void Enter(CRoleSwitcher& aContext) const; + virtual void EventReceived(CRoleSwitcher& aContext, TBTBasebandEventNotification& aEvent) const; + virtual void TimerExpired(CRoleSwitcher& aContext) const; + }; + +NONSHARABLE_CLASS(TRSStateEnablingEncryption) : public TRoleSwitcherState + { +public: + TRSStateEnablingEncryption(CRoleSwitcherStateFactory& aFactory); + + virtual void Enter(CRoleSwitcher& aContext) const; + virtual void Exit(CRoleSwitcher& aContext) const; + virtual void EventReceived(CRoleSwitcher& aContext, TBTBasebandEventNotification& aEvent) const; + virtual void TimerExpired(CRoleSwitcher& aContext) const; + }; + +#ifdef __FLOG_ACTIVE +#define STATENAME(x) iName=_L(x) +#else +#define STATENAME(x) +#endif + +inline TBTBasebandRole CRoleSwitcher::RequestedRole() const + { + return iRole; + } + +inline TBool CRoleSwitcher::IsEncryptionDisabledForRoleSwitch() const + { + return iIsEncryptionDisabledForRoleSwitch; + } + +#endif /* ROLESWITCHHELPER_H */ diff -r e9b924a62a66 -r 99439b07e980 bluetooth/btstack/rfcomm/rfcommstates.cpp --- a/bluetooth/btstack/rfcomm/rfcommstates.cpp Wed Sep 01 12:38:54 2010 +0100 +++ b/bluetooth/btstack/rfcomm/rfcommstates.cpp Tue Sep 14 23:28:24 2010 +0300 @@ -99,7 +99,6 @@ if(aType & MSocketNotify::EErrorFatal) { - aSAP.iProtocol.ControlPlane().ModifyPhysicalLink(EUndoOverridePark, aSAP.iRemoteDev); ChangeState(aSAP, CRfcommStateFactory::EError); } return aErr; @@ -657,6 +656,16 @@ don't want to get any more notifications from the mux **/ { + // Depending where we came from we may have applied either a + // park override or an all LPM override. We remove both these + // overrides because it's safe to remove an override that + // hasn't been applied. + // Note that although park is one of the LPMs the different + // levels of override are managed separately, so an + // UndoOverrideLPM does not remove an explicit park only + // override. + aSAP.iProtocol.ControlPlane().ModifyPhysicalLink(EUndoOverridePark, aSAP.iRemoteDev); + aSAP.iProtocol.ControlPlane().ModifyPhysicalLink(EUndoOverrideLPM, aSAP.iRemoteDev); aSAP.DeregisterCodService(); // See if there is a Service to remove for CodMan @@ -694,13 +703,23 @@ } aSAP.iNewDataToNotify=0; aSAP.iDataBuffer.Reset(); + + // Depending where we came from we may have applied either a + // park override or an all LPM override. We remove both these + // overrides because it's safe to remove an override that + // hasn't been applied. + // Note that although park is one of the LPMs the different + // levels of override are managed separately, so an + // UndoOverrideLPM does not remove an explicit park only + // override. aSAP.iProtocol.ControlPlane().ModifyPhysicalLink(EUndoOverridePark, aSAP.iRemoteDev); + aSAP.iProtocol.ControlPlane().ModifyPhysicalLink(EUndoOverrideLPM, aSAP.iRemoteDev); + if(aSAP.iMux) { aSAP.iMux->DetachSAP(aSAP); } aSAP.DeregisterCodService(); // See if there is a Service to remove for CodMan - } void TRfcommStateClosed::Error(CRfcommSAP& /*aSAP*/, TInt /*aErr*/, @@ -731,7 +750,11 @@ } aSAP.RegisterCodService(); // See if there is a Service set for CodMan - + + // Override LPM while we do some sigalling to ensure it can complete in + // a timely fashion. + aSAP.iProtocol.ControlPlane().ModifyPhysicalLink(EOverrideLPM, aSAP.iRemoteDev); + // First get a Mux. ChangeState(aSAP, CRfcommStateFactory::EWaitForMux); } @@ -1313,7 +1336,7 @@ newSAP->iRemoteDev=aMux.RemoteBTAddr(); // Must come after registering the remote address with the new SAP because we will need // the remote address to find a link in LinkMgrProtocol to override LPM on - newSAP->iProtocol.ControlPlane().ModifyPhysicalLink(EOverrideLPMWithTimeout, newSAP->iRemoteDev); + newSAP->iProtocol.ControlPlane().ModifyPhysicalLink(EOverrideLPM, newSAP->iRemoteDev); newSAP->iUserDefinedMTU=aSAP.iUserDefinedMTU; // We take our cues as // regards max MTU from // the listening SAP. @@ -1738,7 +1761,17 @@ return; } + // Depending where we came from we may have applied either a + // park override or an all LPM override. We remove both these + // overrides because it's safe to remove an override that + // hasn't been applied. + // Note that although park is one of the LPMs the different + // levels of override are managed separately, so an + // UndoOverrideLPM does not remove an explicit park only + // override. aSAP.iProtocol.ControlPlane().ModifyPhysicalLink(EUndoOverridePark, aSAP.iRemoteDev); + aSAP.iProtocol.ControlPlane().ModifyPhysicalLink(EUndoOverrideLPM, aSAP.iRemoteDev); + aSAP.iSocket->ConnectComplete(); aSAP.CTS(EFalse); // So that we block should anyone try to write // anything through this SAP before we get MSC @@ -1779,6 +1812,9 @@ Shutdown the open channel gracefully **/ { + // Only override park for disconnect. We need to be able + // to send the signalling, but we don't care if it takes + // ages. No point starting a sniff bun-fight. aSAP.iProtocol.ControlPlane().ModifyPhysicalLink(EOverridePark, aSAP.iRemoteDev); aSAP.iClosePending=ETrue; ChangeState(aSAP, CRfcommStateFactory::EDisconnect); @@ -1796,6 +1832,10 @@ // the queued DISC frame does not get deleted when the SAP gets // removed from the muxer __ASSERT_DEBUG(aSAP.iMux!=NULL,PanicInState(ERfcommNullMux)); + + // Only override park for disconnect. We need to be able + // to send the signalling, but we don't care if it takes + // ages. No point starting a sniff bun-fight. aSAP.iProtocol.ControlPlane().ModifyPhysicalLink(EOverridePark, aSAP.iRemoteDev); aSAP.iMux->SendDISC(aSAP.DLCI()); // Disassociated from the SAP ChangeState(aSAP, CRfcommStateFactory::EClosed); diff -r e9b924a62a66 -r 99439b07e980 bthci/hciextensioninterface/tsrc/tproxycorehci/group/bluetooth_stack.ini --- a/bthci/hciextensioninterface/tsrc/tproxycorehci/group/bluetooth_stack.ini Wed Sep 01 12:38:54 2010 +0100 +++ b/bthci/hciextensioninterface/tsrc/tproxycorehci/group/bluetooth_stack.ini Tue Sep 14 23:28:24 2010 +0300 @@ -18,6 +18,3 @@ [CoreHci] EcomUid= 0x10286A7B - -[lowpowermodeconfiguration] -overridelpmtimeout_microseconds= 0 \ No newline at end of file