bluetoothengine/btnotif/btnotifsrv/src/btnotifoutgoingpairinghandler.cpp
changeset 31 a0ea99b6fa53
child 40 997690c3397a
child 42 b72428996822
equal deleted inserted replaced
30:df7a93ede42e 31:a0ea99b6fa53
       
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: Pairing handler for local device initiated pairing
       
    15 *
       
    16 */
       
    17 
       
    18 #include "btnotifoutgoingpairinghandler.h"
       
    19 #include <btengconstants.h>
       
    20 #include <btservices/btdevextension.h>
       
    21 #include "btnotifpairingmanager.h"
       
    22 
       
    23 /**  Length of the default PIN. */
       
    24 const TInt KDefaultHeadsetPinLength = 4;
       
    25 
       
    26 enum TPairingStageId
       
    27     {
       
    28     /**
       
    29      * no pairing operation ongoing
       
    30      */
       
    31     ENoBonding = 0,
       
    32     
       
    33     /**
       
    34      * pair with dedicated bonding method
       
    35      */
       
    36     EDedicatedBonding = 200,
       
    37     
       
    38     /**
       
    39      * pair with general bonding by establishing L2CAP connection.
       
    40      */
       
    41     EGeneralBonding,  
       
    42     
       
    43     /**
       
    44      * delaying next pairing request for a while
       
    45      */
       
    46     EGeneralBondingRetryTimer,
       
    47     
       
    48     /**
       
    49      * The last pairing retry
       
    50      */
       
    51     EGeneralBondingRetry,
       
    52     
       
    53     /**
       
    54      * disconnecting physical link after pairing operation.
       
    55      * 
       
    56      * todo: not used yet.
       
    57      */
       
    58     EDisconnectLinkAfterBonding,
       
    59     };
       
    60 
       
    61 /**  SDP PSM (used for pairing) */
       
    62 const TInt KSDPPSM = 0x0001;
       
    63 
       
    64 // Delay time to void Repeated Attempts on pairing
       
    65 const TInt KGeneralBondingRetryDelayMicroSeconds = 5000000; // 5.0s
       
    66 
       
    67 // ======== MEMBER FUNCTIONS ========
       
    68 
       
    69 // ---------------------------------------------------------------------------
       
    70 // C++ default constructor
       
    71 // ---------------------------------------------------------------------------
       
    72 //
       
    73 CBTNotifOutgoingPairingHandler::CBTNotifOutgoingPairingHandler( CBTNotifPairingManager& aParent, const TBTDevAddr& aAddr)
       
    74     :  CBTNotifBasePairingHandler( aParent, aAddr )
       
    75     {
       
    76     }
       
    77 
       
    78 // ---------------------------------------------------------------------------
       
    79 // Symbian 2nd-phase constructor
       
    80 // ---------------------------------------------------------------------------
       
    81 //
       
    82 void CBTNotifOutgoingPairingHandler::ConstructL()
       
    83     {
       
    84     BaseConstructL();
       
    85     User::LeaveIfError( iTimer.CreateLocal() );
       
    86     }
       
    87 
       
    88 // ---------------------------------------------------------------------------
       
    89 // NewL
       
    90 // ---------------------------------------------------------------------------
       
    91 //
       
    92 CBTNotifBasePairingHandler* CBTNotifOutgoingPairingHandler::NewL( CBTNotifPairingManager& aParent, 
       
    93         const TBTDevAddr& aAddr )
       
    94     {
       
    95     CBTNotifOutgoingPairingHandler* self = new( ELeave ) CBTNotifOutgoingPairingHandler( aParent, aAddr );
       
    96     CleanupStack::PushL( self );
       
    97     self->ConstructL();
       
    98     CleanupStack::Pop( self );
       
    99     return self;
       
   100     }
       
   101 
       
   102 // ---------------------------------------------------------------------------
       
   103 // Destructor
       
   104 // ---------------------------------------------------------------------------
       
   105 //
       
   106 CBTNotifOutgoingPairingHandler::~CBTNotifOutgoingPairingHandler()
       
   107     {
       
   108     if ( iActive ) 
       
   109         {
       
   110         iActive->Cancel();
       
   111         }
       
   112     iBondingSession.Close();
       
   113     iSocket.Close();
       
   114     iTimer.Close();
       
   115     }
       
   116 
       
   117 // ---------------------------------------------------------------------------
       
   118 // Simply deny the request as this is handing outgoing pairing
       
   119 // ---------------------------------------------------------------------------
       
   120 //
       
   121 TInt CBTNotifOutgoingPairingHandler::ObserveIncomingPair( const TBTDevAddr& /*aAddr*/ )
       
   122     {
       
   123     return KErrServerBusy;
       
   124     }
       
   125 
       
   126 // ---------------------------------------------------------------------------
       
   127 // Accept the request only this device is not busy with another pairing request.
       
   128 // ---------------------------------------------------------------------------
       
   129 //
       
   130 void CBTNotifOutgoingPairingHandler::HandleOutgoingPairL( const TBTDevAddr& aAddr, TUint aCod )
       
   131     {
       
   132     // TRACE_FUNC_ARG( ( _L(" cod 0x%08x"), aCod ) )
       
   133     if ( iActive->IsActive() || aAddr != iAddr )
       
   134         {
       
   135         // we don't allow another pairing request.
       
   136         User::Leave( KErrServerBusy );
       
   137         }
       
   138     
       
   139     iAddr = aAddr;
       
   140     iCod = TBTDeviceClass( aCod );
       
   141     UnSetPairResult();
       
   142     iParent.UnpairDevice( iAddr );
       
   143     if ( CBtDevExtension::IsHeadset( iCod ) )
       
   144         {
       
   145         // If the devie is a headset, set to 0000 pin auto pairing
       
   146         iPairMode = EBTOutgoingHeadsetAutoPairing;
       
   147         }
       
   148     else
       
   149         {
       
   150         iPairMode = EBTOutgoingNoneHeadsetPairing;
       
   151         }
       
   152     // SetOutgoPairProperty( iOutgoProperty, iAddr, iPairMode );
       
   153     DoPairingL();
       
   154     }
       
   155 
       
   156 // ---------------------------------------------------------------------------
       
   157 // Cancels an outstanding pair request by self-destruct
       
   158 // ---------------------------------------------------------------------------
       
   159 //
       
   160 void CBTNotifOutgoingPairingHandler::CancelOutgoingPair()
       
   161     {
       
   162     iParent.RenewPairingHandler( NULL );
       
   163     }
       
   164 
       
   165 
       
   166 // ---------------------------------------------------------------------------
       
   167 // when phone initiated a pairing request towards a headset,
       
   168 // Pin code 0000 is first tried.
       
   169 // ---------------------------------------------------------------------------
       
   170 //
       
   171 void CBTNotifOutgoingPairingHandler::GetPinCode( 
       
   172         TBTPinCode& aPin, const TBTDevAddr& aAddr, TInt aMinPinLength )
       
   173     {
       
   174     aPin().iLength = 0;
       
   175     if ( aMinPinLength <= KDefaultHeadsetPinLength 
       
   176             && aAddr == iAddr
       
   177             && iPairMode == EBTOutgoingHeadsetAutoPairing)
       
   178         {
       
   179         // if the pairing requires a stronger security level (indicated
       
   180         // by aMinPinLength), 
       
   181         // 0000 will not be supplied as it does not mmet the security
       
   182         // requirements
       
   183         const TUint8 KZeroPinValue = '0';
       
   184         for (TInt i = 0; i < KDefaultHeadsetPinLength; ++i)
       
   185             {
       
   186             aPin().iPIN[i] = KZeroPinValue;
       
   187             }
       
   188         aPin().iLength = KDefaultHeadsetPinLength;
       
   189         }
       
   190     }
       
   191 
       
   192 // ---------------------------------------------------------------------------
       
   193 // Abort pairing handling, request the owner to destroy this.
       
   194 // ---------------------------------------------------------------------------
       
   195 //
       
   196 void CBTNotifOutgoingPairingHandler::StopPairHandling( const TBTDevAddr& aAddr )
       
   197     {
       
   198     if ( aAddr == iAddr )
       
   199         {
       
   200         iParent.OutgoingPairCompleted( KErrCancel );
       
   201         iParent.RenewPairingHandler( NULL );
       
   202         }
       
   203     }
       
   204 
       
   205 // ---------------------------------------------------------------------------
       
   206 // Pairing result will be received when pairing operation completes.
       
   207 // ---------------------------------------------------------------------------
       
   208 //
       
   209 void CBTNotifOutgoingPairingHandler::DoHandlePairServerResult( TInt aResult )
       
   210     {
       
   211 	if (aResult == (KHCIErrorBase-EPairingNotAllowed))
       
   212 		{
       
   213 		// if EPairingNotAllowed is recieved then any further pairing attempts will fail
       
   214 		// so don't attampt to pair
       
   215         iPairMode = EBTOutgoingPairNone;
       
   216 		}
       
   217     }
       
   218 
       
   219 // ---------------------------------------------------------------------------
       
   220 // Cancels possible outstanding pairing and notify user pair success.
       
   221 // ---------------------------------------------------------------------------
       
   222 //
       
   223 void CBTNotifOutgoingPairingHandler::DoHandleRegistryNewPairedEvent( 
       
   224         const TBTNamelessDevice& aDev )
       
   225     {
       
   226     TInt err( KErrNone );
       
   227     // If pairing was performed using Just Works mode, we set a 
       
   228     // UICookie to indicate that the device is successfully 
       
   229     // bonded so that this device will be listed in paired device view of
       
   230     // bluetooth application:
       
   231     if ( aDev.LinkKeyType() == ELinkKeyUnauthenticatedNonUpgradable )
       
   232         {
       
   233         // TRACE_INFO( ( _L( "[BTENG] CBTEngOtgPair, Just Works pairing" ) ) );
       
   234         err = iParent.AddUiCookieJustWorksPaired( aDev );
       
   235         }
       
   236     iActive->Cancel();
       
   237     SetPairResult( err ? err : KErrNone );
       
   238     iParent.OutgoingPairCompleted( err );
       
   239     iParent.RenewPairingHandler( NULL );
       
   240     }
       
   241 
       
   242 // ---------------------------------------------------------------------------
       
   243 // From class MBTNotifPairingAOObserver.
       
   244 // Based on the result code, decides the next operation, either try pairing 
       
   245 // with another mode, or complete pair request.
       
   246 // ---------------------------------------------------------------------------
       
   247 //
       
   248 void CBTNotifOutgoingPairingHandler::RequestCompletedL( 
       
   249         CBtSimpleActive* aActive, TInt aStatus )
       
   250     {
       
   251     // TRACE_FUNC_ARG( ( _L( "reqid %d, status: %d, pair mode %d " ), aId, aStatus, iPairMode ) )
       
   252     if( aActive->RequestId() == EDedicatedBonding && 
       
   253 				( aStatus == KErrRemoteDeviceIndicatedNoBonding || 
       
   254 					( aStatus && iPairMode != EBTOutgoingNoneHeadsetPairing && iPairMode != EBTOutgoingPairNone ) )   )
       
   255         {
       
   256         // try general pairing if the remote doesn't have dedicated bonding, or
       
   257         // pairing fails with a headset.
       
   258         DoPairingL();
       
   259         }
       
   260     else if ( aStatus && iPairMode == EBTOutgoingHeadsetAutoPairing )
       
   261         {
       
   262         iPairMode = EBTOutgoingHeadsetManualPairing;
       
   263         // auto pairing with headset failed, try to pair again with manual pin:
       
   264         // ( void ) SetOutgoPairProperty( iOutgoProperty, iAddr, iPairMode );
       
   265         // TRACE_INFO( _L( " auto pairing failed, switch to manual pairing") );     
       
   266         DoPairingL();
       
   267         }
       
   268     else if ( aStatus && aActive->RequestId() == EGeneralBonding && 
       
   269               iPairMode == EBTOutgoingHeadsetManualPairing )
       
   270         {
       
   271         // pairing headset with manual pin failed, wait for a while and try again:
       
   272         iActive->SetRequestId( EGeneralBondingRetryTimer );
       
   273         iTimer.After( iActive->iStatus, KGeneralBondingRetryDelayMicroSeconds );
       
   274         iActive->GoActive();
       
   275         }
       
   276     else if( aActive->RequestId() == EGeneralBondingRetryTimer )
       
   277         {
       
   278         // try to pair headset again with manual pin again:
       
   279         DoPairingL();
       
   280         }
       
   281     else if ( aStatus )
       
   282         {
       
   283         // we only starts showing note if pairing failed.
       
   284         // For a successful pair, we must wait until registry has been updated.
       
   285         if ( !IsPairResultSet() )
       
   286             {
       
   287             SetPairResult( aStatus );
       
   288             }
       
   289         if ( aStatus )
       
   290             {
       
   291             // todo: show error note?
       
   292             iParent.OutgoingPairCompleted( aStatus );
       
   293             }
       
   294         }
       
   295     }
       
   296 
       
   297 // ---------------------------------------------------------------------------
       
   298 // From class MBTEngActiveObserver.
       
   299 // cancels an outstanding request according to the given id.
       
   300 // ---------------------------------------------------------------------------
       
   301 //
       
   302 void CBTNotifOutgoingPairingHandler::CancelRequest( TInt aRequestId )
       
   303     {
       
   304     switch ( aRequestId )
       
   305         {
       
   306         case EDedicatedBonding:
       
   307             {
       
   308             iBondingSession.Close();
       
   309             }
       
   310         case EGeneralBonding:
       
   311         case EGeneralBondingRetry:
       
   312             {
       
   313             iSocket.CancelConnect();
       
   314             iSocket.Close();
       
   315             }
       
   316         case EGeneralBondingRetryTimer:
       
   317             {
       
   318             iTimer.Cancel();
       
   319             }     
       
   320         }
       
   321     }
       
   322 
       
   323 // ---------------------------------------------------------------------------
       
   324 // From class MBTEngActiveObserver.
       
   325 // Handles a leave in RequestCompleted by self-destructing.
       
   326 // ---------------------------------------------------------------------------
       
   327 //
       
   328 void CBTNotifOutgoingPairingHandler::HandleError( 
       
   329         CBtSimpleActive* aActive, TInt aError )
       
   330     {
       
   331     // TRACE_FUNC_ARG( ( _L( "error: %d" ), aError ) )
       
   332     // Our RunL can actually not leave, so we should never reach here.
       
   333     (void) aActive;
       
   334     iParent.OutgoingPairCompleted( aError );
       
   335     iParent.RenewPairingHandler( NULL );
       
   336     }
       
   337 
       
   338 // ---------------------------------------------------------------------------
       
   339 // decide the next state and issue pair request
       
   340 // ---------------------------------------------------------------------------
       
   341 //
       
   342 void CBTNotifOutgoingPairingHandler::DoPairingL()
       
   343     {
       
   344     // TRACE_FUNC_ENTRY
       
   345     TPairingStageId currentMode = ( TPairingStageId ) iActive->RequestId();
       
   346     ASSERT( !iActive->IsActive() );
       
   347     TPairingStageId nextMode( EGeneralBonding );
       
   348     
       
   349     // if running BTv2.0 stack, dedicated bonding method 
       
   350     // is not available.
       
   351     if ( currentMode == ENoBonding && iParent.PairingServer() != NULL )
       
   352         {
       
   353         nextMode = EDedicatedBonding;
       
   354         }
       
   355     else if(currentMode == EGeneralBondingRetryTimer)
       
   356         {
       
   357         nextMode = EGeneralBondingRetry;
       
   358         }
       
   359     
       
   360     // TRACE_INFO( ( _L( "[BTENG] CBTEngOtgPair::DoPairingL: bonding mode: pre %d, next %d"), currentMode, nextMode ) );
       
   361     
       
   362     iActive->SetRequestId( nextMode );
       
   363     if ( nextMode == EDedicatedBonding )
       
   364         {
       
   365         iBondingSession.Start( *iParent.PairingServer(), iAddr, iActive->RequestStatus() );          
       
   366         }
       
   367     else
       
   368         {
       
   369         TBTServiceSecurity sec;
       
   370         sec.SetAuthentication( ETrue );
       
   371         iSockAddr.SetBTAddr( iAddr );
       
   372         iSockAddr.SetPort(KSDPPSM);
       
   373         iSockAddr.SetSecurity( sec );    
       
   374         iSocket.Close();
       
   375         User::LeaveIfError( iSocket.Open( iParent.SocketServ(), KL2CAPDesC ) );
       
   376         iSocket.Connect( iSockAddr, iActive->RequestStatus() );
       
   377         }
       
   378     iActive->GoActive();
       
   379     // TRACE_FUNC_EXIT
       
   380     }
       
   381