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