bluetoothengine/btui/devmodel/src/btpairedmodel.cpp
branchRCL_3
changeset 23 9386f31cc85b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/btui/devmodel/src/btpairedmodel.cpp	Wed Sep 01 12:20:04 2010 +0100
@@ -0,0 +1,999 @@
+/*
+* Copyright (c) 2006-2007 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"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Maintain a Bluetooth devices data model for paired devices view
+*
+*/
+
+
+#include "btpairedmodel.h"
+#include <btengutil.h>
+#include "debug.h"
+#include "btui.h"
+
+const TInt KMaxCheckedConnections=20;
+
+
+// ---------------------------------------------------------------------
+// CBTPairedModel::CBTPairedModel
+// ---------------------------------------------------------------------
+//
+CBTPairedModel::CBTPairedModel(MBTDeviceObserver* aObserver, TBTDeviceSortOrder* aOrder)
+	: CBTDevModelBase(aObserver, aOrder)
+    {
+	TRACE_FUNC_ENTRY    
+    TRACE_FUNC_EXIT	
+    }
+
+// ---------------------------------------------------------------------
+// CBTPairedModel::NewL
+// ---------------------------------------------------------------------
+//
+CBTPairedModel* CBTPairedModel::NewL(MBTDeviceObserver* aObserver, TBTDeviceSortOrder* aOrder )
+    {
+    CBTPairedModel* self = new (ELeave) CBTPairedModel(aObserver, aOrder);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+     
+    return self;       
+    }
+    
+// --------------------------------------------------------------------------------------------
+// Destructor
+// --------------------------------------------------------------------------------------------
+//
+CBTPairedModel::~CBTPairedModel()
+    {
+	TRACE_FUNC_ENTRY    
+	
+    delete iConnMan;
+    delete iPairingDevice;
+    delete iLinks;
+    delete iBtEngSettings;
+    iSocketServ.Close();    
+    
+    TRACE_FUNC_EXIT    
+    }
+
+// ---------------------------------------------------------------------
+// CBTPairedModel::ConstructL
+// ----------------------------------------------------------------------
+//
+void CBTPairedModel::ConstructL()
+    {
+	TRACE_FUNC_ENTRY
+	
+    // get all devices from btregistry to cache - local copy of CBTDeviceArray
+    iDevMan = CBTEngDevMan::NewL(this);
+    iConnMan = CBTEngConnMan::NewL(this);
+    iSearchPattern.FindAll(); 
+   	iRegistryObserver = CBTRegistryObserver::NewL(this, iSearchPattern);
+	iRegistryObserver->Refresh();
+	User::LeaveIfError( iSocketServ.Connect() );
+	iLinks=CBluetoothPhysicalLinks::NewL(*this,iSocketServ);
+	
+	iBtEngSettings = CBTEngSettings::NewL(this);
+	
+    TRACE_FUNC_EXIT	
+    }
+    
+// ---------------------------------------------------------------------
+// CBTPairedModel::IsAnyDeviceConnected
+// ----------------------------------------------------------------------
+//
+TBool CBTPairedModel::IsAnyDeviceConnected()
+    {        
+	TRACE_FUNC_ENTRY
+
+	FlagPhysicallyConnectedDevices(iDeviceArray);
+    
+	for(TInt i = 0; i < iDeviceArray.Count(); i++)
+		{
+		if(iDeviceArray[i]->iStatus & (EStatusPhysicallyConnected|EStatusBtuiConnected))
+			{
+			TRACE_FUNC_EXIT				
+			return ETrue;
+			}        
+		}
+					
+	TRACE_FUNC_EXIT				
+	
+    return EFalse;
+    }
+    
+// ---------------------------------------------------------------------
+// CBTPairedModel::DoChangeDevice
+// ---------------------------------------------------------------------
+
+TInt CBTPairedModel::DoChangeDeviceL(const TBTDevice& aDevice)
+    {
+    TRACE_FUNC_ENTRY
+    TRACE_BDADDR(aDevice.iAddr)
+   	// check that the device actually still exists
+   	if(aDevice.iOperation != EOpPair )
+   		{
+   		User::LeaveIfError( GetIndexByAddress(aDevice.iAddr, aDevice.iIndex ) );	
+   		}
+   	
+    // disconnect device to be unpaired, or blocked
+    if((aDevice.iOperation == EOpBlock || aDevice.iOperation == EOpUnpair ))
+    	{    	
+    	if( iState != EDisconnectBeforeOperationState)
+    		{
+    			// disconnect by CBTEngConnMan if connected that way.
+    			if (aDevice.iStatus & static_cast<TInt>(EStatusBtuiConnected ) )
+    				{
+    				TInt code=KErrNone;
+		    		TRAPD(err,
+		    		iState=EDisconnectBeforeOperationState;
+			    		iDisconnectDevice=new(ELeave) TBTDevice(aDevice);
+			    		code=iConnMan->Disconnect(aDevice.iAddr,EBTDiscImmediate);    				
+			    		);
+					// if the return code is KErrNone then there will be
+					// a callback. However if it fails, there will not be any.
+					// So the execution will go on inside this method, if there was an error.
+					if(err == KErrNone && code==KErrNone )
+						{
+						return KErrNone;
+						}
+						
+    				}
+    			else // try disconnecting from the link layer
+    				{
+    				TInt code=KErrNone;
+    				TRAPD(err,
+					iState=EDisconnectBeforeOperationState;
+						iDisconnectDevice=new(ELeave) TBTDevice(aDevice);
+						code=iLinks->Disconnect(aDevice.iAddr);
+						);
+					// if the return code is KErrNone then there will be
+					// a callback. However if it fails, there will not be any.
+					// So the execution will go on inside this method, if there was an error.
+					if(err == KErrNone && code==KErrNone )
+						{
+						return KErrNone;
+						}
+    				}
+    		}
+   		else    
+			iState=EIdleState;
+    
+    	}
+    	
+    if(	aDevice.iOperation ==EOpPair)
+    	{
+    	DoPairDeviceL();
+    	TRACE_FUNC_EXIT 
+    	return KErrNone;    	
+    	}
+    
+    TInt err = CBTDevModelBase::DoChangeDeviceL(aDevice);
+    if(iDisconnectDevice!= NULL)
+    	{
+    	delete iDisconnectDevice;
+    	iDisconnectDevice=NULL;
+    	}
+    
+    if (err != KErrNone)
+        {      
+        TBTDevAddr addr;
+        if(aDevice.iAddr == KNullAddress )
+        	{        	        	
+        	if(aDevice.iIndex < 0 || aDevice.iIndex >= iDeviceArray.Count())
+        		return KErrArgument;
+        	else
+        		addr=iDeviceArray[aDevice.iIndex]->iAddr;
+        	}
+        	else
+        		addr=aDevice.iAddr;
+        	
+        switch (aDevice.iOperation)
+            {
+            case EOpConnect:
+            	{                    	   		            		               
+                err = iConnMan->Connect(addr, aDevice.iDeviceClass);
+                break;
+            	}
+            case EOpDisconnect:
+            	{
+            	iDisconnectDevice=new(ELeave) TBTDevice(aDevice);            		            		           	
+				if (aDevice.iStatus & static_cast<TInt>(EStatusBtuiConnected ) )            	
+					{
+					err = iConnMan->Disconnect(addr, EBTDiscImmediate);	
+					}
+				else
+					{
+					err=iLinks->Disconnect(aDevice.iAddr);
+					}
+                
+                break;
+            	}
+            default:
+            	User::Leave(err);
+                break;
+            }
+        }
+        
+    TRACE_FUNC_EXIT        
+    
+    return err;
+    }
+    
+// ---------------------------------------------------------------------
+// CBTPairedModel::DoCancelChange
+// ---------------------------------------------------------------------
+//    
+void CBTPairedModel::DoCancelChangeL(const TBTDevice& aDevice)
+    {
+    TRACE_FUNC_ENTRY
+    
+	if(aDevice.iIndex >= iDeviceArray.Count())
+        {
+        TRACE_INFO((_L("index is %d, max expected is %d"), aDevice.iIndex, iDeviceArray.Count()));
+        TRACE_FUNC_EXIT    
+		return; 
+        }
+    
+    // in case it was stopped
+    iRegistryObserver->StartIfNotRunning();
+    switch (aDevice.iOperation)
+        {
+        case EOpPair:
+        	if( iState==EDeleteDeviceState || iState==EAddDeviceState )
+        		{
+        		iDevMan->Cancel();
+        		}        		
+        	else
+        		{
+        		iConnMan->CancelPairDevice();
+        		}            	        	
+            delete iPairingDevice;
+            iPairingDevice=NULL;
+            iState=EIdleState;
+            iRegistryObserver->Refresh();
+            break;
+            
+        case EOpConnect:
+        	{	
+        	
+            TBTDevAddr addr;
+            if(aDevice.iIndex == KErrNotFound) 
+            	{
+            	addr=aDevice.iAddr;
+            	}                
+            else
+            	{
+            	addr=iDeviceArray[aDevice.iIndex]->iAddr;
+            	}
+            	
+            iConnMan->CancelConnect(addr);
+            break;
+        	}
+        default:
+            CBTDevModelBase::CancelChange(aDevice);
+            return;
+        }
+    iRegistryObserver->StartIfNotRunning();
+    
+	if(iQueue.Count()>0)
+		{
+		delete iQueue[0];
+		iQueue.Remove(0);		
+		HandleQueue();
+		}
+	
+    TRACE_FUNC_EXIT	       
+    }
+    
+// ---------------------------------------------------------------------
+// CBTPairedModel::HandleNewDevice
+//
+// Adds the device if it is not banned
+// ---------------------------------------------------------------------
+//
+void CBTPairedModel::HandleNewDeviceL(const CBTDevice* aRegDevice,
+        TNameEntry* aNameEntry)
+    {
+    TRACE_FUNC_ENTRY
+    
+    // It is needed to filter out blocked devices,
+    // since otherwise blocked and paired devices would
+    // be listed.
+    if( ! aRegDevice->GlobalSecurity().Banned()     	
+            && IsUserAwarePaired( aRegDevice->AsNamelessDevice() ) ) 
+        {
+        AddDeviceL(aRegDevice, aNameEntry, EOpNone);
+        }
+
+    TRACE_FUNC_EXIT		    
+    }
+    
+// -----------------------------------------------------------------------
+// CBTPairedModel::CreateDevice
+//
+// This implementaion will add the connectable status from the superclass.
+// -----------------------------------------------------------------------  
+//
+TBTDevice* CBTPairedModel::CreateDeviceL(const CBTDevice* aRegDevice,
+        TNameEntry* aNameEntry)
+    {
+    TRACE_FUNC_ENTRY
+    
+    TBTDevice* device = CBTDevModelBase::CreateDeviceL(aRegDevice, aNameEntry);
+    
+    // add EStatusBtuiConnected status if the device has a profile connection
+    TBTEngConnectionStatus connStatus;
+    iConnMan->IsConnected(device->iAddr, connStatus);
+    
+    if(connStatus == EBTEngConnecting || connStatus == EBTEngConnected)
+    	{
+    	SetStatusFlags(device->iStatus,EStatusBtuiConnected);
+    	}
+    
+    // add connectable status
+    TBool connectable=EFalse;
+    iConnMan->IsConnectable(aRegDevice->BDAddr(), aRegDevice->DeviceClass(), connectable );
+    
+    if( connectable) 
+    	{
+    	SetStatusFlags(device->iStatus, EStatusConnectable );
+    	}
+    	
+	TRACE_FUNC_EXIT 
+	       
+    return device;
+    }
+    
+// ---------------------------------------------------------------------
+// CBTPairedModel::ConnectComplete
+// from MBTEngConnObserver
+// ----------------------------------------------------------------------
+//
+void CBTPairedModel::ConnectComplete(TBTDevAddr& aAddr, TInt aErr, RBTDevAddrArray* aConflicts)
+    {
+    TRACE_FUNC_ENTRY
+    
+    TRACE_INFO((_L("aErr=%d"), aErr))
+
+    TInt index = GetIndexByAddress(aAddr);
+    TBool requestIssuedFromPhone = EFalse;
+    TBTDevice connectedDevice;
+    
+    // was the device connected from request by the ui
+	if(iQueue.Count()>0 && iQueue[0]->iOperation==EOpConnect && 
+	  iQueue[0]->iAddr == aAddr)
+		{
+		requestIssuedFromPhone = ETrue;
+		if(index >=0) // is it from paired list
+			{			
+			connectedDevice=*iDeviceArray[index];
+			connectedDevice.iOperation=EOpConnect;
+			}
+		else
+			{
+			connectedDevice=*iQueue[0];		
+			}
+    	
+    	}
+    else
+    	{
+    	requestIssuedFromPhone = EFalse;
+		if(index >=0) // is it from paired list
+			{
+			connectedDevice=*iDeviceArray[index];
+			connectedDevice.iOperation=EOpConnect;
+			}
+		else
+			{
+	    	// it was not. Try to fill what can be filled.
+			connectedDevice.iAddr=aAddr;
+			connectedDevice.iIndex=KErrNotFound;
+			connectedDevice.iOperation = EOpConnect;			
+			}    	
+    	}        
+    
+    if (aErr == KErrAlreadyExists )
+        { 
+        // gather the names of the conflicting devices.
+        RBTDevNameArray nameArray;
+        for (TInt i = 0; aConflicts!= NULL && i < aConflicts->Count(); i++)
+            {
+            //remove duplicates
+            if(i>0&& (*aConflicts)[i]==(*aConflicts)[i-1])
+            	{
+            	continue;
+            	}
+            TInt di = GetIndexByAddress((*aConflicts)[i]);
+            
+            if(di >=0 )
+            	{
+            	nameArray.Append(&iDeviceArray[di]->iName);
+            	}
+            }
+
+        // we will unset the connect status of the device if connection failed &
+            // it is found in paired devices.
+        if( index >= 0 )
+            {
+            // add EStatusBtuiConnected status if the device has a profile connection
+            TBTEngConnectionStatus connStatus;
+            iConnMan->IsConnected(connectedDevice.iAddr, connStatus);
+   
+            if (connStatus != EBTEngConnecting && connStatus != EBTEngConnected)
+                {
+                TRACE_INFO(_L("Unset EStatusBtuiConnected"))
+                UnsetStatusFlags(iDeviceArray[index]->iStatus,EStatusBtuiConnected );
+                }
+            }
+        
+        if(iObserver)
+            {
+            //Show only phone issued request complete notes
+            //Do not show notes for device issued request when BTUI is active
+            if ( requestIssuedFromPhone ) 
+                {
+                iObserver->NotifyChangeDeviceComplete(aErr, connectedDevice, &nameArray);
+                }
+               
+            SendRefreshIfNoError(aErr);
+            }
+        nameArray.Reset();
+        }
+    else 
+        {
+        if (aErr == KErrNone)
+            {
+            // we will set the connect status of the device
+            // if it is found in paired devices.
+            if( index >= 0 )
+            	{
+            	SetStatusFlags(iDeviceArray[index]->iStatus,EStatusBtuiConnected );
+            	}
+            }
+        else        
+            {
+            // we will unset the connect status of the device if connection failed &
+            // it is found in paired devices.
+            if( index >= 0 )
+                {                   
+                // add EStatusBtuiConnected status if the device has a profile connection
+                TBTEngConnectionStatus connStatus;
+                iConnMan->IsConnected(connectedDevice.iAddr, connStatus);
+   
+                if (connStatus != EBTEngConnecting && connStatus != EBTEngConnected)
+                   {
+                   TRACE_INFO(_L("Unset EStatusBtuiConnected"))
+                   UnsetStatusFlags(iDeviceArray[index]->iStatus,EStatusBtuiConnected );
+                   }                
+                }
+            }
+		if(iObserver)
+			{
+			//Show only phone issued request complete notes
+			//Do not show notes for device issued request when BTUI is active
+			if ( requestIssuedFromPhone ) 
+			    {
+        	    iObserver->NotifyChangeDeviceComplete(aErr, connectedDevice);
+			    }
+        	
+        	SendRefreshIfNoError(aErr);
+			}		
+        }           
+    
+    // Process the next command if the connect was
+    //initiated by this UI.    
+	if(iQueue.Count()>0 && iQueue[0]->iOperation==EOpConnect && 
+       iQueue[0]->iAddr == aAddr)        
+        {
+        delete iQueue[0];
+        iQueue.Remove(0);		
+        HandleQueue();
+        }
+    else
+        {
+        if( iQueue.Count()==0 ) 
+            {
+            TRACE_INFO((_L("op Q is empty")));
+            }
+        else
+            {
+            TRACE_INFO((_L("unexpected op Q contents, count is %d, op is %d"), iDeviceArray.Count(), iQueue[0]->iOperation));
+            }
+        }
+    TRACE_FUNC_EXIT	
+    }
+    
+// ---------------------------------------------------------------------
+// CBTPairedModel::PowerStateChanged
+// from MBTEngSettingObserver
+// ----------------------------------------------------------------------
+//
+void CBTPairedModel::PowerStateChanged( TBTPowerStateValue )
+	{
+	TRACE_FUNC_ENTRY
+	
+	// This is implemented for case like when user choses offlne mode, Bluetooth is swithced off
+	// very fast. Bt audio components don't have enough time to close audio connection.
+	// BTUI needs to update UI display.
+	
+	TInt count = iDeviceArray.Count();  
+    
+    for (TInt i = 0; i < count; i++)
+    	{
+     	UnsetStatusFlags(iDeviceArray[i]->iStatus, EStatusBtuiConnected );
+    	}
+	
+	SendRefreshIfNoError(KErrNone);
+	
+	TRACE_FUNC_EXIT
+	}
+    
+// ----------------------------------------------------
+// CBTPairedModel::VisibilityModeChanged
+// from MBTEngSettingObserver
+// ----------------------------------------------------
+//    
+void CBTPairedModel::VisibilityModeChanged( TBTVisibilityMode  )
+    {
+	TRACE_FUNC_ENTRY
+	
+	
+	TRACE_FUNC_EXIT	
+    }
+        
+// ---------------------------------------------------------------------
+// CBTPairedModel::DisconnectComplete
+// from MBTEngConnObserver
+// ----------------------------------------------------------------------
+//
+void CBTPairedModel::DisconnectComplete(TBTDevAddr& aAddr, TInt aErr)
+    {
+    TRACE_FUNC_ENTRY
+    
+    // the disconnect was part of a unpairing or blocking operation
+	if(iState == EDisconnectBeforeOperationState && iDisconnectDevice && aAddr == iDisconnectDevice->iAddr )
+		{
+
+		TRAPD(err,
+			DoChangeDeviceL(*iDisconnectDevice);		
+		);
+		iState=EIdleState;		
+		if(err != KErrNone)
+			{
+			HandleLeave(err,iDisconnectDevice);
+			}
+		TRACE_FUNC_EXIT
+		return;
+		}		    
+    
+    TInt index = GetIndexByAddress(aAddr);
+    
+    // the disconnected device was not the devicein the list,
+    // so we do not tell anyone about it.
+    if ( iDisconnectDevice == NULL || iDisconnectDevice->iAddr != aAddr )
+    	{
+    	if (index >=0 )
+    	{
+    		UnsetStatusFlags(iDeviceArray[index]->iStatus, EStatusBtuiConnected );
+    	}
+    	
+    	SendRefreshIfNoError(KErrNone);
+
+		TBTDevice disconnectedDevice;
+		disconnectedDevice.iAddr = aAddr;
+		// Notify needed when there is active disconnect query dialog
+    	iObserver->NotifyChangeDeviceComplete(KErrDisconnected, disconnectedDevice);
+		
+    	TRACE_FUNC_EXIT  
+    	return;
+    	}
+    	
+	if(index >=0 )
+		{
+	    // set it to "not connected" no matter disconnection works or not
+	    UnsetStatusFlags(iDeviceArray[index]->iStatus, EStatusBtuiConnected );
+	    iDeviceArray[index]->iOperation = EOpDisconnect;
+	    iObserver->NotifyChangeDeviceComplete(aErr, *iDeviceArray[index]);		
+		}
+	else
+		{
+		iDisconnectDevice->iIndex=index;
+		iObserver->NotifyChangeDeviceComplete(aErr, *iDisconnectDevice);		
+		}
+
+	delete iDisconnectDevice;
+	iDisconnectDevice=NULL;    	
+
+   	SendRefreshIfNoError(aErr);
+   	// continue processing queue only if the disconnected device is
+   	// the device with we requested disconnect to.
+   	// this has to be checked so that we do not end on having multiple
+   	// queue processors at the same time
+	if(iQueue.Count()>0 && iQueue[0]->iOperation==EOpDisconnect && 
+	  iQueue[0]->iAddr == aAddr)           	
+		{
+		delete iQueue[0];
+		iQueue.Remove(0);		
+		HandleQueue();
+		}
+    else
+        {
+        if( iQueue.Count()==0 ) 
+            {
+            TRACE_INFO((_L("op Q is empty")));
+            }
+        else
+            {
+            TRACE_INFO((_L("unexpected op Q contents, count is %d, op is %d"), iDeviceArray.Count(), iQueue[0]->iOperation));
+            }
+        }
+    TRACE_FUNC_EXIT   	
+    }
+    
+// ---------------------------------------------------------------------
+// CBTPairedModel::PairingComplete
+// from MBTEngConnObserver
+// ----------------------------------------------------------------------
+//
+void CBTPairedModel::PairingComplete(TBTDevAddr& aAddr, TInt aErr)
+	{
+	TRACE_FUNC_ENTRY
+	
+	TRAPD(err,
+		PairingCompleteL(aAddr,aErr);
+		);
+		
+	if(err!=KErrNone)
+	{
+		TBTDevice tmp;
+		tmp.iAddr=aAddr;					
+		tmp.iIndex=GetIndexByAddress(aAddr);
+		tmp.iOperation=EOpPair;
+		HandleLeave(err,&tmp );
+
+		delete iPairingDevice;
+		iPairingDevice=NULL;				
+	}
+	
+	TRACE_FUNC_EXIT
+	}
+	
+// ---------------------------------------------------------------------
+// CBTPairedModel::PairingCompleteL
+// Leaving version of PairingComplete
+// ----------------------------------------------------------------------
+//	
+void CBTPairedModel::PairingCompleteL(TBTDevAddr& aAddr, TInt aErr)
+    {
+    TRACE_FUNC_ENTRY
+    
+	// The device that was attempted to be paired is 
+	// different from the the device that the pairing is finnished.
+	// This cannot happen, since CBTConnMan will report
+	// only pairing started by the listener and the UI
+	// does not allow making two pairings at the same time
+    __ASSERT_DEBUG(aAddr==iPairingDevice->BDAddr(),
+      PANIC(EBTPanicCommandComplettedToDiffrentDeviceThanStarted));
+    (void) aAddr;
+
+    // bail out if the operation queue is not what we expect
+    if( iQueue.Count() == 0 
+        || iQueue[0]->iOperation != EOpPair 
+        || iQueue[0]->iAddr != aAddr )        
+        {
+        if( iQueue.Count()==0 ) 
+            {
+            TRACE_INFO((_L("op Q is empty")));
+            }
+        else
+            {
+            TRACE_INFO((_L("unexpected op Q contents, count is %d, op is %d"), iDeviceArray.Count(), iQueue[0]->iOperation));
+            }
+        TRACE_FUNC_EXIT
+        return;
+        }
+
+    iState=EIdleState;		
+	TBTDevice* tmpDevice=NULL;
+	tmpDevice=CreateDeviceL(iPairingDevice, &( iQueue[0]->iNameEntry ) );
+	tmpDevice->iOperation=EOpPair;    		
+	
+    // new paired device must be inserted to the array, since
+    // user may be doing trust/ connect operations before
+    // it is refreshed from registry
+    TBool deleleteTmpDevice=ETrue;
+	
+	if( aErr == KErrNone  )    	
+		{
+		SetStatusFlags(tmpDevice->iStatus,EStatusPaired);
+		TInt index;
+		index=GetIndexByAddress(iPairingDevice->BDAddr());
+		
+		if(index == KErrNotFound)
+			{
+			iDeviceArray.InsertInOrderL(tmpDevice,*iSortOrder );
+  			  			
+    		RenumberDeviceArray();
+
+    		// iPairingDevice is now owned by iDeviceArray. 
+    		// So it must not be deleted by his function
+    		deleleteTmpDevice=EFalse;
+    		
+    		SendRefreshIfNoError(aErr,GetIndexByAddress(iPairingDevice->BDAddr()));
+			}					
+		}
+
+	
+    iObserver->NotifyChangeDeviceComplete(aErr, *tmpDevice);         
+    
+    /*
+     * We issue an background refresh in case 
+     * registry is updated from btnotif
+     */
+	iRegistryObserver->StartIfNotRunning();
+	iRegistryObserver->Refresh();
+    // delete if the ownership has not changed
+    if(deleleteTmpDevice )
+        {
+    	delete tmpDevice;
+    	tmpDevice=NULL;
+        }
+
+	delete iPairingDevice;    
+    iPairingDevice=NULL;       
+	delete iQueue[0];
+	iQueue.Remove(0);
+    
+    HandleQueue();    		    
+
+    TRACE_FUNC_EXIT    
+    }
+    
+// ---------------------------------------------------------------------
+// BTPairedModel::HandleDevManComplete
+// from MBTEngDevModelBase
+// ----------------------------------------------------------------------
+//
+void  CBTPairedModel::HandleDevManComplete(TInt aErr)
+	{
+	TRACE_FUNC_ENTRY
+	
+	// if this is handled we can remove this
+	if(iDisconnectDevice)
+		{
+		delete iDisconnectDevice;
+		iDisconnectDevice=NULL;
+		}
+		
+	if(iPairingDevice)
+		{
+		// add the device just deleted	
+		if(iState==EDeleteDeviceState && (aErr==KErrNone || aErr == KErrNotFound))
+			{
+				iPairingDevice->DeleteLinkKey();
+				TBTDeviceSecurity sec=iPairingDevice->GlobalSecurity();
+				sec.SetBanned(EFalse);
+				sec.SetNoAuthorise(EFalse);
+				iDevMan->AddDevice(*iPairingDevice);
+				iState=EAddDeviceState;
+				TRACE_FUNC_EXIT	
+				return;
+			}
+		// if the device is added allready, or if deletion failed
+		// we will go on with pairing the device
+		if(iState==EAddDeviceState||(iState==EDeleteDeviceState&& aErr != KErrNone))
+			{
+			aErr = iConnMan->PairDevice(iPairingDevice->BDAddr(), iPairingDevice->DeviceClass());
+			iState=EPairDeviceState;
+			// NOTE: now PairingComplete will be called and not this method.
+			TRACE_FUNC_EXIT	
+			return;
+			}
+		}
+	// these are not handled by superclass		
+	if(iQueue.Count()>0 &&
+	    ( iQueue[0]->iOperation==EOpConnect || 
+	     iQueue[0]->iOperation==EOpDisconnect ) )
+		{
+		iObserver->NotifyChangeDeviceComplete(aErr, *iQueue[0]);
+		}
+			
+	CBTDevModelBase::HandleDevManComplete(aErr);
+	
+    TRACE_FUNC_EXIT	
+	}
+	
+// ---------------------------------------------------------------------
+// CBTPairedModel::DoPairDevice
+// ---------------------------------------------------------------------
+//
+void  CBTPairedModel::DoPairDeviceL()
+	{
+	TRACE_FUNC_ENTRY
+	
+	// we are starting a new command. Checks that no earlier commands 
+	// have been executed, but not finished properly.
+	__ASSERT_DEBUG(iState==EIdleState,PANIC(EBTPanicDevManQueueIsInIllegalState));
+	// check that there is no other pairing going on.
+	__ASSERT_DEBUG(iPairingDevice!=NULL,PANIC(EBTPanicTwoPairingAttemptsAtTheSameTime));
+	
+	iRegistryObserver->Cancel();
+	
+	// devices to be paired are first deleted
+	// then added back. Only after that the paring itself is
+	// started
+	TBTRegistrySearch dele;
+	dele.FindAddress(iPairingDevice->BDAddr());
+	TInt err = iDevMan->DeleteDevices(dele);
+
+	iState=EDeleteDeviceState;
+   if (err)
+       {
+       HandleDevManComplete(err);
+       }
+       
+    TRACE_FUNC_EXIT
+	}
+	
+// ---------------------------------------------------------------------
+// CBTPairedModel::PairDevice
+//
+// Puts the given aPairingDevice to iPairingDevice and
+// adds and empty device with iOperation=EOpPair as placeholder to iQueue.
+// the pairing itself will be handled by DoChangeDevice that
+// cals then 
+// ---------------------------------------------------------------------
+//
+TInt CBTPairedModel::PairDeviceL(const CBTDevice* aPairingDevice,
+        TNameEntry* aNameEntry)	
+	{
+	TRACE_FUNC_ENTRY
+	
+	// cannot put two pairings to queue. 
+	// this is not possible since ui does not allow it.
+	if(iPairingDevice)
+		return KErrInUse;
+		
+	TBTDevice*  device=new(ELeave) TBTDevice();
+	device->iOperation=EOpPair;
+	device->iAddr=aPairingDevice->BDAddr();
+	if ( aNameEntry )
+	    {
+	    device->iNameEntry = *aNameEntry;
+	    }
+	CleanupStack::PushL(device);
+	iPairingDevice=aPairingDevice->CopyL();
+	// put the device to queue directly
+	iQueue.AppendL(device);
+	TInt err = KErrNone;
+	if(iQueue.Count() ==1 )
+		{
+		err = DoChangeDeviceL(*iQueue[0]);
+		}
+	CleanupStack::Pop(device);	
+    TRACE_FUNC_EXIT			
+	return err;
+	
+	}
+	
+// ---------------------------------------------------------------------
+// CBTPairedModel::HandleDisconnectCompleteL
+// Disconnection by CBluetoothPhysicalLinks, for those
+// connections not opened by btui. 
+// ---------------------------------------------------------------------
+//
+void CBTPairedModel::HandleDisconnectCompleteL(TInt aErr)
+	{
+	 TRACE_FUNC_ENTRY 
+	 
+	 if(iDisconnectDevice)
+	 	{
+	 	DisconnectComplete(iDisconnectDevice->iAddr,aErr);
+	 	}
+	 	
+	TRACE_FUNC_EXIT
+	}
+	
+// ---------------------------------------------------------------------
+// CBTPairedModel::FlagPhysicallyConnectedDevices
+//
+// Marks the EStatusPhysicallyConnected attribute to the devices
+// that have active connection.
+// ---------------------------------------------------------------------
+//
+void CBTPairedModel::FlagPhysicallyConnectedDevices(RDeviceArray &aDeviceArray)
+	{
+	TRACE_FUNC_ENTRY 
+	
+	RBTDevAddrArray a;
+	iLinks->Enumerate(a,KMaxCheckedConnections);
+	
+	TInt i=0; 
+	
+	for(i=0;i<aDeviceArray.Count();i++)
+		{
+        FlagPhysicallyConnectedDevices( *aDeviceArray[i], a );
+		}
+	a.Close();	
+	
+	TRACE_FUNC_EXIT 	
+	}
+	
+void CBTPairedModel::FlagPhysicallyConnectedDevices(TBTDevice& aDevice, RBTDevAddrArray& aBTDeviceArray)
+	{
+	TRACE_FUNC_ENTRY 
+	
+	TInt i2=0;
+	
+    UnsetStatusFlags( aDevice.iStatus, EStatusPhysicallyConnected );		
+    for( i2=0; i2<aBTDeviceArray.Count(); i2++ )
+        {
+        if(aDevice.iAddr == aBTDeviceArray[i2])
+            {
+            SetStatusFlags( aDevice.iStatus,EStatusPhysicallyConnected );		
+            break;				
+            }
+        }
+	
+	TRACE_FUNC_EXIT 	
+	}
+	
+// ---------------------------------------------------------------------
+// CBTPairedModel::GetDevice
+//
+// Adds the EPhysicallyConnected attribute devices that have any active
+// bluetooth connection.
+// ---------------------------------------------------------------------	
+//
+TInt CBTPairedModel::GetDevice(TBTDevice& aDevice)
+	{	
+	TRACE_FUNC_ENTRY 	
+	
+	TInt rvalue=CBTDevModelBase::GetDevice(aDevice);
+	RBTDevAddrArray a;
+	iLinks->Enumerate(a,KMaxCheckedConnections);
+    FlagPhysicallyConnectedDevices(aDevice, a);
+	a.Close();	
+	
+	TRACE_FUNC_EXIT 
+	
+	return rvalue;	
+	}
+	
+// ---------------------------------------------------------------------
+// CBTPairedModel::HandleLeave
+// from CBTDevModelBase
+// ---------------------------------------------------------------------
+//
+void CBTPairedModel::HandleLeave(TInt aErr,const TBTDevice* aDevice )
+	{
+	TRACE_FUNC_ENTRY
+	
+	iConnMan->CancelPairDevice();
+
+	delete iPairingDevice;
+	iPairingDevice=NULL;
+
+	delete iDisconnectDevice;
+	iDisconnectDevice=NULL;
+	
+	iRegistryObserver->StartIfNotRunning();
+	iRegistryObserver->Refresh();
+	
+	iState=EIdleState;
+	
+	CBTDevModelBase::HandleLeave(aErr,aDevice );
+	
+	TRACE_FUNC_EXIT
+	}