bluetoothengine/bteng/src/btengsrvpluginmgr.cpp
changeset 0 f63038272f30
child 10 0707dd69d236
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/bteng/src/btengsrvpluginmgr.cpp	Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,843 @@
+/*
+* 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 BTEng server to manage and interface with
+*                the profile plug-ins the profile plug-ins.
+*
+*/
+
+
+
+#include <ecom/ecom.h>
+#include <btsdp.h>
+#include <centralrepository.h>
+#include <featmgr.h>
+
+#include "btengsrvpluginmgr.h"
+#include "btengserver.h"
+#include "btengsrvsession.h"
+#include "btengsrvbbconnectionmgr.h"
+#include "btengprivatecrkeys.h"
+#include "debug.h"
+#include <btfeaturescfg.h>
+
+/**  UID for BTEng plug-ins */
+const TUid KBTEngPluginUid = { 0x2000277B };
+/**  ECOM registration info for BTSAP plugin */
+_LIT8( KEComBTSapPlugin, "112D" );
+/**  The message argument which holds the Bluetooth address. */
+const TInt KBTEngAddrSlot = 0;
+/**  The message argument which holds the connection status parameter. */
+const TInt KBTEngParamSlot = 1;
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// C++ default constructor
+// ---------------------------------------------------------------------------
+//
+CBTEngSrvPluginMgr::CBTEngSrvPluginMgr( CBTEngServer* aServer )
+:    iServer( aServer )
+    {
+    }
+
+
+// ---------------------------------------------------------------------------
+// Symbian 2nd-phase constructor
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvPluginMgr::ConstructL()
+    {
+    }
+
+
+// ---------------------------------------------------------------------------
+// NewL
+// ---------------------------------------------------------------------------
+//
+CBTEngSrvPluginMgr* CBTEngSrvPluginMgr::NewL( CBTEngServer* aServer )
+    {
+    CBTEngSrvPluginMgr* self = new( ELeave ) CBTEngSrvPluginMgr( aServer );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CBTEngSrvPluginMgr::~CBTEngSrvPluginMgr()
+    {
+    iPluginInfoArray.Close();
+    iPluginArray.ResetAndDestroy();
+    }
+
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvPluginMgr::ProcessCommandL( const RMessage2& aMessage )
+    {
+    TRACE_FUNC_ENTRY
+    TInt opcode = aMessage.Function();
+    TInt err = KErrNone;
+    TBTDevAddrPckgBuf addr;
+    switch( opcode )
+        {
+        case EBTEngConnectDevice:
+            {
+            aMessage.ReadL( KBTEngAddrSlot, addr );
+            TBTEngDevClassPkg cod;
+            aMessage.ReadL( KBTEngParamSlot, cod );
+            err = Connect( addr(), TBTDeviceClass( cod() ) );
+            }
+            break;
+        case EBTEngCancelConnectDevice:
+            {
+            aMessage.ReadL( KBTEngAddrSlot, addr );
+            err = CancelConnect( addr() );
+            }
+            break;
+        case EBTEngDisconnectDevice:
+            {
+            aMessage.ReadL( KBTEngAddrSlot, addr );
+            TPckgBuf<TUint> discType;
+            aMessage.ReadL( KBTEngParamSlot, discType );
+            err = Disconnect( addr(), (TBTDisconnectType) discType() );
+            }
+            break;
+        case EBTEngIsDeviceConnected:
+            {
+            aMessage.ReadL( KBTEngAddrSlot, addr );
+            TBTEngConnectionStatus connectStatus = EBTEngNotConnected;
+            connectStatus = IsDeviceConnected( addr() );
+            TBTEngParamPkg statusPkg( connectStatus );
+            aMessage.WriteL( KBTEngParamSlot, statusPkg );
+            }
+            break;
+        case EBTEngIsDeviceConnectable:
+            {
+            aMessage.ReadL( KBTEngAddrSlot, addr );
+            TBTEngDevClassPkg cod;
+            aMessage.ReadL( KBTEngParamSlot, cod );
+            TBool connectable = ( GetConnectablePluginIndex(cod(), addr() ) != KErrNotFound ) ;
+            TPckgBuf<TBool> connPkg( connectable );
+            aMessage.WriteL( 2, connPkg );
+            }
+            break;
+        case EBTEngGetConnectedAddresses:
+            {
+            TPckgBuf<TBTProfile> profile;
+            aMessage.ReadL( KBTEngParamSlot, profile );
+            RBTDevAddrArray addrArray;
+            if( profile() == EBTProfileUndefined )
+                {
+                    // Get all baseband connections
+                iServer->iBBConnMgr->GetConnectedAddressesL( addrArray );
+                }
+            else
+                {
+                err = GetConnectedAddresses( addrArray, profile() );
+                }
+            HBufC8* buf = HBufC8::NewLC( aMessage.GetDesMaxLengthL( KBTEngAddrSlot ) );
+            TPtr8 ptr = buf->Des();
+            aMessage.ReadL( KBTEngAddrSlot, ptr );
+            ptr.Zero();
+            for( TInt i = 0; i < addrArray.Count(); i++ )
+                {
+                addr = addrArray[ i ];
+                ptr.Append( addr );
+                }
+            aMessage.WriteL( KBTEngAddrSlot, ptr );
+            CleanupStack::PopAndDestroy( buf );
+            }
+            break;
+        default:
+            {
+            TRACE_INFO( ( _L( "ProcessCommandL: bad request (%d)" ), 
+                           aMessage.Function() ) )
+            err = KErrArgument;
+            }
+            break;
+        }
+    User::LeaveIfError( err );
+    TRACE_FUNC_EXIT
+    }
+
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvPluginMgr::DisconnectAllPlugins()
+    {
+    TRACE_FUNC_ENTRY
+    TBTDevAddr nullAddr;
+    for( TInt i = 0; i < iPluginArray.Count(); i++ )
+        {
+        (void) iPluginArray[ i ]->Disconnect( nullAddr, EBTDiscImmediate );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvPluginMgr::LoadProfilePluginsL( const TEComResolverParams aParams )
+    {
+    TRACE_FUNC_ENTRY
+    if( aParams.DataType().Length() )
+        {
+            // This is a request to enable a specific service, e.g. BT SAP.
+        REComSession::ListImplementationsL( KBTEngPluginUid, aParams, 
+                                             iPluginInfoArray );
+        }
+    else
+        {
+        if( iPluginArray.Count() > 0 || iPluginInfoArray.Count() > 0 )
+            {
+                // Could be the case if we received a command to turn BT on 
+                // halfway through a power down sequence. Just ignore.
+            return;
+            }
+        iPluginInfoArray.Reset();
+        iPluginArray.Reset();
+        REComSession::ListImplementationsL( KBTEngPluginUid, iPluginInfoArray );
+        }
+        // Ignore the number of plug-ins left to load; the server state machine 
+        // will handle this at a later stage.
+    (void) LoadPluginL();
+    TRACE_FUNC_EXIT
+    }
+
+TBool CBTEngSrvPluginMgr::FilterByEnterpriseDisablementModeL(TUid aUid) const
+	{
+	TRACE_FUNC_ENTRY
+	TBool want = EFalse;
+	switch ( iServer->EnterpriseEnablementMode() )
+		{
+	case BluetoothFeatures::EDisabled:
+		// In Disabled mode all plugins are filtered out.
+		break;
+	case BluetoothFeatures::EDataProfilesDisabled:
+		// In 'privileged profiles only' mode we only allow the following.
+		if ( 		aUid == TUid::Uid(0x1020897B) // audio (i.e. allow HSP, HFP and A2DP)
+				||	aUid == TUid::Uid(0x10208979) // remote control (i.e. allow AVRCP) )
+				||	aUid == TUid::Uid(0x2001E309) // HID
+			)
+			{
+			want = ETrue;
+			}
+		break;
+	case BluetoothFeatures::EEnabled:
+		// In Enabled mode we do not filter plugins.
+		want = ETrue;
+		break;
+	default:
+		__ASSERT_DEBUG( NULL, PanicServer( EBTEngPanicCorruptSettings ) );
+		break;
+		}
+	TRACE_INFO( ( _L( "[BTENG]\t returning want = %d" ), want ) )
+	TRACE_FUNC_EXIT
+	return want;
+	}
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TInt CBTEngSrvPluginMgr::LoadPluginL()
+    {
+    TRACE_FUNC_ENTRY
+    if( !iPluginInfoArray.Count() )
+        {
+            // All plug-ins have been loaded.
+        return KErrNotFound;
+        }
+
+        // Simply pop the first info object, process it, and delete it.
+        // There is no need to keep it after the plug-in has been constructed.
+    CImplementationInformation* implInfo = iPluginInfoArray[ 0 ];
+    iPluginInfoArray.Remove( 0 );
+    CleanupStack::PushL( implInfo );
+    TLex8 lex( implInfo->DataType() );
+    TUint profile = (TInt) EBTProfileUndefined;
+    TInt err = lex.Val( profile, EHex );
+        // Check if the feature is allowed to be loaded
+    if( !err && CheckFeatureEnabledL( profile ) && FilterByEnterpriseDisablementModeL(implInfo->ImplementationUid()) )
+        {
+        TRACE_INFO( ( _L( "[BTENG]\t loading profile 0x%04x" ), profile ) )
+        TUid implUid = implInfo->ImplementationUid();
+        CBTEngPlugin* plugin = CBTEngPlugin::NewL( implUid );
+        CleanupStack::PushL( plugin );
+        plugin->SetObserver( ( MBTEngPluginObserver* ) this );
+        User::LeaveIfError( iPluginArray.Append( plugin ) );
+        CleanupStack::Pop( plugin );
+        }
+    CleanupStack::PopAndDestroy( implInfo ); 
+    TRACE_FUNC_RES( ( _L( "%d plug-ins left to load" ), iPluginInfoArray.Count() ) )
+    return iPluginInfoArray.Count();
+    }
+
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvPluginMgr::UnloadProfilePlugins()
+    {
+    TRACE_FUNC_ARG( ( _L( "[BTENG]\t unloading %d plug-ins" ), iPluginArray.Count() ) )
+
+    // All plug-ins need to be unloaded at once. Otherwise it gets too
+    // difficult to keep track in case of a power-on command during a 
+    // power-off sequence.
+    iPluginArray.ResetAndDestroy();
+
+    REComSession::FinalClose();
+    TRACE_FUNC_EXIT
+    }
+
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvPluginMgr::LoadBTSapPluginL()
+    {
+    TRACE_FUNC_ENTRY
+
+	// SAP is supported in neither Data Profiles Disabled nor Disabled mode.
+    if ( iServer->EnterpriseEnablementMode() != BluetoothFeatures::EEnabled )
+        {
+        TRACE_INFO( ( _L( "\tno we're not... Bluetooth is enterprise-IT-disabled" ) ) )
+        User::Leave(KErrNotSupported);
+        }
+    
+    if( CheckFeatureEnabledL( EBTProfileSAP ) )
+        {
+        TEComResolverParams params;
+        TPtrC8 ptr( KEComBTSapPlugin );
+        params.SetDataType( ptr );
+        LoadProfilePluginsL( params );
+        }
+    TRACE_FUNC_EXIT
+    }
+
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvPluginMgr::UnloadBTSapPlugin()
+    {
+    TRACE_FUNC_ENTRY
+    TInt ret = GetFirstPluginOfProfileSupported( EBTProfileSAP );
+    if( ret != KErrNotFound )
+        {
+        CBTEngPlugin* plugin = iPluginArray[ ret ];
+        iPluginArray.Remove( ret );
+        delete plugin;
+        }
+    
+    TRACE_FUNC_EXIT
+    }
+    
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvPluginMgr::DisconnectProfile( TBTProfile aProfile )
+    {
+    TRACE_FUNC_ENTRY
+    RBTDevAddrArray addrArray;
+    TInt count = iPluginArray.Count();
+    while( count )
+        {
+        count--;
+        if( iPluginArray[ count ]->IsProfileSupported( aProfile ) )
+            {
+            iPluginArray[ count ]->GetConnections( addrArray, aProfile );
+            for ( TInt i = 0;  i < addrArray.Count(); i++ )
+                {
+                iPluginArray[ count ]->Disconnect( addrArray[i], EBTDiscImmediate );
+                }
+            break;
+            }
+        }
+    TRACE_FUNC_EXIT
+    }
+
+
+// ---------------------------------------------------------------------------
+// From class MBTEngPluginObserver.
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvPluginMgr::ConnectComplete( const TBTDevAddr& aAddr, 
+    TBTProfile aProfile, TInt aErr, RBTDevAddrArray* aConflicts )
+    {
+    TRACE_FUNC_ENTRY
+        // Inform listeners of this event.
+    (void) aProfile;
+    iServer->iSessionIter.SetToFirst();
+    CBTEngSrvSession* session = (CBTEngSrvSession*) iServer->iSessionIter++;
+    while( session )
+        {
+        TRACE_INFO( ( _L( "[BTEng]\t Notifying session %d" ), (TInt) session ) )
+        session->NotifyConnectionEvent( aAddr, EBTEngConnected, aConflicts, aErr );
+        session = (CBTEngSrvSession*) iServer->iSessionIter++;
+        }
+    TRACE_FUNC_EXIT
+    }
+
+
+// ---------------------------------------------------------------------------
+// From class MBTEngPluginObserver.
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CBTEngSrvPluginMgr::DisconnectComplete( const TBTDevAddr& aAddr, 
+    TBTProfile aProfile, TInt aErr )
+    {
+    TRACE_FUNC_ENTRY
+        // Inform listeners of this event.
+    (void) aProfile;
+    iServer->iSessionIter.SetToFirst();
+    CBTEngSrvSession* session = (CBTEngSrvSession*) iServer->iSessionIter++;
+    while( session )
+        {
+        TRACE_INFO( ( _L( "[BTEng]\t Notifying session %d" ), (TInt) session ) )
+        session->NotifyConnectionEvent( aAddr, EBTEngNotConnected, NULL, aErr );
+        session = (CBTEngSrvSession*) iServer->iSessionIter++;
+        }
+    TRACE_FUNC_EXIT
+    }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TInt CBTEngSrvPluginMgr::Connect( const TBTDevAddr& aAddr, 
+    const TBTDeviceClass& aDeviceClass )
+    {
+    TRACE_FUNC_ENTRY
+    TRACE_BDADDR ( aAddr )
+    TInt pindex = GetConnectablePluginIndex( aDeviceClass );    
+    TRACE_INFO( ( _L( "[BTEng]\t The %dth of plugin in plugarray to connect" ), pindex ) )
+    TInt err (KErrNotFound);
+    if( pindex != KErrNotFound && iPluginArray.Count())
+        {
+        err = iPluginArray[ pindex ]->Connect( aAddr );
+        }
+    TRACE_FUNC_RES( ( _L( "result: %d" ), err ) )
+    return err;
+    }
+
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TInt CBTEngSrvPluginMgr::CancelConnect( const TBTDevAddr& aAddr )
+    {
+    TRACE_FUNC_ENTRY
+    TInt err = KErrNotFound;
+    TRACE_BDADDR(aAddr);
+    for( TInt i = 0; i < iPluginArray.Count(); i++ )
+        {
+        TBTEngConnectionStatus status = iPluginArray[ i ]->IsConnected( aAddr );
+        if( status == EBTEngConnecting || status == EBTEngConnected )
+            {
+            (void) iPluginArray[ i ]->CancelConnect( aAddr );
+            err = KErrNone;
+            break;
+            }
+        }
+    TRACE_FUNC_RES( ( _L( "result: %d" ), err ) )
+    return err;
+    }
+
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TInt CBTEngSrvPluginMgr::Disconnect( const TBTDevAddr& aAddr, 
+    TBTDisconnectType aDiscType )
+    {
+    TRACE_FUNC_ENTRY
+    TRACE_BDADDR(aAddr);
+    TInt err = KErrNotFound;
+    for( TInt i = 0; i < iPluginArray.Count(); i++ )
+        {
+            // Should be ignored if the plug-in does not have 
+            // a connection to the address.
+        err = iPluginArray[ i ]->Disconnect( aAddr, aDiscType );
+        }
+    TRACE_FUNC_RES( ( _L( "result: %d" ), err ) )
+    return err;
+    }
+
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TBTEngConnectionStatus CBTEngSrvPluginMgr::IsDeviceConnected( const TBTDevAddr& aAddr )
+    {
+    TRACE_FUNC_ENTRY
+    TRACE_BDADDR(aAddr);
+    TBTEngConnectionStatus status = EBTEngNotConnected;
+    for( TInt i = 0; i < iPluginArray.Count(); i++ )
+        {
+        status = iPluginArray[ i ]->IsConnected( aAddr );
+        if( status == EBTEngConnecting || status == EBTEngConnected )
+            {
+            break;  // Just exit the loop here, we have a connection status.
+            }
+        }
+    TRACE_FUNC_RES( ( _L( "result: %d" ), (TInt) status ) )
+    return status;
+    }
+
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TInt CBTEngSrvPluginMgr::GetConnectablePluginIndex( const TBTDeviceClass& aDeviceClass, const TBTDevAddr& aAddr )
+    {
+    TRACE_FUNC_ENTRY
+    TInt plugindex( KErrNotFound );
+    TRACE_BDADDR(aAddr);
+    TRACE_INFO ( (_L("[BTENG] cod %b"), aDeviceClass.DeviceClass()))
+    if( aAddr != TBTDevAddr() )
+        {
+        DoGetEirData( aAddr );
+        }
+    
+    if( iUuidContainter.UUIDs().Count() > 0)
+        {
+        plugindex = GetConnectablePluginIndexByEir();
+        }
+    
+    if ( plugindex == KErrNotFound )
+        {
+        TBTProfile profile = MapDeviceClassToProfile( aDeviceClass );
+        if( profile == EBTProfileUndefined )
+            {
+            return plugindex;
+            }
+        
+        plugindex = GetFirstPluginOfProfileSupported( profile );
+        
+        if ( !iPluginArray.Count() )
+            {
+            // In case BT is off and plugins are not loaded
+            if ( profile == EBTProfileHFP || profile == EBTProfileA2DP )
+                {
+                plugindex = KErrNone; 
+                }
+            }
+        }
+    
+    TRACE_FUNC_RES( ( _L( "result: %d" ), plugindex ) )
+    return plugindex;
+    }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TInt CBTEngSrvPluginMgr::GetConnectedAddresses( RBTDevAddrArray& aAddrArray, 
+    TBTProfile aProfile )
+    {
+    TRACE_FUNC_ENTRY    
+    TInt ret = GetFirstPluginOfProfileSupported( aProfile );
+    if( ret != KErrNotFound )
+        {
+        iPluginArray[ ret ]->GetConnections( aAddrArray, aProfile );
+        ret = KErrNone;
+        }
+    TRACE_FUNC_RES( ( _L( "result: %d" ), ret ) )
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TBool CBTEngSrvPluginMgr::CheckFeatureEnabledL( TInt aProfile )
+    {
+    TRACE_FUNC_ARG( ( _L( "requested feature: 0x%04x" ), aProfile ) )
+        // By default, a feature is supported. This allowd features that do not
+        // have a related feature flag to be loaded too.
+    TBool supported = ETrue;
+    if( aProfile == EBTProfileSAP )
+        {
+            // First check from central repository.
+        CRepository* cenrep = CRepository::NewL( KCRUidBTEngPrivateSettings );
+        TInt enabled = 0;
+        TInt err = cenrep->Get( KBTSapEnabled, enabled );
+        delete cenrep;
+        if( err || !enabled )
+            {
+            return EFalse;
+            }
+        }
+
+    TInt feature = MapProfileToFeature( aProfile );
+    if( feature )
+        {
+            // Check from feature manager if this phone enables this feature.
+        FeatureManager::InitializeLibL();
+        supported = FeatureManager::FeatureSupported( feature );
+        FeatureManager::UnInitializeLib();
+        }
+    TRACE_FUNC_RES( ( _L ( "result: %d" ), supported ) )
+    return supported;
+    }
+
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TBTProfile CBTEngSrvPluginMgr::MapDeviceClassToProfile( 
+    const TBTDeviceClass& aDeviceClass )
+    {
+    TRACE_FUNC_ARG( ( _L( "Mapping CoD %b ..." ), aDeviceClass.DeviceClass() ) )
+    // Could (should?) be done more dynamically or with some header file definition.
+    // Right now these are the only known/possible ECOM plug-ins.
+    TBTProfile profile = EBTProfileUndefined;
+    if( aDeviceClass.MajorServiceClass() & EMajorServiceAudio )
+        {
+        profile = EBTProfileHFP;
+        }
+    else if( aDeviceClass.MajorServiceClass() & EMajorServiceRendering &&
+            ( aDeviceClass.MajorDeviceClass() != EMajorDeviceImaging ) )
+        // Printer or camera or other imaging device may set EMajorServiceRendering bit
+        // as well as stereo audio device, so check EMajorDeviceImaging too.
+        {
+        profile = EBTProfileA2DP;
+        }
+    else if( aDeviceClass.MajorDeviceClass() == EMajorDevicePeripheral &&
+            ( (aDeviceClass.MinorDeviceClass() & EMinorDevicePeripheralKeyboard) ||
+              (aDeviceClass.MinorDeviceClass() & EMinorDevicePeripheralPointer) ) )
+        {
+        profile = EBTProfileHID;
+        }
+    else if( aDeviceClass.MajorDeviceClass() == EMajorDeviceLanAccessPoint )
+        {
+            // Mainly for testing now; PAN profile is a personal favorite.
+        profile = EBTProfilePANU;
+        }
+    
+    TRACE_FUNC_RES( ( _L( "... to profile 0x%04x." ), profile ) )
+    return profile;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Maps a profile UUID to any Bluetooth-related pflatfom feature flag.
+// ---------------------------------------------------------------------------
+//
+TInt CBTEngSrvPluginMgr::MapProfileToFeature( TInt aProfile )
+    {
+    TInt feature = 0;
+    switch( aProfile )
+        {
+        case EBTProfileHSP:
+        case EBTProfileHFP:
+            {
+            feature = KFeatureIdBtAudio;
+            }
+            break;
+        case EBTProfileA2DP:
+            {
+            feature = KFeatureIdBtStereoAudio;
+            }
+            break;
+        case EBTProfileSAP:
+            {
+            feature = KFeatureIdBtSap;
+            }
+            break;
+        case EBTProfileDUN:
+            {
+            feature = KFeatureIdDialupNetworking;
+            }
+            break;
+        case EBTProfileFAX:
+            {
+            feature = KFeatureIdBtFaxProfile;
+            }
+            break;
+        case EBTProfilePANU:
+        case EBTProfileNAP:
+        case EBTProfileGN:
+            {
+            //feature = KFeatureIdBtPanProfile;
+            feature = 0;// Testin'
+            }
+            break;
+        case EBTProfileBIP:
+            {
+            feature = KFeatureIdBtImagingProfile;
+            }
+            break;
+        case EBTProfileBPP:
+            {
+            feature = KFeatureIdBtPrintingProfile;
+            }
+            break;
+        default:
+            break;
+        }
+    TRACE_FUNC_RES( ( _L( "selected feature %d" ), feature ) )
+    return feature;
+    }
+
+// ---------------------------------------------------------------------------
+// Get Eir Data by hostResolver in Cache
+// ---------------------------------------------------------------------------
+//
+TInt CBTEngSrvPluginMgr::DoGetEirData( const TBTDevAddr& aAddr )
+    {
+    TRACE_FUNC_ENTRY
+    TInt err = KErrNone;
+    iUuidContainter.Close();
+    
+    if( !iServer->iSocketServ.Handle() )
+        {
+        err = iServer->iSocketServ.Connect();
+        }
+    
+    TProtocolDesc pInfo;
+    if(err == KErrNone)
+        {
+        _LIT(KBTLinkManagerProtocol, "BTLinkManager");
+        err = iServer->iSocketServ.FindProtocol( KBTLinkManagerProtocol(), pInfo );
+        }
+    if (err == KErrNone)
+        {
+        err = iHostResolver.Open(iServer->iSocketServ, pInfo.iAddrFamily, pInfo.iProtocol);
+        }
+    if(err == KErrNone)
+        {
+        iInquirySockAddr = TInquirySockAddr();
+        iInquirySockAddr.SetBTAddr(aAddr);
+        iInquirySockAddr.SetAction(KHostResCache | KHostResEir);
+        
+        TRequestStatus status;
+        iHostResolver.GetByAddress(iInquirySockAddr, iNameEntry, status);
+        User::WaitForRequest(status);
+        err = status.Int();
+        TRACE_FUNC_RES(( _L( "HostResolver GetByAddress status: %d" ), err))
+        iHostResolver.Close();
+        }
+    if(err == KErrNone)
+        {
+        TBluetoothNameRecordWrapper eirWrapper( iNameEntry() );
+        err = eirWrapper.GetServiceClassUuids( iUuidContainter );
+        }
+    
+    TRACE_FUNC_EXIT
+    return err;
+    }
+
+// ---------------------------------------------------------------------------
+// Check if Service UUID is supported by some plugin.
+// ---------------------------------------------------------------------------
+//
+TInt CBTEngSrvPluginMgr::GetConnectablePluginIndexByEir()
+    {
+    CBTEngPlugin::RProfileArray profiles;
+    TInt count = iUuidContainter.UUIDs().Count();
+    
+    for( TInt u = 0; u < count; u++)
+        {
+        for( TInt i = 0; i < iPluginArray.Count(); i++ )
+            {
+            profiles.Reset();
+            iPluginArray[ i ]->GetSupportedProfiles( profiles );
+            for (TInt x = 0; x < profiles.Count(); x++)
+                {
+                if (iUuidContainter.UUIDs().At(u) == TUUID(profiles[x]))
+                    {
+                    profiles.Close();
+    				TRACE_INFO( ( _L( "connectable plugin index %d" ), i ) )
+                    return i;
+                    }
+                }
+            }
+        }
+    profiles.Close();
+    return KErrNotFound;
+    }
+
+// ---------------------------------------------------------------------------
+// Internal utility function 
+// ---------------------------------------------------------------------------
+//
+TInt CBTEngSrvPluginMgr::GetFirstPluginOfProfileSupported(TBTProfile aProfile )
+    {
+    TRACE_FUNC_ENTRY
+    for( TInt i = 0; i < iPluginArray.Count(); i++ )
+        {
+        if( iPluginArray[ i ]->IsProfileSupported( aProfile ) )
+            {
+            return i;
+            }
+        }
+    return KErrNotFound;
+    }
+
+// ---------------------------------------------------------------------------
+//  Check if any audio connection exists. 
+// ---------------------------------------------------------------------------
+//
+	
+TBool CBTEngSrvPluginMgr::CheckAudioConnectionsL()
+    {
+    TRACE_FUNC_ENTRY
+    TBool result = EFalse;
+    RArray <TBTProfile> profiles;
+	CleanupClosePushL( profiles );
+    profiles.AppendL( EBTProfileHSP );
+    profiles.AppendL( EBTProfileHFP );
+    profiles.AppendL( EBTProfileA2DP );
+    profiles.AppendL( EBTProfileAVRCP );
+    
+	RBTDevAddrArray addrArray;	
+    for ( TInt i = 0; i < profiles.Count(); i++ )
+        {
+        GetConnectedAddresses( addrArray, profiles[i] );
+        if ( addrArray.Count() > 0 )
+            {
+            result = ETrue;
+            break;
+            }
+        addrArray.Reset();
+        }
+	addrArray.Close();
+	
+	CleanupStack::PopAndDestroy( &profiles );
+    TRACE_FUNC_RES( ( _L( "result: %d" ), result ) )
+    return result;
+    }