bluetoothengine/btnotif/btnotifsrv/src/btnotifpairinghelper.cpp
changeset 31 a0ea99b6fa53
parent 30 df7a93ede42e
child 32 19bd632b5100
equal deleted inserted replaced
30:df7a93ede42e 31:a0ea99b6fa53
     1 /*
       
     2 * ============================================================================
       
     3 *  Name        : btnotifpairinghelper.cpp
       
     4 *  Part of     : bluetoothengine / btnotif
       
     5 *  Description : Helper class for processing pairing requests and results, as extended functionality for CBTNotifConnection.
       
     6 *
       
     7 *  Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     8 *  All rights reserved.
       
     9 *  This component and the accompanying materials are made available
       
    10 *  under the terms of "Eclipse Public License v1.0"
       
    11 *  which accompanies this distribution, and is available
       
    12 *  at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
    13 *
       
    14 *  Initial Contributors:
       
    15 *  Nokia Corporation - initial contribution.
       
    16 *
       
    17 *  Contributors:
       
    18 *  Nokia Corporation
       
    19 * ============================================================================
       
    20 * Template version: 4.1
       
    21 */
       
    22 
       
    23 #include "btnotifpairinghelper.h"
       
    24 #include <bt_sock.h>
       
    25 #include <btextnotifiers.h>
       
    26 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    27 #include <btextnotifierspartner.h>
       
    28 #endif
       
    29 
       
    30 #include "btnotifconnection.h"
       
    31 #include "btnotifconnectiontracker.h"
       
    32 #include "btnotificationmanager.h"
       
    33 #include "btnotifserver.h"
       
    34 #include "bluetoothtrace.h"
       
    35 
       
    36 /**  Id for the active object for a dedicated bonding session. */
       
    37 const TInt KDedicatedBonding = 50;
       
    38 /**  Length of the default PIN. */
       
    39 const TInt KDefaultPinLength = 4;
       
    40 /**  Default PIN character. */
       
    41 const TText8 KDefaultPinValue = '0';
       
    42 /**  Format syntax for numeric comparison value. */
       
    43 _LIT( KNumCompFormat, "%06u" );
       
    44 /**  Format syntax for passkey display value. */
       
    45 _LIT( KPassKeyFormat, "%06u" );
       
    46 
       
    47 
       
    48 // ======== LOCAL FUNCTIONS ========
       
    49 
       
    50 // ---------------------------------------------------------------------------
       
    51 // ?description
       
    52 // ---------------------------------------------------------------------------
       
    53 //
       
    54 /*?type ?function_name( ?arg_type ?arg,
       
    55                       ?arg_type ?arg )
       
    56     {
       
    57     }
       
    58 */
       
    59 
       
    60 // ======== MEMBER FUNCTIONS ========
       
    61 
       
    62 // ---------------------------------------------------------------------------
       
    63 // C++ default constructor.
       
    64 // ---------------------------------------------------------------------------
       
    65 //
       
    66 CBTNotifPairingHelper::CBTNotifPairingHelper( CBTNotifConnection* aConnection,
       
    67     CBTNotifConnectionTracker* aTracker )
       
    68 :   iConnection( aConnection ),
       
    69     iTracker( aTracker )
       
    70     {
       
    71     }
       
    72 
       
    73 
       
    74 // ---------------------------------------------------------------------------
       
    75 // Symbian 2nd-phase constructor.
       
    76 // ---------------------------------------------------------------------------
       
    77 //
       
    78 void CBTNotifPairingHelper::ConstructL()
       
    79     {
       
    80     if( iConnection )
       
    81         {
       
    82         iDevice = iConnection->BTDevice();
       
    83         }
       
    84     }
       
    85 
       
    86 
       
    87 // ---------------------------------------------------------------------------
       
    88 // NewL
       
    89 // ---------------------------------------------------------------------------
       
    90 //
       
    91 CBTNotifPairingHelper* CBTNotifPairingHelper::NewL( CBTNotifConnection* aConnection,
       
    92     CBTNotifConnectionTracker* aTracker )
       
    93     {
       
    94     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
    95     CBTNotifPairingHelper* self = new( ELeave ) CBTNotifPairingHelper( aConnection, aTracker );
       
    96     CleanupStack::PushL( self );
       
    97     self->ConstructL();
       
    98     CleanupStack::Pop( self );
       
    99     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   100     return self;
       
   101     }
       
   102 
       
   103 
       
   104 // ---------------------------------------------------------------------------
       
   105 // Destructor.
       
   106 // ---------------------------------------------------------------------------
       
   107 //
       
   108 CBTNotifPairingHelper::~CBTNotifPairingHelper()
       
   109     {
       
   110     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   111     if( iNotification )
       
   112         {
       
   113         // Clear the notification callback, we cannot receive them anymore.
       
   114         iNotification->RemoveObserver();
       
   115         iNotification->Close(); // Also dequeues the notification from the queue.
       
   116         iNotification = NULL;
       
   117         }
       
   118     delete iParams;
       
   119     if( iBondingActive )
       
   120         {
       
   121         iBondingActive->Cancel();   // Will close subsession;
       
   122         }
       
   123     delete iBondingActive;
       
   124     iBondingSession.Close();
       
   125     iBondingSocket.Close();
       
   126     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   127     }
       
   128 
       
   129 
       
   130 // ---------------------------------------------------------------------------
       
   131 // Handle the authentication result from the baseband. Show the result in a note.
       
   132 // ---------------------------------------------------------------------------
       
   133 //
       
   134 void CBTNotifPairingHelper::HandleAuthenticationCompleteL( TInt aError )
       
   135     {
       
   136     BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aError );
       
   137     if( iOperation == EDedicatedBonding || iOperation == EAwaitingPairingResult ||
       
   138         iOperation == EAutoPairing )
       
   139         {
       
   140         // Default case (aError == 0): Success, we are now paired.
       
   141         TBTDialogResourceId resourceId = EPairingSuccess;
       
   142         TBool autoPairing = ( iOperation == EAutoPairing ); // Remember the autopairing state
       
   143         iOperation = EShowPairingSuccess;
       
   144         if( aError && aError != KHCIErrorBase )
       
   145             {
       
   146             // Authentication failure, means pairing failed.
       
   147             resourceId = EPairingFailure;
       
   148             iOperation = EShowPairingFailure;
       
   149             // Communicate the error now that we still remember it.
       
   150             if( iDedicatedBonding )
       
   151                 {
       
   152                 if( autoPairing && aError == KHCIErrorBase - EAuthenticationFailure )
       
   153                     {
       
   154                     BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST, 
       
   155                             "[BTNOTIF]\t CBTNotifPairingHelper::HandleAuthenticationCompleteL: Autopairing failed, we need to try again.");
       
   156                     // Autopairing failed, we need to try again.
       
   157                     iOperation = EAutoPairing;  // Reset back
       
   158                     resourceId = ENoResource;
       
   159                     }
       
   160                 CompleteBondingL( aError );
       
   161                 }
       
   162             }
       
   163         if( resourceId )
       
   164             {
       
   165             // Inform the user of the result.
       
   166             BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST,  
       
   167                     "[BTNOTIF]\t CBTNotifPairingHelper::HandleAuthenticationCompleteL: pairing successful, inform user" );
       
   168             PrepareNotificationL( TBluetoothDialogParams::EGlobalNotif, resourceId );
       
   169             // MBRNotificationClosed will be called from this, which will 
       
   170             // check the next stage.
       
   171             }
       
   172         }
       
   173     BOstraceFunctionExit1( DUMMY_DEVLIST, this );
       
   174     }
       
   175 
       
   176 
       
   177 // ---------------------------------------------------------------------------
       
   178 // Start a bonding operation with the remote device.
       
   179 // ---------------------------------------------------------------------------
       
   180 //
       
   181 void CBTNotifPairingHelper::StartBondingL( TInt aHandle )
       
   182     {
       
   183     BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aHandle );
       
   184     __ASSERT_ALWAYS( iOperation == EIdle || iOperation == EDedicatedBonding
       
   185                 || iOperation == EAutoPairing, PanicServer( EBTNotifPanicBadState ) );
       
   186     if( !iBondingActive )
       
   187         {
       
   188         iBondingActive = CBtSimpleActive::NewL( *this, KDedicatedBonding );
       
   189         }
       
   190     if( aHandle )
       
   191         {
       
   192         iDedicatedBonding = aHandle;
       
   193         }
       
   194     if( iOperation == EIdle )
       
   195         {
       
   196         iOperation = EDedicatedBonding;
       
   197         }
       
   198     if( iOperation == EDedicatedBonding && iTracker->PairingServerSession() )
       
   199         {
       
   200         if( !iBondingActive->IsActive() )
       
   201             {
       
   202             BtTraceBtAddr1( TRACE_DEBUG,DUMMY_LIST,"CBTNotifPairingHelper::StartBondingL()",iDevice->BDAddr() );
       
   203             iBondingSession.Start( *iTracker->PairingServerSession(),
       
   204                         iDevice->BDAddr(), iBondingActive->RequestStatus() );
       
   205             iBondingActive->GoActive();
       
   206             }
       
   207         }
       
   208     else
       
   209         {
       
   210         // We are doing autopairing (or the unlikely situation that the pairing server is unavailable)
       
   211         CompleteBondingL( KErrServerTerminated );
       
   212         }
       
   213     BOstraceFunctionExit1( DUMMY_DEVLIST, this);
       
   214     }
       
   215 
       
   216 
       
   217 // ---------------------------------------------------------------------------
       
   218 // Cancel an ongoing bonding operation with the remote device.
       
   219 // ---------------------------------------------------------------------------
       
   220 //
       
   221 void CBTNotifPairingHelper::CancelBondingL()
       
   222     {
       
   223     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   224     if( iDedicatedBonding )
       
   225         {
       
   226         CompleteBondingL( KErrCancel ); // Closes sessions
       
   227         if( iNotification )
       
   228             {
       
   229             // Cancel the outstanding user query
       
   230             // This will also unregister us from the notification.
       
   231             TInt err = iNotification->Close();
       
   232             NOTIF_NOTHANDLED( !err )
       
   233             iNotification = NULL;
       
   234             }
       
   235         if( iNotifierUid )
       
   236             {
       
   237             // Also finish up the notifier processing.
       
   238             CompletePairingNotifierL( KErrCancel, EFalse, KNullDesC8 );
       
   239             }
       
   240         iOperation = EIdle;
       
   241         iConnection->PairingCompleted();   // This may delete us.
       
   242         }
       
   243     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   244     }
       
   245 
       
   246 
       
   247 // ---------------------------------------------------------------------------
       
   248 // Handle a notifier request for pairing with the remote device of this connection.
       
   249 // ---------------------------------------------------------------------------
       
   250 //
       
   251 void CBTNotifPairingHelper::StartPairingNotifierL( TInt aUid, const TDesC8& aParams )
       
   252     {
       
   253     BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aUid );
       
   254     if( iDevice->GlobalSecurity().Banned() && !iDedicatedBonding )
       
   255         {
       
   256         // ToDo: should this case actually be ignored, and presume that
       
   257         // the caller will take care of unblocking the device?
       
   258         iOperation = EIdle;
       
   259         User::Leave( KErrAccessDenied );
       
   260         }
       
   261     // Store the parameters locally, we need them later again.
       
   262     delete iParams;
       
   263     iParams = NULL;
       
   264     iParams = HBufC8::NewL( aParams.Length() );
       
   265     *iParams = aParams;
       
   266     iNotifierUid = aUid;
       
   267 
       
   268     if( iDevice->IsValidPaired() && iDevice->IsPaired() )
       
   269         {
       
   270         // The device is still paired, we unpair it first.
       
   271         // Deleting the link key will set the device as unpaired.
       
   272         iDevice->DeleteLinkKey();
       
   273         iOperation = EUnpairing;    // So that parent state does not get changed.
       
   274         iConnection->UpdateRegistryEntryL();
       
   275         // Note that this will only be done before trying autopairing, so
       
   276         // it not interfere with a second attempt;
       
   277         }
       
   278     // Update the device name
       
   279     TBTPasskeyDisplayParams params; // Enough for reading the base class type parameter
       
   280     TPckgC<TBTPasskeyDisplayParams> paramsPckg( params );
       
   281     paramsPckg.Set( *iParams );
       
   282     if( paramsPckg().DeviceName().Length() )
       
   283         {
       
   284         // The name in the parameter package is the latest one, retrieved from 
       
   285         // the remote device during this connection. Update locally.
       
   286         iDevice->SetDeviceNameL( BTDeviceNameConverter::ToUTF8L( paramsPckg().DeviceName() ) );
       
   287         }
       
   288 
       
   289     TBool locallyInitiated = EFalse;
       
   290     TBuf<8> numVal;
       
   291     TBluetoothDialogParams::TBTDialogType dialog = TBluetoothDialogParams::EInvalidDialog;
       
   292     TBTDialogResourceId resource = ENoResource;
       
   293     // Read the notifier parameters (sets iOperation as well)
       
   294     ParseNotifierReqParamsL( locallyInitiated, numVal, dialog, resource );
       
   295     // If this is an incoming pairing, we first ask the user to accept it.
       
   296     if( !locallyInitiated && !iDedicatedBonding )
       
   297         {
       
   298         // Ignore the initatior if we initiated bonding.
       
   299         StartAcceptPairingQueryL(); // Overrides iOperation
       
   300         }
       
   301     else
       
   302         {
       
   303         __ASSERT_ALWAYS( resource != ENoResource, PanicServer( EBTNotifPanicBadState ) );
       
   304         CheckAutoPairingL( locallyInitiated, numVal );
       
   305         // CheckAutoPairingL sets 
       
   306         if( iOperation != EAutoPairing )
       
   307             {
       
   308             PrepareNotificationL( dialog, resource );
       
   309             if( numVal.Length() )
       
   310                 {
       
   311                 TInt err = iNotification->SetData( TBluetoothDeviceDialog::EAdditionalDesc, numVal );
       
   312                 NOTIF_NOTHANDLED( !err )
       
   313                 }
       
   314             }
       
   315         }
       
   316     BOstraceFunctionExit1( DUMMY_DEVLIST, this );
       
   317     }
       
   318 
       
   319 
       
   320 // ---------------------------------------------------------------------------
       
   321 // Update a notifier, update the outstanding dialog if the notifier request 
       
   322 // is currently being served.
       
   323 // ---------------------------------------------------------------------------
       
   324 //
       
   325 void CBTNotifPairingHelper::UpdatePairingNotifierL( TInt aUid, const TDesC8& aParams )
       
   326     {
       
   327     (void) aUid;
       
   328     TBTNotifierUpdateParams2 params;    // Enough for reading the base class type parameter
       
   329     TPckgC<TBTNotifierUpdateParams2> paramsPckg( params );
       
   330     paramsPckg.Set( aParams );
       
   331     if( paramsPckg().Type() == TBTNotifierUpdateParams2::EPasskeyDisplay )
       
   332         {
       
   333         // Paskey display update - keypress on remote device.
       
   334         }
       
   335     else
       
   336         {
       
   337         // name update
       
   338         TBTDeviceNameUpdateParams nameUpdate;
       
   339         TPckgC<TBTDeviceNameUpdateParams> nameUpdatePckg( nameUpdate );
       
   340         nameUpdatePckg.Set( aParams );
       
   341         // The result means result of conversion to unicode
       
   342         if( !nameUpdatePckg().Result() )
       
   343             {
       
   344             // Only update locally, registry will update us with the same info later on.
       
   345             iDevice->SetDeviceNameL( BTDeviceNameConverter::ToUTF8L( nameUpdatePckg().DeviceName() ) );
       
   346             if( iNotification )
       
   347                 {
       
   348                 // Update the dialog with the new name. It is up to the dialog to 
       
   349                 // determine the validity (in case another dialog is shown).
       
   350                 //iNotification->Update(  )
       
   351                 }
       
   352             }
       
   353         }
       
   354     }
       
   355 
       
   356 
       
   357 // ---------------------------------------------------------------------------
       
   358 // Cancel a request, dismiss the outstanding dialog if the notifier request 
       
   359 // is currently being served.
       
   360 // ---------------------------------------------------------------------------
       
   361 //
       
   362 void CBTNotifPairingHelper::CancelPairingNotifierL( TInt aUid )
       
   363     {
       
   364     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   365     // ToDo: we need to check that the UID and the outstanding notification
       
   366     // type are matching?
       
   367     if( iOperation > EIdle && iOperation < EPostPairingOperations && aUid == iNotifierUid &&
       
   368         ( aUid == KBTPinCodeEntryNotifierUid.iUid ||
       
   369           aUid == KBTNumericComparisonNotifierUid.iUid ||
       
   370           aUid == KBTPasskeyDisplayNotifierUid.iUid ) )
       
   371         {
       
   372         if( iNotification )
       
   373             {
       
   374             // Cancel the user query
       
   375             // This will also unregister us from the notification.
       
   376             TInt err = iNotification->Close();
       
   377             NOTIF_NOTHANDLED( !err )
       
   378             iNotification = NULL;
       
   379             }
       
   380         iOperation = EIdle;
       
   381         iNotifierUid = 0;
       
   382         // We do not call pairing completed from here, our parent will
       
   383         // check our status by itself, and may delete us.
       
   384 
       
   385         // Any bonding requester needs to be informed though.
       
   386         CancelBondingL();
       
   387         }
       
   388     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   389     }
       
   390 
       
   391 
       
   392 // ---------------------------------------------------------------------------
       
   393 // 
       
   394 // ---------------------------------------------------------------------------
       
   395 //
       
   396 void CBTNotifPairingHelper::StartJustWorksProcessingL()
       
   397     {
       
   398     }
       
   399 
       
   400 
       
   401 // ---------------------------------------------------------------------------
       
   402 // 
       
   403 // ---------------------------------------------------------------------------
       
   404 //
       
   405 void CBTNotifPairingHelper::CancelJustWorksProcessingL()
       
   406     {
       
   407     }
       
   408 
       
   409 
       
   410 // ---------------------------------------------------------------------------
       
   411 // From class MBTNotificationResult.
       
   412 // Handle a result from a user query.
       
   413 // ---------------------------------------------------------------------------
       
   414 //
       
   415 void CBTNotifPairingHelper::MBRDataReceived( CHbSymbianVariantMap& aData )
       
   416     {
       
   417     (void) aData;
       
   418     NOTIF_NOTIMPL
       
   419     }
       
   420 
       
   421 
       
   422 // ---------------------------------------------------------------------------
       
   423 // From class MBTNotificationResult.
       
   424 // The notification is finished.
       
   425 // ---------------------------------------------------------------------------
       
   426 //
       
   427 void CBTNotifPairingHelper::MBRNotificationClosed( TInt aError, const TDesC8& aData )
       
   428     {
       
   429     BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aError );
       
   430     // First unregister from the notification, so we can already get the next one.
       
   431     iNotification->RemoveObserver();
       
   432     iNotification = NULL;
       
   433     TRAP_IGNORE( NotificationClosedL( aError, aData ) );
       
   434     if( iOperation == EIdle )
       
   435         {
       
   436         // Any error has been communicated already.
       
   437         iConnection->PairingCompleted();   // This may delete us.
       
   438         }
       
   439     BOstraceFunctionExit1( DUMMY_DEVLIST, this );
       
   440     }
       
   441 
       
   442 
       
   443 // ---------------------------------------------------------------------------
       
   444 // From class MBtSimpleActiveObserver.
       
   445 // Handle the active object completion.
       
   446 // ---------------------------------------------------------------------------
       
   447 //
       
   448 void CBTNotifPairingHelper::RequestCompletedL( CBtSimpleActive* aActive,
       
   449     TInt aStatus )
       
   450     {
       
   451     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   452     switch( aActive->RequestId() )
       
   453         {
       
   454         case KDedicatedBonding:
       
   455             {
       
   456             if( iDedicatedBonding )
       
   457                 {
       
   458                 // If the result hasn't been processed already.
       
   459                 HandleAuthenticationCompleteL( aStatus );
       
   460                 }
       
   461             }
       
   462             break;
       
   463         default:
       
   464             NOTIF_NOTIMPL
       
   465             break;
       
   466         }
       
   467     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   468     }
       
   469 
       
   470 
       
   471 // ---------------------------------------------------------------------------
       
   472 // From class MBtSimpleActiveObserver.
       
   473 // Cancel and clean up all requests related to the active object.
       
   474 // ---------------------------------------------------------------------------
       
   475 //
       
   476 void CBTNotifPairingHelper::CancelRequest( TInt aRequestId )
       
   477     {
       
   478     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   479     switch( aRequestId )
       
   480         {
       
   481         case KDedicatedBonding:
       
   482             iBondingSession.Close();
       
   483             break;
       
   484         default:
       
   485             NOTIF_NOTIMPL
       
   486             break;
       
   487         }
       
   488     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   489     }
       
   490 
       
   491 // ---------------------------------------------------------------------------
       
   492 // From class MBtSimpleActiveObserver.
       
   493 // 
       
   494 // ---------------------------------------------------------------------------
       
   495 //
       
   496 void CBTNotifPairingHelper::HandleError( CBtSimpleActive* aActive, 
       
   497         TInt aError )
       
   498     {
       
   499     (void) aActive;
       
   500     (void) aError;
       
   501     }
       
   502 
       
   503 // ---------------------------------------------------------------------------
       
   504 // Process the user input and complete the outstanding pairing request.
       
   505 // ---------------------------------------------------------------------------
       
   506 //
       
   507 void CBTNotifPairingHelper::CompletePairingNotifierL( TInt aError, TBool aResult,
       
   508     const TDesC8& aData )
       
   509     {
       
   510     BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aError );
       
   511     TInt err = aError;
       
   512     TPtrC8 resultData;
       
   513     if( !err )
       
   514         {
       
   515         // The returned data is the entered passkey.
       
   516         TBool proceed = iTracker->UpdateBlockingHistoryL( iDevice, aResult );
       
   517         if( iOperation == ESspPairing && iNotifierUid == KBTNumericComparisonNotifierUid.iUid )
       
   518             {
       
   519             // Numeric comparison needs the boolean result passed back.
       
   520             TPckgBuf<TBool> userAcceptance( aResult );
       
   521             resultData.Set( userAcceptance );
       
   522             }
       
   523         if( aResult )
       
   524             {
       
   525             if( iOperation == ELegacyPairing || iOperation == EAutoPairing )
       
   526                 {
       
   527                 // Check the passkey entered by the user.
       
   528                 // The length of the returned data equals the number of characters
       
   529                 // entered by the user.
       
   530                 TBTPinCode pinCode;
       
   531                 pinCode().iLength = aData.Length();
       
   532                 TUint minLen = 0;
       
   533                 TBool locallyInitiated = EFalse; // Not used here.
       
   534                 ParsePinCodeReqParamsL( locallyInitiated, minLen );
       
   535                 if( aData.Length() >= minLen )
       
   536                     {
       
   537                     // Check that the length of the passkey meets the minimum 
       
   538                     // required pin code length
       
   539                     for( TInt i = 0; i < aData.Length(); i++ )
       
   540                         {
       
   541                         pinCode().iPIN[i] = aData[i];
       
   542                         }
       
   543                     resultData.Set( pinCode );
       
   544                     }
       
   545                 else
       
   546                     {
       
   547                     // PIN wasn't long enough. This should be handled by the dialog though.
       
   548                     err = KErrCompletion;
       
   549                     }
       
   550                 }
       
   551             // Now we just wait for the result to come in.
       
   552             if( iOperation != EAutoPairing )
       
   553                 {
       
   554                 iOperation = EAwaitingPairingResult; 
       
   555                 }
       
   556             }
       
   557         else
       
   558             {
       
   559             err = KErrCancel;
       
   560             TBool locallyInitiated = EFalse;    // Needed below
       
   561             TBuf<8> numVal;     // Not needed here.
       
   562             TBluetoothDialogParams::TBTDialogType type = TBluetoothDialogParams::EInvalidDialog;
       
   563             TBTDialogResourceId resource = ENoResource; // Resources and type are not needed here.
       
   564             // Check the notifier parameters
       
   565             ParseNotifierReqParamsL( locallyInitiated, numVal, type, resource );
       
   566             if( proceed && locallyInitiated && !iDedicatedBonding )
       
   567                 {
       
   568                 // The user denied the connection, ask to block the device.
       
   569                 // This is only for pairing (and not bonding) initiated by us,
       
   570                 // as the user already gets the opportunity to block when
       
   571                 // rejecting an incoming pairing request.
       
   572                 // This case may be for someone requesting to access a service
       
   573                 // which requires authentication by us, but not by the remote device.
       
   574                 iConnection->LaunchBlockingQueryL();
       
   575                 // For incoming pairing, blocking is asked after rejecting the 
       
   576                 // pairing request. This is done in CompleteAcceptPairingQueryL
       
   577                 }
       
   578             CompleteBondingL( err );    // Notify the client if there was a bonding request.
       
   579             }
       
   580         }
       
   581     iNotifierUid = 0;   // Clean up notifier data
       
   582     delete iParams;
       
   583     iParams = NULL;
       
   584     if( err )
       
   585         {
       
   586         iOperation = EIdle; // We are done now.
       
   587         }
       
   588     // Complete the message with the result, and result data if any.
       
   589     iConnection->CompleteClientRequest( err, resultData );
       
   590     BOstraceFunctionExit1( DUMMY_DEVLIST, this );
       
   591     }
       
   592 
       
   593 
       
   594 // ---------------------------------------------------------------------------
       
   595 // Completes a bonding operation.
       
   596 // ---------------------------------------------------------------------------
       
   597 //
       
   598 void CBTNotifPairingHelper::CompleteBondingL( TInt aError )
       
   599     {
       
   600     BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aError );
       
   601     if( iDedicatedBonding )
       
   602         {
       
   603         if( iBondingActive )
       
   604             {
       
   605             iBondingActive->Cancel();   // Will close subsession;
       
   606             }
       
   607         iBondingSession.Close();    // In case not active
       
   608         iBondingSocket.Close();
       
   609         }
       
   610     // Determine if we try another time.
       
   611     if( ( iOperation == EAutoPairing && aError == KHCIErrorBase - EAuthenticationFailure ) ||
       
   612         ( iDedicatedBonding && iOperation == EAwaitingPairingResult &&
       
   613           aError == KErrRemoteDeviceIndicatedNoBonding ) ||
       
   614         aError == KErrServerTerminated )
       
   615         {
       
   616         // The cases are: 2) autopairing with a headset that has a non-default passkey
       
   617         // 2) SSP dedicated bonding with a device that does not allow that.
       
   618         // 3) the pairing server is unavailable (unlikely)
       
   619         // Then we try another time, requesting authentication on a 
       
   620         // RBTPhysicialLinkAdapter
       
   621         BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST,  
       
   622                 "[BTNOTIF]\t CBTNotifPairingHelper::CompleteBondingL: trying another time." );
       
   623         TInt err = iBondingSocket.Open( iTracker->SocketServerSession(), iConnection->Address() );
       
   624         TUint32 linkState = 0;
       
   625         if( !err )
       
   626             {
       
   627             err = iBondingSocket.PhysicalLinkState( linkState );
       
   628             }
       
   629         if( !err && linkState & ENotifyPhysicalLinkUp )
       
   630             {
       
   631             err = iBondingSocket.Authenticate();
       
   632             // Now wait for the dialog and then the link state notification
       
   633             }
       
   634         else
       
   635             {
       
   636             // We need to wait for the link to come up. We wait until our
       
   637             // parent calls us again.
       
   638             iBondingSocket.Close();
       
   639             }
       
   640         if( err )
       
   641             {
       
   642             // Cannot continue, show the result to the user.
       
   643             BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST,  
       
   644                     "[BTNOTIF]\t CBTNotifPairingHelper::HandleAuthenticationCompleteL: pairing failed, complete message." );
       
   645             iOperation = EShowPairingFailure;
       
   646             PrepareNotificationL( TBluetoothDialogParams::ENote, EPairingFailure );
       
   647             }
       
   648         }
       
   649     if( iDedicatedBonding && iOperation != EAutoPairing )
       
   650         {
       
   651         BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST,      
       
   652                 "[BTNOTIF]\t CBTNotifPairingHelper::CompleteBondingL: complete message." );
       
   653         TInt err = iTracker->Server()->CompleteMessage( iDedicatedBonding, aError, KNullDesC8 );
       
   654         NOTIF_NOTHANDLED( !err )
       
   655         iDedicatedBonding = 0;
       
   656         }
       
   657     BOstraceFunctionExit1( DUMMY_DEVLIST, this );
       
   658     }
       
   659 
       
   660 
       
   661 // ---------------------------------------------------------------------------
       
   662 // 
       
   663 // ---------------------------------------------------------------------------
       
   664 //
       
   665 void CBTNotifPairingHelper::CompleteJustWorksProcessingL( TInt aError )
       
   666     {
       
   667     (void) aError;
       
   668     }
       
   669 
       
   670 
       
   671 // ---------------------------------------------------------------------------
       
   672 // Ask the user to allow incoming pairing.
       
   673 // ---------------------------------------------------------------------------
       
   674 //
       
   675 void CBTNotifPairingHelper::StartAcceptPairingQueryL()
       
   676     {
       
   677     iOperation = EAcceptPairing;
       
   678     PrepareNotificationL( TBluetoothDialogParams::EQuery, EIncomingPairing );
       
   679     // if rejected, the client message is completed in CompleteAcceptPairingQueryL
       
   680     }
       
   681 
       
   682 
       
   683 // ---------------------------------------------------------------------------
       
   684 // The user was asked to accept an incoming pairing. Process and proceed. 
       
   685 // ---------------------------------------------------------------------------
       
   686 //
       
   687 void CBTNotifPairingHelper::CompleteAcceptPairingQueryL( TInt aError, TBool aResult )
       
   688     {
       
   689     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   690     // Set our state to idle for now. This may get changed if the user just chose 
       
   691     // to block, or if we have a pending request.
       
   692     iOperation = EIdle;
       
   693     TInt err = aError;
       
   694     if( !err )
       
   695         {
       
   696         TBool proceed = iTracker->UpdateBlockingHistoryL( iDevice, aResult );
       
   697         if( aResult )
       
   698             {
       
   699             // User accepted, continue to show pairing query.
       
   700             // Minimum lenght does not apply, should only be set on outgoing pairing
       
   701             TBool locallyInitiated = EFalse;
       
   702             TBuf<8> numVal;
       
   703             TBluetoothDialogParams::TBTDialogType dialog = TBluetoothDialogParams::EInvalidDialog;
       
   704             TBTDialogResourceId resource = ENoResource;
       
   705             // Read the notifier parameters
       
   706             ParseNotifierReqParamsL( locallyInitiated, numVal, dialog, resource );
       
   707             __ASSERT_ALWAYS( resource != ENoResource, PanicServer( EBTNotifPanicBadState ) );
       
   708             PrepareNotificationL( dialog, resource );
       
   709             if( numVal.Length() )
       
   710                 {
       
   711                 TInt err = iNotification->SetData( TBluetoothDeviceDialog::EAdditionalDesc, numVal );
       
   712                 NOTIF_NOTHANDLED( !err )
       
   713                 }
       
   714             }
       
   715         else
       
   716             {
       
   717             err = KErrCancel;
       
   718             if( proceed )
       
   719                 {
       
   720                 // The user denied the connection, ask to block the device.
       
   721                 iConnection->LaunchBlockingQueryL();
       
   722                 }
       
   723             }
       
   724         }
       
   725     if( err )
       
   726         {
       
   727         // The user denied the connection, or something else prevented completion.
       
   728         CompletePairingNotifierL( err, EFalse, KNullDesC8 );
       
   729         }
       
   730     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   731     }
       
   732 
       
   733 
       
   734 // ---------------------------------------------------------------------------
       
   735 // Launch a dialog for setting the device as trusted.
       
   736 // ---------------------------------------------------------------------------
       
   737 //
       
   738 void CBTNotifPairingHelper::StartTrustedQueryL()
       
   739     {
       
   740     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   741     // Assume that the registry update has come through by now.
       
   742     iOperation = EQueryTrust;
       
   743     PrepareNotificationL( TBluetoothDialogParams::EQuery, ESetTrusted );
       
   744     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   745     }
       
   746 
       
   747 
       
   748 // ---------------------------------------------------------------------------
       
   749 // Process the user input for setting the device as trusted.
       
   750 // ---------------------------------------------------------------------------
       
   751 //
       
   752 void CBTNotifPairingHelper::CompleteTrustedQueryL( TInt aError, TBool aResult )
       
   753     {
       
   754     BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aError );
       
   755     BOstraceExt2( TRACE_DEBUG, DUMMY_DEVLIST, 
       
   756             "CBTNotifPairingHelper::CompleteTrustedQueryL() err=%d result=%d", aError, aResult );
       
   757     iOperation = EIdle; // We are done with pairing now.
       
   758     if( !aError && aResult )
       
   759         {
       
   760         // need to update pairing info from registry before writing trusted status
       
   761         iConnection->UpdateRegistryEntryL(true);
       
   762         }
       
   763     CompleteBondingL( KErrNone );   // Notify the client if there was a bonding request.
       
   764     BOstraceFunctionExit1( DUMMY_DEVLIST, this );
       
   765     }
       
   766 
       
   767 
       
   768 // ---------------------------------------------------------------------------
       
   769 // Parse the parameters of a request for pairing.
       
   770 // ---------------------------------------------------------------------------
       
   771 //
       
   772 void CBTNotifPairingHelper::ParseNotifierReqParamsL( TBool& aLocallyInitiated,
       
   773     TDes& aNumVal, TBluetoothDialogParams::TBTDialogType& aDialogType,
       
   774     TBTDialogResourceId& aResourceId )
       
   775     {
       
   776     // Determine the notifier type by the length of the parameter buffer
       
   777     if( iNotifierUid == KBTPinCodeEntryNotifierUid.iUid )
       
   778         {
       
   779         aNumVal.Zero();
       
   780         TUint minLen = 0;
       
   781         ParsePinCodeReqParamsL( aLocallyInitiated, minLen );
       
   782         if( minLen )
       
   783             {
       
   784             // Don't set zero to this buffer, the buffer length serves for this.
       
   785             aNumVal.Num( minLen );
       
   786             }
       
   787         aDialogType = TBluetoothDialogParams::EInput;
       
   788         aResourceId = EPinInput;
       
   789         if( iOperation != EAutoPairing )
       
   790             {
       
   791             iOperation = ELegacyPairing;
       
   792             }
       
   793         }
       
   794     else if( iNotifierUid == KBTNumericComparisonNotifierUid.iUid )
       
   795         {
       
   796         ParseNumericCompReqParamsL( aLocallyInitiated, aNumVal );
       
   797         aDialogType = TBluetoothDialogParams::EQuery;
       
   798         aResourceId = ENumericComparison;
       
   799         iOperation = ESspPairing;
       
   800         }
       
   801     else if( iNotifierUid == KBTPasskeyDisplayNotifierUid.iUid )
       
   802         {
       
   803         ParsePasskeyDisplayReqParamsL( aLocallyInitiated, aNumVal );
       
   804         aDialogType = TBluetoothDialogParams::EQuery;
       
   805         aResourceId = EPasskeyDisplay;
       
   806         iOperation = ESspPairing;
       
   807         }
       
   808     }
       
   809 
       
   810 
       
   811 // ---------------------------------------------------------------------------
       
   812 // Parse the parameters of a request for pairing using pin query.
       
   813 // ---------------------------------------------------------------------------
       
   814 //
       
   815 void CBTNotifPairingHelper::ParsePinCodeReqParamsL( TBool& aLocallyInitiated,
       
   816     TUint& aNumVal )
       
   817     {
       
   818     TBTPinCodeEntryNotifierParams params;
       
   819     TPckgC<TBTPinCodeEntryNotifierParams> paramsPckg( params );
       
   820     paramsPckg.Set( *iParams );
       
   821     aLocallyInitiated = paramsPckg().LocallyInitiated();
       
   822     aNumVal = paramsPckg().PinCodeMinLength();
       
   823     }
       
   824 
       
   825 
       
   826 // ---------------------------------------------------------------------------
       
   827 // Parse the parameters of a request for pairing using numeric comparison.
       
   828 // ---------------------------------------------------------------------------
       
   829 //
       
   830 void CBTNotifPairingHelper::ParseNumericCompReqParamsL( TBool& aLocallyInitiated,
       
   831     TDes& aNumVal )
       
   832     {
       
   833     TBTNumericComparisonParams params;
       
   834     TPckgC<TBTNumericComparisonParams> paramsPckg( params );
       
   835     paramsPckg.Set( *iParams );
       
   836     aLocallyInitiated = paramsPckg().LocallyInitiated();
       
   837     TBTNumericComparisonParams::TComparisonScenario scenario =
       
   838                 paramsPckg().ComparisonScenario();
       
   839     aNumVal.Format( KNumCompFormat, paramsPckg().NumericalValue() );
       
   840     }
       
   841 
       
   842 
       
   843 // ---------------------------------------------------------------------------
       
   844 // Parse the parameters of a request for pairing using passkey display.
       
   845 // ---------------------------------------------------------------------------
       
   846 //
       
   847 void CBTNotifPairingHelper::ParsePasskeyDisplayReqParamsL( TBool& aLocallyInitiated,
       
   848     TDes& aNumVal )
       
   849     {
       
   850     TBTPasskeyDisplayParams params;
       
   851     TPckgC<TBTPasskeyDisplayParams> paramsPckg( params );
       
   852     paramsPckg.Set( *iParams );
       
   853     aLocallyInitiated = paramsPckg().LocallyInitiated();
       
   854     aNumVal.Format( KPassKeyFormat, paramsPckg().NumericalValue() );
       
   855     }
       
   856 
       
   857 
       
   858 // ---------------------------------------------------------------------------
       
   859 // Check if we can guess the PIN and complete the notifier without user interaction.
       
   860 // ---------------------------------------------------------------------------
       
   861 //
       
   862 void CBTNotifPairingHelper::CheckAutoPairingL( TBool aLocallyInitiated, const TDesC& aNumVal )
       
   863     {
       
   864     TUint minLen = 0;
       
   865     if( aNumVal.Length() )
       
   866         {
       
   867         ParsePinCodeReqParamsL( aLocallyInitiated, minLen );
       
   868         }
       
   869     // ToDo: Add support for NFC OOB pairing
       
   870     if( iDedicatedBonding && iOperation == ELegacyPairing &&
       
   871         iDevice->DeviceClass().MajorDeviceClass() == EMajorDeviceAV &&
       
   872         iDevice->DeviceClass().MinorDeviceClass() != EMinorDeviceAVHandsfree &&
       
   873         minLen <= KDefaultPinLength )
       
   874         {
       
   875         // Outgoing bonding with headset and no passkey requirement => AutomatedPairing
       
   876         // Complete message with 0000 and return.
       
   877         iOperation = EAutoPairing;
       
   878         TBuf8<KDefaultPinLength + sizeof( TPckgBuf<TBool> )> defaultPin( KDefaultPinLength );
       
   879         for( TInt i = 0; i < KDefaultPinLength; i++ )
       
   880             {
       
   881             defaultPin[i] = KDefaultPinValue;
       
   882             }
       
   883         // Complete the pairing through the function dedicated to that.
       
   884         CompletePairingNotifierL( KErrNone, ETrue, defaultPin );
       
   885         }
       
   886     else if( iOperation == EAutoPairing )
       
   887         {
       
   888         iOperation = ELegacyPairing;    // Reset the autopairing status
       
   889         }
       
   890     }
       
   891 
       
   892 
       
   893 // ---------------------------------------------------------------------------
       
   894 // Get and configure a notification.
       
   895 // ---------------------------------------------------------------------------
       
   896 //
       
   897 void CBTNotifPairingHelper::PrepareNotificationL( TBluetoothDialogParams::TBTDialogType aType,
       
   898     TBTDialogResourceId aResourceId )
       
   899     {
       
   900     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   901     __ASSERT_ALWAYS( iOperation != EIdle || aType == TBluetoothDialogParams::ENote, PanicServer( EBTNotifPanicBadState ) );
       
   902     iNotification = iTracker->NotificationManager()->GetNotification();
       
   903     User::LeaveIfNull( iNotification ); // For OOM exception, leaves with KErrNoMemory
       
   904     iNotification->SetObserver( this );
       
   905     iNotification->SetNotificationType( aType, aResourceId );
       
   906     TBTDeviceName name;
       
   907     GetDeviceNameL( name, *iDevice );
       
   908     TInt err = iNotification->SetData( TBluetoothDeviceDialog::EDeviceName, name );
       
   909     NOTIF_NOTHANDLED( !err )
       
   910     // Re-use name buffer for 16-bit descriptor representation of remote address.
       
   911     iConnection->Address().GetReadable( name );
       
   912     err = iNotification->SetData( TBluetoothDialogParams::EAddress, name );
       
   913     NOTIF_NOTHANDLED( !err )
       
   914     err = iNotification->SetData( (TInt) TBluetoothDeviceDialog::EDeviceClass,
       
   915                 iDevice->DeviceClass().DeviceClass() );
       
   916     err = iTracker->NotificationManager()->QueueNotification( iNotification );
       
   917     NOTIF_NOTHANDLED( !err )
       
   918     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   919     }
       
   920 
       
   921 
       
   922 // ---------------------------------------------------------------------------
       
   923 // The notification is finished, handle the result.
       
   924 // ---------------------------------------------------------------------------
       
   925 //
       
   926 void CBTNotifPairingHelper::NotificationClosedL( TInt aError, const TDesC8& aData )
       
   927     {
       
   928     BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aError );
       
   929     // Read the result.
       
   930     TPckgC<TBool> result( EFalse );
       
   931     result.Set( aData.Ptr(), result.Length() ); // Read the part containing the result
       
   932     // Set a pointer descriptor to capture the remaining data, if any.
       
   933     TPtrC8 dataPtr( aData.Mid( result.Length() ) );
       
   934     switch( iOperation )
       
   935         {
       
   936         case EAcceptPairing:
       
   937             CompleteAcceptPairingQueryL( aError, result() );
       
   938             break;
       
   939         case ELegacyPairing:
       
   940         case ESspPairing:
       
   941             CompletePairingNotifierL( aError, result(), dataPtr );
       
   942             break;
       
   943         case EQueryTrust:
       
   944             CompleteTrustedQueryL( aError, result() );
       
   945             break;
       
   946         case EShowPairingSuccess:
       
   947             StartTrustedQueryL();
       
   948             break;
       
   949         case EShowPairingFailure:
       
   950             // Pairing failure, we are done.
       
   951             iOperation = EIdle;
       
   952             break;
       
   953         default:
       
   954             NOTIF_NOTIMPL
       
   955             break;
       
   956         }
       
   957     BOstraceFunctionExit1( DUMMY_DEVLIST, this );
       
   958     }