bluetoothengine/btui/devmodel/src/btpairedmodel.cpp
branchRCL_3
changeset 56 9386f31cc85b
child 72 4b59561a31c0
equal deleted inserted replaced
55:613943a21004 56:9386f31cc85b
       
     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 
       
   425         // we will unset the connect status of the device if connection failed &
       
   426             // it is found in paired devices.
       
   427         if( index >= 0 )
       
   428             {
       
   429             // add EStatusBtuiConnected status if the device has a profile connection
       
   430             TBTEngConnectionStatus connStatus;
       
   431             iConnMan->IsConnected(connectedDevice.iAddr, connStatus);
       
   432    
       
   433             if (connStatus != EBTEngConnecting && connStatus != EBTEngConnected)
       
   434                 {
       
   435                 TRACE_INFO(_L("Unset EStatusBtuiConnected"))
       
   436                 UnsetStatusFlags(iDeviceArray[index]->iStatus,EStatusBtuiConnected );
       
   437                 }
       
   438             }
       
   439         
       
   440         if(iObserver)
       
   441             {
       
   442             //Show only phone issued request complete notes
       
   443             //Do not show notes for device issued request when BTUI is active
       
   444             if ( requestIssuedFromPhone ) 
       
   445                 {
       
   446                 iObserver->NotifyChangeDeviceComplete(aErr, connectedDevice, &nameArray);
       
   447                 }
       
   448                
       
   449             SendRefreshIfNoError(aErr);
       
   450             }
       
   451         nameArray.Reset();
       
   452         }
       
   453     else 
       
   454         {
       
   455         if (aErr == KErrNone)
       
   456             {
       
   457             // we will set the connect status of the device
       
   458             // if it is found in paired devices.
       
   459             if( index >= 0 )
       
   460             	{
       
   461             	SetStatusFlags(iDeviceArray[index]->iStatus,EStatusBtuiConnected );
       
   462             	}
       
   463             }
       
   464         else        
       
   465             {
       
   466             // we will unset the connect status of the device if connection failed &
       
   467             // it is found in paired devices.
       
   468             if( index >= 0 )
       
   469                 {                   
       
   470                 // add EStatusBtuiConnected status if the device has a profile connection
       
   471                 TBTEngConnectionStatus connStatus;
       
   472                 iConnMan->IsConnected(connectedDevice.iAddr, connStatus);
       
   473    
       
   474                 if (connStatus != EBTEngConnecting && connStatus != EBTEngConnected)
       
   475                    {
       
   476                    TRACE_INFO(_L("Unset EStatusBtuiConnected"))
       
   477                    UnsetStatusFlags(iDeviceArray[index]->iStatus,EStatusBtuiConnected );
       
   478                    }                
       
   479                 }
       
   480             }
       
   481 		if(iObserver)
       
   482 			{
       
   483 			//Show only phone issued request complete notes
       
   484 			//Do not show notes for device issued request when BTUI is active
       
   485 			if ( requestIssuedFromPhone ) 
       
   486 			    {
       
   487         	    iObserver->NotifyChangeDeviceComplete(aErr, connectedDevice);
       
   488 			    }
       
   489         	
       
   490         	SendRefreshIfNoError(aErr);
       
   491 			}		
       
   492         }           
       
   493     
       
   494     // Process the next command if the connect was
       
   495     //initiated by this UI.    
       
   496 	if(iQueue.Count()>0 && iQueue[0]->iOperation==EOpConnect && 
       
   497        iQueue[0]->iAddr == aAddr)        
       
   498         {
       
   499         delete iQueue[0];
       
   500         iQueue.Remove(0);		
       
   501         HandleQueue();
       
   502         }
       
   503     else
       
   504         {
       
   505         if( iQueue.Count()==0 ) 
       
   506             {
       
   507             TRACE_INFO((_L("op Q is empty")));
       
   508             }
       
   509         else
       
   510             {
       
   511             TRACE_INFO((_L("unexpected op Q contents, count is %d, op is %d"), iDeviceArray.Count(), iQueue[0]->iOperation));
       
   512             }
       
   513         }
       
   514     TRACE_FUNC_EXIT	
       
   515     }
       
   516     
       
   517 // ---------------------------------------------------------------------
       
   518 // CBTPairedModel::PowerStateChanged
       
   519 // from MBTEngSettingObserver
       
   520 // ----------------------------------------------------------------------
       
   521 //
       
   522 void CBTPairedModel::PowerStateChanged( TBTPowerStateValue )
       
   523 	{
       
   524 	TRACE_FUNC_ENTRY
       
   525 	
       
   526 	// This is implemented for case like when user choses offlne mode, Bluetooth is swithced off
       
   527 	// very fast. Bt audio components don't have enough time to close audio connection.
       
   528 	// BTUI needs to update UI display.
       
   529 	
       
   530 	TInt count = iDeviceArray.Count();  
       
   531     
       
   532     for (TInt i = 0; i < count; i++)
       
   533     	{
       
   534      	UnsetStatusFlags(iDeviceArray[i]->iStatus, EStatusBtuiConnected );
       
   535     	}
       
   536 	
       
   537 	SendRefreshIfNoError(KErrNone);
       
   538 	
       
   539 	TRACE_FUNC_EXIT
       
   540 	}
       
   541     
       
   542 // ----------------------------------------------------
       
   543 // CBTPairedModel::VisibilityModeChanged
       
   544 // from MBTEngSettingObserver
       
   545 // ----------------------------------------------------
       
   546 //    
       
   547 void CBTPairedModel::VisibilityModeChanged( TBTVisibilityMode  )
       
   548     {
       
   549 	TRACE_FUNC_ENTRY
       
   550 	
       
   551 	
       
   552 	TRACE_FUNC_EXIT	
       
   553     }
       
   554         
       
   555 // ---------------------------------------------------------------------
       
   556 // CBTPairedModel::DisconnectComplete
       
   557 // from MBTEngConnObserver
       
   558 // ----------------------------------------------------------------------
       
   559 //
       
   560 void CBTPairedModel::DisconnectComplete(TBTDevAddr& aAddr, TInt aErr)
       
   561     {
       
   562     TRACE_FUNC_ENTRY
       
   563     
       
   564     // the disconnect was part of a unpairing or blocking operation
       
   565 	if(iState == EDisconnectBeforeOperationState && iDisconnectDevice && aAddr == iDisconnectDevice->iAddr )
       
   566 		{
       
   567 
       
   568 		TRAPD(err,
       
   569 			DoChangeDeviceL(*iDisconnectDevice);		
       
   570 		);
       
   571 		iState=EIdleState;		
       
   572 		if(err != KErrNone)
       
   573 			{
       
   574 			HandleLeave(err,iDisconnectDevice);
       
   575 			}
       
   576 		TRACE_FUNC_EXIT
       
   577 		return;
       
   578 		}		    
       
   579     
       
   580     TInt index = GetIndexByAddress(aAddr);
       
   581     
       
   582     // the disconnected device was not the devicein the list,
       
   583     // so we do not tell anyone about it.
       
   584     if ( iDisconnectDevice == NULL || iDisconnectDevice->iAddr != aAddr )
       
   585     	{
       
   586     	if (index >=0 )
       
   587     	{
       
   588     		UnsetStatusFlags(iDeviceArray[index]->iStatus, EStatusBtuiConnected );
       
   589     	}
       
   590     	
       
   591     	SendRefreshIfNoError(KErrNone);
       
   592 
       
   593 		TBTDevice disconnectedDevice;
       
   594 		disconnectedDevice.iAddr = aAddr;
       
   595 		// Notify needed when there is active disconnect query dialog
       
   596     	iObserver->NotifyChangeDeviceComplete(KErrDisconnected, disconnectedDevice);
       
   597 		
       
   598     	TRACE_FUNC_EXIT  
       
   599     	return;
       
   600     	}
       
   601     	
       
   602 	if(index >=0 )
       
   603 		{
       
   604 	    // set it to "not connected" no matter disconnection works or not
       
   605 	    UnsetStatusFlags(iDeviceArray[index]->iStatus, EStatusBtuiConnected );
       
   606 	    iDeviceArray[index]->iOperation = EOpDisconnect;
       
   607 	    iObserver->NotifyChangeDeviceComplete(aErr, *iDeviceArray[index]);		
       
   608 		}
       
   609 	else
       
   610 		{
       
   611 		iDisconnectDevice->iIndex=index;
       
   612 		iObserver->NotifyChangeDeviceComplete(aErr, *iDisconnectDevice);		
       
   613 		}
       
   614 
       
   615 	delete iDisconnectDevice;
       
   616 	iDisconnectDevice=NULL;    	
       
   617 
       
   618    	SendRefreshIfNoError(aErr);
       
   619    	// continue processing queue only if the disconnected device is
       
   620    	// the device with we requested disconnect to.
       
   621    	// this has to be checked so that we do not end on having multiple
       
   622    	// queue processors at the same time
       
   623 	if(iQueue.Count()>0 && iQueue[0]->iOperation==EOpDisconnect && 
       
   624 	  iQueue[0]->iAddr == aAddr)           	
       
   625 		{
       
   626 		delete iQueue[0];
       
   627 		iQueue.Remove(0);		
       
   628 		HandleQueue();
       
   629 		}
       
   630     else
       
   631         {
       
   632         if( iQueue.Count()==0 ) 
       
   633             {
       
   634             TRACE_INFO((_L("op Q is empty")));
       
   635             }
       
   636         else
       
   637             {
       
   638             TRACE_INFO((_L("unexpected op Q contents, count is %d, op is %d"), iDeviceArray.Count(), iQueue[0]->iOperation));
       
   639             }
       
   640         }
       
   641     TRACE_FUNC_EXIT   	
       
   642     }
       
   643     
       
   644 // ---------------------------------------------------------------------
       
   645 // CBTPairedModel::PairingComplete
       
   646 // from MBTEngConnObserver
       
   647 // ----------------------------------------------------------------------
       
   648 //
       
   649 void CBTPairedModel::PairingComplete(TBTDevAddr& aAddr, TInt aErr)
       
   650 	{
       
   651 	TRACE_FUNC_ENTRY
       
   652 	
       
   653 	TRAPD(err,
       
   654 		PairingCompleteL(aAddr,aErr);
       
   655 		);
       
   656 		
       
   657 	if(err!=KErrNone)
       
   658 	{
       
   659 		TBTDevice tmp;
       
   660 		tmp.iAddr=aAddr;					
       
   661 		tmp.iIndex=GetIndexByAddress(aAddr);
       
   662 		tmp.iOperation=EOpPair;
       
   663 		HandleLeave(err,&tmp );
       
   664 
       
   665 		delete iPairingDevice;
       
   666 		iPairingDevice=NULL;				
       
   667 	}
       
   668 	
       
   669 	TRACE_FUNC_EXIT
       
   670 	}
       
   671 	
       
   672 // ---------------------------------------------------------------------
       
   673 // CBTPairedModel::PairingCompleteL
       
   674 // Leaving version of PairingComplete
       
   675 // ----------------------------------------------------------------------
       
   676 //	
       
   677 void CBTPairedModel::PairingCompleteL(TBTDevAddr& aAddr, TInt aErr)
       
   678     {
       
   679     TRACE_FUNC_ENTRY
       
   680     
       
   681 	// The device that was attempted to be paired is 
       
   682 	// different from the the device that the pairing is finnished.
       
   683 	// This cannot happen, since CBTConnMan will report
       
   684 	// only pairing started by the listener and the UI
       
   685 	// does not allow making two pairings at the same time
       
   686     __ASSERT_DEBUG(aAddr==iPairingDevice->BDAddr(),
       
   687       PANIC(EBTPanicCommandComplettedToDiffrentDeviceThanStarted));
       
   688     (void) aAddr;
       
   689 
       
   690     // bail out if the operation queue is not what we expect
       
   691     if( iQueue.Count() == 0 
       
   692         || iQueue[0]->iOperation != EOpPair 
       
   693         || iQueue[0]->iAddr != aAddr )        
       
   694         {
       
   695         if( iQueue.Count()==0 ) 
       
   696             {
       
   697             TRACE_INFO((_L("op Q is empty")));
       
   698             }
       
   699         else
       
   700             {
       
   701             TRACE_INFO((_L("unexpected op Q contents, count is %d, op is %d"), iDeviceArray.Count(), iQueue[0]->iOperation));
       
   702             }
       
   703         TRACE_FUNC_EXIT
       
   704         return;
       
   705         }
       
   706 
       
   707     iState=EIdleState;		
       
   708 	TBTDevice* tmpDevice=NULL;
       
   709 	tmpDevice=CreateDeviceL(iPairingDevice, &( iQueue[0]->iNameEntry ) );
       
   710 	tmpDevice->iOperation=EOpPair;    		
       
   711 	
       
   712     // new paired device must be inserted to the array, since
       
   713     // user may be doing trust/ connect operations before
       
   714     // it is refreshed from registry
       
   715     TBool deleleteTmpDevice=ETrue;
       
   716 	
       
   717 	if( aErr == KErrNone  )    	
       
   718 		{
       
   719 		SetStatusFlags(tmpDevice->iStatus,EStatusPaired);
       
   720 		TInt index;
       
   721 		index=GetIndexByAddress(iPairingDevice->BDAddr());
       
   722 		
       
   723 		if(index == KErrNotFound)
       
   724 			{
       
   725 			iDeviceArray.InsertInOrderL(tmpDevice,*iSortOrder );
       
   726   			  			
       
   727     		RenumberDeviceArray();
       
   728 
       
   729     		// iPairingDevice is now owned by iDeviceArray. 
       
   730     		// So it must not be deleted by his function
       
   731     		deleleteTmpDevice=EFalse;
       
   732     		
       
   733     		SendRefreshIfNoError(aErr,GetIndexByAddress(iPairingDevice->BDAddr()));
       
   734 			}					
       
   735 		}
       
   736 
       
   737 	
       
   738     iObserver->NotifyChangeDeviceComplete(aErr, *tmpDevice);         
       
   739     
       
   740     /*
       
   741      * We issue an background refresh in case 
       
   742      * registry is updated from btnotif
       
   743      */
       
   744 	iRegistryObserver->StartIfNotRunning();
       
   745 	iRegistryObserver->Refresh();
       
   746     // delete if the ownership has not changed
       
   747     if(deleleteTmpDevice )
       
   748         {
       
   749     	delete tmpDevice;
       
   750     	tmpDevice=NULL;
       
   751         }
       
   752 
       
   753 	delete iPairingDevice;    
       
   754     iPairingDevice=NULL;       
       
   755 	delete iQueue[0];
       
   756 	iQueue.Remove(0);
       
   757     
       
   758     HandleQueue();    		    
       
   759 
       
   760     TRACE_FUNC_EXIT    
       
   761     }
       
   762     
       
   763 // ---------------------------------------------------------------------
       
   764 // BTPairedModel::HandleDevManComplete
       
   765 // from MBTEngDevModelBase
       
   766 // ----------------------------------------------------------------------
       
   767 //
       
   768 void  CBTPairedModel::HandleDevManComplete(TInt aErr)
       
   769 	{
       
   770 	TRACE_FUNC_ENTRY
       
   771 	
       
   772 	// if this is handled we can remove this
       
   773 	if(iDisconnectDevice)
       
   774 		{
       
   775 		delete iDisconnectDevice;
       
   776 		iDisconnectDevice=NULL;
       
   777 		}
       
   778 		
       
   779 	if(iPairingDevice)
       
   780 		{
       
   781 		// add the device just deleted	
       
   782 		if(iState==EDeleteDeviceState && (aErr==KErrNone || aErr == KErrNotFound))
       
   783 			{
       
   784 				iPairingDevice->DeleteLinkKey();
       
   785 				TBTDeviceSecurity sec=iPairingDevice->GlobalSecurity();
       
   786 				sec.SetBanned(EFalse);
       
   787 				sec.SetNoAuthorise(EFalse);
       
   788 				iDevMan->AddDevice(*iPairingDevice);
       
   789 				iState=EAddDeviceState;
       
   790 				TRACE_FUNC_EXIT	
       
   791 				return;
       
   792 			}
       
   793 		// if the device is added allready, or if deletion failed
       
   794 		// we will go on with pairing the device
       
   795 		if(iState==EAddDeviceState||(iState==EDeleteDeviceState&& aErr != KErrNone))
       
   796 			{
       
   797 			aErr = iConnMan->PairDevice(iPairingDevice->BDAddr(), iPairingDevice->DeviceClass());
       
   798 			iState=EPairDeviceState;
       
   799 			// NOTE: now PairingComplete will be called and not this method.
       
   800 			TRACE_FUNC_EXIT	
       
   801 			return;
       
   802 			}
       
   803 		}
       
   804 	// these are not handled by superclass		
       
   805 	if(iQueue.Count()>0 &&
       
   806 	    ( iQueue[0]->iOperation==EOpConnect || 
       
   807 	     iQueue[0]->iOperation==EOpDisconnect ) )
       
   808 		{
       
   809 		iObserver->NotifyChangeDeviceComplete(aErr, *iQueue[0]);
       
   810 		}
       
   811 			
       
   812 	CBTDevModelBase::HandleDevManComplete(aErr);
       
   813 	
       
   814     TRACE_FUNC_EXIT	
       
   815 	}
       
   816 	
       
   817 // ---------------------------------------------------------------------
       
   818 // CBTPairedModel::DoPairDevice
       
   819 // ---------------------------------------------------------------------
       
   820 //
       
   821 void  CBTPairedModel::DoPairDeviceL()
       
   822 	{
       
   823 	TRACE_FUNC_ENTRY
       
   824 	
       
   825 	// we are starting a new command. Checks that no earlier commands 
       
   826 	// have been executed, but not finished properly.
       
   827 	__ASSERT_DEBUG(iState==EIdleState,PANIC(EBTPanicDevManQueueIsInIllegalState));
       
   828 	// check that there is no other pairing going on.
       
   829 	__ASSERT_DEBUG(iPairingDevice!=NULL,PANIC(EBTPanicTwoPairingAttemptsAtTheSameTime));
       
   830 	
       
   831 	iRegistryObserver->Cancel();
       
   832 	
       
   833 	// devices to be paired are first deleted
       
   834 	// then added back. Only after that the paring itself is
       
   835 	// started
       
   836 	TBTRegistrySearch dele;
       
   837 	dele.FindAddress(iPairingDevice->BDAddr());
       
   838 	TInt err = iDevMan->DeleteDevices(dele);
       
   839 
       
   840 	iState=EDeleteDeviceState;
       
   841    if (err)
       
   842        {
       
   843        HandleDevManComplete(err);
       
   844        }
       
   845        
       
   846     TRACE_FUNC_EXIT
       
   847 	}
       
   848 	
       
   849 // ---------------------------------------------------------------------
       
   850 // CBTPairedModel::PairDevice
       
   851 //
       
   852 // Puts the given aPairingDevice to iPairingDevice and
       
   853 // adds and empty device with iOperation=EOpPair as placeholder to iQueue.
       
   854 // the pairing itself will be handled by DoChangeDevice that
       
   855 // cals then 
       
   856 // ---------------------------------------------------------------------
       
   857 //
       
   858 TInt CBTPairedModel::PairDeviceL(const CBTDevice* aPairingDevice,
       
   859         TNameEntry* aNameEntry)	
       
   860 	{
       
   861 	TRACE_FUNC_ENTRY
       
   862 	
       
   863 	// cannot put two pairings to queue. 
       
   864 	// this is not possible since ui does not allow it.
       
   865 	if(iPairingDevice)
       
   866 		return KErrInUse;
       
   867 		
       
   868 	TBTDevice*  device=new(ELeave) TBTDevice();
       
   869 	device->iOperation=EOpPair;
       
   870 	device->iAddr=aPairingDevice->BDAddr();
       
   871 	if ( aNameEntry )
       
   872 	    {
       
   873 	    device->iNameEntry = *aNameEntry;
       
   874 	    }
       
   875 	CleanupStack::PushL(device);
       
   876 	iPairingDevice=aPairingDevice->CopyL();
       
   877 	// put the device to queue directly
       
   878 	iQueue.AppendL(device);
       
   879 	TInt err = KErrNone;
       
   880 	if(iQueue.Count() ==1 )
       
   881 		{
       
   882 		err = DoChangeDeviceL(*iQueue[0]);
       
   883 		}
       
   884 	CleanupStack::Pop(device);	
       
   885     TRACE_FUNC_EXIT			
       
   886 	return err;
       
   887 	
       
   888 	}
       
   889 	
       
   890 // ---------------------------------------------------------------------
       
   891 // CBTPairedModel::HandleDisconnectCompleteL
       
   892 // Disconnection by CBluetoothPhysicalLinks, for those
       
   893 // connections not opened by btui. 
       
   894 // ---------------------------------------------------------------------
       
   895 //
       
   896 void CBTPairedModel::HandleDisconnectCompleteL(TInt aErr)
       
   897 	{
       
   898 	 TRACE_FUNC_ENTRY 
       
   899 	 
       
   900 	 if(iDisconnectDevice)
       
   901 	 	{
       
   902 	 	DisconnectComplete(iDisconnectDevice->iAddr,aErr);
       
   903 	 	}
       
   904 	 	
       
   905 	TRACE_FUNC_EXIT
       
   906 	}
       
   907 	
       
   908 // ---------------------------------------------------------------------
       
   909 // CBTPairedModel::FlagPhysicallyConnectedDevices
       
   910 //
       
   911 // Marks the EStatusPhysicallyConnected attribute to the devices
       
   912 // that have active connection.
       
   913 // ---------------------------------------------------------------------
       
   914 //
       
   915 void CBTPairedModel::FlagPhysicallyConnectedDevices(RDeviceArray &aDeviceArray)
       
   916 	{
       
   917 	TRACE_FUNC_ENTRY 
       
   918 	
       
   919 	RBTDevAddrArray a;
       
   920 	iLinks->Enumerate(a,KMaxCheckedConnections);
       
   921 	
       
   922 	TInt i=0; 
       
   923 	
       
   924 	for(i=0;i<aDeviceArray.Count();i++)
       
   925 		{
       
   926         FlagPhysicallyConnectedDevices( *aDeviceArray[i], a );
       
   927 		}
       
   928 	a.Close();	
       
   929 	
       
   930 	TRACE_FUNC_EXIT 	
       
   931 	}
       
   932 	
       
   933 void CBTPairedModel::FlagPhysicallyConnectedDevices(TBTDevice& aDevice, RBTDevAddrArray& aBTDeviceArray)
       
   934 	{
       
   935 	TRACE_FUNC_ENTRY 
       
   936 	
       
   937 	TInt i2=0;
       
   938 	
       
   939     UnsetStatusFlags( aDevice.iStatus, EStatusPhysicallyConnected );		
       
   940     for( i2=0; i2<aBTDeviceArray.Count(); i2++ )
       
   941         {
       
   942         if(aDevice.iAddr == aBTDeviceArray[i2])
       
   943             {
       
   944             SetStatusFlags( aDevice.iStatus,EStatusPhysicallyConnected );		
       
   945             break;				
       
   946             }
       
   947         }
       
   948 	
       
   949 	TRACE_FUNC_EXIT 	
       
   950 	}
       
   951 	
       
   952 // ---------------------------------------------------------------------
       
   953 // CBTPairedModel::GetDevice
       
   954 //
       
   955 // Adds the EPhysicallyConnected attribute devices that have any active
       
   956 // bluetooth connection.
       
   957 // ---------------------------------------------------------------------	
       
   958 //
       
   959 TInt CBTPairedModel::GetDevice(TBTDevice& aDevice)
       
   960 	{	
       
   961 	TRACE_FUNC_ENTRY 	
       
   962 	
       
   963 	TInt rvalue=CBTDevModelBase::GetDevice(aDevice);
       
   964 	RBTDevAddrArray a;
       
   965 	iLinks->Enumerate(a,KMaxCheckedConnections);
       
   966     FlagPhysicallyConnectedDevices(aDevice, a);
       
   967 	a.Close();	
       
   968 	
       
   969 	TRACE_FUNC_EXIT 
       
   970 	
       
   971 	return rvalue;	
       
   972 	}
       
   973 	
       
   974 // ---------------------------------------------------------------------
       
   975 // CBTPairedModel::HandleLeave
       
   976 // from CBTDevModelBase
       
   977 // ---------------------------------------------------------------------
       
   978 //
       
   979 void CBTPairedModel::HandleLeave(TInt aErr,const TBTDevice* aDevice )
       
   980 	{
       
   981 	TRACE_FUNC_ENTRY
       
   982 	
       
   983 	iConnMan->CancelPairDevice();
       
   984 
       
   985 	delete iPairingDevice;
       
   986 	iPairingDevice=NULL;
       
   987 
       
   988 	delete iDisconnectDevice;
       
   989 	iDisconnectDevice=NULL;
       
   990 	
       
   991 	iRegistryObserver->StartIfNotRunning();
       
   992 	iRegistryObserver->Refresh();
       
   993 	
       
   994 	iState=EIdleState;
       
   995 	
       
   996 	CBTDevModelBase::HandleLeave(aErr,aDevice );
       
   997 	
       
   998 	TRACE_FUNC_EXIT
       
   999 	}