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