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