--- /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 <bluetooth/logger.h>
+
+#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<TIPBearerCoexistenceStatus>(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();
+ }
+