bluetoothengine/bteng/btengdevman/src/btengdevman.cpp
changeset 0 f63038272f30
equal deleted inserted replaced
-1:000000000000 0:f63038272f30
       
     1 /*
       
     2 * Copyright (c) 2006, 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:  Implementation of the Bluetooth Engine Device Management API
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include <featmgr.h>
       
    21 
       
    22 #include "btengdevman.h"
       
    23 #include "btengconstants.h"
       
    24 #include "debug.h"
       
    25 #include "btengdevmanpanic.h"
       
    26 
       
    27 void Panic(TBtEngDevManPanicCode aPanic)
       
    28     {
       
    29     User::Panic(KBtEngDevManPanic, aPanic);
       
    30     }
       
    31 
       
    32 
       
    33 // ======== MEMBER FUNCTIONS ========
       
    34 
       
    35 // ---------------------------------------------------------------------------
       
    36 // C++ default constructor
       
    37 // ---------------------------------------------------------------------------
       
    38 //
       
    39 CBTEngDevMan::CBTEngDevMan( MBTEngDevManObserver* aObserver )
       
    40 :   CActive( EPriorityStandard ),
       
    41     iState( EStateIdle ),
       
    42     iCreatingView( EFalse ),
       
    43     iObserver( aObserver )
       
    44     {
       
    45     CActiveScheduler::Add( this );
       
    46     }
       
    47 
       
    48 
       
    49 // ---------------------------------------------------------------------------
       
    50 // Symbian 2nd-phase constructor
       
    51 // ---------------------------------------------------------------------------
       
    52 //
       
    53 void CBTEngDevMan::ConstructL()
       
    54     {
       
    55     TRACE_FUNC_ENTRY
       
    56         // Check if BT is supported at all
       
    57     FeatureManager::InitializeLibL();
       
    58     TBool btSupported = FeatureManager::FeatureSupported( KFeatureIdBt );
       
    59     FeatureManager::UnInitializeLib();
       
    60     if( !btSupported )
       
    61         {
       
    62         TRACE_INFO( ( _L( "[BTENGDEVMAN]\t ConstructL: BT not supported" ) ) )
       
    63         User::Leave( KErrNotSupported );
       
    64         }
       
    65 
       
    66     User::LeaveIfError( iRegServ.Connect() );
       
    67     User::LeaveIfError( iRegistry.Open( iRegServ ) );
       
    68 
       
    69     TRACE_FUNC_EXIT
       
    70     }
       
    71 
       
    72 
       
    73 // ---------------------------------------------------------------------------
       
    74 // NewL
       
    75 // ---------------------------------------------------------------------------
       
    76 //
       
    77 EXPORT_C CBTEngDevMan* CBTEngDevMan::NewL( MBTEngDevManObserver* aObserver )
       
    78     {
       
    79     CBTEngDevMan* self = CBTEngDevMan::NewLC( aObserver );
       
    80     CleanupStack::Pop( self );
       
    81     return self;
       
    82     }
       
    83 
       
    84 
       
    85 // ---------------------------------------------------------------------------
       
    86 // NewLC
       
    87 // ---------------------------------------------------------------------------
       
    88 //
       
    89 EXPORT_C CBTEngDevMan* CBTEngDevMan::NewLC( MBTEngDevManObserver* aObserver )
       
    90     {
       
    91     CBTEngDevMan* self = new( ELeave ) CBTEngDevMan( aObserver );
       
    92     CleanupStack::PushL( self );
       
    93     self->ConstructL();
       
    94     return self;
       
    95     }
       
    96 
       
    97 
       
    98 // ---------------------------------------------------------------------------
       
    99 // Destructor
       
   100 // ---------------------------------------------------------------------------
       
   101 //
       
   102 CBTEngDevMan::~CBTEngDevMan()
       
   103     {
       
   104     TRACE_FUNC_ENTRY
       
   105     Cancel();
       
   106     iRegistry.Close();
       
   107     iRegServ.Close();
       
   108     delete iResponse;
       
   109     delete iModifiedDevice;
       
   110     }
       
   111 
       
   112 
       
   113 // ---------------------------------------------------------------------------
       
   114 // Add a device into the Bluetooth device registry.
       
   115 // ---------------------------------------------------------------------------
       
   116 //
       
   117 EXPORT_C TInt CBTEngDevMan::AddDevice( const CBTDevice& aDevice )
       
   118     {
       
   119     TRACE_FUNC_ENTRY
       
   120     __ASSERT_ALWAYS( iObserver, Panic(EBtEngDevManPanicNullObserver) );
       
   121     TInt err = KErrNone;
       
   122     if( iState != EStateIdle )
       
   123         {
       
   124         err = KErrInUse;
       
   125         }
       
   126     else
       
   127         {
       
   128         TRAP( err, iRegistry.AddDeviceL( aDevice, iStatus ) );
       
   129         if( err == KErrNone )
       
   130             {
       
   131             iState = EStateAddDevice;
       
   132             SetActive();
       
   133             }
       
   134         }
       
   135     TRACE_FUNC_EXIT
       
   136     return err;
       
   137     }
       
   138 
       
   139 
       
   140 // ---------------------------------------------------------------------------
       
   141 // Get an array of devices which matches the search criteria.
       
   142 // ---------------------------------------------------------------------------
       
   143 //
       
   144 EXPORT_C TInt CBTEngDevMan::GetDevices( const TBTRegistrySearch& aCriteria, 
       
   145     CBTDeviceArray* aResultArray )
       
   146     {
       
   147     TRACE_FUNC_ENTRY
       
   148     __ASSERT_ALWAYS( aResultArray, Panic(EBtEngDevManPanicNullResultArray) );
       
   149     TInt err = KErrNone;
       
   150     if( iState != EStateIdle )
       
   151         {
       
   152         err = KErrInUse;
       
   153         }
       
   154     else
       
   155         {
       
   156         ASSERT( !iResultArray && !iAsyncWaiter );
       
   157         iResultArray = aResultArray;
       
   158         iRegistry.CreateView( aCriteria, iStatus );
       
   159         iState = EStateGetDevices;
       
   160         iCreatingView = ETrue;
       
   161         SetActive();
       
   162         if( !iObserver )
       
   163             {
       
   164                 // Synchronous version of GetDevices, will not use callback.
       
   165             iAsyncWaiter = new CActiveSchedulerWait();
       
   166             if( !iAsyncWaiter )
       
   167                 {
       
   168                 Cancel();
       
   169                 return KErrNoMemory;
       
   170                 }
       
   171             iAsyncWaiter->Start();
       
   172             err = iStatus.Int();
       
   173             iResultArray = NULL;
       
   174             delete iAsyncWaiter;
       
   175             iAsyncWaiter = NULL;
       
   176             }
       
   177         }
       
   178     TRACE_FUNC_RES( ( _L( "result: %d" ), err ) )
       
   179     return err;
       
   180     }
       
   181 
       
   182 
       
   183 // ---------------------------------------------------------------------------
       
   184 // Delete the devices which matches the search criteria.
       
   185 // ---------------------------------------------------------------------------
       
   186 //
       
   187 EXPORT_C TInt CBTEngDevMan::DeleteDevices( const TBTRegistrySearch& aCriteria )
       
   188     {
       
   189     TRACE_FUNC_ENTRY
       
   190     __ASSERT_ALWAYS( iObserver, Panic(EBtEngDevManPanicNullObserver) );
       
   191     TInt err = KErrNone;
       
   192     if( iState != EStateIdle )
       
   193         {
       
   194         err = KErrInUse;
       
   195         }
       
   196     else
       
   197         {
       
   198         iRegistry.CreateView( aCriteria, iStatus );
       
   199         iState = EStateDeleteDevices;
       
   200         iCreatingView = ETrue;
       
   201         SetActive();
       
   202         }
       
   203     TRACE_FUNC_RES( ( _L( "result: %d" ), err ) )
       
   204     return err;
       
   205     }
       
   206 
       
   207 
       
   208 // ---------------------------------------------------------------------------
       
   209 // Modify a device in the Bluetooth device registry.
       
   210 // ---------------------------------------------------------------------------
       
   211 //
       
   212 EXPORT_C TInt CBTEngDevMan::ModifyDevice( const CBTDevice& aDevice )
       
   213     {
       
   214     TRACE_FUNC_ENTRY
       
   215     __ASSERT_ALWAYS( iObserver, Panic(EBtEngDevManPanicNullObserver) );
       
   216     TInt err = KErrNone;
       
   217     if( iState != EStateIdle )
       
   218         {
       
   219         err = KErrInUse;
       
   220         }
       
   221     else
       
   222         {
       
   223         ASSERT( !iModifiedDevice );
       
   224         TRAP( err, iModifiedDevice = aDevice.CopyL() );
       
   225         }
       
   226     if( !err )
       
   227         {
       
   228         TBTRegistrySearch searchPattern;
       
   229         searchPattern.FindAddress( iModifiedDevice->BDAddr() );
       
   230         iRegistry.CreateView( searchPattern, iStatus );
       
   231         iState = EStateModifyDevice;
       
   232         iModifyState = ECheckPairing;
       
   233         iCreatingView = ETrue;
       
   234         SetActive();
       
   235         }
       
   236     TRACE_FUNC_RES( ( _L( "result: %d" ), err ) )
       
   237     return err;
       
   238     }
       
   239 
       
   240 
       
   241 // ---------------------------------------------------------------------------
       
   242 // From class CActive.
       
   243 // Handle request completion, eventually making the callback.
       
   244 // ---------------------------------------------------------------------------
       
   245 //
       
   246 void CBTEngDevMan::RunL()
       
   247     {
       
   248     TRACE_FUNC_ARG( ( _L( "status: %d" ), iStatus.Int() ) )
       
   249     TInt count = User::LeaveIfError(iStatus.Int());
       
   250     if( iCreatingView )
       
   251         {
       
   252             // First stage completed, got a view on the registry.
       
   253         iCreatingView = EFalse;
       
   254             // When creating a view, iStatus represents 
       
   255             // the number of matching results.
       
   256         if( count )
       
   257             {
       
   258             ASSERT(iState >= EStateIdle && iState <= EStateDeleteDevices);
       
   259             if( iState == EStateDeleteDevices )
       
   260                 {
       
   261                 iRegistry.DeleteAllInView( iStatus );
       
   262                 SetActive();
       
   263                 }
       
   264             else
       
   265                 {
       
   266                 iResponse = CBTRegistryResponse::NewL( iRegistry );
       
   267                 iResponse->Start( iStatus );
       
   268                 SetActive();
       
   269                 }
       
   270             }
       
   271         else
       
   272             {
       
   273             if( iState == EStateGetDevices )
       
   274                 {
       
   275                 iState = EStateIdle;
       
   276                 if( iObserver )
       
   277                     {
       
   278                     CBTDeviceArray* clientArray = iResultArray;
       
   279                     iResultArray = NULL;
       
   280                     iObserver->HandleGetDevicesComplete( KErrNone, clientArray );
       
   281                     }
       
   282                 else
       
   283                     {
       
   284                     __ASSERT_ALWAYS(iAsyncWaiter,Panic(EBtEngDevManPanicNullWaiter));
       
   285                     iAsyncWaiter->AsyncStop(); // Synchronous version
       
   286                     }
       
   287                 }
       
   288             else
       
   289                 {
       
   290                 iState = EStateIdle;
       
   291                 iObserver->HandleDevManComplete( KErrNone );
       
   292                 }
       
   293             }
       
   294         }
       
   295     else
       
   296         {
       
   297             // Second stage completed.
       
   298         switch( iState )
       
   299             {
       
   300             case EStateGetDevices:
       
   301                 {
       
   302                 (void) iRegistry.CloseView();
       
   303                 RBTDeviceArray& resultArray = iResponse->Results();
       
   304                 while (resultArray.Count())
       
   305                     {
       
   306                     CBTDevice* dev = resultArray[ 0 ];
       
   307                     resultArray.Remove( 0 );
       
   308                     iResultArray->AppendL( dev );
       
   309                     }
       
   310                 delete iResponse;
       
   311                 iResponse = NULL;
       
   312                 iState = EStateIdle;
       
   313                 if( iObserver )
       
   314                     {
       
   315                     CBTDeviceArray* clientArray = iResultArray;
       
   316                     iResultArray = NULL;
       
   317                     iObserver->HandleGetDevicesComplete( count, clientArray );
       
   318                     }
       
   319                 else
       
   320                     {
       
   321                     __ASSERT_ALWAYS(iAsyncWaiter,Panic(EBtEngDevManPanicNullWaiter));
       
   322                     iAsyncWaiter->AsyncStop(); // Synchronous version
       
   323                     }
       
   324                 }
       
   325                 break;
       
   326             case EStateModifyDevice:
       
   327                 {
       
   328                 DoModifyDeviceL();
       
   329                 if( iModifyState != ECheckNone )
       
   330                     {
       
   331                     break;
       
   332                     }
       
   333                 delete iModifiedDevice;
       
   334                 iModifiedDevice = NULL;
       
   335                 delete iResponse;
       
   336                 iResponse = NULL;
       
   337                 }   // Fall through
       
   338             case EStateDeleteDevices:
       
   339                 {
       
   340                 (void) iRegistry.CloseView();
       
   341                 }   // Fall through
       
   342             case EStateAddDevice:
       
   343                 {
       
   344                 iState = EStateIdle;
       
   345                 iObserver->HandleDevManComplete( count );
       
   346                 }
       
   347                 break;
       
   348             case EStateIdle:
       
   349             default:
       
   350                 {
       
   351                 ASSERT(EFalse);
       
   352                 TRACE_INFO( ( _L( "[BTEngDevMan]\t RunL - bad state! %d" ), iState ) )
       
   353                 }
       
   354                 break;
       
   355             }
       
   356         }
       
   357     }
       
   358 
       
   359 
       
   360 // ---------------------------------------------------------------------------
       
   361 // From class CActive.
       
   362 // Called if something leaves in RunL.
       
   363 // ---------------------------------------------------------------------------
       
   364 //
       
   365 TInt CBTEngDevMan::RunError( TInt aError )
       
   366     {
       
   367     TRACE_FUNC_ARG( ( _L( "state: %d (modifystate: %d); error: %d" ), 
       
   368                       iState, iModifyState, aError ) )
       
   369         // Reset all state information
       
   370     iModifyState = ECheckNone;
       
   371     iCreatingView = EFalse;
       
   372         // Clean up all used resources
       
   373     (void) iRegistry.CloseView();   // An error is returned if there is no 
       
   374                                     // open view -> can be safely ignored.
       
   375     delete iResponse;
       
   376     iResponse = NULL;
       
   377         // Inform the client
       
   378     if( iState == EStateGetDevices )
       
   379         {
       
   380         iState = EStateIdle;
       
   381         if( iObserver )
       
   382             {
       
   383             CBTDeviceArray* clientArray = iResultArray;
       
   384             iResultArray = NULL;
       
   385             iObserver->HandleGetDevicesComplete( aError, clientArray );
       
   386             }
       
   387         else
       
   388             {
       
   389             __ASSERT_ALWAYS(iAsyncWaiter,Panic(EBtEngDevManPanicNullWaiter));
       
   390             iAsyncWaiter->AsyncStop(); // Synchronous version
       
   391             }
       
   392         }
       
   393     else
       
   394         {
       
   395         iState = EStateIdle;
       
   396         iObserver->HandleDevManComplete( aError );
       
   397         }
       
   398     return KErrNone;
       
   399     }
       
   400 
       
   401 
       
   402 // ---------------------------------------------------------------------------
       
   403 // From class CActive.
       
   404 // Cancel current outstanding operation, if any.
       
   405 // ---------------------------------------------------------------------------
       
   406 //
       
   407 void CBTEngDevMan::DoCancel()
       
   408     {
       
   409     TRACE_FUNC_ENTRY
       
   410     iRegistry.CancelRequest( iStatus );
       
   411     (void) iRegistry.CloseView();
       
   412     iState = EStateIdle;
       
   413     iModifyState = ECheckNone;
       
   414     iCreatingView = EFalse;
       
   415     if( iResponse )
       
   416         {
       
   417         iResponse->Cancel();
       
   418         delete iResponse;
       
   419         iResponse = NULL;
       
   420         }
       
   421     delete iModifiedDevice;
       
   422     iModifiedDevice = NULL;
       
   423     if( iAsyncWaiter )
       
   424         {
       
   425         iAsyncWaiter->AsyncStop();
       
   426         }
       
   427     iResultArray = NULL;
       
   428     TRACE_FUNC_EXIT
       
   429     }
       
   430 
       
   431 
       
   432 // ---------------------------------------------------------------------------
       
   433 // Process result of a registry search, when GetDevice or
       
   434 // ModifyDevice has been called.
       
   435 // ---------------------------------------------------------------------------
       
   436 //
       
   437 void CBTEngDevMan::DoModifyDeviceL()
       
   438     {
       
   439     TRACE_FUNC_ENTRY
       
   440     if( iModifyState == ECheckFinal )
       
   441         {
       
   442             // Modifications have completed.
       
   443         iModifyState = ECheckNone;
       
   444         return;
       
   445         }
       
   446 
       
   447         // We searched for a device address, so assume that 
       
   448         // there is only one match.
       
   449     ASSERT(iResponse->Results().Count() > 0);
       
   450     CBTDevice* regDevice = iResponse->Results()[ 0 ];
       
   451         // Modifications to CBTDevice parameteres could include multiple 
       
   452         // asynchronous operations. Therefore each possibilbe modification 
       
   453         // is checked. The order is always the same so that we can know what
       
   454         // the next step is.
       
   455     if( iModifyState == ECheckPairing )
       
   456         {
       
   457             // IsValidPaired returns if the pairing bit has been set.
       
   458             // IsPaired returns if the device is actually paired.
       
   459         if( ( regDevice->IsValidPaired() && regDevice->IsPaired() ) &&
       
   460             ( !iModifiedDevice->IsValidPaired() || !iModifiedDevice->IsPaired() ) )
       
   461             {
       
   462             TRACE_INFO( _L( "[BTEngDevMan]\t DoModifyDeviceL UnpairDevice ") );
       
   463             // check if client request to ban or unpair a device paired with Just Works
       
   464             if ( regDevice->LinkKeyType() == ELinkKeyUnauthenticatedNonUpgradable &&
       
   465                  regDevice->IsValidUiCookie() &&
       
   466                  ( regDevice->UiCookie() & EBTUiCookieJustWorksPaired ) )
       
   467                 {
       
   468                 // Remove the UI cookie bit for Just Works pairing. Modifying registry
       
   469                 // will be called at nameless device checking.
       
   470                 TInt32 cookie = regDevice->UiCookie() & ~EBTUiCookieJustWorksPaired;
       
   471                 iModifiedDevice->SetUiCookie( cookie );
       
   472                 TRACE_INFO( _L( "[BTEngDevMan]\t DoModifyDeviceL removed JW cookie ") );
       
   473                 }
       
   474             // Unpairing is requested.
       
   475             iRegistry.UnpairDevice( iModifiedDevice->BDAddr(), iStatus );
       
   476             SetActive();
       
   477                 //  The reverse operation (pairing) is not performed through DevMan.
       
   478             }
       
   479         iModifyState = ECheckDevName;
       
   480         }
       
   481     if( !IsActive() && iModifyState == ECheckDevName )
       
   482         {
       
   483             // Check that there is a valid device name, and that it is not 
       
   484             // the same as the registered name, or that the registry does not
       
   485             // contain a valid name yet.
       
   486         if( iModifiedDevice->IsValidDeviceName() && 
       
   487             ( !regDevice->IsValidDeviceName() || 
       
   488             ( iModifiedDevice->DeviceName() != regDevice->DeviceName() ) ) )
       
   489             {
       
   490             TRACE_INFO( _L( "[BTEngDevMan]\t DoModifyDeviceL ModifyBluetoothDeviceName ") );
       
   491             iRegistry.ModifyBluetoothDeviceNameL( iModifiedDevice->BDAddr(), 
       
   492                                                    iModifiedDevice->DeviceName(), 
       
   493                                                    iStatus );
       
   494             SetActive();
       
   495             }
       
   496         iModifyState = ECheckFriendlyName;
       
   497         }
       
   498     if( !IsActive() && iModifyState == ECheckFriendlyName )
       
   499         {
       
   500             // Check that there is a valid friendly name, and that it is not 
       
   501             // the same as the registered name, or that the friendly name 
       
   502             // is removed.
       
   503         if( ( iModifiedDevice->IsValidFriendlyName() && 
       
   504             ( iModifiedDevice->FriendlyName() != regDevice->FriendlyName() ) ) || 
       
   505             ( !iModifiedDevice->IsValidFriendlyName() &&  
       
   506               regDevice->IsValidFriendlyName() ) )
       
   507             {
       
   508             TRACE_INFO( _L( "[BTEngDevMan]\t DoModifyDeviceL ModifyFriendlyDeviceName ") );
       
   509                 // If CBTDevice does not contain a valid friendly name, 
       
   510                 // KNullDesC is returned.
       
   511             iRegistry.ModifyFriendlyDeviceNameL( iModifiedDevice->BDAddr(), 
       
   512                                                   iModifiedDevice->FriendlyName(), 
       
   513                                                   iStatus );
       
   514             SetActive();
       
   515             }
       
   516             iModifyState = ECheckNameless;
       
   517         }
       
   518     if( !IsActive() && iModifyState == ECheckNameless )
       
   519         {
       
   520         iModifyState = ECheckNone;
       
   521         if( iModifiedDevice->AsNamelessDevice() != regDevice->AsNamelessDevice() )
       
   522             {
       
   523             TRACE_INFO( _L( "[BTEngDevMan]\t DoModifyDeviceL Modify NamelessDevice ") );           
       
   524                 // Update all other parameters.
       
   525             iRegistry.ModifyDevice( iModifiedDevice->AsNamelessDevice(), iStatus );
       
   526             SetActive();
       
   527             iModifyState = ECheckFinal; // One more cycle needed to complete.
       
   528             }
       
   529         }
       
   530     TRACE_FUNC_EXIT
       
   531     }
       
   532 
       
   533 
       
   534 // ---------------------------------------------------------------------------
       
   535 // This is the default implementation of the MBTEngDevManObserver methods 
       
   536 // HandleDevManComplete just returns.
       
   537 // ---------------------------------------------------------------------------
       
   538 //
       
   539 EXPORT_C void MBTEngDevManObserver::HandleDevManComplete( TInt /*aErr*/ )
       
   540     {
       
   541     }
       
   542 
       
   543 
       
   544 // ---------------------------------------------------------------------------
       
   545 // This is the default implementation of the MBTEngDevManObserver methods 
       
   546 // HandleGetDevicesComplete just returns.
       
   547 // ---------------------------------------------------------------------------
       
   548 //
       
   549 EXPORT_C void MBTEngDevManObserver::HandleGetDevicesComplete( TInt /*aErr*/, 
       
   550     CBTDeviceArray* /*aDeviceArray*/ )
       
   551     {
       
   552     }