bluetoothengine/bteng/src/btengsrvbbconnectionmgr.cpp
changeset 0 f63038272f30
child 12 b23265fb36da
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/bteng/src/btengsrvbbconnectionmgr.cpp	Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,390 @@
+/*
+* Copyright (c) 2006 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:  Helper class for handling Bluetooth Baseband-related 
+*                connection management.
+*
+*/
+
+
+
+#include <wlaninternalpskeys.h>
+#include <featmgr.h>
+
+#include "btengsrvbbconnectionmgr.h"
+#include "debug.h"
+
+/**  ?description */
+const TInt KBTEngSrvBBConnId = 11;
+/**  ?description */
+const TInt KBTEngSrvWlanStatusId = 12;
+/**  ?description */
+const TInt KBTEngMaxAddrArraySize = 10;
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// C++ default constructor
+// ---------------------------------------------------------------------------
+//
+CBTEngSrvBBConnMgr::CBTEngSrvBBConnMgr(RSocketServ& aSockServ)
+    : iSockServ(aSockServ)
+    {
+    }
+
+
+// ---------------------------------------------------------------------------
+// Symbian 2nd-phase constructor
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvBBConnMgr::ConstructL()
+    {
+    iLinkCountWatcher = CBTEngActive::NewL( *this, KBTEngSrvBBConnId, 
+                                             CActive::EPriorityStandard );
+        // Subscribe to the BT Baseband link count.
+    User::LeaveIfError( iLinkCountProperty.Attach( KPropertyUidBluetoothCategory, 
+                                                KPropertyKeyBluetoothGetPHYCount ) );
+    // Check if we need to monitor WLAN
+    FeatureManager::InitializeLibL();
+    iWlanSupported = FeatureManager::FeatureSupported( KFeatureIdProtocolWlan );
+    FeatureManager::UnInitializeLib();
+    if( iWlanSupported )
+        {
+        iWlanWatcher = CBTEngActive::NewL( *this, KBTEngSrvWlanStatusId, 
+                                                  CActive::EPriorityStandard );
+        User::LeaveIfError( iWlanStatusProperty.Attach( KPSUidWlan, 
+                                                         KPSWlanIndicator ) );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// NewL
+// ---------------------------------------------------------------------------
+//
+CBTEngSrvBBConnMgr* CBTEngSrvBBConnMgr::NewL(RSocketServ& aSockServ)
+    {
+    CBTEngSrvBBConnMgr* self = new( ELeave ) CBTEngSrvBBConnMgr(aSockServ);
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CBTEngSrvBBConnMgr::~CBTEngSrvBBConnMgr()
+    {
+    Unsubscribe();
+	iLinkCountProperty.Close();
+    iWlanStatusProperty.Close();
+	delete iLinkCountWatcher;
+	delete iWlanWatcher;
+	delete iPhyLinks;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Start listening to the relevant properties.
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvBBConnMgr::Subscribe()
+    {
+    if( !iLinkCountWatcher->IsActive() )
+        {
+        iLinkCountProperty.Subscribe( iLinkCountWatcher->RequestStatus() );
+        iLinkCountWatcher->GoActive();
+        }
+    if( iWlanSupported && !iWlanWatcher->IsActive() )
+        {
+        iWlanStatusProperty.Subscribe( iWlanWatcher->RequestStatus() );
+        iWlanWatcher->GoActive();
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Stop listening to the subscribed properties.
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvBBConnMgr::Unsubscribe()
+    {
+    if( iLinkCountWatcher->IsActive() )
+        {
+        iLinkCountProperty.Cancel();
+        iLinkCountWatcher->CancelRequest();
+        }
+	if( iWlanWatcher && iWlanWatcher->IsActive() )
+	    {
+	    iWlanStatusProperty.Cancel();
+	    iWlanWatcher->CancelRequest();
+	    }
+    }
+
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TInt CBTEngSrvBBConnMgr::ManageTopology( TBool aPrepDiscovery )
+    {
+    TInt linkCount = 0;
+    TBool closeSock = ETrue;    // To check if we can close the handle again.
+    TInt err = iLinkCountProperty.Get( linkCount );
+    if( !err && !linkCount && iAutoSwitchOff )
+        {
+            // Inform server that there are no active connections anymore.
+        iAutoSwitchOff = EFalse;
+        iCallBack.CallBack();
+        }
+    RBTDevAddrArray addrArray;
+    TInt minLinks = 1;  // We don't care about our role if we have only one link.
+    if( aPrepDiscovery || GetWlanStatus() )
+        {
+            // If we are performing discovery shortly, or we have an active WLAN 
+            // connection, then request master role on all links.
+        minLinks = 0;
+        }
+    if( !err && linkCount > minLinks )
+        {
+        if( iPhyLinks )
+            {
+                // If we have an open handle with the socket server (because we
+                // are disconnecting all links), then don't close the socket.
+            closeSock = EFalse;
+            }
+            // There are existing links; get the addresses.
+        TRAP( err, GetConnectedAddressesL( addrArray ) );
+        }
+    if( !err && addrArray.Count() > minLinks )
+        {
+            // Try to become master on all the links.
+        RBTPhysicalLinkAdapter btLink;
+        for( TInt i = 0; i < addrArray.Count(); i++ )
+            {
+                // At this point, the results of the operations do not matter 
+                // too much. If an error is returned, then that only affects 
+                // further operations on the same link, and they should not be 
+                // passed back to the caller.
+            TUint32 basebandState = 0;
+            err = btLink.Open( iSockServ, addrArray[ i ] );
+            if( !err )
+                {
+                    // Mostly for logging purposes, check the current role (the 
+                    // request will anyway be ignored if we're already master).
+                err = btLink.PhysicalLinkState( basebandState );
+                TRACE_INFO( ( 
+                    _L( "[BTEng]\t ManageTopology: Current role: %d; status: %d" ), 
+                    (TInt) ( basebandState & ENotifyAnyRole ), err ) )
+                }
+            if( !err && ( basebandState & ENotifySlave ) )
+                {
+                    // Try to become master of this link. This request could 
+                    // be issued without checking the current role, and would 
+                    // just be ignored if we are already master. The return 
+                    // value is also ignored later on, at this stage it is 
+                    // not important if the call succeeds.
+                err = btLink.RequestMasterRole();
+                TRACE_INFO( ( 
+                    _L( "[BTEng]\t Requesting master role; result: %d" ),  err ) )
+                }
+                // Reset the result, so that it is not passed up 
+                // (in case this was the last one in the loop).
+            err = KErrNone;
+            btLink.Close();
+            }
+        }
+    addrArray.Close();
+    if( closeSock )
+        {
+        delete iPhyLinks;
+        iPhyLinks = NULL;
+        }
+    return err;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Gets an array of addresses of remote devices for all Baseband connections.
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvBBConnMgr::GetConnectedAddressesL( RBTDevAddrArray& aAddrArray )
+    {
+    TInt err = KErrNone;
+    if( !iPhyLinks )
+        {
+        iPhyLinks = CBluetoothPhysicalLinks::NewL( *this, iSockServ );
+        }
+    if( !err )
+        {
+        err = iPhyLinks->Enumerate( aAddrArray, KBTEngMaxAddrArraySize );
+        }
+    User::LeaveIfError( err );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Request to disconnect all Bluetooth baseband connections.
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvBBConnMgr::DisconnectAllLinksL( TCallBack& aCallBack )
+    {
+    TRACE_FUNC_ENTRY
+    iCallBack = aCallBack;
+    RBTDevAddrArray addrArray;
+    GetConnectedAddressesL( addrArray );
+    TInt err = KErrNone;
+    if( addrArray.Count() > 0 )
+        {
+        err = iPhyLinks->DisconnectAll();
+        }
+    else
+        {
+        err = KErrNotFound;
+        }
+    addrArray.Close();
+    if( err && err != KErrInUse )
+        {
+            // No connections, or something went wrong; just clean up 
+            // and inform our client.
+        HandleDisconnectAllCompleteL( err );
+        }
+    TRACE_FUNC_EXIT
+    }
+
+
+// ---------------------------------------------------------------------------
+// Request to disconnect all Bluetooth baseband connections.
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvBBConnMgr::SetAutoSwitchOff( TBool aEnable, TCallBack& aCallBack )
+    {
+    iAutoSwitchOff = aEnable;
+	iCallBack = aCallBack;
+    if( aEnable )
+        {
+        TInt linkCount = 0;
+        TInt err = iLinkCountProperty.Get( linkCount );
+        if( !err && !linkCount )
+            {
+            iCallBack.CallBack();
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// From class MBluetoothPhysicalLinksNotifier.
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvBBConnMgr::HandleCreateConnectionCompleteL( TInt aErr )
+    {
+    (void) aErr;
+    }
+
+
+// ---------------------------------------------------------------------------
+// From class MBluetoothPhysicalLinksNotifier.
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvBBConnMgr::HandleDisconnectCompleteL( TInt aErr )
+    {
+    (void) aErr;
+    }
+
+
+// ---------------------------------------------------------------------------
+// From class MBluetoothPhysicalLinksNotifier.
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvBBConnMgr::HandleDisconnectAllCompleteL( TInt aErr )
+    {
+    TRACE_FUNC_ARG( ( _L( "error: %d" ), aErr ) )
+    delete iPhyLinks;
+    iPhyLinks = NULL;
+    iCallBack.CallBack();  // Inform our client.
+    (void) aErr;    // There is no way to pass the error code; 
+                    // anyway our client is not interested..
+    }
+
+
+// ---------------------------------------------------------------------------
+// From class MBTEngActiveObserver.
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvBBConnMgr::RequestCompletedL( CBTEngActive* aActive, TInt aId, 
+    TInt aStatus )
+    {
+    TRACE_FUNC_ARG( ( _L( "id: %d; status: %d" ), aId, aStatus ) )
+    ASSERT( aId == KBTEngSrvBBConnId || aId == KBTEngSrvWlanStatusId );
+    (void) aActive;
+    (void) aId;
+    if( aStatus != KErrPermissionDenied )
+        {
+            // Ignore any other errors.
+            // First subscribe again, so that we don't miss any updates.
+            Subscribe();
+        }
+    (void) ManageTopology( EFalse );    // Ignore result; nothing to do 
+                                        // about it here.
+    TRACE_FUNC_EXIT
+    }
+
+
+// ---------------------------------------------------------------------------
+// From class MBTEngActiveObserver.
+// Handles an error in RunL( i.e. RequestCompletedL). Does nothing, since our
+// RunL cannot actually leave.
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvBBConnMgr::HandleError( CBTEngActive* aActive, TInt aId, 
+    TInt aError )
+    {
+    TRACE_FUNC_ARG( ( _L( "id: %d; status: %d" ), aId, aError ) )
+    (void) aActive;
+    (void) aId;
+    (void) aError;
+    }
+
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TBool CBTEngSrvBBConnMgr::GetWlanStatus()
+    {
+    TInt wlanStatus = 0;
+    TBool connected = EFalse;
+    if( iWlanSupported )
+        {
+        TInt err = iWlanStatusProperty.Get( wlanStatus );
+        if( err )
+            {
+            wlanStatus = 0; // Reset just to be sure.
+            }
+        }
+    if( wlanStatus == EPSWlanIndicatorActive || 
+        wlanStatus == EPSWlanIndicatorActiveSecure )
+        {
+        connected = ETrue;
+        }
+    return connected;
+    }