--- /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;
+ }