bluetoothengine/btnotif/btnotifsrv/src/btnotifconnection.cpp
changeset 29 48ae3789ce00
equal deleted inserted replaced
28:7e2761e776bd 29:48ae3789ce00
       
     1 /*
       
     2 * ============================================================================
       
     3 *  Name        : btnotifconnection.cpp
       
     4 *  Part of     : bluetoothengine / btnotif
       
     5 *  Description : Class for observing events of a single connection, and for 
       
     6 *                managing any user notifications related to the connection.
       
     7 *
       
     8 *  Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     9 *  All rights reserved.
       
    10 *  This component and the accompanying materials are made available
       
    11 *  under the terms of "Eclipse Public License v1.0"
       
    12 *  which accompanies this distribution, and is available
       
    13 *  at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
    14 *
       
    15 *  Initial Contributors:
       
    16 *  Nokia Corporation - initial contribution.
       
    17 *
       
    18 *  Contributors:
       
    19 *  Nokia Corporation
       
    20 * ============================================================================
       
    21 * Template version: 4.1
       
    22 */
       
    23 
       
    24 #include "btnotifconnection.h"
       
    25 #include <btextnotifiers.h>
       
    26 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    27 #include <btextnotifierspartner.h>
       
    28 #endif
       
    29 
       
    30 #include "btnotifconnectiontracker.h"
       
    31 #include "btnotifpairinghelper.h"
       
    32 #include "btnotificationmanager.h"
       
    33 #include "btnotifclientserver.h"
       
    34 #include "bluetoothtrace.h"
       
    35 
       
    36 /**  Id for the baseband connection watcher active object. */
       
    37 const TInt KConnectionWatcher = 40;
       
    38 /**  Id for the registry watcher active object. */
       
    39 const TInt KRegistryWatcher = 41;
       
    40 /**  Id for the active object for updating the registry. */
       
    41 const TInt KRegistryRetriever = 42;
       
    42 /**  Event mask for subscribing to baseband connection events  
       
    43  * (need to check if these are appropriate). */
       
    44 const TInt KBbEventMask = ENotifyAnyRole | ENotifyAuthenticationComplete |
       
    45     ENotifyPhysicalLinkUp | ENotifyPhysicalLinkDown | ENotifyPhysicalLinkError;
       
    46 
       
    47 
       
    48 // ======== LOCAL FUNCTIONS ========
       
    49 
       
    50 // ---------------------------------------------------------------------------
       
    51 // Decide the device name to display from the device information, and 
       
    52 // converts the name if necessary.
       
    53 // ---------------------------------------------------------------------------
       
    54 //
       
    55 void GetDeviceNameL( TBTDeviceName& aName, const CBTDevice& aDevice )
       
    56     {
       
    57     if( aDevice.IsValidFriendlyName() )
       
    58         {
       
    59         aName.Copy( aDevice.FriendlyName() );
       
    60         }
       
    61     else
       
    62         {
       
    63         aName.Zero();
       
    64         if( aDevice.IsValidDeviceName() )
       
    65             {
       
    66             aName = BTDeviceNameConverter::ToUnicodeL( aDevice.DeviceName() );
       
    67             }
       
    68         }
       
    69     }
       
    70 
       
    71 
       
    72 // ---------------------------------------------------------------------------
       
    73 // Compare 2 device records device pairing has succeeded.
       
    74 // aDev2 is the updated device record, aDev1 is the previous record.
       
    75 // ---------------------------------------------------------------------------
       
    76 //
       
    77 TBool CheckRegistryPairedStatus( const CBTDevice* aOrig, const CBTDevice* aNew )
       
    78     {
       
    79     TBool result = EFalse;
       
    80     // Use the device class to check that this has any valid information.
       
    81     if( aOrig->AsNamelessDevice().IsValidDeviceClass() &&
       
    82         !( aOrig->IsValidPaired() && aOrig->IsPaired() ) ||
       
    83         aOrig->LinkKeyType() == ELinkKeyUnauthenticatedUpgradable )
       
    84         {
       
    85         // Only consider the result if the original device is not marked as paired.
       
    86         if( aNew->IsValidPaired() && aNew->IsPaired() && aNew->IsValidLinkKey() && 
       
    87             aNew->LinkKeyType() != ELinkKeyUnauthenticatedUpgradable )
       
    88             {
       
    89             // The new device record has valid pairing information, so
       
    90             // this device is now paired.
       
    91             result = ETrue;
       
    92             }
       
    93         }
       
    94     return result;
       
    95     }
       
    96 
       
    97 
       
    98 // ======== MEMBER FUNCTIONS ========
       
    99 
       
   100 // ---------------------------------------------------------------------------
       
   101 // C++ default constructor
       
   102 // ---------------------------------------------------------------------------
       
   103 //
       
   104 CBTNotifConnection::CBTNotifConnection(  const TBTDevAddr& aAddr,
       
   105     CBTNotifConnectionTracker* aTracker )
       
   106 :   iAddr( aAddr ),
       
   107     iTracker( aTracker )
       
   108     {
       
   109     }
       
   110 
       
   111 
       
   112 // ---------------------------------------------------------------------------
       
   113 // Symbian 2nd-phase constructor
       
   114 // ---------------------------------------------------------------------------
       
   115 //
       
   116 void CBTNotifConnection::ConstructL()
       
   117     {
       
   118     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   119     iDevice = CBTDevice::NewL( iAddr );
       
   120     iPhyActive = CBtSimpleActive::NewL(*this, KConnectionWatcher );
       
   121     iRegActive = CBtSimpleActive::NewL( *this, KRegistryRetriever );
       
   122     // ToDo: need to check if this succeeds if a connection is 
       
   123     // being created, in case of outgoing pairing.
       
   124     User::LeaveIfError( iPhyLink.Open( iTracker->SocketServerSession(), iAddr ) );
       
   125     // Subscribe to events.
       
   126     iBasebandEvent.FillZ(); // To be sure that we are not reading false events.
       
   127     iPhyLink.NotifyNextBasebandChangeEvent( iBasebandEvent,
       
   128                 iPhyActive->RequestStatus(), KBbEventMask );
       
   129     iPhyActive->GoActive();
       
   130     // Get the details from BT registry
       
   131     TBTRegistrySearch pattern;
       
   132     pattern.FindAddress( iAddr );
       
   133     User::LeaveIfError( iRegistry.Open( iTracker->RegistryServerSession() ) );
       
   134     iRegistry.CreateView( pattern, iRegActive->RequestStatus() );
       
   135     iRegActive->GoActive();
       
   136     iCurrentOp = EReadingRegistry;
       
   137     iRegDevArray  = new CBTDeviceArray(1);  // only 1 entry ever used
       
   138     // ToDo: more initialization needed?
       
   139     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   140     }
       
   141 
       
   142 
       
   143 // ---------------------------------------------------------------------------
       
   144 // NewLC.
       
   145 // ---------------------------------------------------------------------------
       
   146 //
       
   147 CBTNotifConnection* CBTNotifConnection::NewLC( const TBTDevAddr& aAddr,
       
   148     CBTNotifConnectionTracker* aTracker )
       
   149     {
       
   150     CBTNotifConnection* self = new( ELeave ) CBTNotifConnection( aAddr, aTracker );
       
   151     CleanupStack::PushL( self );
       
   152     self->ConstructL();
       
   153     return self;
       
   154     }
       
   155 
       
   156 
       
   157 // ---------------------------------------------------------------------------
       
   158 // Destructor
       
   159 // ---------------------------------------------------------------------------
       
   160 //
       
   161 CBTNotifConnection::~CBTNotifConnection()
       
   162     {
       
   163     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   164     if( iNotification )
       
   165         {
       
   166         // Clear the notification callback, we cannot receive them anymore.
       
   167         iNotification->RemoveObserver();
       
   168         iNotification->Close(); // Also dequeues the notification from the queue.
       
   169         iNotification = NULL;
       
   170         }
       
   171     delete iRegActive;
       
   172     delete iRegistryResponse;
       
   173     iRegistry.Close();
       
   174     delete iDevMan;
       
   175 
       
   176     delete iPhyActive;
       
   177     iPhyLink.Close();
       
   178     delete iDevice;
       
   179     delete iPairingHelper;
       
   180 
       
   181     while( iMsgHandleQ.Count() )
       
   182         {
       
   183         CompleteClientRequest( KErrDisconnected, KNullDesC8 );
       
   184         }
       
   185     iMsgHandleQ.Close();
       
   186     iAcceptedConnections.Close();
       
   187     iDeniedConnections.Close();
       
   188     iRegDevArray->ResetAndDestroy(); 
       
   189     delete iRegDevArray;
       
   190     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   191     }
       
   192 
       
   193 
       
   194 // ---------------------------------------------------------------------------
       
   195 // Check what to do next.
       
   196 // This function should be called whenever we may be ready for the next
       
   197 // request/action, which is from any callback function i.e. 
       
   198 // MBAORequestCompletedL, MBRNotificationClosed, HandleNotifierRequestL and
       
   199 // CancelNotifierRequestL.
       
   200 // ---------------------------------------------------------------------------
       
   201 //
       
   202 void CBTNotifConnection::CheckNextOperationL()
       
   203     {
       
   204     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   205     if( iCurrentOp == EIdle )
       
   206         {
       
   207         // Check the link state, to see if it has gone down already.
       
   208         TUint32 linkState = 0;
       
   209         TInt err = iPhyLink.PhysicalLinkState( linkState );
       
   210         TBool linkDown = linkState & ENotifyPhysicalLinkDown;
       
   211         if( ( !err && linkDown ) || err == KErrDisconnected )
       
   212             {
       
   213             // The link state tells us that the link is down,
       
   214             // inform the connection tracker the we are done.
       
   215             iTracker->HandleLinkCountChangeL();
       
   216             // Note that we may be deleted now!
       
   217             }
       
   218         else if( iMsgHandleQ.Count() )
       
   219             {
       
   220             // Get the next request and handle it.
       
   221             // ToDo: differentiate between notifier and pairing message!
       
   222             const RMessage2* message = iTracker->Server()->FindMessageFromHandle( iMsgHandleQ[0] );
       
   223             NOTIF_NOTHANDLED( message )
       
   224             TInt opcode = message->Function();
       
   225             if( opcode <= EBTNotifUpdateNotifier )
       
   226                 {
       
   227                 TBuf8<0x250> paramsBuf;    // Size needs to be long enough to read all possible parameter sizes.
       
   228                 message->ReadL( EBTNotifSrvParamSlot, paramsBuf );
       
   229                 HandleNotifierRequestL( paramsBuf, *message );
       
   230                 }
       
   231             else
       
   232                 {
       
   233                 iMsgHandleQ.Remove( 0 );
       
   234                 StartBondingL( *message );
       
   235                 }
       
   236             }
       
   237         }
       
   238     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   239     }
       
   240 
       
   241 
       
   242 // ---------------------------------------------------------------------------
       
   243 // Complete the first outstanding client request and removes it from the queue.
       
   244 // ---------------------------------------------------------------------------
       
   245 //
       
   246 void CBTNotifConnection::CompleteClientRequest( TInt aReason, const TDesC8& aReply )
       
   247     {
       
   248     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   249     NOTIF_NOTHANDLED( iMsgHandleQ.Count() )
       
   250     TInt err = iTracker->Server()->CompleteMessage( iMsgHandleQ[0], aReason, aReply );
       
   251     NOTIF_NOTHANDLED( !err )
       
   252     iMsgHandleQ.Remove( 0 );
       
   253     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   254     }
       
   255 
       
   256 
       
   257 // ---------------------------------------------------------------------------
       
   258 // Distinguish a request and pass to corresponding handle.
       
   259 // ---------------------------------------------------------------------------
       
   260 //
       
   261 void CBTNotifConnection::HandleNotifierRequestL( const TDesC8& aParams,
       
   262     const RMessage2& aMessage )
       
   263     {
       
   264     BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aMessage.Int0() );
       
   265     if( !iMsgHandleQ.Count() || iMsgHandleQ[0] != aMessage.Handle() )
       
   266         {
       
   267         // If we are processing a queued request, we of course don't queue 
       
   268         // it again. In that case we are handling the first request from the queue.
       
   269         iMsgHandleQ.AppendL( aMessage.Handle() );
       
   270         }
       
   271     if( iCurrentOp == EIdle || iCurrentOp == EBonding )
       
   272         {
       
   273         // ToDo: check non-pairing operation when bonding
       
   274         TInt uid = aMessage.Int0();
       
   275         if( uid == KBTManAuthNotifierUid.iUid )
       
   276             {
       
   277             HandleAuthorizationReqL( aParams );
       
   278             }
       
   279         else if( uid == KBTManPinNotifierUid.iUid ||
       
   280                  uid == KBTPinCodeEntryNotifierUid.iUid ||
       
   281                  uid == KBTNumericComparisonNotifierUid.iUid ||
       
   282                  uid == KBTPasskeyDisplayNotifierUid.iUid )
       
   283             {
       
   284             if( !iPairingHelper )
       
   285                 {
       
   286                 BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST, 
       
   287                         "[BTNOTIF]\t CBTNotifConnection::HandleNotifierRequestL: creating CBTNotifPairingHelper");
       
   288                 iPairingHelper = CBTNotifPairingHelper::NewL( this, iTracker );
       
   289                 }
       
   290             if( iCurrentOp != EBonding  )
       
   291                 {
       
   292                 iCurrentOp = EPairing;
       
   293                 }
       
   294             iPairingHelper->StartPairingNotifierL( uid, aParams );
       
   295             }
       
   296         // We may be done with the current request, proceed to the next one
       
   297         CheckNextOperationL();
       
   298         }
       
   299     BOstraceFunctionExit1( DUMMY_DEVLIST, this );
       
   300     }
       
   301 
       
   302 
       
   303 // ---------------------------------------------------------------------------
       
   304 // Update a notifier, update the outstanding dialog if the notifier request 
       
   305 // is currently being served.
       
   306 // ---------------------------------------------------------------------------
       
   307 //
       
   308 void CBTNotifConnection::HandleNotifierUpdateL( const TDesC8& aParams,
       
   309     const RMessage2& aMessage )
       
   310     {
       
   311     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   312     NOTIF_NOTHANDLED( iCurrentOp != EIdle )
       
   313     (void) aParams;
       
   314     TBuf8<0x250> paramsBuf;    // Size needs to be long enough to read all possible sizes.
       
   315     aMessage.ReadL( EBTNotifSrvParamSlot, paramsBuf );
       
   316     TInt uid = aMessage.Int0();
       
   317     if( uid == KBTManAuthNotifierUid.iUid )
       
   318         {
       
   319         TBTNotifierUpdateParams params;
       
   320         TPckgC<TBTNotifierUpdateParams> paramsPckg( params );
       
   321         paramsPckg.Set( paramsBuf );
       
   322         // The result means result of conversion to unicode
       
   323         if( !paramsPckg().iResult )
       
   324             {
       
   325             // Only update locally, registry will update us with the same info later on.
       
   326             iDevice->SetDeviceNameL( BTDeviceNameConverter::ToUTF8L( paramsPckg().iName ) );
       
   327             if( iNotification )
       
   328                 {
       
   329                 // Update the dialog with the new name. It is up to the dialog to 
       
   330                 // determine the validity (in case another dialog is shown).
       
   331                 //iNotification->Update(  )
       
   332                 }
       
   333             }
       
   334         }
       
   335     else if( iPairingHelper && ( uid == KBTPinCodeEntryNotifierUid.iUid ||
       
   336              uid == KBTNumericComparisonNotifierUid.iUid ||
       
   337              uid == KBTPasskeyDisplayNotifierUid.iUid ) )
       
   338         {
       
   339         // Just forward to pairing helper
       
   340         iPairingHelper->UpdatePairingNotifierL( uid, paramsBuf );
       
   341         }
       
   342     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   343     }
       
   344 
       
   345 
       
   346 // ---------------------------------------------------------------------------
       
   347 // Cancel a request, dismiss the outstanding dialog if the notifier request 
       
   348 // is currently being served.
       
   349 // ---------------------------------------------------------------------------
       
   350 //
       
   351 void CBTNotifConnection::CancelNotifierRequestL( const RMessage2& aMessage )
       
   352     {
       
   353     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   354     NOTIF_NOTHANDLED( iCurrentOp != EIdle )
       
   355     TInt pos = iMsgHandleQ.Find( aMessage.Handle() );
       
   356     if( pos > KErrNotFound )
       
   357         {
       
   358         // We have queued the message, remove it from the queue.
       
   359         iMsgHandleQ.Remove( pos );
       
   360         // We use the supplied handle to remove it, as it may not be
       
   361         // the first in the queue.
       
   362         TInt err = iTracker->Server()->CompleteMessage( aMessage.Handle(), KErrCancel, KNullDesC8 );
       
   363         NOTIF_NOTHANDLED( !err )
       
   364         if( pos == 0 )
       
   365             {
       
   366             // There could be the case that we are still post-processing
       
   367             // the previous request (e.g. blocking query), then the next
       
   368             // notification is not yet started but the first in the queue.
       
   369             // We can see that from the current operation type.
       
   370             if( iNotification && iCurrentOp < EAdditionalNotes )
       
   371                 {
       
   372                 // Cancel the user query
       
   373                 // This will also unregister us from the notification.
       
   374                 TInt err = iNotification->Close();
       
   375                 NOTIF_NOTHANDLED( !err )
       
   376                 iNotification = NULL;
       
   377                 iCurrentOp = EIdle;
       
   378                 }
       
   379             if( iPairingHelper )
       
   380                 {
       
   381                 // The pairing helper calls back PairingCompleted and sets state.
       
   382                 iPairingHelper->CancelPairingNotifierL( aMessage.Int0() );
       
   383                 // The pairing helper may have now been deleted.
       
   384                 }
       
   385             }
       
   386         }
       
   387     // We may be done with the current request, proceed to the next one
       
   388     CheckNextOperationL();
       
   389     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   390     }
       
   391 
       
   392 
       
   393 // ---------------------------------------------------------------------------
       
   394 // Start a bonding operation with the remote device.
       
   395 // ---------------------------------------------------------------------------
       
   396 //
       
   397 void CBTNotifConnection::StartBondingL( const RMessage2& aMessage )
       
   398     {
       
   399     BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aMessage.Function() );
       
   400     if( iCurrentOp == EIdle || iCurrentOp > EInternalOperations )
       
   401         {
       
   402         __ASSERT_ALWAYS( !iPairingHelper, PanicServer( EBTNotifPanicBadState ) );
       
   403         iPairingHelper = CBTNotifPairingHelper::NewL( this, iTracker );
       
   404         // The pairingg helper stored the handle, not in our queue here.
       
   405         // This is because bonding will generate a pairing notifier request, which 
       
   406         // will be completed first. The bookkeeping gets complicated if we have to
       
   407         // re-order the queue here.
       
   408         iPairingHelper->StartBondingL( aMessage.Handle() );
       
   409         iCurrentOp = EBonding;
       
   410         }
       
   411     else if( iCurrentOp == EPairing || iCurrentOp == EBonding )
       
   412         {
       
   413         // We only do one pairing at the time.
       
   414         User::Leave( KErrInUse );
       
   415         }
       
   416     else
       
   417         {
       
   418         // We only store it here if it is not handled immediately.
       
   419         iMsgHandleQ.AppendL( aMessage.Handle() );
       
   420         }
       
   421     BOstraceFunctionExit1( DUMMY_DEVLIST, this );
       
   422     }
       
   423 
       
   424 
       
   425 // ---------------------------------------------------------------------------
       
   426 // Cancel an ongoing bonding operation with the remote device.
       
   427 // ---------------------------------------------------------------------------
       
   428 //
       
   429 void CBTNotifConnection::CancelBondingL()
       
   430     {
       
   431     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   432     if( iPairingHelper )
       
   433         {
       
   434         iPairingHelper->CancelBondingL();
       
   435         }
       
   436     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   437     }
       
   438 
       
   439 
       
   440 // ---------------------------------------------------------------------------
       
   441 // The pairing handler has completed a pairing operation.
       
   442 // ---------------------------------------------------------------------------
       
   443 //
       
   444 void CBTNotifConnection::PairingCompleted()
       
   445     {
       
   446     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   447     __ASSERT_ALWAYS( iPairingHelper, PanicServer( EBTNotifPanicNullMember ) );
       
   448     if( iPairingHelper->CurrentOperation() == CBTNotifPairingHelper::EIdle )
       
   449         {
       
   450         // We are still idle. Remove the pairing helper
       
   451         delete iPairingHelper;
       
   452         iPairingHelper = NULL;
       
   453         }
       
   454     if( iCurrentOp == EPairing || iCurrentOp == EBonding )
       
   455         {
       
   456         iCurrentOp = EIdle;
       
   457         TRAP_IGNORE( CheckNextOperationL() );
       
   458         }
       
   459     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   460     }
       
   461 
       
   462 
       
   463 // ---------------------------------------------------------------------------
       
   464 // Process a new pairing result, and determine if we need to show 
       
   465 // anything to the user.
       
   466 // ---------------------------------------------------------------------------
       
   467 //
       
   468 void CBTNotifConnection::PairingResult( TInt aError )
       
   469     {
       
   470     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   471     if( !iPairingHelper )
       
   472         {
       
   473         TRAP_IGNORE( iPairingHelper = CBTNotifPairingHelper::NewL( this, iTracker ) );
       
   474         }
       
   475     if( iPairingHelper )
       
   476         {
       
   477         iPairingHelper->HandleAuthenticationCompleteL( aError );
       
   478         }
       
   479     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   480     }
       
   481 
       
   482 
       
   483 // ---------------------------------------------------------------------------
       
   484 // Process the new service-level connection, and determine if we need to
       
   485 // show anything to the user.
       
   486 // ---------------------------------------------------------------------------
       
   487 //
       
   488 void CBTNotifConnection::ServiceConnectedL( TBTProfile aProfile )
       
   489     {
       
   490     (void) aProfile;
       
   491     }
       
   492 
       
   493 
       
   494 // ---------------------------------------------------------------------------
       
   495 // Process the new service-level disconnection, and determine if we need to
       
   496 // show anything to the user.
       
   497 // ---------------------------------------------------------------------------
       
   498 //
       
   499 void CBTNotifConnection::ServiceDisconnectedL( TBTProfile aProfile )
       
   500     {
       
   501     (void) aProfile;
       
   502     }
       
   503 
       
   504 
       
   505 // ---------------------------------------------------------------------------
       
   506 // Ask the user if he/she wants to block future connection requests. 
       
   507 // ---------------------------------------------------------------------------
       
   508 //
       
   509 void CBTNotifConnection::LaunchBlockingQueryL()
       
   510     {
       
   511     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   512     iCurrentOp = EBlocking;
       
   513     TBTDialogResourceId resourceId = EBlockUnpairedDevice;
       
   514     if( iDevice->IsValidPaired() && iDevice->IsPaired() &&
       
   515         iDevice->LinkKeyType() != ELinkKeyUnauthenticatedUpgradable )
       
   516         {
       
   517         resourceId = EBlockPairedDevice;
       
   518         }
       
   519     PrepareNotificationL( TBluetoothDialogParams::EQuery, resourceId );
       
   520     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   521     }
       
   522 
       
   523 
       
   524 // ---------------------------------------------------------------------------
       
   525 // Modify the record for the remote device in BTRegistry, with the changes 
       
   526 // already made in the local record.
       
   527 // ---------------------------------------------------------------------------
       
   528 //
       
   529 void CBTNotifConnection::UpdateRegistryEntryL()
       
   530     {
       
   531     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   532     // We use CBTEngDevMan here. We could use the registry API directly, however,
       
   533     // using this convenience API makes the registry processing much simpler.
       
   534     if( !iDevMan )
       
   535         {
       
   536         iDevMan = CBTEngDevMan::NewL( this );
       
   537         }
       
   538     iDevMan->ModifyDevice( *iDevice );
       
   539     if( iCurrentOp == EIdle ||
       
   540         ( ( iCurrentOp == EPairing || iCurrentOp == EBonding ) &&
       
   541           iPairingHelper->CurrentOperation() == CBTNotifPairingHelper::EIdle ) )
       
   542         {
       
   543         // To make sure that we don't get deleted while updating.
       
   544         iCurrentOp = EUpdatingRegistry;
       
   545         }
       
   546     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   547     }
       
   548 
       
   549 // ---------------------------------------------------------------------------
       
   550 // Modify the record for the remote device in BTRegistry, if aTrusted == true, then
       
   551 // update trusted status after reading device info from registry
       
   552 //
       
   553 // ---------------------------------------------------------------------------
       
   554 
       
   555 void CBTNotifConnection::UpdateRegistryEntryL( TBool aTrusted )
       
   556     {
       
   557     BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aTrusted );
       
   558     if (!aTrusted) {
       
   559         UpdateRegistryEntryL();
       
   560         return;
       
   561         }
       
   562     // We use CBTEngDevMan here. We could use the registry API directly, however,
       
   563     // using this convenience API makes the registry processing much simpler.
       
   564     if( !iDevMan )
       
   565         {
       
   566         iDevMan = CBTEngDevMan::NewL( this );
       
   567         }
       
   568     // first read device info from registry, to make sure we have up-to-date local info
       
   569     iCurrentOp = EReadingRegistry;
       
   570     GetDeviceFromRegistry( iDevice->BDAddr() );
       
   571     BOstraceFunctionExit1( DUMMY_DEVLIST, this );
       
   572     }
       
   573 
       
   574 // ---------------------------------------------------------------------------
       
   575 // From class MBTNotificationResult.
       
   576 // Handle a result from a user query.
       
   577 // ---------------------------------------------------------------------------
       
   578 //
       
   579 void CBTNotifConnection::MBRDataReceived( CHbSymbianVariantMap & aData )
       
   580     {
       
   581     (void) aData;
       
   582     NOTIF_NOTIMPL
       
   583     }
       
   584 
       
   585 
       
   586 // ---------------------------------------------------------------------------
       
   587 // From class MBTNotificationResult.
       
   588 // The notification is finished.
       
   589 // ---------------------------------------------------------------------------
       
   590 //
       
   591 void CBTNotifConnection::MBRNotificationClosed( TInt aError, const TDesC8& aData )
       
   592     {
       
   593     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   594     // ToDo: call leaving function from here!
       
   595     __ASSERT_ALWAYS( iCurrentOp != EIdle, PanicServer( EBTNotifPanicBadState ) );
       
   596     // First unregister from the notification, so we can already get the next one.
       
   597     iNotification->RemoveObserver();
       
   598     iNotification = NULL;
       
   599     TRAP_IGNORE( NotificationClosedL( aError, aData ) );
       
   600     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   601     }
       
   602 
       
   603 
       
   604 // ---------------------------------------------------------------------------
       
   605 // From class MBtSimpleActiveObserver.
       
   606 // Handle the active object completion.
       
   607 // ---------------------------------------------------------------------------
       
   608 //
       
   609 void CBTNotifConnection::RequestCompletedL( CBtSimpleActive* aActive,
       
   610     TInt aStatus )
       
   611     {
       
   612     BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, aActive->RequestId() );
       
   613     switch( aActive->RequestId() )
       
   614         {
       
   615         case KRegistryRetriever:
       
   616             {
       
   617             BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST,  
       
   618                     "[BTNOTIF]\t CBTNotifConnection::MBAORequestCompletedL: KRegistryRetriever" );
       
   619             if( !iRegistryResponse )
       
   620                 {
       
   621                 // We have just created the view, now get the results.
       
   622                 // There can only be one result, as the address is unique.
       
   623                 // (note: how about LE random addresses?)
       
   624                 // Or then we have tried to re-open an existing view, so we get KErrInuse.
       
   625                 // We anyway just get the results.
       
   626                 __ASSERT_ALWAYS( aStatus < 2, PanicServer( EBTNotifPanicCorrupt ) );
       
   627                 iRegistryResponse = CBTRegistryResponse::NewL( iRegistry );
       
   628                 iRegistryResponse->Start( iRegActive->RequestStatus() );
       
   629                 iRegActive->GoActive();
       
   630                 }
       
   631             else
       
   632                 {
       
   633                 if( !aStatus )
       
   634                     {
       
   635                     // There can be only one result.
       
   636                     __ASSERT_ALWAYS( iRegistryResponse->Results().Count() == 1, PanicServer( EBTNotifPanicCorrupt ) );
       
   637                     CBTDevice* regDevice = iRegistryResponse->Results()[0];
       
   638                     TBool paired = CheckRegistryPairedStatus( iDevice, regDevice );
       
   639                     iDevice->UpdateL( *regDevice );
       
   640                     if( paired )
       
   641                         {
       
   642                         __ASSERT_ALWAYS( iPairingHelper, PanicServer( EBTNotifPanicNullMember ) );
       
   643                         iPairingHelper->HandleAuthenticationCompleteL( KErrNone );
       
   644                         }
       
   645                     }
       
   646                 // ToDo: error handling of registry response result?
       
   647                 delete iRegistryResponse;
       
   648                 iRegistryResponse = NULL;
       
   649                 }
       
   650             if( iCurrentOp == EReadingRegistry && !iRegActive->IsActive() )
       
   651                 {
       
   652                 // If this is part of the sequence of operations, we are done.
       
   653                 // Otherwise we just update with the latest info from registry,
       
   654                 // and then we don't interrupt or change the state.
       
   655                 iCurrentOp = EIdle;
       
   656                 }
       
   657             }
       
   658             // ToDo: start registry watching (preferably using registry API when this is available)
       
   659            break;
       
   660        case KRegistryWatcher:
       
   661            {
       
   662            BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST,  
       
   663                    "[BTNOTIF]\t CBTNotifConnection::MBAORequestCompletedL: KRegistryWatcher" );
       
   664            NOTIF_NOTHANDLED( !aStatus )
       
   665            // Ignore updates while we are already retrieving.
       
   666            if( !iRegActive->IsActive() )
       
   667                {
       
   668                // Refresh our information with the latest from registry
       
   669                iRegActive->SetRequestId( KRegistryRetriever );
       
   670                TBTRegistrySearch pattern;
       
   671                pattern.FindAddress( iAddr );
       
   672                iRegistry.CreateView( pattern, iRegActive->RequestStatus() );
       
   673                iRegActive->GoActive();
       
   674                }
       
   675            }
       
   676            break;
       
   677         case KConnectionWatcher:
       
   678             {
       
   679             BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST, 
       
   680                     "[BTNOTIF]\t CBTNotifConnection::MBAORequestCompletedL: KConnectionWatcher" );
       
   681             TUint32 event = iBasebandEvent().EventType();
       
   682             // First subscribe to the next event notification.
       
   683             // This will overwrite iBasebandEvent().EventType() with KBbEventMask
       
   684             iPhyLink.NotifyNextBasebandChangeEvent( iBasebandEvent,
       
   685                         iPhyActive->RequestStatus(), KBbEventMask );
       
   686             iPhyActive->GoActive();
       
   687             // Link down and link error are handled in CheckNextOperationL below.
       
   688             // ToDo: handle events!
       
   689             if( event & ( ENotifyPhysicalLinkDown | ENotifyPhysicalLinkError ) )
       
   690                 {
       
   691                 // We re-use the error code to store the indication that the 
       
   692                 // link has disconnected. This will only be overridden by next 
       
   693                 // event, which can only be a connection up event.
       
   694                 iBasebandEvent().SetErrorCode( KErrDisconnected );
       
   695                 }
       
   696             if( iPairingHelper )
       
   697                 {
       
   698                 if( event & ( ENotifyPhysicalLinkDown | ENotifyPhysicalLinkError |
       
   699                     ENotifyAuthenticationComplete ) )
       
   700                     {
       
   701                     // Results interesting for pairing result processing.
       
   702                     iPairingHelper->HandleAuthenticationCompleteL( iBasebandEvent().SymbianErrorCode() );
       
   703                     }
       
   704                 else if( event & ENotifyPhysicalLinkUp &&
       
   705                         iPairingHelper->CurrentOperation() == CBTNotifPairingHelper::EDedicatedBonding )
       
   706                     {
       
   707                     iPairingHelper->StartBondingL( 0 );
       
   708                     }
       
   709                 }
       
   710             }
       
   711             break;
       
   712         default:
       
   713             PanicServer( EBTNotifPanicBadState );
       
   714             break;
       
   715         }
       
   716     // We may be done with the current request, proceed to the next one
       
   717     CheckNextOperationL();
       
   718     BOstraceFunctionExit1( DUMMY_DEVLIST, this );
       
   719     }
       
   720 
       
   721 
       
   722 // ---------------------------------------------------------------------------
       
   723 // From class MBtSimpleActiveObserver.
       
   724 // Cancel and clean up all requests related to the active object.
       
   725 // ---------------------------------------------------------------------------
       
   726 //
       
   727 void CBTNotifConnection::CancelRequest( TInt aRequestId )
       
   728     {
       
   729     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   730     if ( aRequestId == KConnectionWatcher )
       
   731         {
       
   732         iPhyLink.CancelNextBasebandChangeEventNotifier();
       
   733         }
       
   734     else if ( aRequestId == KRegistryWatcher && iRegistryResponse )
       
   735         {
       
   736         iRegistryResponse->Cancel();
       
   737         }
       
   738     else if ( aRequestId == KRegistryRetriever )
       
   739         {
       
   740         iRegistry.CancelRequest( iRegActive->RequestStatus());
       
   741         }    
       
   742     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   743     }
       
   744 
       
   745 // ---------------------------------------------------------------------------
       
   746 // From class MBtSimpleActiveObserver.
       
   747 // 
       
   748 // ---------------------------------------------------------------------------
       
   749 //
       
   750 void CBTNotifConnection::HandleError( CBtSimpleActive* aActive, 
       
   751         TInt aError )
       
   752     {
       
   753     (void) aActive;
       
   754     (void) aError;
       
   755     }
       
   756 
       
   757 // ---------------------------------------------------------------------------
       
   758 // From class MBTEngDevmanObserver.
       
   759 // Registry modification has completed.
       
   760 // ---------------------------------------------------------------------------
       
   761 //
       
   762 void CBTNotifConnection::HandleDevManComplete( TInt aErr )
       
   763     {
       
   764     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   765     (void) aErr;
       
   766     NOTIF_NOTHANDLED( !aErr )
       
   767     if( iCurrentOp == EUpdatingRegistry )
       
   768         {
       
   769         // To make sure that we don't get deleted while updating.
       
   770         iCurrentOp = EIdle;
       
   771         }
       
   772     // Refresh is done separately, we will get notified through 
       
   773     // the registry watcher of the change.
       
   774     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   775     }
       
   776 
       
   777 
       
   778 // ---------------------------------------------------------------------------
       
   779 // From class MBTEngDevmanObserver.
       
   780 // Callback for getting a device from the registry
       
   781 //
       
   782 // Currently only used in context of setting device to trusted
       
   783 // ---------------------------------------------------------------------------
       
   784 //
       
   785 void CBTNotifConnection::HandleGetDevicesComplete( 
       
   786         TInt err, CBTDeviceArray* deviceArray ) 
       
   787     {
       
   788     BOstraceFunctionEntryExt( DUMMY_DEVLIST, this, err );
       
   789     // err is not used here very much, -1 could be returned if there is no device in registry,
       
   790     // but this case is covered by examing mRegDevArray.
       
   791     if (!err && (iCurrentOp == EReadingRegistry) ) {
       
   792         CBTDevice* dev (0);
       
   793         if ( deviceArray->Count() ) {
       
   794             dev = deviceArray->At( 0 );
       
   795             }
       
   796         if ( dev ) {
       
   797             iDevice = dev->CopyL();
       
   798             }
       
   799         // Set device to trusted
       
   800         // Copy the existing security settings.
       
   801         TBTDeviceSecurity sec( iDevice->GlobalSecurity().SecurityValue(),
       
   802                       iDevice->GlobalSecurity().PasskeyMinLength() );
       
   803         sec.SetNoAuthorise( ETrue );  // new value:  set device as trusted
       
   804         iDevice->SetGlobalSecurity( sec );
       
   805         iDevMan->ModifyDevice( *iDevice );   // write trusted (& paired) status to registry
       
   806         // To make sure that we don't get deleted while updating.
       
   807         iCurrentOp = EUpdatingRegistry;
       
   808         }
       
   809     BOstraceFunctionExit1( DUMMY_DEVLIST, this );
       
   810     }
       
   811 
       
   812 // ---------------------------------------------------------------------------
       
   813 // Retrieves device from registry based on BT address parameter
       
   814 // ---------------------------------------------------------------------------
       
   815 //
       
   816 void CBTNotifConnection::GetDeviceFromRegistry( const TBTDevAddr &addr )
       
   817 {
       
   818     BOstraceFunctionEntry1( DUMMY_DEVLIST, this );
       
   819     TBTRegistrySearch searchPattern;
       
   820     searchPattern.FindAddress( addr );
       
   821     // and get this device from registry
       
   822     iRegDevArray->ResetAndDestroy();
       
   823     iDevMan->GetDevices(searchPattern, iRegDevArray);
       
   824     BOstraceFunctionExit1( DUMMY_DEVLIST, this );
       
   825 }
       
   826 
       
   827 // ---------------------------------------------------------------------------
       
   828 // Get and configure a notification.
       
   829 // ---------------------------------------------------------------------------
       
   830 //
       
   831 void CBTNotifConnection::PrepareNotificationL( TBluetoothDialogParams::TBTDialogType aType,
       
   832     TBTDialogResourceId aResourceId )
       
   833     {
       
   834     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   835     iNotification = iTracker->NotificationManager()->GetNotification();
       
   836     User::LeaveIfNull( iNotification ); // For OOM exception, leaves with KErrNoMemory
       
   837     iNotification->SetObserver( this );
       
   838     iNotification->SetNotificationType( aType, aResourceId );
       
   839     // Set the address of the remote device
       
   840     TBuf<KBTDevAddrSize> addr;
       
   841     addr.Copy( iAddr.Des() );
       
   842     TInt err = iNotification->SetData( TBluetoothDialogParams::EAddress, addr );
       
   843     NOTIF_NOTHANDLED( !err )
       
   844     // Set the name of the remote device
       
   845     TBTDeviceName name;
       
   846     GetDeviceNameL( name, *iDevice );
       
   847     // ToDo: handle leave in name conversion!
       
   848     err = iNotification->SetData( (TInt) TBluetoothDeviceDialog::EDeviceName, name );
       
   849     NOTIF_NOTHANDLED( !err )
       
   850     // Queue the notification for displaying to the user
       
   851     err = iTracker->NotificationManager()->QueueNotification( iNotification );
       
   852     NOTIF_NOTHANDLED( !err )
       
   853     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   854     }
       
   855 
       
   856 
       
   857 // ---------------------------------------------------------------------------
       
   858 // The notification is finished, handle the result.
       
   859 // ---------------------------------------------------------------------------
       
   860 //
       
   861 void CBTNotifConnection::NotificationClosedL( TInt aError, const TDesC8& aData )
       
   862     {
       
   863     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   864     switch( iCurrentOp )
       
   865         {
       
   866         case EAuthorizing:
       
   867             CompleteAuthorizationReqL( aError, aData );
       
   868             break;
       
   869         case EBlocking:
       
   870             CompleteBlockingReqL( aError, aData );
       
   871             break;
       
   872         default:
       
   873             NOTIF_NOTIMPL
       
   874             break;
       
   875         }
       
   876     // We may be done with the current request, proceed to the next one
       
   877     CheckNextOperationL();
       
   878     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   879     }
       
   880 
       
   881 
       
   882 // ---------------------------------------------------------------------------
       
   883 // Handle a request for authorization of this connection.
       
   884 // ---------------------------------------------------------------------------
       
   885 //
       
   886 void CBTNotifConnection::HandleAuthorizationReqL( const TDesC8& aParams )
       
   887     {
       
   888     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   889     __ASSERT_ALWAYS( iCurrentOp == EIdle, PanicServer( EBTNotifPanicBadState ) );
       
   890     __ASSERT_ALWAYS( !iNotification, PanicServer( EBTNotifPanicCorrupt ) );
       
   891     TBTAuthorisationParams params;
       
   892     TPckgC<TBTAuthorisationParams> paramsPckg( params );
       
   893     paramsPckg.Set( aParams );
       
   894     iCurrentOp = EAuthorizing;
       
   895     // The name in the parameter package is the latest one, retrieved from 
       
   896     // the remote device during this connection.
       
   897     if( paramsPckg().iName.Length() )
       
   898         {
       
   899         // Update the local device record. No need to update the registry,
       
   900         // that will be done by the stack, and we will receive the update 
       
   901         // information when that has completed.
       
   902         iDevice->SetDeviceNameL( BTDeviceNameConverter::ToUTF8L( paramsPckg().iName ) );
       
   903         }
       
   904     PrepareNotificationL( TBluetoothDialogParams::EQuery, EAuthorization );
       
   905     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   906     }
       
   907 
       
   908 
       
   909 // ---------------------------------------------------------------------------
       
   910 // Process the user input and complete the outstanding authorization request. 
       
   911 // ---------------------------------------------------------------------------
       
   912 //
       
   913 void CBTNotifConnection::CompleteAuthorizationReqL( TInt aError, const TDesC8& aData )
       
   914     {
       
   915     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   916     // Set our state to idle for now. This may get changed if the user just chose 
       
   917     // to block, or if we have a pending request.
       
   918     iCurrentOp = EIdle;
       
   919     if( !aError )
       
   920         {
       
   921         TPckgC<TBool> result( EFalse );
       
   922         result.Set( aData );
       
   923         TBool proceed = iTracker->UpdateBlockingHistoryL( iDevice, result() );
       
   924         if( result() == EFalse && proceed )
       
   925             {
       
   926             // The user denied the connection, ask to block the device.
       
   927             LaunchBlockingQueryL();
       
   928             }
       
   929         CompleteClientRequest( KErrNone, aData );
       
   930         }
       
   931     else
       
   932         {
       
   933         CompleteClientRequest( aError, KNullDesC8 );
       
   934         }
       
   935     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   936     }
       
   937 
       
   938 
       
   939 // ---------------------------------------------------------------------------
       
   940 // Process the user input for blocking a device.
       
   941 // ---------------------------------------------------------------------------
       
   942 //
       
   943 void CBTNotifConnection::CompleteBlockingReqL( TInt aError, const TDesC8& aData )
       
   944     {
       
   945     BOstraceFunctionEntry0( DUMMY_DEVLIST );
       
   946     TPckgC<TBool> result( EFalse );
       
   947     result.Set( KNullDesC8 );    // to test!
       
   948     result.Set( aData );
       
   949     iCurrentOp = EIdle; // May get changed if we have a pending request.
       
   950     if( !aError && result() )
       
   951         {
       
   952         // The user accepted to block this device.
       
   953         TBTDeviceSecurity sec;  // use default values when setting as banned.
       
   954         sec.SetBanned( ETrue );
       
   955         iDevice->SetGlobalSecurity( sec );
       
   956         if( iDevice->IsValidPaired() && iDevice->IsPaired() )
       
   957             {
       
   958             // Deleting the link key will also set the device as unpaired.
       
   959             iDevice->DeleteLinkKey();
       
   960             }
       
   961         UpdateRegistryEntryL();
       
   962         }
       
   963     BOstraceFunctionExit0( DUMMY_DEVLIST );
       
   964     }