bluetoothengine/btnotif/btnotifsrv/src/btnotifpairinghelper.cpp
changeset 19 43824b19ee35
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/btnotif/btnotifsrv/src/btnotifpairinghelper.cpp	Fri May 14 16:01:46 2010 +0300
@@ -0,0 +1,958 @@
+/*
+* ============================================================================
+*  Name        : btnotifpairinghelper.cpp
+*  Part of     : bluetoothengine / btnotif
+*  Description : Helper class for processing pairing requests and results, as extended functionality for CBTNotifConnection.
+*
+*  Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies).
+*  All rights reserved.
+*  This component and the accompanying materials are made available
+*  under the terms of "Eclipse Public License v1.0"
+*  which accompanies this distribution, and is available
+*  at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+*  Initial Contributors:
+*  Nokia Corporation - initial contribution.
+*
+*  Contributors:
+*  Nokia Corporation
+* ============================================================================
+* Template version: 4.1
+*/
+
+#include "btnotifpairinghelper.h"
+#include <bt_sock.h>
+#include <btextnotifiers.h>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <btextnotifierspartner.h>
+#endif
+
+#include "btnotifconnection.h"
+#include "btnotifconnectiontracker.h"
+#include "btnotificationmanager.h"
+#include "btnotifserver.h"
+#include "bluetoothtrace.h"
+
+/**  Id for the active object for a dedicated bonding session. */
+const TInt KDedicatedBonding = 50;
+/**  Length of the default PIN. */
+const TInt KDefaultPinLength = 4;
+/**  Default PIN character. */
+const TText8 KDefaultPinValue = '0';
+/**  Format syntax for numeric comparison value. */
+_LIT( KNumCompFormat, "%06u" );
+/**  Format syntax for passkey display value. */
+_LIT( KPassKeyFormat, "%06u" );
+
+
+// ======== LOCAL FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// ?description
+// ---------------------------------------------------------------------------
+//
+/*?type ?function_name( ?arg_type ?arg,
+                      ?arg_type ?arg )
+    {
+    }
+*/
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// C++ default constructor.
+// ---------------------------------------------------------------------------
+//
+CBTNotifPairingHelper::CBTNotifPairingHelper( CBTNotifConnection* aConnection,
+    CBTNotifConnectionTracker* aTracker )
+:   iConnection( aConnection ),
+    iTracker( aTracker )
+    {
+    }
+
+
+// ---------------------------------------------------------------------------
+// Symbian 2nd-phase constructor.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::ConstructL()
+    {
+    if( iConnection )
+        {
+        iDevice = iConnection->BTDevice();
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// NewL
+// ---------------------------------------------------------------------------
+//
+CBTNotifPairingHelper* CBTNotifPairingHelper::NewL( CBTNotifConnection* aConnection,
+    CBTNotifConnectionTracker* aTracker )
+    {
+    BOstraceFunctionEntry0( DUMMY_DEVLIST );
+    CBTNotifPairingHelper* self = new( ELeave ) CBTNotifPairingHelper( aConnection, aTracker );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    BOstraceFunctionExit0( DUMMY_DEVLIST );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CBTNotifPairingHelper::~CBTNotifPairingHelper()
+    {
+    BOstraceFunctionEntry0( DUMMY_DEVLIST );
+    if( iNotification )
+        {
+        // Clear the notification callback, we cannot receive them anymore.
+        iNotification->RemoveObserver();
+        iNotification->Close(); // Also dequeues the notification from the queue.
+        iNotification = NULL;
+        }
+    delete iParams;
+    if( iBondingActive )
+        {
+        iBondingActive->Cancel();   // Will close subsession;
+        }
+    delete iBondingActive;
+    iBondingSession.Close();
+    iBondingSocket.Close();
+    BOstraceFunctionExit0( DUMMY_DEVLIST );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Handle the authentication result from the baseband. Show the result in a note.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::HandleAuthenticationCompleteL( TInt aError )
+    {
+    BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aError );
+    if( iOperation == EDedicatedBonding || iOperation == EAwaitingPairingResult ||
+        iOperation == EAutoPairing )
+        {
+        // Default case (aError == 0): Success, we are now paired.
+        TBTDialogResourceId resourceId = EPairingSuccess;
+        TBool autoPairing = ( iOperation == EAutoPairing ); // Remember the autopairing state
+        iOperation = EShowPairingSuccess;
+        if( aError && aError != KHCIErrorBase )
+            {
+            // Authentication failure, means pairing failed.
+            resourceId = EPairingFailure;
+            iOperation = EShowPairingFailure;
+            // Communicate the error now that we still remember it.
+            if( iDedicatedBonding )
+                {
+                if( autoPairing && aError == KHCIErrorBase - EAuthenticationFailure )
+                    {
+                    BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST, 
+                            "[BTNOTIF]\t CBTNotifPairingHelper::HandleAuthenticationCompleteL: Autopairing failed, we need to try again.");
+                    // Autopairing failed, we need to try again.
+                    iOperation = EAutoPairing;  // Reset back
+                    resourceId = ENoResource;
+                    }
+                CompleteBondingL( aError );
+                }
+            }
+        if( resourceId )
+            {
+            // Inform the user of the result.
+            BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST,  
+                    "[BTNOTIF]\t CBTNotifPairingHelper::HandleAuthenticationCompleteL: pairing successful, inform user" );
+            PrepareNotificationL( TBluetoothDialogParams::EGlobalNotif, resourceId );
+            // MBRNotificationClosed will be called from this, which will 
+            // check the next stage.
+            }
+        }
+    BOstraceFunctionExit1( DUMMY_DEVLIST, this );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Start a bonding operation with the remote device.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::StartBondingL( TInt aHandle )
+    {
+    BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aHandle );
+    __ASSERT_ALWAYS( iOperation == EIdle || iOperation == EDedicatedBonding
+                || iOperation == EAutoPairing, PanicServer( EBTNotifPanicBadState ) );
+    if( !iBondingActive )
+        {
+        iBondingActive = CBtSimpleActive::NewL( *this, KDedicatedBonding );
+        }
+    if( aHandle )
+        {
+        iDedicatedBonding = aHandle;
+        }
+    if( iOperation == EIdle )
+        {
+        iOperation = EDedicatedBonding;
+        }
+    if( iOperation == EDedicatedBonding && iTracker->PairingServerSession() )
+        {
+        if( !iBondingActive->IsActive() )
+            {
+            BtTraceBtAddr1( TRACE_DEBUG,DUMMY_LIST,"CBTNotifPairingHelper::StartBondingL()",iDevice->BDAddr() );
+            iBondingSession.Start( *iTracker->PairingServerSession(),
+                        iDevice->BDAddr(), iBondingActive->RequestStatus() );
+            iBondingActive->GoActive();
+            }
+        }
+    else
+        {
+        // We are doing autopairing (or the unlikely situation that the pairing server is unavailable)
+        CompleteBondingL( KErrServerTerminated );
+        }
+    BOstraceFunctionExit1( DUMMY_DEVLIST, this);
+    }
+
+
+// ---------------------------------------------------------------------------
+// Cancel an ongoing bonding operation with the remote device.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::CancelBondingL()
+    {
+    BOstraceFunctionEntry0( DUMMY_DEVLIST );
+    if( iDedicatedBonding )
+        {
+        CompleteBondingL( KErrCancel ); // Closes sessions
+        if( iNotification )
+            {
+            // Cancel the outstanding user query
+            // This will also unregister us from the notification.
+            TInt err = iNotification->Close();
+            NOTIF_NOTHANDLED( !err )
+            iNotification = NULL;
+            }
+        if( iNotifierUid )
+            {
+            // Also finish up the notifier processing.
+            CompletePairingNotifierL( KErrCancel, EFalse, KNullDesC8 );
+            }
+        iOperation = EIdle;
+        iConnection->PairingCompleted();   // This may delete us.
+        }
+    BOstraceFunctionExit0( DUMMY_DEVLIST );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Handle a notifier request for pairing with the remote device of this connection.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::StartPairingNotifierL( TInt aUid, const TDesC8& aParams )
+    {
+    BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aUid );
+    if( iDevice->GlobalSecurity().Banned() && !iDedicatedBonding )
+        {
+        // ToDo: should this case actually be ignored, and presume that
+        // the caller will take care of unblocking the device?
+        iOperation = EIdle;
+        User::Leave( KErrAccessDenied );
+        }
+    // Store the parameters locally, we need them later again.
+    delete iParams;
+    iParams = NULL;
+    iParams = HBufC8::NewL( aParams.Length() );
+    *iParams = aParams;
+    iNotifierUid = aUid;
+
+    if( iDevice->IsValidPaired() && iDevice->IsPaired() )
+        {
+        // The device is still paired, we unpair it first.
+        // Deleting the link key will set the device as unpaired.
+        iDevice->DeleteLinkKey();
+        iOperation = EUnpairing;    // So that parent state does not get changed.
+        iConnection->UpdateRegistryEntryL();
+        // Note that this will only be done before trying autopairing, so
+        // it not interfere with a second attempt;
+        }
+    // Update the device name
+    TBTPasskeyDisplayParams params; // Enough for reading the base class type parameter
+    TPckgC<TBTPasskeyDisplayParams> paramsPckg( params );
+    paramsPckg.Set( *iParams );
+    if( paramsPckg().DeviceName().Length() )
+        {
+        // The name in the parameter package is the latest one, retrieved from 
+        // the remote device during this connection. Update locally.
+        iDevice->SetDeviceNameL( BTDeviceNameConverter::ToUTF8L( paramsPckg().DeviceName() ) );
+        }
+
+    TBool locallyInitiated = EFalse;
+    TBuf<8> numVal;
+    TBluetoothDialogParams::TBTDialogType dialog = TBluetoothDialogParams::EInvalidDialog;
+    TBTDialogResourceId resource = ENoResource;
+    // Read the notifier parameters (sets iOperation as well)
+    ParseNotifierReqParamsL( locallyInitiated, numVal, dialog, resource );
+    // If this is an incoming pairing, we first ask the user to accept it.
+    if( !locallyInitiated && !iDedicatedBonding )
+        {
+        // Ignore the initatior if we initiated bonding.
+        StartAcceptPairingQueryL(); // Overrides iOperation
+        }
+    else
+        {
+        __ASSERT_ALWAYS( resource != ENoResource, PanicServer( EBTNotifPanicBadState ) );
+        CheckAutoPairingL( locallyInitiated, numVal );
+        // CheckAutoPairingL sets 
+        if( iOperation != EAutoPairing )
+            {
+            PrepareNotificationL( dialog, resource );
+            if( numVal.Length() )
+                {
+                TInt err = iNotification->SetData( TBluetoothDeviceDialog::EAdditionalDesc, numVal );
+                NOTIF_NOTHANDLED( !err )
+                }
+            }
+        }
+    BOstraceFunctionExit1( DUMMY_DEVLIST, this );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Update a notifier, update the outstanding dialog if the notifier request 
+// is currently being served.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::UpdatePairingNotifierL( TInt aUid, const TDesC8& aParams )
+    {
+    (void) aUid;
+    TBTNotifierUpdateParams2 params;    // Enough for reading the base class type parameter
+    TPckgC<TBTNotifierUpdateParams2> paramsPckg( params );
+    paramsPckg.Set( aParams );
+    if( paramsPckg().Type() == TBTNotifierUpdateParams2::EPasskeyDisplay )
+        {
+        // Paskey display update - keypress on remote device.
+        }
+    else
+        {
+        // name update
+        TBTDeviceNameUpdateParams nameUpdate;
+        TPckgC<TBTDeviceNameUpdateParams> nameUpdatePckg( nameUpdate );
+        nameUpdatePckg.Set( aParams );
+        // The result means result of conversion to unicode
+        if( !nameUpdatePckg().Result() )
+            {
+            // Only update locally, registry will update us with the same info later on.
+            iDevice->SetDeviceNameL( BTDeviceNameConverter::ToUTF8L( nameUpdatePckg().DeviceName() ) );
+            if( iNotification )
+                {
+                // Update the dialog with the new name. It is up to the dialog to 
+                // determine the validity (in case another dialog is shown).
+                //iNotification->Update(  )
+                }
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Cancel a request, dismiss the outstanding dialog if the notifier request 
+// is currently being served.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::CancelPairingNotifierL( TInt aUid )
+    {
+    BOstraceFunctionEntry0( DUMMY_DEVLIST );
+    // ToDo: we need to check that the UID and the outstanding notification
+    // type are matching?
+    if( iOperation > EIdle && iOperation < EPostPairingOperations && aUid == iNotifierUid &&
+        ( aUid == KBTPinCodeEntryNotifierUid.iUid ||
+          aUid == KBTNumericComparisonNotifierUid.iUid ||
+          aUid == KBTPasskeyDisplayNotifierUid.iUid ) )
+        {
+        if( iNotification )
+            {
+            // Cancel the user query
+            // This will also unregister us from the notification.
+            TInt err = iNotification->Close();
+            NOTIF_NOTHANDLED( !err )
+            iNotification = NULL;
+            }
+        iOperation = EIdle;
+        iNotifierUid = 0;
+        // We do not call pairing completed from here, our parent will
+        // check our status by itself, and may delete us.
+
+        // Any bonding requester needs to be informed though.
+        CancelBondingL();
+        }
+    BOstraceFunctionExit0( DUMMY_DEVLIST );
+    }
+
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::StartJustWorksProcessingL()
+    {
+    }
+
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::CancelJustWorksProcessingL()
+    {
+    }
+
+
+// ---------------------------------------------------------------------------
+// From class MBTNotificationResult.
+// Handle a result from a user query.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::MBRDataReceived( CHbSymbianVariantMap& aData )
+    {
+    (void) aData;
+    NOTIF_NOTIMPL
+    }
+
+
+// ---------------------------------------------------------------------------
+// From class MBTNotificationResult.
+// The notification is finished.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::MBRNotificationClosed( TInt aError, const TDesC8& aData )
+    {
+    BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aError );
+    // First unregister from the notification, so we can already get the next one.
+    iNotification->RemoveObserver();
+    iNotification = NULL;
+    TRAP_IGNORE( NotificationClosedL( aError, aData ) );
+    if( iOperation == EIdle )
+        {
+        // Any error has been communicated already.
+        iConnection->PairingCompleted();   // This may delete us.
+        }
+    BOstraceFunctionExit1( DUMMY_DEVLIST, this );
+    }
+
+
+// ---------------------------------------------------------------------------
+// From class MBtSimpleActiveObserver.
+// Handle the active object completion.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::RequestCompletedL( CBtSimpleActive* aActive,
+    TInt aStatus )
+    {
+    BOstraceFunctionEntry0( DUMMY_DEVLIST );
+    switch( aActive->RequestId() )
+        {
+        case KDedicatedBonding:
+            {
+            if( iDedicatedBonding )
+                {
+                // If the result hasn't been processed already.
+                HandleAuthenticationCompleteL( aStatus );
+                }
+            }
+            break;
+        default:
+            NOTIF_NOTIMPL
+            break;
+        }
+    BOstraceFunctionExit0( DUMMY_DEVLIST );
+    }
+
+
+// ---------------------------------------------------------------------------
+// From class MBtSimpleActiveObserver.
+// Cancel and clean up all requests related to the active object.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::CancelRequest( TInt aRequestId )
+    {
+    BOstraceFunctionEntry0( DUMMY_DEVLIST );
+    switch( aRequestId )
+        {
+        case KDedicatedBonding:
+            iBondingSession.Close();
+            break;
+        default:
+            NOTIF_NOTIMPL
+            break;
+        }
+    BOstraceFunctionExit0( DUMMY_DEVLIST );
+    }
+
+// ---------------------------------------------------------------------------
+// From class MBtSimpleActiveObserver.
+// 
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::HandleError( CBtSimpleActive* aActive, 
+        TInt aError )
+    {
+    (void) aActive;
+    (void) aError;
+    }
+
+// ---------------------------------------------------------------------------
+// Process the user input and complete the outstanding pairing request.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::CompletePairingNotifierL( TInt aError, TBool aResult,
+    const TDesC8& aData )
+    {
+    BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aError );
+    TInt err = aError;
+    TPtrC8 resultData;
+    if( !err )
+        {
+        // The returned data is the entered passkey.
+        TBool proceed = iTracker->UpdateBlockingHistoryL( iDevice, aResult );
+        if( iOperation == ESspPairing && iNotifierUid == KBTNumericComparisonNotifierUid.iUid )
+            {
+            // Numeric comparison needs the boolean result passed back.
+            TPckgBuf<TBool> userAcceptance( aResult );
+            resultData.Set( userAcceptance );
+            }
+        if( aResult )
+            {
+            if( iOperation == ELegacyPairing || iOperation == EAutoPairing )
+                {
+                // Check the passkey entered by the user.
+                // The length of the returned data equals the number of characters
+                // entered by the user.
+                TBTPinCode pinCode;
+                pinCode().iLength = aData.Length();
+                TUint minLen = 0;
+                TBool locallyInitiated = EFalse; // Not used here.
+                ParsePinCodeReqParamsL( locallyInitiated, minLen );
+                if( aData.Length() >= minLen )
+                    {
+                    // Check that the length of the passkey meets the minimum 
+                    // required pin code length
+                    for( TInt i = 0; i < aData.Length(); i++ )
+                        {
+                        pinCode().iPIN[i] = aData[i];
+                        }
+                    resultData.Set( pinCode );
+                    }
+                else
+                    {
+                    // PIN wasn't long enough. This should be handled by the dialog though.
+                    err = KErrCompletion;
+                    }
+                }
+            // Now we just wait for the result to come in.
+            if( iOperation != EAutoPairing )
+                {
+                iOperation = EAwaitingPairingResult; 
+                }
+            }
+        else
+            {
+            err = KErrCancel;
+            TBool locallyInitiated = EFalse;    // Needed below
+            TBuf<8> numVal;     // Not needed here.
+            TBluetoothDialogParams::TBTDialogType type = TBluetoothDialogParams::EInvalidDialog;
+            TBTDialogResourceId resource = ENoResource; // Resources and type are not needed here.
+            // Check the notifier parameters
+            ParseNotifierReqParamsL( locallyInitiated, numVal, type, resource );
+            if( proceed && locallyInitiated && !iDedicatedBonding )
+                {
+                // The user denied the connection, ask to block the device.
+                // This is only for pairing (and not bonding) initiated by us,
+                // as the user already gets the opportunity to block when
+                // rejecting an incoming pairing request.
+                // This case may be for someone requesting to access a service
+                // which requires authentication by us, but not by the remote device.
+                iConnection->LaunchBlockingQueryL();
+                // For incoming pairing, blocking is asked after rejecting the 
+                // pairing request. This is done in CompleteAcceptPairingQueryL
+                }
+            CompleteBondingL( err );    // Notify the client if there was a bonding request.
+            }
+        }
+    iNotifierUid = 0;   // Clean up notifier data
+    delete iParams;
+    iParams = NULL;
+    if( err )
+        {
+        iOperation = EIdle; // We are done now.
+        }
+    // Complete the message with the result, and result data if any.
+    iConnection->CompleteClientRequest( err, resultData );
+    BOstraceFunctionExit1( DUMMY_DEVLIST, this );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Completes a bonding operation.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::CompleteBondingL( TInt aError )
+    {
+    BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aError );
+    if( iDedicatedBonding )
+        {
+        if( iBondingActive )
+            {
+            iBondingActive->Cancel();   // Will close subsession;
+            }
+        iBondingSession.Close();    // In case not active
+        iBondingSocket.Close();
+        }
+    // Determine if we try another time.
+    if( ( iOperation == EAutoPairing && aError == KHCIErrorBase - EAuthenticationFailure ) ||
+        ( iDedicatedBonding && iOperation == EAwaitingPairingResult &&
+          aError == KErrRemoteDeviceIndicatedNoBonding ) ||
+        aError == KErrServerTerminated )
+        {
+        // The cases are: 2) autopairing with a headset that has a non-default passkey
+        // 2) SSP dedicated bonding with a device that does not allow that.
+        // 3) the pairing server is unavailable (unlikely)
+        // Then we try another time, requesting authentication on a 
+        // RBTPhysicialLinkAdapter
+        BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST,  
+                "[BTNOTIF]\t CBTNotifPairingHelper::CompleteBondingL: trying another time." );
+        TInt err = iBondingSocket.Open( iTracker->SocketServerSession(), iConnection->Address() );
+        TUint32 linkState = 0;
+        if( !err )
+            {
+            err = iBondingSocket.PhysicalLinkState( linkState );
+            }
+        if( !err && linkState & ENotifyPhysicalLinkUp )
+            {
+            err = iBondingSocket.Authenticate();
+            // Now wait for the dialog and then the link state notification
+            }
+        else
+            {
+            // We need to wait for the link to come up. We wait until our
+            // parent calls us again.
+            iBondingSocket.Close();
+            }
+        if( err )
+            {
+            // Cannot continue, show the result to the user.
+            BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST,  
+                    "[BTNOTIF]\t CBTNotifPairingHelper::HandleAuthenticationCompleteL: pairing failed, complete message." );
+            iOperation = EShowPairingFailure;
+            PrepareNotificationL( TBluetoothDialogParams::ENote, EPairingFailure );
+            }
+        }
+    if( iDedicatedBonding && iOperation != EAutoPairing )
+        {
+        BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST,      
+                "[BTNOTIF]\t CBTNotifPairingHelper::CompleteBondingL: complete message." );
+        TInt err = iTracker->Server()->CompleteMessage( iDedicatedBonding, aError, KNullDesC8 );
+        NOTIF_NOTHANDLED( !err )
+        iDedicatedBonding = 0;
+        }
+    BOstraceFunctionExit1( DUMMY_DEVLIST, this );
+    }
+
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::CompleteJustWorksProcessingL( TInt aError )
+    {
+    (void) aError;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Ask the user to allow incoming pairing.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::StartAcceptPairingQueryL()
+    {
+    iOperation = EAcceptPairing;
+    PrepareNotificationL( TBluetoothDialogParams::EQuery, EIncomingPairing );
+    // if rejected, the client message is completed in CompleteAcceptPairingQueryL
+    }
+
+
+// ---------------------------------------------------------------------------
+// The user was asked to accept an incoming pairing. Process and proceed. 
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::CompleteAcceptPairingQueryL( TInt aError, TBool aResult )
+    {
+    BOstraceFunctionEntry0( DUMMY_DEVLIST );
+    // Set our state to idle for now. This may get changed if the user just chose 
+    // to block, or if we have a pending request.
+    iOperation = EIdle;
+    TInt err = aError;
+    if( !err )
+        {
+        TBool proceed = iTracker->UpdateBlockingHistoryL( iDevice, aResult );
+        if( aResult )
+            {
+            // User accepted, continue to show pairing query.
+            // Minimum lenght does not apply, should only be set on outgoing pairing
+            TBool locallyInitiated = EFalse;
+            TBuf<8> numVal;
+            TBluetoothDialogParams::TBTDialogType dialog = TBluetoothDialogParams::EInvalidDialog;
+            TBTDialogResourceId resource = ENoResource;
+            // Read the notifier parameters
+            ParseNotifierReqParamsL( locallyInitiated, numVal, dialog, resource );
+            __ASSERT_ALWAYS( resource != ENoResource, PanicServer( EBTNotifPanicBadState ) );
+            PrepareNotificationL( dialog, resource );
+            if( numVal.Length() )
+                {
+                TInt err = iNotification->SetData( TBluetoothDeviceDialog::EAdditionalDesc, numVal );
+                NOTIF_NOTHANDLED( !err )
+                }
+            }
+        else
+            {
+            err = KErrCancel;
+            if( proceed )
+                {
+                // The user denied the connection, ask to block the device.
+                iConnection->LaunchBlockingQueryL();
+                }
+            }
+        }
+    if( err )
+        {
+        // The user denied the connection, or something else prevented completion.
+        CompletePairingNotifierL( err, EFalse, KNullDesC8 );
+        }
+    BOstraceFunctionExit0( DUMMY_DEVLIST );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Launch a dialog for setting the device as trusted.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::StartTrustedQueryL()
+    {
+    BOstraceFunctionEntry0( DUMMY_DEVLIST );
+    // Assume that the registry update has come through by now.
+    iOperation = EQueryTrust;
+    PrepareNotificationL( TBluetoothDialogParams::EQuery, ESetTrusted );
+    BOstraceFunctionExit0( DUMMY_DEVLIST );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Process the user input for setting the device as trusted.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::CompleteTrustedQueryL( TInt aError, TBool aResult )
+    {
+    BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aError );
+    BOstraceExt2( TRACE_DEBUG, DUMMY_DEVLIST, 
+            "CBTNotifPairingHelper::CompleteTrustedQueryL() err=%d result=%d", aError, aResult );
+    iOperation = EIdle; // We are done with pairing now.
+    if( !aError && aResult )
+        {
+        // need to update pairing info from registry before writing trusted status
+        iConnection->UpdateRegistryEntryL(true);
+        }
+    CompleteBondingL( KErrNone );   // Notify the client if there was a bonding request.
+    BOstraceFunctionExit1( DUMMY_DEVLIST, this );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Parse the parameters of a request for pairing.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::ParseNotifierReqParamsL( TBool& aLocallyInitiated,
+    TDes& aNumVal, TBluetoothDialogParams::TBTDialogType& aDialogType,
+    TBTDialogResourceId& aResourceId )
+    {
+    // Determine the notifier type by the length of the parameter buffer
+    if( iNotifierUid == KBTPinCodeEntryNotifierUid.iUid )
+        {
+        aNumVal.Zero();
+        TUint minLen = 0;
+        ParsePinCodeReqParamsL( aLocallyInitiated, minLen );
+        if( minLen )
+            {
+            // Don't set zero to this buffer, the buffer length serves for this.
+            aNumVal.Num( minLen );
+            }
+        aDialogType = TBluetoothDialogParams::EInput;
+        aResourceId = EPinInput;
+        if( iOperation != EAutoPairing )
+            {
+            iOperation = ELegacyPairing;
+            }
+        }
+    else if( iNotifierUid == KBTNumericComparisonNotifierUid.iUid )
+        {
+        ParseNumericCompReqParamsL( aLocallyInitiated, aNumVal );
+        aDialogType = TBluetoothDialogParams::EQuery;
+        aResourceId = ENumericComparison;
+        iOperation = ESspPairing;
+        }
+    else if( iNotifierUid == KBTPasskeyDisplayNotifierUid.iUid )
+        {
+        ParsePasskeyDisplayReqParamsL( aLocallyInitiated, aNumVal );
+        aDialogType = TBluetoothDialogParams::EQuery;
+        aResourceId = EPasskeyDisplay;
+        iOperation = ESspPairing;
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Parse the parameters of a request for pairing using pin query.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::ParsePinCodeReqParamsL( TBool& aLocallyInitiated,
+    TUint& aNumVal )
+    {
+    TBTPinCodeEntryNotifierParams params;
+    TPckgC<TBTPinCodeEntryNotifierParams> paramsPckg( params );
+    paramsPckg.Set( *iParams );
+    aLocallyInitiated = paramsPckg().LocallyInitiated();
+    aNumVal = paramsPckg().PinCodeMinLength();
+    }
+
+
+// ---------------------------------------------------------------------------
+// Parse the parameters of a request for pairing using numeric comparison.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::ParseNumericCompReqParamsL( TBool& aLocallyInitiated,
+    TDes& aNumVal )
+    {
+    TBTNumericComparisonParams params;
+    TPckgC<TBTNumericComparisonParams> paramsPckg( params );
+    paramsPckg.Set( *iParams );
+    aLocallyInitiated = paramsPckg().LocallyInitiated();
+    TBTNumericComparisonParams::TComparisonScenario scenario =
+                paramsPckg().ComparisonScenario();
+    aNumVal.Format( KNumCompFormat, paramsPckg().NumericalValue() );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Parse the parameters of a request for pairing using passkey display.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::ParsePasskeyDisplayReqParamsL( TBool& aLocallyInitiated,
+    TDes& aNumVal )
+    {
+    TBTPasskeyDisplayParams params;
+    TPckgC<TBTPasskeyDisplayParams> paramsPckg( params );
+    paramsPckg.Set( *iParams );
+    aLocallyInitiated = paramsPckg().LocallyInitiated();
+    aNumVal.Format( KPassKeyFormat, paramsPckg().NumericalValue() );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Check if we can guess the PIN and complete the notifier without user interaction.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::CheckAutoPairingL( TBool aLocallyInitiated, const TDesC& aNumVal )
+    {
+    TUint minLen = 0;
+    if( aNumVal.Length() )
+        {
+        ParsePinCodeReqParamsL( aLocallyInitiated, minLen );
+        }
+    // ToDo: Add support for NFC OOB pairing
+    if( iDedicatedBonding && iOperation == ELegacyPairing &&
+        iDevice->DeviceClass().MajorDeviceClass() == EMajorDeviceAV &&
+        iDevice->DeviceClass().MinorDeviceClass() != EMinorDeviceAVHandsfree &&
+        minLen <= KDefaultPinLength )
+        {
+        // Outgoing bonding with headset and no passkey requirement => AutomatedPairing
+        // Complete message with 0000 and return.
+        iOperation = EAutoPairing;
+        TBuf8<KDefaultPinLength + sizeof( TPckgBuf<TBool> )> defaultPin( KDefaultPinLength );
+        for( TInt i = 0; i < KDefaultPinLength; i++ )
+            {
+            defaultPin[i] = KDefaultPinValue;
+            }
+        // Complete the pairing through the function dedicated to that.
+        CompletePairingNotifierL( KErrNone, ETrue, defaultPin );
+        }
+    else if( iOperation == EAutoPairing )
+        {
+        iOperation = ELegacyPairing;    // Reset the autopairing status
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Get and configure a notification.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::PrepareNotificationL( TBluetoothDialogParams::TBTDialogType aType,
+    TBTDialogResourceId aResourceId )
+    {
+    BOstraceFunctionEntry0( DUMMY_DEVLIST );
+    __ASSERT_ALWAYS( iOperation != EIdle || aType == TBluetoothDialogParams::ENote, PanicServer( EBTNotifPanicBadState ) );
+    iNotification = iTracker->NotificationManager()->GetNotification();
+    User::LeaveIfNull( iNotification ); // For OOM exception, leaves with KErrNoMemory
+    iNotification->SetObserver( this );
+    iNotification->SetNotificationType( aType, aResourceId );
+    TBTDeviceName name;
+    GetDeviceNameL( name, *iDevice );
+    TInt err = iNotification->SetData( TBluetoothDeviceDialog::EDeviceName, name );
+    NOTIF_NOTHANDLED( !err )
+    // Re-use name buffer for 16-bit descriptor representation of remote address.
+    iConnection->Address().GetReadable( name );
+    err = iNotification->SetData( TBluetoothDialogParams::EAddress, name );
+    NOTIF_NOTHANDLED( !err )
+    err = iNotification->SetData( (TInt) TBluetoothDeviceDialog::EDeviceClass,
+                iDevice->DeviceClass().DeviceClass() );
+    err = iTracker->NotificationManager()->QueueNotification( iNotification );
+    NOTIF_NOTHANDLED( !err )
+    BOstraceFunctionExit0( DUMMY_DEVLIST );
+    }
+
+
+// ---------------------------------------------------------------------------
+// The notification is finished, handle the result.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifPairingHelper::NotificationClosedL( TInt aError, const TDesC8& aData )
+    {
+    BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aError );
+    // Read the result.
+    TPckgC<TBool> result( EFalse );
+    result.Set( aData.Ptr(), result.Length() ); // Read the part containing the result
+    // Set a pointer descriptor to capture the remaining data, if any.
+    TPtrC8 dataPtr( aData.Mid( result.Length() ) );
+    switch( iOperation )
+        {
+        case EAcceptPairing:
+            CompleteAcceptPairingQueryL( aError, result() );
+            break;
+        case ELegacyPairing:
+        case ESspPairing:
+            CompletePairingNotifierL( aError, result(), dataPtr );
+            break;
+        case EQueryTrust:
+            CompleteTrustedQueryL( aError, result() );
+            break;
+        case EShowPairingSuccess:
+            StartTrustedQueryL();
+            break;
+        case EShowPairingFailure:
+            // Pairing failure, we are done.
+            iOperation = EIdle;
+            break;
+        default:
+            NOTIF_NOTIMPL
+            break;
+        }
+    BOstraceFunctionExit1( DUMMY_DEVLIST, this );
+    }