--- a/bluetoothengine/btnotif/btnotifsrv/src/btnotifoutgoingpairinghandler.cpp Tue Aug 31 15:25:10 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,553 +0,0 @@
-/*
-* Copyright (c) 2010 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:
-*
-* Description: Pairing handler for local device initiated pairing
-*
-*/
-
-#include "btnotifoutgoingpairinghandler.h"
-#include <btengconstants.h>
-#include <btservices/btdevextension.h>
-#include "btnotifsecuritymanager.h"
-#include "bluetoothtrace.h"
-#include "bluetoothnotification.h"
-#include "btnotifserver.h"
-#include "btnotifconnectiontracker.h"
-#include "btnotificationmanager.h"
-
-/** Length of the default PIN. */
-const TInt KDefaultHeadsetPinLength = 4;
-
-/** Maximum repeated outgoing pairing attempt.
- * if the pairing fails the UI specs says
- * we can ask twice the user if he/she want
- * to retry pairing.
- */
-const TInt KMaxRepeatedPairingAttempt = 2;
-
-enum TPairingStageId
- {
- /**
- * no pairing operation ongoing
- */
- ENoBonding = 0,
-
- /**
- * pair with dedicated bonding method
- */
- EDedicatedBonding = 200,
-
- /**
- * pair with general bonding by establishing L2CAP connection.
- */
- EGeneralBonding,
-
- /**
- * delaying next pairing request for a while
- */
- EGeneralBondingRetryTimer,
-
- /**
- * The last pairing retry
- */
- EGeneralBondingRetry,
-
- /**
- * disconnecting physical link after pairing operation.
- *
- * todo: not used yet.
- */
- EDisconnectLinkAfterBonding,
- };
-
-/** SDP PSM (used for pairing) */
-const TInt KSDPPSM = 0x0001;
-
-// Delay time to void Repeated Attempts on pairing
-const TInt KGeneralBondingRetryDelayMicroSeconds = 5000000; // 5.0s
-
-// ======== MEMBER FUNCTIONS ========
-
-// ---------------------------------------------------------------------------
-// C++ default constructor
-// ---------------------------------------------------------------------------
-//
-CBTNotifOutgoingPairingHandler::CBTNotifOutgoingPairingHandler( CBTNotifSecurityManager& aParent, const TBTDevAddr& aAddr)
- : CBTNotifBasePairingHandler( aParent, aAddr )
- {
- }
-
-// ---------------------------------------------------------------------------
-// Symbian 2nd-phase constructor
-// ---------------------------------------------------------------------------
-//
-void CBTNotifOutgoingPairingHandler::ConstructL()
- {
- BaseConstructL();
- User::LeaveIfError( iTimer.CreateLocal() );
- iPairingAttempt = KMaxRepeatedPairingAttempt;
- }
-
-// ---------------------------------------------------------------------------
-// NewL
-// ---------------------------------------------------------------------------
-//
-CBTNotifBasePairingHandler* CBTNotifOutgoingPairingHandler::NewL( CBTNotifSecurityManager& aParent,
- const TBTDevAddr& aAddr )
- {
- CBTNotifOutgoingPairingHandler* self = new( ELeave ) CBTNotifOutgoingPairingHandler( aParent, aAddr );
- CleanupStack::PushL( self );
- self->ConstructL();
- CleanupStack::Pop( self );
- return self;
- }
-
-// ---------------------------------------------------------------------------
-// Destructor
-// ---------------------------------------------------------------------------
-//
-CBTNotifOutgoingPairingHandler::~CBTNotifOutgoingPairingHandler()
- {
- if ( iActive )
- {
- iActive->Cancel();
- }
- iBondingSession.Close();
- iSocket.Close();
- iTimer.Close();
- if( iNotification )
- {
- // Clear the notification callback, we cannot receive them anymore.
- iNotification->RemoveObserver();
- iNotification->Close(); // Also dequeues the notification from the queue.
- iNotification = NULL;
- }
- }
-
-// ---------------------------------------------------------------------------
-// Simply deny the request as this is handing outgoing pairing
-// ---------------------------------------------------------------------------
-//
-TInt CBTNotifOutgoingPairingHandler::ObserveIncomingPair( const TBTDevAddr& aAddr )
- {
- (void)aAddr;
- return KErrServerBusy;
- }
-
-// ---------------------------------------------------------------------------
-// Accept the request only this device is not busy with another pairing request.
-// ---------------------------------------------------------------------------
-//
-void CBTNotifOutgoingPairingHandler::HandleOutgoingPairL( const TBTDevAddr& aAddr, TUint aCod )
- {
- BOstrace1(TRACE_DEBUG,DUMMY_DEVLIST," cod 0x%08x", aCod );
- if ( iActive->IsActive() || aAddr != iAddr )
- {
- // we don't allow another pairing request.
- User::Leave( KErrServerBusy );
- }
- iAddr = aAddr;
- iCod = TBTDeviceClass( aCod );
- UnSetPairResult();
- iParent.UnpairDevice( iAddr );
- if ( CBtDevExtension::IsHeadset( iCod ) )
- {
- // If the devie is a headset, set to 0000 pin auto pairing
- iPairMode = EBTOutgoingHeadsetAutoPairing;
- }
- else
- {
- iPairMode = EBTOutgoingNoneHeadsetPairing;
- }
- DoPairingL();
- }
-
-// ---------------------------------------------------------------------------
-// Cancels an outstanding pair request by self-destruct
-// ---------------------------------------------------------------------------
-//
-void CBTNotifOutgoingPairingHandler::CancelOutgoingPair()
- {
- BOstraceFunctionEntry0( DUMMY_DEVLIST );
- iParent.RenewPairingHandler( NULL );
- if( iNotification )
- {
- // Cancel the user query
- // This will also unregister us from the notification.
- TInt err = iNotification->Close();
- NOTIF_NOTHANDLED( !err )
- iNotification = NULL;
- }
- }
-
-
-// ---------------------------------------------------------------------------
-// when phone initiated a pairing request towards a headset,
-// Pin code 0000 is first tried.
-// ---------------------------------------------------------------------------
-//
-void CBTNotifOutgoingPairingHandler::GetPinCode(
- TBTPinCode& aPin, const TBTDevAddr& aAddr, TInt aMinPinLength )
- {
- BOstraceFunctionEntry0( DUMMY_DEVLIST );
- aPin().iLength = 0;
- if ( aMinPinLength <= KDefaultHeadsetPinLength
- && aAddr == iAddr
- && iPairMode == EBTOutgoingHeadsetAutoPairing)
- {
- // if the pairing requires a stronger security level (indicated
- // by aMinPinLength),
- // 0000 will not be supplied as it does not mmet the security
- // requirements
- const TUint8 KZeroPinValue = '0';
- for (TInt i = 0; i < KDefaultHeadsetPinLength; ++i)
- {
- aPin().iPIN[i] = KZeroPinValue;
- }
- aPin().iLength = KDefaultHeadsetPinLength;
- }
- }
-
-// ---------------------------------------------------------------------------
-// Abort pairing handling, request the owner to destroy this.
-// ---------------------------------------------------------------------------
-//
-void CBTNotifOutgoingPairingHandler::StopPairHandling( const TBTDevAddr& aAddr )
- {
- BOstraceFunctionEntry0( DUMMY_DEVLIST );
- if ( aAddr == iAddr )
- {
- iParent.OutgoingPairCompleted( KErrCancel );
- iParent.RenewPairingHandler( NULL );
- if( iNotification )
- {
- // Cancel the user query
- // This will also unregister us from the notification.
- TInt err = iNotification->Close();
- NOTIF_NOTHANDLED( !err )
- iNotification = NULL;
- }
- }
- }
-
-// ---------------------------------------------------------------------------
-// Pairing result will be received when pairing operation completes.
-// ---------------------------------------------------------------------------
-//
-void CBTNotifOutgoingPairingHandler::DoHandlePairServerResult( TInt aResult )
- {
- BOstraceFunctionEntry0( DUMMY_DEVLIST );
- if (aResult == (KHCIErrorBase-EPairingNotAllowed))
- {
- // if EPairingNotAllowed is recieved then any further pairing attempts will fail
- // so don't attampt to pair
- iPairMode = EBTOutgoingPairNone;
- }
- }
-
-// ---------------------------------------------------------------------------
-// Cancels possible outstanding pairing and notify user pair success.
-// ---------------------------------------------------------------------------
-//
-void CBTNotifOutgoingPairingHandler::DoHandleRegistryNewPairedEvent(
- const TBTNamelessDevice& aDev )
- {
- BOstraceFunctionEntry0( DUMMY_DEVLIST );
- TInt err( KErrNone );
- // If pairing was performed using Just Works mode, we set a
- // UICookie to indicate that the device is successfully
- // bonded so that this device will be listed in paired device view of
- // bluetooth application:
- if ( aDev.LinkKeyType() == ELinkKeyUnauthenticatedNonUpgradable )
- {
- BOstrace0(TRACE_DEBUG,DUMMY_DEVLIST,"[BTNOTIF] Outgoing Pairing, Just Works pairing");
- err = iParent.AddUiCookieJustWorksPaired( aDev );
- }
- iActive->Cancel();
- SetPairResult( err ? err : KErrNone );
- if(err == KErrNone){
- TRAP_IGNORE(ShowPairingResultNoteL(err));
- }
- iParent.OutgoingPairCompleted( err );
- iParent.RenewPairingHandler( NULL );
- }
-
-// ---------------------------------------------------------------------------
-// From class MBTNotifPairingAOObserver.
-// Based on the result code, decides the next operation, either try pairing
-// with another mode, or complete pair request.
-// ---------------------------------------------------------------------------
-//
-void CBTNotifOutgoingPairingHandler::RequestCompletedL(
- CBtSimpleActive* aActive, TInt aStatus )
- {
- BOstraceFunctionEntry0( DUMMY_DEVLIST );
- BOstraceExt3(TRACE_DEBUG,DUMMY_DEVLIST,"reqid %d, status: %d, pair mode %d ", aActive->RequestId(), aStatus, iPairMode);
- if( aActive->RequestId() == EDedicatedBonding &&
- ( aStatus == KErrRemoteDeviceIndicatedNoBonding ||
- ( aStatus && iPairMode != EBTOutgoingNoneHeadsetPairing && iPairMode != EBTOutgoingPairNone ) ) )
- {
- // try general pairing if the remote doesn't have dedicated bonding, or
- // pairing fails with a headset.
- DoPairingL();
- }
- else if ( aStatus && iPairMode == EBTOutgoingHeadsetAutoPairing )
- {
- iPairMode = EBTOutgoingHeadsetManualPairing;
- // auto pairing with headset failed, try to pair again with manual pin:
- BOstrace0(TRACE_DEBUG,DUMMY_DEVLIST," auto pairing failed, switch to manual pairing");
- DoPairingL();
- }
- else if ( aStatus && aActive->RequestId() == EGeneralBonding &&
- iPairMode == EBTOutgoingHeadsetManualPairing )
- {
- // pairing headset with manual pin failed, wait for a while and try again:
- iActive->SetRequestId( EGeneralBondingRetryTimer );
- iTimer.After( iActive->iStatus, KGeneralBondingRetryDelayMicroSeconds );
- iActive->GoActive();
- }
- else if( aActive->RequestId() == EGeneralBondingRetryTimer )
- {
- // try to pair headset again with manual pin again:
- DoPairingL();
- }
- else if ( aStatus )
- {
- // we only starts showing note if pairing failed.
- // For a successful pair, we must wait until registry has been updated.
- if ( !IsPairResultSet() )
- {
- SetPairResult( aStatus );
- }
- if ( aStatus )
- {
- // retry pairing
- if(aStatus && iPairingAttempt > 0)
- {
- if(aActive->RequestId() == EGeneralBondingRetry && iPairMode == EBTOutgoingHeadsetManualPairing)
- {
- // Headset pairing failed, reset and try again from auto pairing
- iActive->SetRequestId(EGeneralBonding);
- }
- iPairingAttempt --;
- ShowPairingRetryDialog();
- }
- else
- {
- iPairingAttempt --;
- ShowPairingFailureDialog();
- }
- }
- }
- }
-
-// ---------------------------------------------------------------------------
-// From class MBTEngActiveObserver.
-// cancels an outstanding request according to the given id.
-// ---------------------------------------------------------------------------
-//
-void CBTNotifOutgoingPairingHandler::CancelRequest( TInt aRequestId )
- {
- BOstraceFunctionEntry0( DUMMY_DEVLIST );
- switch ( aRequestId )
- {
- case EDedicatedBonding:
- {
- iBondingSession.Close();
- break;
- }
- case EGeneralBonding:
- case EGeneralBondingRetry:
- {
- iSocket.CancelConnect();
- iSocket.Close();
- break;
- }
- case EGeneralBondingRetryTimer:
- {
- iTimer.Cancel();
- break;
- }
- }
- }
-
-// ---------------------------------------------------------------------------
-// From class MBTEngActiveObserver.
-// Handles a leave in RequestCompleted by self-destructing.
-// ---------------------------------------------------------------------------
-//
-void CBTNotifOutgoingPairingHandler::HandleError(
- CBtSimpleActive* aActive, TInt aError )
- {
- BOstrace1(TRACE_DEBUG,DUMMY_DEVLIST,"error: %d", aError );
- // Our RunL can actually not leave, so we should never reach here.
- (void) aActive;
- iParent.OutgoingPairCompleted( aError );
- iParent.RenewPairingHandler( NULL );
- if( iNotification )
- {
- // Cancel the user query
- // This will also unregister us from the notification.
- TInt err = iNotification->Close();
- NOTIF_NOTHANDLED( !err )
- iNotification = NULL;
- }
- }
-
-// ---------------------------------------------------------------------------
-// decide the next state and issue pair request
-// ---------------------------------------------------------------------------
-//
-void CBTNotifOutgoingPairingHandler::DoPairingL()
- {
- BOstraceFunctionEntry0( DUMMY_DEVLIST );
- TPairingStageId currentMode = ( TPairingStageId ) iActive->RequestId();
- ASSERT( !iActive->IsActive() );
- TPairingStageId nextMode( EGeneralBonding );
-
- // if running BTv2.0 stack, dedicated bonding method
- // is not available.
- if ( currentMode == ENoBonding && iParent.PairingServer() != NULL )
- {
- nextMode = EDedicatedBonding;
- }
- else if(currentMode == EGeneralBondingRetryTimer)
- {
- nextMode = EGeneralBondingRetry;
- }
-
- BOstraceExt2(TRACE_DEBUG,DUMMY_DEVLIST,"[BTENG] CBTEngOtgPair::DoPairingL: bonding mode: pre %d, next %d", currentMode, nextMode);
-
- iActive->SetRequestId( nextMode );
- if ( nextMode == EDedicatedBonding )
- {
- iBondingSession.Start( *iParent.PairingServer(), iAddr, iActive->RequestStatus() );
- }
- else
- {
- TBTServiceSecurity sec;
- sec.SetAuthentication( ETrue );
- iSockAddr.SetBTAddr( iAddr );
- iSockAddr.SetPort(KSDPPSM);
- iSockAddr.SetSecurity( sec );
- iSocket.Close();
- User::LeaveIfError( iSocket.Open( iParent.SocketServ(), KL2CAPDesC ) );
- iSocket.Connect( iSockAddr, iActive->RequestStatus() );
- }
- iActive->GoActive();
- BOstraceFunctionExit0( DUMMY_DEVLIST );
- }
-
-// ---------------------------------------------------------------------------
-// From class MBTNotificationResult.
-// Handle a result from a user query.
-// ---------------------------------------------------------------------------
-//
-void CBTNotifOutgoingPairingHandler::MBRDataReceived( CHbSymbianVariantMap& aData )
- {
- BOstraceFunctionEntry0( DUMMY_DEVLIST );
- (void) aData;
- BOstraceFunctionExit0( DUMMY_DEVLIST );
- }
-
-// ---------------------------------------------------------------------------
-// From class MBTNotificationResult.
-// The notification is finished.
-// ---------------------------------------------------------------------------
-//
-void CBTNotifOutgoingPairingHandler::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 ) );
- BOstraceFunctionExit1( DUMMY_DEVLIST, this );
- }
-
-// ---------------------------------------------------------------------------
-// Get and configure a notification.
-// ---------------------------------------------------------------------------
-//
-void CBTNotifOutgoingPairingHandler::PrepareNotificationL( TBluetoothDialogParams::TBTDialogType aType,
- TBTDialogResourceId aResourceId )
- {
- BOstraceFunctionEntry0( DUMMY_DEVLIST );
- iNotification =
- iParent.ConnectionTracker().NotificationManager()->GetNotification();
- User::LeaveIfNull( iNotification ); // For OOM exception, leaves with KErrNoMemory
- iNotification->SetObserver( this );
- iNotification->SetNotificationType( aType, aResourceId );
- const CBtDevExtension* dev = iParent.BTDevRepository().Device(iAddr);
- if(dev)
- {
- User::LeaveIfError(iNotification->SetData( TBluetoothDeviceDialog::EDeviceName, dev->Alias()));
- }
- else
- {
- TBTDeviceName name;
- iAddr.GetReadable(name);
- User::LeaveIfError(iNotification->SetData( TBluetoothDeviceDialog::EDeviceName, name));
- NOTIF_NOTHANDLED( !err )
- }
- iParent.ConnectionTracker().NotificationManager()->QueueNotificationL( iNotification);
- NOTIF_NOTHANDLED( !err )
- BOstraceFunctionExit0( DUMMY_DEVLIST );
- }
-
-// ---------------------------------------------------------------------------
-// The notification is finished, handle the result.
-// ---------------------------------------------------------------------------
-//
-void CBTNotifOutgoingPairingHandler::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() ) );
-
- if(result() && iPairingAttempt >= 0)
- {
- HandleOutgoingPairL(iAddr,iCod.DeviceClass());
- }
- else
- {
- iPairingAttempt = KMaxRepeatedPairingAttempt; // reset the counter
- iParent.OutgoingPairCompleted( KErrCancel );
- iParent.RenewPairingHandler( NULL );
- }
- BOstraceFunctionExit1( DUMMY_DEVLIST, this );
- }
-
-// ---------------------------------------------------------------------------
-// Show a dialog to ask the user to retry the pairing
-// ---------------------------------------------------------------------------
-//
-void CBTNotifOutgoingPairingHandler::ShowPairingRetryDialog()
- {
- PrepareNotificationL( TBluetoothDialogParams::EQuery, EPairingFailureRetry);
- }
-
-// ---------------------------------------------------------------------------
-// Show a dialog to tell the user pairing retry attempt failed
-// ---------------------------------------------------------------------------
-//
-void CBTNotifOutgoingPairingHandler::ShowPairingFailureDialog()
- {
- PrepareNotificationL( TBluetoothDialogParams::EQuery, EPairingFailureOk );
- }
-
-
-