bluetoothengine/bteng/src/btengotgpair.cpp
branchRCL_3
changeset 56 9386f31cc85b
parent 0 f63038272f30
equal deleted inserted replaced
55:613943a21004 56:9386f31cc85b
       
     1 /*
       
     2 * Copyright (c) 2006-2009 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:  Helper class for performing pairing (i.e. bonding) 
       
    15 *                with another device.
       
    16 *
       
    17 */
       
    18 
       
    19 #include "btengotgpair.h"
       
    20 #include <btengconstants.h>
       
    21 #include "btengpairman.h"
       
    22 #include "btotgpairpub.inl"
       
    23 #include "debug.h"
       
    24 
       
    25 enum TPairingStageId
       
    26     {
       
    27     /**
       
    28      * no pairing operation ongoing
       
    29      */
       
    30     ENoBonding = 0,
       
    31     
       
    32     /**
       
    33      * pair with dedicated bonding method
       
    34      */
       
    35     EDedicatedBonding = EDevicePairUserNotification + 1,
       
    36     
       
    37     /**
       
    38      * pair with general bonding by establishing L2CAP connection.
       
    39      */
       
    40     EGeneralBonding,  
       
    41     
       
    42     /**
       
    43      * delaying next pairing request for a while
       
    44      */
       
    45     EGeneralBondingRetryTimer,
       
    46     
       
    47     /**
       
    48      * The last pairing retry
       
    49      */
       
    50     EGeneralBondingRetry
       
    51     };
       
    52 
       
    53 /**  SDP PSM (used for pairing) */
       
    54 const TInt KSDPPSM = 0x0001;
       
    55 
       
    56 // Delay time to void Repeated Attempts on pairing
       
    57 const TInt KBTEngGeneralBondingRetryDelayMicroSeconds = 5000000; // 5.0s
       
    58 
       
    59 // ======== MEMBER FUNCTIONS ========
       
    60 
       
    61 // ---------------------------------------------------------------------------
       
    62 // C++ default constructor
       
    63 // ---------------------------------------------------------------------------
       
    64 //
       
    65 CBTEngOtgPair::CBTEngOtgPair( CBTEngPairMan& aParent, const TBTDevAddr& aAddr)
       
    66     :  CBTEngPairBase( aParent, aAddr )
       
    67     {
       
    68     }
       
    69 
       
    70 // ---------------------------------------------------------------------------
       
    71 // Symbian 2nd-phase constructor
       
    72 // ---------------------------------------------------------------------------
       
    73 //
       
    74 void CBTEngOtgPair::ConstructL()
       
    75     {
       
    76     TRACE_FUNC_ENTRY
       
    77     BaseConstructL();
       
    78     User::LeaveIfError( iOutgoProperty.Attach( KPSUidBluetoothEnginePrivateCategory, 
       
    79             KBTOutgoingPairing ) );
       
    80     User::LeaveIfError( iTimer.CreateLocal() );
       
    81     TRACE_FUNC_EXIT
       
    82     }
       
    83 
       
    84 // ---------------------------------------------------------------------------
       
    85 // NewL
       
    86 // ---------------------------------------------------------------------------
       
    87 //
       
    88 CBTEngPairBase* CBTEngOtgPair::NewL( CBTEngPairMan& aParent, 
       
    89         const TBTDevAddr& aAddr )
       
    90     {
       
    91     CBTEngOtgPair* self = new( ELeave ) CBTEngOtgPair( aParent, aAddr );
       
    92     CleanupStack::PushL( self );
       
    93     self->ConstructL();
       
    94     CleanupStack::Pop( self );
       
    95     return self;
       
    96     }
       
    97 
       
    98 // ---------------------------------------------------------------------------
       
    99 // Destructor
       
   100 // ---------------------------------------------------------------------------
       
   101 //
       
   102 CBTEngOtgPair::~CBTEngOtgPair()
       
   103     {
       
   104     TRACE_FUNC_ENTRY
       
   105     SetOutgoPairProperty( iOutgoProperty, TBTDevAddr(), EBTOutgoingPairNone );
       
   106     CancelNotifier();
       
   107     DoCancelOutgoingPair();
       
   108     iBondingSession.Close();
       
   109     iSocket.Close();
       
   110     iTimer.Close();
       
   111     iOutgoProperty.Close();
       
   112     TRACE_FUNC_EXIT
       
   113     }
       
   114 
       
   115 // ---------------------------------------------------------------------------
       
   116 // Simply deny the request as this is handing outgoing pairing
       
   117 // ---------------------------------------------------------------------------
       
   118 //
       
   119 TInt CBTEngOtgPair::ObserveIncomingPair( const TBTDevAddr& /*aAddr*/ )
       
   120     {
       
   121     return KErrServerBusy;
       
   122     }
       
   123 
       
   124 // ---------------------------------------------------------------------------
       
   125 // Accept the request only this device is not busy with another pairing request.
       
   126 // ---------------------------------------------------------------------------
       
   127 //
       
   128 void CBTEngOtgPair::HandleOutgoingPairL( const TBTDevAddr& aAddr, TUint aCod )
       
   129     {
       
   130     TRACE_FUNC_ARG( ( _L(" cod 0x%08x"), aCod ) )
       
   131     if ( iActive->IsActive() || aAddr != iAddr )
       
   132         {
       
   133         // we don't allow another pairing request.
       
   134         User::Leave( KErrServerBusy );
       
   135         }
       
   136     
       
   137     iAddr = aAddr;
       
   138     iCod = aCod;
       
   139     UnSetPairResult();
       
   140     iParent.UnpairDevice( iAddr );
       
   141     TBTDeviceClass decls( iCod );
       
   142     if ( decls.MajorDeviceClass() == EMajorDeviceAV && 
       
   143             decls.MinorDeviceClass() != EMinorDeviceAVHandsfree )
       
   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     TRACE_FUNC_EXIT
       
   155     }
       
   156 
       
   157 // ---------------------------------------------------------------------------
       
   158 // Cancels an outstanding pair request by self-destruct
       
   159 // ---------------------------------------------------------------------------
       
   160 //
       
   161 void CBTEngOtgPair::CancelOutgoingPair()
       
   162     {
       
   163     TRACE_FUNC_ENTRY
       
   164     iParent.RenewPairer( NULL );
       
   165     TRACE_FUNC_EXIT
       
   166     }
       
   167 
       
   168 // ---------------------------------------------------------------------------
       
   169 // Abort pairing handling, request the owner to destroy this.
       
   170 // ---------------------------------------------------------------------------
       
   171 //
       
   172 void CBTEngOtgPair::StopPairHandling( const TBTDevAddr& aAddr )
       
   173     {
       
   174     if ( aAddr == iAddr )
       
   175         {
       
   176         TRACE_FUNC_ENTRY
       
   177         iParent.OutgoingPairCompleted( KErrCancel );
       
   178         iParent.RenewPairer( NULL );
       
   179         TRACE_FUNC_EXIT
       
   180         }
       
   181     }
       
   182 
       
   183 // ---------------------------------------------------------------------------
       
   184 // Pairing result will be received when pairing operation completes.
       
   185 // ---------------------------------------------------------------------------
       
   186 //
       
   187 void CBTEngOtgPair::DoHandlePairServerResult( TInt aResult )
       
   188     {
       
   189 	if (aResult == (KHCIErrorBase-EPairingNotAllowed))
       
   190 		{
       
   191 		// if EPairingNotAllowed is recieved then any further pairing attempts will fail
       
   192 		// so don't attampt to pair
       
   193         iPairMode = EBTOutgoingPairNone;
       
   194 		}
       
   195     }
       
   196 
       
   197 // ---------------------------------------------------------------------------
       
   198 // Cancels possible outstanding pairing and notify user pair success.
       
   199 // ---------------------------------------------------------------------------
       
   200 //
       
   201 void CBTEngOtgPair::DoHandleRegistryNewPairedEvent( const TBTNamelessDevice& aDev )
       
   202     {
       
   203     TRACE_FUNC_ENTRY
       
   204     if ( !IsNotifyingPairResult() )
       
   205         {
       
   206         TInt err( KErrNone );
       
   207         // If pairing was performed using Just Works mode, we set a 
       
   208         // UICookie to indicate that the device is successfully 
       
   209         // bonded so that this device will be listed in paired device view of
       
   210         // bluetooth application:
       
   211         if ( aDev.LinkKeyType() == ELinkKeyUnauthenticatedNonUpgradable )
       
   212             {
       
   213             TRACE_INFO( ( _L( "[BTENG] CBTEngOtgPair, Just Works pairing" ) ) );
       
   214             err = iParent.AddUiCookieJustWorksPaired( aDev );
       
   215             }
       
   216         DoCancelOutgoingPair();
       
   217         SetPairResult( err ? err : KErrNone );
       
   218         ShowPairingNoteAndAuthorizeQuery();
       
   219         }
       
   220     TRACE_FUNC_EXIT
       
   221     }
       
   222 
       
   223 // ---------------------------------------------------------------------------
       
   224 // From class MBTEngActiveObserver.
       
   225 // Based on the result code, decides the next operation, either try pairing 
       
   226 // with another mode, or complete pair request.
       
   227 // ---------------------------------------------------------------------------
       
   228 //
       
   229 void CBTEngOtgPair::RequestCompletedL( CBTEngActive* aActive, TInt aId, 
       
   230     TInt aStatus )
       
   231     {
       
   232     TRACE_FUNC_ARG( ( _L( "reqid %d, status: %d, pair mode %d " ), aId, aStatus, iPairMode ) )
       
   233     (void) aActive;
       
   234     (void) aId;
       
   235  
       
   236     if ( aId == EDevicePairUserNotification)
       
   237         {
       
   238         // user notification completes:
       
   239         iParent.OutgoingPairCompleted( aStatus ? aStatus : iPairResult );
       
   240         iParent.RenewPairer( NULL );
       
   241         return;
       
   242         }
       
   243     
       
   244     if( aId == EDedicatedBonding && 
       
   245 				( aStatus == KErrRemoteDeviceIndicatedNoBonding || 
       
   246 					( aStatus && iPairMode != EBTOutgoingNoneHeadsetPairing && iPairMode != EBTOutgoingPairNone ) )   )
       
   247         {
       
   248         // try general pairing if the remote doesn't have dedicated bonding, or
       
   249         // pairing fails with a headset.
       
   250         DoPairingL();
       
   251         }
       
   252     else if ( aStatus && iPairMode == EBTOutgoingHeadsetAutoPairing )
       
   253         {
       
   254         iPairMode = EBTOutgoingHeadsetManualPairing;
       
   255         // auto pairing with headset failed, try to pair again with manual pin:
       
   256         ( void ) SetOutgoPairProperty( iOutgoProperty, iAddr, iPairMode );
       
   257         TRACE_INFO( _L( " auto pairing failed, switch to manual pairing") );     
       
   258         DoPairingL();
       
   259         }
       
   260     else if ( aStatus && aId == EGeneralBonding && 
       
   261               iPairMode == EBTOutgoingHeadsetManualPairing )
       
   262         {
       
   263         // pairing headset with manual pin failed, wait for a while and try again:
       
   264         iActive->SetRequestId( EGeneralBondingRetryTimer );
       
   265         iTimer.After( iActive->iStatus, KBTEngGeneralBondingRetryDelayMicroSeconds );
       
   266         iActive->GoActive();
       
   267         }
       
   268     else if( aId == EGeneralBondingRetryTimer )
       
   269         {
       
   270         // try to pair headset again with manual pin again:
       
   271         DoPairingL();
       
   272         }
       
   273     else if ( aStatus )
       
   274         {
       
   275         // we only starts showing note if pairing failed.
       
   276         // For a successful pair, we must wait until registry has been updated.
       
   277         if ( !IsPairResultSet() )
       
   278             {
       
   279             SetPairResult( aStatus );
       
   280             }
       
   281         if ( aStatus )
       
   282             {
       
   283             ShowPairingNoteAndAuthorizeQuery();
       
   284             }
       
   285         }
       
   286     TRACE_FUNC_EXIT
       
   287     }
       
   288 
       
   289 // ---------------------------------------------------------------------------
       
   290 // From class MBTEngActiveObserver.
       
   291 // Handles a leave in RequestCompleted by self-destructing.
       
   292 // ---------------------------------------------------------------------------
       
   293 //
       
   294 void CBTEngOtgPair::HandleError( CBTEngActive* aActive, TInt aId, 
       
   295     TInt aError )
       
   296     {
       
   297     TRACE_FUNC_ARG( ( _L( "error: %d" ), aError ) )
       
   298     // Our RunL can actually not leave, so we should never reach here.
       
   299     (void) aActive;
       
   300     (void) aId;
       
   301     iParent.OutgoingPairCompleted( aError );
       
   302     iParent.RenewPairer( NULL );
       
   303     }
       
   304 
       
   305 // ---------------------------------------------------------------------------
       
   306 // decide the next state and issue pair request
       
   307 // ---------------------------------------------------------------------------
       
   308 //
       
   309 void CBTEngOtgPair::DoPairingL()
       
   310     {
       
   311     TRACE_FUNC_ENTRY
       
   312     TPairingStageId currentMode = ( TPairingStageId ) iActive->RequestId();
       
   313     ASSERT( !iActive->IsActive() );
       
   314     TPairingStageId nextMode( EGeneralBonding );
       
   315     
       
   316     // if running BTv2.0 stack, dedicated bonding method 
       
   317     // is not available.
       
   318     if ( currentMode == ENoBonding && iParent.PairingServer() != NULL )
       
   319         {
       
   320         nextMode = EDedicatedBonding;
       
   321         }
       
   322     else if(currentMode == EGeneralBondingRetryTimer)
       
   323         {
       
   324         nextMode = EGeneralBondingRetry;
       
   325         }
       
   326     
       
   327     TRACE_INFO( ( _L( "[BTENG] CBTEngOtgPair::DoPairingL: bonding mode: pre %d, next %d"), currentMode, nextMode ) );
       
   328     
       
   329     iActive->SetRequestId( nextMode );
       
   330     if ( nextMode == EDedicatedBonding )
       
   331         {
       
   332         iBondingSession.Start( *iParent.PairingServer(), iAddr, iActive->RequestStatus() );          
       
   333         }
       
   334     else
       
   335         {
       
   336         TBTServiceSecurity sec;
       
   337         sec.SetAuthentication( ETrue );
       
   338         iSockAddr.SetBTAddr( iAddr );
       
   339         iSockAddr.SetPort(KSDPPSM);
       
   340         iSockAddr.SetSecurity( sec );    
       
   341         iSocket.Close();
       
   342         User::LeaveIfError( iSocket.Open( iParent.SocketServ(), KL2CAPDesC ) );
       
   343         iSocket.Connect( iSockAddr, iActive->RequestStatus() );
       
   344         }
       
   345     iActive->GoActive();
       
   346     TRACE_FUNC_EXIT
       
   347     }
       
   348 
       
   349 // ---------------------------------------------------------------------------
       
   350 // Make sure no outstanding pairing request is existing
       
   351 // ---------------------------------------------------------------------------
       
   352 //
       
   353 void CBTEngOtgPair::DoCancelOutgoingPair()
       
   354     {
       
   355     TRACE_FUNC_ENTRY
       
   356     if( iActive->IsActive() )
       
   357         {
       
   358         iBondingSession.Close();
       
   359         if( iSocket.SubSessionHandle() )
       
   360             {
       
   361             iSocket.CancelConnect();
       
   362             iSocket.Close();
       
   363             }
       
   364         iTimer.Cancel();
       
   365         iActive->CancelRequest();
       
   366         }
       
   367     TRACE_FUNC_EXIT
       
   368     }