diff -r 000000000000 -r 29b1cd4cb562 bluetoothcommsprofiles/btpan/panagt/pancoexistenceconnectioncontroller.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothcommsprofiles/btpan/panagt/pancoexistenceconnectioncontroller.cpp Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,328 @@ +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include + +#include "pancoexistenceconnectioncontroller.h" +#include "panagtutils.h" + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, LOG_COMPONENT_PAN_AGENT); +#endif + +// This is the identifer of the shared mutex used to allow safe read / write of the coexistence P&S key. +// This can only be changed if all other existing definitions of the mutex name are also changed. +_LIT(KIPBearerCoexistenceMutex, "IPBearerCoexistenceMutex"); + +using namespace PanAgent; + +CPanCoexistenceConnectionController* CPanCoexistenceConnectionController::NewL(MPanCoexistenceConnectionObserver& aObserver) + { + CPanCoexistenceConnectionController* self = new(ELeave) CPanCoexistenceConnectionController(aObserver); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CPanCoexistenceConnectionController::CPanCoexistenceConnectionController(MPanCoexistenceConnectionObserver& aObserver) + : CActive(EPriorityStandard),iPanCoexistenceConnectionObserver(aObserver) + { + CActiveScheduler::Add(this); + } + +CPanCoexistenceConnectionController::~CPanCoexistenceConnectionController() + { + Cancel(); + iProperty.Close(); + iMutex.Close(); + } + +void CPanCoexistenceConnectionController::ConstructL() + { + LOG_FUNC + + // Creates a global mutex and open a handle to the mutex. + // (Note if CreateGlobal returns wirh KErrNone then the mutex is also opened). + TInt err = iMutex.CreateGlobal(KIPBearerCoexistenceMutex); + if (err==KErrAlreadyExists) + { + err=iMutex.OpenGlobal(KIPBearerCoexistenceMutex); + } + + User::LeaveIfError(err); + + // Define property + err = DefineProperty(); + + if(err != KErrNone && err != KErrAlreadyExists) + { + User::Leave(err); + } + + // Attach to the property + TSecureId thisSID = RProcess().SecureId(); + User::LeaveIfError(iProperty.Attach(thisSID, KIPBearerCoexistenceProperty)); + + SubscribeToProperty(); + } + +//Define the P&S key +TInt CPanCoexistenceConnectionController::DefineProperty() + { + TInt err; + _LIT_SECURITY_POLICY_PASS(KPassPolicy); + _LIT_SECURITY_POLICY_C1(KNetworkControl, ECapabilityNetworkControl); + + err=iProperty.Define(KIPBearerCoexistenceProperty, + RProperty::EInt, + KPassPolicy, // Read policy + KNetworkControl); // Write policy + return err; + } + +// If another IP bearer has not set the key then this method will set the P&S key to indicate +// that a PAN connection is active. +TInt CPanCoexistenceConnectionController::TryToCreateNewPanConnection() + { + LOG_FUNC + + TInt err = KErrNone; + + // Wait for the Mutex to become free and then acquire it. + iMutex.Wait(); + + //Get the property + TIPBearerCoexistenceStatus value = ReadStatus(); + + switch (value) + { + case ENoneIsActive: + iActivePanConnectionExists = ETrue; + iLocallyInitiatedTransition = ETrue; + + WriteStatus(EBTPanIsActive); + break; + + case EBTPanIsActive: + //P&S key is allready set to EBTPanIsActive + __ASSERT_DEBUG(EFalse, PanAgentPanic(EBTPanIsAlreadyActive)); + break; + + case ERndisIsActive: + //BT PAN cannot be active at the point, since Rndis holds the key + __ASSERT_DEBUG(!iActivePanConnectionExists, PanAgentPanic(ERndisIsActiveWhenBTPanTriesToBeActive)); + err = KErrAccessDenied; + break; + + default: + __ASSERT_DEBUG(EFalse, PanAgentPanic(EInvalidIPBearerCoexistanceProperty)); + break; + } + + //Release the mutex + iMutex.Signal(); + return err; + } + +// If the co-existence P&S key has been set by the PAN service then +// clear the P&S key +void CPanCoexistenceConnectionController::HandleAllPanConnectionsClosed() + { + LOG_FUNC + + // Get the property + TIPBearerCoexistenceStatus value = ReadStatus(); + + switch(value) + { + case ENoneIsActive: + // The P&S key is ENoneIsActive, when BT PAN tries to clear it. + __ASSERT_DEBUG(EFalse, PanAgentPanic(EClearKeyWhenNoneIsActive)); + break; + + case ERndisIsActive: + // This is the race condition where RNDIS sets the key when BT PAN incoming connection request + // goes through the stack, we didn't own the key, do nothing + LOG(_L("CPanCoexistenceConnectionController::HandleAllPanConnectionsClosed, enter the race condition")); + break; + + case EBTPanIsActive: + __ASSERT_DEBUG(iActivePanConnectionExists, PanAgentPanic(ENoPanConnectionExistsWhileInPanIsActiveCoexistencePandSState)); + iActivePanConnectionExists = EFalse; + iLocallyInitiatedTransition = ETrue; + + WriteStatus(ENoneIsActive); + break; + + default: + __ASSERT_DEBUG(EFalse, PanAgentPanic(EInvalidIPBearerCoexistanceProperty)); + break; + } + } + +// Read property and handle error conditions +TIPBearerCoexistenceStatus CPanCoexistenceConnectionController::ReadStatus() + { + LOG_FUNC + + //Get the property + TInt value = ENoneIsActive; + TInt err = iProperty.Get(value); + + if(err) + { + if (err == KErrNotFound) + { + __ASSERT_DEBUG(EFalse, PanAgentPanic(EIPBearerCoexistancePropertyIsNotDefined)); + + //Redefine property if property has been deleted + err = DefineProperty(); + + if (err == KErrNone) + { + value = iActivePanConnectionExists ? EBTPanIsActive : ENoneIsActive; + err = iProperty.Set(value); + if (err) + { + //reset failed, log the error and assert the debug + LOG1(_L("CPanCoexistenceConnectionController::ReadProperty reset Property with error: %d"), err); + __ASSERT_DEBUG(EFalse, PanAgentPanic(EIPBearerCoexistancePropertySetFailed)); + } + } + else + { + //Define P&S failed, log the error and assert the debug + LOG1(_L("CPanCoexistenceConnectionController::ReadProperty Define Property with error: %d"), err); + __ASSERT_DEBUG(EFalse, PanAgentPanic(EIPBearerCoexistancePropertyCanNotBeDefined)); + } + } + else + { + //Getter returns error rather than KErrNotFound, log the error and assert the debug + LOG1(_L("CPanCoexistenceConnectionController::ReadProperty Get Property with error: %d"), err); + __ASSERT_DEBUG(EFalse, PanAgentPanic(EIPBearerCoexistancePropertyGetFailed)); + } + } + + return static_cast(value); + } + +//Write the property and handle setter errors +void CPanCoexistenceConnectionController::WriteStatus(TIPBearerCoexistenceStatus aStatus) + { + LOG_FUNC + + //Set the property + TInt err = iProperty.Set(aStatus); + if (err) + { + if (err == KErrNotFound) + { + __ASSERT_DEBUG(EFalse, PanAgentPanic(EIPBearerCoexistancePropertyIsNotDefined)); + + //Redefine property if property has been deleted + err = DefineProperty(); + + if (err == KErrNone) + { + //Reset the property + err = iProperty.Set(aStatus); + if (err) + { + LOG1(_L("CPanCoexistenceConnectionController::WriteStatus Set Property with error: %d"), err); + __ASSERT_DEBUG(EFalse, PanAgentPanic(EIPBearerCoexistancePropertySetFailed)); + } + } + else + { + //Define P&S failed, log the error and assert the debug + LOG1(_L("CPanCoexistenceConnectionController::ReadProperty Define Property with error: %d"), err); + __ASSERT_DEBUG(EFalse, PanAgentPanic(EIPBearerCoexistancePropertyCanNotBeDefined)); + //Nothing else we can do at this stage + } + + } + else + { + //Setter returns error rather than KErrNotFound + LOG1(_L("CPanCoexistenceConnectionController::WriteStatus Set Property with error: %d"), err); + __ASSERT_DEBUG(EFalse, PanAgentPanic(EIPBearerCoexistancePropertySetFailed)); + } + } + } + +void CPanCoexistenceConnectionController::SubscribeToProperty() + { + LOG_FUNC + iProperty.Subscribe(iStatus); + SetActive(); + } + +void CPanCoexistenceConnectionController::DoCancel() + { + LOG_FUNC + iProperty.Cancel(); + } + +void CPanCoexistenceConnectionController::RunL() + { + LOG_FUNC + + // Do not check the iStatus, since the ReadStatus() will redefine the P&S key if the key + // has been deleted by mistakes + + //Read the property + TIPBearerCoexistenceStatus value = ReadStatus(); + + switch(value) + { + case ENoneIsActive: + if (!iLocallyInitiatedTransition) + { + // BT PAN cannot be active at this point, since the P&S key is ENoneIsActive + __ASSERT_DEBUG(!iActivePanConnectionExists, PanAgentPanic(EPropertyIsNoneIsActiveWhenBTPanIsActive)); + + // Notify Agent P&S Key has been updated + iPanCoexistenceConnectionObserver.MpccoPanCoexistenceConnectionUpdated(ENoneIsActive); + } + break; + + case ERndisIsActive: + // BT PAN cannot be active at this point + __ASSERT_DEBUG(!iActivePanConnectionExists, PanAgentPanic(ERndisIsActiveWhenBTPanTriesToBeActive)); + __ASSERT_DEBUG(!iLocallyInitiatedTransition, PanAgentPanic(EBTPanInitiateDirectTransitionToRndis)); + + //from non service to Rndis + //Notify Agent P&S Key has been updated + iPanCoexistenceConnectionObserver.MpccoPanCoexistenceConnectionUpdated(ERndisIsActive); + break; + + case EBTPanIsActive: + //Setting the P&S key to EBTPanIsActive when BT PAN is not active or BT PAN is already active + __ASSERT_DEBUG(iActivePanConnectionExists && iLocallyInitiatedTransition, PanAgentPanic(EImproperSituationToSetPropertyToBTPanIsActive)); + break; + + default: + __ASSERT_DEBUG(EFalse, PanAgentPanic(EInvalidIPBearerCoexistanceProperty)); + break; + } + + iLocallyInitiatedTransition = EFalse; + + //Resubscribe to the property + SubscribeToProperty(); + } +