# HG changeset patch # User Dremov Kirill (Nokia-D-MSW/Tampere) # Date 1268649899 -7200 # Node ID 20fda83a639826ae80086aca5f0eb3113eec04ff # Parent 8a27654f7b62a073679c046522cd22ae6c37351a Revision: 201008 Kit: 201010 diff -r 8a27654f7b62 -r 20fda83a6398 atext/server/group/extsrv.mmp --- a/atext/server/group/extsrv.mmp Fri Mar 12 15:49:00 2010 +0200 +++ b/atext/server/group/extsrv.mmp Mon Mar 15 12:44:59 2010 +0200 @@ -47,7 +47,7 @@ EPOCSTACKSIZE 0x5000 // Hack for plugins using RCmManager; remove this line when RCmManager becomes client-server EPOCHEAPSIZE 0x1000 0x2000000 // Use same as MCE -CAPABILITY CAP_SERVER NetworkControl CommDD +CAPABILITY CAP_SERVER NetworkControl CommDD PowerMgmt VENDORID VID_DEFAULT SOURCEPATH ../src diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btcomm/src/states.cpp --- a/bluetooth/btcomm/src/states.cpp Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btcomm/src/states.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -693,6 +693,7 @@ RNetDatabase& netdb=aContext->iNetDatabase; TSDPAttributeKey key; + Mem::FillZ(&key, sizeof(TSDPAttributeKey)); key.iQueryType = KSDPAttributeQuery; // suck out the first service record handle. iFactory->iExtractedHandleCount = 1; diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btdocs/Designs/backuprestore.mdzip Binary file bluetooth/btdocs/Designs/backuprestore.mdzip has changed diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btextnotifiers/bwins/BTEXTNOTIFIERSU.DEF --- a/bluetooth/btextnotifiers/bwins/BTEXTNOTIFIERSU.DEF Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btextnotifiers/bwins/BTEXTNOTIFIERSU.DEF Mon Mar 15 12:44:59 2010 +0200 @@ -76,3 +76,7 @@ ?StrongPinCodeRequired@TBTPinCodeEntryNotifierParams@@QBEHXZ @ 75 NONAME ; int TBTPinCodeEntryNotifierParams::StrongPinCodeRequired(void) const ?Type@TBTNotifierUpdateParams2@@QBE?AW4TUpdateParamType@1@XZ @ 76 NONAME ; enum TBTNotifierUpdateParams2::TUpdateParamType TBTNotifierUpdateParams2::Type(void) const ?RecommendedPinCodeMinLength@TBTPinCodeEntryNotifierParams@@QBEIXZ @ 77 NONAME ; unsigned int TBTPinCodeEntryNotifierParams::RecommendedPinCodeMinLength(void) const + ??0TBTUserConfirmationParams@@QAE@XZ @ 78 NONAME ; TBTUserConfirmationParams::TBTUserConfirmationParams(void) + ?LocallyInitiated@TBTUserConfirmationParams@@QBEHXZ @ 79 NONAME ; int TBTUserConfirmationParams::LocallyInitiated(void) const + ??0TBTUserConfirmationParams@@QAE@ABVTBTDevAddr@@ABVTDesC16@@H@Z @ 80 NONAME ; TBTUserConfirmationParams::TBTUserConfirmationParams(class TBTDevAddr const &, class TDesC16 const &, int) + diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btextnotifiers/eabi/BTExtNotifiersU.DEF --- a/bluetooth/btextnotifiers/eabi/BTExtNotifiersU.DEF Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btextnotifiers/eabi/BTExtNotifiersU.DEF Mon Mar 15 12:44:59 2010 +0200 @@ -95,3 +95,9 @@ _ZNK29TBTPinCodeEntryNotifierParams16PinCodeMinLengthEv @ 94 NONAME _ZNK29TBTPinCodeEntryNotifierParams21StrongPinCodeRequiredEv @ 95 NONAME _ZNK29TBTPinCodeEntryNotifierParams27RecommendedPinCodeMinLengthEv @ 96 NONAME + _ZN25TBTUserConfirmationParamsC1ERK10TBTDevAddrRK7TDesC16i @ 97 NONAME + _ZN25TBTUserConfirmationParamsC1Ev @ 98 NONAME + _ZN25TBTUserConfirmationParamsC2ERK10TBTDevAddrRK7TDesC16i @ 99 NONAME + _ZN25TBTUserConfirmationParamsC2Ev @ 100 NONAME + _ZNK25TBTUserConfirmationParams16LocallyInitiatedEv @ 101 NONAME + diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btextnotifiers/inc/BTExtNotifiersPartner.h --- a/bluetooth/btextnotifiers/inc/BTExtNotifiersPartner.h Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btextnotifiers/inc/BTExtNotifiersPartner.h Mon Mar 15 12:44:59 2010 +0200 @@ -184,6 +184,20 @@ */ const TUid KBTPasskeyDisplayNotifierUid={0x10285AD4}; +/* +UID of the "User Confirmation" confirmation request RNotifier plugin. + +The notifier will be started with a parameter of type TBTUserConfirmationParamsPckg. + +The notifier will receive updates of type TBTNotifierUpdateParamsPckg2. + +@see TBTNotifierUpdateParamsPckg2 + +@publishedPartner +@released +*/ +const TUid KBTUserConfirmationNotifierUid={0x2002E224}; + /** UID of the "PIN Code Entry" RNotifier plugin. @@ -330,6 +344,33 @@ TUint32 iPadding1; }; +/** +Secure simple pairing "User Confirmation" parameters. +This class packages the parameters passed to a numeric comparison notifier. + +@publishedPartner +@released +*/ +NONSHARABLE_CLASS(TBTUserConfirmationParams) + : public TBTNotifierParams2 + { +public: + IMPORT_C TBTUserConfirmationParams(const TBTDevAddr& aDevAddr, const TDesC& aDeviceName, TBool aLocallyInitiated); + IMPORT_C TBTUserConfirmationParams(); + +public: + IMPORT_C TBool LocallyInitiated() const; + +private: + TBool iLocallyInitiated; + + // This data padding has been added to help prevent future binary compatibility breaks + // Neither iPadding1 nor iPadding2 have been zero'd because they are currently not used + TUint32 iPadding1; + TUint32 iPadding2; + }; + + /** The base update parameter for the Bluetooth pairing notifiers. This class is intended to allow multiple different updates parameters to be @@ -431,6 +472,12 @@ */ typedef TPckgBuf TBTPasskeyDisplayParamsPckg; /** +Typedef'ed pckgbuf to send passkey entry display parameters to the notifier framework. +@publishedPartner +@released +*/ +typedef TPckgBuf TBTUserConfirmationParamsPckg; +/** Typedef'ed pckgbuf to send PIN code entry parameters to the notifier framework. @publishedPartner @released @@ -456,4 +503,4 @@ */ typedef TPckgBuf TBTPasskeyDisplayUpdateParamsPckg; -#endif // BTEXTNOTIFIERSPARTNER_H \ No newline at end of file +#endif // BTEXTNOTIFIERSPARTNER_H diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btextnotifiers/src/BTExtNotifiers.cpp --- a/bluetooth/btextnotifiers/src/BTExtNotifiers.cpp Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btextnotifiers/src/BTExtNotifiers.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -664,6 +664,42 @@ return iLocallyInitiated; } +// +// TBTUserConfirmationParams +// + +/** +@internalTechnology +*/ +EXPORT_C TBTUserConfirmationParams::TBTUserConfirmationParams(const TBTDevAddr& aDevAddr, const TDesC& aDeviceName, TBool aLocallyInitiated) + : TBTNotifierParams2(aDevAddr, aDeviceName) + , iLocallyInitiated(aLocallyInitiated) + { + LOG_FUNC + } + +/** +Default constructor. Required to allow the class to be packaged with the TPckg family of classes. +@internalTechnology +*/ +EXPORT_C TBTUserConfirmationParams::TBTUserConfirmationParams() + : TBTNotifierParams2() + { + LOG_FUNC + } + +/** +Accessor for indicating whether the user confirmation process was initiated by a local request, +or whether it was trigger by the remote device. +@return EFalse if remote side initiated, otherwise it is locally initiated. +*/ +EXPORT_C TBool TBTUserConfirmationParams::LocallyInitiated() const + { + LOG_FUNC + return iLocallyInitiated; + } + + // // TBTPinCodeEntryNotifierParams diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btstack/avctp/avctp.cpp --- a/bluetooth/btstack/avctp/avctp.cpp Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btstack/avctp/avctp.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -398,6 +398,8 @@ config().SetMinMTU(KDefaultMtu); config().SetMaxReceiveUnitSize(KAvctpSecondaryChannelInboundMTU); config().SetMinMRU(KDefaultMtu); + config().ConfigureReliableChannel(TL2CapConfig::EDefaultRetransmission); + config().SetLegacyModesDisallowed(ETrue); __DEBUG_ONLY(TInt err =) sap2->SetOption(KSolBtL2CAP, KL2CAPUpdateChannelConfig, config); __ASSERT_DEBUG(err == KErrNone, Panic(ESetOptionError)); diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btstack/avctp/avctpmuxerstates.cpp --- a/bluetooth/btstack/avctp/avctpmuxerstates.cpp Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btstack/avctp/avctpmuxerstates.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -822,6 +822,8 @@ config().SetMinMTU(KDefaultMtu); config().SetMaxReceiveUnitSize(KAvctpSecondaryChannelInboundMTU); config().SetMinMRU(KDefaultMtu); + config().ConfigureReliableChannel(TL2CapConfig::EDefaultRetransmission); + config().SetLegacyModesDisallowed(ETrue); err = aTransport.iChannelSAPs[KAvctpSecondaryChannel]->SetOption(KSolBtL2CAP, KL2CAPUpdateChannelConfig, config); __ASSERT_DEBUG(err == KErrNone, Panic(ESetOptionError)); diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btstack/common/bt_v2.mmp --- a/bluetooth/btstack/common/bt_v2.mmp Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btstack/common/bt_v2.mmp Mon Mar 15 12:44:59 2010 +0200 @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2006-2010 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" @@ -70,6 +70,7 @@ SOURCE btcommands.cpp SOURCE AclDataQ.cpp SOURCE AclDataQController.cpp +SOURCE bredrcontrollerconfiguration.cpp SOURCE hcifacade.cpp SOURCE hcifacade_commands.cpp diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btstack/linkmgr/Subscribers.cpp --- a/bluetooth/btstack/linkmgr/Subscribers.cpp Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btstack/linkmgr/Subscribers.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -1,4 +1,4 @@ -// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2003-2010 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" @@ -328,4 +328,35 @@ } } +//----------------- +CPageScanParametersSubscriber* CPageScanParametersSubscriber::NewL(CLinkMgrProtocol& aLinkMgrProtocol) + { + CPageScanParametersSubscriber* s = new(ELeave) CPageScanParametersSubscriber(aLinkMgrProtocol); + CleanupStack::PushL(s); + s->ConstructL(KPropertyKeyBluetoothSetPageScanParameters); + CleanupStack::Pop(s); + return s; + } + +CPageScanParametersSubscriber::CPageScanParametersSubscriber(CLinkMgrProtocol& aLinkMgrProtocol) +: CSubscriber(aLinkMgrProtocol) + { + } + +void CPageScanParametersSubscriber::RunL() + { + //Get this value first before we subscribe again + TInt ret = iStatus.Int(); + Subscribe(); + + if(ret==KErrNone) + { + TInt pageScanParameters; + ret = iProperty.Get(pageScanParameters); + if(ret == KErrNone) + { + iParent.SetPageScanParameters(static_cast(pageScanParameters)); + } + } + } diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btstack/linkmgr/Subscribers.h --- a/bluetooth/btstack/linkmgr/Subscribers.h Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btstack/linkmgr/Subscribers.h Mon Mar 15 12:44:59 2010 +0200 @@ -1,4 +1,4 @@ -// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2003-2010 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" @@ -119,4 +119,13 @@ void RunL(); }; +NONSHARABLE_CLASS(CPageScanParametersSubscriber) : public CSubscriber + { +public: + static CPageScanParametersSubscriber* NewL(CLinkMgrProtocol& aLinkMgrProtocol); +private: + CPageScanParametersSubscriber(CLinkMgrProtocol& aLinkMgrProtocol); + void RunL(); + }; + #endif //#ifndef _SUBSCRIBERS_H diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btstack/linkmgr/bredrcontrollerconfiguration.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btstack/linkmgr/bredrcontrollerconfiguration.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -0,0 +1,192 @@ +// Copyright (c) 2010 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: +// + +#include +#include "debug.h" +#include "linkutil.h" +#include "bredrcontrollerconfiguration.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, LOG_COMPONENT_LINKMGR); +#endif + +const TInt KUnitializedParameters = -1; + +const TUint16 KDefaultPageScanInterval = 0x0800; +const TUint16 KDefaultPageScanWindow = 0x0012; +const TUint8 KDefaultPageScanType = 0x00; + +const TUint16 KFastConnectionPageScanInterval = 0x0024; +const TUint16 KFastConnectionPageScanWindow = 0x0012; +const TUint8 KFastConnectionPageScanType = 0x01; + + +CBrEdrControllerConfiguration::CBrEdrControllerConfiguration(MHCICommandQueue& aCommandQueue, + CLinkMgrProtocol& aLinkMgrProtocol) + : iOriginalPageScanInterval(KDefaultPageScanInterval), + iOriginalPageScanWindow(KDefaultPageScanWindow), + iOriginalPageScanType(KDefaultPageScanType), + iPageScanParameters(KUnitializedParameters), + iCommandQueue(aCommandQueue), + iLinkMgrProtocol(aLinkMgrProtocol) + { + LOG_FUNC + } + +CBrEdrControllerConfiguration::~CBrEdrControllerConfiguration() + { + LOG_FUNC + } + +CBrEdrControllerConfiguration* CBrEdrControllerConfiguration::NewL(MHCICommandQueue& aCommandQueue, + CLinkMgrProtocol& aLinkMgrProtocol) + { + LOG_STATIC_FUNC + CBrEdrControllerConfiguration* self + = new (ELeave) CBrEdrControllerConfiguration(aCommandQueue, aLinkMgrProtocol); + return self; + } + +void CBrEdrControllerConfiguration::SetPageScanParametersL(TPageScanParameterSettings aPageScanParameters) + { + LOG_FUNC + if (iPageScanParameters == KUnitializedParameters) + { + // obtain the original Controller parameters + LOG(_L("obtaining the original Controller parameters")); + + CReadPageScanActivityCommand* readPageScanActCmd = CReadPageScanActivityCommand::NewL(); + // ownership of cmd transfered even if MhcqAddCommandL leaves + iCommandQueue.MhcqAddCommandL(readPageScanActCmd, *this); + + CReadPageScanTypeCommand* readPageScanTypeCmd = CReadPageScanTypeCommand::NewL(); + // ownership of cmd transfered even if MhcqAddCommandL leaves + iCommandQueue.MhcqAddCommandL(readPageScanTypeCmd, *this); + + iPageScanParameters = EStandardPageScanParameters; + + // if the original parameters are requested we don't do anything + if (aPageScanParameters == EStandardPageScanParameters) + return; + } + + // store the settings to publish them later + iPageScanParameters = EStandardPageScanParameters; + + TUint16 pageScanInterval = iOriginalPageScanInterval; + TUint16 pageScanWindow = iOriginalPageScanWindow; + TUint8 pageScanType = iOriginalPageScanType; + + if (aPageScanParameters == EFastConnectionPageScanParameters) + { + // store the settings to publish them later + iPageScanParameters = EFastConnectionPageScanParameters; + pageScanInterval = KFastConnectionPageScanInterval; + pageScanWindow = KFastConnectionPageScanWindow; + pageScanType = KFastConnectionPageScanType; + } + + LOG1(_L("Applying page scan parameter settings %d"), iPageScanParameters); + + // apply the requested page scan parameters + CWritePageScanActivityCommand* writePageScanActCmd + = CWritePageScanActivityCommand::NewL(pageScanInterval, pageScanWindow); + // ownership of cmd transfered even if MhcqAddCommandL leaves + iCommandQueue.MhcqAddCommandL(writePageScanActCmd, *this); + + CWritePageScanTypeCommand* writePageScanTypeCmd = CWritePageScanTypeCommand::NewL(pageScanType); + // ownership of cmd transfered even if MhcqAddCommandL leaves + iCommandQueue.MhcqAddCommandL(writePageScanTypeCmd, *this); + } + +void CBrEdrControllerConfiguration::MhcqcCommandEventReceived(const THCIEventBase& aEvent, + const CHCICommandBase* aRelatedCommand) + { + LOG_FUNC + LOG3(_L("Event 0x%02x (errorcode=%d) received for Command 0x%04x"), aEvent.EventCode(), + aEvent.ErrorCode(), aRelatedCommand->Opcode()); + if (aEvent.EventCode() == ECommandCompleteEvent && aEvent.ErrorCode() == KErrNone) + { + switch (aRelatedCommand->Opcode()) + { + case KReadPageScanActivityOpcode: + { + const TReadPageScanActivityCompleteEvent& readPageScanActivityCompleteEvent + = TReadPageScanActivityCompleteEvent::Cast(aEvent); + iOriginalPageScanInterval = readPageScanActivityCompleteEvent.PageScanInterval(); + iOriginalPageScanWindow = readPageScanActivityCompleteEvent.PageScanwindow(); + LOG2(_L("page scan activity parameters received (interval=0x%04x, window=0x%04x)"), + iOriginalPageScanInterval, iOriginalPageScanWindow); + break; + } + case KReadPageScanTypeOpcode: + { + const TReadPageScanTypeCompleteEvent& readPageScanTypeCompleteEvent + = TReadPageScanTypeCompleteEvent::Cast(aEvent); + iOriginalPageScanType = readPageScanTypeCompleteEvent.PageScanType(); + LOG1(_L("page scan type received (=0x%02)"), iOriginalPageScanType); + break; + } + case KWritePageScanActivityOpcode: + // provide an indication that the requested parameters have been enabled + // as there is no way to indicate halfway success (one command sent succefully, another failed) + // page scan activity command status is the criteria for the whole operation + (void) RProperty::Set(KPropertyUidBluetoothCategory, + KPropertyKeyBluetoothGetPageScanParameters, iPageScanParameters); + LOG1(_L("Write Page Scan Activity command confirmed, page scan parameter settings %d applied"), + iPageScanParameters); + break; + case KWritePageScanTypeOpcode: + LOG(_L("Write Page Scan Type command confirmed")); + break; + default: + LOG1(_L("Warning!! Upexpected Command Complete Event Received (command opcode:0x%04x)"), + aRelatedCommand->Opcode()); + __ASSERT_DEBUG(EFalse, Panic(EHCIUnexpectedEvent)); + break; + } + } + } + +void CBrEdrControllerConfiguration::SetPageScanParameters(TPageScanParameterSettings aPageScanParameters) + { + LOG_FUNC + // errors handled by upper level component + // not updated in time the KPropertyKeyBluetoothGetPageScanParameters P&K key indicates an error situation + TRAPD(err, SetPageScanParametersL(aPageScanParameters)); + if (err) + { + LOG1(_L("Warning!! SetPageScanParameters left with error %d"), err); + } + } + +void CBrEdrControllerConfiguration::MhcqcCommandErrored(TInt IF_FLOGGING(aErrorCode), + const CHCICommandBase* IF_FLOGGING(aCommand)) + { + LOG_FUNC + // errors handled by upper level component + // not updated in time the KPropertyKeyBluetoothGetPageScanParameters P&K key indicates an error situation + LOG2(_L("Warning!! Command 0x%04x failed with error %d"), aCommand->Opcode(), aErrorCode); + } + diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btstack/linkmgr/bredrcontrollerconfiguration.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btstack/linkmgr/bredrcontrollerconfiguration.h Mon Mar 15 12:44:59 2010 +0200 @@ -0,0 +1,63 @@ +// Copyright (c) 2010 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: +// + +#ifndef BREDRCONTROLLERCONFIGURATION_H +#define BREDRCONTROLLERCONFIGURATION_H + +#include +#include +#include + +class MHCICommandQueue; +class CLinkMgrProtocol; + +/** + Handles page scan parameters update requests. Maps KPageScanParametersInfo enums to actual page scan parameters + and sends appropriate HCI commands. + Before the first update the original settings are stored. If fetching of them fails the default values + from the Bluetooth specification are used instead of them. +*/ +NONSHARABLE_CLASS(CBrEdrControllerConfiguration) : public CBase, public MHCICommandQueueClient + { +public: + static CBrEdrControllerConfiguration* NewL(MHCICommandQueue& aCommandQueue, CLinkMgrProtocol& aLinkMgrProtocol); + ~CBrEdrControllerConfiguration(); + + // from MHCICommandQueueClient + void MhcqcCommandEventReceived(const THCIEventBase& aEvent, const CHCICommandBase* aRelatedCommand); + void MhcqcCommandErrored(TInt aErrorCode, const CHCICommandBase* aCommand); + + void SetPageScanParameters(TPageScanParameterSettings aPageScanSettings); + +private: + CBrEdrControllerConfiguration(MHCICommandQueue& aCommandQueue, CLinkMgrProtocol& aLinkMgrProtocol); + +private: + void SetPageScanParametersL(TPageScanParameterSettings aPageScanSettings); + +private: +// owned + TUint16 iOriginalPageScanInterval; + TUint16 iOriginalPageScanWindow; + TUint8 iOriginalPageScanType; + + TInt iPageScanParameters; + +// non-owned resources + MHCICommandQueue& iCommandQueue; + CLinkMgrProtocol& iLinkMgrProtocol; + }; + +#endif diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btstack/linkmgr/hcifacade.cpp --- a/bluetooth/btstack/linkmgr/hcifacade.cpp Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btstack/linkmgr/hcifacade.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2006-2010 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" @@ -372,6 +372,7 @@ switch(aStatus) { case EBTOn: + { // Start-up Bluetooth // Avoid from ON to ON __ASSERT_DEBUG (iLastPowerState == EBTOff, Panic(EHCIPowerStateError)); @@ -380,7 +381,10 @@ //recovery the channels iLinkMgrProtocol.LinkMuxer().ChannelsFree(iHCTLState); - TRAPD(err, InitL(iLinkMgrProtocol.LocalDevice())); + TBTLocalDevice settings(iLinkMgrProtocol.LocalDevice()); + iLinkMgrProtocol.DesiredLocalDeviceSettings().Modify(settings); + + TRAPD(err, InitL(settings)); // Hopefully this should just work it won't rename the device though // since that is persisted if (err) @@ -390,14 +394,17 @@ } else { + iLinkMgrProtocol.DesiredLocalDeviceSettings().ResetChangesMask(); // Reset the inquiry manager iLinkMgrProtocol.InquiryMgr().SetHWState(CBTInquiryMgr::EIdle); // Clear debug mode iLinkMgrProtocol.SecMan().ClearDebugMode(); } + } break; case EBTOff: + { // Reset the Command Queue // Avoid from OFF to OFF __ASSERT_DEBUG (iLastPowerState == EBTOn, Panic(EHCIPowerStateError)); @@ -433,10 +440,13 @@ // NB This ensures AFH host channel classification command blocking is // not in place if power comes back on. iAFHTimer->Reset(); + } break; default: + { Panic(EHCIUnknownPowerState); + } break; } diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btstack/linkmgr/linkmgr.cpp --- a/bluetooth/btstack/linkmgr/linkmgr.cpp Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btstack/linkmgr/linkmgr.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -1,4 +1,4 @@ -// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 1999-2010 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" @@ -37,6 +37,7 @@ #include "eirmanager.h" #include "eirpublisherlocalname.h" #include "eirpublishertxpowerlevel.h" +#include "bredrcontrollerconfiguration.h" #include "ProxySAP.h" @@ -110,6 +111,7 @@ iProperty.Delete(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothSetAFHChannelAssessmentMode); iProperty.Delete(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothSetDeviceName); iProperty.Delete(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothSetAcceptPairedOnlyMode); + iProperty.Delete(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothSetPageScanParameters); // Delete standard P&S values (possibly trying to delete already deleted shared set+get values) iProperty.Delete(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothGetLocalDeviceAddress); @@ -122,6 +124,8 @@ iProperty.Delete(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothGetAcceptPairedOnlyMode); iProperty.Delete(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothHostResolverActive); iProperty.Delete(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothSetSimplePairingDebugMode); + iProperty.Delete(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothGetPageScanParameters); + delete iPhysicalLinksMgr; delete iInquiryMgr; @@ -190,7 +194,6 @@ // iLocalDeviceSettings.SetDeviceClass(iLocalDeviceSettings.DeviceClass() & KDeviceClassBitMask); - //NB - no (ELeave) here - in OOM we'd rather continue and not update the registry //than Leave. All calls to methods are guarded by "if (iRegistryUpdater)" iRegistryUpdater = new CRegistryUpdater(iLocalDevice, iLocalDeviceSettings); @@ -283,6 +286,11 @@ CleanupStack::Pop(subscriber); } + subscriber = CPageScanParametersSubscriber::NewL(*this); + CleanupStack::PushL(subscriber); + User::LeaveIfError(iSubscribers.Append(subscriber)); + CleanupStack::Pop(subscriber); + // set CoD - leave if goes wrong, user's device will be "unknown" otherwise // NB - In future we should tie this to the SDP Server...(or someother higher API...) @@ -306,6 +314,9 @@ //is, as a consequence, 'Set' appropriately (when the associated controller //event arrives). DoSetLimitedDiscoverableL(iLocalDeviceSettings.LimitedDiscoverable()); + + LOG(_L("LinkMgr : Initialising BR/EDR Controller Configuration")); + iBrEdrControllerConfiguration = CBrEdrControllerConfiguration::NewL(iHCIFacade->CommandQController(), *this); LOG(_L("LinkMgr : Initialising complete")); } @@ -382,6 +393,17 @@ KCOMMDD )); + (void)(iProperty.Define(KPropertyUidBluetoothCategory, + KPropertyKeyBluetoothSetPageScanParameters, + RProperty::EInt, + KLOCAL_SERVICES_AND_NETWORK_CONTROL, + KLOCAL_SERVICES_AND_NETWORK_CONTROL + )); + + (void) RProperty::Set(KPropertyUidBluetoothCategory, + KPropertyKeyBluetoothSetPageScanParameters, + EStandardPageScanParameters); + // Original Get P&S value definitions. @@ -454,6 +476,17 @@ KLOCAL_SERVICES, KLOCAL_SERVICES_AND_NETWORK_CONTROL )); + + (void)(iProperty.Define(KPropertyUidBluetoothCategory, + KPropertyKeyBluetoothGetPageScanParameters, + RProperty::EInt, + KLOCAL_SERVICES_AND_NETWORK_CONTROL, + KLOCAL_SERVICES_AND_NETWORK_CONTROL + )); + + (void) RProperty::Set(KPropertyUidBluetoothCategory, + KPropertyKeyBluetoothGetPageScanParameters, + EStandardPageScanParameters); } void CLinkMgrProtocol::DeletePublications() @@ -948,8 +981,19 @@ // Only write the CoD bits if they have changed from the existing setting if (iPendingLocalDeviceSettings.DeviceClass() != aCoD) { - iPendingLocalDeviceSettings.SetDeviceClass(aCoD); - iHCIFacade->WriteDeviceClassL(aCoD); + TRAPD(err, iHCIFacade->WriteDeviceClassL(aCoD)); + if (err == KErrNone) + { + iPendingLocalDeviceSettings.SetDeviceClass(aCoD); + } + else + { + /* If the function errors, it is probably becuase the power is off, so we'll save the setting for power on + If the error is for a different reason, setting this doesn't do any harm anyway - it will get picked + up the next time the power is turned on */ + iDesiredLocalDeviceSettings.SetDeviceClass(aCoD); + User::Leave(err); + } } } @@ -963,6 +1007,13 @@ { iPendingLocalDeviceSettings.SetDeviceName(aName); } + else + { + /* If the function leaves, it is probably becuase the power is off, so we'll save the setting for power on + If the leave is for a different reason, setting this doesn't do any harm anyway - it will get picked + up the next time the power is turned on */ + iDesiredLocalDeviceSettings.SetDeviceName(aName); + } return err; } @@ -975,8 +1026,19 @@ void CLinkMgrProtocol::SetAFHChannelAssessmentModeL(TBool aMode) { LOG_FUNC - iPendingLocalDeviceSettings.SetAFHChannelAssessmentMode(aMode); - iHCIFacade->WriteAFHChannelAssessmentModeL(aMode); + TRAPD(err, iHCIFacade->WriteAFHChannelAssessmentModeL(aMode)); + if (err == KErrNone) + { + iPendingLocalDeviceSettings.SetAFHChannelAssessmentMode(aMode); + } + else + { + /* If the function leaves, it is probably becuase the power is off, so we'll save the setting for power on + If the leave is for a different reason, setting this doesn't do any harm anyway - it will get picked + up the next time the power is turned on */ + iDesiredLocalDeviceSettings.SetAFHChannelAssessmentMode(aMode); + User::Leave(err); + } } void CLinkMgrProtocol::SetLimitedDiscoverableIfChangedL(TBool aOn) @@ -1004,9 +1066,20 @@ if (aOn) { // turn on LIAC - iPendingLocalDeviceSettings.SetLimitedDiscoverable(ETrue); - WriteClassOfDeviceL(iPendingLocalDeviceSettings.DeviceClass() | (EMajorServiceLimitedDiscoverableMode << - (KLengthOfDeviceClass+KStartingOffsetOfDeviceClass))); + TRAPD(err, WriteClassOfDeviceL(iPendingLocalDeviceSettings.DeviceClass() | (EMajorServiceLimitedDiscoverableMode << + (KLengthOfDeviceClass+KStartingOffsetOfDeviceClass)))); + if (err == KErrNone) + { + iPendingLocalDeviceSettings.SetLimitedDiscoverable(ETrue); + } + else + { + /* If the function leaves, it is probably becuase the power is off, so we'll save the setting for power on + If the leave is for a different reason, setting this doesn't do any harm anyway - it will get picked + up the next time the power is turned on */ + iDesiredLocalDeviceSettings.SetLimitedDiscoverable(ETrue); + User::Leave(err); + } numIACs = 2; iacs[0] = KLIAC; iacs[1] = KGIAC; @@ -1014,9 +1087,20 @@ else { // turn off LIAC - could do the 1 minute GAP timer? - iPendingLocalDeviceSettings.SetLimitedDiscoverable(EFalse); - WriteClassOfDeviceL(iPendingLocalDeviceSettings.DeviceClass() & ~(EMajorServiceLimitedDiscoverableMode << - (KLengthOfDeviceClass+KStartingOffsetOfDeviceClass))); + TRAPD(err, WriteClassOfDeviceL(iPendingLocalDeviceSettings.DeviceClass() & ~(EMajorServiceLimitedDiscoverableMode << + (KLengthOfDeviceClass+KStartingOffsetOfDeviceClass)))); + if (err == KErrNone) + { + iPendingLocalDeviceSettings.SetLimitedDiscoverable(EFalse); + } + else + { + /* If the function leaves, it is probably becuase the power is off, so we'll save the setting for power on + If the leave is for a different reason, setting this doesn't do any harm anyway - it will get picked + up the next time the power is turned on */ + iDesiredLocalDeviceSettings.SetLimitedDiscoverable(EFalse); + User::Leave(err); + } numIACs = 1; iacs[0] = KGIAC; } @@ -1223,6 +1307,10 @@ LOG_FUNC iLocalDeviceAddress = aAddr; + // Also update registry with local device address + iLocalDeviceSettings.SetAddress(iLocalDeviceAddress); + UpdateSettings(); + // publish this number - might be useful const TDesC8& des = aAddr.Des(); (void)iProperty.Set(KPropertyUidBluetoothCategory, @@ -1320,6 +1408,11 @@ iPendingLocalDeviceSettings.SetDeviceClass(KDeviceClassReset); } +void CLinkMgrProtocol::SetPageScanParameters(TPageScanParameterSettings aPageScanParameters) + { + LOG_FUNC + iBrEdrControllerConfiguration->SetPageScanParameters(aPageScanParameters); + } // @@ -1383,7 +1476,6 @@ } - //class CRegistryUpdater CRegistryUpdater::~CRegistryUpdater() { @@ -1449,57 +1541,81 @@ void TBTTrackedLocalDevice::SetAddress(const TBTDevAddr& aAddr) { LOG_FUNC - TBTLocalDevice::SetAddress(aAddr); - StoreChange(EAddress); + if (aAddr != Address()) + { + TBTLocalDevice::SetAddress(aAddr); + StoreChange(EAddress); + } } void TBTTrackedLocalDevice::SetDeviceClass(TUint32 aCod) { LOG_FUNC - TBTLocalDevice::SetDeviceClass(aCod); - StoreChange(ECoD); + if (aCod != DeviceClass()) + { + TBTLocalDevice::SetDeviceClass(aCod); + StoreChange(ECoD); + } } void TBTTrackedLocalDevice::SetDeviceName(const TDesC8& aName) { LOG_FUNC - TBTLocalDevice::SetDeviceName(aName); - StoreChange(EDeviceName); + if (aName != DeviceName()) + { + TBTLocalDevice::SetDeviceName(aName); + StoreChange(EDeviceName); + } } void TBTTrackedLocalDevice::SetScanEnable(THCIScanEnable aEnable) { LOG_FUNC - TBTLocalDevice::SetScanEnable(aEnable); - StoreChange(EScanEnable); + if (aEnable != ScanEnable()) + { + TBTLocalDevice::SetScanEnable(aEnable); + StoreChange(EScanEnable); + } } void TBTTrackedLocalDevice::SetLimitedDiscoverable(TBool aOn) { LOG_FUNC - TBTLocalDevice::SetLimitedDiscoverable(aOn); - StoreChange(ELimitedDiscoverable); + if (aOn != LimitedDiscoverable()) + { + TBTLocalDevice::SetLimitedDiscoverable(aOn); + StoreChange(ELimitedDiscoverable); + } } void TBTTrackedLocalDevice::SetPowerSetting(TUint8 aPowerSetting) { LOG_FUNC - TBTLocalDevice::SetPowerSetting(aPowerSetting); - StoreChange(EPowerSetting); + if (aPowerSetting != PowerSetting()) + { + TBTLocalDevice::SetPowerSetting(aPowerSetting); + StoreChange(EPowerSetting); + } } void TBTTrackedLocalDevice::SetAFHChannelAssessmentMode(TBool aOn) { LOG_FUNC - TBTLocalDevice::SetAFHChannelAssessmentMode(aOn); - StoreChange(EAFHChannelAssessmentMode); + if (aOn != AFHChannelAssessmentMode()) + { + TBTLocalDevice::SetAFHChannelAssessmentMode(aOn); + StoreChange(EAFHChannelAssessmentMode); + } } void TBTTrackedLocalDevice::SetAcceptPairedOnlyMode(TBool aOn) { LOG_FUNC - TBTLocalDevice::SetAcceptPairedOnlyMode(aOn); - StoreChange(EAcceptPairedOnlyMode); + if (aOn != AcceptPairedOnlyMode()) + { + TBTLocalDevice::SetAcceptPairedOnlyMode(aOn); + StoreChange(EAcceptPairedOnlyMode); + } } void TBTTrackedLocalDevice::StoreChange(TUint8 aChange) diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btstack/linkmgr/linkmgr.h --- a/bluetooth/btstack/linkmgr/linkmgr.h Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btstack/linkmgr/linkmgr.h Mon Mar 15 12:44:59 2010 +0200 @@ -1,4 +1,4 @@ -// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 1999-2010 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" @@ -52,6 +52,7 @@ class CEirManServer; class CEirPublisherTxPowerLevel; class CEirPublisherLocalName; +class CBrEdrControllerConfiguration; NONSHARABLE_CLASS(CRegistrySession) : public CBase @@ -165,6 +166,7 @@ // later - change local device management/notification to be nicer... inline const TBTLocalDevice& LocalDevice() const; + inline TBTTrackedLocalDevice& DesiredLocalDeviceSettings(); void UpdateLocalDeviceName(const TDesC8& aName); void UpdateLocalDeviceName(TBool aSucceeded); void UpdateLocalDevicePower(TBTPowerState aState); @@ -187,6 +189,7 @@ void SetUIConnecting(TBool aConnecting); void SetUINumPhysicalLinks(TUint aNum); void SetUINumSynchronousLinks(TUint aNum); + void SetPageScanParameters(TPageScanParameterSettings aPageScanParameters); inline CHCIFacade& HCIFacade() const; inline CBTInquiryMgr& InquiryMgr() const; @@ -245,6 +248,7 @@ RBTLocalDevice iLocalDevice; //subsession TBTTrackedLocalDevice iLocalDeviceSettings; TBTLocalDevice iPendingLocalDeviceSettings; + TBTTrackedLocalDevice iDesiredLocalDeviceSettings; RProperty iProperty; @@ -252,6 +256,8 @@ CHCIFacade* iHCIFacade; CLinkMuxer* iLinkMuxer; CEirManServer* iEirManServer; + + CBrEdrControllerConfiguration* iBrEdrControllerConfiguration; CACLLinkStateFactory* iACLStateFactory; CSyncLinkStateFactory* iSCOStateFactory; @@ -311,6 +317,12 @@ return iLocalDeviceSettings; } +inline TBTTrackedLocalDevice& CLinkMgrProtocol::DesiredLocalDeviceSettings() + { + return iDesiredLocalDeviceSettings; + } + + inline CBTInquiryMgr& CLinkMgrProtocol::InquiryMgr() const { return *iInquiryMgr; diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btstack/linkmgr/physicallinks.cpp --- a/bluetooth/btstack/linkmgr/physicallinks.cpp Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btstack/linkmgr/physicallinks.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -509,6 +509,10 @@ iDevice.SetPassKey(iNewPinCode); } + if (iLinksMan.SecMan().IsDedicatedBondingAttempted(iDevice.Address())) + { + iLinkKeyObtainedThroughDedicatedBonding = ETrue; + } SetLinkKey(aLinkKey, linkKeyType); // keeps a copy in our 'cache', updates paired list in PHYs mananger @@ -572,7 +576,10 @@ } if(iDevice.IsValidLinkKey() && !iPreventLinkKeyUpdateReg) { - if(!(iIOCapsReceived && (iAuthenticationRequirement == EMitmNotReqNoBonding || iAuthenticationRequirement == EMitmReqNoBonding))) + // We store the link key if it was obtained through dedicated bonding, even if the remote device indicated "no bonding" + // This fixes issues with a lot of remote stacks, and we'll let the UI delete the link key if they want to. + if(iLinkKeyObtainedThroughDedicatedBonding || + !(iIOCapsReceived && (iAuthenticationRequirement == EMitmNotReqNoBonding || iAuthenticationRequirement == EMitmReqNoBonding))) { LOG(_L("!!! Storing Link Key in Registry")); device.SetLinkKey(iDevice.LinkKey(), iDevice.LinkKeyType()); @@ -859,6 +866,7 @@ TRAP(err, iLinksMan.HCIFacade().AuthenticateL(Handle())); if(err == KErrNone) { + iLinkKeyReturnedInThisAuthentication = EFalse; SetAuthenticationPending(EAuthenticationRequestPending); } } @@ -2941,6 +2949,12 @@ || iLinksMan.SecMan().IsDedicatedBondingAttempted(iDevice.Address()); } +TBool CPhysicalLink::IsPairingExpected() const + { + LOG_FUNC + return !(IsAuthenticationPending() && iLinkKeyReturnedInThisAuthentication); + } + void CPhysicalLink::DeleteLinkKeyL() /** ensure that the LinkKey is removed from the device in the registry @@ -3648,6 +3662,40 @@ iPasskeyEntry->KeyPressed(aKey); } +void CPhysicalLink::NewUserConfirmerL(const TBTDevAddr aAddr, + CBTSecMan& aSecMan, + TBool aInternallyInitiated) + { + LOG_FUNC + __ASSERT_DEBUG(aAddr == BDAddr(), Panic(EBTConnectionBadDeviceAddress)); + iUserConfirmer = CBTUserConfirmer::NewL(aAddr, aSecMan, aInternallyInitiated); + } + +CBTUserConfirmer* CPhysicalLink::InstanceUserConfirmer() const + { + LOG_FUNC + return iUserConfirmer; + } + +TBool CPhysicalLink::IsUserConfirmerActive()const + { + LOG_FUNC + return iUserConfirmer->IsActive(); + } + +void CPhysicalLink::DeleteUserConfirmer() + { + LOG_FUNC + delete iUserConfirmer; + iUserConfirmer = NULL; + } + +void CPhysicalLink::CancelUserConfirmer() + { + LOG_FUNC + iUserConfirmer->Cancel(); + } + TBasebandTime CPhysicalLink::GetSniffInterval() const { @@ -3740,6 +3788,10 @@ { LOG(_L("CPhysicalLink: Providing link key to HC...")) ASSERT_DEBUG(iDevice.IsValidLinkKey()); + if (IsAuthenticationPending()) + { + iLinkKeyReturnedInThisAuthentication = ETrue; + } iAuthenticationCtrl.LinkKeyRequestReply(iDevice.Address(), iDevice.LinkKey()); } else diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btstack/linkmgr/physicallinks.h --- a/bluetooth/btstack/linkmgr/physicallinks.h Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btstack/linkmgr/physicallinks.h Mon Mar 15 12:44:59 2010 +0200 @@ -444,10 +444,21 @@ void DeletePasskeyEntry(); void CancelPasskeyEntry(); void PasskeyEntryKeyPressed(THCIPasskeyEntryNotificationType aKey); + + void NewUserConfirmerL(const TBTDevAddr aAddr,CBTSecMan& aSecMan,TBool aInternallyInitiated); + + CBTUserConfirmer* InstanceUserConfirmer() const; + TBool IsUserConfirmerActive()const; + void DeleteUserConfirmer(); + void CancelUserConfirmer(); + + TBasebandTime GetSniffInterval() const; TBool IsPairable() const; + TBool IsPairingExpected() const; + private: CPhysicalLink(CPhysicalLinksManager& aParent, CRegistrySession& aRegSess, const TBTNamelessDevice& aDevice); void ConstructL(); @@ -486,7 +497,7 @@ void PINCodeRequestNegativeReply(const TBTDevAddr& aDevAddr); inline TBool IsAuthenticationPending() const; - + void LinkKeyRequestResponseAttempt(TBool aForceResponse = EFalse); void DoLinkKeyResponse(TBool aPositive); @@ -519,6 +530,7 @@ CBTPinRequester* iPinRequester; // looks after PIN entry UI/state CBTNumericComparator* iNumericComparator; // looks after the numeric comparison UI/state CBTPasskeyEntry* iPasskeyEntry; // looks after the passkey entry UI/state + CBTUserConfirmer* iUserConfirmer; // looks after the user confirmation UI/state CEncryptionEnforcer* iEncryptionEnforcer; @@ -579,6 +591,8 @@ TBool iNewPinCodeValid; TBTPinCode iNewPinCode; + TBool iLinkKeyReturnedInThisAuthentication; + TBool iLinkKeyObtainedThroughDedicatedBonding; private: /** Enumeration to represent the current state of the physical links storage in the registry, diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btstack/secman/btaccessrequester.cpp --- a/bluetooth/btstack/secman/btaccessrequester.cpp Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btstack/secman/btaccessrequester.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -79,7 +79,7 @@ , iPrefetchQueueLink(this) , iAuthenticationInProgress(EFalse) , iAccessType(aAccessType) - , iDedicatedBondingNotAvailable(EFalse) + , iRemoteIndicatedNoBonding(EFalse) , iCurrentState(EBTUninitialised) { LOG_FUNC @@ -508,7 +508,7 @@ THCIAuthenticationRequirement authReq = event->AuthenticationRequirements(); if (iAccessType == EDedicatedBonding && (authReq == EMitmReqNoBonding || authReq == EMitmNotReqNoBonding)) { - iDedicatedBondingNotAvailable = ETrue; + iRemoteIndicatedNoBonding = ETrue; } } @@ -592,15 +592,6 @@ TBTSecEventUserConfirmationRequest* event = TBTSecEventUserConfirmationRequest::Cast(&aEvent); __ASSERT_ALWAYS(event, User::Panic(KBTSecPanic, EBTSecBadStateMachineEvent)); - // Ignore the user confirmation request, we're unable to bond - // (dedicated bonding not available at both ends of the link) - // A negative reply is also sent in secman.cpp - if (UnableToBond()) - { - CompleteRequest(KErrRemoteDeviceIndicatedNoBonding); - return; - } - // start guard timer... iTimer->Start(); } @@ -705,6 +696,12 @@ else if(aResult == EBTSecManAccessGranted) { LOG(_L8("\tACCESS GRANTED")); + if (RemoteIndicatedNoBondingToDedicatedBonding()) + { + // We allow the device to bond, but tell theUI layer so it can delete the link key if it wants to + aResult = KErrRemoteDeviceIndicatedNoBonding; + LOG(_L8("\t... but remote indicated no bonding")); + } } else { @@ -1004,10 +1001,10 @@ return encryptionRequired; } -TBool CBTAccessRequester::UnableToBond() const +TBool CBTAccessRequester::RemoteIndicatedNoBondingToDedicatedBonding() const { LOG_FUNC - return (iAccessType == EDedicatedBonding && iDedicatedBondingNotAvailable); + return (iAccessType == EDedicatedBonding && iRemoteIndicatedNoBonding); } TAccessType CBTAccessRequester::AccessType() const diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btstack/secman/secman.cpp --- a/bluetooth/btstack/secman/secman.cpp Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btstack/secman/secman.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -555,6 +555,7 @@ CPhysicalLink* link = iPhysicalLinksManager->FindPhysicalLink(aAddr); __ASSERT_ALWAYS(link, PANIC(KBTSecPanic, EBTSecPhysicalLinkMissing)); __ASSERT_DEBUG(!link->InstanceNumericComparator(), PANIC(KBTSecPanic, EBTSecConnectionNumericComparisonTwice)); + __ASSERT_DEBUG(!link->InstanceUserConfirmer(), PANIC(KBTSecPanic, EBTSecConnectionUserConfirmationTwice)); if(link->InstanceNumericComparator()) { return; @@ -581,6 +582,22 @@ } } } + else if (!link->IsPairingExpected()) + { + TRAPD(err,link->NewUserConfirmerL(aAddr, *this, ETrue)); + if(err) + { + if(requester) + { + requester->CompleteRequest(EBTSecManAccessDenied); + } + else + { + TRAP_IGNORE(iCommandController->UserConfirmationRequestNegativeReplyL(aAddr)); + return;// No passkey or comparison dialogs; disconnect instead + } + } + } else { // Just Work... @@ -596,7 +613,7 @@ } } -void CBTSecMan::UserConfirmationComplete(const TBTDevAddr& aAddr, TBool aResult, TInt aError) +void CBTSecMan::NumericComparisonComplete(const TBTDevAddr& aAddr, TBool aResult, TInt aError) { LOG_FUNC CBTAccessRequester* requester = FindActiveAccessRequester(aAddr); @@ -642,6 +659,63 @@ link->DeleteNumericComparator(); } +void CBTSecMan::UserConfirmationComplete(const TBTDevAddr& aAddr, TBool aResult, TInt aError) + { + LOG_FUNC + CBTAccessRequester* requester = FindActiveAccessRequester(aAddr); + if (requester) + { + LOG(_L8("\tCBTAccessRequester FOUND!\n")); + if (aError == KErrNone) + { + TBTSecEventUserConfirmationComplete event(aResult); + requester->SendEvent(event); + } + else if (aError == KErrNotFound) // KErrNotFound -> Notifier isn't present, so allow anyway + { + TBTSecEventUserConfirmationComplete event(ETrue); + requester->SendEvent(event); + } + else + { + TBTSecEventUserConfirmationComplete event(EFalse); // Failed, so send EFalse + requester->SendEvent(event); + } + } + + CPhysicalLink* link = iPhysicalLinksManager->FindPhysicalLink(aAddr); + __ASSERT_ALWAYS(link, PANIC(KBTSecPanic, EBTSecPhysicalLinkMissing)); + + if (aError==KErrNotFound) // KErrNotFound -> Notifier isn't present, so allow anyway + { + link->PinRequestSent(); + // note: -- check errors here + TRAP_IGNORE(iCommandController->UserConfirmationRequestReplyL(aAddr)); + } + else if (aError!=KErrNone) + { + // there was an error somewhere a long the way so respond negatively + // note: -- check errors here + TRAP_IGNORE(iCommandController->UserConfirmationRequestNegativeReplyL(aAddr)); + } + else + { + // got a result + if(aResult) + { + link->PinRequestSent(); + // note: -- check errors here + TRAP_IGNORE(iCommandController->UserConfirmationRequestReplyL(aAddr)); + } + else + { + // note: -- check errors here + TRAP_IGNORE(iCommandController->UserConfirmationRequestNegativeReplyL(aAddr)); + } + } + link->DeleteUserConfirmer(); + } + void CBTSecMan::PasskeyNotification(const TBTDevAddr& aAddr, TUint32 aPasskey) { LOG_FUNC @@ -806,9 +880,13 @@ if (link->InstanceNumericComparator() && link->IsNumericComparatorActive()) { link->CancelNumericComparator(); + NumericComparisonComplete(aAddr, EFalse, err); + } + if (link->InstanceUserConfirmer() && link->IsUserConfirmerActive()) + { + link->CancelUserConfirmer(); UserConfirmationComplete(aAddr, EFalse, err); } - iPhysicalLinksManager->SimplePairingComplete(aAddr, aError); // Add result to list (always with HCI error code). @@ -1753,7 +1831,7 @@ __ASSERT_DEBUG(iNumericComparisonParamsPckg().DeviceAddress() == iDevAddr, PANIC(KBTSecPanic, EBTSecBadDeviceAddress)); - iSecMan.UserConfirmationComplete(iDevAddr, iResultPckg(), iStatus.Int()); + iSecMan.NumericComparisonComplete(iDevAddr, iResultPckg(), iStatus.Int()); } TInt CBTNumericComparator::RunError(TInt aError) @@ -1917,3 +1995,133 @@ return aError; } +//------------------------------------------------------------------------// +//class CBTNumericComparator +//------------------------------------------------------------------------// +CBTUserConfirmer* CBTUserConfirmer::NewL(const TBTDevAddr aAddr, + CBTSecMan& aSecMan, + TBool aInternallyInitiated) + { + LOG_STATIC_FUNC + CBTUserConfirmer* s = CBTUserConfirmer::NewLC(aAddr, aSecMan, aInternallyInitiated); + CleanupStack::Pop(s); + return s; + } + +CBTUserConfirmer* CBTUserConfirmer::NewLC(const TBTDevAddr aAddr, + CBTSecMan& aSecMan, + TBool aInternallyInitiated) + { + LOG_STATIC_FUNC + CBTUserConfirmer* s = new(ELeave) CBTUserConfirmer(aSecMan, aInternallyInitiated); + CleanupStack::PushL(s); + s->ConstructL(aAddr); + return s; + } + +CBTUserConfirmer::CBTUserConfirmer(CBTSecMan& aSecMan, TBool aInternallyInitiated) + : CSecNotifierRequester(aSecMan) + , iSecMan(aSecMan) + , iInternallyInitiated(aInternallyInitiated) + { + LOG_FUNC + CActiveScheduler::Add(this); + } + +CBTUserConfirmer::~CBTUserConfirmer() + { + LOG_FUNC + Cancel(); + delete iNameUpdater; + } + + +void CBTUserConfirmer::DoUpdateNotifier() + { + LOG_FUNC + if(IsActive()) + { + if(!iNameUpdater) + { + //Create a new CSecNotifierUpdateAO object + TRAP_IGNORE(iNameUpdater = CSecNotifierUpdateAO::NewL(iNotifier, KBTUserConfirmationNotifierUid)); + } + if(iNameUpdater) + { + TBTDeviceName deviceName(KNullDesC); + TInt err = KErrNotFound; + if(iDeviceName) + { + TRAP(err, deviceName = BTDeviceNameConverter::ToUnicodeL(*iDeviceName)); // Best effort attempt. + } + + TBTDeviceNameUpdateParamsPckg pckg = TBTDeviceNameUpdateParams(deviceName, err); + iNameUpdater->DoUpdate(pckg); + } + } + } + +void CBTUserConfirmer::DoRequest() +/** +Start the RNotifier plugin that deals with authorisation. +**/ + { + LOG_FUNC + TInt err(KErrNone); + + TBTDeviceName deviceName; + + if (iDeviceName) + { + TRAP(err, deviceName = BTDeviceNameConverter::ToUnicodeL(*iDeviceName)); + if (err!=KErrNone) + { + deviceName = KNullDesC; + } + } + else + { + deviceName = KNullDesC; + } + iUserConfirmationParamsPckg = TBTUserConfirmationParams(iDevAddr, deviceName, iInternallyInitiated); + + iNotifier.StartNotifierAndGetResponse(iStatus, KBTUserConfirmationNotifierUid, iUserConfirmationParamsPckg, iResultPckg); + SetActive(); + } + + +void CBTUserConfirmer::DoCancel() + { + LOG_FUNC + iNotifier.CancelNotifier(KBTUserConfirmationNotifierUid); + if(iNameUpdater) + { + iNameUpdater->Cancel(); + } + } + +void CBTUserConfirmer::RunL() + { + LOG_FUNC + // got an answer so unload the notifier + iNotifier.CancelNotifier(KBTUserConfirmationNotifierUid); + + //remove ourself from the notifier que, allowing the next notifier to be activated + RemoveMyselfFromQue(); + iIsAddedToNotifierQue = EFalse; + + __ASSERT_DEBUG(iUserConfirmationParamsPckg().DeviceAddress() == iDevAddr, PANIC(KBTSecPanic, EBTSecBadDeviceAddress)); + + iSecMan.UserConfirmationComplete(iDevAddr, iResultPckg(), iStatus.Int()); + } + +TInt CBTUserConfirmer::RunError(TInt aError) + { + LOG_FUNC + //will never get called as our RunL doesn't leave. + LOG1(_L8("\tCBTUserConfirmation::RunError(%d)\n"), aError); + return aError; + } + + + diff -r 8a27654f7b62 -r 20fda83a6398 bluetooth/btstack/secman/secman.h --- a/bluetooth/btstack/secman/secman.h Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetooth/btstack/secman/secman.h Mon Mar 15 12:44:59 2010 +0200 @@ -266,6 +266,7 @@ void RemoteOOBDataRequest(const TBTDevAddr& aAddr); void RemoteOOBDataRequestComplete(const TBTDevAddr& aAddr); void UserConfirmationRequest(const TBTDevAddr& aAddr, TUint32 aNumericValue); + void NumericComparisonComplete(const TBTDevAddr& aAddr, TBool aResult, TInt aError); void UserConfirmationComplete(const TBTDevAddr& aAddr, TBool aResult, TInt aError); void PasskeyNotification(const TBTDevAddr& aAddr, TUint32 aPasskey); void PasskeyNotificationComplete(const TBTDevAddr& aAddr, TInt aError); @@ -360,7 +361,7 @@ TBool AuthenticationRequired() const; TBool EncryptionRequired() const; TBool AuthenticationInProgress() const; - TBool UnableToBond() const; + TBool RemoteIndicatedNoBondingToDedicatedBonding() const; TBool BasebandConnected() const; void CompleteRequest(TInt aReason); @@ -445,7 +446,7 @@ TAccessType iAccessType; - TBool iDedicatedBondingNotAvailable; //< Remote IOCapabilitiesResponse says no dedicated bonding + TBool iRemoteIndicatedNoBonding; //< Remote IOCapabilitiesResponse says no dedicated bonding THCIIoCapability iRemoteIOCapability; THCIOobDataPresence iRemoteOOBDataPresence; @@ -668,6 +669,44 @@ TBuf8<1> iResultPckg; }; +/** +Prompts the user to confirm whether or not they want to pair +Uses the RNotifier framework to produce a dialog containing information +about the remote device +**/ +NONSHARABLE_CLASS(CBTUserConfirmer) + : public CSecNotifierRequester + { +public: + static CBTUserConfirmer* NewL(const TBTDevAddr aAddr, + CBTSecMan& aSecMan, + TBool aInternallyInitiated); + static CBTUserConfirmer* NewLC(const TBTDevAddr aAddr, + CBTSecMan& aSecMan, + TBool aInternallyInitiated); + ~CBTUserConfirmer(); + +private: // from CActive + void DoCancel(); + void RunL(); + TInt RunError(TInt aError); + +private: //from CSecNotifierRequester + virtual void DoRequest(); + virtual void DoUpdateNotifier(); + +private: + CBTUserConfirmer(CBTSecMan& aSecMan, + TBool aInternallyInitiated); + +private: + CSecNotifierUpdateAO* iNameUpdater; + CBTSecMan& iSecMan; + TBool iInternallyInitiated; + TBTUserConfirmationParamsPckg iUserConfirmationParamsPckg; + TPckgBuf iResultPckg; + }; + _LIT(KBTSecPanic, "BT Security"); enum TBTSecPanic @@ -708,6 +747,7 @@ EBTSecAccessRequesterShouldHaveNotBeenFound, EBTSecAccessRequesterShouldHaveBeenFound, EBTSecNotifierRequesterUsingTimerWithoutHandling, + EBTSecConnectionUserConfirmationTwice, }; diff -r 8a27654f7b62 -r 20fda83a6398 bluetoothmgmt/bluetoothclientlib/btlib/btsocket.cpp --- a/bluetoothmgmt/bluetoothclientlib/btlib/btsocket.cpp Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetoothmgmt/bluetoothclientlib/btlib/btsocket.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -2792,11 +2792,8 @@ void CAutoSniffDelayTimer::StartActive() { Start(); - if(iSniffModeRequested) - { - // When enabling auto sniffing, we make use of Explicit active mode. - (void)MbbhBTBaseband().RequestExplicitActiveMode(ETrue); - } + // When enabling auto sniffing, we make use of Explicit active mode. + (void)MbbhBTBaseband().RequestExplicitActiveMode(ETrue); } RBTBaseband& CAutoSniffDelayTimer::MbbhBTBaseband() @@ -2814,7 +2811,7 @@ if(iSniffModeRequested) { MbbhBTBaseband().CancelLowPowerModeRequester(); - StartActive(); + iSniffModeRequested = EFalse; } } __ASSERT_ALWAYS(iBTAutoSniffBasebandChangeEventNotifier != NULL, Panic(EBBInvalidAddress)); diff -r 8a27654f7b62 -r 20fda83a6398 bluetoothmgmt/bluetoothclientlib/inc/bt_subscribe_partner.h --- a/bluetoothmgmt/bluetoothclientlib/inc/bt_subscribe_partner.h Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetoothmgmt/bluetoothclientlib/inc/bt_subscribe_partner.h Mon Mar 15 12:44:59 2010 +0200 @@ -1,4 +1,4 @@ -// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2003-2010 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" @@ -67,4 +67,32 @@ */ const TUint KPropertyKeyBluetoothSetSimplePairingDebugMode = (KUidBluetoothPubSubKeyBase + 21); +/** +- +KPropertyKeyBluetoothSetPageScanParameters +The key to control the parameters of the page scan Bluetooth hardware is currently performing. +The P&S value will contain an integer from TPageScanParameterSettings enumeration. +The values are mapped to actual parameters in the Bluetooth stack. +@see TPageScanParameterSettings +@publishedPartner +@released +@capability LocalServices Needed for both read and write access to this property +@capability NetworkControl Needed for both read and write access to this property +*/ +const TUint KPropertyKeyBluetoothSetPageScanParameters = (KUidBluetoothPubSubKeyBase + 23); + +/** +KPropertyKeyBluetoothGetPageScanParameters +The key is intended to be used by the Bluetooth stack to provide an indication to the client +which has requested a page scan parameters change that the parameters have been enabled. +The value returned is of the TPageScanParameterSettings type. +The enumeration may gain additional members in future. +@see TPageScanParameterSettings +@publishedPartner +@released +@capability LocalServices Needed for both read and write access to this property +@capability NetworkControl Needed for both read and write access to this property +*/ +const TUint KPropertyKeyBluetoothGetPageScanParameters = (KUidBluetoothPubSubKeyBase + 24); + + #endif //BT_SUBSCRIBE_PARTNER_H \ No newline at end of file diff -r 8a27654f7b62 -r 20fda83a6398 bluetoothmgmt/bluetoothclientlib/inc/bttypespartner.h --- a/bluetoothmgmt/bluetoothclientlib/inc/bttypespartner.h Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetoothmgmt/bluetoothclientlib/inc/bttypespartner.h Mon Mar 15 12:44:59 2010 +0200 @@ -1,4 +1,4 @@ -// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 1999-2010 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" @@ -47,4 +47,15 @@ */ typedef TBuf8 TBluetoothSimplePairingRandomizer; +/** For page scan parameters setting. +- +The enumeration may gain additional members in future. +@publishedPartner +@released +*/ +enum TPageScanParameterSettings + { + EStandardPageScanParameters, + EFastConnectionPageScanParameters + }; + #endif //_BTTYPESPARTNER_H diff -r 8a27654f7b62 -r 20fda83a6398 bluetoothmgmt/btmgr/BTDevice/BTDevice.cpp --- a/bluetoothmgmt/btmgr/BTDevice/BTDevice.cpp Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetoothmgmt/btmgr/BTDevice/BTDevice.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -88,7 +88,7 @@ Initialises the device class to 0. **/ EXPORT_C TBTDeviceClass::TBTDeviceClass() : - iDeviceClass(0) + iDeviceClass(0), iPadding1(0), iPadding2(0) { } @@ -97,7 +97,7 @@ @param aDeviceClass The initial device class **/ EXPORT_C TBTDeviceClass::TBTDeviceClass(TUint32 aDeviceClass) : - iDeviceClass(aDeviceClass) + iDeviceClass(aDeviceClass), iPadding1(0), iPadding2(0) { } @@ -115,7 +115,7 @@ */ EXPORT_C TBTDeviceClass::TBTDeviceClass(TUint16 aMajorServiceClass, TUint8 aMajorDeviceClass, TUint8 aMinorDeviceClass) : - iDeviceClass(0) + iDeviceClass(0), iPadding1(0), iPadding2(0) { iDeviceClass = (aMajorServiceClass & EMajorServiceMask); // [00000000]0000000000000xxxxxxxxxxx iDeviceClass <<= EMajorDeviceLength; // [00000000]00000000xxxxxxxxxxx00000 diff -r 8a27654f7b62 -r 20fda83a6398 bluetoothmgmt/btmgr/BTManServer/BTManServer.cpp --- a/bluetoothmgmt/btmgr/BTManServer/BTManServer.cpp Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetoothmgmt/btmgr/BTManServer/BTManServer.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -1,4 +1,4 @@ -// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 1999-2010 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" @@ -109,6 +109,9 @@ iContainerIndex = CObjectConIx::NewL(); // don't stop the server if we can't provide this service... + + //Start Backup/Restore Manager and obtain notification of backup/restore operations. + iBURManager=CBTManServerBURMgr::NewL(*this, this); } @@ -140,6 +143,7 @@ // Close the RProperty handle in case it is ever attached. iProperty.Close(); + delete iBURManager; delete iRegistry; delete iContainerIndex; } @@ -156,6 +160,32 @@ return new(ELeave) CBTManSession(*iRegistry, aMessage); } +void CBTManServer::BUROperationStarted() +/** +A backup or restore operation has started. +Cancel the shutdown timer if it was running +**/ + { + LOG_FUNC + __ASSERT_DEBUG(!iBUROperationStarted, PanicServer(EBTManBadState)); + + iBUROperationStarted = ETrue; + iShutdown.Cancel(); + } + +void CBTManServer::BUROperationStopped() +/** +A backup or restore operation has finished. +Start the shutdown timer if there are no sessions running. +**/ + { + LOG_FUNC + __ASSERT_DEBUG(iBUROperationStarted, PanicServer(EBTManBadState)); + + iBUROperationStarted = EFalse; + TryToStartShutdownTimer(); + } + void CBTManServer::AddSession() /** A new session is being created @@ -180,7 +210,18 @@ LOG_FUNC __ASSERT_DEBUG(iSessionCount > 0, PanicServer(EBTManBadState)); - if (--iSessionCount==0) + --iSessionCount; + TryToStartShutdownTimer(); + } + +void CBTManServer::TryToStartShutdownTimer() +/** +Starts the shutdown timer if the server is able to shutdown +**/ + { + LOG_FUNC + + if (iSessionCount == 0 && !iBUROperationStarted) { iShutdown.Start(); } @@ -204,13 +245,28 @@ // Go through all sessions - they'll dispatch so all the subessions apart from the one calling here iSessionIter.SetToFirst(); - while (iSessionIter != NULL) + while (iSessionIter) { CBTManSession* s = static_cast(iSessionIter++); s->SubSessionHasOverlappingView(aSubSessionViewOwner, aViewDescriptor); } } +void CBTManServer::NotifyViewChange(const TDesC& aViewDescriptor) + { + LOG_FUNC + // For views not owned by subsessions (e.g. views owned by Backup/Restore classes) + + // Go through all sessions - they'll dispatch so all the subessions apart from the one calling here + iSessionIter.SetToFirst(); + + while (iSessionIter) + { + CBTManSession* s = static_cast(iSessionIter++); + s->SubSessionHasOverlappingView(aViewDescriptor); + } + } + void PanicClient(const RMessage2& aMessage,TInt aPanic, CBTManSession* aSession) /** RMessage2::Panic() also completes the message. This is: @@ -1097,6 +1153,25 @@ return overlapFound; } +TBool CBTManSession::SubSessionHasOverlappingView(const TDesC& aViewDescriptor) + { + LOG_FUNC + // Iterate over all subsessions (view owner is not a subsession) + TBool overlapFound = EFalse; + for (TInt i = 0; i < iContainer->Count(); i++) + { + CBTManSubSession* ss = static_cast((*iContainer)[i]); + if (ss->IsOverlappingView(aViewDescriptor)) + { + // Overlaps - subsession will have completed the Notify message + // With bool return, we can test if indeed it did. + overlapFound = ETrue; + } + } + + return overlapFound; + } + //===================================================================== // CBTManSubSession diff -r 8a27654f7b62 -r 20fda83a6398 bluetoothmgmt/btmgr/BTManServer/BTManServer.mmp --- a/bluetoothmgmt/btmgr/BTManServer/BTManServer.mmp Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetoothmgmt/btmgr/BTManServer/BTManServer.mmp Mon Mar 15 12:44:59 2010 +0200 @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2006-2010 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" @@ -34,6 +34,8 @@ SOURCE LocalDeviceSubSession.cpp SOURCE CSYSubSession.cpp SOURCE BTRegistrySQL.cpp +SOURCE btmanserverburmgr.cpp +SOURCE btmanserverburstatemachine.cpp USERINCLUDE . ../Inc ../../btcommon/inc USERINCLUDE ../../bluetoothclientlib/inc @@ -44,6 +46,8 @@ LIBRARY esock.lib +LIBRARY abclient.lib + #include //MACRO ALLOW_UNREGISTERED_SERVICES diff -r 8a27654f7b62 -r 20fda83a6398 bluetoothmgmt/btmgr/BTManServer/BTRegistryDB.cpp --- a/bluetoothmgmt/btmgr/BTManServer/BTRegistryDB.cpp Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetoothmgmt/btmgr/BTManServer/BTRegistryDB.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -1,4 +1,4 @@ -// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 1999-2010 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" @@ -1173,6 +1173,16 @@ return device; } +TBTLocalDevice* CBTRegistry::GetLocalDeviceL() + { + LOG_FUNC + TBTLocalDevice* device = GetLocalDeviceLC(); + CleanupStack::Pop(device); + return device; + } + + + const TBTCommPortSettings* CBTRegistry::GetCommPortSettingsLC(const TBTCommPortSettings& aSettings) /** Get the virtual serial port settings for the port referred to in aSettings diff -r 8a27654f7b62 -r 20fda83a6398 bluetoothmgmt/btmgr/BTManServer/BTRegistryDB.h --- a/bluetoothmgmt/btmgr/BTManServer/BTRegistryDB.h Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetoothmgmt/btmgr/BTManServer/BTRegistryDB.h Mon Mar 15 12:44:59 2010 +0200 @@ -1,4 +1,4 @@ -// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 1999-2010 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" @@ -106,6 +106,8 @@ // 1.1 - Adjusted the Time/Date fields for 64 bit integers (remote device table). // 1.2 - Added additional fields Link-key type and UI cookie (remote device table). +// Note: Any changes to the registry version will also require changes to the CBTRegistryBURData class. + // Useful SQL literals _LIT(KSQLIsNotNull, " IS NOT NULL"); _LIT(KSQLCommaSpace, ", "); @@ -173,6 +175,7 @@ void UpdateNameL(const TBTDevAddr& aAddress, const TDesC8& aName, TBTManServerRequest aRequest); // for local device table TBTLocalDevice* GetLocalDeviceLC(); + TBTLocalDevice* GetLocalDeviceL(); void UpdateLocalDeviceL(const TBTLocalDevice& aDevice); // CSY table const TBTCommPortSettings* GetCommPortSettingsLC(const TBTCommPortSettings& aPort); @@ -184,6 +187,8 @@ RDbView* OpenCommPortLC(const TBTCommPortSettings& aSettings); RDbView* OpenCommPortL(const TBTCommPortSettings& aSettings); + void GetDefaultDeviceFromIniL(TBTLocalDevice& aDevice); + private: RDbTable* OpenTableL(const TDesC& aTable); // opens and transfers ownership RDbTable* OpenPersistTableL(); // opens and transfers ownership @@ -209,7 +214,6 @@ CBTRegistry(); void DeleteCorruptRegistryL(); void SetupDefaultRegistryL(); - void GetDefaultDeviceFromIniL(TBTLocalDevice& aDevice); TBool FindVar(const TDesC8& aPtr, const TDesC8& aVarName, TPtrC8& aResult) const; TBool FindVar(const TDesC8& aPtr, const TDesC8& aVarName, TInt& aResult) const; TInt SetDeviceName(const TDesC& aDeviceName, TBTLocalDevice& aDevice); diff -r 8a27654f7b62 -r 20fda83a6398 bluetoothmgmt/btmgr/BTManServer/backup_registration.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothmgmt/btmgr/BTManServer/backup_registration.xml Mon Mar 15 12:44:59 2010 +0200 @@ -0,0 +1,28 @@ + + + + + + + + + + + diff -r 8a27654f7b62 -r 20fda83a6398 bluetoothmgmt/btmgr/BTManServer/btmanserverburmgr.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothmgmt/btmgr/BTManServer/btmanserverburmgr.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -0,0 +1,2020 @@ +// Copyright (c) 2010 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: +// Implements backup and restore support for the Bluetooth Manager server. +// + +#include +#include +#include +#include +#include +#include "btmanserverutil.h" +#include "btmanserverburmgr.h" +#include "BTManServer.h" + +#include "btmanclient.h" +#include "btdevice.h" +#include +#include +#include "BTSec.h" + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, LOG_COMPONENT_BT_MANAGER_SERVER); +#endif + + +/** +Raises an EBTBURMgrInvalidState panic with state information encoded within the panic code. +The first digit denotes the panic code (EBTBURMgrInvalidState). +The second digit is a delimiter and is always 1. +The next two digits represent the expected state +The next digit again is a delimiter and is always 1. +The final two digits represent the actual state. + +For example, the panic code 7101100 indicates an EBTBURMgrInvalidState panic raised because the state +machine is in the EBTBURStateNormal state when it was expected to be in the EBTBURStateBackupRequest state. +**/ +void InvalidStatePanic(TBTBURState aExpectedState, TBTBURState aActualState) + { + LOG_STATIC_FUNC + User::Panic(KBTBackupPanicCat, (EBTBURMgrInvalidState*KBTBackupStatePanicMultiplier) + KBTBackupStatePanicMajorDelimiter + (aExpectedState * KBTBackupStateMultiplier) + KBTBackupStatePanicMinorDelimiter + aActualState); + } + +/** +Raises an EBTBURMgrInvalidStateTransition panic with state information encoded within the panic code. +The first digit denotes the panic code (EBTBURMgrInvalidStateTransition). +The second digit is a delimiter and is always 1. +The next two digits represent the expected state +The next digit again is a delimiter and is always 1. +The final two digits represent the actual state. + +For example, the panic code 6101100 indicates an EBTBURMgrInvalidStateTransition panic raised because the state +machine is in the EBTBURStateNormal state when it was expected to be in the EBTBURStateBackupRequest state. +**/ +void InvalidStateTransitionPanic(TBTBURState aCurrentState, TBTBUREvent aEvent) + { + LOG_STATIC_FUNC + User::Panic(KBTBackupPanicCat, (EBTBURMgrInvalidStateTransition*KBTBackupStatePanicMultiplier) + KBTBackupStatePanicMajorDelimiter + (aCurrentState * KBTBackupStateMultiplier) + KBTBackupStatePanicMinorDelimiter + aEvent); + } + + +/** +CBTManServerBURMgr - Manages backup and restore support for the Bluetooth Manager server. +**/ + +/** +Constructs a new instance of a CBTManServerBURMgr. +An MBTBURNotify instance may be registered here for notifications. Ownership of the MBTBURNotify instance is not transferred. +@see CBTManServerBURMgr::RequestBURNotification() +**/ +CBTManServerBURMgr* CBTManServerBURMgr::NewL(CBTManServer& aBTManServer, MBTBURNotify* aBURNotify, TInt aPriority) + { + LOG_STATIC_FUNC + CBTManServerBURMgr* self = new(ELeave) CBTManServerBURMgr(aBTManServer, aBURNotify, aPriority); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CBTManServerBURMgr::CBTManServerBURMgr(CBTManServer& aBTManServer, MBTBURNotify* aBURNotify, TInt aPriority) + : CActive(aPriority), + iBTManServer(aBTManServer), + iBUROperationStartNotified(EFalse) + { + LOG_FUNC + + RequestBURNotification(aBURNotify); + CActiveScheduler::Add(this); + } + +CBTManServerBURMgr::~CBTManServerBURMgr() + { + LOG_FUNC + + Cancel(); + iProperty.Close(); + + // Close any open session on BT Manager + NotifyAnyBUROperationStopped(); + + // Members which either hold data or are NULL + delete iActiveBackupClient; + delete iActiveBackupDataClient; + delete iBackupHandler; + delete iRestoreHandler; + delete iLocalAddrFetcher; + + // Member that is instantiated for entire lifetime of CBTManServerBURMgr + delete iStateMachine; + } + +void CBTManServerBURMgr::ConstructL() + { + LOG_FUNC + + // Construct state machine + iStateMachine = CBTManServerBURMgrStateFactory::NewL(*this); + // Construction counts as a transition into the default state (EBTBURStateNormal) of the state machine. + // However, since this does nothing if no backup/restore cleanup is required, we do not need to execute the + // state action. + + // Setup iProperty to catch BUR flag from Secure Backup Engine + LEAVEIFERRORL(iProperty.Attach(KUidSystemCategory, KUidBackupRestoreKey)); + + // Subscribe to BUR P&S key to catch transitions + SubscribeToBackupRestoreKey(); + + // Also check flag now (it may have already transitioned) + TInt backupKeyValue = 0; + LEAVEIFERRORL(iProperty.Get(backupKeyValue)); + TBURPartType backupState = GetBURPartType(backupKeyValue); + + // If we're not about to perform a restore, check if a restore file exists. If so, try to process restore file. + // The restore operation may not affect us, or may be postponed. In either case, we try to process the restore file + // again next time we start. + if (backupState != EBURRestoreFull && backupState != EBURRestorePartial) + { + // Delete any stale backup files + DeleteBackupFile(); + // See if a restore file needs processing + CheckForRestoreFileL(); + } + + // Process flag + ProcessBackupState(backupState); + } + +/** +Translates a given integer obtained from the KUidBackupRestoreKey P&S key to a TBURPartType value. +This will validate the masked value to ensure that it falls within the range of the TBURPartType enum. +In debug builds, a panic will be raised if this value is out of range. +In release builds, EBURUnset is returned if the value is out of range. +**/ +TBURPartType CBTManServerBURMgr::GetBURPartType(TInt aValue) + { + LOG_FUNC + + switch (aValue & KBURPartTypeMask) + { + case EBURUnset: + return EBURUnset; + case EBURNormal: + return EBURNormal; + case EBURBackupFull: + return EBURBackupFull; + case EBURBackupPartial: + return EBURBackupPartial; + case EBURRestoreFull: + return EBURRestoreFull; + case EBURRestorePartial: + return EBURRestorePartial; + default: + __ASSERT_DEBUG(EFalse, PANIC(KBTBackupPanicCat, EBTBURMgrInvalidBackupRestoreState)); + return EBURUnset; + } + } + +/** +Attempts to locate a restore file in the private directory of this server. +@return ETrue if the file can be found, EFalse otherwise. +**/ +TBool CBTManServerBURMgr::RestoreFilePresent() + { + LOG_FUNC + + RFs fsSession; + TInt err = fsSession.Connect(); + if (err == KErrNone) + { + err = fsSession.SetSessionToPrivate(fsSession.GetSystemDrive()); + if (err ==KErrNone) + { + TEntry entry; + err = fsSession.Entry(KBTManServerRestoreFileName, entry); + } + + fsSession.Close(); + } + + // If restore file was found, err will be KErrNone + return (err == KErrNone); + } + +/** +Checks for the existence of a restore file. If a restore file is found, then the local device address +is feteched and processing of that restore file is initiated. +**/ +void CBTManServerBURMgr::CheckForRestoreFileL() + { + LOG_FUNC + + if (RestoreFilePresent()) + { + // Fetch local address. When this is received, restore file processing will begin. + iLocalAddrFetcher = CBTLocalAddressFetcher::NewL(*this, iBTManServer.Registry()); + iLocalAddrFetcher->FetchLocalAddress(); + } + } + +/** +Subscribes to the P&S flag provided by the Secure Backup Engine (to receive notification of backup/restore state changes). +**/ +void CBTManServerBURMgr::SubscribeToBackupRestoreKey() + { + LOG_FUNC + + iProperty.Subscribe(iStatus); + SetActive(); + } + +/** +Processes a change in the backup/restore state of the device. +@param aBackupStateValue A value expressing the backup/restore state of the device. +**/ +void CBTManServerBURMgr::ProcessBackupState(TBURPartType aBURStateValue) + { + LOG_FUNC + + iBURState = aBURStateValue; + + switch (aBURStateValue) + { + case EBURBackupFull: + // Fall-through + case EBURBackupPartial: + iStateMachine->TransitionState(EBTBUREventBackup); + break; + case EBURRestoreFull: + // Fall-through + case EBURRestorePartial: + iStateMachine->TransitionState(EBTBUREventRestore); + break; + case EBURNormal: + iStateMachine->TransitionState(EBTBUREventNormal); + break; + default: // EBURUnset + __ASSERT_DEBUG(aBURStateValue == EBURUnset, PANIC(KBTBackupPanicCat, EBTBURMgrUnknownBUREvent)); + iStateMachine->TransitionState(EBTBUREventUnset); + } + } + +/** +Registers an MBTBURNotify instance to receive notification of backup/restore operations starting and stopping. +Ownership of this MBTBURNotify instance is not transferred. +Any previous MBTBURNotify instance is deregistered on this method call. +Supplying a NULL pointer will deregister the previously registered instance (if present). +**/ +void CBTManServerBURMgr::RequestBURNotification(MBTBURNotify* aBURNotify) + { + LOG_FUNC + + iBURNotify = aBURNotify; + } + + +/** +Receives a local address from a CBTLocalAddressFetcher instance. +This will trigger processing of a pending restore file. +**/ +void CBTManServerBURMgr::SetLocalAddress(TBTDevAddr& aLocalAddr) + { + LOG_FUNC + __ASSERT_DEBUG(aLocalAddr != TBTDevAddr(), PANIC(KBTBackupPanicCat, EBTBURMgrMissingLocalAddress)); + + // Use address only if it is non-zero. + if (aLocalAddr != TBTDevAddr()) + { + // Take a copy + iLocalAddr = aLocalAddr; + // Attempt to start restore file processing. + // Note that this will fail if we are not in the normal state. + iStateMachine->TransitionState(EBTBUREventProcessRestoreFile); + } + } + +/** +Receives notification that a restore file has been provided by the Secure Backup Engine. +Upon receiving this notification, the restore file is renamed to have the appropriate extension and +the local device name is updated in the registry. The restore of the remote devices table is postponed +until the next time BTManServer starts, so any ongoing BT connections are not affected. +**/ +void CBTManServerBURMgr::RestoreFileReady() + { + LOG_FUNC + __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreOngoing, InvalidStatePanic(EBTBURStateRestoreOngoing, iStateMachine->GetCurrentState())); + + // Rename restore file + RenameBackupFileForRestore(); + // Attempt to update local device name in the registry (best efforts only) + TRAP_IGNORE(UpdateLocalDeviceNameL()); + } + +void CBTManServerBURMgr::HandleStateNormal() + { + LOG_FUNC + __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateNormal, InvalidStatePanic(EBTBURStateNormal, iStateMachine->GetCurrentState())); + + if (iActiveBackupClient) + { + // Backup or restore finished + if (iBackupHandler) + { + // Backup operation finished + // Delete backup file and destroy backup handler + DeleteBackupFile(); + delete iBackupHandler; + iBackupHandler = NULL; + } + else + { + // Restore operation finished + delete iActiveBackupDataClient; + iActiveBackupDataClient = NULL; + } + + // Destroy active backup client + delete iActiveBackupClient; + iActiveBackupClient = NULL; + + // Notify that backup/restore operation has finished + NotifyBUROperationStopped(); + } + } + +/** +Determines if a BUR operation affects the Bluetooth Manager server. +@return ETrue if a full backup or restore is ongoing, otherwise the return value +given by CActiveBackupClient::DoesPartialBURAffectMeL() +**/ +TBool CBTManServerBURMgr::DoesBURAffectMeL(CActiveBackupClient& aClient) + { + LOG_FUNC + + if (iBURState == EBURBackupFull || iBURState == EBURRestoreFull) + { + return ETrue; + } + else + { + return aClient.DoesPartialBURAffectMeL(); + } + } + +void CBTManServerBURMgr::HandleStateBackupRequestL() + { + LOG_FUNC + __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupRequest, InvalidStatePanic(EBTBURStateBackupRequest, iStateMachine->GetCurrentState())); + + // Determine if this backup operation affects us and transition to next state based on this outcome. + iActiveBackupClient = CActiveBackupClient::NewL(); + + if (DoesBURAffectMeL(*iActiveBackupClient)) + { + // We're affected, proceed with backup + iStateMachine->TransitionState(EBTBUREventBackupProceed); + } + else + { + // We're not effected, don't do any backup handling + iStateMachine->TransitionState(EBTBUREventBackupReject); + } + } + +void CBTManServerBURMgr::HandleStateBackupRequestError() + { + LOG_FUNC + __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupRequest, InvalidStatePanic(EBTBURStateBackupRequest, iStateMachine->GetCurrentState())); + + // Transition to normal state + iStateMachine->TransitionState(EBTBUREventAbortStateAction); + } + +void CBTManServerBURMgr::HandleStateBackupOngoingL() + { + LOG_FUNC + __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupOngoing, InvalidStatePanic(EBTBURStateBackupOngoing, iStateMachine->GetCurrentState())); + __ASSERT_DEBUG(iActiveBackupClient, PANIC(KBTBackupPanicCat, EBTBURMgrActiveBackupClientNull)); + + // Provide notification that a BUR operation has started. + NotifyBUROperationStarted(); + + // Construct backup handler and prepare for backup + iBackupHandler = CBTBackupHandler::NewL(*this, iBTManServer.Registry()); + iBackupHandler->CreateBackupFileL(); + + // Signal that we're ready for (passive) backup of prepared file + iActiveBackupClient->ConfirmReadyForBURL(KErrNone); + + // Next state transition will be invoked when BUR P&S key changes + } + +void CBTManServerBURMgr::HandleStateBackupOngoingError() + { + LOG_FUNC + __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupOngoing, InvalidStatePanic(EBTBURStateBackupOngoing, iStateMachine->GetCurrentState())); + + // Transition to normal state + iStateMachine->TransitionState(EBTBUREventAbortStateAction); + } + +void CBTManServerBURMgr::HandleStateBackupIgnore() + { + LOG_FUNC + __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupIgnore, InvalidStatePanic(EBTBURStateBackupIgnore, iStateMachine->GetCurrentState())); + + // Destroy active backup client + delete iActiveBackupClient; + iActiveBackupClient = NULL; + + // Next state transition will be invoked when BUR P&S key changes + } + +void CBTManServerBURMgr::HandleStateRestoreRequestL() + { + LOG_FUNC + __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreRequest, InvalidStatePanic(EBTBURStateRestoreRequest, iStateMachine->GetCurrentState())); + + // We do want a callback here. Even though the actual restore operation has been handled passively, we + // still need notificaton that the passive restore has completed (so we can then deal with the file). + iActiveBackupDataClient = CBTActiveBackupDataClient::NewL(*this); + iActiveBackupClient = CActiveBackupClient::NewL(iActiveBackupDataClient); + + // Determine if this restore operation affects us and transition to next state based on this outcome + if (DoesBURAffectMeL(*iActiveBackupClient)) + { + // We're affected, proceed with restore + iStateMachine->TransitionState(EBTBUREventRestoreProceed); + } + else + { + // We're not effected, don't do any restore handling + iStateMachine->TransitionState(EBTBUREventRestoreReject); + } + } + +void CBTManServerBURMgr::HandleStateRestoreRequestError() + { + LOG_FUNC + __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreRequest, InvalidStatePanic(EBTBURStateRestoreRequest, iStateMachine->GetCurrentState())); + + // Transition to normal state + iStateMachine->TransitionState(EBTBUREventAbortStateAction); + } + +void CBTManServerBURMgr::HandleStateRestoreOngoingL() + { + LOG_FUNC + __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreOngoing, InvalidStatePanic(EBTBURStateRestoreOngoing, iStateMachine->GetCurrentState())); + + // Cancel any local address requests + if (iLocalAddrFetcher) + { + iLocalAddrFetcher->Cancel(); + } + + // Provide notification that a BUR operation has started. + NotifyBUROperationStarted(); + + // Signal that we're ready for active restore of prepared file + // (note that no data is actively restored, but we still need to invoke this method) + iActiveBackupClient->ConfirmReadyForBURL(KErrNone); + + // Next state transition will be invoked when BUR P&S key changes + } + +void CBTManServerBURMgr::HandleStateRestoreOngoingError() + { + LOG_FUNC + __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreOngoing, InvalidStatePanic(EBTBURStateRestoreOngoing, iStateMachine->GetCurrentState())); + + // Transition to normal state + iStateMachine->TransitionState(EBTBUREventAbortStateAction); + } + +void CBTManServerBURMgr::HandleStateRestoreIgnore() + { + LOG_FUNC + __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreIgnore, InvalidStatePanic(EBTBURStateRestoreIgnore, iStateMachine->GetCurrentState())); + + // Destroy active backup client + delete iActiveBackupClient; + delete iActiveBackupDataClient; + iActiveBackupClient = NULL; + iActiveBackupDataClient = NULL; + + // Next state transition will be invoked when BUR P&S key changes + } + +void CBTManServerBURMgr::HandleStateProcessRestoreFileL() + { + LOG_FUNC + __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateProcessRestoreFile, InvalidStatePanic(EBTBURStateProcessRestoreFile, iStateMachine->GetCurrentState())); + + // Start restore file processing + iRestoreHandler = CBTRestoreHandler::NewL(*this, iBTManServer); + iRestoreHandler->RestoreRemoteDeviceTableL(iLocalAddr); + + iStateMachine->TransitionState(EBTBUREventProcessRestoreFileComplete); + } + +void CBTManServerBURMgr::HandleStateProcessRestoreFileError(TInt aError) + { + LOG_FUNC + __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateProcessRestoreFile, InvalidStatePanic(EBTBURStateProcessRestoreFile, iStateMachine->GetCurrentState())); + + // Delete restore handler + delete iRestoreHandler; + iRestoreHandler = NULL; + + // If aError is anything other than KErrNoMemory, then delete restore file. + // OOM errors may be temporary, and a subsequent restore attempt may succeed. + if (aError != KErrNoMemory) + { + DeleteRestoreFile(); + } + + // Transition to normal state + iStateMachine->TransitionState(EBTBUREventAbortStateAction); + } + +void CBTManServerBURMgr::HandleStateRestoreFileProcessingComplete() + { + LOG_FUNC + __ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreFileProcessingComplete, InvalidStatePanic(EBTBURStateRestoreFileProcessingComplete, iStateMachine->GetCurrentState())); + + // Delete restore file (we're now done with it) + DeleteRestoreFile(); + + // Delete restore handler + delete iRestoreHandler; + iRestoreHandler = NULL; + + iStateMachine->TransitionState(EBTBUREventRestoreFileTransitionNormal); + } + +/** +Sends notification to a registered MBTBURNotify instance that a backup or restore operation has started. +@see CBTManServerBURMgr::RequestBURNotification() +**/ +void CBTManServerBURMgr::NotifyBUROperationStarted() + { + LOG_FUNC + __ASSERT_DEBUG(!iBUROperationStartNotified, PANIC(KBTBackupPanicCat, EBTBURMgrBUROperationStartAlreadyNotified)); + + if (!iBUROperationStartNotified) + { + iBUROperationStartNotified = ETrue; + + if (iBURNotify) + { + iBURNotify->BUROperationStarted(); + } + } + } + +/** +Sends notification to the MBTBURNotify instance that a backup or restore operation has started. +This should correspond to a call to NotifyBUROperationStarted(). +@see CBTManServerBURMgr::RequestBURNotification() +**/ +void CBTManServerBURMgr::NotifyBUROperationStopped() + { + LOG_FUNC + __ASSERT_DEBUG(iBUROperationStartNotified, PANIC(KBTBackupPanicCat, EBTBURMgrBUROperationStartNotNotified)); + + if (iBUROperationStartNotified) + { + iBUROperationStartNotified = EFalse; + + if (iBURNotify) + { + iBURNotify->BUROperationStopped(); + } + } + } + +/** +Sends notification to the MBTBURNotify instance that a backup or restore operation has started. +This will send notification only if NotifyBUROperationStarted() has been called without a corresponding +call to NotifyBUROperationStopped(). +This is intended for use in error situations only. +**/ +void CBTManServerBURMgr::NotifyAnyBUROperationStopped() + { + LOG_FUNC + + // We deliberately want to fail silently here if no stop notification is expected. + if (iBUROperationStartNotified) + { + iBUROperationStartNotified = EFalse; + + if (iBURNotify) + { + iBURNotify->BUROperationStopped(); + } + } + } + +/** +Utility function to delete a named file from the private directory of this process on the system drive. +This is a best-efforts attempt which fails silently on error. +@param aFileName The name of the file to delete. +**/ +void CBTManServerBURMgr::DeleteFile(const TDesC& aFileName) + { + LOG_FUNC + + RFs fsSession; + // Attempt to delete file + // This is best-efforts, failing silently on any error (as there is no remedy action that we can take). + if (fsSession.Connect() == KErrNone) + { + if (fsSession.SetSessionToPrivate(fsSession.GetSystemDrive()) == KErrNone) + { + // Try to ensure read-only and system attributes are not set + TUint attrs; + TInt err = fsSession.Att(aFileName, attrs); + if (err == KErrNone) + { + // Unset the files read-only and system attributes if these are set. + TUint unsetAttrs = (attrs & KEntryAttReadOnly) | (attrs & KEntryAttSystem); + if (unsetAttrs != KEntryAttNormal) + { + err = fsSession.SetAtt(aFileName, KEntryAttNormal, unsetAttrs); + } + + // Attempt to delete the file, if we've managed to successfully retrieve and reset the file attributes. + // Note that this is best-efforts. + if (err == KErrNone) + { + static_cast(fsSession.Delete(aFileName)); + } + } + } + + fsSession.Close(); + } + } + +/** +Deletes the backup file (with name KBTManServerBackupFileName) from the private directory of this process on the system drive. +This is a best-efforts attempt which fails silently on error. +**/ +void CBTManServerBURMgr::DeleteBackupFile() + { + LOG_FUNC + + DeleteFile(KBTManServerBackupFileName); + } + +/** +Deletes the restore file (with name KBTManServerRestoreFileName) from the private directory of this process on the system drive. +This is a best-efforts attempt which fails silently on error. +**/ +void CBTManServerBURMgr::DeleteRestoreFile() + { + LOG_FUNC + + DeleteFile(KBTManServerRestoreFileName); + } + +/** +Renames a restored backup file from KBTManServerBackupFileName to KBTManServerRestoreFileName. +This facilitates processing of the restore file when the Bluetooth Manager server next starts. +This is a best-efforts attempt, as no remedial action can be taken if this operation fails. +**/ +void CBTManServerBURMgr::RenameBackupFileForRestore() + { + LOG_FUNC + + // Delete any previous restore file + DeleteRestoreFile(); + + RFs fsSession; + if (fsSession.Connect() == KErrNone) + { + static_cast(fsSession.Rename(KBTManServerBackupFileName, KBTManServerRestoreFileName)); + fsSession.Close(); + } + } + +/** +Parses the restore file and updates the loal device name in the registry. +This update takes place as soon as the restore file is available, regardless of whether or not the local device +address matches that held in the registry. If the local device name has already been set to a non-default value, +then it is not modified. +**/ +void CBTManServerBURMgr::UpdateLocalDeviceNameL() + { + LOG_FUNC + + CBTRestoreHandler* restoreHandler = CBTRestoreHandler::NewL(*this, iBTManServer); + CleanupStack::PushL(restoreHandler); + + restoreHandler->RestoreLocalDeviceNameL(); + + CleanupStack::PopAndDestroy(restoreHandler); + } + +void CBTManServerBURMgr::RunL() + { + LOG_FUNC + + if (iStatus == KErrNone) + { + // Subscribe to catch the next transition + SubscribeToBackupRestoreKey(); + + // Handle this event + TInt backupKeyValue = 0; + LEAVEIFERRORL(iProperty.Get(backupKeyValue)); + TBURPartType backupState = GetBURPartType(backupKeyValue); + + ProcessBackupState(backupState); + } + } + +TInt CBTManServerBURMgr::RunError(TInt /*aError*/) + { + LOG_FUNC + + // Problem occured in obtaining backup key value. + // Ignore the error, as there is nothing we can do. + return KErrNone; + } + +void CBTManServerBURMgr::DoCancel() + { + LOG_FUNC + + // Cancel our subscription + iProperty.Cancel(); + } + +/** + CBTBackupHandler - Handles the task of backing up the BT registry into a backup file ready for passive backup. + **/ +CBTBackupHandler* CBTBackupHandler::NewL(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry) + { + LOG_STATIC_FUNC + + CBTBackupHandler* result = new(ELeave) CBTBackupHandler(aBURMgr, aRegistry); + CleanupStack::PushL(result); + result->ConstructL(); + CleanupStack::Pop(result); + return result; + } + +CBTBackupHandler::CBTBackupHandler(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry) + : iBURMgr(aBURMgr), + iRegistry(aRegistry) + { + LOG_FUNC + } + +void CBTBackupHandler::ConstructL() + { + LOG_FUNC + + iRegistryData=CBTRegistryBURData::NewL(); + } + +CBTBackupHandler::~CBTBackupHandler() + { + LOG_FUNC + + delete iRegistryData; + } + +void CBTBackupHandler::CreateBackupFileL() + { + LOG_FUNC + + // Collect backup registry data + iRegistryData->ReadFromRegistryL(iRegistry); + + // Only continue if the registry is populated (i.e. it may be in its default state, which does not need to be backed up). + // Determine this by examining the local device address stored in the registry. The default registry has this set to 0x0. + if (iRegistryData->IsLocalAddressNonZeroL()) + { + // Construct backup file in private directory. + RFs fsSession; + LEAVEIFERRORL(fsSession.Connect()); + CleanupClosePushL(fsSession); + LEAVEIFERRORL(fsSession.SetSessionToPrivate(fsSession.GetSystemDrive())); + // Create private path if it does not already exist. + LEAVEIFERRORL(fsSession.CreatePrivatePath(fsSession.GetSystemDrive())); + + RFileWriteStream fStream; + // Create backup file, overwriting if necessary (don't care about previous backup files). + LEAVEIFERRORL(fStream.Replace(fsSession, KBTManServerBackupFileName, EFileWrite)); + fStream.PushL(); + + // Write out data + iRegistryData->WriteToStreamL(fStream); + fStream.CommitL(); + + CleanupStack::PopAndDestroy(2, &fsSession); + } + } + +/** + CBTRestoreHandler - Handles the task of restoring the BT registry from a restore file given by passive restore. + **/ +CBTRestoreHandler* CBTRestoreHandler::NewL(CBTManServerBURMgr& aBURMgr, CBTManServer& aManServer) + { + LOG_STATIC_FUNC + + CBTRestoreHandler* result = new(ELeave) CBTRestoreHandler(aBURMgr, aManServer); + CleanupStack::PushL(result); + result->ConstructL(); + CleanupStack::Pop(result); + return result; + } + +CBTRestoreHandler::CBTRestoreHandler(CBTManServerBURMgr& aBURMgr, CBTManServer& aManServer) + : iBURMgr(aBURMgr), + iManServer(aManServer) + { + LOG_FUNC + } + +void CBTRestoreHandler::ConstructL() + { + LOG_FUNC + + iRegistryData = CBTRegistryBURData::NewL(); + } + +CBTRestoreHandler::~CBTRestoreHandler() + { + LOG_FUNC + + delete iRegistryData; + } + +void CBTRestoreHandler::RestoreLocalDeviceNameL() + { + LOG_FUNC + + LoadRestoreDataL(); + + // If the local device name is still default, restore without validating the local address + // (otherwise we will not be able to restore this field before the next stack start, which may cause problems with some UIs) + CBTRegistry& registry = iManServer.Registry(); + if (iRegistryData->WriteLocalDeviceNameToRegistryL(registry)) + { + NotifyLocalTableChange(); + } + } + +void CBTRestoreHandler::RestoreRemoteDeviceTableL(TBTDevAddr& aLocalAddr) + { + LOG_FUNC + __ASSERT_DEBUG(aLocalAddr != TBTDevAddr(), PANIC(KBTBackupPanicCat, EBTBURMgrMissingLocalAddress)); + + LoadRestoreDataL(); + + // Compare local address held in restore file with our local address + if (iRegistryData->IsLocalAddressEqualL(aLocalAddr)) + { + // Proceed with restore of remote devices table + CBTRegistry& registry = iManServer.Registry(); + + TInt noRemoteDevices = iRegistryData->CountRemoteDevicesL(); + for (TInt i = 0; i < noRemoteDevices; i++) + { + if (iRegistryData->WriteRemoteDeviceToRegistryL(registry, i)) + { + NotifyRemoteTableChangeL(iRegistryData->GetRemoteDeviceL(i).BDAddr()); + } + } + } + } + +void CBTRestoreHandler::LoadRestoreDataL() + { + LOG_FUNC + + // Read restore file + RFs fsSession; + LEAVEIFERRORL(fsSession.Connect()); + CleanupClosePushL(fsSession); + LEAVEIFERRORL(fsSession.SetSessionToPrivate(fsSession.GetSystemDrive())); + // Assuming private directory exists at this point + + RFileReadStream fStream; + LEAVEIFERRORL(fStream.Open(fsSession, KBTManServerRestoreFileName, EFileRead)); + fStream.PushL(); + + // Read in data + iRegistryData->ReadFromStreamL(fStream); + + // Cleanup + CleanupStack::PopAndDestroy(2, &fsSession); //fStream and fsSession + } + +/** +Sends a notification that the persistence table has been changed. +The notification is observable through the P&S key KPropertyKeyBluetoothGetRegistryTableChange. +**/ +void CBTRestoreHandler::NotifyLocalTableChange() + { + LOG_FUNC + + // Notify the P&S key that the remote devices table has changed + iManServer.Publish(KPropertyKeyBluetoothGetRegistryTableChange, KRegistryChangeLocalTable); + } + +/** +Sends a notification that a device in the remote devices table has been changed. +The notification is observable through the P&S key KPropertyKeyBluetoothGetRegistryTableChange. +Interested parties can also use RBTRegistry::NotifyViewChange() to detect if the change affects their view. +**/ +void CBTRestoreHandler::NotifyRemoteTableChangeL(const TBTDevAddr& aAddress) + { + LOG_FUNC + + // Construct SQL constraint which selects the device + RBTDbQuery query; + CleanupClosePushL(query); + query.FindDeviceL(aAddress); + + HBufC* conDes = query.ConstraintBuf().AllocLC(); + + // Notify the P&S key that the remote devices table has changed + iManServer.Publish(KPropertyKeyBluetoothGetRegistryTableChange, KRegistryChangeRemoteTable); + + // Signal notifiers waiting on view change + iManServer.NotifyViewChange(*conDes); + + // Cleanup constDes and query + CleanupStack::PopAndDestroy(2, &query); + } + +/** +CBTRegistryBURData - manages data from the Bluetooth registry that is to be backed up or restored. +**/ +CBTRegistryBURData* CBTRegistryBURData::NewL() + { + LOG_STATIC_FUNC + + CBTRegistryBURData* self = new(ELeave) CBTRegistryBURData(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CBTRegistryBURData::CBTRegistryBURData() + : iHasRegistryData(EFalse) + { + LOG_FUNC + } + +CBTRegistryBURData::~CBTRegistryBURData() + { + LOG_FUNC + + if (iRemoteDevices) // Dont use ClearRegistryData() here as leave may have occured in ReadFromRegistryL() or ReadFromStreamL() + { + // Destroy all CBTDevices in iRemoteDevices (necessary before array deletion for CArrayPtrFlat) + iRemoteDevices->ResetAndDestroy(); + } + + delete iLocalDevice; + delete iRemoteDevicesSid; + delete iRemoteDevices; + } + +void CBTRegistryBURData::ConstructL() + { + LOG_FUNC + + iRemoteDevicesSid = new (ELeave) CArrayFixFlat(1); + iRemoteDevices = new(ELeave) CBTDeviceArray(1); + } + +/** +Writes the registry data held in this instance to a given stream. +This does not write those registry fields which contain unset values. +@param aStream The stream to write the registry data to. +**/ +void CBTRegistryBURData::WriteToStreamL(RWriteStream& aStream) const + { + LOG_FUNC + + // Writes registry data out to a given stream, avoiding any use of class externalisation. + if (HasRegistryData()) + { + // This follows a specific file-format (tied to the registry version information), which is documented seperately. + + // We should already have the following information for the local device. + __ASSERT_DEBUG(iLocalDevice->IsValidAddress(), PANIC(KBTBackupPanicCat, EBTBURMgrExpectedDataMissing)); + + // Write out version information + aStream.WriteUint32L(iRegistryVersionMajor); + aStream.WriteUint32L(iRegistryVersionMinor); + + // Persistence table: + // Local device address and name only (both are mandatory). + aStream.WriteL(iLocalDevice->Address().Des(), KBTDevAddrSize); + + __ASSERT_DEBUG(iLocalDevice->DeviceName().Length() <= KMaxTUint8, PANIC(KBTBackupPanicCat, EBTBURMgrDescriptorLengthTooLong)); + aStream.WriteUint8L(iLocalDevice->DeviceName().Length()); + aStream.WriteL(iLocalDevice->DeviceName(), iLocalDevice->DeviceName().Length()); + + // Remote devices table + TInt rdCount=CountRemoteDevicesL(); + + aStream.WriteUint32L(rdCount); + for (TInt i = 0; i < rdCount; i++) + { + const CBTDevice& nextRemDev = GetRemoteDeviceL(i); + const TBTNamelessDevice& nextRemDevNameless = nextRemDev.AsNamelessDevice(); + + __ASSERT_DEBUG(nextRemDev.IsValidBDAddr(), PANIC(KBTBackupPanicCat, EBTBURMgrExpectedDataMissing)); + + // Work out what is set and derive bitmask (can use TBTDeviceSet here as is public) + TUint32 rdSetMask = TBTNamelessDevice::EAddress; + if (nextRemDev.IsValidDeviceClass()) + { + rdSetMask |= TBTNamelessDevice::EDeviceClass; + } + if (nextRemDev.IsValidLinkKey()) + { + rdSetMask |= TBTNamelessDevice::ELinkKey; + } + if (nextRemDev.IsValidGlobalSecurity()) + { + rdSetMask |= TBTNamelessDevice::EGlobalSecurity; + } + if (nextRemDevNameless.IsValidPageScanRepMode()) + { + rdSetMask |= TBTNamelessDevice::EPageScanRepMode; + } + if (nextRemDevNameless.IsValidPageScanMode()) + { + rdSetMask |= TBTNamelessDevice::EPageScanMode; + } + if (nextRemDevNameless.IsValidPageScanPeriodMode()) + { + rdSetMask |= TBTNamelessDevice::EPageScanPeriodMode; + } + if (nextRemDevNameless.IsValidClockOffset()) + { + rdSetMask |= TBTNamelessDevice::EClockOffset; + } + if (nextRemDev.IsValidUsed()) + { + rdSetMask |= TBTNamelessDevice::EUsed; + } + if (nextRemDev.IsValidSeen()) + { + rdSetMask |= TBTNamelessDevice::ESeen; + } + if (nextRemDev.IsValidPassKey()) + { + rdSetMask |= TBTNamelessDevice::EPassKey; + } + if (nextRemDev.IsValidUiCookie()) + { + rdSetMask |= TBTNamelessDevice::EUiCookie; + } + if (nextRemDev.IsValidDeviceName()) + { + rdSetMask |= CBTDevice::EDeviceName; + } + if (nextRemDev.IsValidFriendlyName()) + { + rdSetMask |= CBTDevice::EFriendlyName; + } + // Now write out bitmask + aStream.WriteUint32L(rdSetMask); + + // Write valid setting for next remote device + aStream.WriteUint32L(GetRemoteDeviceEntrySidL(i)); + aStream.WriteL(nextRemDev.BDAddr().Des(), KBTDevAddrSize); + if (rdSetMask & TBTNamelessDevice::EDeviceClass) + { + aStream.WriteUint32L(nextRemDev.DeviceClass().DeviceClass()); + } + if (rdSetMask & TBTNamelessDevice::ELinkKey) + { + const TBTLinkKey& nextRemDevLinkKey = nextRemDev.LinkKey(); + aStream.WriteL(nextRemDevLinkKey, KHCILinkKeySize); + aStream.WriteUint8L(nextRemDev.LinkKeyType()); + } + if (rdSetMask & TBTNamelessDevice::EGlobalSecurity) + { + TBTDeviceSecurity nextRemDevGlobSec = nextRemDev.GlobalSecurity(); + aStream.WriteUint8L(nextRemDevGlobSec.SecurityValue()); + aStream.WriteUint32L(nextRemDevGlobSec.PasskeyMinLength()); + } + if (rdSetMask & TBTNamelessDevice::EPageScanRepMode) + { + aStream.WriteUint8L(nextRemDevNameless.PageScanRepMode()); + } + if (rdSetMask & TBTNamelessDevice::EPageScanMode) + { + aStream.WriteUint8L(nextRemDevNameless.PageScanMode()); + } + if (rdSetMask & TBTNamelessDevice::EPageScanPeriodMode) + { + aStream.WriteUint8L(nextRemDevNameless.PageScanPeriodMode()); + } + if (rdSetMask & TBTNamelessDevice::EClockOffset) + { + aStream.WriteUint16L(nextRemDevNameless.ClockOffset()); + } + if (rdSetMask & TBTNamelessDevice::EUsed) + { + const TInt64& used = nextRemDev.Used().Int64(); + aStream.WriteInt32L(I64HIGH(used)); + aStream.WriteInt32L(I64LOW(used)); + } + if (rdSetMask & TBTNamelessDevice::ESeen) + { + const TInt64& seen = nextRemDev.Seen().Int64(); + aStream.WriteInt32L(I64HIGH(seen)); + aStream.WriteInt32L(I64LOW(seen)); + } + if (rdSetMask & TBTNamelessDevice::EPassKey) + { + const TBTPinCode& nextRemDevPassKey = nextRemDev.PassKey(); + __ASSERT_DEBUG(nextRemDevPassKey.Length() == KHCIPINCodeSize + 1, PANIC(KBTBackupPanicCat, EBTBURMgrDescriptorUnexpectedLength)); + aStream.WriteL(nextRemDevPassKey, KHCIPINCodeSize + 1); + } + if (rdSetMask & TBTNamelessDevice::EUiCookie) + { + aStream.WriteUint32L(nextRemDev.UiCookie()); + } + if (rdSetMask & CBTDevice::EDeviceName) + { + __ASSERT_DEBUG(nextRemDev.DeviceName().Length() <= KMaxTUint8, PANIC(KBTBackupPanicCat, EBTBURMgrDescriptorLengthTooLong)); + aStream.WriteUint8L(nextRemDev.DeviceName().Length()); + aStream.WriteL(nextRemDev.DeviceName(), nextRemDev.DeviceName().Length()); + } + if (rdSetMask & CBTDevice::EFriendlyName) + { + __ASSERT_DEBUG(nextRemDev.FriendlyName().Length() <= KMaxTUint8, PANIC(KBTBackupPanicCat, EBTBURMgrDescriptorLengthTooLong)); + aStream.WriteUint8L(nextRemDev.FriendlyName().Length()); + aStream.WriteL(nextRemDev.FriendlyName(), nextRemDev.FriendlyName().Length()); + } + } + } + else + { + User::Leave(KErrNotFound); + } + } + +/** +Reads registry data from a given stream and stores within this instance. +Any registry data currently held is cleared first. +@param aStream The stream to ready the registry data from. +**/ +void CBTRegistryBURData::ReadFromStreamL(RReadStream& aStream) + { + LOG_FUNC + + // This follows a specific file-format (tied to the registry version information), which is documented seperately. + + // Note that we dont make *ANY* assumptions as to what data should always be available, since the restore file could be corrupt. + // We will fail the restore if it turns out we do not have enough information, or if we have invalid information. + + // WARNING: When a new registry version is produced, this implementaton of backup/restore support will need modification. + // This assert should be updated to include all supported registry versions. + __ASSERT_DEBUG(KRegistryDBVersionMajor == 1 && KRegistryDBVersionMinor == 2, PANIC(KBTBackupPanicCat, EBTBURMgrUnsupportedRegistryVersion)); + + // Extract version information and continue if we can handle it. + TUint32 regVersionMajor = aStream.ReadUint32L(); + TUint32 regVersionMinor = aStream.ReadUint32L(); + if (regVersionMajor == KRegistryDBVersionMajor && regVersionMinor == KRegistryDBVersionMinor) + { + // We support this version and this version only - read in registry data + ClearRegistryData(); + + iLocalDevice = new(ELeave) TBTLocalDevice; + + // Note version information for this registry + iRegistryVersionMajor = regVersionMajor; + iRegistryVersionMinor = regVersionMinor; + + // Persistence table: + // Local device address and name only (both fields are mandatory). + TBTDevAddr address; + TPtr8 addrPtr(address.Des()); + aStream.ReadL(addrPtr, KBTDevAddrSize); + if (addrPtr.Length() == KBTDevAddrSize) + { + iLocalDevice->SetAddress(address); + } + else + { + User::Leave(KErrCorrupt); + } + + TInt deviceNameLength = static_cast(aStream.ReadUint8L()); + if (deviceNameLength <= KMaxBluetoothNameLen) + { + RBuf8 deviceName; + deviceName.CreateL(KMaxBluetoothNameLen); + CleanupClosePushL(deviceName); + + aStream.ReadL(deviceName,deviceNameLength); + if (deviceName.Length() == deviceNameLength) + { + iLocalDevice->SetDeviceName(deviceName); + } + else + { + User::Leave(KErrCorrupt); + } + CleanupStack::PopAndDestroy(&deviceName); + } + else + { + User::Leave(KErrCorrupt); + } + + // Remote devices table: + TInt rdCount = aStream.ReadUint32L(); + for (TInt i = 0; i < rdCount; i++) + { + // First read bitmask of available data + TUint32 rdSetMask = aStream.ReadUint32L(); + + // Then read available data from file and store + CBTDevice *rdInstance = CBTDevice::NewLC(); + TBTNamelessDevice& rdNamelessDevInstance = rdInstance->AsNamelessDevice(); + TSecureId rdSid = aStream.ReadUint32L(); + + // Remote BT address is mandatory + if (rdSetMask & TBTNamelessDevice::EAddress) + { + TBTDevAddr rdAddr; + TPtr8 rdAddrPtr(rdAddr.Des()); + aStream.ReadL(rdAddrPtr, KBTDevAddrSize); + + // Ensure address is of required length and is non-zero + if (rdAddrPtr.Length() == KBTDevAddrSize && rdAddr != TBTDevAddr()) + { + rdInstance->SetDeviceAddress(rdAddr); + } + else + { + User::Leave(KErrCorrupt); + } + } + else + { + User::Leave(KErrCorrupt); + } + + if (rdSetMask & TBTNamelessDevice::EDeviceClass) + { + TBTDeviceClass rdClass = TBTDeviceClass(aStream.ReadUint32L()); + rdInstance->SetDeviceClass(rdClass); + } + + if (rdSetMask & TBTNamelessDevice::ELinkKey) + { + TBTLinkKey rdLinkKey; + aStream.ReadL(rdLinkKey, KHCILinkKeySize); + if (rdLinkKey.Length() == KHCILinkKeySize) + { + TUint8 rdLinkKeyType = static_cast(aStream.ReadUint8L()); + // Ensure value is in the valid range (ELinkKeyCombination is zero so (pointless) comparison with this gives warnings). + if (rdLinkKeyType <= ELinkKeyDebug) + { + rdInstance->SetLinkKey(rdLinkKey, static_cast(rdLinkKeyType)); + } + else + { + User::Leave(KErrCorrupt); + } + + } + else + { + User::Leave(KErrCorrupt); + } + } + + if (rdSetMask & TBTNamelessDevice::EGlobalSecurity) + { + TBTDeviceSecurity rdGlobSec; + TUint8 globSecValue = aStream.ReadUint8L(); + // Ensure value is in the valid range (lower value is zero so (pointless) comparison with this gives warnings). + if (globSecValue <= KBTBURMgrMaxGlobalSecurityValue) + { + rdGlobSec.SetSecurityValue(globSecValue); + + TUint32 passKeyMinLen = aStream.ReadUint32L(); + + if (passKeyMinLen <= KHCIPINCodeSize) + { + rdGlobSec.SetPasskeyMinLength(passKeyMinLen); + rdInstance->SetGlobalSecurity(rdGlobSec); + } + else + { + User::Leave(KErrCorrupt); + } + } + else + { + User::Leave(KErrCorrupt); + } + } + + if (rdSetMask & TBTNamelessDevice::EPageScanRepMode) + { + TUint8 rdPageScanRepMode = aStream.ReadUint8L(); + // Ensure value is in the valid range (lower value is zero so (pointless) comparison with this gives warnings). + if (rdPageScanRepMode <= EPageScanModeR2) + { + rdNamelessDevInstance.SetPageScanRepMode(rdPageScanRepMode); + } + else + { + User::Leave(KErrCorrupt); + } + } + + if (rdSetMask & TBTNamelessDevice::EPageScanMode) + { + TUint8 rdPageScanMode = aStream.ReadUint8L(); + // Ensure value is in the valid range (lower value is zero so (pointless) comparison with this gives warnings). + if (rdPageScanMode <= KBTBURMgrMaxPageScanMode) + { + rdNamelessDevInstance.SetPageScanMode(rdPageScanMode); + } + else + { + User::Leave(KErrCorrupt); + } + } + + if (rdSetMask & TBTNamelessDevice::EPageScanPeriodMode) + { + TUint8 rdPageScanPeriodMode = aStream.ReadUint8L(); + // Ensure value is in the valid range (lower value is zero so (pointless) comparison with this gives warnings). + if (rdPageScanPeriodMode <= KBTBURMgrMaxPageScanPeriodMode) + { + rdNamelessDevInstance.SetPageScanPeriodMode(rdPageScanPeriodMode); + } + else + { + User::Leave(KErrCorrupt); + } + } + + if (rdSetMask & TBTNamelessDevice::EClockOffset) + { + TUint16 rdClockOffset = aStream.ReadUint16L(); + rdNamelessDevInstance.SetClockOffset(rdClockOffset); + } + + if (rdSetMask & TBTNamelessDevice::EUsed) + { + TInt32 usedU = aStream.ReadInt32L(); + TInt32 usedL = aStream.ReadInt32L(); + TInt64 rdUsed = MAKE_TINT64(usedU, usedL); + rdNamelessDevInstance.SetUsed(rdUsed); + } + + if (rdSetMask & TBTNamelessDevice::ESeen) + { + TInt32 seenU = aStream.ReadInt32L(); + TInt32 seenL = aStream.ReadInt32L(); + TInt64 rdSeen = MAKE_TINT64(seenU, seenL); + rdNamelessDevInstance.SetSeen(rdSeen); + } + + if (rdSetMask & TBTNamelessDevice::EPassKey) + { + TBTPinCode rdPassKey; + aStream.ReadL(rdPassKey, KHCIPINCodeSize + 1); + if (rdPassKey.Length() == KHCIPINCodeSize + 1) + { + rdInstance->SetPassKey(rdPassKey); + } + else + { + User::Leave(KErrCorrupt); + } + } + + if (rdSetMask & TBTNamelessDevice::EUiCookie) + { + TUint32 rdUiCookie = aStream.ReadUint32L(); + rdNamelessDevInstance.SetUiCookie(rdUiCookie); + } + + if (rdSetMask & CBTDevice::EDeviceName) + { + TInt rdNameLen = static_cast(aStream.ReadUint8L()); + if (rdNameLen <= KMaxBluetoothNameLen) + { + RBuf8 rdName; + rdName.CreateL(KMaxBluetoothNameLen); + CleanupClosePushL(rdName); + + aStream.ReadL(rdName, rdNameLen); + if (rdName.Length() == rdNameLen) + { + rdInstance->SetDeviceNameL(rdName); + } + else + { + User::Leave(KErrCorrupt); + } + CleanupStack::PopAndDestroy(&rdName); + } + else + { + User::Leave(KErrCorrupt); + } + } + + if (rdSetMask & CBTDevice::EFriendlyName) + { + TInt rdFriendlyNameLen = static_cast(aStream.ReadUint8L()); + if (rdFriendlyNameLen <= KMaxFriendlyNameLen) + { + RBuf rdFriendlyName; + rdFriendlyName.CreateL(KMaxFriendlyNameLen); + CleanupClosePushL(rdFriendlyName); + + aStream.ReadL(rdFriendlyName, rdFriendlyNameLen); + if (rdFriendlyName.Length() == rdFriendlyNameLen) + { + rdInstance->SetFriendlyNameL(rdFriendlyName); + } + else + { + User::Leave(KErrCorrupt); + } + CleanupStack::PopAndDestroy(&rdFriendlyName); + } + else + { + User::Leave(KErrCorrupt); + } + } + + // Data now stored, add rdInstance to our remote devices list + iRemoteDevices->AppendL(rdInstance); + iRemoteDevicesSid->AppendL(rdSid); + CleanupStack::Pop(rdInstance); + } + + // Mark that we now have registry data + iHasRegistryData = ETrue; + } + } + +/** +Reads registry data from the registry into this instance. +Any existing registry data held in this instance is cleared first. +@param aRegistry The CBTRegistry instance to use for registry access. +**/ +void CBTRegistryBURData::ReadFromRegistryL(CBTRegistry& aRegistry) + { + LOG_FUNC + + ClearRegistryData(); + + // The meta information from our registry is known. + iRegistryVersionMajor = KRegistryDBVersionMajor; + iRegistryVersionMinor = KRegistryDBVersionMinor; + + // Persistence table + iLocalDevice = aRegistry.GetLocalDeviceL(); + + // Remote device table + // Create a view on the table. + RBTDbQuery query; + CleanupClosePushL(query); + TBTRegistrySearch searchCriteria; + searchCriteria.FindAll(); + query.SearchL(searchCriteria); + TDbBookmark bookmark; + RDbView* view = aRegistry.OpenViewL(query, bookmark); + CleanupCloseDeletePushL(view); + + // Populate iRemoteDevices from the view. + while (!view->AtEnd()) + { + CBTDevice *next = aRegistry.GetNextDeviceL(*view, bookmark, ETrue); + CleanupStack::PushL(next); + + // CBTRegisty::CreatingProcessUidL() requires a rowset with exactly one row. + // So we have to requery for this device to get a singular row. + TDbBookmark singleBookmark; + RDbView* singleView = aRegistry.OpenDeviceL(next->BDAddr(), singleBookmark); + CleanupCloseDeletePushL(singleView); + TSecureId nextSid = aRegistry.CreatingProcessUidL(*singleView); + CleanupStack::PopAndDestroy(singleView); + + iRemoteDevices->AppendL(next); + iRemoteDevicesSid->AppendL(nextSid); + + CleanupStack::Pop(next); // iRemoteDevices now takes ownership + } + + CleanupStack::PopAndDestroy(2, &query); // view and query + + // Mark that we now have registry data + iHasRegistryData = ETrue; + } + +/** +Updates the persistence table of the registry with local device name held in this instance +if the registry currently holds a default name. +@param aRegistry The CBTRegistry instance to use for registry access. +@return ETrue if an update was made to the registry. +**/ +TBool CBTRegistryBURData::WriteLocalDeviceNameToRegistryL(CBTRegistry& aRegistry) const + { + LOG_FUNC + + TBool updateDone = EFalse; + + // Update device name only if the registry has a default name + TBTLocalDevice defaultDevice; + TRAP_IGNORE(aRegistry.GetDefaultDeviceFromIniL(defaultDevice)); + + if (!defaultDevice.IsValidDeviceName()) + { + // Could not obtain a default name - use KDefaultLocalName instead + defaultDevice.SetDeviceName(KDefaultLocalName); + } + + TBTLocalDevice* localDevice = aRegistry.GetLocalDeviceL(); + CleanupStack::PushL(localDevice); + + if (localDevice->DeviceName() == defaultDevice.DeviceName()) + { + // Local device name is default, update with restored value. + localDevice->SetDeviceName(GetLocalDeviceNameL()); + aRegistry.UpdateLocalDeviceL(*localDevice); + updateDone = ETrue; + } + + CleanupStack::PopAndDestroy(localDevice); + + return updateDone; + } + +/** +Updates an entry of the remote devices table of the registry with data held in this instance. +If the remote device already exists in the registry, the registry version is updated only if it +does not hold a link key. +Otherwise, the remote device is added to the registry. +@param aRegistry The CBTRegistry instance to use for registry access. +@param aDeviceIndex The remote device held in this CBTRegistryBURData instance to be written to the registry. +@return ETrue if an update was made to the registry. +**/ +TBool CBTRegistryBURData::WriteRemoteDeviceToRegistryL(CBTRegistry& aRegistry, TInt aDeviceIndex) const + { + LOG_FUNC + + TBool updateDone = EFalse; + + // Get device and SID + const CBTDevice& nextRemDevice = GetRemoteDeviceL(aDeviceIndex); + TSecureId nextRemDeviceSid = GetRemoteDeviceEntrySidL(aDeviceIndex); + + // Try to add device to registry. If this fails with KErrAlreadExists, then update existing device. + TRAPD(err, aRegistry.CreateDeviceL(nextRemDevice, nextRemDevice.IsValidUiCookie(), nextRemDeviceSid)); + + if (err == KErrNone) + { + // New device added successfully + updateDone = ETrue; + } + else if (err == KErrAlreadyExists) + { + // Device already exists. Extract and examine + TDbBookmark bookmark; + RDbView* view = aRegistry.OpenDeviceL(nextRemDevice.BDAddr(), bookmark); + CleanupCloseDeletePushL(view); + CBTDevice *regDev = aRegistry.GetNextDeviceL(*view, bookmark, ETrue); + CleanupStack::PushL(regDev); + + if (!regDev->IsValidLinkKey()) + { + // No link key - safe to restore remote device from file. + view->FirstL(); + aRegistry.UpdateDeviceL(*view, nextRemDevice); + updateDone = ETrue; + } + + CleanupStack::PopAndDestroy(2, view); + } + else + { + // Unexpected error - pass upward for handling + User::Leave(err); + } + + return updateDone; + } + +void CBTRegistryBURData::GetRegistryVersionL(TUint32& aRegistryVersionMajor, TUint32& aRegistryVersionMinor) const + { + LOG_FUNC + + if (!HasRegistryData()) + { + User::Leave(KErrNotFound); + } + + aRegistryVersionMajor = iRegistryVersionMajor; + aRegistryVersionMinor = iRegistryVersionMinor; + } + +const TDesC8& CBTRegistryBURData::GetLocalDeviceNameL() const + { + LOG_FUNC + + if (!HasRegistryData()) + { + User::Leave(KErrNotFound); + } + + __ASSERT_DEBUG(iLocalDevice, PANIC(KBTBackupPanicCat, EBTBURMgrExpectedDataMissing)); + return iLocalDevice->DeviceName(); + } + +TBool CBTRegistryBURData::IsLocalAddressNonZeroL() const + { + LOG_FUNC + + TBTDevAddr zeroAddr; + return !IsLocalAddressEqualL(zeroAddr); + } + +TBool CBTRegistryBURData::IsLocalAddressEqualL(TBTDevAddr& aAddr) const + { + LOG_FUNC + + if (!HasRegistryData()) + { + User::Leave(KErrNotFound); + } + + __ASSERT_DEBUG(iLocalDevice, PANIC(KBTBackupPanicCat, EBTBURMgrExpectedDataMissing)); + return (iLocalDevice->Address() == aAddr); + } + +TInt CBTRegistryBURData::CountRemoteDevicesL() const + { + LOG_FUNC + + if (!HasRegistryData()) + { + User::Leave(KErrNotFound); + } + + __ASSERT_DEBUG(iRemoteDevices->Count() == iRemoteDevicesSid->Count(), PANIC(KBTBackupPanicCat, EBTBURMgrArraySizeMisMatch)); + return iRemoteDevices->Count(); + } + +const CBTDevice& CBTRegistryBURData::GetRemoteDeviceL(TInt aDeviceIndex) const + { + LOG_FUNC + + if (!HasRegistryData() || !((aDeviceIndex >= 0) && (aDeviceIndex < iRemoteDevices->Count()))) + { + User::Leave(KErrNotFound); + } + + __ASSERT_DEBUG(iRemoteDevices->Count() == iRemoteDevicesSid->Count(), PANIC(KBTBackupPanicCat, EBTBURMgrArraySizeMisMatch)); + return *(iRemoteDevices->At(aDeviceIndex)); + } + +TSecureId CBTRegistryBURData::GetRemoteDeviceEntrySidL(TInt aDeviceIndex) const + { + LOG_FUNC + + if (!HasRegistryData() || !((aDeviceIndex >= 0) && (aDeviceIndex < iRemoteDevicesSid->Count()))) + { + User::Leave(KErrNotFound); + } + + __ASSERT_DEBUG(iRemoteDevices->Count() == iRemoteDevicesSid->Count(), PANIC(KBTBackupPanicCat, EBTBURMgrArraySizeMisMatch)); + return iRemoteDevicesSid->At(aDeviceIndex); + } + +/** +Clears any registry data stored internally within this instance. +If no data is stored, this method does nothing. +**/ +void CBTRegistryBURData::ClearRegistryData() + { + LOG_FUNC + + // This is a no-op if we have no registry data to clear + if (HasRegistryData()) + { + // Clear data held previously + iRemoteDevicesSid->Reset(); + iRemoteDevices->ResetAndDestroy(); + delete iLocalDevice; + iLocalDevice = NULL; + + iHasRegistryData = EFalse; + } + } + +/** +CBTLocalAddressFetcher - Fetches the local device address, or waits for the addresss to become available, and +passes to CBTManServerBURMgr. +**/ +CBTLocalAddressFetcher* CBTLocalAddressFetcher::NewL(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry, TInt aPriority) + { + LOG_STATIC_FUNC + + CBTLocalAddressFetcher* result = new(ELeave) CBTLocalAddressFetcher(aBURMgr, aRegistry, aPriority); + CleanupStack::PushL(result); + result->ConstructL(); + CleanupStack::Pop(result); + return result; + } + +CBTLocalAddressFetcher::CBTLocalAddressFetcher(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry, TInt aPriority) + : CActive(aPriority), + iBURMgr(aBURMgr), + iRegistry(aRegistry) + { + LOG_FUNC + + CActiveScheduler::Add(this); + } + +CBTLocalAddressFetcher::~CBTLocalAddressFetcher() + { + LOG_FUNC + + // Cancel any outstanding requests + Cancel(); + iProperty.Close(); + } + +void CBTLocalAddressFetcher::ConstructL() + { + LOG_FUNC + + // Attach to KPropertyKeyBluetoothGetLocalDeviceAddress + LEAVEIFERRORL(iProperty.Attach(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothGetLocalDeviceAddress)); + } + +void CBTLocalAddressFetcher::FetchLocalAddress() + { + LOG_FUNC + + // Subscribe for local address, in case we need to wait + SubscribeToGetLocalDeviceAddressKey(); + + // Attempt to read the BT address from KPropertyKeyBluetoothGetLocalDeviceAddress key + // If key is not found or yields a zero address then try the registry. + // If the registry also holds a zero address then wait for notification from the P&S key. + TBuf8 btAddrDes; + TBTDevAddr btAddr; + TInt err = iProperty.Get(btAddrDes); + + if (err != KErrNone) + { + // Key does not exist or could not be read. + // Stack may not be loaded, so now try registry. + // Ignore any errors; if we can't read this now then we will wait for the stack. + TRAP_IGNORE(btAddr = GetLocalAddressFromRegistryL()); + } + else + { + // Convert btAddrDes to TBTDevAddr if it has the required size. + if (btAddrDes.Length() == KBTDevAddrSize) + { + btAddr = btAddrDes; + } + + if (btAddr == TBTDevAddr()) + { + // Key exists, so stack is loaded, but address is zero, so now try registry + // Ignore any errors; if we can't read this now then we will wait for the stack. + TRAP_IGNORE(btAddr = GetLocalAddressFromRegistryL()); + } + } + + // We have tried our best to get the local address. + // If this is non-zero, provide to CBTManServerBURMgr instance. + // Otherwise, wait on P&S key + if (btAddr != TBTDevAddr()) + { + // We have a non-zero address. + // Cancel subscription and inform CBTManServerBURMgr. + Cancel(); + iBURMgr.SetLocalAddress(btAddr); + } + } + +void CBTLocalAddressFetcher::SubscribeToGetLocalDeviceAddressKey() + { + LOG_FUNC + + // Subscribe to KPropertyKeyBluetoothGetLocalDeviceAddress key + iProperty.Subscribe(iStatus); + SetActive(); + } + +TBTDevAddr CBTLocalAddressFetcher::GetLocalAddressFromRegistryL() + { + LOG_FUNC + + TBTLocalDevice* regLocalDevice=iRegistry.GetLocalDeviceL(); + TBTDevAddr result=regLocalDevice->Address(); + delete regLocalDevice; + + return result; + } + +void CBTLocalAddressFetcher::RunL() + { + LOG_FUNC + + if (iStatus == KErrNone) + { + // Obtain address and send to CBTManServerBURMgr + TBuf8 btAddrDes; + TBTDevAddr btAddr; + TInt err = iProperty.Get(btAddrDes); + + __ASSERT_DEBUG(err == KErrNone, PANIC(KBTBackupPanicCat, EBTBURMgrUnexpectedRPropertyError)); + + if (err == KErrNone) + { + btAddr = btAddrDes; + iBURMgr.SetLocalAddress(btAddr); + } + } + } + +void CBTLocalAddressFetcher::DoCancel() + { + LOG_FUNC + + // Cancel our subscription + iProperty.Cancel(); + } + +/** +CBTActiveBackupDataClient - Active callback implementation (for restore notification) +**/ +CBTActiveBackupDataClient* CBTActiveBackupDataClient::NewL(CBTManServerBURMgr& aBURMgr) + { + LOG_STATIC_FUNC + + CBTActiveBackupDataClient* result = new (ELeave) CBTActiveBackupDataClient(aBURMgr); + return result; + } + +CBTActiveBackupDataClient::CBTActiveBackupDataClient(CBTManServerBURMgr& aBURMgr) + : iBURMgr(aBURMgr) + { + LOG_FUNC + } + +CBTActiveBackupDataClient::~CBTActiveBackupDataClient() + { + LOG_FUNC + } + +// Backup methods (not used) +void CBTActiveBackupDataClient::AllSnapshotsSuppliedL() + { + LOG_FUNC + + //Not supported + User::Leave(KErrNotSupported); + } + +void CBTActiveBackupDataClient::ReceiveSnapshotDataL(TDriveNumber /*aDrive*/, TDesC8& /*aBuffer*/, TBool /*aLastSection*/) + { + LOG_FUNC + + //Not supported + User::Leave(KErrNotSupported); + } + +TUint CBTActiveBackupDataClient::GetExpectedDataSize(TDriveNumber /*aDrive*/) + { + LOG_FUNC + + //Not supported - so expected size can be 0 + return 0; + } + +void CBTActiveBackupDataClient::GetSnapshotDataL(TDriveNumber /*aDrive*/, TPtr8& /*aBuffer*/, TBool& /*aFinished*/) + { + LOG_FUNC + + //Not supported + User::Leave(KErrNotSupported); + } + +void CBTActiveBackupDataClient::InitialiseGetBackupDataL(TDriveNumber /*aDrive*/) + { + LOG_FUNC + + //Not supported + User::Leave(KErrNotSupported); + } + +void CBTActiveBackupDataClient::GetBackupDataSectionL(TPtr8& /*aBuffer*/, TBool& /*aFinished*/) + { + LOG_FUNC + + //Not supported + User::Leave(KErrNotSupported); + } + +//Restore methods (only the notification method RestoreComplete() is used) + +void CBTActiveBackupDataClient::InitialiseRestoreBaseDataL(TDriveNumber /*aDrive*/) + { + LOG_FUNC + + //Note that we are doing a base restore. + User::Leave(KErrNotSupported); + } + +void CBTActiveBackupDataClient::RestoreBaseDataSectionL(TDesC8& /*aBuffer*/, TBool /*aFinished*/) + { + LOG_FUNC + + //Not supported + User::Leave(KErrNotSupported); + } + +void CBTActiveBackupDataClient::InitialiseRestoreIncrementDataL(TDriveNumber /*aDrive*/) + { + LOG_FUNC + + //Not supported + User::Leave(KErrNotSupported); + } + +void CBTActiveBackupDataClient::RestoreIncrementDataSectionL(TDesC8& /*aBuffer*/, TBool /*aFinished*/) + { + LOG_FUNC + + //Not supported + User::Leave(KErrNotSupported); + } + +void CBTActiveBackupDataClient::RestoreComplete(TDriveNumber aDrive) + { + LOG_FUNC + + // Allow CBTManServerBURMgr instance to handle arrival of restore file. + if (aDrive == RFs::GetSystemDrive()) + { + iBURMgr.RestoreFileReady(); + } + } + + +//General methods + +void CBTActiveBackupDataClient::TerminateMultiStageOperation() + { + LOG_FUNC + + //Dont care - we will see the operation is cancelled when normal or unset mode is invoked. + } + +//Test methods + +TUint CBTActiveBackupDataClient::GetDataChecksum(TDriveNumber /*aDrive*/) + { + LOG_FUNC + + //Return an invariant checksum + return 0; + } diff -r 8a27654f7b62 -r 20fda83a6398 bluetoothmgmt/btmgr/BTManServer/btmanserverburmgr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothmgmt/btmgr/BTManServer/btmanserverburmgr.h Mon Mar 15 12:44:59 2010 +0200 @@ -0,0 +1,347 @@ +// Copyright (c) 2010 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: +// Implements backup and restore support for the Bluetooth Manager server. +// + +/** + @file + @internalAll +*/ + +#ifndef BTMANSERVERBURMGR_H +#define BTMANSERVERBURMGR_H + +#include + +#include "BTRegistryDB.h" + +#include "btmanserverburstatemachine.h" + +using namespace conn; + +_LIT(KBTBackupPanicCat, "BTManServer BUR Panic"); +// Used to allow state information to be encoded into a panic code. +const TInt KBTBackupStatePanicMultiplier = 1000000; +const TInt KBTBackupStateMultiplier = 1000; +// Used to seperate the panic and state / event values in a panic code. +const TInt KBTBackupStatePanicMajorDelimiter = 100000; +const TInt KBTBackupStatePanicMinorDelimiter = 100; + +/** +TBTBackupPanic - Panics that may be raised by the BUR manager +**/ +enum TBTBackupPanic + { + EBTBURMgrAlreadyInOperation = 0, // A backup/restore event has been received during an ongoing BUR operation + EBTBURMgrExpectedDataMissing = 1, // An operation has found that it is missing essential data + EBTBURMgrBUROperationStartAlreadyNotified = 2, // An MBTNotify instance has already been told that a BUR operation has started (and has not received a corresponding BUROperationStop notification) + EBTBURMgrBUROperationStartNotNotified = 3, // An MBTNotify instance has been notified that a BUR operation has stopped, without receiving notification that it had started. + + EBTBURMgrNoSessionAdded = 4, // No session has been registered on BTManServer for the BUR manager + EBTBURMgrInvalidRemoteDeviceIndex = 5, // An index for a remote device is invalid. + EBTBURMgrInvalidStateTransition = 6, // An attempted state transition was invalid. + EBTBURMgrInvalidState = 7, // Either the requested state was invalid or the current state is not valid for some operation. + EBTBURMgrInvalidStateIndex = 8, // A given state index is invalid. + EBTBURMgrMissingLocalAddress = 9, // A nonzero local address was expected but not found + EBTBURMgrUnexpectedMethodCall = 10, // A method was unexpectedly called + EBTBURMgrArraySizeMisMatch = 11, // An array does not have the expected size + EBTBURMgrUnknownBUREvent = 12, // An unrecognised backup or restore event was received. + EBTBURMgrActiveBackupClientNull = 13, // A pointer to a CActiveBackupClient instance is unexpectedly NULL + EBTBURMgrUnsupportedRegistryVersion = 14, // A new version of the registry is being used locally, which is not yet supported by this implementation. + EBTBURMgrUnexpectedRPropertyError = 15, // An RProperty::Get() call returned an error that was not expected. + EBTBURMgrInvalidBackupRestoreState = 16, // The masked value from the KUidBackupRestoreKey P&S key was not in the range of the TBURPartType enum. + EBTBURMgrDescriptorLengthTooLong = 17, // A descriptor length is greater than expected. + EBTBURMgrDescriptorUnexpectedLength = 18, // A descriptor length is different to what was expected. + }; + +// The name of the backup file to which the BT registry will be copied to. +_LIT(KBTManServerBackupFileName, "btregistrydb.bak"); +// The name of the restore file from which the BT registry will be restored from. +_LIT(KBTManServerRestoreFileName, "btregistrydb.rst"); + +// Some data range maximum values (where predefined const values are not available elsewhere) +const TUint8 KBTBURMgrMaxGlobalSecurityValue = 0x1F; // All security options on in TBTDeviceSecurity +const TUint8 KBTBURMgrMaxPageScanMode = 0x3; // Optional page scan mode III +const TUint8 KBTBURMgrMaxPageScanPeriodMode = 0x2; // P2 + +void InvalidStateTransitionPanic(TBTBURState aCurrentState, TBTBUREvent aEvent); + + +class MBTBURNotify + { +public: + /** + Invoked by CBTManServerBURMgr to provide notification that a backup or restore + operation has started. + **/ + virtual void BUROperationStarted()=0; + + /** + Invoked by CBTManServerBURMgr to provide notification that a backup or restore + operation has stopped. + **/ + virtual void BUROperationStopped()=0; + + }; + +class CBTManServer; +class CBTLocalAddressFetcher; +class CBTBackupHandler; +class CBTRestoreHandler; +class CBTActiveBackupDataClient; + +NONSHARABLE_CLASS(CBTManServerBURMgr) : public CActive + { +public: + static CBTManServerBURMgr* NewL(CBTManServer& aBTManServer, MBTBURNotify* aBURNotify, TInt aPriority=EPriorityStandard); + ~CBTManServerBURMgr(); + + void RequestBURNotification(MBTBURNotify* aBURNotify); + void SetLocalAddress(TBTDevAddr& aLocalAddr); + void RestoreFileReady(); + + // Implementation of normal state action + void HandleStateNormal(); + + // Implementation of backup state-specific actions. + void HandleStateBackupRequestL(); + void HandleStateBackupRequestError(); + void HandleStateBackupOngoingL(); + void HandleStateBackupOngoingError(); + void HandleStateBackupIgnore(); + + // Implementation of restore state-specific actions. + void HandleStateRestoreRequestL(); + void HandleStateRestoreRequestError(); + void HandleStateRestoreOngoingL(); + void HandleStateRestoreOngoingError(); + void HandleStateRestoreIgnore(); + + // Implementation of restore file processing state-specific actions. + void HandleStateProcessRestoreFileL(); + void HandleStateProcessRestoreFileError(TInt aError); + void HandleStateRestoreFileProcessingComplete(); + + inline TInt TransitionState(TBTBUREvent aBUREvent); + +private: + CBTManServerBURMgr(CBTManServer& aBTManServer, MBTBURNotify* aBURNotify, TInt aPriority); + void ConstructL(); + + TBURPartType GetBURPartType(TInt aValue); + + TBool RestoreFilePresent(); + void CheckForRestoreFileL(); + + void SubscribeToBackupRestoreKey(); + void ProcessBackupState(TBURPartType aBURStateValue); + TBool DoesBURAffectMeL(CActiveBackupClient& aClient); + + void NotifyBUROperationStarted(); + void NotifyBUROperationStopped(); + void NotifyAnyBUROperationStopped(); + + void DeleteFile(const TDesC& fileName); + void DeleteBackupFile(); + void DeleteRestoreFile(); + + void RenameBackupFileForRestore(); + void UpdateLocalDeviceNameL(); + + // From CActive: + void RunL(); + TInt RunError(TInt aError); + void DoCancel(); + +private: + CBTManServer& iBTManServer; + MBTBURNotify* iBURNotify; // Does not own this object. + + TBURPartType iBURState; + + CActiveBackupClient* iActiveBackupClient; + RProperty iProperty; + CBTLocalAddressFetcher* iLocalAddrFetcher; + + CBTManServerBURMgrStateFactory* iStateMachine; + + CBTActiveBackupDataClient* iActiveBackupDataClient; + + TBool iBUROperationStartNotified; + + CBTBackupHandler* iBackupHandler; + CBTRestoreHandler* iRestoreHandler; + + TBTDevAddr iLocalAddr; + + }; + +class CBTRegistryBURData; + +NONSHARABLE_CLASS(CBTBackupHandler) : public CBase + { +public: + static CBTBackupHandler* NewL(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry); + ~CBTBackupHandler(); + + void CreateBackupFileL(); + +private: + CBTBackupHandler(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry); + void ConstructL(); + +private: + CBTManServerBURMgr& iBURMgr; + CBTRegistry& iRegistry; + CBTRegistryBURData* iRegistryData; + }; + +NONSHARABLE_CLASS(CBTRestoreHandler) : public CBase + { +public: + static CBTRestoreHandler* NewL(CBTManServerBURMgr& aBURMgr, CBTManServer& aManServer); + ~CBTRestoreHandler(); + + void RestoreLocalDeviceNameL(); + void RestoreRemoteDeviceTableL(TBTDevAddr& aLocalAddr); + +private: + CBTRestoreHandler(CBTManServerBURMgr& aBURMgr, CBTManServer& aManServer); + void ConstructL(); + + void LoadRestoreDataL(); + + void NotifyLocalTableChange(); + void NotifyRemoteTableChangeL(const TBTDevAddr& aAddress); + +private: + CBTManServerBURMgr& iBURMgr; + CBTManServer& iManServer; + CBTRegistryBURData* iRegistryData; + + TBTDevAddr iBTLocalAddr; + }; + + +NONSHARABLE_CLASS(CBTRegistryBURData) : public CBase + { +public: + static CBTRegistryBURData* NewL(); + ~CBTRegistryBURData(); + + void WriteToStreamL(RWriteStream& aStream) const; + void ReadFromStreamL(RReadStream& aStream); + + void ReadFromRegistryL(CBTRegistry& aRegistry); + TBool WriteLocalDeviceNameToRegistryL(CBTRegistry& aRegistry) const; + TBool WriteRemoteDeviceToRegistryL(CBTRegistry& aRegistry, TInt aDeviceIndex) const; + + inline TBool HasRegistryData() const; + + void GetRegistryVersionL(TUint32& aRegistryVersionMajor, TUint32& aRegistryVersionMinor) const; + TBool IsLocalAddressNonZeroL() const; + TBool IsLocalAddressEqualL(TBTDevAddr& aAddr) const; + TInt CountRemoteDevicesL() const; + const CBTDevice& GetRemoteDeviceL(TInt aDeviceIndex) const; + TSecureId GetRemoteDeviceEntrySidL(TInt aDeviceIndex) const; + + void ClearRegistryData(); + +private: + CBTRegistryBURData(); + void ConstructL(); + + const TDesC8& GetLocalDeviceNameL() const; + +private: + TBool iHasRegistryData; + + // Meta table: + TUint32 iRegistryVersionMajor; + TUint32 iRegistryVersionMinor; + + // Persistence table + TBTLocalDevice* iLocalDevice; + + // Remote device table: + CArrayFixFlat* iRemoteDevicesSid; + CBTDeviceArray* iRemoteDevices; + + }; + +NONSHARABLE_CLASS(CBTLocalAddressFetcher) : public CActive + { +public: + // High priority to ensure this AO fires before a client request to BTManServer + static CBTLocalAddressFetcher* NewL(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry, TInt aPriority=EPriorityHigh); + ~CBTLocalAddressFetcher(); + + void FetchLocalAddress(); + + +private: + CBTLocalAddressFetcher(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry, TInt aPriority); + void ConstructL(); + + void SubscribeToGetLocalDeviceAddressKey(); + TBTDevAddr GetLocalAddressFromRegistryL(); + + // From CActive + void RunL(); + void DoCancel(); +private: + CBTManServerBURMgr& iBURMgr; + CBTRegistry& iRegistry; + RProperty iProperty; + + }; + +NONSHARABLE_CLASS(CBTActiveBackupDataClient) : public CBase, public MActiveBackupDataClient + { +public: + static CBTActiveBackupDataClient* NewL(CBTManServerBURMgr& aBURMgr); + ~CBTActiveBackupDataClient(); + + // Backup methods (not used) + virtual void AllSnapshotsSuppliedL(); + virtual void ReceiveSnapshotDataL(TDriveNumber aDrive, TDesC8& aBuffer, TBool aLastSection); + virtual TUint GetExpectedDataSize(TDriveNumber aDrive); + virtual void GetSnapshotDataL(TDriveNumber aDrive, TPtr8& aBuffer, TBool& aFinished); + virtual void InitialiseGetBackupDataL(TDriveNumber aDrive); + virtual void GetBackupDataSectionL(TPtr8& aBuffer, TBool& aFinished); + + // Restore methods (only the notification method RestoreComplete() is used) + virtual void InitialiseRestoreBaseDataL(TDriveNumber aDrive); + virtual void RestoreBaseDataSectionL(TDesC8& aBuffer, TBool aFinished); + virtual void InitialiseRestoreIncrementDataL(TDriveNumber aDrive); + virtual void RestoreIncrementDataSectionL(TDesC8& aBuffer, TBool aFinished); + virtual void RestoreComplete(TDriveNumber aDrive); + + // General methods + virtual void TerminateMultiStageOperation(); + + // Test methods + virtual TUint GetDataChecksum(TDriveNumber aDrive); + +private: + CBTActiveBackupDataClient(CBTManServerBURMgr& aBURMgr); + +private: + CBTManServerBURMgr& iBURMgr; + + }; + +#include "btmanserverburmgr.inl" + +#endif //BTMANSERVERBURMGR_H diff -r 8a27654f7b62 -r 20fda83a6398 bluetoothmgmt/btmgr/BTManServer/btmanserverburmgr.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothmgmt/btmgr/BTManServer/btmanserverburmgr.inl Mon Mar 15 12:44:59 2010 +0200 @@ -0,0 +1,36 @@ +// Copyright (c) 2010 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: +// Implements backup and restore support for the Bluetooth Manager server. +// + + +inline TInt CBTManServerBURMgr::TransitionState(TBTBUREvent aBUREvent) + { + return iStateMachine->TransitionState(aBUREvent); + } + +inline TBool CBTRegistryBURData::HasRegistryData() const + { + return iHasRegistryData; + } + +inline TBTBURState CBTManServerBURMgrStateFactory::GetCurrentState() + { + return iState; + } + +inline TBTBURState CBTManServerBURMgrStateAction::GetThisState() + { + return iState; + } diff -r 8a27654f7b62 -r 20fda83a6398 bluetoothmgmt/btmgr/BTManServer/btmanserverburstatemachine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothmgmt/btmgr/BTManServer/btmanserverburstatemachine.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -0,0 +1,682 @@ +// Copyright (c) 2010 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: +// Implements the state machine which drives backup and restore support for the +// Bluetooth Manager server. +// + +#include +#include +#include "btmanserverburmgr.h" + +#include + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, LOG_COMPONENT_BT_MANAGER_SERVER); +#endif + +/** +CBTManServerBURMgrStateFactory - Manages the state machine that drives CBTManServerBURMgr +**/ + +CBTManServerBURMgrStateFactory* CBTManServerBURMgrStateFactory::NewL(CBTManServerBURMgr& aBURMgr) + { + LOG_STATIC_FUNC + + CBTManServerBURMgrStateFactory* result = new (ELeave) CBTManServerBURMgrStateFactory(aBURMgr); + CleanupStack::PushL(result); + result->ConstructL(); + CleanupStack::Pop(result); + return result; + } + +CBTManServerBURMgrStateFactory::CBTManServerBURMgrStateFactory(CBTManServerBURMgr& aBURMgr) + : iBURMgr(aBURMgr), + iState(EBTBURStateNormal) + { + LOG_FUNC + } + +CBTManServerBURMgrStateFactory::~CBTManServerBURMgrStateFactory() + { + LOG_FUNC + + // Destroy state machine + iStateActions.ResetAndDestroy(); + } + +void CBTManServerBURMgrStateFactory::ConstructL() + { + LOG_FUNC + + ConstructStateMachineL(); + } + +void CBTManServerBURMgrStateFactory::ConstructStateMachineL() + { + LOG_FUNC + + // Construct the state instances - each state knows how to carry out its action and its possible transitions + // Note that the ordering here is critical - it must reflect the ordering of the enums in TBTBURState + for (TInt i = EBTBURStateNormal; i < EBTBURStateUnknown; i++) + { + CBTManServerBURMgrStateAction* nextState = ConstructStateLC(static_cast(i)); + iStateActions.AppendL(nextState); + CleanupStack::Pop(nextState); + } + } + +CBTManServerBURMgrStateAction* CBTManServerBURMgrStateFactory::ConstructStateLC(TBTBURState aState) + { + LOG_FUNC + + CBTManServerBURMgrStateAction* result = NULL; + + switch (aState) + { + case EBTBURStateNormal: + result = CBTManServerBURMgrStateNormal::NewLC(); + break; + case EBTBURStateBackupRequest: + result = CBTManServerBURMgrStateBackupRequest::NewLC(); + break; + case EBTBURStateBackupOngoing: + result = CBTManServerBURMgrStateBackupOngoing::NewLC(); + break; + case EBTBURStateBackupIgnore: + result = CBTManServerBURMgrStateBackupIgnore::NewLC(); + break; + case EBTBURStateRestoreRequest: + result = CBTManServerBURMgrStateRestoreRequest::NewLC(); + break; + case EBTBURStateRestoreOngoing: + result = CBTManServerBURMgrStateRestoreOngoing::NewLC(); + break; + case EBTBURStateRestoreIgnore: + result = CBTManServerBURMgrStateRestoreIgnore::NewLC(); + break; + case EBTBURStateProcessRestoreFile: + result = CBTManServerBURMgrStateProcessRestoreFile::NewLC(); + break; + case EBTBURStateRestoreFileProcessingComplete: + result = CBTManServerBURMgrStateRestoreFileProcessingComplete::NewLC(); + break; + default: + // EBTBURStateUnknown + __ASSERT_DEBUG(EFalse, PANIC(KBTBackupPanicCat, EBTBURMgrInvalidStateIndex)); + User::Leave(KErrNotFound); + } + + return result; + } + +/** +Attempts to transition to a new state in the state machine, in response to a given event. +This only succeeds if the event yields a valid transition from the current state. +The transition event EBTBUREventAbortStateAction yields a valid transition for any state, +and this is tested for here. +Upon successful transition, the action associated with the new state is executed. +An invalid state transition in debug mode will result in a panic. In release mode, the current +state is maintained. +@param aTransitionEvent The event driving the state transition. +@return KErrNone if state transition is successful. + KErrNotFound if aTransitionEvent does not yield a valid transition for the current state. +**/ +TInt CBTManServerBURMgrStateFactory::TransitionState(TBTBUREvent aTransitionEvent) + { + LOG_FUNC + + TBTBURState nextState; + + // We allow EBTBUREventAbortStateAction to transition any state back to normal (used for error handling) + if (aTransitionEvent == EBTBUREventAbortStateAction) + { + nextState = EBTBURStateNormal; + } + else + { + nextState = iStateActions[iState]->GetNextState(aTransitionEvent); + } + + // A request to process a restore file may come in at any time, and we may not be in a correct state to deal with it. + // This scenario is not an error, instead the request is simply ignored (as state transition is disallowed) and will be picked up + // when BTManServer next starts. + __ASSERT_DEBUG(nextState != EBTBURStateUnknown || aTransitionEvent == EBTBUREventProcessRestoreFile, InvalidStateTransitionPanic(iState, aTransitionEvent)); + + if (nextState == EBTBURStateUnknown) + { + // Invalid transition + return KErrNotFound; + } + else + { + // Make the transition and execute new state action. + iState = nextState; + ExecuteAction(); + + return KErrNone; + } + } + +/** +Executes the action associated with the current state. +The implementation of the action is given by CBTManServerBURMgrStateAction::ExecuteActionL(). +Error handling is provided by CBTManServerBURMgrStateAction::HandleActionError(). +**/ +void CBTManServerBURMgrStateFactory::ExecuteAction() + { + LOG_FUNC + + TRAPD(err, iStateActions[iState]->ExecuteActionL(iBURMgr)); + if (err != KErrNone) + { + iStateActions[iState]->HandleActionError(iBURMgr, err); + } + } + +/** +CBTManServerBURMgrStateAction - Base class for action/transition handling for states of CBTManServerBURMgr +**/ + +CBTManServerBURMgrStateAction::CBTManServerBURMgrStateAction(TBTBURState aState) + : iState(aState) + { + LOG_FUNC + } + +CBTManServerBURMgrStateAction::~CBTManServerBURMgrStateAction() + { + LOG_FUNC + } + +/** +Handles a leave generated by ExecuteActionL(). +The default implementation is to do nothing. This accomodates states whose implementation of ExecuteActionL() +is guaranteed not to leave. +If a leave does occur, the state must either recover from the error in some way (allowing the state machine to +remain in its current state) or initiate a transition back to the normal state using the EBTBUREventAbortStateAction +transition event (after any necessary cleanup has been performed). +@param aBURMgr The CBTManServerBURMgr instance +@param aError The error which generated the leave in ExecuteActionL() +**/ +void CBTManServerBURMgrStateAction::HandleActionError(CBTManServerBURMgr& /*aBURMgr*/, TInt /*aError*/) + { + LOG_FUNC + + // Do nothing by default (state may not have a leavable action) + } + +/** +CBTManServerBURMgrStateNormal - Action/transition handling for EBTBURStateNormal state of CBTManServerBURMgr +**/ + +CBTManServerBURMgrStateNormal* CBTManServerBURMgrStateNormal::NewLC() + { + LOG_STATIC_FUNC + + CBTManServerBURMgrStateNormal* result = new(ELeave) CBTManServerBURMgrStateNormal(); + CleanupStack::PushL(result); + return result; + } + +CBTManServerBURMgrStateNormal::CBTManServerBURMgrStateNormal() + : CBTManServerBURMgrStateAction(EBTBURStateNormal) + { + LOG_FUNC + } + +CBTManServerBURMgrStateNormal::~CBTManServerBURMgrStateNormal() + { + LOG_FUNC + } + +TBTBURState CBTManServerBURMgrStateNormal::GetNextState(TBTBUREvent aTransitionEvent) + { + LOG_FUNC + + // Valid transition events: EBTBUREventBackup, EBTBUREventRestore, EBTBUREventProcessRestoreFile, EBTBUREventUnset, EBTBUREventNormal + switch (aTransitionEvent) + { + case EBTBUREventBackup: + return EBTBURStateBackupRequest; + case EBTBUREventRestore: + return EBTBURStateRestoreRequest; + case EBTBUREventProcessRestoreFile: + return EBTBURStateProcessRestoreFile; + case EBTBUREventUnset: + // Fall-through + case EBTBUREventNormal: + return EBTBURStateNormal; + default: + // Unknown state (no valid transition) + return EBTBURStateUnknown; + } + } + +void CBTManServerBURMgrStateNormal::ExecuteActionL(CBTManServerBURMgr& aBURMgr) + { + LOG_FUNC + + aBURMgr.HandleStateNormal(); + } + +/** +CBTManServerBURMgrStateBackupRequest - Action/transition handling for EBTBURStateBackupRequest state of CBTManServerBURMgr +**/ + +CBTManServerBURMgrStateBackupRequest* CBTManServerBURMgrStateBackupRequest::NewLC() + { + LOG_STATIC_FUNC + + CBTManServerBURMgrStateBackupRequest* result = new(ELeave) CBTManServerBURMgrStateBackupRequest(); + CleanupStack::PushL(result); + return result; + } + +CBTManServerBURMgrStateBackupRequest::CBTManServerBURMgrStateBackupRequest() + : CBTManServerBURMgrStateAction(EBTBURStateBackupRequest) + { + LOG_FUNC + } + +CBTManServerBURMgrStateBackupRequest::~CBTManServerBURMgrStateBackupRequest() + { + LOG_FUNC + } + +TBTBURState CBTManServerBURMgrStateBackupRequest::GetNextState(TBTBUREvent aTransitionEvent) + { + LOG_FUNC + + // Valid transition events: EBTBUREventBackupProceed, EBTBUREventBackupReject + switch (aTransitionEvent) + { + case EBTBUREventBackupProceed: + return EBTBURStateBackupOngoing; + case EBTBUREventBackupReject: + return EBTBURStateBackupIgnore; + default: + // Unknown state (no valid transition) + return EBTBURStateUnknown; + } + } + +void CBTManServerBURMgrStateBackupRequest::ExecuteActionL(CBTManServerBURMgr& aBURMgr) + { + LOG_FUNC + + aBURMgr.HandleStateBackupRequestL(); + } + +void CBTManServerBURMgrStateBackupRequest::HandleActionError(CBTManServerBURMgr& aBURMgr, TInt /*aError*/) + { + LOG_FUNC + + aBURMgr.HandleStateBackupRequestError(); + } + +/** +CBTManServerBURMgrStateBackupOngoing - Action/transition handling for EBTBURStateBackupOngoing state of CBTManServerBURMgr +**/ + +CBTManServerBURMgrStateBackupOngoing* CBTManServerBURMgrStateBackupOngoing::NewLC() + { + LOG_STATIC_FUNC + + CBTManServerBURMgrStateBackupOngoing* result = new(ELeave) CBTManServerBURMgrStateBackupOngoing(); + CleanupStack::PushL(result); + return result; + } + +CBTManServerBURMgrStateBackupOngoing::CBTManServerBURMgrStateBackupOngoing() + : CBTManServerBURMgrStateAction(EBTBURStateBackupOngoing) + { + LOG_FUNC + } + +CBTManServerBURMgrStateBackupOngoing::~CBTManServerBURMgrStateBackupOngoing() + { + LOG_FUNC + } + +TBTBURState CBTManServerBURMgrStateBackupOngoing::GetNextState(TBTBUREvent aTransitionEvent) + { + LOG_FUNC + + // Valid transition events: EBTBUREventNormal + if (aTransitionEvent == EBTBUREventNormal) + { + return EBTBURStateNormal; + } + else + { + // Unknown state (no valid transition) + return EBTBURStateUnknown; + } + } + +void CBTManServerBURMgrStateBackupOngoing::ExecuteActionL(CBTManServerBURMgr& aBURMgr) + { + LOG_FUNC + + aBURMgr.HandleStateBackupOngoingL(); + } + +void CBTManServerBURMgrStateBackupOngoing::HandleActionError(CBTManServerBURMgr& aBURMgr, TInt /*aError*/) + { + LOG_FUNC + + aBURMgr.HandleStateBackupOngoingError(); + } + +/** +CBTManServerBURMgrStateBackupIgnore - Action/transition handling for EBTBURStateBackupIgnore state of CBTManServerBURMgr +**/ + +CBTManServerBURMgrStateBackupIgnore* CBTManServerBURMgrStateBackupIgnore::NewLC() + { + LOG_STATIC_FUNC + + CBTManServerBURMgrStateBackupIgnore* result = new(ELeave) CBTManServerBURMgrStateBackupIgnore(); + CleanupStack::PushL(result); + return result; + } + +CBTManServerBURMgrStateBackupIgnore::CBTManServerBURMgrStateBackupIgnore() + : CBTManServerBURMgrStateAction(EBTBURStateBackupIgnore) + { + LOG_FUNC + } + +CBTManServerBURMgrStateBackupIgnore::~CBTManServerBURMgrStateBackupIgnore() + { + LOG_FUNC + } + +TBTBURState CBTManServerBURMgrStateBackupIgnore::GetNextState(TBTBUREvent aTransitionEvent) + { + LOG_FUNC + + // Valid transition events: EBTBUREventNormal + if (aTransitionEvent == EBTBUREventNormal) + { + return EBTBURStateNormal; + } + else + { + // Unknown state (no valid transition) + return EBTBURStateUnknown; + } + } + +void CBTManServerBURMgrStateBackupIgnore::ExecuteActionL(CBTManServerBURMgr& aBURMgr) + { + LOG_FUNC + + aBURMgr.HandleStateBackupIgnore(); + } + +/** +CBTManServerBURMgrStateRestoreRequest - Action/transition handling for EBTBURStateRestoreRequest state of CBTManServerBURMgr +**/ + +CBTManServerBURMgrStateRestoreRequest* CBTManServerBURMgrStateRestoreRequest::NewLC() + { + LOG_STATIC_FUNC + + CBTManServerBURMgrStateRestoreRequest* result = new(ELeave) CBTManServerBURMgrStateRestoreRequest(); + CleanupStack::PushL(result); + return result; + } + +CBTManServerBURMgrStateRestoreRequest::CBTManServerBURMgrStateRestoreRequest() + : CBTManServerBURMgrStateAction(EBTBURStateRestoreRequest) + { + LOG_FUNC + } + +CBTManServerBURMgrStateRestoreRequest::~CBTManServerBURMgrStateRestoreRequest() + { + LOG_FUNC + } + +TBTBURState CBTManServerBURMgrStateRestoreRequest::GetNextState(TBTBUREvent aTransitionEvent) + { + LOG_FUNC + + // Valid transition events: EBTBUREventRestoreProceed, EBTBUREventRestoreReject + switch (aTransitionEvent) + { + case EBTBUREventRestoreProceed: + return EBTBURStateRestoreOngoing; + case EBTBUREventRestoreReject: + return EBTBURStateRestoreIgnore; + default: + // Unknown state (no valid transition) + return EBTBURStateUnknown; + } + } + +void CBTManServerBURMgrStateRestoreRequest::ExecuteActionL(CBTManServerBURMgr& aBURMgr) + { + LOG_FUNC + + aBURMgr.HandleStateRestoreRequestL(); + } + +void CBTManServerBURMgrStateRestoreRequest::HandleActionError(CBTManServerBURMgr& aBURMgr, TInt /*aError*/) + { + LOG_FUNC + + aBURMgr.HandleStateRestoreRequestError(); + } + +/** +CBTManServerBURMgrStateRestoreOngoing - Action/transition handling for EBTBURStateRestoreOngoing state of CBTManServerBURMgr +**/ + +CBTManServerBURMgrStateRestoreOngoing* CBTManServerBURMgrStateRestoreOngoing::NewLC() + { + LOG_STATIC_FUNC + + CBTManServerBURMgrStateRestoreOngoing* result = new(ELeave) CBTManServerBURMgrStateRestoreOngoing(); + CleanupStack::PushL(result); + return result; + } + +CBTManServerBURMgrStateRestoreOngoing::CBTManServerBURMgrStateRestoreOngoing() + : CBTManServerBURMgrStateAction(EBTBURStateRestoreOngoing) + { + LOG_FUNC + } + +CBTManServerBURMgrStateRestoreOngoing::~CBTManServerBURMgrStateRestoreOngoing() + { + LOG_FUNC + } + +TBTBURState CBTManServerBURMgrStateRestoreOngoing::GetNextState(TBTBUREvent aTransitionEvent) + { + LOG_FUNC + + // Valid transition events: EBTBUREventNormal + if (aTransitionEvent == EBTBUREventNormal) + { + return EBTBURStateNormal; + } + else + { + // Unknown state (no valid transition) + return EBTBURStateUnknown; + } + } + +void CBTManServerBURMgrStateRestoreOngoing::ExecuteActionL(CBTManServerBURMgr& aBURMgr) + { + LOG_FUNC + + aBURMgr.HandleStateRestoreOngoingL(); + } + +void CBTManServerBURMgrStateRestoreOngoing::HandleActionError(CBTManServerBURMgr& aBURMgr, TInt /*aError*/) + { + LOG_FUNC + + aBURMgr.HandleStateRestoreOngoingError(); + } + +/** +CBTManServerBURMgrStateRestoreIgnore - Action/transition handling for EBTBURStateRestoreIgnore state of CBTManServerBURMgr +**/ + +CBTManServerBURMgrStateRestoreIgnore* CBTManServerBURMgrStateRestoreIgnore::NewLC() + { + LOG_STATIC_FUNC + + CBTManServerBURMgrStateRestoreIgnore* result = new(ELeave) CBTManServerBURMgrStateRestoreIgnore(); + CleanupStack::PushL(result); + return result; + } + +CBTManServerBURMgrStateRestoreIgnore::CBTManServerBURMgrStateRestoreIgnore() + : CBTManServerBURMgrStateAction(EBTBURStateRestoreIgnore) + { + LOG_FUNC + } + +CBTManServerBURMgrStateRestoreIgnore::~CBTManServerBURMgrStateRestoreIgnore() + { + LOG_FUNC + } + +TBTBURState CBTManServerBURMgrStateRestoreIgnore::GetNextState(TBTBUREvent aTransitionEvent) + { + LOG_FUNC + + // Valid transition events: EBTBUREventNormal + if (aTransitionEvent==EBTBUREventNormal) + { + return EBTBURStateNormal; + } + else + { + // Unknown state (no valid transition) + return EBTBURStateUnknown; + } + } + +void CBTManServerBURMgrStateRestoreIgnore::ExecuteActionL(CBTManServerBURMgr& aBURMgr) + { + LOG_FUNC + + aBURMgr.HandleStateRestoreIgnore(); + } + +/** +CBTManServerBURMgrStateProcessRestoreFile - Action/transition handling for EBTBURStateProcessRestoreFile state of CBTManServerBURMgr +**/ + +CBTManServerBURMgrStateProcessRestoreFile* CBTManServerBURMgrStateProcessRestoreFile::NewLC() + { + LOG_STATIC_FUNC + + CBTManServerBURMgrStateProcessRestoreFile* result = new(ELeave) CBTManServerBURMgrStateProcessRestoreFile(); + CleanupStack::PushL(result); + return result; + } + +CBTManServerBURMgrStateProcessRestoreFile::CBTManServerBURMgrStateProcessRestoreFile() + : CBTManServerBURMgrStateAction(EBTBURStateProcessRestoreFile) + { + LOG_FUNC + } + +CBTManServerBURMgrStateProcessRestoreFile::~CBTManServerBURMgrStateProcessRestoreFile() + { + LOG_FUNC + } + +TBTBURState CBTManServerBURMgrStateProcessRestoreFile::GetNextState(TBTBUREvent aTransitionEvent) + { + LOG_FUNC + + // Valid transition event: EBTBUREventProcessRestoreFileComplete + switch (aTransitionEvent) + { + case EBTBUREventProcessRestoreFileComplete: + return EBTBURStateRestoreFileProcessingComplete; + default: + // Unknown state (no valid transition) + return EBTBURStateUnknown; + } + } + +void CBTManServerBURMgrStateProcessRestoreFile::ExecuteActionL(CBTManServerBURMgr& aBURMgr) + { + LOG_FUNC + + aBURMgr.HandleStateProcessRestoreFileL(); + } + +void CBTManServerBURMgrStateProcessRestoreFile::HandleActionError(CBTManServerBURMgr& aBURMgr, TInt aError) + { + LOG_FUNC + + aBURMgr.HandleStateProcessRestoreFileError(aError); + } + +/** +CBTManServerBURMgrStateRestoreFileProcessingComplete - Action/transition handling for EBTBURStateRestoreFileProcessingComplete state of CBTManServerBURMgr +**/ + +CBTManServerBURMgrStateRestoreFileProcessingComplete* CBTManServerBURMgrStateRestoreFileProcessingComplete::NewLC() + { + LOG_STATIC_FUNC + + CBTManServerBURMgrStateRestoreFileProcessingComplete* result = new(ELeave) CBTManServerBURMgrStateRestoreFileProcessingComplete(); + CleanupStack::PushL(result); + return result; + } + +CBTManServerBURMgrStateRestoreFileProcessingComplete::CBTManServerBURMgrStateRestoreFileProcessingComplete() + : CBTManServerBURMgrStateAction(EBTBURStateRestoreFileProcessingComplete) + { + LOG_FUNC + } + +CBTManServerBURMgrStateRestoreFileProcessingComplete::~CBTManServerBURMgrStateRestoreFileProcessingComplete() + { + LOG_FUNC + } + +TBTBURState CBTManServerBURMgrStateRestoreFileProcessingComplete::GetNextState(TBTBUREvent aTransitionEvent) + { + LOG_FUNC + + // Valid transition events: EBTBUREventRestoreFileTransitionNormal + if (aTransitionEvent == EBTBUREventRestoreFileTransitionNormal) + { + return EBTBURStateNormal; + } + else + { + // Unknown state (no valid transition) + return EBTBURStateUnknown; + } + } + +void CBTManServerBURMgrStateRestoreFileProcessingComplete::ExecuteActionL(CBTManServerBURMgr& aBURMgr) + { + LOG_FUNC + aBURMgr.HandleStateRestoreFileProcessingComplete(); + } diff -r 8a27654f7b62 -r 20fda83a6398 bluetoothmgmt/btmgr/BTManServer/btmanserverburstatemachine.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothmgmt/btmgr/BTManServer/btmanserverburstatemachine.h Mon Mar 15 12:44:59 2010 +0200 @@ -0,0 +1,267 @@ +// Copyright (c) 2010 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: +// Implements the state machine which drives backup and restore support for the +// Bluetooth Manager server. +// + +/** + @file + @internalAll +*/ + +#ifndef BTMANSERVERBURSTATEMACHINE_H +#define BTMANSERVERBURSTATEMACHINE_H + +/** +TBTBURState - records the state of the BUR manager. +**/ +enum TBTBURState + { + EBTBURStateNormal, // Waiting for a BUR event + + EBTBURStateBackupRequest, // Processing a backup request + EBTBURStateBackupOngoing, // Taking part in a backup operation + EBTBURStateBackupIgnore, // Not taking part in a backup operation (e.g. operation may not affect us) + + EBTBURStateRestoreRequest, // Processing a restore request + EBTBURStateRestoreOngoing, // Taking part in a restore operation + EBTBURStateRestoreIgnore, // Not taking part in a restore operation (e.g. operation may not affect us) + + EBTBURStateProcessRestoreFile, // Processing an available restore file. + EBTBURStateRestoreFileProcessingComplete, // Processing of restore file has completed and registry has been updated + + EBTBURStateUnknown, // Used to indicate an invalid transition + }; + +/** +TBTBUREvent - Events which can cause transitions in the state of the BUR manager +**/ +enum TBTBUREvent + { + // Events relating to P&S key changes from BUR engine + EBTBUREventUnset, // Unset notification event received from the Secure Backup Engine + EBTBUREventNormal, // Normal mode notification event received from the Secure Backup Engine + EBTBUREventBackup, // Backup notification event received from the Secure Backup Engine + EBTBUREventRestore, // Restore notification event received from the Secure Backup Engine + + // Internally generated events + EBTBUREventBackupProceed, // BUR manager should proceed with backup operation + EBTBUREventBackupReject, // BUR manager should not proceed with backup operation + EBTBUREventRestoreProceed, // BUR manager should proceed with restore operation + EBTBUREventRestoreReject, // BUR manager should not proceed with restore operation + EBTBUREventProcessRestoreFile, // Request to process an available restore file + EBTBUREventProcessRestoreFileComplete, // Parsing of restore file has completed + EBTBUREventRestoreFileTransitionNormal, // Parsing of restore file has been completed, transition should be made to normal state. + + EBTBUREventAbortStateAction, // A state action has encountered an error which requires an abort back to normal state. + }; + +/** +State handling mechanisms - these classes support the state machine used by the BUR manager. +**/ + +class CBTManServerBURMgr; +class CBTManServerBURMgrStateAction; + +NONSHARABLE_CLASS(CBTManServerBURMgrStateFactory) : public CBase + { +public: + static CBTManServerBURMgrStateFactory* NewL(CBTManServerBURMgr& aBURMgr); + ~CBTManServerBURMgrStateFactory(); + + inline TBTBURState GetCurrentState(); + TInt TransitionState(TBTBUREvent aTransitionEvent); + void ExecuteAction(); + +private: + CBTManServerBURMgrStateFactory(CBTManServerBURMgr& aBURMgr); + void ConstructL(); + + void ConstructStateMachineL(); + CBTManServerBURMgrStateAction* ConstructStateLC(TBTBURState aState); + +private: + RPointerArray iStateActions; + CBTManServerBURMgr& iBURMgr; + TBTBURState iState; + + }; + +NONSHARABLE_CLASS(CBTManServerBURMgrStateAction) : public CBase + { +public: + ~CBTManServerBURMgrStateAction(); + + inline TBTBURState GetThisState(); + virtual TBTBURState GetNextState(TBTBUREvent aTransitionEvent)=0; + virtual void ExecuteActionL(CBTManServerBURMgr& aBURMgr)=0; + virtual void HandleActionError(CBTManServerBURMgr& aBURMgr, TInt aError); + +protected: + CBTManServerBURMgrStateAction(TBTBURState aState); + +protected: + TBTBURState iState; + + }; + +/** +Normal state +**/ + +NONSHARABLE_CLASS(CBTManServerBURMgrStateNormal) : public CBTManServerBURMgrStateAction + { +public: + static CBTManServerBURMgrStateNormal* NewLC(); + ~CBTManServerBURMgrStateNormal(); + + virtual TBTBURState GetNextState(TBTBUREvent aTransitionEvent); + virtual void ExecuteActionL(CBTManServerBURMgr& aBURMgr); + +protected: + CBTManServerBURMgrStateNormal(); + + }; + +/** +Backup states +**/ + +NONSHARABLE_CLASS(CBTManServerBURMgrStateBackupRequest) : public CBTManServerBURMgrStateAction + { +public: + static CBTManServerBURMgrStateBackupRequest* NewLC(); + ~CBTManServerBURMgrStateBackupRequest(); + + virtual TBTBURState GetNextState(TBTBUREvent aTransitionEvent); + virtual void ExecuteActionL(CBTManServerBURMgr& aBURMgr); + virtual void HandleActionError(CBTManServerBURMgr& aBURMgr, TInt aError); + +protected: + CBTManServerBURMgrStateBackupRequest(); + + }; + +NONSHARABLE_CLASS(CBTManServerBURMgrStateBackupOngoing) : public CBTManServerBURMgrStateAction + { +public: + static CBTManServerBURMgrStateBackupOngoing* NewLC(); + ~CBTManServerBURMgrStateBackupOngoing(); + + virtual TBTBURState GetNextState(TBTBUREvent aTransitionEvent); + virtual void ExecuteActionL(CBTManServerBURMgr& aBURMgr); + virtual void HandleActionError(CBTManServerBURMgr& aBURMgr, TInt aError); + +protected: + CBTManServerBURMgrStateBackupOngoing(); + + }; + + +NONSHARABLE_CLASS(CBTManServerBURMgrStateBackupIgnore) : public CBTManServerBURMgrStateAction + { +public: + static CBTManServerBURMgrStateBackupIgnore* NewLC(); + ~CBTManServerBURMgrStateBackupIgnore(); + + virtual TBTBURState GetNextState(TBTBUREvent aTransitionEvent); + virtual void ExecuteActionL(CBTManServerBURMgr& aBURMgr); + +protected: + CBTManServerBURMgrStateBackupIgnore(); + + }; + +/** +Restore states +**/ + +NONSHARABLE_CLASS(CBTManServerBURMgrStateRestoreRequest) : public CBTManServerBURMgrStateAction + { +public: + static CBTManServerBURMgrStateRestoreRequest* NewLC(); + ~CBTManServerBURMgrStateRestoreRequest(); + + virtual TBTBURState GetNextState(TBTBUREvent aTransitionEvent); + virtual void ExecuteActionL(CBTManServerBURMgr& aBURMgr); + virtual void HandleActionError(CBTManServerBURMgr& aBURMgr, TInt aError); + +protected: + CBTManServerBURMgrStateRestoreRequest(); + + }; + +NONSHARABLE_CLASS(CBTManServerBURMgrStateRestoreOngoing) : public CBTManServerBURMgrStateAction + { +public: + static CBTManServerBURMgrStateRestoreOngoing* NewLC(); + ~CBTManServerBURMgrStateRestoreOngoing(); + + virtual TBTBURState GetNextState(TBTBUREvent aTransitionEvent); + virtual void ExecuteActionL(CBTManServerBURMgr& aBURMgr); + virtual void HandleActionError(CBTManServerBURMgr& aBURMgr, TInt aError); + +protected: + CBTManServerBURMgrStateRestoreOngoing(); + + }; + +NONSHARABLE_CLASS(CBTManServerBURMgrStateRestoreIgnore) : public CBTManServerBURMgrStateAction + { +public: + static CBTManServerBURMgrStateRestoreIgnore* NewLC(); + ~CBTManServerBURMgrStateRestoreIgnore(); + + virtual TBTBURState GetNextState(TBTBUREvent aTransitionEvent); + virtual void ExecuteActionL(CBTManServerBURMgr& aBURMgr); + +protected: + CBTManServerBURMgrStateRestoreIgnore(); + + }; + +/** +Restore file processing states +**/ + +NONSHARABLE_CLASS(CBTManServerBURMgrStateProcessRestoreFile) : public CBTManServerBURMgrStateAction + { +public: + static CBTManServerBURMgrStateProcessRestoreFile* NewLC(); + ~CBTManServerBURMgrStateProcessRestoreFile(); + + virtual TBTBURState GetNextState(TBTBUREvent aTransitionEvent); + virtual void ExecuteActionL(CBTManServerBURMgr& aBURMgr); + virtual void HandleActionError(CBTManServerBURMgr& aBURMgr, TInt aError); + +protected: + CBTManServerBURMgrStateProcessRestoreFile(); + + }; + +NONSHARABLE_CLASS(CBTManServerBURMgrStateRestoreFileProcessingComplete) : public CBTManServerBURMgrStateAction + { +public: + static CBTManServerBURMgrStateRestoreFileProcessingComplete* NewLC(); + ~CBTManServerBURMgrStateRestoreFileProcessingComplete(); + + virtual TBTBURState GetNextState(TBTBUREvent aTransitionEvent); + virtual void ExecuteActionL(CBTManServerBURMgr& aBURMgr); + +protected: + CBTManServerBURMgrStateRestoreFileProcessingComplete(); + + }; + +#endif // BTMANSERVERBURSTATEMACHINE_H diff -r 8a27654f7b62 -r 20fda83a6398 bluetoothmgmt/btmgr/Inc/BTManServer.h --- a/bluetoothmgmt/btmgr/Inc/BTManServer.h Fri Mar 12 15:49:00 2010 +0200 +++ b/bluetoothmgmt/btmgr/Inc/BTManServer.h Mon Mar 15 12:44:59 2010 +0200 @@ -1,4 +1,4 @@ -// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 1999-2010 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" @@ -24,6 +24,7 @@ #include #include "BTRegistryDB.h" #include "btmanclientserver.h" +#include "btmanserverburmgr.h" #if KMaxBluetoothNameLen > KMaxFriendlyNameLen #define KLongestName KMaxBluetoothNameLen @@ -105,13 +106,17 @@ /** The BTMan Server. **/ -NONSHARABLE_CLASS(CBTManServer) : public CPolicyServer +NONSHARABLE_CLASS(CBTManServer) : public CPolicyServer, public MBTBURNotify { public: //construct / destruct static CServer2* NewLC(); ~CBTManServer(); + // From MBTBURNotify + virtual void BUROperationStarted(); + virtual void BUROperationStopped(); + void AddSession(); void DropSession(); @@ -126,12 +131,14 @@ void Publish(TUint aKey, TInt aValue); // only publish ints for now, ignore error void NotifyViewChange(CBTManSubSession& aSubSessionViewOwner, const TDesC& aViewDescriptor); + void NotifyViewChange(const TDesC& aViewDescriptor); private: CBTManServer(); void ConstructL(); //open/close a session CSession2* NewSessionL(const TVersion& aVersion,const RMessage2& aMessage) const; + void TryToStartShutdownTimer(); private: TInt iMaxSessionCount; @@ -140,6 +147,9 @@ CObjectConIx* iContainerIndex;// attName; // BFTP Attribute name - for(TInt j=0;j<4;j++) // we don't like it .. hardcoded - { - attName.Append(a_Header[a_offset+j]); - } - - a_offset+=4; - - if(attName.Compare(KTranpFIL0) == 0) - { - TUint32 length = IrTranpUtil::LExtract(a_Header, a_offset); - BFTPPRINT(_L("BFTP: Attribute FIL0\n")); - - m_FileName.SetLength(0); - m_FileName.Append((unsigned char*)a_Header.Ptr() + a_offset + 6, length-2); - - a_offset+=(length+4); - } - else if(attName.Compare(KTranpLFL0) == 0) - { - TUint32 length = IrTranpUtil::LExtract(a_Header, a_offset); - BFTPPRINT(_L("BFTP: Attribute LFL0\n")); - - iLongFilename.Append((unsigned char*)a_Header.Ptr() + a_offset + 6, length-2); - - a_offset+=(length+4); - } - else if(attName.Compare(KTranpTIM0) == 0) - { - TUint32 length = IrTranpUtil::LExtract(a_Header, a_offset); - BFTPPRINT(_L("BFTP: Attribute TIM0\n")); - a_offset+=(length+4); - } - else if(attName.Compare(KTranpTYP0) == 0) - { - TUint32 length = IrTranpUtil::LExtract(a_Header, a_offset); - BFTPPRINT(_L("BFTP: Attribute TYP0\n")); - a_offset+=(length+4); - } - else if(attName.Compare(KTranpTMB0) == 0) - { - TUint32 length = IrTranpUtil::LExtract(a_Header, a_offset); - BFTPPRINT(_L("BFTP: Attribute TMB0\n")); - a_offset+=(length+4); - } - else if(attName.Compare(KTranpBDY0) == 0) - { - TUint32 length = IrTranpUtil::LExtract(a_Header, a_offset); - BFTPPRINT(_L("BFTP: Attribute BDY0\n")); - - //iPicture.Set((unsigned char*)a_Header.Ptr() + a_offset + 6 + KTranpUPFHeader, length-2, length-2); - iUPFPicture.Set((unsigned char*)a_Header.Ptr() + a_offset + 6, length-2, length-2); - - iTranpProtocol->SetPicture(iPicture, m_FileName, iUPFPicture, iLongFilename); - - a_offset+=(length+4); - /**/ - TBuf8<256> userData; - - // AttNum - userData.Append(0x00); - userData.Append(0x01); - // attName - userData.Append(KTranpRPL0); - // AttLength - userData.Append(0x00); - userData.Append(0x00); - userData.Append(0x00); - userData.Append(2 + m_FileName.Length()); - // AttType - userData.Append(0x01); - // AFLG - userData.Append(0x00); - // AttValue - userData.Append(m_FileName); - - TUint8 pduType = KTranpPduTypeRplAck; - m_oSCEP->SCEPSendCommand(userData, pduType); // We want SCEP to send a packet with this command - } - else if(attName.Compare(KTranpCMD0) == 0) - { - TUint32 length = IrTranpUtil::LExtract(a_Header, a_offset); - BFTPPRINT(_L("BFTP: Attribute CMD0\n")); - a_offset+=(length+4); - } - else if(attName.Compare(KTranpWHT0) == 0) - { - TUint32 length = IrTranpUtil::LExtract(a_Header, a_offset); - BFTPPRINT(_L("BFTP: Attribute WHT0\n")); - - // how to avoid copying of the information we put in the command??? Don't avoid it for now. - TPtr8 queryType((unsigned char*)a_Header.Ptr() + a_offset+6, 4, 4); - - TBuf8<256> userData; - //TPtr8 userDataPtr = userData.Des(); - - if (queryType.Compare(KTranpRIMG) == 0) - { - //This reply is for an RIMG query - // Its instructs the peer to send the image in its orginal lattice size - - // AttNum - userData.Append(0x00); - userData.Append(0x01); - // AttName - userData.Append(KTranpBDY0); - // AttLength - userData.Append(0x00); - userData.Append(0x00); - userData.Append(0x00); - userData.Append(0x0d); - // AttType - userData.Append(0x00); - // AFLG - userData.Append(0x00); - - /*userData.Append(0x00);// 3 bytes - userData.Append(0x01); - userData.Append(0x01); */ +void BFTP::ReqPDU(const TDesC8& /*a_Header*/, TInt /*a_offset*/) +/** No Longer used. - switch(iLatticeSize) - { - case EQVGA: - //QVGA:=320x240 (0x0140 x 0x00f0) -// userData.Append(0x01);// 5 bytes -// userData.Append(0x40); // width [2 bytes] -// userData.Append(0x01); -// userData.Append(0xf0);// height [2 bytes] -// userData.Append(0x00); - - userData.Append(0x02);// 6 bytes - userData.Append(0x01);// - userData.Append(0x40);// width [2 bytes] - userData.Append(0x01); - userData.Append(0xf0);// height [2 bytes] - userData.Append(0x00); - break; - case EVGA : - // VGA:=640x480 ( 0x0280 x 0x01e0) -// userData.Append(0x01);// 5 bytes -// userData.Append(0x80); // width [2 bytes] -// userData.Append(0x02); -// userData.Append(0xe0);// height [2 bytes] -// userData.Append(0x01); - - userData.Append(0x02);// 6 bytes - userData.Append(0x01);// - userData.Append(0x80); // width [2 bytes] - userData.Append(0x02); - userData.Append(0xe0);// height [2 bytes] - userData.Append(0x01); - break; - case ESVGA: - // SVGA:=800x600 (0x0320 x 0x0258) -// userData.Append(0x01);// 5 bytes -// userData.Append(0x20);// width [2 bytes] -// userData.Append(0x03); -// userData.Append(0x58);// height [2 bytes] -// userData.Append(0x02); - - userData.Append(0x02);// 6 bytes - userData.Append(0x01);// - userData.Append(0x20);// width [2 bytes] - userData.Append(0x03); - userData.Append(0x58);// height [2 bytes] - userData.Append(0x02); - break; - case EXGA: - // XGA:=1024x768 ( 0x0400 x 0x0300) -// userData.Append(0x01);// 5 bytes -// userData.Append(0x00);// width [2 bytes] -// userData.Append(0x04); -// userData.Append(0x00);// height [2 bytes] -// userData.Append(0x30); - - userData.Append(0x02);// 6 bytes - userData.Append(0x01);// - userData.Append(0x00);// width [2 bytes] - userData.Append(0x04); - userData.Append(0x00);// height [2 bytes] - userData.Append(0x03); - break; - case ESXGA: - // SXGA:=1280x960 (0x0500 x 0x03c0) -// userData.Append(0x01);// 5 bytes -// userData.Append(0x00);// width [2 bytes] -// userData.Append(0x05); -// userData.Append(0xc0);// height [2 bytes] -// userData.Append(0x03); - - userData.Append(0x02);// 6 bytes - userData.Append(0x01);// - userData.Append(0x00);// width [2 bytes] - userData.Append(0x05); - userData.Append(0xc0);// height [2 bytes] - userData.Append(0x03); - break; - case EFREE: - // FREE:=m x n - default: - // Send in orginal size -// userData.Append(0x01);// 5 bytes -// userData.Append(0xFF); -// userData.Append(0xFF); -// userData.Append(0xFF); -// userData.Append(0xFF); - - userData.Append(0x02);// 6 bytes - userData.Append(0x01);// - userData.Append(0xFF);// width [2 bytes] - userData.Append(0xFF); - userData.Append(0xFF);// height [2 bytes] - userData.Append(0xFF); - }; - - /*userData.Append(0x03);// 3 bytes - userData.Append(0xC4); - userData.Append(0x20); - - userData.Append(0x04);// 3 bytes - userData.Append(0xC4); - userData.Append(0x20);*/ - - userData.Append(0x05);// 5 bytes - userData.Append(0xFF); - userData.Append(0xFF); - userData.Append(0xFF); - userData.Append(0xFF); - } - else if (queryType.Compare(KTranpRINF) == 0) - { - // This reply is for an RINF query - userData.Append(0x00); - userData.Append(0x01); - // AttName - userData.Append(KTranpBDY0); - // AttLength - userData.Append(0x00); - userData.Append(0x00); - userData.Append(0x00); - userData.Append(0x08); - // AttType - userData.Append(0x00); - // AFLG - userData.Append(0x00); - // AttValue - userData.Append(0x10); // memory - userData.Append(0xff); - userData.Append(0xff); - userData.Append(0x11); // battery - userData.Append(0xff); - userData.Append(0xff); - } - else if (queryType.Compare(KTranpRCMD) == 0) - { - // This reply is for an RINF query - userData.Append(0x00); - userData.Append(0x01); - // AttName - userData.Append(KTranpBDY0); - // AttLength - userData.Append(0x00); - userData.Append(0x00); - userData.Append(0x00); - userData.Append(0x07); - // AttType - userData.Append(0x00); - // AFLG - userData.Append(0x00); - // AttValue - userData.Append(0x20); // tag-opt-func - userData.Append(0x00); - userData.Append(0x01); - userData.Append(0x00); - userData.Append(0x01); // func-multi-command - } - - a_offset+=(length+4); - - TUint8 pduType = KTranpPduTypeRplAck; - m_oSCEP->SCEPSendCommand(userData, pduType); // We want SCEP to send a packet with this command - } - else if(attName.Compare(KTranpERR0) == 0) - { - TUint32 length = IrTranpUtil::LExtract(a_Header, a_offset); - BFTPPRINT(_L("BFTP: Attribute ERR0\n")); - a_offset+=(length+4); - } - else if(attName.Compare(KTranpRPL0) == 0) - { - TUint32 length = IrTranpUtil::LExtract(a_Header, a_offset); - BFTPPRINT(_L("BFTP: Attribute RPL0\n")); - a_offset+=(length+4); - } +irda client libraries left in to avoid breaks */ + { } - - BFTPPRINT(_L("BFTP: Exiting ReqPDU\n")); -} /* * Method description: Called from the application with a picture to send diff -r 8a27654f7b62 -r 20fda83a6398 irda/irdastack/irtranp/SCEP.CPP --- a/irda/irdastack/irtranp/SCEP.CPP Fri Mar 12 15:49:00 2010 +0200 +++ b/irda/irdastack/irtranp/SCEP.CPP Mon Mar 15 12:44:59 2010 +0200 @@ -109,149 +109,11 @@ return 0; } -void SCEP::ReceiveComplete(TDesC8& aBuffer) - { - SCEPPRINT_2(_L("SCEP::ReceiveComplete(%d)\n"),aBuffer.Length()); - - iSCEPFrame.Append(aBuffer); // Add new data to cached packet - - TBool loopagain; - do - { - loopagain = EFalse; - - if ((iSCEPFrame[0]==0x00)&&(iSCEPFrame.Length()>=3)) - { - TInt tempLength = 0; - TInt additionalLength = 0; - TInt lengthPos = 3; - - if ((iSCEPFrame[1]==KTranpMsgTypeCER) && (iSCEPFrame[2]==KTranpInfTypeVer)) - { - lengthPos = 5; - additionalLength = 4; // ... and that same packet has 4 trailing bytes - } - - if (iSCEPFrame.Length()>lengthPos+2)// Otherwise we might miss out on the last packet - { - if(iSCEPFrame[0] == 0x00) // Let's guess it's an SCEP header - HARDCODED AND UGLY!!! - { - tempLength = iSCEPFrame[lengthPos]; - if(tempLength == 0xff) - { - tempLength = IrTranpUtil::DExtract(iSCEPFrame, lengthPos+1); - lengthPos = 5; - } - SCEPPRINT_2(_L("tempLength = %d"), tempLength); - } - - tempLength += ((lengthPos+1) + additionalLength); - - SCEPPRINT_3(_L("iSCEPFrame.length(%d) >= templength(%d)"),iSCEPFrame.Length(),tempLength); - - switch (iSCEPFrame[1]) - { - case KTranpMsgTypeCER: // MsgType = Connection establishment request - case KTranpMsgTypeCEC: // MsgType = Connection establishment confirmation - case KTranpMsgTypeData: // Data (Command) - case KTranpMsgTypeDisc: // Disconnection - { - switch (iSCEPFrame[2]) - { - case KTranpInfTypeVer: // Version of MsgType - case KTranpInfTypeNeg: // Negotiation Information - case KTranpInfTypeUser: // UserData - case KTranpInfTypeExt: // Extend in the future - case KTranpInfTypeRsn: // Reason - break; - default: - // bogus frame - SCEPPRINT(_L("SCEP::Bogus Inf Type in frame\n")); - iSCEPFrame.SetLength(0); - } - } - break; - default: - // bogus frame - SCEPPRINT(_L("SCEP::Bogus Msg Type in frame\n")); - iSCEPFrame.SetLength(0); - } +void SCEP::ReceiveComplete(TDesC8& /*aBuffer*/) +/** No Longer used. - if(iSCEPFrame.Length() >= tempLength) // yes, complete packet - { - TInt oldLength = iSCEPFrame.Length(); - iSCEPFrame.SetLength(tempLength); // We only want exactly one packet - ParseCommand(iSCEPFrame); - - iSCEPFrame.SetLength(oldLength); - iSCEPFrame.Delete(0, tempLength); // The surplus data belongs to the next packet - SCEPPRINT(_L("\r\n***\r\n")); - //IrTranpUtil::HexOut(iSCEPFrame); - SCEPPRINT(_L("***\r\n")); - loopagain = (oldLength > tempLength) ? ETrue : EFalse; - } - } - } - else - { - SCEPPRINT(_L("SCEP:: Bogus Frame header\n")); - iSCEPFrame.SetLength(0); - } - } while (loopagain); - - - // let the commandprocessor send whatever's in queue - - m_oCommandP->DoCommand(); - - if ( (!(iComReadWrite->IsActive())) && !(iState == EError) ) //Make sure that thre is always an outstanding request - iComReadWrite->Receive(); - - switch(iState) - { - case EConnected: - iNotifier->Connected(); - iState = EProgress; - SCEPPRINT(_L("SCEP: EConnected -> EProgress\r\n")); - break; - case EDisconnected: - iNotifier->Disconnected(); - iComReadWrite->Close(); - iState = EWaiting; - SCEPPRINT(_L("SCEP: EDisconnected -> EWaiting\r\n")); - break; - case EProgress: - { - SCEPPRINT(_L("SCEP: EProgress\r\n")); - - TInt32 progress = 0; - if(m_packet!=NULL) - { - if(m_packet->Length() != 0) - { - Math::Int(progress, m_packet->Length()*100 / m_iPicSize); - } - iNotifier->ProgressIndication(progress); - } - } - break; - case EWaiting: - SCEPPRINT(_L("SCEP: EWaiting\r\n")); - break; - case EError: - SCEPPRINT(_L("SCEP: EError\r\n")); - break; - case ECommunicationInt: - SCEPPRINT(_L("SCEP: ECommunicationInt\r\n")); - iNotifier->Disconnected(); - iComReadWrite->Close(); - iState = EWaiting; - break; - default: - SCEPPRINT(_L("SCEP: Unknown state\r\n")); - break; - } - SCEPPRINT(_L("SCEP: Exit ReceiveComplete\r\n")); +irda client libraries left in to avoid breaks */ + { } void SCEP::SendComplete() @@ -319,19 +181,11 @@ * */ -void SCEP::SCEPSendCommand(TDes8& a_userData, TUint8 a_pduType) +void SCEP::SCEPSendCommand(TDes8& /*a_userData*/, TUint8 /*a_pduType*/) +/** No Longer used. + +irda client libraries left in to avoid breaks */ { - SRPSCommand* command = new (ELeave) SRPSCommand(iComReadWrite); - command->SetPMID(m_PMID.Des()); - command->SetSMID(m_SMID.Des()); - command->SetDPID(m_DPID); - command->SetSPID(m_SPID); - command->SetCmdId(m_CmdId); - command->SetPDUType(a_pduType); - command->SetUserData(a_userData); - command->Create(); -// IrTranpUtil::HexOut(command->GetData()); - m_oCommandP->Add(command); } /* @@ -394,156 +248,12 @@ * Parameter: offset - where in the packet to start parsing */ -void SCEP::SCEPDataCommand(TDes8& a_Header, TInt offset) +void SCEP::SCEPDataCommand(TDes8& /*a_Header*/, TInt /*offset*/) +/** No Longer used. + +irda client libraries left in to avoid breaks */ { - SCEPPRINT(_L("Inside SCEPDataCommand\n")); - - if(a_Header[offset] == KTranpInfTypeUser) - { - // Always InfTypeUser when in SCEPDataCommand - TInt packetLength = a_Header[offset+1]; - if(packetLength == 0xff) - { - // since length1 was 0xff, look at length2 - packetLength = ((a_Header[offset+2] << 8) + (a_Header[offset+3])); // 16bit - offset+=4; // include inftype and length2 - } - else - { - offset+=2; // include inftype and length1 - } - - // TUint8 InfVer = a_Header[offset]; - TUint8 DFLG = a_Header[offset+1]; - // TUint16 length3 = IrTranpUtil::DExtract(a_Header, offset+2); - - if(DFLG == KTranpDFLGrcon) - { - // Reject to request connection - SCEPPRINT(_L("Connection rejected\n")); - } - else if(DFLG == KTranpDFLGnseg) - { - // PDU not segmented (single PDU) - DoCommand(a_Header, offset+4); - // break; - } - else if(DFLG == KTranpDFLGfPDU) - { - // First segmented PDU - // We do all reassembling in SCEP, and then send the complete (big) packet to bFTP - // restno * PDU must be able to hold the complete packet, right? - - // Ownership of this data [m_packet] belongs to the TTranpPicture object - // so must ask the correct object to delete its heap. - // If we were already building a packet, get rid of it - iTranpProtocol->DeleteHeapData(); - - TUint32 seqno = IrTranpUtil::LExtract(a_Header, offset+4); - TUint32 restno = IrTranpUtil::LExtract(a_Header, offset+8); - - TUint32 PDUSize; - switch(m_uiMaxPDU) - { - case '1': - { - PDUSize = 512; - break; - } - case '2': - { - PDUSize = 1024; - break; - } - case '3': - { - PDUSize = 2048; - break; - } - case '4': - { - PDUSize = 4096; - break; - } - default: - { - PDUSize = 512; - break; - } - } - - // This should not leave and report an error back... - //__UHEAP_FAILNEXT(1); - TRAPD( err , m_packet = HBufC8::NewL(PDUSize*restno)); // should be enough - if (err != KErrNone) - { - iNotifier->Error(err); - iState = EError; - return; - } - else - iTranpProtocol->SetHeapData(m_packet); - - m_iPicSize = PDUSize*restno; - - SCEPPRINT(_L("ResizeL went well\n")); - - m_seq = seqno; - AddSegment(a_Header, offset+12); - } - else if(DFLG == KTranpDFLGiPDU) - { - // Intermediate segmented PDUs - - TUint32 seqno = IrTranpUtil::LExtract(a_Header, offset+4); - if(seqno == m_seq+1) - { - AddSegment(a_Header, offset+12); - m_seq++; - } - else - { - SCEPPRINT(_L("Error in intermediate PDU\n")); - } - } - else if(DFLG == KTranpDFLGlPDU) - { - // Last segmented PDU - - m_seq++; - TUint32 restno = IrTranpUtil::LExtract(a_Header, offset+8); - if(restno == 1) - { - AddSegment(a_Header, offset+12); - //TPtr8 packetPtr = m_packet->Des(); - DoCommand(*m_packet, 0); // Now let's play - iNotifier->ProgressIndication(100); // Makes sure 100% is reached - iNotifier->GetComplete(); - TPtr8 temp2 = m_packet->Des(); - temp2.Zero(); - } - else - { - SCEPPRINT(_L("Error in last PDU\n")); - } - } - else if(DFLG == KTranpDFLGcint) - { - SCEPPRINT(_L("Communication interrupted\n")); - iState = ECommunicationInt; - } - else - { - // Ooops. - } - } - else - { - // oops - } - - SCEPPRINT(_L("Exiting SCEPDataCommand\n")); -} + } /* * Method description: Adds segmented packets into a complete packet @@ -664,46 +374,11 @@ * Parameter: a_offset - where in the packet the command is */ -void SCEP::DoCommand(const TDesC8& a_Header, TInt a_offset) - { - SCEPPRINT(_L("SCEP: DoCommand\n")); - - if(a_Header[a_offset] != 0x58) // Always 0x58 at the start of a command - { - SCEPPRINT(_L("SCEP: Command did not start with 0x58\n")); - return; - } - - TUint8 switchVar = (TUint8)(a_Header[a_offset+1] & 0xc0); // we only want the two highest bits for PDU type - if(switchVar == KTranpPduTypeReq) - { - // Don't care about the MachineIDs for now - SCEPPRINT(_L("SCEP: PduTypeReq\n")); +void SCEP::DoCommand(const TDesC8& /*a_Header*/, TInt /*a_offset*/) +/** No Longer used. - m_SPID = IrTranpUtil::DExtract(a_Header, 22 + a_offset); - m_DPID = IrTranpUtil::DExtract(a_Header, 24 + a_offset); - m_CmdId = IrTranpUtil::DExtract(a_Header,26 + a_offset); - // Pass SCEP packet Payload to BFTP layer - m_oBFTP->ReqPDU(a_Header, a_offset + 28); // hardcoded, but always 28 - } - else if(switchVar == KTranpPduTypeRplAck) - { - SCEPPRINT(_L("SCEP: PduTypeRplAck\n")); - } - else if(switchVar == KTranpPduTypeRplNack) - { - SCEPPRINT(_L("SCEP: PduTypeRplNack\n")); - } - else if(switchVar == KTranpPduTypeAbt) - { - SCEPPRINT(_L("SCEP: PduTypeAbt\n")); - } - else - { - SCEPPRINT(_L("SCEP: PduType Broken\n")); - } - - SCEPPRINT(_L("SCEP: Exiting DoCommand\n")); +irda client libraries left in to avoid breaks */ + { } /* @@ -839,53 +514,11 @@ // Parameter: a_TempBuffer - the packet itself // -void SCEP::ParseCommand(TDes8& a_TempBuffer) +void SCEP::ParseCommand(TDes8& /*a_TempBuffer*/) +/** No Longer used. + +irda client libraries left in to avoid breaks */ { - SCEPPRINT(_L("SCEP: ParseCommand\n")); - // parse the incoming buffer and see what command we're talking about. Return an instance of such a command. - - // Look at the first bytes, see what command it might be, call the correct private method and let it take care of the rest? - - if(a_TempBuffer[1] == KTranpMsgTypeCER) - // MsgType = Connection establishment request - { - SCEPPRINT(_L("SCEP: Got a connection request")); - SCEPConRequest(a_TempBuffer, 2); - - // Create and add a SCEPConConfirm! - SCONconL(); - } - else if(a_TempBuffer[1] == KTranpMsgTypeCEC) - // MsgType = Connection establishment confirmation - { - SCEPPRINT(_L("SCEP: Got a connect ack")); - SCEPConConfirm(a_TempBuffer, 2); - } - else if(a_TempBuffer[1] == KTranpMsgTypeData) - // Data (Command) - { - SCEPPRINT(_L("SCEP: Got a data packet\n")); - SCEPDataCommand(a_TempBuffer, 2); - } - else if(a_TempBuffer[1] == KTranpMsgTypeDisc) - // Disconnection - { - SCEPPRINT(_L("SCEP: Got a disconnect packet\n")); - SCEPDisconnect(a_TempBuffer, 2); - if (m_packet != NULL) - m_iPicSize = m_packet->Length(); // Otherwise we'll never get to 100% - iSCEPFrame.Zero(); - } - else - { - SCEPPRINT(_L("SCEP: Wacko! Default!\n")); - // Reserved - } - - - SCEPPRINT(_L("SCEP: Exiting ParseCommand\n")); - - return; } // diff -r 8a27654f7b62 -r 20fda83a6398 irda/irdastack/irtranp/tranp.cpp --- a/irda/irdastack/irtranp/tranp.cpp Fri Mar 12 15:49:00 2010 +0200 +++ b/irda/irdastack/irtranp/tranp.cpp Mon Mar 15 12:44:59 2010 +0200 @@ -312,38 +312,27 @@ } EXPORT_C void CTranpSession::Connect() -/** Establishes a connection with a peer device. This function is called before -sending a picture. +/** No Longer used. -The callback function Connect() is called when the connection has been successfully -established. +irda client libraries left in to avoid breaks */ -@see MTranpNotification::Connected() */ { - User::Leave(KErrNotSupported); //Qualified } EXPORT_C void CTranpSession::Disconnect() -/** Breaks the connection with a peer device. This function is called after sending -a picture. +/** No Longer used. -The callback function Disconnected() is called when the connection has been -broken. +irda client libraries left in to avoid breaks */ -@see MTranpNotification::Connected() */ { - User::Leave(KErrNotSupported); //Qualified } EXPORT_C void CTranpSession::Query(TTranP /*aWhat*/) -/** Requests information on the processing ability of the peer device. Typically, -this is called before sending a picture to that peer device. The information -is returned through the callback function QueryComplete(). +/** No Longer used. -@param aWhat The specific type of information required from the peer device. -@see MTranpNotification::QueryComplete() */ +irda client libraries left in to avoid breaks */ + { - User::Leave(KErrNotSupported); //Qualified } EXPORT_C void CTranpSession::Abort() @@ -383,43 +372,25 @@ } EXPORT_C void CTranpSession::Put(const TTranpPicture& /*aPicture*/) -/** Sends a picture to a peer device. - -The following sequence of events is expected: - -This device sends picture data to the peer device, resulting in successive -calls to the ProgressIndication() callback function indicating how much of -the picture data has been received. +/** No Longer used. -Transmission of picture data is complete, resulting in a call to the GetComplete() -callback function. - -If the connection with the peer device is dropped at any stage in the transmission, -then this results in a call to the Error() callback function. - -@param aPicture The picture object -@see MTranpNotification::ProgressIndication() -@see MTranpNotification::GetComplete() -@see MTranpNotification::Error() */ +irda client libraries left in to avoid breaks */ { - User::Leave(KErrNotSupported); //Qualified } EXPORT_C void CTranpSession::Config(const TTranpConfig& /*aConfig*/) -/** Sets the configuration parameters. +/** No Longer used. -@param aConfig The configuration parameters */ +irda client libraries left in to avoid breaks */ { - User::Leave(KErrNotSupported); //Qualified } EXPORT_C TTranpConfig CTranpSession::Config() const -/** Returns the configuration parameters. +/** No Longer used. -@return The configuration parameters. */ +irda client libraries left in to avoid breaks */ { - User::Leave(KErrNotSupported); //Qualified return iConfig; }