diff -r 0707dd69d236 -r a42ed326b458 bluetoothengine/bteng/src/btengpairman.cpp --- a/bluetoothengine/bteng/src/btengpairman.cpp Fri Mar 12 15:43:23 2010 +0200 +++ b/bluetoothengine/bteng/src/btengpairman.cpp Mon Mar 15 12:41:15 2010 +0200 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). * All rights reserved. * This component and the accompanying materials are made available * under the terms of "Eclipse Public License v1.0" @@ -33,6 +33,7 @@ ERegistryPairedDevicesNewView, ERegistryInitiatePairedDevicesList, ERegistryGetPairedDevices, + ERegistryGetLocalAddress, }; /** The message argument which holds the Bluetooth address. */ @@ -81,16 +82,20 @@ User::LeaveIfError( iAuthenResult.Open( *iPairingServ ) ); iSSPResultActive = CBTEngActive::NewL( *this, ESimplePairingResult, CActive::EPriorityStandard ); iAuthenResultActive = CBTEngActive::NewL( *this, EAuthenticationResult, CActive::EPriorityStandard ); - SubscribeSspPairingResult(); - SubscribeAuthenticateResult(); } + // RProperty for accessing the local device address + User::LeaveIfError( iPropertyLocalAddr.Attach(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothGetLocalDeviceAddress) ); + // connect to registry User::LeaveIfError( iBTRegistry.Open( BTRegServ() ) ); iRegistryActive = CBTEngActive::NewL( *this, ERegistryInitiatePairedDevicesView, CActive::EPriorityStandard ); - // Start to get the list of all paired devices. - CreatePairedDevicesView( ERegistryInitiatePairedDevicesView ); - iPairedDevices = new (ELeave) RArray; + iPairedDevices = new (ELeave) RArray; + + // Initialise paired devices list + iLocalAddrActive = CBTEngActive::NewL( *this, ERegistryGetLocalAddress, CActive::EPriorityStandard ); + InitPairedDevicesList(); + TRACE_FUNC_EXIT } @@ -138,6 +143,85 @@ { iMessage.Complete( KErrCancel ); } + iPropertyLocalAddr.Cancel(); + iPropertyLocalAddr.Close(); + delete iLocalAddrActive; + TRACE_FUNC_EXIT + } + +// --------------------------------------------------------------------------- +// Initialises the paired devices list. +// If the local address is not available from the P&S key +// KPropertyKeyBluetoothGetLocalDeviceAddress, then the list may need to be +// updated once the H/W is switched on. This is so that any registry update +// from a restore operation can be included in the list, without mistaking the +// new devices for new pairings. +// --------------------------------------------------------------------------- +// +void CBTEngPairMan::InitPairedDevicesList() + { + TRACE_FUNC_ENTRY + + // Check that we have the Bluetooth local address. If we don't then initialise anyway, but subscribe for an update. + // This allows us to refresh our paired devices list to include updates made to the remote devices table of the + // Bluetooth registry from a restore operation. We need to include these devices without mistaking them for new + // pairings. We look solely at the P&S key for the address to avoid the condition whereby the address has been + // entered into the reigstry but the Bluetooth Manager server has not begun the restore process yet. The signalling + // of the P&S key will cause Bluetooth Manager to update the registry with any restored devices before fulfilling + // any further requests. + + // Subscribe to local address property in case we need an update. + iPropertyLocalAddr.Subscribe( iLocalAddrActive->iStatus ); + iLocalAddrActive->SetRequestId( ERegistryGetLocalAddress ); + iLocalAddrActive->GoActive(); + + // Attempt to read address from P&S key. + TBuf8 btAddrDes; + TInt err = iPropertyLocalAddr.Get( btAddrDes ); + + // Is the P&S key defined yet? (if not, stack not up yet) + if ( err == KErrNone ) + { + // P&S key defined, is local address set? (if not, H/W not initialised yet) + if ( btAddrDes.Length() == KBTDevAddrSize ) + { + TBTDevAddr btAddr = btAddrDes; + + if ( btAddr != TBTDevAddr() ) + { + // Non-zero local address is available. + iPropertyLocalAddr.Cancel(); + iLocalAddrActive->CancelRequest(); + } + } + } + + // Perform initialisation of the paired devices list. + DoInitPairedDevicesList(); + + TRACE_FUNC_EXIT + } + +// --------------------------------------------------------------------------- +// Initialises the paired devices list (second stage) +// This method performs the actual initialisation, now that the local BT H/W +// address had been made available. +// --------------------------------------------------------------------------- +// +void CBTEngPairMan::DoInitPairedDevicesList() + { + TRACE_FUNC_ENTRY + + if ( !iRegistryActive->IsActive() ) + { + // Start to get the list of all paired devices. + CreatePairedDevicesView( ERegistryInitiatePairedDevicesView ); + } + else + { + iNotHandledInitEventCounter++; + } + TRACE_FUNC_EXIT } @@ -294,24 +378,34 @@ if ( index > KErrNotFound ) { dev = (*iPairedDevices)[index]; - TBTDeviceSecurity security = dev.GlobalSecurity(); - // Clear trust setting so that correct icon will be shown in ui applications. - security.SetNoAuthenticate(EFalse ); - security.SetNoAuthorise(EFalse ); - dev.SetGlobalSecurity(security); - dev.DeleteLinkKey(); - if ( dev.IsValidUiCookie() && - ( dev.UiCookie() & EBTUiCookieJustWorksPaired ) ) + + TRequestStatus status( KRequestPending ); + // Unpair the device in registry (synchronously) + iBTRegistry.UnpairDevice( dev.Address(), status ); + User::WaitForRequest( status ); + TRACE_INFO( ( _L( "Delete link key, res %d"), status.Int() ) ) + + if ( status == KErrNone ) { - // Remove the UI cookie bit for Just Works pairing. - TInt32 cookie = dev.UiCookie() & ~EBTUiCookieJustWorksPaired; - dev.SetUiCookie( cookie ); - TRACE_INFO( ( _L( "UI cookie %x cleared"), EBTUiCookieJustWorksPaired ) ); + TBTDeviceSecurity security = dev.GlobalSecurity(); + // Clear trust setting so that correct icon will be shown in ui applications. + security.SetNoAuthenticate(EFalse ); + security.SetNoAuthorise(EFalse ); + dev.SetGlobalSecurity(security); + dev.DeleteLinkKey(); + if ( dev.IsValidUiCookie() && + ( dev.UiCookie() & EBTUiCookieJustWorksPaired ) ) + { + // Remove the UI cookie bit for Just Works pairing. + TInt32 cookie = dev.UiCookie() & ~EBTUiCookieJustWorksPaired; + dev.SetUiCookie( cookie ); + TRACE_INFO( ( _L( "UI cookie %x cleared"), EBTUiCookieJustWorksPaired ) ); + } + // modify the device in registry synchronously + // status.Int() could be -1 if the device is not in registry + // which is totally fine for us. + (void) UpdateRegDevice( dev ); } - // modify the device in registry synchronously - // status.Int() could be -1 if the device is not in registry - // which is totally fine for us. - (void) UpdateRegDevice( dev ); } TRACE_FUNC_EXIT } @@ -396,11 +490,26 @@ break; } case ERegistryInitiatePairedDevicesList: + { + if (iSSPResultActive && iAuthenResultActive) + { + SubscribeSspPairingResult(); + SubscribeAuthenticateResult(); + } + HandleGetPairedDevicesCompletedL( aStatus, aId ); + break; + } case ERegistryGetPairedDevices: { HandleGetPairedDevicesCompletedL( aStatus, aId ); break; } + case ERegistryGetLocalAddress: + { + // Refresh paired devices list to include any restored devices. + DoInitPairedDevicesList(); + break; + } default: // Should not be possible, but no need for handling. TRACE_INFO( (_L("[BTEng]: CBTEngPairMan::RequestCompletedL unhandled event!!") ) ) @@ -434,6 +543,7 @@ { TRACE_FUNC_ARG( ( _L( "%d" ), aActivate ) ) TRACE_BDADDR( aAddr ) + iPairingOperationAttempted = ETrue; TInt err( KErrNone ); if ( !aActivate ) { @@ -466,6 +576,7 @@ // void CBTEngPairMan::PairDeviceL( const TBTDevAddr& aAddr, TUint32 aCod ) { + iPairingOperationAttempted = ETrue; if ( !iPairer) { // no existing pair handling, create one: @@ -499,27 +610,35 @@ } // --------------------------------------------------------------------------- -// Subscribes to simple pairing result from Pairing Server +// Subscribes to simple pairing result from Pairing Server (if not already +// subscribed). // --------------------------------------------------------------------------- // void CBTEngPairMan::SubscribeSspPairingResult() { TRACE_FUNC_ENTRY - iPairingResult.SimplePairingResult( iSimplePairingRemote, iSSPResultActive->RequestStatus() ); - iSSPResultActive->GoActive(); + if ( !iSSPResultActive->IsActive() ) + { + iPairingResult.SimplePairingResult( iSimplePairingRemote, iSSPResultActive->RequestStatus() ); + iSSPResultActive->GoActive(); + } TRACE_FUNC_EXIT } // --------------------------------------------------------------------------- -// Subscribes to authentication result from Pairing Server +// Subscribes to authentication result from Pairing Server (if not already +// subscribed). // --------------------------------------------------------------------------- // void CBTEngPairMan::SubscribeAuthenticateResult() { TRACE_FUNC_ENTRY - // Subscribe authentication result (which requires pairing for unpaired devices) - iAuthenResult.AuthenticationResult( iAuthenticateRemote, iAuthenResultActive->RequestStatus() ); - iAuthenResultActive->GoActive(); + if ( !iAuthenResultActive->IsActive() ) + { + // Subscribe authentication result (which requires pairing for unpaired devices) + iAuthenResult.AuthenticationResult( iAuthenticateRemote, iAuthenResultActive->RequestStatus() ); + iAuthenResultActive->GoActive(); + } TRACE_FUNC_EXIT } @@ -570,7 +689,14 @@ void CBTEngPairMan::CreatePairedDevicesView( TInt aReqId ) { TRACE_FUNC_ENTRY - iNotHandledRegEventCounter = 0; + if ( aReqId == ERegistryInitiatePairedDevicesView ) + { + iNotHandledInitEventCounter = 0; + } + else + { + iNotHandledRegEventCounter = 0; + } TBTRegistrySearch searchPattern; searchPattern.FindBonded(); iRegistryActive->SetRequestId( aReqId ); @@ -608,8 +734,14 @@ TRACE_FUNC_ENTRY if ( aReqId == ERegistryInitiatePairedDevicesView ) - {// Initialization phase, list paired devices if there are. - if ( aStatus > KErrNone ) + {// Initialization phase, list paired devices if there are any. + if ( iNotHandledInitEventCounter ) + { + // Reinitialisaton detected, create paired device view again: + (void) iBTRegistry.CloseView(); + CreatePairedDevicesView( ERegistryInitiatePairedDevicesView ); + } + else if ( aStatus > KErrNone ) { GetPairedDevices( ERegistryInitiatePairedDevicesList ); } @@ -620,7 +752,25 @@ } else { - if (iNotHandledRegEventCounter) + if ( iNotHandledInitEventCounter ) + { + // We need to reinitialise but we may be pairing. + // This situation is not expected to arise, as reinitialisation means + // that the H/W was only just switched on. + // If we have ever started to take part in a pairing, then prioritise that + // pairing. + (void) iBTRegistry.CloseView(); + if ( iPairingOperationAttempted ) + { + iNotHandledInitEventCounter = 0; + CreatePairedDevicesView( ERegistryPairedDevicesNewView ); + } + else + { + CreatePairedDevicesView( ERegistryInitiatePairedDevicesView ); + } + } + else if (iNotHandledRegEventCounter) { // more registry change detected, create paired device view again: (void) iBTRegistry.CloseView(); CreatePairedDevicesView( ERegistryPairedDevicesNewView ); @@ -650,19 +800,46 @@ (void) iBTRegistry.CloseView(); if ( aReqId == ERegistryInitiatePairedDevicesList ) { - // We completed the initialization of paired device list, - // move all paired devices to the array: - UpdatePairedDeviceListL(); + if ( iNotHandledInitEventCounter ) + { + // Reinitialisation required, create paired device view again: + CreatePairedDevicesView( ERegistryInitiatePairedDevicesView ); + } + else + { + // We completed the initialisation of paired device list, + // move all paired devices to the array: + UpdatePairedDeviceListL(); + } } - - if (iNotHandledRegEventCounter) - { // more registry change detected, create paired device view again: - CreatePairedDevicesView( ERegistryPairedDevicesNewView ); - } - else if ( aReqId == ERegistryGetPairedDevices) + else { - // no more registry change detected, find new pairings: - CheckPairEventL(); + if (iNotHandledInitEventCounter) + { + // We need to reinitialise but we may be pairing. + // This situation is not expected to arise, as reinitialisation means + // that the H/W was only just switched on. + // If we have ever started to take part in a pairing, then prioritise that + // pairing. + if ( iPairingOperationAttempted ) + { + iNotHandledInitEventCounter = 0; + CreatePairedDevicesView( ERegistryPairedDevicesNewView ); + } + else + { + CreatePairedDevicesView( ERegistryInitiatePairedDevicesView ); + } + } + else if (iNotHandledRegEventCounter) + { // more registry change detected, create paired device view again: + CreatePairedDevicesView( ERegistryPairedDevicesNewView ); + } + else if ( aReqId == ERegistryGetPairedDevices) + { + // no more registry change detected, find new pairings: + CheckPairEventL(); + } } TRACE_FUNC_EXIT @@ -721,9 +898,10 @@ TRACE_BDADDR( dev.Address() ); if ( newPaired && !iPairer) { + iPairingOperationAttempted = ETrue; iPairer = CBTEngIncPair::NewL( *this, dev.Address() ); } - if ( iPairer ) + if ( newPaired && iPairer ) { // Ask pair handler to decide what to do: iPairer->HandleRegistryNewPairedEvent( dev );