diff -r 000000000000 -r f63038272f30 bluetoothengine/bteng/src/btengsrvbbconnectionmgr.cpp --- /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 +#include + +#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; + }