--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/btui/devmodel/src/btdevmodelbase.cpp Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,807 @@
+/*
+* 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 UI components.
+*
+*/
+
+#include "btdevice.h"
+#include "btdevmodelbase.h"
+#include <btengutil.h>
+#include "debug.h"
+#include "btui.h"
+#include "btregistryobserver.h"
+
+// --------------------------------------------------------------------------------------------
+// 1st phaze constructor
+// --------------------------------------------------------------------------------------------
+CBTDevModelBase::CBTDevModelBase(MBTDeviceObserver* aObserver, TBTDeviceSortOrder* aOrder)
+ : iObserver(aObserver)
+ {
+ TRACE_FUNC_ENTRY
+ iSortOrder=aOrder;
+ TRACE_FUNC_EXIT
+
+ }
+
+// --------------------------------------------------------------------------------------------
+// Destructor
+// --------------------------------------------------------------------------------------------
+CBTDevModelBase::~CBTDevModelBase()
+ {
+ TRACE_FUNC_ENTRY
+ delete iRegistryObserver;
+
+ for(TInt i=0;i<iDeviceArray.Count();i++)
+ delete iDeviceArray[i];
+ iDeviceArray.Close();
+ delete iDevice;
+ iDevice=NULL;
+
+ for(TInt i=0;i<iQueue.Count();i++)
+ delete iQueue[i];
+ iQueue.Close();
+
+ if(iDevMan)
+ iDevMan->Cancel();
+ delete iDevMan;
+
+ delete iSortOrder;
+ TRACE_FUNC_EXIT
+ }
+// --------------------------------------------------------------------------------------------
+// CBTDevModelBase::IsAnyDeviceConnected
+// Allways false, since base class does not support connection
+// --------------------------------------------------------------------------------------------
+
+TBool CBTDevModelBase::IsAnyDeviceConnected()
+ {
+ TRACE_FUNC_ENTRY
+ return EFalse;
+
+ }
+
+// --------------------------------------------------------------------------------------------
+// CBTDevModelBase::GetDevice
+// --------------------------------------------------------------------------------------------
+TInt CBTDevModelBase::GetDevice(TBTDevice& aDevice)
+ {
+ TRACE_FUNC_ENTRY
+ TBTDeviceOp op=aDevice.iOperation;
+
+ TInt index = GetIndexByAddress(aDevice.iAddr,aDevice.iIndex);
+
+ if (index < 0 )
+ {
+ if(aDevice.iAddr == KNullAddress )
+ {
+ return KErrArgument;
+ }
+ else
+ {
+ return KErrNotFound ;
+ }
+ }
+ if(index >= iDeviceArray.Count())
+ return KErrOverflow;
+
+ aDevice=*iDeviceArray[index];
+ aDevice.iOperation=op;
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+// --------------------------------------------------------------------------------------------
+// CBTDevModelBase::ChangeAllDevices
+// --------------------------------------------------------------------------------------------
+void CBTDevModelBase::ChangeAllDevices(const TBTDeviceOp aOperation)
+ {
+ TRACE_FUNC_ENTRY
+ TInt count = iDeviceArray.Count();
+
+ for (TInt i = 0; i < count; i++)
+ {
+ //TBTDevice device;
+ //device=iDeviceArray[i];
+ //device.iIndex = i;
+ //device.iOperation = aOperation;
+ //ChangeDevice(device);
+ iDeviceArray[i]->iIndex = i;
+ iDeviceArray[i]->iOperation = aOperation;
+ ChangeDevice(*iDeviceArray[i]);
+ }
+ TRACE_FUNC_EXIT
+ }
+
+// --------------------------------------------------------------------------------------------
+// CBTDevModelBase::GetIndexByAddress
+//
+// returns the index of the address, if one is not null address.
+// if it is give aNullAdressIndex
+// --------------------------------------------------------------------------------------------
+TInt CBTDevModelBase::GetIndexByAddress(TBTDevAddr aAddr,TInt aNullAdressIndex)
+ {
+ TRACE_FUNC_ENTRY
+
+ if(aAddr == KNullAddress )
+ {
+ TRACE_FUNC_EXIT
+ return aNullAdressIndex;
+ }
+ else
+ {
+ TInt count = iDeviceArray.Count();
+ TInt i;
+ for (i = 0; i < count; i++)
+ {
+ if (iDeviceArray[i]->iAddr == aAddr) break;
+ }
+ if(i == count)
+ {
+ TRACE_FUNC_EXIT
+ return KErrNotFound ;
+ }
+
+ else
+ {
+ TRACE_FUNC_EXIT
+ return i;
+ }
+ }
+ }
+// --------------------------------------------------------------------------------------------
+// CBTDevModelBase::DoChangeDevice
+// --------------------------------------------------------------------------------------------
+TInt CBTDevModelBase::DoChangeDeviceL(const TBTDevice& aDevice)
+ {
+ TRACE_FUNC_ENTRY
+ //check that the command in progress has been started
+ __ASSERT_DEBUG(iDevice==NULL,PANIC(EBTPanicDevManQueueIsCorrupt));
+
+ TInt index = GetIndexByAddress(aDevice.iAddr, aDevice.iIndex );
+
+ if (index == KErrNotFound)
+ {
+ TRACE_INFO(_L("index not found"));
+ TRACE_FUNC_EXIT
+ if (aDevice.iAddr == KNullAddress)
+ {
+ return KErrArgument;
+ }
+ else
+ {
+ return KErrNotFound ;
+ }
+ }
+ if(index >= iDeviceArray.Count())
+ {
+ TRACE_INFO((_L("index is %d, max expected is %d"), index, iDeviceArray.Count()));
+ TRACE_FUNC_EXIT
+ return KErrOverflow;
+ }
+
+
+ TBTDevice* device = iDeviceArray[index];
+ // store pointer to the indexed TBTDevice
+
+ // untrust trusted device to be deleted, and delete it only after that
+ if( (device->iStatus & EStatusTrusted )
+ && aDevice.iOperation== EOpUnpair )
+ {
+ device=new (ELeave) TBTDevice(*iDeviceArray[index]);
+ device->iOperation=EOPInternalUntust;
+ iQueue.Insert(device,0);
+ TInt rvalue=DoChangeDeviceL(*device);
+ TRACE_FUNC_EXIT
+ return rvalue;
+ }
+
+
+ iDevice = new (ELeave) TBTDevice(*device);
+ iDevice->iOperation = aDevice.iOperation;
+
+ CBTDevice* regDevice = CBTDevice::NewL(iDevice->iAddr);
+
+ regDevice->SetPaired( aDevice.iLinkKeyType );
+
+ TBTDeviceSecurity security;
+
+ if(aDevice.iOperation != EOpChangeName)
+ {
+ regDevice->SetDeviceNameL( BTDeviceNameConverter::ToUTF8L( iDevice->iName ) );
+
+ // BTEngDevMan will delete friendly name when modify device if friendly name is not set
+ // So if friendly name has been set before, it need to be set again before modify it for
+ // any other purpuse e.g change security
+ regDevice->SetFriendlyNameL(iDevice->iFriendlyName);
+ }
+
+ switch (aDevice.iOperation)
+ {
+ case EOpUntrust:
+ case EOPInternalUntust:
+ security.SetNoAuthenticate(EFalse);
+ security.SetNoAuthorise(EFalse);
+ regDevice->SetGlobalSecurity(security);
+ UnsetStatusFlags(iDeviceArray[index]->iStatus,EStatusTrusted );
+ break;
+
+ case EOpTrust:
+ security.SetNoAuthenticate(EFalse);
+ security.SetNoAuthorise(ETrue);
+ security.SetBanned(EFalse);
+ regDevice->SetGlobalSecurity(security);
+
+ SetStatusFlags(iDeviceArray[index]->iStatus,EStatusTrusted );
+ break;
+
+ case EOpUnblock:
+ // unblock may be done to a number of devices.
+ // So we want it to happen as quicky as possible
+ iRegistryObserver->Cancel();
+ UnsetStatusFlags( iDevice->iStatus,EStatusBlocked );
+ security.SetBanned(EFalse );
+ regDevice->DeleteLinkKey();
+
+ regDevice->SetGlobalSecurity(security);
+ break;
+
+ case EOpBlock:
+ security.SetBanned(ETrue );
+ security.SetNoAuthenticate(EFalse );
+ security.SetNoAuthorise(EFalse);
+ regDevice->SetGlobalSecurity(security);
+ regDevice->DeleteLinkKey();
+
+ UnsetStatusFlags( iDevice->iStatus,EStatusTrusted );
+ SetStatusFlags( iDevice->iStatus,EStatusBlocked );
+ break;
+
+ case EOpUnpair:
+ // unpair may be done to a number of devices.
+ // So we want it to happen as quicky as possible
+ iRegistryObserver->Cancel();
+ regDevice->DeleteLinkKey();
+
+ UnsetStatusFlags(iDevice->iStatus,EStatusPaired);
+ security.SetNoAuthenticate(EFalse );
+ security.SetNoAuthorise(EFalse );
+ regDevice->SetGlobalSecurity(security);
+ break;
+
+ case EOpChangeName:
+ if (IsNameExisting(aDevice.iName))
+ {
+ delete regDevice;
+ regDevice=NULL;
+ return KErrAlreadyExists;
+ }
+
+ regDevice->SetFriendlyNameL(aDevice.iName);
+ iDevice->iName = aDevice.iName;
+
+ // set iFriendlyName to remember that friendly name has been set
+ iDevice->iFriendlyName = aDevice.iName;
+ break;
+
+ default:
+ delete regDevice;
+ delete iDevice;
+ iDevice=NULL;
+ TRACE_FUNC_EXIT
+ return KErrNotSupported;
+ }
+ iDevMan->ModifyDevice(*regDevice);
+ delete regDevice;
+
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+// --------------------------------------------------------------------------------------------
+// CBTDevModelBase::DoChangeDevice
+// --------------------------------------------------------------------------------------------
+void CBTDevModelBase::DoCancelChangeL(const TBTDevice& /*aDevice*/)
+ {
+ TRACE_FUNC_ENTRY
+ iDevMan->Cancel();
+ TRACE_FUNC_EXIT
+ }
+
+// --------------------------------------------------------------------------------------------
+// CBTDevModelBase::CreateDevice
+// --------------------------------------------------------------------------------------------
+TBTDevice* CBTDevModelBase::CreateDeviceL(const CBTDevice* aRegDevice,
+ TNameEntry* aNameEntry)
+ {
+ TRACE_FUNC_ENTRY
+ TRACE_BDADDR(aRegDevice->BDAddr());
+ TRACE_INFO((_L("CoD %b"), aRegDevice->DeviceClass().DeviceClass()));
+ TBTDevice* device = new (ELeave) TBTDevice();
+ if ( aNameEntry )
+ {
+ device->iNameEntry = *aNameEntry;
+ }
+ switch( aRegDevice->DeviceClass().MajorDeviceClass() )
+ {
+ case EMajorDeviceComputer:
+ device->iType=EDeviceComputer;
+ break;
+ case EMajorDevicePhone:
+ device->iType=EDevicePhone;
+ break;
+ case EMajorDeviceAudioDevice:
+ if ( aRegDevice->DeviceClass().MinorDeviceClass() == EMinorDeviceAVCarAudio ||
+ aRegDevice->DeviceClass().MinorDeviceClass() == EMinorDeviceAVHandsfree)
+ {
+ device->iType=EDeviceCarkit;
+ }
+ else
+ {
+ device->iType=EDeviceAudio;
+ }
+ break;
+
+ case EMajorDevicePeripheral:
+ if ( aRegDevice->DeviceClass().MinorDeviceClass() == EMinorDevicePeripheralKeyboard )
+ {
+ device->iType=EDeviceKeyboard;
+ }
+ else
+ {
+
+ if ( aRegDevice->DeviceClass().MinorDeviceClass() == EMinorDevicePeripheralPointer )
+ {
+ device->iType=EDeviceMice;
+ }
+ else
+ {
+ device->iType=EDeviceDefault;
+ }
+ }
+ break;
+
+ case EMajorDeviceImaging:
+ if ( aRegDevice->DeviceClass().MinorDeviceClass() == EMinorDeviceImagingPrinter )
+ {
+ device->iType=EDevicePrinter;
+ }
+ else
+ {
+ device->iType=EDeviceDefault;
+ }
+ break;
+
+ default:
+ device->iType=EDeviceDefault;
+ break;
+ }
+ device->iAddr = aRegDevice->BDAddr();
+
+ TBTDeviceSecurity security = aRegDevice->GlobalSecurity();
+
+ if(security.Banned() )
+ {
+ SetStatusFlags(device->iStatus,EStatusBlocked);
+ }
+ if( IsUserAwarePaired( aRegDevice->AsNamelessDevice() ) )
+ {
+ SetStatusFlags(device->iStatus,EStatusPaired);
+ device->iLinkKeyType = aRegDevice->LinkKeyType();
+ }
+ if( security.NoAuthorise())
+ SetStatusFlags(device->iStatus,EStatusTrusted);
+ if(aRegDevice->FriendlyName().Length() >0)
+ {
+ device->iName = aRegDevice->FriendlyName();
+
+ // set iFriendlyName to remember that friendly name has been set before in registry
+ device->iFriendlyName = aRegDevice->FriendlyName();
+ }
+ else
+ {
+ CleanupStack::PushL(device);
+ device->iName = BTDeviceNameConverter::ToUnicodeL(aRegDevice->DeviceName());
+ CleanupStack::Pop(device);
+ }
+
+
+ device->iDeviceClass=aRegDevice->DeviceClass();
+ TRACE_FUNC_EXIT
+ return device;
+ }
+// --------------------------------------------------------------------------------------------
+// CBTDevModelBase::AddDeviceL
+// --------------------------------------------------------------------------------------------
+void CBTDevModelBase::AddDeviceL(const CBTDevice* aRegDevice,
+ TNameEntry* aNameEntry, const TBTDeviceOp aOperation)
+ {
+ TRACE_FUNC_ENTRY
+ TBTDevice* device = CreateDeviceL(aRegDevice, aNameEntry);
+ device->iOperation = aOperation;
+ // insert it to the RDeviceArray by order
+ iDeviceArray.InsertInOrderL(device,*iSortOrder);
+ TRACE_FUNC_EXIT
+ }
+// --------------------------------------------------------------------------------------------
+// CBTDevModelBase::CreateDevices
+// --------------------------------------------------------------------------------------------
+void CBTDevModelBase::CreateDevicesL(const CBTDeviceArray* aDeviceArray)
+ {
+ TRACE_FUNC_ENTRY
+ // clear the old contents of the array
+ for(TInt i=0;i<iDeviceArray.Count();i++)
+ delete iDeviceArray[i];
+ iDeviceArray.Reset();
+
+ TInt count = aDeviceArray->Count();
+ for (TInt i = 0; i < count; i++)
+ {
+ // form a TBTDevice for a CBTDevice
+ CBTDevice* regDevice = aDeviceArray->At(i);
+ HandleNewDeviceL(regDevice, NULL);
+ RenumberDeviceArray();
+ }
+ TRACE_FUNC_EXIT
+ }
+// --------------------------------------------------------------------------------------------
+// CBTDevModelBase::IsNameExisting
+// --------------------------------------------------------------------------------------------
+TBool CBTDevModelBase::IsNameExisting(const TDesC& aName)
+ {
+ TRACE_FUNC_ENTRY
+ for (TInt i = 0; i < iDeviceArray.Count(); i++)
+ {
+ if (iDeviceArray[i]->iName.Compare(aName) == 0)
+ {
+ return ETrue;
+ }
+ }
+ TRACE_FUNC_EXIT
+ return EFalse;
+ }
+// --------------------------------------------------------------------------------------------
+// CBTDevModelBase::RegistryChangedL
+// --------------------------------------------------------------------------------------------
+void CBTDevModelBase::RegistryChangedL(const CBTDeviceArray* aDeviceArray)
+ {
+ TRACE_FUNC_ENTRY
+
+ // Store the device seleted before refresh
+ TInt bSelectedDeviceIndex = KErrNotFound;
+ if (iObserver)
+ {
+ bSelectedDeviceIndex=iObserver->CurrentItemIndex();
+ }
+
+ // the selected device before the update
+ TBTDevice currentDevice;
+
+ if (bSelectedDeviceIndex != KErrNotFound && bSelectedDeviceIndex < iDeviceArray.Count() )
+ {
+ currentDevice=*iDeviceArray[bSelectedDeviceIndex];
+ }
+
+ CreateDevicesL(aDeviceArray);
+
+ TInt newIndex=GetIndexByAddress(currentDevice.iAddr,KErrNotFound);
+ if (newIndex==KErrNotFound)
+ {
+ newIndex= bSelectedDeviceIndex;
+ }
+
+ newIndex=Min(newIndex,iDeviceArray.Count() -1 );
+
+ // notify the listener about the new list of devices
+ SendRefreshIfNoError(KErrNone,newIndex);
+ TRACE_FUNC_EXIT
+ }
+// ----------------------------------------------------------
+// CBTDevModelBase::RenumberDeviceArray
+//
+// ReCalculates the indexes of internal array.
+// ----------------------------------------------------------
+void CBTDevModelBase::RenumberDeviceArray()
+ {
+ TRACE_FUNC_ENTRY
+ for(TInt i=0;i<iDeviceArray.Count();i++)
+ {
+ iDeviceArray[i]->iIndex=i;
+ }
+ TRACE_FUNC_EXIT
+ }
+//---------------------------------------------------------------------------------------------
+// from MBTEngDevManObserver for call back on adding, modifying, deleting device completion
+//---------------------------------------------------------------------------------------------
+void CBTDevModelBase::HandleDevManComplete(TInt aErr)
+ {
+ TRACE_FUNC_ENTRY
+ //command has been succesfully completed. If there is no command but something has
+ // completed, something is very wrong.
+ __ASSERT_DEBUG(iDevice != NULL || aErr != KErrNone, PANIC(EBTPanicDevManQueueIsCorrupt));
+ __ASSERT_DEBUG(iQueue.Count()>0, PANIC(EBTPanicDevManQueueIsCorrupt));
+
+ RenumberDeviceArray();
+
+ // EOPInternalUntust is untrst before delete. It is not an operation of its own, so no-one is notified about it.
+ if(iDevice && iDevice->iOperation== EOPInternalUntust)
+ {
+ delete(iDevice);
+ iDevice=NULL;
+ delete iQueue[0];
+ iQueue.Remove(0);
+
+ HandleQueue();
+ TRACE_FUNC_EXIT
+ return;
+ }
+ // in case of just paired device the refresh does
+ // not work adequately quickly, so we have not refresh the
+ // shown devices immediately.
+ //
+ // If we would not do it, there might be a small window, for
+ // answering yes to to question if user wants to trust the
+ // device. This would fail, since the device would not
+ // be in the list.
+ if( aErr == KErrNone && (iDevice->iOperation== EOpTrust || iDevice->iOperation== EOpUntrust ))
+ {
+ TInt index=GetIndexByAddress(iDevice->iAddr);
+ if(index != KErrNotFound)
+ {
+ if(iDevice->iOperation== EOpTrust )
+ {
+ SetStatusFlags(iDeviceArray[index]->iStatus, EStatusTrusted);
+ }
+ else
+ {
+ UnsetStatusFlags(iDeviceArray[index]->iStatus, EStatusTrusted);
+ }
+
+ SendRefreshIfNoError(aErr);
+ }
+
+ }
+ // delete the unpaired and blocked devices from the list
+ if( aErr == KErrNone && iDevice &&
+ (iDevice->iOperation== EOpBlock || iDevice->iOperation== EOpUnpair ) )
+ {
+ TInt index=GetIndexByAddress(iDevice->iAddr);
+ if(index != KErrNotFound )
+ {
+ delete( iDeviceArray[index] );
+ iDeviceArray.Remove(index);
+ }
+ // do not send refresh if this and the next are unpair/unblock operations.
+ // This is meant to hasten the screen refresh, in case of DeleteAll command
+ // is issued.
+ if( iQueue.Count()>1 && iQueue[1]->iOperation==iDevice->iOperation )
+ {
+
+ }
+ else
+ {
+ SendRefreshIfNoError();
+ iRegistryObserver->StartIfNotRunning();
+ //NOTE:It is ok to attempt starting when allready running.
+ }
+
+ }
+ if(iObserver && iDevice)
+ iObserver->NotifyChangeDeviceComplete(aErr, *iDevice);
+
+ delete(iDevice);
+ iDevice=NULL;
+
+ iRegistryObserver->Refresh();
+
+ delete iQueue[0];
+ iQueue.Remove(0);
+
+ HandleQueue();
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------
+// CBTDevModelBase::HandleGetDevicesComplete
+// From MBTEngDevManObserver
+//
+// Devices are received from CBTRegistryObserver, so this is not used.
+// ----------------------------------------------------------------------
+void CBTDevModelBase::HandleGetDevicesComplete(TInt /*aErr*/, CBTDeviceArray* /*aDeviceArray*/)
+ {
+ TRACE_FUNC_ENTRY
+
+ TRACE_FUNC_EXIT
+ }
+
+
+// ---------------------------------------------------------------------
+// CBTDevModelBase::SendRefreshIfNoError
+// ---------------------------------------------------------------------
+void CBTDevModelBase::SendRefreshIfNoError(TInt aErr,TInt selectedItem)
+ {
+ TRACE_FUNC_ENTRY
+
+ //this shouldn't be reached if iObserver is NULL
+ __ASSERT_DEBUG(iObserver, PANIC(EBTPanicNullObserver));
+
+ if (selectedItem == KErrNotSupported )
+ {
+ iObserver->RefreshDeviceList( &iDeviceArray ,
+ Min(iObserver->CurrentItemIndex(),iDeviceArray.Count()-1 ) );
+ }
+ else
+ {
+ if (aErr == KErrNone && iObserver)
+ {
+ iObserver->RefreshDeviceList( &iDeviceArray,
+ Min(selectedItem,iDeviceArray.Count()-1 ) );
+ }
+ }
+
+ TRACE_FUNC_EXIT
+ }
+// ---------------------------------------------------------------------
+// CBTDevModelBase::ChangeDeviceL
+//
+// puts the change device command into Queue
+// ---------------------------------------------------------------------
+void CBTDevModelBase::ChangeDeviceL(const TBTDevice& aDevice)
+ {
+ TRACE_FUNC_ENTRY
+
+ TBTDevice* device=new(ELeave) TBTDevice(aDevice);
+ CleanupStack::PushL(device);
+
+ TInt err = GetDevice(*device);
+ if(err!=KErrNone)
+ {
+ CleanupStack::PopAndDestroy(device);
+ User::Leave(err);
+ }
+
+ if(aDevice.iOperation==EOpChangeName)
+ {
+ device->iName=aDevice.iName;
+ }
+
+ iQueue.Append(device);
+ CleanupStack::Pop(device);
+ if(iQueue.Count() ==1 )
+ {
+ User::LeaveIfError( DoChangeDeviceL(*iQueue[0]) );
+ }
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------
+// CBTDevModelBase::ChangeDevice
+//
+// Calls the ChangeDeviceL and traps leaves and calls error callback,
+// if they occur.
+// ---------------------------------------------------------------------
+void CBTDevModelBase::ChangeDevice(const TBTDevice& aDevice)
+ {
+ TRACE_FUNC_ENTRY
+ TRAPD(err,
+ ChangeDeviceL(aDevice);
+ );
+ if(err!=KErrNone)
+ {
+ HandleLeave(err,&aDevice);
+ }
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------
+// CBTDevModelBase::CancelChange
+//
+// cancels the change from queue, only calls DoCancelChange,
+// if the command is actually in progress.
+// ---------------------------------------------------------------------
+void CBTDevModelBase::CancelChange(const TBTDevice& aDevice)
+ {
+ TRACE_FUNC_ENTRY
+ // retrieve the device based on index, in
+ // case the address is not filled in.
+ TBTDevice device=aDevice;
+ GetDevice(device);
+ device.iOperation=aDevice.iOperation;
+
+ // delete any operations to device from queueu
+ if(iQueue.Count()>0 )
+ {
+ // Before calling DoCancelChangeL check if first operation on the
+ // queue is the one to be cancelled - otherwise crash may occure
+ // as per TSW EMZA-7EUHYE
+ if(iQueue[0]->iAddr== device.iAddr &&
+ iQueue[0]->iOperation== device.iOperation )
+ TRAP_IGNORE(DoCancelChangeL(device));
+
+ for (TInt i = iQueue.Count() - 1; i >= 0; i--)
+ {
+ if(iQueue[i]->iAddr== device.iAddr &&
+ iQueue[i]->iOperation== device.iOperation )
+ {
+ delete iQueue[i];
+ iQueue.Remove(i);
+ }
+ }
+ }
+ // failed cancel is not reported forward.
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------
+// CBTDevModelBase::DeviceChangeInProgress
+// ---------------------------------------------------------------------
+TBool CBTDevModelBase::DeviceChangeInProgress()
+ {
+ TRACE_FUNC_ENTRY
+ TRACE_FUNC_EXIT
+ return iQueue.Count() !=0;
+ }
+
+// ---------------------------------------------------------------------
+// CBTDevModelBase::HandleQueue
+//
+// Starts executing the next devicechange(if any).
+// Currently Executed command must be deleted from iQueue and iDevice
+// (and corresponding places in subclasses), before calling this method.
+// ---------------------------------------------------------------------
+
+void CBTDevModelBase::HandleQueue()
+ {
+ TRACE_FUNC_ENTRY
+
+ RenumberDeviceArray();
+ if(iQueue.Count() >0 )
+ {
+ TRAPD(err2, DoChangeDeviceL(*iQueue[0]); );
+ if (err2 !=KErrNone)
+ {
+ HandleLeave(err2,iQueue[0]);
+ }
+ }
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------
+// CBTDevModelBase::HandleLeave
+// ---------------------------------------------------------------------
+void CBTDevModelBase::HandleLeave(TInt aErr,const TBTDevice* aDevice )
+ {
+ TRACE_FUNC_ENTRY
+ iRegistryObserver->StartIfNotRunning();
+ iRegistryObserver->Refresh();
+ if(aDevice == NULL )
+ {
+ iObserver->NotifyChangeDeviceComplete(aErr,TBTDevice() );
+ }
+ else
+ {
+ iObserver->NotifyChangeDeviceComplete(aErr, *aDevice );
+ }
+ delete iDevice;
+ iDevice=NULL;
+ iDevMan->Cancel();
+
+ if(aDevice != NULL && iQueue.Count() > 0 &&
+ (iQueue[0]->iAddr == aDevice->iAddr ) &&
+ (iQueue[0]->iOperation == aDevice->iOperation ) )
+ {
+ delete iQueue[0];
+ iQueue.Remove(0);
+ }
+
+ HandleQueue();
+ TRACE_FUNC_EXIT
+ }