bluetoothengine/bteng/src/btengpairman.cpp
branchRCL_3
changeset 56 9386f31cc85b
equal deleted inserted replaced
55:613943a21004 56:9386f31cc85b
       
     1 /*
       
     2 * Copyright (c) 2009-2010 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:  Pairing result receiver in Bluetooth engine subsystem
       
    15 *
       
    16 */
       
    17 
       
    18 #include "btengpairman.h"
       
    19 #include "btengserver.h"
       
    20 #include "btengsrvsession.h"
       
    21 #include "btengotgpair.h"
       
    22 #include "btengincpair.h"
       
    23 #include "btengclientserver.h"
       
    24 #include "debug.h"
       
    25 #include <e32property.h>
       
    26 
       
    27 /**  Identification for active object */
       
    28 enum TPairManActiveRequestId
       
    29     {
       
    30     ESimplePairingResult,
       
    31     EAuthenticationResult,
       
    32     ERegistryInitiatePairedDevicesView,
       
    33     ERegistryPairedDevicesNewView,
       
    34     ERegistryInitiatePairedDevicesList,
       
    35     ERegistryGetPairedDevices,
       
    36     ERegistryGetLocalAddress,
       
    37     };
       
    38 
       
    39 /**  The message argument which holds the Bluetooth address. */
       
    40 const TInt KBTEngAddrSlot = 0;
       
    41 
       
    42 // ---------------------------------------------------------------------------
       
    43 // Tells if two TBTNamelessDevice instances are for the same remote device
       
    44 // ---------------------------------------------------------------------------
       
    45 //
       
    46 TBool CompareDeviceByAddress( const TBTNamelessDevice& aDevA, const TBTNamelessDevice& aDevB )
       
    47     {
       
    48     return aDevA.Address() == aDevB.Address();
       
    49     }
       
    50 
       
    51 // ======== MEMBER FUNCTIONS ========
       
    52 
       
    53 // ---------------------------------------------------------------------------
       
    54 // C++ default constructor
       
    55 // ---------------------------------------------------------------------------
       
    56 //
       
    57 CBTEngPairMan::CBTEngPairMan( CBTEngServer& aServer )
       
    58     : iServer( aServer )
       
    59     {
       
    60     }
       
    61 
       
    62 // ---------------------------------------------------------------------------
       
    63 // Symbian 2nd-phase constructor
       
    64 // ---------------------------------------------------------------------------
       
    65 //
       
    66 void CBTEngPairMan::ConstructL()
       
    67     {
       
    68     TRACE_FUNC_ENTRY
       
    69         // Connect to pairing server for authentication & simple pairing 
       
    70         // results directly from the BT stack.
       
    71         // Pairing server doesn't exist if we run BT 2.0 stack:
       
    72     iPairingServ = new (ELeave) RBluetoothPairingServer;
       
    73     TInt err = iPairingServ->Connect();
       
    74     if ( err)
       
    75         {
       
    76         delete iPairingServ;
       
    77         iPairingServ = NULL;
       
    78         }
       
    79     else
       
    80         {
       
    81         User::LeaveIfError( iPairingResult.Open( *iPairingServ ) );
       
    82         User::LeaveIfError( iAuthenResult.Open( *iPairingServ ) );
       
    83         iSSPResultActive = CBTEngActive::NewL( *this, ESimplePairingResult, CActive::EPriorityStandard );
       
    84         iAuthenResultActive = CBTEngActive::NewL( *this, EAuthenticationResult, CActive::EPriorityStandard );        
       
    85         }
       
    86 
       
    87     // RProperty for accessing the local device address
       
    88     User::LeaveIfError( iPropertyLocalAddr.Attach(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothGetLocalDeviceAddress) );
       
    89 
       
    90     // connect to registry
       
    91     User::LeaveIfError( iBTRegistry.Open( BTRegServ() ) );    
       
    92     iRegistryActive = CBTEngActive::NewL( *this, ERegistryInitiatePairedDevicesView, CActive::EPriorityStandard );
       
    93     iPairedDevices = new (ELeave) RArray<TBTNamelessDevice>; 
       
    94 
       
    95     // Initialise paired devices list
       
    96     iLocalAddrActive = CBTEngActive::NewL( *this, ERegistryGetLocalAddress, CActive::EPriorityStandard );
       
    97     InitPairedDevicesList();
       
    98  
       
    99     TRACE_FUNC_EXIT
       
   100     }
       
   101 
       
   102 // ---------------------------------------------------------------------------
       
   103 // NewL
       
   104 // ---------------------------------------------------------------------------
       
   105 //
       
   106 CBTEngPairMan* CBTEngPairMan::NewL( CBTEngServer& aServer )
       
   107     {
       
   108     CBTEngPairMan* self = NULL;
       
   109     self = new  CBTEngPairMan( aServer );
       
   110     CleanupStack::PushL( self );
       
   111     self->ConstructL();
       
   112     CleanupStack::Pop( self );
       
   113     return self;
       
   114     }
       
   115 
       
   116 // ---------------------------------------------------------------------------
       
   117 // Destructor
       
   118 // ---------------------------------------------------------------------------
       
   119 //
       
   120 CBTEngPairMan::~CBTEngPairMan()
       
   121     {
       
   122     TRACE_FUNC_ENTRY
       
   123     CancelSubscribe();
       
   124     delete iSSPResultActive;
       
   125     delete iAuthenResultActive;
       
   126     delete iRegistryActive;
       
   127     delete iPairedDevicesResp;
       
   128     delete iPairer;
       
   129     if ( iPairedDevices )
       
   130         {
       
   131         iPairedDevices->Close();
       
   132         delete iPairedDevices;
       
   133         }
       
   134     iBTRegistry.Close();
       
   135     iPairingResult.Close();
       
   136     iAuthenResult.Close();
       
   137     if ( iPairingServ )
       
   138         {
       
   139         iPairingServ->Close();
       
   140         delete iPairingServ;
       
   141         }
       
   142     if ( !iMessage.IsNull() )
       
   143         {
       
   144         iMessage.Complete( KErrCancel );
       
   145         }
       
   146     iPropertyLocalAddr.Cancel();
       
   147     iPropertyLocalAddr.Close();
       
   148     delete iLocalAddrActive;
       
   149     TRACE_FUNC_EXIT
       
   150     }
       
   151 
       
   152 // ---------------------------------------------------------------------------
       
   153 // Initialises the paired devices list.
       
   154 // If the local address is not available from the P&S key 
       
   155 // KPropertyKeyBluetoothGetLocalDeviceAddress, then the list may need to be 
       
   156 // updated once the H/W is switched on. This is so that any registry update 
       
   157 // from a restore operation can be included in the list, without mistaking the 
       
   158 // new devices for new pairings.
       
   159 // ---------------------------------------------------------------------------
       
   160 //
       
   161 void CBTEngPairMan::InitPairedDevicesList()
       
   162     {
       
   163     TRACE_FUNC_ENTRY
       
   164 
       
   165     // Check that we have the Bluetooth local address. If we don't then initialise anyway, but subscribe for an update.
       
   166     // This allows us to refresh our paired devices list to include updates made to the remote devices table of the 
       
   167     // Bluetooth registry from a restore operation. We need to include these devices without mistaking them for new 
       
   168     // pairings. We look solely at the P&S key for the address to avoid the condition whereby the address has been
       
   169     // entered into the reigstry but the Bluetooth Manager server has not begun the restore process yet. The signalling
       
   170     // of the P&S key will cause Bluetooth Manager to update the registry with any restored devices before fulfilling
       
   171     // any further requests.
       
   172 
       
   173     // Subscribe to local address property in case we need an update.
       
   174     iPropertyLocalAddr.Subscribe( iLocalAddrActive->iStatus );
       
   175     iLocalAddrActive->SetRequestId( ERegistryGetLocalAddress );
       
   176     iLocalAddrActive->GoActive();
       
   177 
       
   178     // Attempt to read address from P&S key.
       
   179     TBuf8<KBTDevAddrSize> btAddrDes;
       
   180     TInt err = iPropertyLocalAddr.Get( btAddrDes );
       
   181 
       
   182     // Is the P&S key defined yet? (if not, stack not up yet)
       
   183     if ( err == KErrNone )
       
   184         {
       
   185         // P&S key defined, is local address set? (if not, H/W not initialised yet)
       
   186         if ( btAddrDes.Length() == KBTDevAddrSize )
       
   187             {
       
   188             TBTDevAddr btAddr = btAddrDes;
       
   189 
       
   190             if ( btAddr != TBTDevAddr() )
       
   191                 {
       
   192                 // Non-zero local address is available.
       
   193                 iPropertyLocalAddr.Cancel();
       
   194                 iLocalAddrActive->CancelRequest();
       
   195                 }
       
   196             }
       
   197         }
       
   198 
       
   199     // Perform initialisation of the paired devices list.
       
   200     DoInitPairedDevicesList();
       
   201 
       
   202     TRACE_FUNC_EXIT
       
   203     }
       
   204 
       
   205 // ---------------------------------------------------------------------------
       
   206 // Initialises the paired devices list (second stage)
       
   207 // This method performs the actual initialisation, now that the local BT H/W
       
   208 // address had been made available.
       
   209 // ---------------------------------------------------------------------------
       
   210 //
       
   211 void CBTEngPairMan::DoInitPairedDevicesList()
       
   212     {
       
   213     TRACE_FUNC_ENTRY
       
   214 
       
   215     if ( !iRegistryActive->IsActive() )
       
   216         {
       
   217         // Start to get the list of all paired devices.
       
   218         CreatePairedDevicesView( ERegistryInitiatePairedDevicesView );
       
   219         }
       
   220     else
       
   221         {
       
   222         iNotHandledInitEventCounter++;
       
   223         }
       
   224 
       
   225     TRACE_FUNC_EXIT
       
   226     }
       
   227 
       
   228 // ---------------------------------------------------------------------------
       
   229 // Handles pairing related commands from BTEng clients.
       
   230 // ---------------------------------------------------------------------------
       
   231 //
       
   232 void CBTEngPairMan::ProcessCommandL( const RMessage2& aMessage )
       
   233     {
       
   234     TRACE_FUNC_ENTRY
       
   235     TInt opcode = aMessage.Function();
       
   236     TBTDevAddrPckgBuf addrPkg;
       
   237     switch( opcode )
       
   238         {
       
   239         case EBTEngSetPairingObserver:
       
   240             {
       
   241             aMessage.ReadL( KBTEngAddrSlot, addrPkg );
       
   242             SetPairObserver( addrPkg(), aMessage.Int1() );
       
   243             break;
       
   244             }
       
   245         case EBTEngPairDevice:
       
   246             {
       
   247             if ( !iMessage.IsNull() )
       
   248                 {
       
   249                 User::Leave( KErrServerBusy );
       
   250                 }
       
   251             TBTDevAddrPckgBuf addrPkg;
       
   252             aMessage.ReadL( KBTEngAddrSlot, addrPkg );
       
   253             PairDeviceL( addrPkg(), aMessage.Int1() );
       
   254             iMessage = RMessage2( aMessage );
       
   255             break;
       
   256             }
       
   257         case EBTEngCancelPairDevice:
       
   258             {
       
   259             // Only the client who requested pairing can cancel it:
       
   260             if ( !iMessage.IsNull() && aMessage.Session() == iMessage.Session() )
       
   261                 {
       
   262                 iPairer->CancelOutgoingPair();
       
   263                 iMessage.Complete( KErrCancel );
       
   264                 }
       
   265             break;
       
   266             }
       
   267         default:
       
   268             {
       
   269             TRACE_INFO( ( _L( "CBTEngPairMan ProcessCommandL: bad request (%d)" ), 
       
   270                            aMessage.Function() ) )
       
   271             User::Leave( KErrArgument );
       
   272             }
       
   273         }
       
   274     TRACE_FUNC_EXIT    
       
   275     }
       
   276 
       
   277 // ---------------------------------------------------------------------------
       
   278 // Handle a change in BTRegistry remote devices table.
       
   279 // ---------------------------------------------------------------------------
       
   280 //
       
   281 void CBTEngPairMan::RemoteRegistryChangeDetected()
       
   282     {
       
   283     if ( !iRegistryActive->IsActive() )
       
   284         {
       
   285         CreatePairedDevicesView( ERegistryPairedDevicesNewView );
       
   286         }
       
   287     else
       
   288         {
       
   289         iNotHandledRegEventCounter++;
       
   290         }
       
   291     }
       
   292 
       
   293 // ---------------------------------------------------------------------------
       
   294 // Returns the RBluetoothPairingServer instance.
       
   295 // ---------------------------------------------------------------------------
       
   296 //
       
   297 RBluetoothPairingServer* CBTEngPairMan::PairingServer()
       
   298     {
       
   299     return iPairingServ;
       
   300     }
       
   301 
       
   302 // ---------------------------------------------------------------------------
       
   303 // Access the reference of RSockServ
       
   304 // ---------------------------------------------------------------------------
       
   305 //
       
   306 RSocketServ& CBTEngPairMan::SocketServ()
       
   307     {
       
   308     return iServer.SocketServer();
       
   309     }
       
   310 
       
   311 // ---------------------------------------------------------------------------
       
   312 // Access the reference of RBTRegSrv
       
   313 // ---------------------------------------------------------------------------
       
   314 //
       
   315 RBTRegServ& CBTEngPairMan::BTRegServ()
       
   316     {
       
   317     return iServer.RegistrServer();
       
   318     }
       
   319 
       
   320 // ---------------------------------------------------------------------------
       
   321 // Deletes the current pairing handler and transfer the responsibility
       
   322 // to the specified.
       
   323 // ---------------------------------------------------------------------------
       
   324 //
       
   325 void CBTEngPairMan::RenewPairer( CBTEngPairBase* aPairer )
       
   326     {
       
   327     delete iPairer;
       
   328     iPairer = aPairer;
       
   329     }
       
   330 
       
   331 // ---------------------------------------------------------------------------
       
   332 // Find the session who requested this and completes its request.
       
   333 // ---------------------------------------------------------------------------
       
   334 //
       
   335 void CBTEngPairMan::OutgoingPairCompleted( TInt aErr )
       
   336     {
       
   337     TRACE_FUNC_ENTRY
       
   338     // the meaning of KHCIErrorBase equals KErrNone. Hide this specific BT stack
       
   339 	// detail from clients:
       
   340     if ( aErr == KHCIErrorBase )
       
   341         {
       
   342         aErr = KErrNone;
       
   343         }
       
   344     // we must complete client's pairing request:
       
   345     if ( !iMessage.IsNull()  )
       
   346         {
       
   347         iMessage.Complete( aErr );
       
   348         }
       
   349     TRACE_FUNC_EXIT
       
   350     }
       
   351 
       
   352 // ---------------------------------------------------------------------------
       
   353 // A session will be ended, completes the pending request for this session.
       
   354 // ---------------------------------------------------------------------------
       
   355 //
       
   356 void CBTEngPairMan::SessionClosed( CSession2* aSession )
       
   357     {
       
   358     TRACE_FUNC_ARG( ( _L( " session %x"), aSession ) )
       
   359     if ( !iMessage.IsNull() && iMessage.Session() == aSession )
       
   360         {
       
   361         iMessage.Complete( KErrCancel );
       
   362         }
       
   363     TRACE_FUNC_EXIT
       
   364     }
       
   365 
       
   366 // ---------------------------------------------------------------------------
       
   367 // Unpair the device from registry
       
   368 // ---------------------------------------------------------------------------
       
   369 //
       
   370 void CBTEngPairMan::UnpairDevice( const TBTDevAddr& aAddr )
       
   371     {
       
   372     TRACE_FUNC_ENTRY
       
   373     TIdentityRelation<TBTNamelessDevice> addrComp( CompareDeviceByAddress );
       
   374     TBTNamelessDevice dev;
       
   375     dev.SetAddress( aAddr );
       
   376     // only do unpairing if the we have a link key with it.
       
   377     TInt index = iPairedDevices->Find( dev, addrComp );
       
   378     if ( index > KErrNotFound )
       
   379         {
       
   380         dev = (*iPairedDevices)[index];
       
   381         
       
   382         TRequestStatus status( KRequestPending );
       
   383         // Unpair the device in registry (synchronously)
       
   384         iBTRegistry.UnpairDevice( dev.Address(), status );
       
   385         User::WaitForRequest( status );
       
   386         TRACE_INFO( ( _L( "Delete link key, res %d"), status.Int() ) )
       
   387         
       
   388         if ( status == KErrNone )
       
   389             {
       
   390             TBTDeviceSecurity security = dev.GlobalSecurity();
       
   391             // Clear trust setting so that correct icon will be shown in ui applications.
       
   392             security.SetNoAuthenticate(EFalse );
       
   393             security.SetNoAuthorise(EFalse );
       
   394             dev.SetGlobalSecurity(security);
       
   395             dev.DeleteLinkKey();
       
   396             if ( dev.IsValidUiCookie() && 
       
   397                  ( dev.UiCookie() & EBTUiCookieJustWorksPaired ) )
       
   398                 {
       
   399                 // Remove the UI cookie bit for Just Works pairing.
       
   400                 TInt32 cookie = dev.UiCookie() & ~EBTUiCookieJustWorksPaired;
       
   401                 dev.SetUiCookie( cookie );
       
   402                 TRACE_INFO( ( _L( "UI cookie %x cleared"), EBTUiCookieJustWorksPaired ) );
       
   403                 }
       
   404             // modify the device in registry synchronously
       
   405             // status.Int() could be -1 if the device is not in registry 
       
   406             // which is totally fine for us.
       
   407             (void) UpdateRegDevice( dev );
       
   408             }
       
   409         }
       
   410     TRACE_FUNC_EXIT
       
   411     }
       
   412 
       
   413 TInt CBTEngPairMan::AddUiCookieJustWorksPaired( const TBTNamelessDevice& aDev )
       
   414     {
       
   415 	TRACE_FUNC_ENTRY
       
   416     TInt err( KErrNone );
       
   417     // There might be UI cookies used by other applications,
       
   418     // we should not overwrite them. 
       
   419     TInt32 cookie = aDev.IsValidUiCookie() ? aDev.UiCookie() : EBTUiCookieUndefined;
       
   420     if ( !( cookie & EBTUiCookieJustWorksPaired ) )
       
   421         {
       
   422         // Only update the cookie if the wanted one is not in registry yet
       
   423         // to keep minimal operations with registry.
       
   424         TBTNamelessDevice dev = aDev;		
       
   425         cookie |= EBTUiCookieJustWorksPaired;
       
   426         dev.SetUiCookie( cookie );
       
   427         err = UpdateRegDevice( dev );
       
   428         TRACE_INFO( ( _L( "[BTENG] CBTEngOtgPair write Ui cookie ret %d"), err ) );
       
   429         }
       
   430     TRACE_FUNC_EXIT
       
   431     return err;
       
   432     }
       
   433 
       
   434 // ---------------------------------------------------------------------------
       
   435 // update a nameless device in registry
       
   436 // ---------------------------------------------------------------------------
       
   437 //
       
   438 TInt CBTEngPairMan::UpdateRegDevice( const TBTNamelessDevice& aDev )
       
   439     {
       
   440     TRequestStatus status( KRequestPending );
       
   441     // update the device in registry synchronously
       
   442     iBTRegistry.ModifyDevice( aDev, status );
       
   443     User::WaitForRequest( status );
       
   444     TRACE_INFO( ( _L( "UpdateRegDevice, ret %d"), status.Int() ) )
       
   445     return status.Int();
       
   446     }
       
   447 
       
   448 // ---------------------------------------------------------------------------
       
   449 // Ask server class the connection status of the specified device
       
   450 // ---------------------------------------------------------------------------
       
   451 //
       
   452 TBTEngConnectionStatus CBTEngPairMan::IsDeviceConnected( const TBTDevAddr& aAddr )
       
   453     {
       
   454     return iServer.IsDeviceConnected( aAddr );
       
   455     }
       
   456 
       
   457 // ---------------------------------------------------------------------------
       
   458 // From class MBTEngActiveObserver.
       
   459 // Checks if there is an authentication result.
       
   460 // ---------------------------------------------------------------------------
       
   461 //
       
   462 void CBTEngPairMan::RequestCompletedL( CBTEngActive* /*aActive*/, TInt aId, TInt aStatus )
       
   463     {
       
   464     TRACE_FUNC_ARG( ( _L( "aId: %d, aStatus: %d"), aId, aStatus ) )
       
   465         // Check which request completed.
       
   466     switch( aId )
       
   467         {
       
   468         case ESimplePairingResult:
       
   469             {
       
   470             TBTDevAddr tmpAddr = iSimplePairingRemote;
       
   471             if (aStatus != KErrServerTerminated)
       
   472                 {
       
   473                 SubscribeSspPairingResult();
       
   474                 }
       
   475             HandlePairingResultL( tmpAddr, aStatus );
       
   476             break;
       
   477             }
       
   478         case EAuthenticationResult:
       
   479             {
       
   480             TBTDevAddr tmpAddr = iAuthenticateRemote;
       
   481             if (aStatus != KErrServerTerminated)
       
   482                 {
       
   483                 SubscribeAuthenticateResult();
       
   484                 }
       
   485             HandlePairingResultL( tmpAddr, aStatus );
       
   486             break;
       
   487             }
       
   488         case ERegistryInitiatePairedDevicesView:
       
   489         case ERegistryPairedDevicesNewView:
       
   490             {
       
   491             HandleCreatePairedDevicesViewCompletedL( aStatus, aId );
       
   492             break;
       
   493             }
       
   494         case ERegistryInitiatePairedDevicesList:
       
   495             {			
       
   496 			if (iSSPResultActive && iAuthenResultActive)
       
   497 				{
       
   498 				SubscribeSspPairingResult();
       
   499 				SubscribeAuthenticateResult();
       
   500 				}
       
   501             HandleGetPairedDevicesCompletedL( aStatus, aId );
       
   502             break;
       
   503             }
       
   504         case ERegistryGetPairedDevices:    
       
   505             {
       
   506             HandleGetPairedDevicesCompletedL( aStatus, aId );
       
   507             break;
       
   508             }
       
   509         case ERegistryGetLocalAddress:
       
   510             {
       
   511             // Refresh paired devices list to include any restored devices.
       
   512             DoInitPairedDevicesList();
       
   513             break;
       
   514             }
       
   515         default:
       
   516                 // Should not be possible, but no need for handling.
       
   517             TRACE_INFO( (_L("[BTEng]: CBTEngPairMan::RequestCompletedL unhandled event!!") ) )
       
   518             break;
       
   519         }
       
   520     TRACE_FUNC_EXIT
       
   521     }
       
   522 
       
   523 // ---------------------------------------------------------------------------
       
   524 // From class MBTEngActiveObserver.
       
   525 // ---------------------------------------------------------------------------
       
   526 //
       
   527 void CBTEngPairMan::HandleError( CBTEngActive* aActive, TInt aId, TInt aError )
       
   528     {
       
   529     TRACE_FUNC_ARG( ( _L( "request id: %d, error: %d" ), aId, aError ) )
       
   530     (void) aActive;
       
   531     (void) aError;
       
   532     if ( aId == ERegistryInitiatePairedDevicesList || 
       
   533          aId == ERegistryGetPairedDevices )
       
   534         {// leave happened in registry operation, delete registry response:
       
   535         delete iPairedDevicesResp;
       
   536         iPairedDevicesResp = NULL;
       
   537         }
       
   538     }
       
   539 
       
   540 // ---------------------------------------------------------------------------
       
   541 // Activate or deactivate a pairing handler
       
   542 // ---------------------------------------------------------------------------
       
   543 //
       
   544 TInt CBTEngPairMan::SetPairObserver(const TBTDevAddr& aAddr, TBool aActivate)
       
   545     {
       
   546     TRACE_FUNC_ARG( ( _L( "%d" ), aActivate ) )
       
   547     TRACE_BDADDR( aAddr )
       
   548     iPairingOperationAttempted = ETrue;
       
   549     TInt err( KErrNone );
       
   550     if ( !aActivate )
       
   551         {
       
   552         if ( iPairer )
       
   553             {
       
   554             iPairer->StopPairHandling( aAddr );
       
   555             }
       
   556         return err;
       
   557         }
       
   558     
       
   559     if ( !iPairer)
       
   560         {
       
   561         // This is an incoming pair, unpair it from registry and 
       
   562         // create the handler:
       
   563         UnpairDevice( aAddr );
       
   564         TRAP( err, iPairer = CBTEngIncPair::NewL( *this, aAddr ));     
       
   565         }
       
   566     if ( iPairer)
       
   567         {
       
   568         // let the handler decide what to do:
       
   569         err = iPairer->ObserveIncomingPair( aAddr );        
       
   570         }    
       
   571     TRACE_FUNC_EXIT
       
   572     return err;
       
   573     }
       
   574 
       
   575 // ---------------------------------------------------------------------------
       
   576 // Delegates the request to current pair handler
       
   577 // ---------------------------------------------------------------------------
       
   578 //
       
   579 void CBTEngPairMan::PairDeviceL( const TBTDevAddr& aAddr, TUint32 aCod )
       
   580     {
       
   581     iPairingOperationAttempted = ETrue;
       
   582     if ( !iPairer)
       
   583         {
       
   584         // no existing pair handling, create one:
       
   585         iPairer = CBTEngOtgPair::NewL( *this, aAddr );
       
   586         }
       
   587     // let pair handler decide what to do:
       
   588     iPairer->HandleOutgoingPairL( aAddr, aCod );
       
   589     }
       
   590 
       
   591 // ---------------------------------------------------------------------------
       
   592 // cancel Subscribings to simple pairing result and authentication result from
       
   593 // Pairing Server
       
   594 // ---------------------------------------------------------------------------
       
   595 //
       
   596 void CBTEngPairMan::CancelSubscribe()
       
   597     {
       
   598     TRACE_FUNC_ENTRY
       
   599     if( iSSPResultActive && iSSPResultActive->IsActive() )
       
   600         {
       
   601             // Cancel listening Simple pairing result
       
   602         iPairingResult.CancelSimplePairingResult();
       
   603         iSSPResultActive->Cancel();
       
   604         }
       
   605     if( iAuthenResultActive && iAuthenResultActive->IsActive() )
       
   606         {
       
   607             // Cancel listening authentication result
       
   608         iAuthenResult.CancelAuthenticationResult();
       
   609         iAuthenResultActive->Cancel();
       
   610         }
       
   611     TRACE_FUNC_EXIT
       
   612     }
       
   613 
       
   614 // ---------------------------------------------------------------------------
       
   615 // Subscribes to simple pairing result from Pairing Server (if not already 
       
   616 // subscribed).
       
   617 // ---------------------------------------------------------------------------
       
   618 //
       
   619 void CBTEngPairMan::SubscribeSspPairingResult()
       
   620     {
       
   621     TRACE_FUNC_ENTRY
       
   622     if ( !iSSPResultActive->IsActive() )
       
   623         {
       
   624         iPairingResult.SimplePairingResult( iSimplePairingRemote, iSSPResultActive->RequestStatus() );
       
   625         iSSPResultActive->GoActive();
       
   626         }
       
   627     TRACE_FUNC_EXIT
       
   628     }
       
   629 
       
   630 // ---------------------------------------------------------------------------
       
   631 // Subscribes to authentication result from Pairing Server (if not already
       
   632 // subscribed).
       
   633 // ---------------------------------------------------------------------------
       
   634 //
       
   635 void CBTEngPairMan::SubscribeAuthenticateResult()
       
   636     {
       
   637     TRACE_FUNC_ENTRY
       
   638     if ( !iAuthenResultActive->IsActive() )
       
   639         {
       
   640         // Subscribe authentication result (which requires pairing for unpaired devices)
       
   641         iAuthenResult.AuthenticationResult( iAuthenticateRemote, iAuthenResultActive->RequestStatus() );
       
   642         iAuthenResultActive->GoActive();
       
   643         }
       
   644     TRACE_FUNC_EXIT
       
   645     }
       
   646 
       
   647 // ---------------------------------------------------------------------------
       
   648 // Handle a pairing result from the pairing server.
       
   649 // ---------------------------------------------------------------------------
       
   650 //
       
   651 void CBTEngPairMan::HandlePairingResultL( const TBTDevAddr& aAddr, TInt aResult )
       
   652     {
       
   653     TRACE_FUNC_ARG( (_L("result %d"), aResult ) )
       
   654     TRACE_BDADDR( aAddr );
       
   655     if ( !iPairer && ( aResult == KErrNone || aResult == KHCIErrorBase ) )
       
   656         {
       
   657         // we only create new handler if incoming pairing succeeds.
       
   658         // Pairing failure could be caused by user local cancellation, as the  
       
   659         // result, the handler was destroyed by notifier. We shall not
       
   660         // instantiate the handler again.
       
   661         // If a pairing failed due to other reasons than user local cancelling,
       
   662         // it will be catched by the already started handler 
       
   663         // (except Just Works pairing - no handler for it at all until we receive
       
   664         // registry change event. Thus if incoming JWs pairing failed, no user
       
   665         // notification will be shown.)
       
   666         TBTNamelessDevice dev;
       
   667         dev.SetAddress( aAddr );
       
   668         TIdentityRelation<TBTNamelessDevice> addrComp( CompareDeviceByAddress );
       
   669         TInt index = iPairedDevices->Find( dev, addrComp );
       
   670         
       
   671         // If the device is not found in the old paired device list, it is a new
       
   672         // paired device:
       
   673         if ( index == KErrNotFound)
       
   674             {
       
   675             // No handler yet, create incoming pairing handler:
       
   676             iPairer = CBTEngIncPair::NewL( *this, aAddr );
       
   677             }
       
   678         }
       
   679     if ( iPairer )
       
   680         {
       
   681         iPairer->HandlePairServerResult( aAddr, aResult );
       
   682         }  
       
   683 
       
   684     TRACE_FUNC_EXIT
       
   685     }
       
   686 
       
   687 // ---------------------------------------------------------------------------
       
   688 // issue creating a bonded devices view
       
   689 // ---------------------------------------------------------------------------
       
   690 //
       
   691 void CBTEngPairMan::CreatePairedDevicesView( TInt aReqId )
       
   692     {
       
   693     TRACE_FUNC_ENTRY
       
   694     if ( aReqId == ERegistryInitiatePairedDevicesView )
       
   695         {
       
   696         iNotHandledInitEventCounter = 0;
       
   697         }
       
   698     else
       
   699         {
       
   700         iNotHandledRegEventCounter = 0;
       
   701         }
       
   702     TBTRegistrySearch searchPattern;
       
   703     searchPattern.FindBonded();
       
   704     iRegistryActive->SetRequestId( aReqId );
       
   705     iBTRegistry.CreateView( searchPattern, iRegistryActive->iStatus );
       
   706     iRegistryActive->GoActive();
       
   707     TRACE_FUNC_EXIT
       
   708     }
       
   709 
       
   710 // ---------------------------------------------------------------------------
       
   711 // gets the paired devices from the view created by CreatePairedDevicesView
       
   712 // ---------------------------------------------------------------------------
       
   713 //
       
   714 void CBTEngPairMan::GetPairedDevices( TInt aReqId )
       
   715     {
       
   716     TRACE_FUNC_ENTRY
       
   717     delete iPairedDevicesResp;
       
   718     iPairedDevicesResp = NULL;
       
   719     TRAP_IGNORE( iPairedDevicesResp = CBTRegistryResponse::NewL( iBTRegistry ) );
       
   720     if ( iPairedDevicesResp )
       
   721         {
       
   722         iRegistryActive->SetRequestId( aReqId );
       
   723         iPairedDevicesResp->Start( iRegistryActive->iStatus );
       
   724         iRegistryActive->GoActive();
       
   725         }
       
   726     TRACE_FUNC_EXIT
       
   727     }
       
   728 
       
   729 // ---------------------------------------------------------------------------
       
   730 // re-create a paired device view if registry was changed during the previous
       
   731 // operation. otherwise if the view is not empty, get the paired devices.
       
   732 // ---------------------------------------------------------------------------
       
   733 //
       
   734 void CBTEngPairMan::HandleCreatePairedDevicesViewCompletedL( TInt aStatus, TInt aReqId )
       
   735     {
       
   736     TRACE_FUNC_ENTRY
       
   737 
       
   738     if ( aReqId == ERegistryInitiatePairedDevicesView )
       
   739         {// Initialization phase, list paired devices if there are any.
       
   740         if ( iNotHandledInitEventCounter )
       
   741             {
       
   742             // Reinitialisaton detected, create paired device view again:
       
   743             (void) iBTRegistry.CloseView();
       
   744             CreatePairedDevicesView( ERegistryInitiatePairedDevicesView );
       
   745             }
       
   746         else if ( aStatus > KErrNone )
       
   747             {
       
   748             GetPairedDevices( ERegistryInitiatePairedDevicesList );
       
   749             }
       
   750         else
       
   751             {//no paired device, close the view.
       
   752             (void) iBTRegistry.CloseView();
       
   753             }
       
   754         }
       
   755     else
       
   756         {
       
   757         if ( iNotHandledInitEventCounter )
       
   758             {
       
   759             // We need to reinitialise but we may be pairing.
       
   760             // This situation is not expected to arise, as reinitialisation means
       
   761             // that the H/W was only just switched on.
       
   762             // If we have ever started to take part in a pairing, then prioritise that
       
   763             // pairing.
       
   764             (void) iBTRegistry.CloseView();
       
   765             if ( iPairingOperationAttempted )
       
   766                 {
       
   767                 iNotHandledInitEventCounter = 0;
       
   768                 CreatePairedDevicesView( ERegistryPairedDevicesNewView );
       
   769                 }
       
   770             else
       
   771                 {
       
   772                 CreatePairedDevicesView( ERegistryInitiatePairedDevicesView );
       
   773                 }
       
   774             }
       
   775         else if (iNotHandledRegEventCounter)
       
   776             { // more registry change detected, create paired device view again:
       
   777             (void) iBTRegistry.CloseView();
       
   778             CreatePairedDevicesView( ERegistryPairedDevicesNewView );
       
   779             }          
       
   780         else if ( aStatus > KErrNone )
       
   781             { // paired device available, get them:
       
   782             GetPairedDevices( ERegistryGetPairedDevices );
       
   783             }
       
   784         else
       
   785             {
       
   786             // No paired devices in registry, empty local db:
       
   787             (void) iBTRegistry.CloseView();
       
   788             iPairedDevices->Reset();
       
   789             }
       
   790         }
       
   791     TRACE_FUNC_EXIT
       
   792     }
       
   793 
       
   794 // ---------------------------------------------------------------------------
       
   795 // update paired device list. if registry was changed, create a new view.
       
   796 // otherwise check for new pairing event.
       
   797 // ---------------------------------------------------------------------------
       
   798 //
       
   799 void CBTEngPairMan::HandleGetPairedDevicesCompletedL( TInt /*aStatus*/, TInt aReqId )
       
   800     {
       
   801     TRACE_FUNC_ENTRY
       
   802     (void) iBTRegistry.CloseView();
       
   803     if ( aReqId == ERegistryInitiatePairedDevicesList )
       
   804         {
       
   805         if ( iNotHandledInitEventCounter )
       
   806             {
       
   807             // Reinitialisation required, create paired device view again:
       
   808             CreatePairedDevicesView( ERegistryInitiatePairedDevicesView );
       
   809             }
       
   810         else
       
   811             {
       
   812             // We completed the initialisation of paired device list, 
       
   813             // move all paired devices to the array:
       
   814             UpdatePairedDeviceListL();
       
   815             }
       
   816         }
       
   817     else
       
   818         {
       
   819         if (iNotHandledInitEventCounter)
       
   820             {
       
   821             // We need to reinitialise but we may be pairing.
       
   822             // This situation is not expected to arise, as reinitialisation means
       
   823             // that the H/W was only just switched on.
       
   824             // If we have ever started to take part in a pairing, then prioritise that
       
   825             // pairing.
       
   826             if ( iPairingOperationAttempted )
       
   827                 {
       
   828                 iNotHandledInitEventCounter = 0;
       
   829                 CreatePairedDevicesView( ERegistryPairedDevicesNewView );
       
   830                 }
       
   831             else
       
   832                 {
       
   833                 CreatePairedDevicesView( ERegistryInitiatePairedDevicesView );
       
   834                 }		
       
   835             }     
       
   836         else if (iNotHandledRegEventCounter)
       
   837             { // more registry change detected, create paired device view again:
       
   838             CreatePairedDevicesView( ERegistryPairedDevicesNewView );
       
   839             }
       
   840         else if ( aReqId == ERegistryGetPairedDevices)
       
   841            {
       
   842             // no more registry change detected, find new pairings:
       
   843             CheckPairEventL();
       
   844            }
       
   845         }
       
   846 
       
   847     TRACE_FUNC_EXIT
       
   848     }
       
   849 
       
   850 // ---------------------------------------------------------------------------
       
   851 // copy the nameless devices to local array
       
   852 // ---------------------------------------------------------------------------
       
   853 //
       
   854 void CBTEngPairMan::UpdatePairedDeviceListL()
       
   855     {
       
   856     TRACE_FUNC_ENTRY
       
   857     iPairedDevices->Reset();
       
   858     for ( TInt i = 0; i < iPairedDevicesResp->Results().Count(); i++ )
       
   859         {
       
   860         TRACE_BDADDR( iPairedDevicesResp->Results()[i]->BDAddr() );
       
   861         TRACE_INFO((_L("[BTENG]\t linkkeytype %d"), 
       
   862                 iPairedDevicesResp->Results()[i]->LinkKeyType()))
       
   863         iPairedDevices->AppendL( iPairedDevicesResp->Results()[i]->AsNamelessDevice() );
       
   864         }
       
   865     delete iPairedDevicesResp;
       
   866     iPairedDevicesResp = NULL;
       
   867     TRACE_FUNC_EXIT
       
   868     }
       
   869 
       
   870 // ---------------------------------------------------------------------------
       
   871 // find new paired devices. for each, delegate the information to
       
   872 // current pair handler.
       
   873 // ---------------------------------------------------------------------------
       
   874 //
       
   875 void CBTEngPairMan::CheckPairEventL()
       
   876     {
       
   877     TRACE_FUNC_ENTRY
       
   878     RArray<TBTNamelessDevice>* pairedDevicesOld;
       
   879     pairedDevicesOld = iPairedDevices;
       
   880     CleanupStack::PushL( pairedDevicesOld );
       
   881     CleanupClosePushL( *pairedDevicesOld );
       
   882     iPairedDevices = NULL;
       
   883     iPairedDevices = new (ELeave) RArray<TBTNamelessDevice>;
       
   884     UpdatePairedDeviceListL();
       
   885     
       
   886     TIdentityRelation<TBTNamelessDevice> addrComp( CompareDeviceByAddress );
       
   887     for ( TInt i = 0; i < iPairedDevices->Count(); i++ )
       
   888         {
       
   889         TBTNamelessDevice& dev = (*iPairedDevices)[i];        
       
   890         TInt index = pairedDevicesOld->Find( dev, addrComp );
       
   891  
       
   892         // If the device is not found in the old paired device list or
       
   893         // the link key type has been changed from 
       
   894         // ELinkKeyUnauthenticatedUpgradable, the device is a new 
       
   895         // paired device:
       
   896         TBool newPaired = dev.LinkKeyType() != ELinkKeyUnauthenticatedUpgradable && 
       
   897              ( index == KErrNotFound  || 
       
   898                  ( index > KErrNotFound &&
       
   899                  dev.LinkKeyType() != (*pairedDevicesOld)[index].LinkKeyType() ) );
       
   900         TRACE_BDADDR( dev.Address() );
       
   901         if ( newPaired && !iPairer)
       
   902             {
       
   903             iPairingOperationAttempted = ETrue;
       
   904             iPairer = CBTEngIncPair::NewL( *this, dev.Address() );
       
   905             }
       
   906         if ( newPaired && iPairer )
       
   907             {
       
   908             // Ask pair handler to decide what to do:
       
   909             iPairer->HandleRegistryNewPairedEvent( dev );
       
   910             }
       
   911         }
       
   912     // Free old paired device list resource:
       
   913     CleanupStack::PopAndDestroy( 2 );
       
   914     TRACE_FUNC_EXIT
       
   915     }
       
   916