bluetoothengine/bteng/src/btengsrvsettingsmgr.cpp
changeset 23 988cddd6adbd
child 11 a42ed326b458
equal deleted inserted replaced
22:4255033c5d30 23:988cddd6adbd
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: Class to manage Bluetooth hardware and stack settings.
       
    15 *
       
    16 */
       
    17 
       
    18 #include "btengsrvsettingsmgr.h"
       
    19 #include <bthci.h>
       
    20 #include <bt_subscribe_partner.h>
       
    21 #include <btnotif.h>
       
    22 #include <btengdomainpskeys.h>
       
    23 #include <centralrepository.h>
       
    24 #include <featmgr.h>
       
    25 #include <AknSmallIndicator.h>
       
    26 #include <avkon.hrh>
       
    27 
       
    28 #include "btengserver.h"
       
    29 #include "btengsrvpluginmgr.h"
       
    30 #include "btengsrvbbconnectionmgr.h"
       
    31 #include "btengsrvstate.h"
       
    32 #include "debug.h"
       
    33 
       
    34 #ifndef SETLOCALNAME
       
    35 #include <btengsettings.h>
       
    36 #endif
       
    37 
       
    38 /** ID of active object helper */
       
    39 const TInt KBTEngSettingsActive = 30;
       
    40 /** Constant for converting minutes to microseconds */
       
    41 //const TInt64 KMinutesInMicroSecs = 60000000;
       
    42 const TInt64 KMinutesInMicroSecs = MAKE_TINT64( 0, 60000000 );
       
    43 /**  Timeout for disabling Simple Pairing debug mode. The value is 30 minutes. */
       
    44 //const TInt KBTEngSspDebugModeTimeout = 1800000000;
       
    45 const TInt64 KBTEngSspDebugModeTimeout = MAKE_TINT64( 0, 1800000000 );
       
    46 /**  Timeout for turning BT off automatically. The value is 10.5 seconds. */
       
    47 const TInt KBTEngBtAutoOffTimeout = 10500000;
       
    48 /**  Default values for Major Service Class */
       
    49 const TUint16 KCoDDefaultServiceClass = EMajorServiceTelephony | EMajorServiceObjectTransfer | EMajorServiceNetworking;
       
    50 /**  Default values for Major Device Class */
       
    51 const TUint8 KCoDDefaultMajorDeviceClass = EMajorDevicePhone;
       
    52 /**  Default values for Minor Device Class */
       
    53 const TUint8 KCoDDefaultMinorDeviceClass = EMinorDevicePhoneSmartPhone;
       
    54 
       
    55 
       
    56 // ======== MEMBER FUNCTIONS ========
       
    57 
       
    58 // ---------------------------------------------------------------------------
       
    59 // C++ default constructor
       
    60 // ---------------------------------------------------------------------------
       
    61 //
       
    62 CBTEngSrvSettingsMgr::CBTEngSrvSettingsMgr( CBTEngServer* aServer )
       
    63 :   iServer( aServer )
       
    64     {
       
    65     }
       
    66 
       
    67 
       
    68 // ---------------------------------------------------------------------------
       
    69 // Symbian second-phase constructor
       
    70 // ---------------------------------------------------------------------------
       
    71 //
       
    72 void CBTEngSrvSettingsMgr::ConstructL()
       
    73     {
       
    74     TRACE_FUNC_ENTRY
       
    75     iActive = CBTEngActive::NewL( *this, KBTEngSettingsActive );
       
    76     LoadBTPowerManagerL();
       
    77     iEnterpriseEnablementMode = BluetoothFeatures::EnterpriseEnablementL();
       
    78     TRACE_INFO( ( _L( "iEnterpriseEnablementMode = %d" ), iEnterpriseEnablementMode) )
       
    79     if ( iEnterpriseEnablementMode == BluetoothFeatures::EDisabled )
       
    80         {
       
    81         SetVisibilityModeL( EBTVisibilityModeNoScans, 0 );
       
    82         }
       
    83     TRACE_FUNC_EXIT
       
    84     }
       
    85 
       
    86 
       
    87 // ---------------------------------------------------------------------------
       
    88 // NewL
       
    89 // ---------------------------------------------------------------------------
       
    90 //
       
    91 CBTEngSrvSettingsMgr* CBTEngSrvSettingsMgr::NewL( CBTEngServer* aServer )
       
    92     {
       
    93     CBTEngSrvSettingsMgr* self = new( ELeave ) CBTEngSrvSettingsMgr( aServer );
       
    94     CleanupStack::PushL( self );
       
    95     self->ConstructL();
       
    96     CleanupStack::Pop( self );
       
    97     return self;
       
    98     }
       
    99 
       
   100 
       
   101 // ---------------------------------------------------------------------------
       
   102 // Destructor
       
   103 // ---------------------------------------------------------------------------
       
   104 //
       
   105 CBTEngSrvSettingsMgr::~CBTEngSrvSettingsMgr()
       
   106     {
       
   107     if( iActive && iActive->IsActive() )
       
   108         {
       
   109         // Cancel the outstanding request.
       
   110         iPowerMgr.Cancel();
       
   111         }
       
   112     delete iActive;  
       
   113     iPowerMgr.Close();
       
   114     }
       
   115 
       
   116 
       
   117 // ---------------------------------------------------------------------------
       
   118 // Power Bluetooth hardware on or off.
       
   119 // ---------------------------------------------------------------------------
       
   120 //
       
   121 TInt CBTEngSrvSettingsMgr::SetHwPowerState( TBTPowerState aState )
       
   122     {
       
   123     TRACE_FUNC_ENTRY
       
   124     TInt err = KErrNone;
       
   125 #ifndef __WINS__
       
   126     if( iActive->IsActive() )
       
   127         {
       
   128         // Cancel the outstanding request.
       
   129         iPowerMgr.Cancel();
       
   130         iActive->Cancel();
       
   131         }
       
   132     iPowerMgr.SetPower( aState, NULL, iActive->RequestStatus() );
       
   133     iActive->GoActive();
       
   134 #else   //__WINS__
       
   135     iPowerState = aState;
       
   136 #endif  //__WINS__
       
   137 
       
   138    if( !err && aState == EBTOn )
       
   139         {
       
   140         TInt dutMode = EBTDutOff;
       
   141         err = RProperty::Get( KPSUidBluetoothTestingMode, KBTDutEnabled, dutMode );
       
   142         if( !err && dutMode == EBTDutOn )
       
   143             {
       
   144             // Set the DUT mode key to OFF since DUT mode is disabled at this point
       
   145             err = RProperty::Set( KPSUidBluetoothTestingMode, KBTDutEnabled, EBTDutOff );
       
   146             }
       
   147         }
       
   148     if( err )
       
   149         {
       
   150         // Power off if an error occurred during power on sequence.
       
   151 #ifndef __WINS__
       
   152             // This cannot happen in emulator environment.
       
   153         iPowerMgr.Cancel();
       
   154         iActive->Cancel();
       
   155         iPowerMgr.SetPower( EBTOff, NULL, iActive->RequestStatus() );
       
   156         User::WaitForRequest( iActive->RequestStatus() );
       
   157         // Result will be communicated through the caller of this function (by leaving).
       
   158 #else   //__WINS__
       
   159         iPowerState = EBTOff;
       
   160 #endif  //__WINS__
       
   161         } 
       
   162     TRACE_FUNC_RES( ( _L( "result: %d" ), err ) )
       
   163     return err;
       
   164     }
       
   165 
       
   166 
       
   167 // ---------------------------------------------------------------------------
       
   168 // Turn BT on or off.
       
   169 // ---------------------------------------------------------------------------
       
   170 //
       
   171 void CBTEngSrvSettingsMgr::SetPowerStateL( TBTPowerState aState, TBool aTemporary )
       
   172     {
       
   173     TRACE_FUNC_ARG( ( _L( "%d (temporary=%d" ), aState, aTemporary ) )
       
   174     if ( aState == EBTOn && iEnterpriseEnablementMode == BluetoothFeatures::EDisabled )
       
   175         {
       
   176         TRACE_INFO( ( _L( "no we're not... Bluetooth is enterprise-IT-disabled" ) ) )
       
   177         User::Leave(KErrNotSupported);
       
   178         }
       
   179     TBool idle = ( iServer->StateMachine()->CurrentOperation() == CBTEngSrvState::ESrvOpIdle );
       
   180     TBTPowerState currentState = EBTOff;
       
   181     CheckTemporaryPowerStateL( currentState, aState, aTemporary );
       
   182 
       
   183     if ( ( currentState == aState || ( aTemporary && aState == EBTOff ) ) && idle )
       
   184         {
       
   185         // The requested power state is already active, ignore silently.
       
   186         // We don't return an error here, as there is no error situation.
       
   187         TRACE_INFO( ( _L( "SetPowerStateL: nothing to do" ) ) )
       
   188         if ( currentState == aState )
       
   189             {
       
   190             // Make sure that the CenRep key is in sync.
       
   191             // During boot-up, the pwoer is set from the CenRep key, so we could 
       
   192             // end up out-of-sync.
       
   193             TRACE_INFO( ( _L( "SetPowerStateL: currentState == aState" ) ) )
       
   194             UpdateCenRepPowerKeyL( aState );
       
   195             } 
       
   196         return;
       
   197         }
       
   198     if ( aState == EBTOn )
       
   199         {
       
   200         // Hardware power on is the first step.
       
   201         User::LeaveIfError( SetHwPowerState( aState ) );
       
   202         }
       
   203     else
       
   204         {
       
   205         //Prevent BT visibility in the situation when we turn OFF BT Engine 
       
   206         //but FM Radio is still alive
       
   207         SetVisibilityModeL( EBTVisibilityModeNoScans, 0 );
       
   208         // Hardware power off is the last step.
       
   209         // First disconnect all plug-ins.
       
   210         iServer->PluginManager()->DisconnectAllPlugins();
       
   211         }
       
   212     // We only signal that BT is on after everything has completed (through 
       
   213     // the CenRep power state key), so that all services are initialized.
       
   214     // We signal that BT is off immediately though, so that our clients will 
       
   215     // not try to use BT during power down.
       
   216     iServer->StateMachine()->StartStateMachineL( aState );
       
   217     TRACE_FUNC_EXIT
       
   218     }
       
   219 
       
   220 // ---------------------------------------------------------------------------
       
   221 // Turn BT on or off.
       
   222 // ---------------------------------------------------------------------------
       
   223 //
       
   224 void CBTEngSrvSettingsMgr::SetPowerStateL(const RMessage2 aMessage )
       
   225     {
       
   226     TRACE_FUNC_ENTRY
       
   227     __ASSERT_ALWAYS( aMessage.Function() == EBTEngSetPowerState, 
       
   228             PanicServer( EBTEngPanicExpectSetPowerOpcode ) );
       
   229     if ( !iMessage.IsNull() )
       
   230         {
       
   231         // A power management request from a client is outstanding.
       
   232         User::Leave( KErrAlreadyExists );
       
   233         }
       
   234  
       
   235     TBTPowerStateValue arg = (TBTPowerStateValue) aMessage.Int0();
       
   236     // TBTPowerState power state type is inverted from TBTPowerStateValue,
       
   237     // which is used by the client to pass the parameter...
       
   238     TBTPowerState reqedPowerState( EBTOff );
       
   239     if ( arg == EBTPowerOn )
       
   240         {
       
   241         reqedPowerState = EBTOn;
       
   242         }
       
   243     TBool tempPowerOn = (TBool) aMessage.Int1();
       
   244     
       
   245     SetPowerStateL( reqedPowerState, tempPowerOn );
       
   246     if ( iServer->StateMachine()->CurrentOperation() == CBTEngSrvState::ESrvOpIdle )
       
   247         {
       
   248         // The request is accepted but the state machine is not running. This means the
       
   249         // requested power state is already active. Request is done.
       
   250         aMessage.Complete( KErrNone );
       
   251         }
       
   252     else
       
   253         {
       
   254         iMessage = RMessage2( aMessage );
       
   255         }
       
   256     TRACE_FUNC_EXIT
       
   257     }
       
   258 
       
   259 // ---------------------------------------------------------------------------
       
   260 // Initialize Bluetooth stack settings.
       
   261 // ---------------------------------------------------------------------------
       
   262 //
       
   263 void CBTEngSrvSettingsMgr::InitBTStackL()
       
   264     {
       
   265     TRACE_FUNC_ENTRY
       
   266     iServer->BasebandConnectionManager()->Subscribe();
       
   267     TBTVisibilityMode visibility = EBTVisibilityModeHidden;
       
   268     CRepository* cenRep = CRepository::NewL( KCRUidBTEngPrivateSettings );
       
   269     TInt err = cenRep->Get( KBTDiscoverable, (TInt&) visibility );
       
   270     delete cenRep;
       
   271     if (iRestoreVisibility == EFalse)
       
   272         {
       
   273         if( err || visibility == EBTVisibilityModeTemporary &&
       
   274             !( iServer->IsTimerQueued( CBTEngServer::EScanModeTimer ) ) )
       
   275             {
       
   276             visibility = EBTVisibilityModeHidden;
       
   277             }
       
   278         SetVisibilityModeL( visibility, 0 );
       
   279         }
       
   280 
       
   281     TBool sspDebugMode = EFalse;
       
   282     (void) RProperty::Get( KPropertyUidBluetoothCategory,
       
   283                 KPropertyKeyBluetoothGetSimplePairingDebugMode, (TInt&) sspDebugMode );
       
   284         // Only set debug mode to off if it is on, to prevent a loop notifications.
       
   285     if( sspDebugMode )
       
   286         {
       
   287         sspDebugMode = EFalse;
       
   288         // Add LeaveIfError if unsuccessful
       
   289         (void) RProperty::Set(KPropertyUidBluetoothCategory,
       
   290                     KPropertyKeyBluetoothSetSimplePairingDebugMode, (TInt) sspDebugMode );
       
   291         }
       
   292     TRACE_FUNC_EXIT
       
   293     }
       
   294 
       
   295 
       
   296 // ---------------------------------------------------------------------------
       
   297 // Reset settings and disconnect all links.
       
   298 // ---------------------------------------------------------------------------
       
   299 //
       
   300 void CBTEngSrvSettingsMgr::StopBTStackL()
       
   301     {
       
   302     TRACE_FUNC_ENTRY
       
   303     TBTVisibilityMode visibility = EBTVisibilityModeHidden;
       
   304     CRepository* cenRep = CRepository::NewL( KCRUidBTEngPrivateSettings );
       
   305           // Ignore error here; if we can't read it, likely we can't set it either.
       
   306     (void) cenRep->Get( KBTDiscoverable, (TInt&) visibility );
       
   307     delete cenRep;
       
   308     if( visibility == EBTVisibilityModeTemporary )
       
   309         {
       
   310         visibility = EBTVisibilityModeHidden;
       
   311         SetVisibilityModeL( visibility, 0 );    // Also cancels scan mode timer.
       
   312         }
       
   313 
       
   314         // Stop listening to events
       
   315     iServer->BasebandConnectionManager()->Unsubscribe();
       
   316         // Disconnect all links
       
   317     TCallBack cb( CBTEngServer::DisconnectAllCallBack, iServer );
       
   318     iServer->BasebandConnectionManager()->DisconnectAllLinksL( cb );
       
   319         // Results in a callback (which is called directly when there are no links).
       
   320     TRACE_FUNC_EXIT
       
   321     }
       
   322 
       
   323 
       
   324 // ---------------------------------------------------------------------------
       
   325 // Update the power state CenRep key.
       
   326 // ---------------------------------------------------------------------------
       
   327 //
       
   328 void CBTEngSrvSettingsMgr::UpdateCenRepPowerKeyL( TBTPowerState aState )
       
   329     {
       
   330     TRACE_FUNC_ENTRY
       
   331     CRepository* cenrep = CRepository::NewLC( KCRUidBluetoothPowerState );
       
   332     // TBTPowerState power state type is inverted from TBTPowerStateValue...
       
   333     TBTPowerStateValue power = (TBTPowerStateValue) !aState;
       
   334     User::LeaveIfError( cenrep->Set( KBTPowerState, (TInt) power ) );
       
   335     CleanupStack::PopAndDestroy( cenrep );
       
   336     TRACE_FUNC_EXIT
       
   337     }
       
   338 
       
   339 
       
   340 // ---------------------------------------------------------------------------
       
   341 // ?implementation_description
       
   342 // ---------------------------------------------------------------------------
       
   343 //
       
   344 void CBTEngSrvSettingsMgr::SetVisibilityModeL( TBTVisibilityMode aMode, TInt aTime )
       
   345     {
       
   346     TRACE_FUNC_ARG( ( _L( "[aMode: %d" ), aMode ) )
       
   347     if ( aMode != EBTVisibilityModeNoScans && iEnterpriseEnablementMode == BluetoothFeatures::EDisabled )
       
   348         {
       
   349         TRACE_INFO( ( _L( "\tnot changing anything... Bluetooth is enterprise-IT-disabled" ) ) )
       
   350         User::Leave( KErrNotSupported );
       
   351         }
       
   352 
       
   353     TInt err = KErrNone;
       
   354     iServer->RemoveTimer( CBTEngServer::EScanModeTimer );
       
   355     if( aMode != EBTVisibilityModeNoScans )
       
   356         {
       
   357         CRepository* cenRep = CRepository::NewL( KCRUidBTEngPrivateSettings );
       
   358         err = cenRep->Set( KBTDiscoverable, aMode );
       
   359         delete cenRep;
       
   360         }
       
   361     if( !err && aMode == EBTVisibilityModeTemporary )
       
   362         {
       
   363             // We need TInt64 here, as the max. time in microseconds for the 
       
   364             // max. value (1 hour) is larger than KMaxTInt32.
       
   365         TInt64 timeMicroSec = MAKE_TINT64( 0, aTime );
       
   366         timeMicroSec = timeMicroSec * KMinutesInMicroSecs;
       
   367             // Queue callback to set the visibility back to hidden.
       
   368         iServer->QueueTimer( CBTEngServer::EScanModeTimer, (TInt64) timeMicroSec );
       
   369         aMode = EBTVisibilityModeGeneral;
       
   370         }
       
   371     else if( !err && iRestoreVisibility )
       
   372         {
       
   373             // The user overrides, do not restore visibility mode anymore.
       
   374         iRestoreVisibility = EFalse;
       
   375         }
       
   376     if( !err )
       
   377         {
       
   378         err = RProperty::Set( KUidSystemCategory, 
       
   379                                KPropertyKeyBluetoothSetScanningStatus, aMode );
       
   380         }
       
   381     TBool hiddenMode = ( aMode == EBTVisibilityModeHidden );
       
   382     if( !err && aMode != EBTVisibilityModeNoScans )
       
   383         {
       
   384             // In hidden mode, we only accept connections from paired devices.
       
   385         err = RProperty::Set( KUidSystemCategory, 
       
   386                                KPropertyKeyBluetoothSetAcceptPairedOnlyMode, 
       
   387                                hiddenMode );
       
   388         }
       
   389 
       
   390     User::LeaveIfError( err );  // To communicate the result to the client.
       
   391     TRACE_FUNC_EXIT
       
   392     }
       
   393 
       
   394 
       
   395 // ---------------------------------------------------------------------------
       
   396 // Timed visible mode has expired.
       
   397 // ---------------------------------------------------------------------------
       
   398 //
       
   399 void CBTEngSrvSettingsMgr::ScanModeTimerCompletedL()
       
   400     {
       
   401     TRACE_FUNC_ENTRY
       
   402     SetVisibilityModeL( EBTVisibilityModeHidden, 0 );
       
   403     TBTPowerState power = EBTOff;
       
   404     TInt err = GetHwPowerState( power );
       
   405     if( !err && power )
       
   406         {
       
   407         // Show a notification to the user
       
   408         TBTGenericInfoNotiferParamsPckg pckg;
       
   409         pckg().iMessageType = EBTVisibilityTimeout;
       
   410         
       
   411         RNotifier notifier;
       
   412         TInt err = notifier.Connect();
       
   413         if( !err )
       
   414             {
       
   415             err = notifier.StartNotifier( KBTGenericInfoNotifierUid, pckg );
       
   416             notifier.Close();
       
   417             }
       
   418         }
       
   419     TRACE_FUNC_RES( ( _L( "result: %d" ), err ) )
       
   420     }
       
   421 
       
   422 
       
   423 // ---------------------------------------------------------------------------
       
   424 // Check the secure simple pairing debug mode and turn it off if needed.
       
   425 // ---------------------------------------------------------------------------
       
   426 //
       
   427 void CBTEngSrvSettingsMgr::CheckSspDebugModeL( TBool aDebugMode )
       
   428     {
       
   429     TRACE_FUNC_ARG( ( _L( "SSP debug mode state %d" ), (TInt) aDebugMode ) )
       
   430     TBTPowerState pwr = EBTOff;
       
   431     TBool currentMode = EFalse;
       
   432     TInt err = RProperty::Get( KPropertyUidBluetoothCategory, 
       
   433                                 KPropertyKeyBluetoothGetSimplePairingDebugMode, 
       
   434                                 (TInt&) currentMode );
       
   435 #ifndef __WINS__
       
   436     err = iPowerMgr.GetPower( pwr, NULL ); // Treat error as power off.
       
   437 #else   //__WINS__
       
   438     pwr = iPowerState;
       
   439 #endif  //__WINS__
       
   440     if( err || pwr == EBTOff )
       
   441         {
       
   442         iServer->RemoveTimer( CBTEngServer::ESspDebugModeTimer );
       
   443             // Only set debug mode to off if it is on, to prevent a loop notifications.
       
   444         if( currentMode )
       
   445             {
       
   446             (void) RProperty::Set( KPropertyUidBluetoothCategory, 
       
   447                                     KPropertyKeyBluetoothSetSimplePairingDebugMode,
       
   448                                     (TInt) aDebugMode );
       
   449             }
       
   450             // In case of an error in getting the power state, turn BT off. 
       
   451             // If BT is already off, this call will be ignored.
       
   452         SetPowerStateL( EBTOff, EFalse );
       
   453         }
       
   454     else if( aDebugMode )
       
   455         {
       
   456             // Ignore if there already is a timer queued.
       
   457         if( !( iServer->IsTimerQueued( CBTEngServer::ESspDebugModeTimer ) ) )
       
   458             {
       
   459             iServer->QueueTimer( CBTEngServer::ESspDebugModeTimer, (TInt64) KBTEngSspDebugModeTimeout );
       
   460             err =  RProperty::Set(KPropertyUidBluetoothCategory, 
       
   461                                    KPropertyKeyBluetoothSetSimplePairingDebugMode, 
       
   462                                    (TInt) aDebugMode );
       
   463             }
       
   464         }
       
   465     else
       
   466         {
       
   467             // Power is on, and debug mode is set to off.
       
   468         TInt linkCount = 0;
       
   469         err = RProperty::Get( KPropertyUidBluetoothCategory, 
       
   470                                KPropertyKeyBluetoothGetPHYCount, linkCount );
       
   471         if( err || !linkCount )
       
   472             {
       
   473             (void) RProperty::Set(KPropertyUidBluetoothCategory, 
       
   474                                    KPropertyKeyBluetoothSetSimplePairingDebugMode,
       
   475                                    (TInt) aDebugMode );
       
   476             SetPowerStateL( EBTOff, EFalse );
       
   477             }
       
   478         else
       
   479             {
       
   480             // There are still existing connections, queue the
       
   481             // timer again for half the period.
       
   482             TInt64 interval = KBTEngSspDebugModeTimeout / 2;
       
   483             iServer->QueueTimer( CBTEngServer::ESspDebugModeTimer, interval );
       
   484             }
       
   485         }
       
   486     TRACE_FUNC_EXIT
       
   487     }
       
   488 
       
   489 // ---------------------------------------------------------------------------
       
   490 // A session will be ended, completes the pending request for this session.
       
   491 // ---------------------------------------------------------------------------
       
   492 //
       
   493 void CBTEngSrvSettingsMgr::SessionClosed( CSession2* aSession )
       
   494     {
       
   495     TRACE_FUNC_ARG( ( _L( " session %x"), aSession ) )
       
   496     if ( !iMessage.IsNull() && iMessage.Session() == aSession )
       
   497         {
       
   498         iMessage.Complete( KErrCancel );
       
   499         }
       
   500     TRACE_FUNC_EXIT
       
   501     }
       
   502 
       
   503 // ---------------------------------------------------------------------------
       
   504 // Check the power state and if BT gets turned off automatically.
       
   505 // This method is invoked either when the timer has expired, or
       
   506 // if there are no more connections while the timer was running.
       
   507 // ---------------------------------------------------------------------------
       
   508 //
       
   509 void CBTEngSrvSettingsMgr::CheckAutoPowerOffL()
       
   510     {
       
   511     TRACE_FUNC_ENTRY
       
   512     if ( iAutoOffClients > 0 )
       
   513         {
       
   514         TRACE_INFO( ( _L( "[CBTEngServer]\t iAutoOffClients %d"), iAutoOffClients ) )
       
   515         return;
       
   516         }
       
   517     TInt linkCount = 0;
       
   518     TInt err = RProperty::Get( KPropertyUidBluetoothCategory, 
       
   519                                 KPropertyKeyBluetoothGetPHYCount, linkCount );
       
   520     if( !err && !linkCount )
       
   521         {
       
   522         TRACE_INFO( ( _L( "[CBTEngServer]\t SetPowerStateL( EBTOff, EFalse );")))
       
   523         SetPowerStateL( EBTOff, EFalse );
       
   524         }
       
   525     else
       
   526         {
       
   527         if( iRestoreVisibility )
       
   528             {
       
   529                 // Set visibility mode back to the value selected by the user.
       
   530             SetVisibilityModeL( EBTVisibilityModeGeneral, 0 );
       
   531             iRestoreVisibility = EFalse;
       
   532             }
       
   533             // show note if non-audio connection exists
       
   534         if ( !iServer->PluginManager()->CheckAudioConnectionsL() )
       
   535             {
       
   536             RNotifier notifier;
       
   537             TInt err = notifier.Connect();
       
   538             if( !err )
       
   539                 {
       
   540                 TRequestStatus status;
       
   541                 TBTGenericInfoNotiferParamsPckg pckg;
       
   542                 pckg().iMessageType = EBTStayPowerOn;
       
   543                 TBuf8<sizeof(TInt)> result;
       
   544                 //notifier.StartNotifier( KBTGenericInfoNotifierUid, pckg, result );
       
   545                 notifier.StartNotifierAndGetResponse( status, 
       
   546                                                   KBTGenericInfoNotifierUid, 
       
   547                                                   pckg, result );   // Reply buffer not used.
       
   548                 User::WaitForRequest( status );
       
   549                 notifier.Close();
       
   550                 }
       
   551             }
       
   552         iAutoOffClients = 0;
       
   553         iAutoSwitchOff = EFalse;
       
   554         TCallBack cb;
       
   555         iServer->BasebandConnectionManager()->SetAutoSwitchOff( EFalse, cb );
       
   556         }
       
   557     TRACE_FUNC_EXIT 
       
   558     }
       
   559 
       
   560 
       
   561 // ---------------------------------------------------------------------------
       
   562 // The method is called when BT stack scanning mode P&S key is changed
       
   563 // ---------------------------------------------------------------------------
       
   564 //
       
   565 void CBTEngSrvSettingsMgr::UpdateVisibilityModeL( TInt aStackScanMode )
       
   566     {
       
   567     TRACE_FUNC_ARG( ( _L( "[aStackScanMode: %d" ), aStackScanMode ) )
       
   568     TBTVisibilityMode currentMode;
       
   569 
       
   570     CRepository* cenRep = CRepository::NewLC( KCRUidBTEngPrivateSettings );
       
   571     User::LeaveIfError( cenRep->Get( KBTDiscoverable, (TInt&) currentMode ) );
       
   572 
       
   573         // In case we are in temp visibility mode, we cannot always know whether the BT stack
       
   574         // scan mode key was set by some external party or by us in SetVisibilityModeL above.
       
   575         // Therefore we cannot stop the timer in case aMode is EBTVisibilityModeGeneral and 
       
   576         // currentmode is EBTVisibilityModeTemporary
       
   577     if( !( currentMode == EBTVisibilityModeTemporary && aStackScanMode == EBTVisibilityModeGeneral ) )
       
   578         {
       
   579             // Cancel the timer and queue it again if needed.
       
   580         iServer->RemoveTimer( CBTEngServer::EScanModeTimer );
       
   581         if( currentMode != aStackScanMode )
       
   582             {
       
   583             if( aStackScanMode == EPageScanOnly || aStackScanMode == EInquiryAndPageScan )
       
   584                 {
       
   585                 User::LeaveIfError( cenRep->Set( KBTDiscoverable, aStackScanMode ) );
       
   586                 }
       
   587             else if( aStackScanMode == EInquiryScanOnly )
       
   588                 {
       
   589                     // We don't support ENoScansEnabled nor EInquiryScanOnly mode
       
   590                     // -> Consider these as same as Hidden 
       
   591                 User::LeaveIfError( cenRep->Set( KBTDiscoverable, EBTVisibilityModeHidden ) );
       
   592                 }
       
   593             else if( aStackScanMode == ENoScansEnabled )
       
   594                 {
       
   595                 //We don't change KBTDiscoverable here, because ENoScansEnabled
       
   596                 //indicates BT/SYSTEM shutdown is happening
       
   597                 }
       
   598             }
       
   599         }
       
   600     SetUiIndicatorsL();
       
   601     CleanupStack::PopAndDestroy( cenRep );
       
   602     TRACE_FUNC_EXIT
       
   603     }
       
   604 
       
   605 
       
   606 // ---------------------------------------------------------------------------
       
   607 // Set Device Under Test mode.
       
   608 // ---------------------------------------------------------------------------
       
   609 //
       
   610 void CBTEngSrvSettingsMgr::SetDutMode( TInt aDutMode )
       
   611     {
       
   612     TRACE_FUNC_ARG( ( _L( "DUT mode %d" ), aDutMode ) )
       
   613 
       
   614     if (aDutMode == EBTDutOff)
       
   615         {
       
   616         return;
       
   617         }
       
   618 
       
   619     TInt powerState = EBTOff;
       
   620     CRepository* cenrep = NULL;
       
   621     
       
   622     TRAPD(err, cenrep = CRepository::NewL(KCRUidBluetoothPowerState));
       
   623     
       
   624     if (!err && cenrep)
       
   625         {
       
   626         cenrep->Get(KBTPowerState, powerState);
       
   627         delete cenrep;
       
   628         cenrep = NULL;
       
   629         }
       
   630     else
       
   631         {
       
   632         return;
       
   633         }
       
   634 
       
   635     if (powerState == EBTOn)
       
   636         {
       
   637 
       
   638 #ifndef __WINS__
       
   639         RBluetoothDutMode dutMode;
       
   640         TInt err = dutMode.Open();
       
   641         TRACE_FUNC_ARG( ( _L( "Open DUT mode handle err %d" ), err) )
       
   642         if(!err) 
       
   643             {
       
   644             dutMode.ActivateDutMode();
       
   645             dutMode.Close();
       
   646             }
       
   647 #endif  //__WINS__                        
       
   648         }
       
   649     }
       
   650 
       
   651 
       
   652 // ---------------------------------------------------------------------------
       
   653 // From class MBTEngActiveObserver.
       
   654 // Callback to notify that an outstanding request has completed.
       
   655 // ---------------------------------------------------------------------------
       
   656 //
       
   657 void CBTEngSrvSettingsMgr::RequestCompletedL( CBTEngActive* aActive, TInt aId, TInt aStatus )
       
   658     {
       
   659     __ASSERT_ALWAYS( aId == KBTEngSettingsActive, PanicServer( EBTEngPanicCorrupt ) );
       
   660     TRACE_FUNC_ENTRY
       
   661     (void) aActive;
       
   662     if ( aStatus != KErrNone && aStatus != KErrAlreadyExists && aStatus != KErrCancel )
       
   663         {
       
   664         // Something went wrong, so we turn BT off again.
       
   665         SetPowerStateL( EBTOff, EFalse );
       
   666         }
       
   667     else
       
   668         {
       
   669         // Write CoD only when the hardware has fully powered up.
       
   670         TBTPowerState currState ( EBTOff );
       
   671         (void) GetHwPowerState( currState );
       
   672         if ( currState == EBTOn )
       
   673             {
       
   674             SetClassOfDeviceL();
       
   675 #ifndef SETLOCALNAME 
       
   676             // the macro SETLOCALNAME is used as a workaround to tackle the BT name 
       
   677             // could not be saved to BT chip before chip initialization completed for the first time,
       
   678             // which is one of the regression after improving the BT boot up time. 
       
   679             // To be removed once the final solution is in place. 
       
   680             CBTEngSettings* settings = CBTEngSettings::NewL();
       
   681             TBTDeviceName localName;           
       
   682             localName.Zero();
       
   683             TInt err = settings->GetLocalName(localName);
       
   684             if (err == KErrNone)
       
   685                 {
       
   686                 settings->SetLocalName(localName);
       
   687                 }
       
   688             delete settings;
       
   689 #endif
       
   690             }
       
   691         }
       
   692     if ( !iMessage.IsNull())
       
   693         {
       
   694         iMessage.Complete( aStatus );
       
   695         }
       
   696     TRACE_FUNC_EXIT
       
   697     }
       
   698 
       
   699 
       
   700 // ---------------------------------------------------------------------------
       
   701 // From class MBTEngActiveObserver.
       
   702 // Callback to notify that an error has occurred in RunL.
       
   703 // ---------------------------------------------------------------------------
       
   704 //
       
   705 void CBTEngSrvSettingsMgr::HandleError( CBTEngActive* aActive, TInt aId, TInt aError )
       
   706     {
       
   707     (void) aActive;
       
   708     (void) aId;
       
   709     if ( !iMessage.IsNull())
       
   710         {
       
   711         iMessage.Complete( aError );
       
   712         }
       
   713     }
       
   714 
       
   715 
       
   716 // ---------------------------------------------------------------------------
       
   717 // Loads the BT Power Manager; leaves if it cannot be loaded.
       
   718 // ---------------------------------------------------------------------------
       
   719 //
       
   720 void CBTEngSrvSettingsMgr::LoadBTPowerManagerL()
       
   721     {
       
   722     TRACE_FUNC_ENTRY
       
   723     TRACE_INFO( ( _L( "[CBTEngSrvSettingsMgr]\t Using HCI API v2 power manager" ) ) )
       
   724     User::LeaveIfError( iPowerMgr.Open() );
       
   725 #ifndef __WINS__
       
   726     iPowerMgr.SetPower( EBTOff, NULL, iActive->RequestStatus() );
       
   727     User::WaitForRequest( iActive->RequestStatus() );
       
   728     TInt status = ( iActive->RequestStatus().Int() == KErrAlreadyExists ? KErrNone : iActive->RequestStatus().Int() ); 
       
   729     User::LeaveIfError( status );
       
   730 #else   //__WINS__
       
   731     iPowerState = EBTOff;
       
   732 #endif  //__WINS__
       
   733     TRACE_FUNC_EXIT
       
   734     }
       
   735 
       
   736 
       
   737 // ---------------------------------------------------------------------------
       
   738 // ?implementation_description
       
   739 // ---------------------------------------------------------------------------
       
   740 //
       
   741 void CBTEngSrvSettingsMgr::SetUiIndicatorsL()
       
   742     {
       
   743     TRACE_FUNC_ENTRY
       
   744     TBTPowerStateValue powerState = EBTPowerOff;
       
   745     TBTVisibilityMode visibilityMode = EBTVisibilityModeHidden;
       
   746     CRepository* cenrep = NULL;
       
   747     TInt phys = 0;
       
   748     TInt connecting = 0;
       
   749 
       
   750     cenrep = CRepository::NewLC( KCRUidBluetoothPowerState );
       
   751     User::LeaveIfError( cenrep->Get( KBTPowerState, (TInt&) powerState ) );
       
   752     CleanupStack::PopAndDestroy( cenrep );
       
   753     
       
   754     if( powerState == EBTPowerOff )
       
   755         {
       
   756         SetIndicatorStateL( EAknIndicatorBluetoothModuleOn, EAknIndicatorStateOff );
       
   757         SetIndicatorStateL( EAknIndicatorBluetooth, EAknIndicatorStateOff );
       
   758         SetIndicatorStateL( EAknIndicatorBluetoothModuleOnVisible, EAknIndicatorStateOff );
       
   759         SetIndicatorStateL( EAknIndicatorBluetoothVisible, EAknIndicatorStateOff );
       
   760         }
       
   761     else
       
   762         {
       
   763         // Power is on.
       
   764         RProperty::Get( KPropertyUidBluetoothCategory, KPropertyKeyBluetoothPHYCount, phys );
       
   765         RProperty::Get( KPropertyUidBluetoothCategory, KPropertyKeyBluetoothConnecting, connecting );
       
   766         
       
   767         cenrep = CRepository::NewLC( KCRUidBTEngPrivateSettings );
       
   768         User::LeaveIfError( cenrep->Get( KBTDiscoverable, (TInt&) visibilityMode ) );
       
   769         CleanupStack::PopAndDestroy( cenrep );
       
   770         
       
   771         if( visibilityMode == EBTVisibilityModeHidden )
       
   772             {
       
   773              if ( connecting ) // BT connecting and hidden
       
   774                 {
       
   775                 SetIndicatorStateL( EAknIndicatorBluetoothModuleOn, EAknIndicatorStateOff );
       
   776                 SetIndicatorStateL( EAknIndicatorBluetooth, EAknIndicatorStateAnimate );
       
   777                 }
       
   778             else if ( phys > 0 ) // BT connection active and hidden     
       
   779                 {
       
   780                 SetIndicatorStateL( EAknIndicatorBluetoothModuleOn, EAknIndicatorStateOff );
       
   781                 SetIndicatorStateL( EAknIndicatorBluetooth, EAknIndicatorStateOn );
       
   782                 }
       
   783             else  // BT connection not active and hidden
       
   784                 {
       
   785                 SetIndicatorStateL( EAknIndicatorBluetoothModuleOn, EAknIndicatorStateOn );
       
   786                 SetIndicatorStateL( EAknIndicatorBluetooth, EAknIndicatorStateOff );
       
   787                 }
       
   788             SetIndicatorStateL( EAknIndicatorBluetoothModuleOnVisible, EAknIndicatorStateOff );
       
   789             SetIndicatorStateL( EAknIndicatorBluetoothVisible, EAknIndicatorStateOff );
       
   790             }           
       
   791         else if( visibilityMode == EBTVisibilityModeGeneral || visibilityMode == EBTVisibilityModeTemporary )
       
   792             {     
       
   793             if ( connecting ) // BT connecting and visible
       
   794                 {
       
   795                 SetIndicatorStateL( EAknIndicatorBluetoothModuleOnVisible, EAknIndicatorStateOff );
       
   796                 SetIndicatorStateL( EAknIndicatorBluetoothVisible, EAknIndicatorStateAnimate );
       
   797                 }
       
   798             else if ( phys > 0 ) // BT connection active and visible 
       
   799                 {
       
   800                 SetIndicatorStateL( EAknIndicatorBluetoothModuleOnVisible, EAknIndicatorStateOff );
       
   801                 SetIndicatorStateL( EAknIndicatorBluetoothVisible, EAknIndicatorStateOn );
       
   802                 }
       
   803             else  // BT connection not active and visible
       
   804                 {
       
   805                 SetIndicatorStateL( EAknIndicatorBluetoothModuleOnVisible, EAknIndicatorStateOn );
       
   806                 SetIndicatorStateL( EAknIndicatorBluetoothVisible, EAknIndicatorStateOff );
       
   807                 }
       
   808             SetIndicatorStateL( EAknIndicatorBluetoothModuleOn, EAknIndicatorStateOff );
       
   809             SetIndicatorStateL( EAknIndicatorBluetooth, EAknIndicatorStateOff );
       
   810             }
       
   811         }
       
   812     TRACE_FUNC_EXIT
       
   813     }
       
   814 
       
   815 
       
   816 // ---------------------------------------------------------------------------
       
   817 // ?implementation_description
       
   818 // ---------------------------------------------------------------------------
       
   819 //
       
   820 void CBTEngSrvSettingsMgr::SetIndicatorStateL( const TInt aIndicator, const TInt aState )
       
   821     {
       
   822     CAknSmallIndicator* indicator = CAknSmallIndicator::NewLC( TUid::Uid( aIndicator ) );
       
   823     indicator->SetIndicatorStateL( aState );
       
   824     CleanupStack::PopAndDestroy( indicator ); //indicator
       
   825     }
       
   826 
       
   827 
       
   828 // ---------------------------------------------------------------------------
       
   829 // Gets the current HW power state.
       
   830 // For now this is a separate method to isolate the different variations.
       
   831 // ---------------------------------------------------------------------------
       
   832 //
       
   833 TInt CBTEngSrvSettingsMgr::GetHwPowerState( TBTPowerState& aState )
       
   834     {
       
   835     TRACE_FUNC_ENTRY
       
   836     TInt err = KErrNone;
       
   837     
       
   838 #ifndef __WINS__
       
   839     err = iPowerMgr.GetPower( aState, NULL );
       
   840 #else   //__WINS__
       
   841     aState = iPowerState;
       
   842 #endif  //__WINS__
       
   843     TRACE_FUNC_ARG( ( _L( "Power state is %d, result %d" ), (TInt) aState, err ) )
       
   844     return err;
       
   845     }
       
   846 
       
   847 // ---------------------------------------------------------------------------
       
   848 // Check the power state and if BT gets turned off automatically.
       
   849 // ---------------------------------------------------------------------------
       
   850 //
       
   851 void CBTEngSrvSettingsMgr::CheckTemporaryPowerStateL( TBTPowerState& aCurrentState, 
       
   852     TBTPowerState aNewState, TBool aTemporary )
       
   853     {
       
   854     TRACE_FUNC_ENTRY
       
   855     User::LeaveIfError( GetHwPowerState( aCurrentState ) );
       
   856     if( !aTemporary )
       
   857         {
       
   858             // Force the new power state, so clear all auto switch off flags.
       
   859             // If power is off, this will anyway be ignored.
       
   860         iAutoOffClients = 0;
       
   861         iAutoSwitchOff = EFalse;
       
   862         TCallBack cb;
       
   863         iServer->BasebandConnectionManager()->SetAutoSwitchOff( EFalse, cb );
       
   864         if( iRestoreVisibility && aCurrentState == EBTOn )
       
   865             {
       
   866                 // Set visibility mode back to the value selected by the user.
       
   867             SetVisibilityModeL( EBTVisibilityModeGeneral, 0 );
       
   868             iRestoreVisibility = EFalse;
       
   869             }
       
   870         }
       
   871     else
       
   872         {
       
   873         if( aCurrentState == aNewState )
       
   874             {
       
   875             if( iAutoSwitchOff && aNewState == EBTOn )
       
   876                 {
       
   877                 iAutoOffClients++;
       
   878                 iServer->RemoveTimer( CBTEngServer::EAutoPowerOffTimer );
       
   879                 }
       
   880             }
       
   881         else if( iAutoSwitchOff || aNewState == EBTOn )
       
   882             {
       
   883             aNewState == EBTOff ? iAutoOffClients-- : iAutoOffClients++;
       
   884             iAutoSwitchOff = ETrue;
       
   885             if( aNewState == EBTOff && iAutoOffClients <= 0 )
       
   886                 {
       
   887                 TCallBack powerOffCb( CBTEngServer::AutoPowerOffCallBack, iServer );
       
   888                 iServer->BasebandConnectionManager()->SetAutoSwitchOff( ETrue, powerOffCb );
       
   889                 TInt64 interval = KBTEngBtAutoOffTimeout;
       
   890                 iServer->QueueTimer( CBTEngServer::EAutoPowerOffTimer, interval );
       
   891                 }
       
   892             else if( aNewState == EBTOn )
       
   893                 {
       
   894                 CRepository* cenRep = CRepository::NewLC( KCRUidBTEngPrivateSettings );
       
   895                 TBTVisibilityMode visibility = EBTVisibilityModeGeneral;
       
   896                 TInt err = cenRep->Get( KBTDiscoverable, (TInt&) visibility );
       
   897                 CleanupStack::PopAndDestroy( cenRep );
       
   898                 if( !err && visibility == EBTVisibilityModeGeneral )
       
   899                     {
       
   900                     SetVisibilityModeL( EBTVisibilityModeHidden, 0 );
       
   901                     iRestoreVisibility = ETrue;
       
   902                    }
       
   903                 iServer->RemoveTimer( CBTEngServer::EAutoPowerOffTimer );
       
   904                 }
       
   905             }
       
   906         }
       
   907     if( iAutoOffClients < 0 )
       
   908         {
       
   909         iAutoOffClients = 0;
       
   910         }
       
   911     TRACE_FUNC_EXIT 
       
   912     }
       
   913 
       
   914 
       
   915 // ---------------------------------------------------------------------------
       
   916 // Set the Class of Device.
       
   917 // ---------------------------------------------------------------------------
       
   918 //
       
   919 void CBTEngSrvSettingsMgr::SetClassOfDeviceL()
       
   920     {
       
   921     TRACE_FUNC_ENTRY
       
   922     TUint16 serviceClass = KCoDDefaultServiceClass;
       
   923         // Check from feature manager if stereo audio is enabled.
       
   924     FeatureManager::InitializeLibL();
       
   925     TBool supported = FeatureManager::FeatureSupported( KFeatureIdBtStereoAudio );
       
   926     FeatureManager::UnInitializeLib();
       
   927     if( supported )
       
   928         {
       
   929         // A2DP spec says we should set this bit as we are a SRC
       
   930         serviceClass |= EMajorServiceCapturing;
       
   931         }
       
   932         // These values may nayway be overridden by HCI
       
   933     TBTDeviceClass cod( serviceClass, KCoDDefaultMajorDeviceClass, 
       
   934                          KCoDDefaultMinorDeviceClass );
       
   935         // Ignore error, it is non-critical
       
   936     (void) RProperty::Set( KPropertyUidBluetoothControlCategory, 
       
   937                             KPropertyKeyBluetoothSetDeviceClass, cod.DeviceClass() );
       
   938     TRACE_FUNC_EXIT
       
   939     }