bluetoothengine/btui/devmodel/src/btpairedmodel.cpp
changeset 0 f63038272f30
child 11 a42ed326b458
equal deleted inserted replaced
-1:000000000000 0:f63038272f30
       
     1 /*
       
     2 * Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Maintain a Bluetooth devices data model for paired devices view
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "btpairedmodel.h"
       
    20 #include <btengutil.h>
       
    21 #include "debug.h"
       
    22 #include "btui.h"
       
    23 
       
    24 const TInt KMaxCheckedConnections=20;
       
    25 
       
    26 
       
    27 // ---------------------------------------------------------------------
       
    28 // CBTPairedModel::CBTPairedModel
       
    29 // ---------------------------------------------------------------------
       
    30 //
       
    31 CBTPairedModel::CBTPairedModel(MBTDeviceObserver* aObserver, TBTDeviceSortOrder* aOrder)
       
    32 	: CBTDevModelBase(aObserver, aOrder)
       
    33     {
       
    34 	TRACE_FUNC_ENTRY    
       
    35     TRACE_FUNC_EXIT	
       
    36     }
       
    37 
       
    38 // ---------------------------------------------------------------------
       
    39 // CBTPairedModel::NewL
       
    40 // ---------------------------------------------------------------------
       
    41 //
       
    42 CBTPairedModel* CBTPairedModel::NewL(MBTDeviceObserver* aObserver, TBTDeviceSortOrder* aOrder )
       
    43     {
       
    44     CBTPairedModel* self = new (ELeave) CBTPairedModel(aObserver, aOrder);
       
    45     CleanupStack::PushL(self);
       
    46     self->ConstructL();
       
    47     CleanupStack::Pop(self);
       
    48      
       
    49     return self;       
       
    50     }
       
    51     
       
    52 // --------------------------------------------------------------------------------------------
       
    53 // Destructor
       
    54 // --------------------------------------------------------------------------------------------
       
    55 //
       
    56 CBTPairedModel::~CBTPairedModel()
       
    57     {
       
    58 	TRACE_FUNC_ENTRY    
       
    59 	
       
    60     delete iConnMan;
       
    61     delete iPairingDevice;
       
    62     delete iLinks;
       
    63     delete iBtEngSettings;
       
    64     iSocketServ.Close();    
       
    65     
       
    66     TRACE_FUNC_EXIT    
       
    67     }
       
    68 
       
    69 // ---------------------------------------------------------------------
       
    70 // CBTPairedModel::ConstructL
       
    71 // ----------------------------------------------------------------------
       
    72 //
       
    73 void CBTPairedModel::ConstructL()
       
    74     {
       
    75 	TRACE_FUNC_ENTRY
       
    76 	
       
    77     // get all devices from btregistry to cache - local copy of CBTDeviceArray
       
    78     iDevMan = CBTEngDevMan::NewL(this);
       
    79     iConnMan = CBTEngConnMan::NewL(this);
       
    80     iSearchPattern.FindAll(); 
       
    81    	iRegistryObserver = CBTRegistryObserver::NewL(this, iSearchPattern);
       
    82 	iRegistryObserver->Refresh();
       
    83 	User::LeaveIfError( iSocketServ.Connect() );
       
    84 	iLinks=CBluetoothPhysicalLinks::NewL(*this,iSocketServ);
       
    85 	
       
    86 	iBtEngSettings = CBTEngSettings::NewL(this);
       
    87 	
       
    88     TRACE_FUNC_EXIT	
       
    89     }
       
    90     
       
    91 // ---------------------------------------------------------------------
       
    92 // CBTPairedModel::IsAnyDeviceConnected
       
    93 // ----------------------------------------------------------------------
       
    94 //
       
    95 TBool CBTPairedModel::IsAnyDeviceConnected()
       
    96     {        
       
    97 	TRACE_FUNC_ENTRY
       
    98 
       
    99 	FlagPhysicallyConnectedDevices(iDeviceArray);
       
   100     
       
   101 	for(TInt i = 0; i < iDeviceArray.Count(); i++)
       
   102 		{
       
   103 		if(iDeviceArray[i]->iStatus & (EStatusPhysicallyConnected|EStatusBtuiConnected))
       
   104 			{
       
   105 			TRACE_FUNC_EXIT				
       
   106 			return ETrue;
       
   107 			}        
       
   108 		}
       
   109 					
       
   110 	TRACE_FUNC_EXIT				
       
   111 	
       
   112     return EFalse;
       
   113     }
       
   114     
       
   115 // ---------------------------------------------------------------------
       
   116 // CBTPairedModel::DoChangeDevice
       
   117 // ---------------------------------------------------------------------
       
   118 
       
   119 TInt CBTPairedModel::DoChangeDeviceL(const TBTDevice& aDevice)
       
   120     {
       
   121     TRACE_FUNC_ENTRY
       
   122     TRACE_BDADDR(aDevice.iAddr)
       
   123    	// check that the device actually still exists
       
   124    	if(aDevice.iOperation != EOpPair )
       
   125    		{
       
   126    		User::LeaveIfError( GetIndexByAddress(aDevice.iAddr, aDevice.iIndex ) );	
       
   127    		}
       
   128    	
       
   129     // disconnect device to be unpaired, or blocked
       
   130     if((aDevice.iOperation == EOpBlock || aDevice.iOperation == EOpUnpair ))
       
   131     	{    	
       
   132     	if( iState != EDisconnectBeforeOperationState)
       
   133     		{
       
   134     			// disconnect by CBTEngConnMan if connected that way.
       
   135     			if (aDevice.iStatus & static_cast<TInt>(EStatusBtuiConnected ) )
       
   136     				{
       
   137     				TInt code=KErrNone;
       
   138 		    		TRAPD(err,
       
   139 		    		iState=EDisconnectBeforeOperationState;
       
   140 			    		iDisconnectDevice=new(ELeave) TBTDevice(aDevice);
       
   141 			    		code=iConnMan->Disconnect(aDevice.iAddr,EBTDiscImmediate);    				
       
   142 			    		);
       
   143 					// if the return code is KErrNone then there will be
       
   144 					// a callback. However if it fails, there will not be any.
       
   145 					// So the execution will go on inside this method, if there was an error.
       
   146 					if(err == KErrNone && code==KErrNone )
       
   147 						{
       
   148 						return KErrNone;
       
   149 						}
       
   150 						
       
   151     				}
       
   152     			else // try disconnecting from the link layer
       
   153     				{
       
   154     				TInt code=KErrNone;
       
   155     				TRAPD(err,
       
   156 					iState=EDisconnectBeforeOperationState;
       
   157 						iDisconnectDevice=new(ELeave) TBTDevice(aDevice);
       
   158 						code=iLinks->Disconnect(aDevice.iAddr);
       
   159 						);
       
   160 					// if the return code is KErrNone then there will be
       
   161 					// a callback. However if it fails, there will not be any.
       
   162 					// So the execution will go on inside this method, if there was an error.
       
   163 					if(err == KErrNone && code==KErrNone )
       
   164 						{
       
   165 						return KErrNone;
       
   166 						}
       
   167     				}
       
   168     		}
       
   169    		else    
       
   170 			iState=EIdleState;
       
   171     
       
   172     	}
       
   173     	
       
   174     if(	aDevice.iOperation ==EOpPair)
       
   175     	{
       
   176     	DoPairDeviceL();
       
   177     	TRACE_FUNC_EXIT 
       
   178     	return KErrNone;    	
       
   179     	}
       
   180     
       
   181     TInt err = CBTDevModelBase::DoChangeDeviceL(aDevice);
       
   182     if(iDisconnectDevice!= NULL)
       
   183     	{
       
   184     	delete iDisconnectDevice;
       
   185     	iDisconnectDevice=NULL;
       
   186     	}
       
   187     
       
   188     if (err != KErrNone)
       
   189         {      
       
   190         TBTDevAddr addr;
       
   191         if(aDevice.iAddr == KNullAddress )
       
   192         	{        	        	
       
   193         	if(aDevice.iIndex < 0 || aDevice.iIndex >= iDeviceArray.Count())
       
   194         		return KErrArgument;
       
   195         	else
       
   196         		addr=iDeviceArray[aDevice.iIndex]->iAddr;
       
   197         	}
       
   198         	else
       
   199         		addr=aDevice.iAddr;
       
   200         	
       
   201         switch (aDevice.iOperation)
       
   202             {
       
   203             case EOpConnect:
       
   204             	{                    	   		            		               
       
   205                 err = iConnMan->Connect(addr, aDevice.iDeviceClass);
       
   206                 break;
       
   207             	}
       
   208             case EOpDisconnect:
       
   209             	{
       
   210             	iDisconnectDevice=new(ELeave) TBTDevice(aDevice);            		            		           	
       
   211 				if (aDevice.iStatus & static_cast<TInt>(EStatusBtuiConnected ) )            	
       
   212 					{
       
   213 					err = iConnMan->Disconnect(addr, EBTDiscImmediate);	
       
   214 					}
       
   215 				else
       
   216 					{
       
   217 					err=iLinks->Disconnect(aDevice.iAddr);
       
   218 					}
       
   219                 
       
   220                 break;
       
   221             	}
       
   222             default:
       
   223             	User::Leave(err);
       
   224                 break;
       
   225             }
       
   226         }
       
   227         
       
   228     TRACE_FUNC_EXIT        
       
   229     
       
   230     return err;
       
   231     }
       
   232     
       
   233 // ---------------------------------------------------------------------
       
   234 // CBTPairedModel::DoCancelChange
       
   235 // ---------------------------------------------------------------------
       
   236 //    
       
   237 void CBTPairedModel::DoCancelChangeL(const TBTDevice& aDevice)
       
   238     {
       
   239     TRACE_FUNC_ENTRY
       
   240     
       
   241 	if(aDevice.iIndex >= iDeviceArray.Count())
       
   242         {
       
   243         TRACE_INFO((_L("index is %d, max expected is %d"), aDevice.iIndex, iDeviceArray.Count()));
       
   244         TRACE_FUNC_EXIT    
       
   245 		return; 
       
   246         }
       
   247     
       
   248     // in case it was stopped
       
   249     iRegistryObserver->StartIfNotRunning();
       
   250     switch (aDevice.iOperation)
       
   251         {
       
   252         case EOpPair:
       
   253         	if( iState==EDeleteDeviceState || iState==EAddDeviceState )
       
   254         		{
       
   255         		iDevMan->Cancel();
       
   256         		}        		
       
   257         	else
       
   258         		{
       
   259         		iConnMan->CancelPairDevice();
       
   260         		}            	        	
       
   261             delete iPairingDevice;
       
   262             iPairingDevice=NULL;
       
   263             iState=EIdleState;
       
   264             iRegistryObserver->Refresh();
       
   265             break;
       
   266             
       
   267         case EOpConnect:
       
   268         	{	
       
   269         	
       
   270             TBTDevAddr addr;
       
   271             if(aDevice.iIndex == KErrNotFound) 
       
   272             	{
       
   273             	addr=aDevice.iAddr;
       
   274             	}                
       
   275             else
       
   276             	{
       
   277             	addr=iDeviceArray[aDevice.iIndex]->iAddr;
       
   278             	}
       
   279             	
       
   280             iConnMan->CancelConnect(addr);
       
   281             break;
       
   282         	}
       
   283         default:
       
   284             CBTDevModelBase::CancelChange(aDevice);
       
   285             return;
       
   286         }
       
   287     iRegistryObserver->StartIfNotRunning();
       
   288     
       
   289 	if(iQueue.Count()>0)
       
   290 		{
       
   291 		delete iQueue[0];
       
   292 		iQueue.Remove(0);		
       
   293 		HandleQueue();
       
   294 		}
       
   295 	
       
   296     TRACE_FUNC_EXIT	       
       
   297     }
       
   298     
       
   299 // ---------------------------------------------------------------------
       
   300 // CBTPairedModel::HandleNewDevice
       
   301 //
       
   302 // Adds the device if it is not banned
       
   303 // ---------------------------------------------------------------------
       
   304 //
       
   305 void CBTPairedModel::HandleNewDeviceL(const CBTDevice* aRegDevice,
       
   306         TNameEntry* aNameEntry)
       
   307     {
       
   308     TRACE_FUNC_ENTRY
       
   309     
       
   310     // It is needed to filter out blocked devices,
       
   311     // since otherwise blocked and paired devices would
       
   312     // be listed.
       
   313     if( ! aRegDevice->GlobalSecurity().Banned()     	
       
   314             && IsUserAwarePaired( aRegDevice->AsNamelessDevice() ) ) 
       
   315         {
       
   316         AddDeviceL(aRegDevice, aNameEntry, EOpNone);
       
   317         }
       
   318 
       
   319     TRACE_FUNC_EXIT		    
       
   320     }
       
   321     
       
   322 // -----------------------------------------------------------------------
       
   323 // CBTPairedModel::CreateDevice
       
   324 //
       
   325 // This implementaion will add the connectable status from the superclass.
       
   326 // -----------------------------------------------------------------------  
       
   327 //
       
   328 TBTDevice* CBTPairedModel::CreateDeviceL(const CBTDevice* aRegDevice,
       
   329         TNameEntry* aNameEntry)
       
   330     {
       
   331     TRACE_FUNC_ENTRY
       
   332     
       
   333     TBTDevice* device = CBTDevModelBase::CreateDeviceL(aRegDevice, aNameEntry);
       
   334     
       
   335     // add EStatusBtuiConnected status if the device has a profile connection
       
   336     TBTEngConnectionStatus connStatus;
       
   337     iConnMan->IsConnected(device->iAddr, connStatus);
       
   338     
       
   339     if(connStatus == EBTEngConnecting || connStatus == EBTEngConnected)
       
   340     	{
       
   341     	SetStatusFlags(device->iStatus,EStatusBtuiConnected);
       
   342     	}
       
   343     
       
   344     // add connectable status
       
   345     TBool connectable=EFalse;
       
   346     iConnMan->IsConnectable(aRegDevice->BDAddr(), aRegDevice->DeviceClass(), connectable );
       
   347     
       
   348     if( connectable) 
       
   349     	{
       
   350     	SetStatusFlags(device->iStatus, EStatusConnectable );
       
   351     	}
       
   352     	
       
   353 	TRACE_FUNC_EXIT 
       
   354 	       
       
   355     return device;
       
   356     }
       
   357     
       
   358 // ---------------------------------------------------------------------
       
   359 // CBTPairedModel::ConnectComplete
       
   360 // from MBTEngConnObserver
       
   361 // ----------------------------------------------------------------------
       
   362 //
       
   363 void CBTPairedModel::ConnectComplete(TBTDevAddr& aAddr, TInt aErr, RBTDevAddrArray* aConflicts)
       
   364     {
       
   365     TRACE_FUNC_ENTRY
       
   366     
       
   367     TRACE_INFO((_L("aErr=%d"), aErr))
       
   368 
       
   369     TInt index = GetIndexByAddress(aAddr);
       
   370     TBool requestIssuedFromPhone = EFalse;
       
   371     TBTDevice connectedDevice;
       
   372     
       
   373     // was the device connected from request by the ui
       
   374 	if(iQueue.Count()>0 && iQueue[0]->iOperation==EOpConnect && 
       
   375 	  iQueue[0]->iAddr == aAddr)
       
   376 		{
       
   377 		requestIssuedFromPhone = ETrue;
       
   378 		if(index >=0) // is it from paired list
       
   379 			{			
       
   380 			connectedDevice=*iDeviceArray[index];
       
   381 			connectedDevice.iOperation=EOpConnect;
       
   382 			}
       
   383 		else
       
   384 			{
       
   385 			connectedDevice=*iQueue[0];		
       
   386 			}
       
   387     	
       
   388     	}
       
   389     else
       
   390     	{
       
   391     	requestIssuedFromPhone = EFalse;
       
   392 		if(index >=0) // is it from paired list
       
   393 			{
       
   394 			connectedDevice=*iDeviceArray[index];
       
   395 			connectedDevice.iOperation=EOpConnect;
       
   396 			}
       
   397 		else
       
   398 			{
       
   399 	    	// it was not. Try to fill what can be filled.
       
   400 			connectedDevice.iAddr=aAddr;
       
   401 			connectedDevice.iIndex=KErrNotFound;
       
   402 			connectedDevice.iOperation = EOpConnect;			
       
   403 			}    	
       
   404     	}        
       
   405     
       
   406     if (aErr == KErrAlreadyExists )
       
   407         { 
       
   408         // gather the names of the conflicting devices.
       
   409         RBTDevNameArray nameArray;
       
   410         for (TInt i = 0; aConflicts!= NULL && i < aConflicts->Count(); i++)
       
   411             {
       
   412             //remove duplicates
       
   413             if(i>0&& (*aConflicts)[i]==(*aConflicts)[i-1])
       
   414             	{
       
   415             	continue;
       
   416             	}
       
   417             TInt di = GetIndexByAddress((*aConflicts)[i]);
       
   418             
       
   419             if(di >=0 )
       
   420             	{
       
   421             	nameArray.Append(&iDeviceArray[di]->iName);
       
   422             	}            	
       
   423             }
       
   424         if(iObserver )
       
   425         	{
       
   426     		iObserver->NotifyChangeDeviceComplete(aErr, connectedDevice, &nameArray);        	
       
   427         	}            
       
   428         nameArray.Reset();
       
   429         }
       
   430     else 
       
   431         {
       
   432         if (aErr == KErrNone)
       
   433             {
       
   434             // we will set the connect status of the device
       
   435             // if it is found in paired devices.
       
   436             if( index >= 0 )
       
   437             	{
       
   438             	SetStatusFlags(iDeviceArray[index]->iStatus,EStatusBtuiConnected );
       
   439             	}
       
   440             }
       
   441         else        
       
   442             {
       
   443             // we will unset the connect status of the device if connection failed &
       
   444             // it is found in paired devices.
       
   445             if( index >= 0 )
       
   446                 {                   
       
   447                 // add EStatusBtuiConnected status if the device has a profile connection
       
   448                 TBTEngConnectionStatus connStatus;
       
   449                 iConnMan->IsConnected(connectedDevice.iAddr, connStatus);
       
   450    
       
   451                 if (connStatus != EBTEngConnecting && connStatus != EBTEngConnected)
       
   452                    {
       
   453                    TRACE_INFO(_L("Unset EStatusBtuiConnected"))
       
   454                    UnsetStatusFlags(iDeviceArray[index]->iStatus,EStatusBtuiConnected );
       
   455                    }                
       
   456                 }
       
   457             }
       
   458 		if(iObserver)
       
   459 			{
       
   460 			//Show only phone issued request complete notes
       
   461 			//Do not show notes for device issued request when BTUI is active
       
   462 			if ( requestIssuedFromPhone ) 
       
   463 			    {
       
   464         	    iObserver->NotifyChangeDeviceComplete(aErr, connectedDevice);
       
   465 			    }
       
   466         	
       
   467         	SendRefreshIfNoError(aErr);
       
   468 			}		
       
   469         }           
       
   470     
       
   471     // Process the next command if the connect was
       
   472     //initiated by this UI.    
       
   473 	if(iQueue.Count()>0 && iQueue[0]->iOperation==EOpConnect && 
       
   474        iQueue[0]->iAddr == aAddr)        
       
   475         {
       
   476         delete iQueue[0];
       
   477         iQueue.Remove(0);		
       
   478         HandleQueue();
       
   479         }
       
   480     else
       
   481         {
       
   482         if( iQueue.Count()==0 ) 
       
   483             {
       
   484             TRACE_INFO((_L("op Q is empty")));
       
   485             }
       
   486         else
       
   487             {
       
   488             TRACE_INFO((_L("unexpected op Q contents, count is %d, op is %d"), iDeviceArray.Count(), iQueue[0]->iOperation));
       
   489             }
       
   490         }
       
   491     TRACE_FUNC_EXIT	
       
   492     }
       
   493     
       
   494 // ---------------------------------------------------------------------
       
   495 // CBTPairedModel::PowerStateChanged
       
   496 // from MBTEngSettingObserver
       
   497 // ----------------------------------------------------------------------
       
   498 //
       
   499 void CBTPairedModel::PowerStateChanged( TBTPowerStateValue )
       
   500 	{
       
   501 	TRACE_FUNC_ENTRY
       
   502 	
       
   503 	// This is implemented for case like when user choses offlne mode, Bluetooth is swithced off
       
   504 	// very fast. Bt audio components don't have enough time to close audio connection.
       
   505 	// BTUI needs to update UI display.
       
   506 	
       
   507 	TInt count = iDeviceArray.Count();  
       
   508     
       
   509     for (TInt i = 0; i < count; i++)
       
   510     	{
       
   511      	UnsetStatusFlags(iDeviceArray[i]->iStatus, EStatusBtuiConnected );
       
   512     	}
       
   513 	
       
   514 	SendRefreshIfNoError(KErrNone);
       
   515 	
       
   516 	TRACE_FUNC_EXIT
       
   517 	}
       
   518     
       
   519 // ----------------------------------------------------
       
   520 // CBTPairedModel::VisibilityModeChanged
       
   521 // from MBTEngSettingObserver
       
   522 // ----------------------------------------------------
       
   523 //    
       
   524 void CBTPairedModel::VisibilityModeChanged( TBTVisibilityMode  )
       
   525     {
       
   526 	TRACE_FUNC_ENTRY
       
   527 	
       
   528 	
       
   529 	TRACE_FUNC_EXIT	
       
   530     }
       
   531         
       
   532 // ---------------------------------------------------------------------
       
   533 // CBTPairedModel::DisconnectComplete
       
   534 // from MBTEngConnObserver
       
   535 // ----------------------------------------------------------------------
       
   536 //
       
   537 void CBTPairedModel::DisconnectComplete(TBTDevAddr& aAddr, TInt aErr)
       
   538     {
       
   539     TRACE_FUNC_ENTRY
       
   540     
       
   541     // the disconnect was part of a unpairing or blocking operation
       
   542 	if(iState == EDisconnectBeforeOperationState && iDisconnectDevice && aAddr == iDisconnectDevice->iAddr )
       
   543 		{
       
   544 
       
   545 		TRAPD(err,
       
   546 			DoChangeDeviceL(*iDisconnectDevice);		
       
   547 		);
       
   548 		iState=EIdleState;		
       
   549 		if(err != KErrNone)
       
   550 			{
       
   551 			HandleLeave(err,iDisconnectDevice);
       
   552 			}
       
   553 		TRACE_FUNC_EXIT
       
   554 		return;
       
   555 		}		    
       
   556     
       
   557     TInt index = GetIndexByAddress(aAddr);
       
   558     
       
   559     // the disconnected device was not the devicein the list,
       
   560     // so we do not tell anyone about it.
       
   561     if ( iDisconnectDevice == NULL || iDisconnectDevice->iAddr != aAddr )
       
   562     	{
       
   563     	if (index >=0 )
       
   564     	{
       
   565     		UnsetStatusFlags(iDeviceArray[index]->iStatus, EStatusBtuiConnected );
       
   566     	}
       
   567     	
       
   568     	SendRefreshIfNoError(KErrNone);
       
   569 
       
   570 		TBTDevice disconnectedDevice;
       
   571 		disconnectedDevice.iAddr = aAddr;
       
   572 		// Notify needed when there is active disconnect query dialog
       
   573     	iObserver->NotifyChangeDeviceComplete(KErrDisconnected, disconnectedDevice);
       
   574 		
       
   575     	TRACE_FUNC_EXIT  
       
   576     	return;
       
   577     	}
       
   578     	
       
   579 	if(index >=0 )
       
   580 		{
       
   581 	    // set it to "not connected" no matter disconnection works or not
       
   582 	    UnsetStatusFlags(iDeviceArray[index]->iStatus, EStatusBtuiConnected );
       
   583 	    iDeviceArray[index]->iOperation = EOpDisconnect;
       
   584 	    iObserver->NotifyChangeDeviceComplete(aErr, *iDeviceArray[index]);		
       
   585 		}
       
   586 	else
       
   587 		{
       
   588 		iDisconnectDevice->iIndex=index;
       
   589 		iObserver->NotifyChangeDeviceComplete(aErr, *iDisconnectDevice);		
       
   590 		}
       
   591 
       
   592 	delete iDisconnectDevice;
       
   593 	iDisconnectDevice=NULL;    	
       
   594 
       
   595    	SendRefreshIfNoError(aErr);
       
   596    	// continue processing queue only if the disconnected device is
       
   597    	// the device with we requested disconnect to.
       
   598    	// this has to be checked so that we do not end on having multiple
       
   599    	// queue processors at the same time
       
   600 	if(iQueue.Count()>0 && iQueue[0]->iOperation==EOpDisconnect && 
       
   601 	  iQueue[0]->iAddr == aAddr)           	
       
   602 		{
       
   603 		delete iQueue[0];
       
   604 		iQueue.Remove(0);		
       
   605 		HandleQueue();
       
   606 		}
       
   607     else
       
   608         {
       
   609         if( iQueue.Count()==0 ) 
       
   610             {
       
   611             TRACE_INFO((_L("op Q is empty")));
       
   612             }
       
   613         else
       
   614             {
       
   615             TRACE_INFO((_L("unexpected op Q contents, count is %d, op is %d"), iDeviceArray.Count(), iQueue[0]->iOperation));
       
   616             }
       
   617         }
       
   618     TRACE_FUNC_EXIT   	
       
   619     }
       
   620     
       
   621 // ---------------------------------------------------------------------
       
   622 // CBTPairedModel::PairingComplete
       
   623 // from MBTEngConnObserver
       
   624 // ----------------------------------------------------------------------
       
   625 //
       
   626 void CBTPairedModel::PairingComplete(TBTDevAddr& aAddr, TInt aErr)
       
   627 	{
       
   628 	TRACE_FUNC_ENTRY
       
   629 	
       
   630 	TRAPD(err,
       
   631 		PairingCompleteL(aAddr,aErr);
       
   632 		);
       
   633 		
       
   634 	if(err!=KErrNone)
       
   635 	{
       
   636 		TBTDevice tmp;
       
   637 		tmp.iAddr=aAddr;					
       
   638 		tmp.iIndex=GetIndexByAddress(aAddr);
       
   639 		tmp.iOperation=EOpPair;
       
   640 		HandleLeave(err,&tmp );
       
   641 
       
   642 		delete iPairingDevice;
       
   643 		iPairingDevice=NULL;				
       
   644 	}
       
   645 	
       
   646 	TRACE_FUNC_EXIT
       
   647 	}
       
   648 	
       
   649 // ---------------------------------------------------------------------
       
   650 // CBTPairedModel::PairingCompleteL
       
   651 // Leaving version of PairingComplete
       
   652 // ----------------------------------------------------------------------
       
   653 //	
       
   654 void CBTPairedModel::PairingCompleteL(TBTDevAddr& aAddr, TInt aErr)
       
   655     {
       
   656     TRACE_FUNC_ENTRY
       
   657     
       
   658 	// The device that was attempted to be paired is 
       
   659 	// different from the the device that the pairing is finnished.
       
   660 	// This cannot happen, since CBTConnMan will report
       
   661 	// only pairing started by the listener and the UI
       
   662 	// does not allow making two pairings at the same time
       
   663     __ASSERT_DEBUG(aAddr==iPairingDevice->BDAddr(),
       
   664       PANIC(EBTPanicCommandComplettedToDiffrentDeviceThanStarted));
       
   665     (void) aAddr;
       
   666 
       
   667     // bail out if the operation queue is not what we expect
       
   668     if( iQueue.Count() == 0 
       
   669         || iQueue[0]->iOperation != EOpPair 
       
   670         || iQueue[0]->iAddr != aAddr )        
       
   671         {
       
   672         if( iQueue.Count()==0 ) 
       
   673             {
       
   674             TRACE_INFO((_L("op Q is empty")));
       
   675             }
       
   676         else
       
   677             {
       
   678             TRACE_INFO((_L("unexpected op Q contents, count is %d, op is %d"), iDeviceArray.Count(), iQueue[0]->iOperation));
       
   679             }
       
   680         TRACE_FUNC_EXIT
       
   681         return;
       
   682         }
       
   683 
       
   684     iState=EIdleState;		
       
   685 	TBTDevice* tmpDevice=NULL;
       
   686 	tmpDevice=CreateDeviceL(iPairingDevice, &( iQueue[0]->iNameEntry ) );
       
   687 	tmpDevice->iOperation=EOpPair;    		
       
   688 	
       
   689     // new paired device must be inserted to the array, since
       
   690     // user may be doing trust/ connect operations before
       
   691     // it is refreshed from registry
       
   692     TBool deleleteTmpDevice=ETrue;
       
   693 	
       
   694 	if( aErr == KErrNone  )    	
       
   695 		{
       
   696 		SetStatusFlags(tmpDevice->iStatus,EStatusPaired);
       
   697 		TInt index;
       
   698 		index=GetIndexByAddress(iPairingDevice->BDAddr());
       
   699 		
       
   700 		if(index == KErrNotFound)
       
   701 			{
       
   702 			iDeviceArray.InsertInOrderL(tmpDevice,*iSortOrder );
       
   703   			  			
       
   704     		RenumberDeviceArray();
       
   705 
       
   706     		// iPairingDevice is now owned by iDeviceArray. 
       
   707     		// So it must not be deleted by his function
       
   708     		deleleteTmpDevice=EFalse;
       
   709     		
       
   710     		SendRefreshIfNoError(aErr,GetIndexByAddress(iPairingDevice->BDAddr()));
       
   711 			}					
       
   712 		}
       
   713 
       
   714 	
       
   715     iObserver->NotifyChangeDeviceComplete(aErr, *tmpDevice);         
       
   716     
       
   717     /*
       
   718      * We issue an background refresh in case 
       
   719      * registry is updated from btnotif
       
   720      */
       
   721 	iRegistryObserver->StartIfNotRunning();
       
   722 	iRegistryObserver->Refresh();
       
   723     // delete if the ownership has not changed
       
   724     if(deleleteTmpDevice )
       
   725         {
       
   726     	delete tmpDevice;
       
   727     	tmpDevice=NULL;
       
   728         }
       
   729 
       
   730 	delete iPairingDevice;    
       
   731     iPairingDevice=NULL;       
       
   732 	delete iQueue[0];
       
   733 	iQueue.Remove(0);
       
   734     
       
   735     HandleQueue();    		    
       
   736 
       
   737     TRACE_FUNC_EXIT    
       
   738     }
       
   739     
       
   740 // ---------------------------------------------------------------------
       
   741 // BTPairedModel::HandleDevManComplete
       
   742 // from MBTEngDevModelBase
       
   743 // ----------------------------------------------------------------------
       
   744 //
       
   745 void  CBTPairedModel::HandleDevManComplete(TInt aErr)
       
   746 	{
       
   747 	TRACE_FUNC_ENTRY
       
   748 	
       
   749 	// if this is handled we can remove this
       
   750 	if(iDisconnectDevice)
       
   751 		{
       
   752 		delete iDisconnectDevice;
       
   753 		iDisconnectDevice=NULL;
       
   754 		}
       
   755 		
       
   756 	if(iPairingDevice)
       
   757 		{
       
   758 		// add the device just deleted	
       
   759 		if(iState==EDeleteDeviceState && (aErr==KErrNone || aErr == KErrNotFound))
       
   760 			{
       
   761 				iPairingDevice->DeleteLinkKey();
       
   762 				TBTDeviceSecurity sec=iPairingDevice->GlobalSecurity();
       
   763 				sec.SetBanned(EFalse);
       
   764 				sec.SetNoAuthorise(EFalse);
       
   765 				iDevMan->AddDevice(*iPairingDevice);
       
   766 				iState=EAddDeviceState;
       
   767 				TRACE_FUNC_EXIT	
       
   768 				return;
       
   769 			}
       
   770 		// if the device is added allready, or if deletion failed
       
   771 		// we will go on with pairing the device
       
   772 		if(iState==EAddDeviceState||(iState==EDeleteDeviceState&& aErr != KErrNone))
       
   773 			{
       
   774 			aErr = iConnMan->PairDevice(iPairingDevice->BDAddr(), iPairingDevice->DeviceClass());
       
   775 			iState=EPairDeviceState;
       
   776 			// NOTE: now PairingComplete will be called and not this method.
       
   777 			TRACE_FUNC_EXIT	
       
   778 			return;
       
   779 			}
       
   780 		}
       
   781 	// these are not handled by superclass		
       
   782 	if(iQueue.Count()>0 &&
       
   783 	    ( iQueue[0]->iOperation==EOpConnect || 
       
   784 	     iQueue[0]->iOperation==EOpDisconnect ) )
       
   785 		{
       
   786 		iObserver->NotifyChangeDeviceComplete(aErr, *iQueue[0]);
       
   787 		}
       
   788 			
       
   789 	CBTDevModelBase::HandleDevManComplete(aErr);
       
   790 	
       
   791     TRACE_FUNC_EXIT	
       
   792 	}
       
   793 	
       
   794 // ---------------------------------------------------------------------
       
   795 // CBTPairedModel::DoPairDevice
       
   796 // ---------------------------------------------------------------------
       
   797 //
       
   798 void  CBTPairedModel::DoPairDeviceL()
       
   799 	{
       
   800 	TRACE_FUNC_ENTRY
       
   801 	
       
   802 	// we are starting a new command. Checks that no earlier commands 
       
   803 	// have been executed, but not finished properly.
       
   804 	__ASSERT_DEBUG(iState==EIdleState,PANIC(EBTPanicDevManQueueIsInIllegalState));
       
   805 	// check that there is no other pairing going on.
       
   806 	__ASSERT_DEBUG(iPairingDevice!=NULL,PANIC(EBTPanicTwoPairingAttemptsAtTheSameTime));
       
   807 	
       
   808 	iRegistryObserver->Cancel();
       
   809 	
       
   810 	// devices to be paired are first deleted
       
   811 	// then added back. Only after that the paring itself is
       
   812 	// started
       
   813 	TBTRegistrySearch dele;
       
   814 	dele.FindAddress(iPairingDevice->BDAddr());
       
   815 	TInt err = iDevMan->DeleteDevices(dele);
       
   816 
       
   817 	iState=EDeleteDeviceState;
       
   818    if (err)
       
   819        {
       
   820        HandleDevManComplete(err);
       
   821        }
       
   822        
       
   823     TRACE_FUNC_EXIT
       
   824 	}
       
   825 	
       
   826 // ---------------------------------------------------------------------
       
   827 // CBTPairedModel::PairDevice
       
   828 //
       
   829 // Puts the given aPairingDevice to iPairingDevice and
       
   830 // adds and empty device with iOperation=EOpPair as placeholder to iQueue.
       
   831 // the pairing itself will be handled by DoChangeDevice that
       
   832 // cals then 
       
   833 // ---------------------------------------------------------------------
       
   834 //
       
   835 TInt CBTPairedModel::PairDeviceL(const CBTDevice* aPairingDevice,
       
   836         TNameEntry* aNameEntry)	
       
   837 	{
       
   838 	TRACE_FUNC_ENTRY
       
   839 	
       
   840 	// cannot put two pairings to queue. 
       
   841 	// this is not possible since ui does not allow it.
       
   842 	if(iPairingDevice)
       
   843 		return KErrInUse;
       
   844 		
       
   845 	TBTDevice*  device=new(ELeave) TBTDevice();
       
   846 	device->iOperation=EOpPair;
       
   847 	device->iAddr=aPairingDevice->BDAddr();
       
   848 	if ( aNameEntry )
       
   849 	    {
       
   850 	    device->iNameEntry = *aNameEntry;
       
   851 	    }
       
   852 	CleanupStack::PushL(device);
       
   853 	iPairingDevice=aPairingDevice->CopyL();
       
   854 	// put the device to queue directly
       
   855 	iQueue.AppendL(device);
       
   856 	TInt err = KErrNone;
       
   857 	if(iQueue.Count() ==1 )
       
   858 		{
       
   859 		err = DoChangeDeviceL(*iQueue[0]);
       
   860 		}
       
   861 	CleanupStack::Pop(device);	
       
   862     TRACE_FUNC_EXIT			
       
   863 	return err;
       
   864 	
       
   865 	}
       
   866 	
       
   867 // ---------------------------------------------------------------------
       
   868 // CBTPairedModel::HandleDisconnectCompleteL
       
   869 // Disconnection by CBluetoothPhysicalLinks, for those
       
   870 // connections not opened by btui. 
       
   871 // ---------------------------------------------------------------------
       
   872 //
       
   873 void CBTPairedModel::HandleDisconnectCompleteL(TInt aErr)
       
   874 	{
       
   875 	 TRACE_FUNC_ENTRY 
       
   876 	 
       
   877 	 if(iDisconnectDevice)
       
   878 	 	{
       
   879 	 	DisconnectComplete(iDisconnectDevice->iAddr,aErr);
       
   880 	 	}
       
   881 	 	
       
   882 	TRACE_FUNC_EXIT
       
   883 	}
       
   884 	
       
   885 // ---------------------------------------------------------------------
       
   886 // CBTPairedModel::FlagPhysicallyConnectedDevices
       
   887 //
       
   888 // Marks the EStatusPhysicallyConnected attribute to the devices
       
   889 // that have active connection.
       
   890 // ---------------------------------------------------------------------
       
   891 //
       
   892 void CBTPairedModel::FlagPhysicallyConnectedDevices(RDeviceArray &aDeviceArray)
       
   893 	{
       
   894 	TRACE_FUNC_ENTRY 
       
   895 	
       
   896 	RBTDevAddrArray a;
       
   897 	iLinks->Enumerate(a,KMaxCheckedConnections);
       
   898 	
       
   899 	TInt i=0; 
       
   900 	
       
   901 	for(i=0;i<aDeviceArray.Count();i++)
       
   902 		{
       
   903         FlagPhysicallyConnectedDevices( *aDeviceArray[i], a );
       
   904 		}
       
   905 	a.Close();	
       
   906 	
       
   907 	TRACE_FUNC_EXIT 	
       
   908 	}
       
   909 	
       
   910 void CBTPairedModel::FlagPhysicallyConnectedDevices(TBTDevice& aDevice, RBTDevAddrArray& aBTDeviceArray)
       
   911 	{
       
   912 	TRACE_FUNC_ENTRY 
       
   913 	
       
   914 	TInt i2=0;
       
   915 	
       
   916     UnsetStatusFlags( aDevice.iStatus, EStatusPhysicallyConnected );		
       
   917     for( i2=0; i2<aBTDeviceArray.Count(); i2++ )
       
   918         {
       
   919         if(aDevice.iAddr == aBTDeviceArray[i2])
       
   920             {
       
   921             SetStatusFlags( aDevice.iStatus,EStatusPhysicallyConnected );		
       
   922             break;				
       
   923             }
       
   924         }
       
   925 	
       
   926 	TRACE_FUNC_EXIT 	
       
   927 	}
       
   928 	
       
   929 // ---------------------------------------------------------------------
       
   930 // CBTPairedModel::GetDevice
       
   931 //
       
   932 // Adds the EPhysicallyConnected attribute devices that have any active
       
   933 // bluetooth connection.
       
   934 // ---------------------------------------------------------------------	
       
   935 //
       
   936 TInt CBTPairedModel::GetDevice(TBTDevice& aDevice)
       
   937 	{	
       
   938 	TRACE_FUNC_ENTRY 	
       
   939 	
       
   940 	TInt rvalue=CBTDevModelBase::GetDevice(aDevice);
       
   941 	RBTDevAddrArray a;
       
   942 	iLinks->Enumerate(a,KMaxCheckedConnections);
       
   943     FlagPhysicallyConnectedDevices(aDevice, a);
       
   944 	a.Close();	
       
   945 	
       
   946 	TRACE_FUNC_EXIT 
       
   947 	
       
   948 	return rvalue;	
       
   949 	}
       
   950 	
       
   951 // ---------------------------------------------------------------------
       
   952 // CBTPairedModel::HandleLeave
       
   953 // from CBTDevModelBase
       
   954 // ---------------------------------------------------------------------
       
   955 //
       
   956 void CBTPairedModel::HandleLeave(TInt aErr,const TBTDevice* aDevice )
       
   957 	{
       
   958 	TRACE_FUNC_ENTRY
       
   959 	
       
   960 	iConnMan->CancelPairDevice();
       
   961 
       
   962 	delete iPairingDevice;
       
   963 	iPairingDevice=NULL;
       
   964 
       
   965 	delete iDisconnectDevice;
       
   966 	iDisconnectDevice=NULL;
       
   967 	
       
   968 	iRegistryObserver->StartIfNotRunning();
       
   969 	iRegistryObserver->Refresh();
       
   970 	
       
   971 	iState=EIdleState;
       
   972 	
       
   973 	CBTDevModelBase::HandleLeave(aErr,aDevice );
       
   974 	
       
   975 	TRACE_FUNC_EXIT
       
   976 	}