bluetoothengine/bteng/src/btengincpair.cpp
branchRCL_3
changeset 23 9386f31cc85b
equal deleted inserted replaced
22:613943a21004 23:9386f31cc85b
       
     1 /*
       
     2 * Copyright (c) 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:  BT determines pairing status 
       
    15 *
       
    16 */
       
    17 
       
    18 #include "btengincpair.h"
       
    19 #include "btengpairman.h"
       
    20 #include "btengotgpair.h"
       
    21 #include "btengconstants.h"
       
    22 #include "debug.h"
       
    23 
       
    24 const TInt KBTEngWaitingForPairingOkDelay = 500000; // 0.5s
       
    25 
       
    26 enum TPairingStageId
       
    27     {
       
    28     /**
       
    29      * is monitoring physical link status
       
    30      */
       
    31     EPhysicalLinkNotify = EDevicePairUserNotification + 1,
       
    32     EWaitingForPairingOk,
       
    33     };
       
    34 
       
    35 // ======== MEMBER FUNCTIONS ========
       
    36 
       
    37 // ---------------------------------------------------------------------------
       
    38 // C++ default constructor
       
    39 // ---------------------------------------------------------------------------
       
    40 //
       
    41 CBTEngIncPair::CBTEngIncPair( CBTEngPairMan& aParent, 
       
    42     const TBTDevAddr& aAddr) : CBTEngPairBase( aParent, aAddr )
       
    43     {
       
    44     }
       
    45 
       
    46 // ---------------------------------------------------------------------------
       
    47 // 2nd phase constructor
       
    48 // ---------------------------------------------------------------------------
       
    49 //
       
    50 void CBTEngIncPair::ConstructL()
       
    51     {
       
    52     BaseConstructL();
       
    53     iActivePairingOk = CBTEngActive::NewL(*this, EWaitingForPairingOk, CActive::EPriorityStandard);
       
    54     User::LeaveIfError( iPairingOkTimer.CreateLocal() );
       
    55     }
       
    56 
       
    57 // ---------------------------------------------------------------------------
       
    58 // NewL
       
    59 // ---------------------------------------------------------------------------
       
    60 //
       
    61 CBTEngIncPair* CBTEngIncPair::NewL( CBTEngPairMan& aParent, 
       
    62     const TBTDevAddr& aAddr)
       
    63     {
       
    64     CBTEngIncPair* self = new (ELeave) CBTEngIncPair(aParent, aAddr);
       
    65     CleanupStack::PushL( self );
       
    66     self->ConstructL();
       
    67     CleanupStack::Pop( self );
       
    68     return self;
       
    69     }
       
    70 
       
    71 // ---------------------------------------------------------------------------
       
    72 // Destructor
       
    73 // ---------------------------------------------------------------------------
       
    74 //
       
    75 CBTEngIncPair::~CBTEngIncPair()
       
    76     {
       
    77     TRACE_FUNC_ENTRY
       
    78     // Cancel all outstanding requests
       
    79     CancelPlaNotification();
       
    80     iPla.Close();
       
    81     iPairingOkTimer.Cancel();
       
    82     iPairingOkTimer.Close();
       
    83     if(iActivePairingOk)
       
    84         {
       
    85         iActivePairingOk->CancelRequest();
       
    86         delete iActivePairingOk;
       
    87         }
       
    88     TRACE_FUNC_EXIT
       
    89     }
       
    90 
       
    91 // ---------------------------------------------------------------------------
       
    92 // Accept this message only if the specified device is the same as this is
       
    93 // dealing with.
       
    94 // ---------------------------------------------------------------------------
       
    95 //
       
    96 TInt CBTEngIncPair::ObserveIncomingPair( const TBTDevAddr& aAddr )
       
    97     {
       
    98     TInt err( KErrServerBusy );
       
    99     if ( iAddr == aAddr )
       
   100         {
       
   101         err = KErrNone;
       
   102         iUserAwarePairing = ETrue; // This function is called by a notifier, which means the UI has been involved
       
   103         // Therefore we can display it in the paired devices list
       
   104         if ( !iActive->IsActive() && !OpenPhysicalLinkAdaptor() )
       
   105             {
       
   106             // If we are observing physical link, or showing user a note,
       
   107             // we won't interrupt it.
       
   108             UnSetPairResult();
       
   109             MonitorPhysicalLink();
       
   110             }
       
   111         }
       
   112     return err;
       
   113     }
       
   114 
       
   115 // ---------------------------------------------------------------------------
       
   116 // Assign the responsibility of outgoing pair handling to CBTEngOtgPair
       
   117 // ---------------------------------------------------------------------------
       
   118 //
       
   119 void CBTEngIncPair::HandleOutgoingPairL( const TBTDevAddr& aAddr, TUint aCod )
       
   120     {
       
   121     TRACE_FUNC_ENTRY
       
   122     // Outgoing pairing always takes highest priority:
       
   123     CBTEngPairBase* pairer = CBTEngOtgPair::NewL( iParent, aAddr );
       
   124     pairer->HandleOutgoingPairL( aAddr, aCod );
       
   125     iParent.RenewPairer( pairer );
       
   126     TRACE_FUNC_EXIT
       
   127     }
       
   128 
       
   129 // ---------------------------------------------------------------------------
       
   130 // Accept this message only if the specified device is the same as this is
       
   131 // dealing with.
       
   132 // ---------------------------------------------------------------------------
       
   133 //
       
   134 void CBTEngIncPair::StopPairHandling( const TBTDevAddr& aAddr )
       
   135     {
       
   136     if ( aAddr == iAddr )
       
   137         {
       
   138         TRACE_FUNC_ENTRY
       
   139         iParent.RenewPairer( NULL );
       
   140         TRACE_FUNC_EXIT
       
   141         }
       
   142     }
       
   143 
       
   144 // ---------------------------------------------------------------------------
       
   145 // Notify user if pairing failed.
       
   146 // ---------------------------------------------------------------------------
       
   147 //
       
   148 void CBTEngIncPair::DoHandlePairServerResult( TInt aResult )
       
   149     {
       
   150     CancelPlaNotification();
       
   151     // For a successful pairing, we need wait for registry table change.
       
   152     if( aResult != KErrNone && aResult != KHCIErrorBase )
       
   153         {
       
   154         // Pair failure situation.
       
   155         SetPairResult( aResult );
       
   156         ShowPairingNoteAndAuthorizeQuery();
       
   157         }
       
   158     }
       
   159 
       
   160 // ---------------------------------------------------------------------------
       
   161 // Kill this if the linkkey type indicates OBEX authentication.
       
   162 // Otherwise notify user the pair result.
       
   163 // ---------------------------------------------------------------------------
       
   164 //
       
   165 void CBTEngIncPair::DoHandleRegistryNewPairedEvent( const TBTNamelessDevice& aDev )
       
   166     {
       
   167     TRACE_FUNC_ENTRY
       
   168     
       
   169     // First of all cancel the iPairingOkTimer timer, if active
       
   170     if (iActivePairingOk->IsActive())
       
   171         {
       
   172         iPairingOkTimer.Cancel();
       
   173         iActivePairingOk->CancelRequest();
       
   174         UnSetPairResult();  // we might have set it before (if the link went down) so we want to reset it.   
       
   175         }
       
   176     if (aDev.LinkKeyType() == ELinkKeyUnauthenticatedNonUpgradable && !iUserAwarePairing)
       
   177 		{
       
   178 		// If an application uses btengconnman API to connect a service of 
       
   179 		// this device and JW pairing occurred as part of security enforcement,
       
   180 		// it shall be a user aware pairing, and we shall add this device in paired
       
   181 		// view. In this way, user is able to disconnect the device from our UI.
       
   182 		// Otherwise the link key has been created by a device without IO requesting 
       
   183 		// a service connection with phone. We won't take any action (e.g. remove 
       
   184 		// link key) in this case. As the result, this device can't be seen in our UI, 
       
   185 		// however other applications are still freely to use its services.
       
   186 		TRACE_INFO(_L("[BTEng]: CBTEngIncPair: JW pairing with no IO device" ) )
       
   187 		TBTEngConnectionStatus status = iParent.IsDeviceConnected( aDev.Address() );
       
   188 		if ( status == EBTEngConnecting || status == EBTEngConnected )
       
   189 			{
       
   190 			// the return error is ingore as we can not have other proper 
       
   191 			// exception handling option:
       
   192 			(void) iParent.AddUiCookieJustWorksPaired( aDev );
       
   193 			}
       
   194 		iParent.RenewPairer( NULL );
       
   195 		}
       
   196     else if (aDev.LinkKeyType() == ELinkKeyUnauthenticatedUpgradable && !iUserAwarePairing)
       
   197 		{
       
   198 		// The linkkey has been created  by an incoming OBEX service request
       
   199 		// which resulted a pairing event received from pair server.
       
   200 		TRACE_INFO(_L("[BTEng]: CBTEngIncPair: JW pairing with IO device" ) )
       
   201 		iParent.RenewPairer( NULL );
       
   202 		}
       
   203     else
       
   204 		{
       
   205 		if (aDev.LinkKeyType() == ELinkKeyUnauthenticatedNonUpgradable || aDev.LinkKeyType() == ELinkKeyUnauthenticatedUpgradable)
       
   206 			{
       
   207 			// The user was involved in the pairing, so display in the paired devices list
       
   208 			(void) iParent.AddUiCookieJustWorksPaired(aDev);
       
   209 			}
       
   210 		TRACE_INFO(_L("[BTEng]: CBTEngIncPair: Non-JW pairing"))
       
   211 		// Other pairing model than Just Works:
       
   212 		CancelPlaNotification();
       
   213 		SetPairResult( KErrNone );
       
   214 		ShowPairingNoteAndAuthorizeQuery();
       
   215 		}
       
   216     TRACE_FUNC_EXIT
       
   217     }
       
   218 
       
   219 // ---------------------------------------------------------------------------
       
   220 // From class MBTEngActiveObserver.
       
   221 // ---------------------------------------------------------------------------
       
   222 //
       
   223 void CBTEngIncPair::RequestCompletedL( CBTEngActive* /*aActive*/, TInt aId, TInt aStatus )
       
   224     {
       
   225     TRACE_FUNC_ARG( ( _L( "aId: %d, aStatus: %d"), aId, aStatus ) )
       
   226         // Check which request completed.
       
   227     switch( aId )
       
   228         {
       
   229         case EPhysicalLinkNotify:
       
   230             {
       
   231                 // Check if the link has disconnected.
       
   232             HandlePhysicalLinkResultL( aStatus );
       
   233             break;
       
   234             }
       
   235         case EDevicePairUserNotification:
       
   236             {
       
   237                 // the user has been informed of the result, kill this:
       
   238             TRACE_INFO(_L("[BTENG]:CBTEngIncPair authorization notifier completed") )
       
   239             iParent.RenewPairer( NULL );
       
   240             break;
       
   241             }
       
   242         case EWaitingForPairingOk:
       
   243             {
       
   244             // pairing failed, inform user:
       
   245             if (iPairResult == KErrNone)
       
   246                 {
       
   247                 // iPairResult must have been set as an error. if it's not it means somewhere else
       
   248                 // it has been reset. But we need to have it set to an error as we are notifying 
       
   249                 // the "unable to pair" message.
       
   250                 SetPairResult(KErrGeneral);
       
   251                 }
       
   252             ShowPairingNoteAndAuthorizeQuery();
       
   253             break;
       
   254             }    
       
   255         default:
       
   256                 // Should not be possible, but no need for handling.
       
   257             TRACE_INFO( (_L("[BTEng]: CBTEngIncPair::RequestCompletedL unhandled event!!") ) )
       
   258             break;
       
   259         }
       
   260     TRACE_FUNC_EXIT
       
   261     }
       
   262 
       
   263 // ---------------------------------------------------------------------------
       
   264 // From class MBTEngActiveObserver.
       
   265 // Handles a leave in RequestCompleted by simply self-destructing.
       
   266 // ---------------------------------------------------------------------------
       
   267 //
       
   268 void CBTEngIncPair::HandleError( CBTEngActive* aActive, TInt aId, TInt aError )
       
   269     {
       
   270     TRACE_FUNC_ARG( ( _L( "request id: %d, error: %d" ), aId, aError ) )
       
   271     (void) aActive;
       
   272     (void) aId;
       
   273     (void) aError;
       
   274         // Our error handling is to just stop observing. 
       
   275         // Nothing critical to be preserved herer, the user 
       
   276         // just won't get any notification of pairing result.
       
   277     iParent.RenewPairer( NULL );
       
   278     }
       
   279 
       
   280 // ---------------------------------------------------------------------------
       
   281 // Subscribe to physical link notifications. 
       
   282 // physical link must exist when calling this function.
       
   283 // ---------------------------------------------------------------------------
       
   284 //
       
   285 void CBTEngIncPair::MonitorPhysicalLink()
       
   286     {
       
   287     TRACE_FUNC_ENTRY
       
   288     iActive->SetRequestId( EPhysicalLinkNotify );
       
   289         // Subscribe to disconnect and error events.
       
   290     iPla.NotifyNextBasebandChangeEvent( iBbEvent, 
       
   291                             iActive->RequestStatus(), 
       
   292                             ENotifyPhysicalLinkDown | ENotifyPhysicalLinkError );
       
   293     iActive->GoActive();
       
   294     TRACE_FUNC_EXIT
       
   295     }
       
   296 
       
   297 // ---------------------------------------------------------------------------
       
   298 // Opens the adaptor if physical link exists.
       
   299 // ---------------------------------------------------------------------------
       
   300 //
       
   301 TInt CBTEngIncPair::OpenPhysicalLinkAdaptor()
       
   302     {
       
   303     TRACE_FUNC_ENTRY
       
   304     TInt err ( KErrNone );
       
   305     if( !iPla.IsOpen() )
       
   306         {
       
   307             // Try to open the adapter in case it failed earlier.
       
   308             // This can happen for outgoing dedicated bonding with 
       
   309             // non-SSP device, as the PIN dialog can be kept open even 
       
   310             // though the link has dropped because of a time-out.
       
   311         err = iPla.Open( iParent.SocketServ(), iAddr );
       
   312         }
       
   313     TRACE_INFO( (_L("[BTEng]: CBTEngIncPair::HasPhysicalLink ? %d"), iPla.IsOpen() ) )
       
   314     return err;
       
   315     }
       
   316 
       
   317 // ---------------------------------------------------------------------------
       
   318 // Cancel outstanding physical link notification
       
   319 // ---------------------------------------------------------------------------
       
   320 //
       
   321 void CBTEngIncPair::CancelPlaNotification()
       
   322     {
       
   323     TRACE_FUNC_ENTRY
       
   324     if( iActive && iActive->IsActive() && 
       
   325             iActive->RequestId() == EPhysicalLinkNotify )
       
   326         {
       
   327         // cancel Baseband monitor
       
   328         iPla.CancelNextBasebandChangeEventNotifier();
       
   329         iActive->Cancel();
       
   330         }
       
   331     TRACE_FUNC_EXIT
       
   332     }
       
   333 
       
   334 // ---------------------------------------------------------------------------
       
   335 // Handle a physical link event. Notify pair failed if physical link is down.
       
   336 // ---------------------------------------------------------------------------
       
   337 //
       
   338 void CBTEngIncPair::HandlePhysicalLinkResultL( TInt aResult )
       
   339     {
       
   340     TRACE_FUNC_ARG( ( _L( " BBEvent 0x%08X, code %d"), 
       
   341                             iBbEvent().EventType(), iBbEvent().SymbianErrorCode() ) )
       
   342         // Check if the connection is still alive.
       
   343     TBool physicalLinkDown = 
       
   344         ( iBbEvent().EventType() == ENotifyPhysicalLinkDown | ENotifyPhysicalLinkError );
       
   345 
       
   346     if( aResult || physicalLinkDown )
       
   347         {
       
   348         // link went down. It might be because of pairing failed or the remote device disconnected the
       
   349         // physical link after a successful pairing.
       
   350         // we wait for 0.5 secs before notifying the "unable to pair" message as, if the pair is 
       
   351         // successful, we manage it to show the right confirmation message.
       
   352         SetPairResult( (aResult == 0) ? KErrGeneral : aResult );
       
   353         iPairingOkTimer.After(iActivePairingOk->iStatus, KBTEngWaitingForPairingOkDelay);
       
   354         iActivePairingOk->GoActive();
       
   355         }
       
   356     else
       
   357         {
       
   358         // Uninteresting event, re-subscribe.
       
   359         MonitorPhysicalLink();
       
   360         }
       
   361     TRACE_FUNC_EXIT
       
   362     }