--- /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
+ }