# HG changeset patch # User Dremov Kirill (Nokia-D-MSW/Tampere) # Date 1271423365 -10800 # Node ID 907b2fb7aa8ef428bf401c8ea44a924180fe7e00 # Parent 0089b2f7ebd8a1cd3cd2602fdd1491c07253089b Revision: 201011 Kit: 201015 diff -r 0089b2f7ebd8 -r 907b2fb7aa8e atext/group/bld.inf --- a/atext/group/bld.inf Fri Mar 19 09:53:48 2010 +0200 +++ b/atext/group/bld.inf Fri Apr 16 16:09:25 2010 +0300 @@ -26,5 +26,6 @@ PRJ_MMPFILES #include "../client/group/bld.inf" #include "../server/group/bld.inf" +#include "../plugins/group/bld.inf" PRJ_TESTMMPFILES diff -r 0089b2f7ebd8 -r 907b2fb7aa8e atext/plugins/group/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/atext/plugins/group/bld.inf Fri Apr 16 16:09:25 2010 +0300 @@ -0,0 +1,28 @@ +/* +* Copyright (c) 2008 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: build file +* +*/ + + +#include + +PRJ_PLATFORMS + +PRJ_EXPORTS + +PRJ_MMPFILES +#include "../legacymodemplugin/group/bld.inf" + +PRJ_TESTMMPFILES diff -r 0089b2f7ebd8 -r 907b2fb7aa8e atext/plugins/legacymodemplugin/group/bld.inf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/atext/plugins/legacymodemplugin/group/bld.inf Fri Apr 16 16:09:25 2010 +0300 @@ -0,0 +1,29 @@ +/* +* Copyright (c) 2009 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: This file provides the information required for building the +* whole of LegacyModemPlugin +* +*/ + +#include + +PRJ_PLATFORMS + +PRJ_EXPORTS +../rom/legacymodemplugin.iby CORE_OS_LAYER_IBY_EXPORT_PATH(legacymodemplugin.iby) + +PRJ_MMPFILES +legacymodemplugin.mmp + +PRJ_TESTMMPFILES diff -r 0089b2f7ebd8 -r 907b2fb7aa8e atext/plugins/legacymodemplugin/group/legacymodemplugin.mmp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/atext/plugins/legacymodemplugin/group/legacymodemplugin.mmp Fri Apr 16 16:09:25 2010 +0300 @@ -0,0 +1,52 @@ +/* +* Copyright (c) 2009 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: Project definition file for project LegacyModemPlugin +* +*/ + + +#include + +TARGET legacymodemplugin.dll +TARGETTYPE PLUGIN +UID 0x10009D8D 0x2002B340 + +CAPABILITY CAP_ECOM_PLUGIN +VENDORID VID_DEFAULT + +SOURCEPATH ../src +SOURCE proxy.cpp +SOURCE legacymodemplugin.cpp +SOURCE monitorspeakerparser.cpp + +START RESOURCE ../src/2002B340.rss +TARGET legacymodemplugin.rsc +END + +USERINCLUDE ../inc + +OS_LAYER_SYSTEMINCLUDE + +// Note: +// The only other SYSTEMINCLUDE should you shall add are Symbian specific ones. +// If there is a S60 header in the subdirectory then that should be +// added into the include statements (like #include ) +//SYSTEMINCLUDE /epoc32/include/ecom +SYSTEMINCLUDE /epoc32/include/ecom + +LIBRARY ecom.lib +LIBRARY euser.lib +LIBRARY atextpluginbase.lib + +DEBUGLIBRARY flogger.lib diff -r 0089b2f7ebd8 -r 907b2fb7aa8e atext/plugins/legacymodemplugin/inc/debug.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/atext/plugins/legacymodemplugin/inc/debug.h Fri Apr 16 16:09:25 2010 +0300 @@ -0,0 +1,171 @@ +/* +* Copyright (c) 2008 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: Logging definitions +* +*/ + + +#ifndef PRJ_LOGGING_H +#define PRJ_LOGGING_H + +#include +#include "debugconfig.h" + +#ifdef PRJ_ENABLE_TRACE + +#ifdef PRJ_FILE_TRACE +#include +#else +#include +#endif + +NONSHARABLE_CLASS(TOverflowTruncate16) : public TDes16Overflow + { +public: + void Overflow(TDes16& /*aDes*/) {} + }; + +NONSHARABLE_CLASS(TOverflowTruncate8) : public TDes8Overflow + { +public: + void Overflow(TDes8& /*aDes*/) {} + }; + +inline void Trace(TRefByValue aFmt, ...) + { + VA_LIST list; + VA_START(list,aFmt); +#ifdef PRJ_FILE_TRACE + RFileLogger::WriteFormat(KLogDir, KLogFile, EFileLoggingModeAppend, aFmt, list); +#else + TBuf16 theFinalString; + theFinalString.Append(KTracePrefix16); + TOverflowTruncate16 overflow; + theFinalString.AppendFormatList(aFmt,list,&overflow); + RDebug::Print(theFinalString); +#endif + } + +inline void Trace(TRefByValue aFmt, ...) + { + VA_LIST list; + VA_START(list, aFmt); +#ifdef PRJ_FILE_TRACE + RFileLogger::WriteFormat(KLogDir, KLogFile, EFileLoggingModeAppend, aFmt, list); +#else + TOverflowTruncate8 overflow; + TBuf8 buf8; + buf8.Append(KTracePrefix8); + buf8.AppendFormatList(aFmt, list, &overflow); + TBuf16 buf16(buf8.Length()); + buf16.Copy(buf8); + TRefByValue tmpFmt(_L("%S")); + RDebug::Print(tmpFmt, &buf16); +#endif + } + +inline void TracePanic( + char* aFile, + TInt aLine, + TInt aPanicCode, + const TDesC& aPanicCategory) + { + TPtrC8 fullFileName((const TUint8*)aFile); + TPtrC8 fileName(fullFileName.Ptr()+fullFileName.LocateReverse('\\')+1); + TBuf8 buf; + buf.Append(KPanicPrefix8); + buf.AppendFormat(_L8("%d at line %d in file %S"), aPanicCode, aLine, &fileName); + Trace(buf); + User::Panic(aPanicCategory, aPanicCode); + } + +inline void TraceLeave(char* aFile, TInt aLine, TInt aReason) + { + TPtrC8 fullFileName((const TUint8*)aFile); + TPtrC8 fileName(fullFileName.Ptr()+fullFileName.LocateReverse('\\')+1); + TBuf8 buf; + buf.Append(KLeavePrefix8); + buf.AppendFormat(_L8("%d at line %d in file %S"), aReason, aLine, &fileName); + Trace(buf); + User::Leave(aReason); + } + +#define TRACE_INFO(p) {if(KTraceMask & KPRINTINFO) Trace p;} + +#define TRACE_ERROR(p) {if(KTraceMask & KPRINTERROR) Trace p;} + +#define TRACE_STATE(p) {if(KTraceMask & KPRINTSTATE) Trace p;} + +#define TRACE_WARNING(p) {if(KTraceMask & KPRINTWARNING) Trace p;} + +#define TRACE_INFO_SEG(p) {if(KTraceMask & KPRINTINFO) p;} + +#define TRACE_ASSERT(GUARD, CODE) {if (!(GUARD)) TracePanic(__FILE__, __LINE__, CODE, KPanicCategory);} + +#define PANIC(CODE) TracePanic(__FILE__, __LINE__, CODE, KPanicCategory) + +#define LEAVE_IF_ERROR(REASON) {if (REASON) TraceLeave(__FILE__, __LINE__, REASON);} + +#define LEAVE_IF_NULL(PTR) {if (!PTR) TraceLeave(__FILE__, __LINE__, PTR);} + +#define LEAVE(REASON) {TraceLeave(__FILE__, __LINE__, REASON);} + +#define TRACE_STATIC_FUNC_ENTRY {if(KTraceMask & KPRINTINFO) { TPtrC8 ptr8((TUint8*)__PRETTY_FUNCTION__); Trace(KFuncEntryFormat8, &ptr8);}} + +#define TRACE_FUNC_ENTRY {if(KTraceMask & KPRINTINFO) { TPtrC8 ptr8((TUint8*)__PRETTY_FUNCTION__); Trace(KFuncEntryThisFormat8, &ptr8, this);}} + +#define TRACE_FUNC_EXIT {if(KTraceMask & KPRINTINFO) { TPtrC8 ptr8((TUint8*)__PRETTY_FUNCTION__); Trace(KFuncExitFormat8, &ptr8);}} + +#define TRACE_STATIC_FUNC {if(KTraceMask & KPRINTINFO) { TPtrC8 ptr8((TUint8*)__PRETTY_FUNCTION__); Trace(KFuncFormat8, &ptr8);}} + +#define TRACE_FUNC {if(KTraceMask & KPRINTINFO) { TPtrC8 ptr8((TUint8*)__PRETTY_FUNCTION__); Trace(KFuncThisFormat8, &ptr8, this);}} + +#define RETURN_IF_ERR(ERR) {if(ERR) {TPtrC8 ptr8((TUint8*)__FILE__); Trace(_L8(" RETURN %d at file %S line %d"), ERR, &ptr8, __LINE__); return ERR;}} + +#else // PRJ_ENABLE_TRACE not defined + +#define TRACE_INFO(p) + +#define TRACE_ERROR(p) + +#define TRACE_STATE(p) + +#define TRACE_WARNING(p) + +#define TRACE_INFO_SEG(p) + +#define TRACE_ASSERT(GUARD, CODE) + +#define PANIC(CODE) {User::Panic(KPanicCategory, CODE);} + +#define LEAVE_IF_ERROR(REASON) {static_cast(User::LeaveIfError(REASON));} + +#define LEAVE_IF_NULL(PTR) {static_cast(User::LeaveIfNull(PTR));} + +#define LEAVE(REASON) {static_cast(User::Leave(REASON));} + +#define TRACE_STATIC_FUNC_ENTRY + +#define TRACE_FUNC_ENTRY + +#define TRACE_FUNC_EXIT + +#define TRACE_STATIC_FUNC + +#define TRACE_FUNC + +#define RETURN_IF_ERR(ERR) {if(ERR) return ERR;} +#endif // PRJ_ENABLE_TRACE + +#endif // PRJ_LOGGING_H diff -r 0089b2f7ebd8 -r 907b2fb7aa8e atext/plugins/legacymodemplugin/inc/debugconfig.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/atext/plugins/legacymodemplugin/inc/debugconfig.h Fri Apr 16 16:09:25 2010 +0300 @@ -0,0 +1,55 @@ +/* +* Copyright (c) 2008 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: Logging configure file +* +*/ + + +#ifndef ATEXT_DEBUGCONFIG_H +#define ATEXT_DEBUGCONFIG_H + +#include "prjconfig.h" + +/** + * Custom logging variations. + */ +#ifdef PRJ_FILE_TRACE +_LIT(KLogFile,"lccustomplugin.txt"); +_LIT(KLogDir,"LCCUSTOMPLUGIN"); +#endif + +#ifdef PRJ_ENABLE_TRACE +_LIT(KTracePrefix16, "[LCCUSTOMPLUGIN] "); +_LIT8(KTracePrefix8, "[LCCUSTOMPLUGIN] "); +_LIT8(KFuncFormat8, "><%S"); +_LIT8(KFuncThisFormat8, "><%S, [0x%08X]"); +_LIT8(KFuncEntryFormat8, ">%S"); +_LIT8(KFuncEntryThisFormat8, ">%S, [0x%08X]"); +_LIT8(KFuncExitFormat8, "<%S"); + +_LIT(KPanicCategory, "lccustomplugin"); +_LIT8(KPanicPrefix8, "PANIC code "); +_LIT8(KLeavePrefix8, "LEAVE code "); +#endif + +const TInt KMaxLogLineLength = 512; + +#define KPRINTERROR 0x00000001 // Tracing level: error +#define KPRINTINFO 0x00000002 // Tracing level: function trace +#define KPRINTSTATE 0x00000004 // Tracing level: state machine info +#define KPRINTWARNING 0x00000008 // Tracing level: warning + +const TInt KTraceMask = KPRINTERROR | KPRINTINFO | KPRINTSTATE | KPRINTWARNING; + +#endif // ATEXT_DEBUGCONFIG_H diff -r 0089b2f7ebd8 -r 907b2fb7aa8e atext/plugins/legacymodemplugin/inc/legacymodemplugin.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/atext/plugins/legacymodemplugin/inc/legacymodemplugin.h Fri Apr 16 16:09:25 2010 +0300 @@ -0,0 +1,421 @@ +/* +* Copyright (c) 2009 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: Main handler for incoming requests +* +*/ + +#ifndef C_LEGACYMODEMPLUGIN_H +#define C_LEGACYMODEMPLUGIN_H + +#include + +class CLegacyModemPlugin; + +/** Character types: carriage return, line feed or backspace */ +enum TCharacterTypes + { + ECharTypeCR, // Carriage return + ECharTypeLF, // Line feed + ECharTypeBS // Backspace + }; + +/** Type of modes (quiet, verbose) */ +enum TModeTypes + { + EModeTypeQuiet, // Quiet mode + EModeTypeVerbose // Verbose mode + }; + +/** Handler types for the four types */ +enum TCmdHandlerType + { + ECmdHandlerTypeUndefined = KErrNotFound, + ECmdHandlerTypeBase = 0x01, // For command "AT+COMMAND" + ECmdHandlerTypeSet = 0x02, // For command "AT+COMMAND=" + ECmdHandlerTypeRead = 0x04, // For command "AT+COMMAND?" + ECmdHandlerTypeTest = 0x08, // For command "AT+COMMAND=?" + }; + +/** + * Class for common AT command handler interface + * + * @since S60 v5.0 + */ +NONSHARABLE_CLASS( CLegacyModemPluginBase ) + { + +public: + + virtual ~CLegacyModemPluginBase() {}; + + /** + * Reports the support status of an AT command. This is a synchronous API. + * + * @param aCmd The AT command. Its format may vary depending on the + * specification. E.g. in BT HFP case, the command may contain + * a character carriage return () in the end. + * @return ETrue if the command is supported; EFalse otherwise. + */ + virtual TBool IsCommandSupported( const TDesC8& aCmd ) = 0; + + /** + * Handles an AT command. Cancelling of the pending request is done by + * HandleCommandCancel(). The implementation in the extension plugin should + * be asynchronous. + * + * The extension plugin which accepts this command is responsible to supply + * the result codes and response and to format result codes properly, e.g. + * in BT HFP case, the format should be + * + * After an extension plugin has handled or decided to reject the given AT + * command, it must inform ATEXT by HandleCommandCompleted() with a proper + * error code. + * + * @since S60 5.0 + * @param aCmd The AT command to be handled. Its format may vary depending + * on the specification. E.g. in BT HFP case, the command may + * contain a character carriage return () in the end. + * @param aReply When passed in, contains the built in answer filled by + * ATEXT if it is not empty; when command handling completes + * successfully, contains the result codes and responses to + * this command; Its ownership always belongs to ATEXT, plugin + * may reallocate its space when needed. + * @param aReplyNeeded Reply needed if ETrue, no reply otherwise. If EFalse, + * the aReply must not contain the reply, otherwise it + * must contain verbose or numeric reply (ATV0/1) or an + * empty string reply (with ATQ). + * @return None + */ + virtual void HandleCommand( const TDesC8& aCmd, + RBuf8& aReply, + TBool aReplyNeeded ) = 0; + + /** + * Cancels a pending HandleCommand request. + * + * @since S60 5.0 + * @return None + */ + virtual void HandleCommandCancel() = 0; + + }; + +/** + * Class for accessing plugin information and common functionality + * + * @since S60 v5.0 + */ +NONSHARABLE_CLASS( MLegacyModemPlugin ) + { + +public: + + /** + * Creates an AT command reply based on the reply type and completes the + * request to ATEXT. Uses iReplyBuffer for reply storage. + * + * @since S60 5.0 + * @param aReplyType Type of reply + * @param aSrcBuffer Source buffer; used only if aReplyType is EReplyTypeOther + * @param aError Completion code. If not KErrNone then other arguments are + * ignored and the request is completed to ATEXT with + * EReplyTypeUndefined. + * @return None + */ + virtual TInt CreateReplyAndComplete( TATExtensionReplyType aReplyType, + const TDesC8& aSrcBuffer=KNullDesC8, + TInt aError=KErrNone ) = 0; + + /** + * Creates a buffer for "OK" or "ERROR" reply based on the line settings + * + * @since S60 5.0 + * @param aReplyBuffer Destination buffer for the created reply + * @param aOkReply ETrue if "OK" reply needed, + * EFalse if "ERROR" reply needed + * @return Symbian error code on error, KErrNone otherwise + */ + virtual TInt CreateOkOrErrorReply( RBuf8& aReplyBuffer, + TBool aOkReply ) = 0; + + /** + * Checks if the command is a base, set, read or test type of command + * + * @since S60 5.0 + * @param aCmdBase Base part of the command to check + * @param aCmdFull Full command to check + * @return Type of command + */ + virtual TCmdHandlerType CheckCommandType( const TDesC8& aCmdBase, + const TDesC8& aCmdFull ) = 0; + + }; + +/** + * Class for selecting handlers for different AT commands + * + * @since S60 v5.0 + */ +NONSHARABLE_CLASS( CLegacyModemPlugin ) : public CATExtPluginBase, + public MLegacyModemPlugin + { + +public: + + /** + * Two-phased constructor. + * @return Instance of self + */ + static CLegacyModemPlugin* NewL(); + + /** + * Destructor. + */ + virtual ~CLegacyModemPlugin(); + +private: + + CLegacyModemPlugin(); + + void ConstructL(); + + /** + * Reports connection identifier name to the extension plugin. + * + * @since S60 5.0 + * @param aName Connection identifier name + * @return None + */ + void ReportConnectionName( const TDesC8& aName ); + + /** + * Reports the support status of an AT command. This is a synchronous API. + * + * @param aCmd The AT command. Its format may vary depending on the + * specification. E.g. in BT HFP case, the command may contain + * a character carriage return () in the end. + * @return ETrue if the command is supported; EFalse otherwise. + */ + TBool IsCommandSupported( const TDesC8& aCmd ); + + /** + * Handles an AT command. Cancelling of the pending request is done by + * HandleCommandCancel(). The implementation in the extension plugin should + * be asynchronous. + * + * The extension plugin which accepts this command is responsible to supply + * the result codes and response and to format result codes properly, e.g. + * in BT HFP case, the format should be + * + * After an extension plugin has handled or decided to reject the given AT + * command, it must inform ATEXT by HandleCommandCompleted() with a proper + * error code. + * + * @since S60 5.0 + * @param aCmd The AT command to be handled. Its format may vary depending + * on the specification. E.g. in BT HFP case, the command may + * contain a character carriage return () in the end. + * @param aReply When passed in, contains the built in answer filled by + * ATEXT if it is not empty; when command handling completes + * successfully, contains the result codes and responses to + * this command; Its ownership always belongs to ATEXT, plugin + * may reallocate its space when needed. + * @param aReplyNeeded Reply needed if ETrue, no reply otherwise. If EFalse, + * the aReply must not contain the reply, otherwise it + * must contain verbose or numeric reply (ATV0/1) or an + * empty string reply (with ATQ). + * @return None + */ + void HandleCommand( const TDesC8& aCmd, RBuf8& aReply, TBool aReplyNeeded ); + + /** + * Cancels a pending HandleCommand request. + * + * @since S60 5.0 + * @return None + */ + void HandleCommandCancel(); + + /** + * Next reply part's length. + * The value must be equal or less than KDefaultCmdBufLength. + * When the reply from this method is zero, ATEXT stops calling + * GetNextPartOfReply(). + * + * @since S60 5.0 + * @return Next reply part's length if zero or positive + */ + TInt NextReplyPartLength(); + + /** + * Gets the next part of reply initially set by HandleCommandComplete(). + * Length of aNextReply must be equal or less than KDefaultCmdBufLength. + * + * @since S60 5.0 + * @param aNextReply Next reply + * @return Symbian error code on error, KErrNone otherwise + */ + TInt GetNextPartOfReply( RBuf8& aNextReply ); + + /** + * Receives unsolicited results. Cancelling of the pending request is done + * by ReceiveUnsolicitedResultCancel(). The implementation in the extension + * plugin should be asynchronous. + * + * @since S60 5.0 + * @return None + */ + void ReceiveUnsolicitedResult(); + + /** + * Cancels a pending ReceiveUnsolicitedResult request. + * + * @since S60 5.0 + * @return None + */ + void ReceiveUnsolicitedResultCancel(); + + /** + * Reports NVRAM status change to the plugins. + * + * @since S60 5.0 + * @param aNvram New NVRAM status. Each call of this function is a result + * of DUN extracting the form notified by + * CATExtCommonBase::SendNvramStatusChange(). Each of the + * settings from SendNvramStatusChange() is separated to + * one call of ReportNvramStatusChange(). + * @return None + */ + void ReportNvramStatusChange( const TDesC8& aNvram ); + + /** + * Reports about external handle command error condition. + * This is for cases when for example DUN decided the reply contained an + * error condition but the plugin is still handling the command internally. + * Example: in command line "AT+TEST;ATDT1234" was given. "AT+TEST" returns + * "OK" and "ATDT" returns "CONNECT". Because "OK" and "CONNECT" are + * different reply types the condition is "ERROR" and DUN ends processing. + * This solution keeps the pointer to the last AT command handling plugin + * inside ATEXT and calls this function there to report the error. + * It is to be noted that HandleCommandCancel() is not sufficient to stop + * the processing as the command handling has already finished. + * + * @since S60 5.0 + * @return None + */ + void ReportExternalHandleCommandError(); + + /** + * Creates part of reply from the global reply buffer to the destination + * buffer. Used with APIs which need the next part of reply in multipart + * reply requests. + * + * @since S60 5.0 + * @param aDstBuffer Destination buffer; the next part of reply is stored to + * this buffer. + * @return None + */ + TInt CreatePartOfReply( RBuf8& aDstBuffer ); + + /** + * Appends one parameter to array for GetParameterArray() + * + * @since S60 5.0 + * @param aParams Array of supported commands + * @param aStartIndex Start index for the parameter to be added + * @param aEndIndex End index for the parameter to be added + * @return None + */ + void AppendOneParameterLC( RPointerArray& aParams, + TInt& aStartIndex, + TInt aEndIndex ); + +// from base class MLegacyModemPlugin + + /** + * From MLegacyModemPlugin. + * Creates an AT command reply based on the reply type and completes the + * request to ATEXT. Uses iReplyBuffer for reply storage. + * + * @since S60 5.0 + * @param aReplyType Type of reply + * @param aSrcBuffer Source buffer; used only if aReplyType is EReplyTypeOther + * @param aError Completion code. If not KErrNone then other arguments are + * ignored and the request is completed to ATEXT with + * EReplyTypeUndefined. + * @return None + */ + TInt CreateReplyAndComplete( TATExtensionReplyType aReplyType, + const TDesC8& aSrcBuffer=KNullDesC8, + TInt aError=KErrNone ); + + /** + * From MLegacyModemPlugin. + * Creates a buffer for "OK" or "ERROR" reply based on the line settings + * + * @since S60 5.0 + * @param aReplyBuffer Destination buffer for the created reply + * @param aOkReply ETrue if "OK" reply needed, + * EFalse if "ERROR" reply needed + * @return Symbian error code on error, KErrNone otherwise + */ + TInt CreateOkOrErrorReply( RBuf8& aReplyBuffer, + TBool aOkReply ); + + /** + * From MLegacyModemPlugin. + * Checks if the command is a base, set, read or test type of command + * + * @since S60 5.0 + * @param aCmdBase Base part of the command to check + * @param aCmdFull Full command to check + * @return Type of command + */ + TCmdHandlerType CheckCommandType( const TDesC8& aCmdBase, + const TDesC8& aCmdFull ); + +private: // data + + /** + * AT commands handler array. Used for mapping HandleCommand() to + * IsCommandSupported() and to limit the number of string comparisons. + */ + RPointerArray iHandlers; + + /** + * Current AT command handler in iHandlers. + * Used when IsCommandSupported() detects a matching handler class. + */ + CLegacyModemPluginBase* iHandler; + + /** + * Buffer for handle command's command + * Not own. + */ + const TDesC8* iHcCmd; + + /** + * Buffer for handle command reply + * Not own. + */ + RBuf8* iHcReply; + + /** + * Global reply buffer for the AT command replies + */ + RBuf8 iReplyBuffer; + + }; + +#endif // C_LEGACYMODEMPLUGIN_H diff -r 0089b2f7ebd8 -r 907b2fb7aa8e atext/plugins/legacymodemplugin/inc/monitorspeakerparser.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/atext/plugins/legacymodemplugin/inc/monitorspeakerparser.h Fri Apr 16 16:09:25 2010 +0300 @@ -0,0 +1,163 @@ +/* +* Copyright (c) 2009 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: Handles commands "ATL", "ATL0", "ATL1", "ATL2", "ATL3", "ATM", +* "ATM0", "ATM1" and "ATM2" +* +*/ + +#ifndef C_MONITORSPEAKERPARSER_H +#define C_MONITORSPEAKERPARSER_H + +#include "legacymodemplugin.h" + +/** Detected commands */ +enum TDetectedCmd + { + EDetectedCmdUndefined, + EDetectedCmdATL, // For command "ATL" + EDetectedCmdATL0, // For command "ATL0" + EDetectedCmdATL1, // For command "ATL1" + EDetectedCmdATL2, // For command "ATL2" + EDetectedCmdATL3, // For command "ATL3" + EDetectedCmdATM, // For command "ATM" + EDetectedCmdATM0, // For command "ATM0" + EDetectedCmdATM1, // For command "ATM1" + EDetectedCmdATM2 // For command "ATM2" + }; + +/** + * Main class for handling commands "ATL", "ATL0", "ATL1", "ATL2", "ATL3", + * "ATM", "ATM0", "ATM1" and "ATM2" + * + * @since S60 v5.0 + */ +NONSHARABLE_CLASS( CMonitorSpeakerParser ) : public CLegacyModemPluginBase + { + +public: + + /** + * Two-phased constructor. + * @param aCallback Callback + * @return Instance of self + */ + static CMonitorSpeakerParser* NewL( MLegacyModemPlugin* aCallback ); + + /** + * Destructor. + */ + virtual ~CMonitorSpeakerParser(); + +private: + + CMonitorSpeakerParser( MLegacyModemPlugin* aCallback ); + + void ConstructL(); + + /** + * Checks if the command is speaker loudness command + * + * @param aCmd Command to check + * @return ETrue if command understood, EFalse otherwise + */ + TBool CheckSpeakerLoudnessCommand( const TDesC8& aCmd ); + + /** + * Checks if the command is speaker mode command + * + * @param aCmd Command to check + * @return ETrue if command understood, EFalse otherwise + */ + TBool CheckSpeakerModeCommand( const TDesC8& aCmd ); + + /** + * Main command handler (leaving version) + * + * @return ETrue if command understood, EFalse otherwise + */ + TBool HandleCommandL(); + +// from base class CLcCustomPluginBase + + /** + * From CLcCustomPluginBase. + * Reports the support status of an AT command. This is a synchronous API. + * + * @param aCmd The AT command. Its format may vary depending on the + * specification. E.g. in BT HFP case, the command may contain + * a character carriage return () in the end. + * @return ETrue if the command is supported; EFalse otherwise. + */ + TBool IsCommandSupported( const TDesC8& aCmd ); + + /** + * From CLcCustomPluginBase. + * Handles an AT command. Cancelling of the pending request is done by + * HandleCommandCancel(). The implementation in the extension plugin should + * be asynchronous. + * + * The extension plugin which accepts this command is responsible to supply + * the result codes and response and to format result codes properly, e.g. + * in BT HFP case, the format should be + * + * After an extension plugin has handled or decided to reject the given AT + * command, it must inform ATEXT by HandleCommandCompleted() with a proper + * error code. + * + * @since S60 5.0 + * @param aCmd The AT command to be handled. Its format may vary depending + * on the specification. E.g. in BT HFP case, the command may + * contain a character carriage return () in the end. + * @param aReply When passed in, contains the built in answer filled by + * ATEXT if it is not empty; when command handling completes + * successfully, contains the result codes and responses to + * this command; Its ownership always belongs to ATEXT, plugin + * may reallocate its space when needed. + * @param aReplyNeeded Reply needed if ETrue, no reply otherwise. If EFalse, + * the aReply must not contain the reply, otherwise it + * must contain verbose or numeric reply (ATV0/1) or an + * empty string reply (with ATQ). + * @return None + */ + void HandleCommand( const TDesC8& aCmd, RBuf8& aReply, TBool aReplyNeeded ); + + /** + * From CLcCustomPluginBase. + * Cancels a pending HandleCommand request. + * + * @since S60 5.0 + * @return None + */ + void HandleCommandCancel(); + +private: // data + + /** + * Callback to call when accessing plugin information + */ + MLegacyModemPlugin* iCallback; + + /** + * Handler type for the three types + */ + TCmdHandlerType iCmdHandlerType; + + /** + * Detected command + */ + TDetectedCmd iDetectedCmd; + + }; + +#endif // C_MONITORSPEAKERPARSER_H diff -r 0089b2f7ebd8 -r 907b2fb7aa8e atext/plugins/legacymodemplugin/inc/prjconfig.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/atext/plugins/legacymodemplugin/inc/prjconfig.h Fri Apr 16 16:09:25 2010 +0300 @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2008 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: Project configure file +* +*/ + + +#ifndef ATEXT_PRJCONFIG_H +#define ATEXT_PRJCONFIG_H + +/** + * Traces are enabled in _DEBUG build, by default. + */ +#ifdef _DEBUG +#define PRJ_ENABLE_TRACE +#endif + +/** + * traces to file if this is defined. + */ +//#define PRJ_FILE_TRACE + + +/** + * build the project for module test purpose if this is defined + */ +//#define PRJ_MODULETEST_BUILD + +/** + * build the project using stubs to replace the dependencies if this is defined + */ +//#define PRJ_USE_STUB + + +#endif // ATEXT_PRJCONFIG_H diff -r 0089b2f7ebd8 -r 907b2fb7aa8e atext/plugins/legacymodemplugin/rom/legacymodemplugin.iby --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/atext/plugins/legacymodemplugin/rom/legacymodemplugin.iby Fri Apr 16 16:09:25 2010 +0300 @@ -0,0 +1,23 @@ +/* +* Copyright (c) 2009 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: Image description file for project LegacyModemPlugin +* +*/ + +#ifndef __LEGACYMODEMPLUGIN_IBY__ +#define __LEGACYMODEMPLUGIN_IBY__ + +ECOM_PLUGIN( legacymodemplugin.dll, legacymodemplugin.rsc ) + +#endif diff -r 0089b2f7ebd8 -r 907b2fb7aa8e atext/plugins/legacymodemplugin/src/2002B340.rss --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/atext/plugins/legacymodemplugin/src/2002B340.rss Fri Apr 16 16:09:25 2010 +0300 @@ -0,0 +1,45 @@ +/* +* Copyright (c) 2009 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: Resource definitions for project LegacyModemPlugin +* +*/ + +#include + +// Declares info for two implementations +RESOURCE REGISTRY_INFO theInfo + { + // UID for the DLL + dll_uid = 0x2002B340; + // Declare array of interface info + interfaces = + { + INTERFACE_INFO + { + // UID of interface that is implemented + interface_uid = 0x2001CBEE; // ATEXT_INTERFACE_DUN_UID + implementations = + { + IMPLEMENTATION_INFO + { + implementation_uid = 0x2002B341; + version_no = 1; + display_name = "LegacyModemPlugin"; + default_data = "MATL|MATL0|MATL1|MATL2|MATL3|MATM|MATM0|MATM1|MATM2"; + opaque_data = ""; + } + }; + } + }; + } diff -r 0089b2f7ebd8 -r 907b2fb7aa8e atext/plugins/legacymodemplugin/src/legacymodemplugin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/atext/plugins/legacymodemplugin/src/legacymodemplugin.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -0,0 +1,408 @@ +/* +* Copyright (c) 2009 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: Main handler for incoming requests +* +*/ + +#include "legacymodemplugin.h" +#include "monitorspeakerparser.h" +#include "debug.h" + +const TInt KErrorReplyLength = 9; // CR+LF+"ERROR"+CR+LF + +// --------------------------------------------------------------------------- +// Two-phased constructor. +// --------------------------------------------------------------------------- +// +CLegacyModemPlugin* CLegacyModemPlugin::NewL() + { + CLegacyModemPlugin* self = new (ELeave) CLegacyModemPlugin(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +// --------------------------------------------------------------------------- +// Destructor. +// --------------------------------------------------------------------------- +// +CLegacyModemPlugin::~CLegacyModemPlugin() + { + iHandlers.ResetAndDestroy(); + iHandlers.Close(); + iReplyBuffer.Close(); + } + +// --------------------------------------------------------------------------- +// CLegacyModemPlugin::CLegacyModemPlugin +// --------------------------------------------------------------------------- +// +CLegacyModemPlugin::CLegacyModemPlugin() : CATExtPluginBase() + { + iHandler = NULL; + iHcCmd = NULL; + iHcReply = NULL; + } + +// --------------------------------------------------------------------------- +// CLegacyModemPlugin::ConstructL +// --------------------------------------------------------------------------- +// +void CLegacyModemPlugin::ConstructL() + { + CLegacyModemPluginBase* handler = NULL; + handler = CMonitorSpeakerParser::NewL( this ); + CleanupStack::PushL( handler ); + iHandlers.AppendL( handler ); + CleanupStack::Pop( handler ); + } + +// --------------------------------------------------------------------------- +// Reports connection identifier name to the extension plugin. +// --------------------------------------------------------------------------- +// +void CLegacyModemPlugin::ReportConnectionName( const TDesC8& /*aName*/ ) + { + } + +// --------------------------------------------------------------------------- +// Reports the support status of an AT command. This is a synchronous API. +// --------------------------------------------------------------------------- +// +TBool CLegacyModemPlugin::IsCommandSupported( const TDesC8& aCmd ) + { + TRACE_FUNC_ENTRY + iHcCmd = NULL; + iHcReply = NULL; + TInt i; + TInt count = iHandlers.Count(); + for ( i=0; iIsCommandSupported( aCmd ); + if ( supported ) + { + iHandler = handler; + TRACE_FUNC_EXIT + return ETrue; + } + } + iHandler = NULL; + TRACE_FUNC_EXIT + return EFalse; + } + +// --------------------------------------------------------------------------- +// Handles an AT command. Cancelling of the pending request is done by +// HandleCommandCancel(). The implementation in the extension plugin should +// be asynchronous. +// --------------------------------------------------------------------------- +// +void CLegacyModemPlugin::HandleCommand( const TDesC8& aCmd, + RBuf8& aReply, + TBool aReplyNeeded ) + { + TRACE_FUNC_ENTRY + if ( iHandler ) + { + iHcCmd = &aCmd; + iHcReply = &aReply; + iHandler->HandleCommand( aCmd, aReply, aReplyNeeded ); + } + TRACE_FUNC_EXIT + } + +// --------------------------------------------------------------------------- +// Cancels a pending HandleCommand request. +// --------------------------------------------------------------------------- +// +void CLegacyModemPlugin::HandleCommandCancel() + { + TRACE_FUNC_ENTRY + if ( iHandler ) + { + iHandler->HandleCommandCancel(); + } + TRACE_FUNC_EXIT + } + +// --------------------------------------------------------------------------- +// Next reply part's length. +// The value must be equal or less than KDefaultCmdBufLength. +// When the reply from this method is zero, ATEXT stops calling +// GetNextPartOfReply(). +// --------------------------------------------------------------------------- +// +TInt CLegacyModemPlugin::NextReplyPartLength() + { + TRACE_FUNC_ENTRY + if ( iReplyBuffer.Length() < KDefaultCmdBufLength ) + { + TRACE_FUNC_EXIT + return iReplyBuffer.Length(); + } + TRACE_FUNC_EXIT + return KDefaultCmdBufLength; + } + +// --------------------------------------------------------------------------- +// Gets the next part of reply initially set by HandleCommandComplete(). +// Length of aNextReply must be equal or less than KDefaultCmdBufLength. +// --------------------------------------------------------------------------- +// +TInt CLegacyModemPlugin::GetNextPartOfReply( RBuf8& aNextReply ) + { + TRACE_FUNC_ENTRY + TInt retVal = CreatePartOfReply( aNextReply ); + TRACE_FUNC_EXIT + return retVal; + } + +// --------------------------------------------------------------------------- +// Receives unsolicited results. Cancelling of the pending request is done by +// by ReceiveUnsolicitedResultCancel(). The implementation in the extension +// plugin should be asynchronous. +// --------------------------------------------------------------------------- +// +void CLegacyModemPlugin::ReceiveUnsolicitedResult() + { + TRACE_FUNC_ENTRY + TRACE_FUNC_EXIT + } + +// --------------------------------------------------------------------------- +// Cancels a pending ReceiveUnsolicitedResult request. +// --------------------------------------------------------------------------- +// +void CLegacyModemPlugin::ReceiveUnsolicitedResultCancel() + { + TRACE_FUNC_ENTRY + TRACE_FUNC_EXIT + } + +// --------------------------------------------------------------------------- +// Reports NVRAM status change to the plugins. +// --------------------------------------------------------------------------- +// +void CLegacyModemPlugin::ReportNvramStatusChange( const TDesC8& /*aNvram*/ ) + { + TRACE_FUNC_ENTRY + TRACE_FUNC_EXIT + } + +// --------------------------------------------------------------------------- +// Reports about external handle command error condition. +// This is for cases when for example DUN decided the reply contained an +// error condition but the plugin is still handling the command internally. +// Example: "AT+TEST;+TEST2" was given in command line; "AT+TEST" returns +// non-EReplyTypeError condition and "AT+TEST2" returns EReplyTypeError. +// As the plugin(s) returning the non-EReplyTypeError may still have some +// ongoing operation then these plugins are notified about the external +// EReplyTypeError in command line processing. It is to be noted that +// HandleCommandCancel() is not sufficient to stop the processing as the +// command handling has already finished. +// --------------------------------------------------------------------------- +// +void CLegacyModemPlugin::ReportExternalHandleCommandError() + { + TRACE_FUNC_ENTRY + TRACE_FUNC_EXIT + } + +// --------------------------------------------------------------------------- +// Creates part of reply from the global reply buffer to the destination +// buffer. Used with APIs which need the next part of reply in multipart reply +// requests. +// --------------------------------------------------------------------------- +// +TInt CLegacyModemPlugin::CreatePartOfReply( RBuf8& aDstBuffer ) + { + TRACE_FUNC_ENTRY + if ( iReplyBuffer.Length() <= 0 ) + { + TRACE_FUNC_EXIT + return KErrGeneral; + } + TInt partLength = NextReplyPartLength(); + if ( iReplyBuffer.Length() < partLength ) + { + TRACE_FUNC_EXIT + return KErrNotFound; + } + aDstBuffer.Create( iReplyBuffer, partLength ); + iReplyBuffer.Delete( 0, partLength ); + if ( iReplyBuffer.Length() == 0 ) + { + iReplyBuffer.Close(); + } + TRACE_FUNC_EXIT + return KErrNone; + } + +// --------------------------------------------------------------------------- +// Creates an AT command reply based on the reply type and completes the +// request to ATEXT. Uses iReplyBuffer for reply storage. +// --------------------------------------------------------------------------- +// +TInt CLegacyModemPlugin::CreateReplyAndComplete( + TATExtensionReplyType aReplyType, + const TDesC8& aSrcBuffer, + TInt aError ) + { + TRACE_FUNC_ENTRY + iReplyBuffer.Close(); + if ( aError != KErrNone ) + { + HandleCommandCompleted( aError, EReplyTypeUndefined ); + iHcCmd = NULL; + iHcReply = NULL; + TRACE_FUNC_EXIT + return KErrNone; + } + if ( !iHcReply ) + { + TRACE_FUNC_EXIT + return KErrGeneral; + } + switch ( aReplyType ) + { + case EReplyTypeOther: + if ( iQuietMode || !iVerboseMode ) + { + iReplyBuffer.Create( KNullDesC8 ); + } + else + { + iReplyBuffer.Create( aSrcBuffer ); + } + break; + case EReplyTypeOk: + CreateOkOrErrorReply( iReplyBuffer, ETrue ); + break; + case EReplyTypeError: + CreateOkOrErrorReply( iReplyBuffer, EFalse ); + break; + default: + TRACE_FUNC_EXIT + return KErrGeneral; + } + CreatePartOfReply( *iHcReply ); + HandleCommandCompleted( KErrNone, aReplyType ); + iHcCmd = NULL; + iHcReply = NULL; + TRACE_FUNC_EXIT + return KErrNone; + } + +// --------------------------------------------------------------------------- +// Creates a buffer for "OK" or "ERROR" reply based on the line settings +// --------------------------------------------------------------------------- +// +TInt CLegacyModemPlugin::CreateOkOrErrorReply( RBuf8& aReplyBuffer, + TBool aOkReply ) + { + TRACE_FUNC_ENTRY + if ( iQuietMode ) + { + TRACE_FUNC_EXIT + return iReplyBuffer.Create( KNullDesC8 ); + } + _LIT8( KErrorReplyVerbose, "ERROR" ); + _LIT8( KOkReplyVerbose, "OK" ); + _LIT8( KErrorReplyNumeric, "4" ); + _LIT8( KOkReplyNumeric, "0" ); + TBuf8 replyBuffer; + if ( iVerboseMode ) + { + replyBuffer.Append( iCarriageReturn ); + replyBuffer.Append( iLineFeed ); + if ( aOkReply ) + { + replyBuffer.Append( KOkReplyVerbose ); + } + else + { + replyBuffer.Append( KErrorReplyVerbose ); + } + replyBuffer.Append( iCarriageReturn ); + replyBuffer.Append( iLineFeed ); + } + else + { + if ( aOkReply ) + { + replyBuffer.Append( KOkReplyNumeric ); + } + else + { + replyBuffer.Append( KErrorReplyNumeric ); + } + replyBuffer.Append( iCarriageReturn ); + } + TInt retVal = aReplyBuffer.Create( replyBuffer ); + TRACE_FUNC_EXIT + return retVal; + } + +// --------------------------------------------------------------------------- +// From MHfpExtPlugin. +// Checks if the command is a base, set, read or test type of command +// --------------------------------------------------------------------------- +// +TCmdHandlerType CLegacyModemPlugin::CheckCommandType( const TDesC8& aCmdBase, + const TDesC8& aCmdFull ) + { + TRACE_FUNC_ENTRY + TInt retTemp = KErrNone; + TBuf8 atCmdBuffer; + atCmdBuffer.Copy( aCmdBase ); + // Check "base" command ("AT+COMMAND") + retTemp = aCmdFull.Compare( atCmdBuffer ); + if ( retTemp == 0 ) + { + TRACE_FUNC_EXIT + return ECmdHandlerTypeBase; + } + // Check "read" command ("AT+COMMAND?") + // Add last question mark + atCmdBuffer.Append( '?' ); + retTemp = aCmdFull.Compare( atCmdBuffer ); + if ( retTemp == 0 ) + { + TRACE_FUNC_EXIT + return ECmdHandlerTypeRead; + } + // Check "test" command ("AT+COMMAND=?") + // Add "=" before the question mark + _LIT8( KAssignmentMark, "=" ); + atCmdBuffer.Insert( atCmdBuffer.Length()-1, KAssignmentMark ); + retTemp = aCmdFull.Compare( atCmdBuffer ); + if ( retTemp == 0 ) + { + TRACE_FUNC_EXIT + return ECmdHandlerTypeTest; + } + // Check "set" command ("AT+COMMAND=") + // Remove last question mark + atCmdBuffer.SetLength( atCmdBuffer.Length() - 1 ); + retTemp = aCmdFull.Compare( atCmdBuffer ); + if ( retTemp == 0 ) + { + TRACE_FUNC_EXIT + return ECmdHandlerTypeSet; + } + TRACE_FUNC_EXIT + return ECmdHandlerTypeUndefined; + } diff -r 0089b2f7ebd8 -r 907b2fb7aa8e atext/plugins/legacymodemplugin/src/monitorspeakerparser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/atext/plugins/legacymodemplugin/src/monitorspeakerparser.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -0,0 +1,256 @@ +/* +* Copyright (c) 2009 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: Handles commands "ATL", "ATL0", "ATL1", "ATL2", "ATL3", "ATM", +* "ATM0", "ATM1" and "ATM2" +* +*/ + +#include "monitorspeakerparser.h" +#include "debug.h" + +_LIT8( KAtlCmd, "ATL" ); +_LIT8( KAtl0Cmd, "ATL0" ); +_LIT8( KAtl1Cmd, "ATL1" ); +_LIT8( KAtl2Cmd, "ATL2" ); +_LIT8( KAtl3Cmd, "ATL3" ); +_LIT8( KAtmCmd, "ATM" ); +_LIT8( KAtm0Cmd, "ATM0" ); +_LIT8( KAtm1Cmd, "ATM1" ); +_LIT8( KAtm2Cmd, "ATM2" ); + +// --------------------------------------------------------------------------- +// Two-phased constructor. +// --------------------------------------------------------------------------- +// +CMonitorSpeakerParser* CMonitorSpeakerParser::NewL( + MLegacyModemPlugin* aCallback ) + { + CMonitorSpeakerParser* self = new (ELeave) CMonitorSpeakerParser( aCallback ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// Destructor. +// --------------------------------------------------------------------------- +// +CMonitorSpeakerParser::~CMonitorSpeakerParser() + { + } + +// --------------------------------------------------------------------------- +// CHfpExtParserMisc::CHfpExtParserMisc +// --------------------------------------------------------------------------- +// +CMonitorSpeakerParser::CMonitorSpeakerParser( MLegacyModemPlugin* aCallback ) : + iCallback( aCallback ) + { + iCmdHandlerType = ECmdHandlerTypeUndefined; + iDetectedCmd = EDetectedCmdUndefined; + } + +// --------------------------------------------------------------------------- +// CHfpExtParserMisc::ConstructL +// --------------------------------------------------------------------------- +// +void CMonitorSpeakerParser::ConstructL() + { + if ( !iCallback ) + { + User::Leave( KErrGeneral ); + } + } + +// --------------------------------------------------------------------------- +// Checks if the command is speaker loudness command +// --------------------------------------------------------------------------- +// +TBool CMonitorSpeakerParser::CheckSpeakerLoudnessCommand( const TDesC8& aCmd ) + { + TRACE_FUNC_ENTRY + // The ATL command only supports one type: base + // The ATL0 command only supports one type: base + // The ATL1 command only supports one type: base + // The ATL2 command only supports one type: base + // The ATL3 command only supports one type: base + iCmdHandlerType = iCallback->CheckCommandType( KAtlCmd, aCmd ); + if ( iCmdHandlerType == ECmdHandlerTypeBase ) + { + iDetectedCmd = EDetectedCmdATL; + TRACE_FUNC_EXIT + return ETrue; + } + iCmdHandlerType = iCallback->CheckCommandType( KAtl0Cmd, aCmd ); + if ( iCmdHandlerType == ECmdHandlerTypeBase ) + { + iDetectedCmd = EDetectedCmdATL0; + TRACE_FUNC_EXIT + return ETrue; + } + iCmdHandlerType = iCallback->CheckCommandType( KAtl1Cmd, aCmd ); + if ( iCmdHandlerType == ECmdHandlerTypeBase ) + { + iDetectedCmd = EDetectedCmdATL1; + TRACE_FUNC_EXIT + return ETrue; + } + iCmdHandlerType = iCallback->CheckCommandType( KAtl2Cmd, aCmd ); + if ( iCmdHandlerType == ECmdHandlerTypeBase ) + { + iDetectedCmd = EDetectedCmdATL2; + TRACE_FUNC_EXIT + return ETrue; + } + iCmdHandlerType = iCallback->CheckCommandType( KAtl3Cmd, aCmd ); + if ( iCmdHandlerType == ECmdHandlerTypeBase ) + { + iDetectedCmd = EDetectedCmdATL3; + TRACE_FUNC_EXIT + return ETrue; + } + TRACE_FUNC_EXIT + return EFalse; + } + +// --------------------------------------------------------------------------- +// Checks if the command is speaker mode command +// --------------------------------------------------------------------------- +// +TBool CMonitorSpeakerParser::CheckSpeakerModeCommand( const TDesC8& aCmd ) + { + TRACE_FUNC_ENTRY + // The ATM command only supports one type: base + // The ATM0 command only supports one type: base + // The ATM1 command only supports one type: base + // The ATM2 command only supports one type: base + iCmdHandlerType = iCallback->CheckCommandType( KAtmCmd, aCmd ); + if ( iCmdHandlerType == ECmdHandlerTypeBase ) + { + iDetectedCmd = EDetectedCmdATM; + TRACE_FUNC_EXIT + return ETrue; + } + iCmdHandlerType = iCallback->CheckCommandType( KAtm0Cmd, aCmd ); + if ( iCmdHandlerType == ECmdHandlerTypeBase ) + { + iDetectedCmd = EDetectedCmdATM0; + TRACE_FUNC_EXIT + return ETrue; + } + iCmdHandlerType = iCallback->CheckCommandType( KAtm1Cmd, aCmd ); + if ( iCmdHandlerType == ECmdHandlerTypeBase ) + { + iDetectedCmd = EDetectedCmdATM1; + TRACE_FUNC_EXIT + return ETrue; + } + iCmdHandlerType = iCallback->CheckCommandType( KAtm2Cmd, aCmd ); + if ( iCmdHandlerType == ECmdHandlerTypeBase ) + { + iDetectedCmd = EDetectedCmdATM2; + TRACE_FUNC_EXIT + return ETrue; + } + TRACE_FUNC_EXIT + return EFalse; + } + +// --------------------------------------------------------------------------- +// Main command handler (leaving version) +// --------------------------------------------------------------------------- +// +TBool CMonitorSpeakerParser::HandleCommandL() + { + TRACE_FUNC_ENTRY + TBool cmdUnderstood = EFalse; + // Just return "OK" for all detected commands + if ( iDetectedCmd != EDetectedCmdUndefined ) + { + iCallback->CreateReplyAndComplete( EReplyTypeOk ); + cmdUnderstood = ETrue; + } + TRACE_FUNC_EXIT + return cmdUnderstood; + } + +// --------------------------------------------------------------------------- +// From CLegacyModemPluginBase. +// Reports the support status of an AT command. This is a synchronous API. +// --------------------------------------------------------------------------- +// +TBool CMonitorSpeakerParser::IsCommandSupported( const TDesC8& aCmd ) + { + TRACE_FUNC_ENTRY + TBool cmdUnderstood = EFalse; + // Set all to undefined if either the command or its type is unknown + // HandleCommand() should be round only when both are set + cmdUnderstood = CheckSpeakerLoudnessCommand( aCmd ); + if ( cmdUnderstood ) + { + TRACE_FUNC_EXIT + return ETrue; + } + cmdUnderstood = CheckSpeakerModeCommand( aCmd ); + if ( cmdUnderstood ) + { + TRACE_FUNC_EXIT + return ETrue; + } + iCmdHandlerType = ECmdHandlerTypeUndefined; + iDetectedCmd = EDetectedCmdUndefined; + TRACE_FUNC_EXIT + return EFalse; + } + +// --------------------------------------------------------------------------- +// From CLegacyModemPluginBase. +// Handles an AT command. Cancelling of the pending request is done by +// HandleCommandCancel(). The implementation in the extension plugin should +// be asynchronous. +// --------------------------------------------------------------------------- +// +void CMonitorSpeakerParser::HandleCommand( const TDesC8& /*aCmd*/, + RBuf8& /*aReply*/, + TBool aReplyNeeded ) + { + TRACE_FUNC_ENTRY + if ( !aReplyNeeded ) + { + TRACE_FUNC_EXIT + return; + } + // Checking the iDetectedCmd here means that the failure is the + // failing cmd type (set/read/test) for the command, not the command + // itself (when cmdUnderstood is EFalse) + TBool cmdUnderstood = EFalse; + TRAPD( retTrap, cmdUnderstood=HandleCommandL() ) + if ( !cmdUnderstood || retTrap!=KErrNone ) + { + iCallback->CreateReplyAndComplete( EReplyTypeError ); + } + TRACE_FUNC_EXIT + } + +// --------------------------------------------------------------------------- +// From CLegacyModemPluginBase. +// Cancels a pending HandleCommand request. +// --------------------------------------------------------------------------- +// +void CMonitorSpeakerParser::HandleCommandCancel() + { + TRACE_FUNC_ENTRY + TRACE_FUNC_EXIT + } diff -r 0089b2f7ebd8 -r 907b2fb7aa8e atext/plugins/legacymodemplugin/src/proxy.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/atext/plugins/legacymodemplugin/src/proxy.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -0,0 +1,42 @@ +/* +* Copyright (c) 2009 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: Export ECom interface implementations +* +*/ + +#include +#include +#include "legacymodemplugin.h" + +// --------------------------------------------------------------------------- +// An array of TImplementationProxy objects which onnect each +// implemeation with its instantiation function +// --------------------------------------------------------------------------- +// +const TImplementationProxy ImplementationTable[] = + { + IMPLEMENTATION_PROXY_ENTRY(0x2002B341, CLegacyModemPlugin::NewL), // DUN + }; + +// --------------------------------------------------------------------------- +// Exported proxy function to resolve instantiation methods for an Ecom +// plug-in DLL +// --------------------------------------------------------------------------- +// +EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) + { + aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); + + return ImplementationTable; + } diff -r 0089b2f7ebd8 -r 907b2fb7aa8e atext/server/inc/atextmetadata.h --- a/atext/server/inc/atextmetadata.h Fri Mar 19 09:53:48 2010 +0200 +++ b/atext/server/inc/atextmetadata.h Fri Apr 16 16:09:25 2010 +0300 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +* Copyright (c) 2008-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" @@ -28,8 +28,10 @@ /** Panic categories */ enum TATExtPanicCategories { - EPanicCategoryFaultyMaster = 1, - EPanicCategoryPluginType = 2 + EPanicCategoryAddPIsM = 1, // Master exists while adding Partial + EPanicCategoryAddMIsP = 2, // Partial exists while adding Master + EPanicCategoryAddMIsM = 3, // Master exists while adding Master + EPanicCategoryType = 4 // Wrong plugin type (not M|P|O) }; /** Support types supported by RSS file (M|P|O) */ diff -r 0089b2f7ebd8 -r 907b2fb7aa8e atext/server/src/atextmetadata.cpp --- a/atext/server/src/atextmetadata.cpp Fri Mar 19 09:53:48 2010 +0200 +++ b/atext/server/src/atextmetadata.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +* Copyright (c) 2008-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" @@ -42,7 +42,7 @@ */ #include -#include +#include #include #include "atextclientsrv.h" #include "atextmetadata.h" @@ -1369,7 +1369,7 @@ break; default: _LIT( KPluginType, "PluginType" ); - User::Panic( KPluginType, EPanicCategoryPluginType ); + User::Panic( KPluginType, EPanicCategoryType ); } i++; if ( i >= count ) @@ -1558,10 +1558,15 @@ if ( aEntries->Count() > 0 ) { TATExtOneCmdSupport& oneCmdSupport = (*aEntries)[0]; + if ( oneCmdSupport.iSupportType == ESupportTypePartial ) + { + _LIT( KAddMIsP, "AddMIsP" ); + User::Panic( KAddMIsP, EPanicCategoryAddMIsP ); + } if ( oneCmdSupport.iSupportType == ESupportTypeMaster ) { - _LIT( KFaultyMaster, "FaultyMaster" ); - User::Panic( KFaultyMaster, EPanicCategoryFaultyMaster ); + _LIT( KAddMIsM, "AddMIsM" ); + User::Panic( KAddMIsM, EPanicCategoryAddMIsM ); } } aEntries->InsertL( 0, aOneCmdSupport ); @@ -1588,6 +1593,15 @@ TATExtOneCmdSupport& aOneCmdSupport ) { TRACE_FUNC_ENTRY + if ( aEntries->Count() > 0 ) + { + TATExtOneCmdSupport& oneCmdSupport = (*aEntries)[0]; + if ( oneCmdSupport.iSupportType == ESupportTypeMaster ) + { + _LIT( KAddPIsM, "AddPIsM" ); + User::Panic( KAddPIsM, EPanicCategoryAddPIsM ); + } + } TInt i = aSearchHelper.iPartialIndex; if ( i < 0 ) { diff -r 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btcomm/src/states.cpp --- a/bluetooth/btcomm/src/states.cpp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btcomm/src/states.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -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; @@ -798,6 +799,7 @@ CleanupStack::PopAndDestroy(2); TSDPAttributeKey key; + Mem::FillZ(&key, sizeof(TSDPAttributeKey)); key.iMaxLength = 200; key.iRange = EFalse; key.iStateLength = 0; diff -r 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btdocs/Designs/backuprestore.mdzip Binary file bluetooth/btdocs/Designs/backuprestore.mdzip has changed diff -r 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btextnotifiers/bwins/BTEXTNOTIFIERSU.DEF --- a/bluetooth/btextnotifiers/bwins/BTEXTNOTIFIERSU.DEF Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btextnotifiers/bwins/BTEXTNOTIFIERSU.DEF Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btextnotifiers/eabi/BTExtNotifiersU.DEF --- a/bluetooth/btextnotifiers/eabi/BTExtNotifiersU.DEF Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btextnotifiers/eabi/BTExtNotifiersU.DEF Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btextnotifiers/inc/BTExtNotifiersPartner.h --- a/bluetooth/btextnotifiers/inc/BTExtNotifiersPartner.h Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btextnotifiers/inc/BTExtNotifiersPartner.h Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btextnotifiers/src/BTExtNotifiers.cpp --- a/bluetooth/btextnotifiers/src/BTExtNotifiers.cpp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btextnotifiers/src/BTExtNotifiers.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btstack/avctp/avctp.cpp --- a/bluetooth/btstack/avctp/avctp.cpp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btstack/avctp/avctp.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btstack/avctp/avctpmuxerstates.cpp --- a/bluetooth/btstack/avctp/avctpmuxerstates.cpp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btstack/avctp/avctpmuxerstates.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btstack/common/bt_v2.mmp --- a/bluetooth/btstack/common/bt_v2.mmp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btstack/common/bt_v2.mmp Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btstack/linkmgr/Subscribers.cpp --- a/bluetooth/btstack/linkmgr/Subscribers.cpp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btstack/linkmgr/Subscribers.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btstack/linkmgr/Subscribers.h --- a/bluetooth/btstack/linkmgr/Subscribers.h Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btstack/linkmgr/Subscribers.h Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btstack/linkmgr/bredrcontrollerconfiguration.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btstack/linkmgr/bredrcontrollerconfiguration.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btstack/linkmgr/bredrcontrollerconfiguration.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btstack/linkmgr/bredrcontrollerconfiguration.h Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btstack/linkmgr/hcifacade.cpp --- a/bluetooth/btstack/linkmgr/hcifacade.cpp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btstack/linkmgr/hcifacade.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btstack/linkmgr/linkmgr.cpp --- a/bluetooth/btstack/linkmgr/linkmgr.cpp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btstack/linkmgr/linkmgr.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btstack/linkmgr/linkmgr.h --- a/bluetooth/btstack/linkmgr/linkmgr.h Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btstack/linkmgr/linkmgr.h Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btstack/linkmgr/physicallinks.cpp --- a/bluetooth/btstack/linkmgr/physicallinks.cpp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btstack/linkmgr/physicallinks.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -384,49 +384,12 @@ // Store the result of the retrieval for usage later. iDeviceResult = aResult; - // the HW asked earlier for a link key - we can respond now - __ASSERT_DEBUG(iDevice.IsValidAddress(), Panic(EBTPhysicalLinksInvalidAddress)); - if(iWaitingForLinkKeyFromRegistry) + if (iLinkKeyRequestOutstanding) { - if (aResult == KErrNone && iDevice.IsValidLinkKey()) - { - if ( iDevice.LinkKeyType() != ELinkKeyCombination) - { - if (iLinksMan.SecMan().DebugMode() && iDevice.LinkKeyType() != ELinkKeyDebug) - { - LOG(_L("CPhysicalLink: Debug mode - Link to debug link key")) - iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address()); - } - else - if (iRequireAuthenticatedLinkKey && iDevice.LinkKeyType() == ELinkKeyUnauthenticatedUpgradable && IsPairable()) - { - LOG(_L("CPhysicalLink: Requiring Authenticated link key but currently only have unauthenticated")) - iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address()); - } - else - { - LOG(_L("CPhysicalLink: Issuing link key to HC now")) - iAuthenticationCtrl.LinkKeyRequestReply(iDevice.Address(), iDevice.LinkKey()); - } - } - else if(IsPasskeyMinLengthOK() && SimplePairingMode() != EPhySimplePairingEnabled) - { - LOG(_L("CPhysicalLink: Issuing link key to HC now")) - iAuthenticationCtrl.LinkKeyRequestReply(iDevice.Address(), iDevice.LinkKey()); - } - else - { - LOG(_L("CPhysicalLink: Current PIN code too short!")) - iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address()); - } - } - else - { - iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address()); - } + // the HW asked earlier for a link key - we can respond now + __ASSERT_DEBUG(iDevice.IsValidAddress(), Panic(EBTPhysicalLinksInvalidAddress)); + LinkKeyRequestResponseAttempt(ETrue); } - iRequireAuthenticatedLinkKey = EFalse; - iWaitingForLinkKeyFromRegistry = EFalse; RegistryTaskComplete(aHelper, aResult); // cleans up our helper } @@ -546,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 @@ -609,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()); @@ -708,15 +678,9 @@ } else { - // If the remote doesn't support extended features, then neither they support SSP - // (no way to indicate the host supported bit). So set it as disabled. - TPhysicalLinkSimplePairingMode previousSetting = SimplePairingMode(); - __ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingDisabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection)); - iSimplePairingMode = EPhySimplePairingDisabled; - if(SimplePairingMode() != previousSetting) - { - iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr()); - } + // If the remote doesn't support extended features, then they cannot support SSP + // (no way to indicate the host supported bit). So set feature as disabled. + RemoteSimplePairingModeDetermined(EPhySimplePairingDisabled); } } else @@ -740,18 +704,12 @@ if (aErr == EOK && aBitMask & (1 << ESecureSimplePairingHostSupportBit) && iLinksMan.SecMan().LocalSimplePairingMode()) { - __ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingEnabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection)); - iSimplePairingMode = EPhySimplePairingEnabled; + RemoteSimplePairingModeDetermined(EPhySimplePairingEnabled); } else { - __ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingDisabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection)); - iSimplePairingMode = EPhySimplePairingDisabled; + RemoteSimplePairingModeDetermined(EPhySimplePairingDisabled); } - if(SimplePairingMode()!=currentSetting) - { - iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr()); - } break; } default: @@ -908,6 +866,7 @@ TRAP(err, iLinksMan.HCIFacade().AuthenticateL(Handle())); if(err == KErrNone) { + iLinkKeyReturnedInThisAuthentication = EFalse; SetAuthenticationPending(EAuthenticationRequestPending); } } @@ -2835,18 +2794,19 @@ SetAuthenticationPending(EPinRequestPending); // if not already set (because the remote initiated authentication). - __ASSERT_DEBUG(iSimplePairingMode != EPhySimplePairingEnabled, Panic(EBTSSPModeChangedDuringConnection)); - if (iSimplePairingMode == EPhySimplePairingUndefined) - { - iSimplePairingMode = EPhySimplePairingDisabled; - } - if (!IsConnected()) { - iPeerInSecurityMode3 = ETrue; + // If the ACL to the peer device is not yet connected, and the peer has initiated + // authentication then it must be in security mode 3. This information is stored and + // if the connection completes the link will be set as authenticated. + SetPeerInSecurityMode3(); } - + // We can receive "fast" PIN requests if the remote device initiates pairing and indicates + // it doesn't have a link key. If we see this then we know that we are not engaging in + // simple pairing on this particular link. + RemoteSimplePairingModeDetermined(EPhySimplePairingDisabled); + if (iPinRequester) { return; @@ -2989,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 @@ -3056,9 +3022,14 @@ return isPasskeyMinLengthOK; } -void CPhysicalLink::LinkKeyRequest(const TBTDevAddr& aAddr, MLinkKeyResponseHandler& /*aRequester*/) +void CPhysicalLink::LinkKeyRequest(const TBTDevAddr& __DEBUG_ONLY(aAddr), MLinkKeyResponseHandler& /*aRequester*/) { LOG_FUNC + __ASSERT_DEBUG(aAddr == BDAddr(), Panic(EBTConnectionBadDeviceAddress)); + ASSERT_DEBUG(!iLinkKeyRequestOutstanding); + + iLinkKeyRequestOutstanding = ETrue; + // we don't keep a copy of the device record - we just leave the one copy with // the baseband - it can tell us if there's a link key // we can tell if the baseband has the device record or not @@ -3070,68 +3041,13 @@ // if the connection completes the link will be set as authenticated. if (!IsConnected()) { - iPeerInSecurityMode3 = ETrue; - } - - if(!iPeerInSecurityMode3 && iLinksMan.SecMan().IsDedicatedBondingAttempted(iDevice.Address())) - { - // If we are doing DedicatedBonding then we should ignore the existing linkkey - // in an attempt to generate a stronger one if possible. - // Security mode 3 is a odd case - because we get what looks like double pairing (the remote - // initiated pairing on connection, then the dedicated bonding pairing). So we have removed - // this feature for security mode 3 devices...they will have to suffer for their transgressions - LOG(_L("CPhysicalLink: Dedicated bonding attempt - Sending link key request negative reply")); - iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr); - iRequireAuthenticatedLinkKey = EFalse; + SetPeerInSecurityMode3(); } - else if (iDeviceResult==KErrNone && iDevice.IsValidLinkKey()) - { - if (iLinksMan.SecMan().DebugMode() && iDevice.LinkKeyType() != ELinkKeyDebug) - { - LOG(_L("CPhysicalLink: Debug mode - Link to debug link key")) - iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr); - } - else - { - if (iDevice.LinkKeyType() != ELinkKeyCombination) - { - if (iRequireAuthenticatedLinkKey && iDevice.LinkKeyType() == ELinkKeyUnauthenticatedUpgradable && IsPairable()) - { - LOG(_L("CPhysicalLink: Requiring Authenticated link key but currently only have unauthenticated")) - iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr); - } - else - { - LOG(_L("CPhysicalLink: Issuing link key to HC now")) - iAuthenticationCtrl.LinkKeyRequestReply(aAddr, iDevice.LinkKey()); - } - } - else if(IsPasskeyMinLengthOK() && SimplePairingMode() != EPhySimplePairingEnabled) - { - LOG(_L("CPhysicalLink: Issuing link key to HC now")) - iAuthenticationCtrl.LinkKeyRequestReply(aAddr, iDevice.LinkKey()); - } - else - { - LOG(_L("CPhysicalLink: Current PIN code too short!")) - iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr); - } - } - iRequireAuthenticatedLinkKey = EFalse; + + if (iLinkKeyRequestOutstanding) + { // might have already been called via SetPeerInSecurityMode3() + LinkKeyRequestResponseAttempt(); } - else if (iDeviceResult==KErrNone && !iDevice.IsValidLinkKey() || iDeviceResult==KErrNotFound) - { - LOG(_L("CPhysicalLink: No Link key available for the device")); - iAuthenticationCtrl.LinkKeyRequestNegativeReply(aAddr); - iRequireAuthenticatedLinkKey = EFalse; - } - else - { - LOG(_L("CPhysicalLink: Waiting for link key from Registry!")) - // we're still waiting for the device....we'll respond when it turns up - iWaitingForLinkKeyFromRegistry = ETrue; - } - } TInt CPhysicalLink::PINCodeRequestReply(const TBTDevAddr& aDevAddr, const TDesC8& aPin) const @@ -3613,16 +3529,11 @@ iOOBDataPresence = aOOBDataPresence; iAuthenticationRequirement = aAuthenticationRequirement; - //If we haven't determined the SSP pairing mode till now then enable it and notify the state m/c. - //This condition is to cater the fast remote device which responds very quickly, - //even before we determine whether it supports simple pairing!*/ - __ASSERT_DEBUG(((SimplePairingMode() == EPhySimplePairingEnabled) || (SimplePairingMode() == EPhySimplePairingUndefined)),Panic(EBTSSPModeChangedDuringConnection)); - if(SimplePairingMode() == EPhySimplePairingUndefined) - { - //Since we have received a I/O cap response the simple pairing must be enabled - iSimplePairingMode = EPhySimplePairingEnabled; - iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr()); - } + // If we haven't determined the SSP pairing mode the link is operating in yet then enable it, + // since we have received a I/O cap response the simple pairing must be enabled. + // This condition is to cater the fast remote device which responds very quickly, + // even before we determine whether it supports simple pairing! + RemoteSimplePairingModeDetermined(EPhySimplePairingEnabled); } @@ -3751,12 +3662,175 @@ 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 { return iSniffInterval; } +void CPhysicalLink::LinkKeyRequestResponseAttempt(TBool aForceResponse) + { + ASSERT_DEBUG(iLinkKeyRequestOutstanding); + + if(!iPeerInSecurityMode3 && iLinksMan.SecMan().IsDedicatedBondingAttempted(iDevice.Address())) + { + // If we are doing DedicatedBonding then we should ignore the existing linkkey + // in an attempt to generate a stronger one if possible. + // Security mode 3 is a odd case - because we get what looks like double pairing (the remote + // initiated pairing on connection, then the dedicated bonding pairing). So we have removed + // this feature for security mode 3 devices...they will have to suffer for their transgressions + LOG(_L("CPhysicalLink: Dedicated bonding attempt - Sending link key request negative reply")); + DoLinkKeyResponse(EFalse); + iRequireAuthenticatedLinkKey = EFalse; + } + else if (iDeviceResult==KErrNone && iDevice.IsValidLinkKey()) + { + if (iLinksMan.SecMan().DebugMode() && iDevice.LinkKeyType() != ELinkKeyDebug) + { + LOG(_L("CPhysicalLink: Debug mode - Link to debug link key")) + DoLinkKeyResponse(EFalse); + } + else if (iDevice.LinkKeyType() != ELinkKeyCombination) + { + if (iRequireAuthenticatedLinkKey && iDevice.LinkKeyType() == ELinkKeyUnauthenticatedUpgradable && IsPairable()) + { + LOG(_L("CPhysicalLink: Requiring Authenticated link key but currently only have unauthenticated")) + DoLinkKeyResponse(EFalse); + } + else + { + LOG(_L("CPhysicalLink: non - combination key, auth OK")) + DoLinkKeyResponse(ETrue); + } + } + else // Standard (legacy) Combination Key + { + if (SimplePairingMode() == EPhySimplePairingUndefined) + { + LOG(_L("CPhysicalLink: Waiting for Secure Simple Pairing mode to be determined")); + // wait for ssp mode to be determined...then try again + } + else if (IsPasskeyMinLengthOK() && SimplePairingMode() == EPhySimplePairingDisabled) + { + LOG(_L("CPhysicalLink: Combination key, Passkey len OK, no SSP")); + DoLinkKeyResponse(ETrue); + } + else + { + LOG(_L("CPhysicalLink: Current link key is not sufficient!")) + DoLinkKeyResponse(EFalse); + } + } + iRequireAuthenticatedLinkKey = EFalse; + } + else if (iDeviceResult==KErrNone && !iDevice.IsValidLinkKey() || iDeviceResult==KErrNotFound) + { + LOG(_L("CPhysicalLink: No Link key available for the device")); + DoLinkKeyResponse(EFalse); + iRequireAuthenticatedLinkKey = EFalse; + } + else if (aForceResponse) + { + LOG(_L("CPhysicalLink: Forcing a link key response (-ve as we don't have a link key yet)")); + DoLinkKeyResponse(EFalse); + } + else + { + LOG(_L("CPhysicalLink: Waiting for link key from Registry!")) + // we're still waiting for the device....we'll respond when it turns up + } + } + +/** +Send a link key response for an outstanding request, assumes that all details +have be validated. +*/ +void CPhysicalLink::DoLinkKeyResponse(TBool aPositive) + { + LOG_FUNC + ASSERT_DEBUG(iLinkKeyRequestOutstanding); + + if(aPositive) + { + LOG(_L("CPhysicalLink: Providing link key to HC...")) + ASSERT_DEBUG(iDevice.IsValidLinkKey()); + if (IsAuthenticationPending()) + { + iLinkKeyReturnedInThisAuthentication = ETrue; + } + iAuthenticationCtrl.LinkKeyRequestReply(iDevice.Address(), iDevice.LinkKey()); + } + else + { + LOG(_L("CPhysicalLink: Indicating no link key to HC...")); + iAuthenticationCtrl.LinkKeyRequestNegativeReply(iDevice.Address()); + } + iLinkKeyRequestOutstanding = EFalse; + } + +void CPhysicalLink::RemoteSimplePairingModeDetermined(TPhysicalLinkSimplePairingMode aSimplePairingMode) + { + LOG2(_L8("Current SimplePairingMode = %d, aSimplePairingMode = %d"), SimplePairingMode(), aSimplePairingMode); + ASSERT_DEBUG(aSimplePairingMode != EPhySimplePairingUndefined); // must be a definite value + __ASSERT_DEBUG(SimplePairingMode() == aSimplePairingMode || SimplePairingMode() == EPhySimplePairingUndefined, Panic(EBTSSPModeChangedDuringConnection)); + + const TPhysicalLinkSimplePairingMode previousSetting = iSimplePairingMode; + iSimplePairingMode = aSimplePairingMode; + if (previousSetting != iSimplePairingMode) + { + iLinksMan.SecMan().SimplePairingSupportDetermined(BDAddr()); + + // Also we may be waiting to respond to a link key request. + if (iLinkKeyRequestOutstanding) + { + LinkKeyRequestResponseAttempt(); + } + } + } + +void CPhysicalLink::SetPeerInSecurityMode3() + { + iPeerInSecurityMode3 = ETrue; + + // We also now know that the remote cannot possibly do SSP, *and* the LMP will + // likely lock our finding if the remote does SSP anyway while we do SM3. + RemoteSimplePairingModeDetermined(EPhySimplePairingDisabled); + } + // // TLowPowModeCmdController // diff -r 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btstack/linkmgr/physicallinks.h --- a/bluetooth/btstack/linkmgr/physicallinks.h Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btstack/linkmgr/physicallinks.h Fri Apr 16 16:09:25 2010 +0300 @@ -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,6 +497,12 @@ void PINCodeRequestNegativeReply(const TBTDevAddr& aDevAddr); inline TBool IsAuthenticationPending() const; + + void LinkKeyRequestResponseAttempt(TBool aForceResponse = EFalse); + void DoLinkKeyResponse(TBool aPositive); + + void RemoteSimplePairingModeDetermined(TPhysicalLinkSimplePairingMode aSimplePairingMode); + void SetPeerInSecurityMode3(); private: // from MPINCodeResponseHandler TInt PINCodeRequestReply(const TBTDevAddr& aDevAddr,const TDesC8& aPin) const; @@ -513,15 +530,18 @@ 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; // the PHY's supported logical links... RPointerArray iACLLogicalLinks; CBTSynchronousLink* iSyncLogicalLink; // stack only supports a signal one per PHY - + + TBool iLinkKeyRequestOutstanding; // for if we have to wait for Registry or SSP support status - MPINCodeResponseHandler* iPinHandler; + MPINCodeResponseHandler* iPinHandler; // for forwarding responses to + TBTConnect iLastPendingConnection; // for if we have to wait for Registry to decide whether to rject or accept a connection TBool iPendingConnection; // is a connection request waiting for a reply TSglQue iProxySAPs; // the proxies bound to us @@ -571,8 +591,8 @@ TBool iNewPinCodeValid; TBTPinCode iNewPinCode; - TBool iWaitingForLinkKeyFromRegistry; - + TBool iLinkKeyReturnedInThisAuthentication; + TBool iLinkKeyObtainedThroughDedicatedBonding; private: /** Enumeration to represent the current state of the physical links storage in the registry, diff -r 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btstack/secman/btaccessrequester.cpp --- a/bluetooth/btstack/secman/btaccessrequester.cpp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btstack/secman/btaccessrequester.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -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(); } @@ -711,6 +702,14 @@ LOG1(_L8("\tERROR (%d)"), aResult); } #endif // __FLOG_ACTIVE + + if (aResult == EBTSecManAccessGranted && 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")); + } + iSecMan.AccessRequestComplete(this, aResult); } @@ -1004,10 +1003,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 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btstack/secman/secman.cpp --- a/bluetooth/btstack/secman/secman.cpp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btstack/secman/secman.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -555,7 +555,8 @@ CPhysicalLink* link = iPhysicalLinksManager->FindPhysicalLink(aAddr); __ASSERT_ALWAYS(link, PANIC(KBTSecPanic, EBTSecPhysicalLinkMissing)); __ASSERT_DEBUG(!link->InstanceNumericComparator(), PANIC(KBTSecPanic, EBTSecConnectionNumericComparisonTwice)); - if(link->InstanceNumericComparator()) + __ASSERT_DEBUG(!link->InstanceUserConfirmer(), PANIC(KBTSecPanic, EBTSecConnectionUserConfirmationTwice)); + if(link->InstanceNumericComparator() || link->InstanceUserConfirmer()) { return; } @@ -581,6 +582,25 @@ } } } + else if (!link->IsPairingExpected() + || ((link->AuthenticationRequirement() == EMitmNotReqDedicatedBonding + || link->AuthenticationRequirement() == EMitmReqDedicatedBonding) + && !IsDedicatedBondingAttempted(aAddr))) + { + 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 +616,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 +662,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 +883,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 +1834,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 +1998,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 0089b2f7ebd8 -r 907b2fb7aa8e bluetooth/btstack/secman/secman.h --- a/bluetooth/btstack/secman/secman.h Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetooth/btstack/secman/secman.h Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetoothapitest/bluetoothsvs/group/bluetoothsvs.mrp --- a/bluetoothapitest/bluetoothsvs/group/bluetoothsvs.mrp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetoothapitest/bluetoothsvs/group/bluetoothsvs.mrp Fri Apr 16 16:09:25 2010 +0300 @@ -1,3 +1,19 @@ +# +# Copyright (c) 2009 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: +# + component bluetoothsvs source \sf\os\bt\bluetoothapitest\bluetoothsvs notes_source \sf\os\bt\bluetoothapitest\bluetoothsvs\group\release.txt diff -r 0089b2f7ebd8 -r 907b2fb7aa8e bluetoothmgmt/bluetoothclientlib/btlib/btsocket.cpp --- a/bluetoothmgmt/bluetoothclientlib/btlib/btsocket.cpp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetoothmgmt/bluetoothclientlib/btlib/btsocket.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetoothmgmt/bluetoothclientlib/inc/bt_subscribe_partner.h --- a/bluetoothmgmt/bluetoothclientlib/inc/bt_subscribe_partner.h Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetoothmgmt/bluetoothclientlib/inc/bt_subscribe_partner.h Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetoothmgmt/bluetoothclientlib/inc/bttypespartner.h --- a/bluetoothmgmt/bluetoothclientlib/inc/bttypespartner.h Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetoothmgmt/bluetoothclientlib/inc/bttypespartner.h Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetoothmgmt/btmgr/BTDevice/BTDevice.cpp --- a/bluetoothmgmt/btmgr/BTDevice/BTDevice.cpp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetoothmgmt/btmgr/BTDevice/BTDevice.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetoothmgmt/btmgr/BTManServer/BTManServer.cpp --- a/bluetoothmgmt/btmgr/BTManServer/BTManServer.cpp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetoothmgmt/btmgr/BTManServer/BTManServer.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetoothmgmt/btmgr/BTManServer/BTManServer.mmp --- a/bluetoothmgmt/btmgr/BTManServer/BTManServer.mmp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetoothmgmt/btmgr/BTManServer/BTManServer.mmp Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetoothmgmt/btmgr/BTManServer/BTRegistryDB.cpp --- a/bluetoothmgmt/btmgr/BTManServer/BTRegistryDB.cpp Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetoothmgmt/btmgr/BTManServer/BTRegistryDB.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -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 @@ -1354,7 +1364,12 @@ defaultDevice.SetDeviceName(KDefaultLocalName); defaultDevice.SetScanEnable(EPageScanOnly); defaultDevice.SetLimitedDiscoverable(EFalse); - defaultDevice.SetDeviceClass(0); + + // set the default device class to be phone|smartphone + // MajorServiceClass set to zero as there are no default service class bits + TBTDeviceClass defaultCod (0, EMajorDevicePhone, EMinorDevicePhoneSmartPhone); + defaultDevice.SetDeviceClass(defaultCod.DeviceClass()); + // The registry is being kicked off with a default channel assessment // mode setting of 'enabled'. This is the default if h/w supports // channel assessment. If h/w does not support channel assessment, diff -r 0089b2f7ebd8 -r 907b2fb7aa8e bluetoothmgmt/btmgr/BTManServer/BTRegistryDB.h --- a/bluetoothmgmt/btmgr/BTManServer/BTRegistryDB.h Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetoothmgmt/btmgr/BTManServer/BTRegistryDB.h Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetoothmgmt/btmgr/BTManServer/backup_registration.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothmgmt/btmgr/BTManServer/backup_registration.xml Fri Apr 16 16:09:25 2010 +0300 @@ -0,0 +1,28 @@ + + + + + + + + + + + diff -r 0089b2f7ebd8 -r 907b2fb7aa8e bluetoothmgmt/btmgr/BTManServer/btmanserverburmgr.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothmgmt/btmgr/BTManServer/btmanserverburmgr.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetoothmgmt/btmgr/BTManServer/btmanserverburmgr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothmgmt/btmgr/BTManServer/btmanserverburmgr.h Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetoothmgmt/btmgr/BTManServer/btmanserverburmgr.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothmgmt/btmgr/BTManServer/btmanserverburmgr.inl Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetoothmgmt/btmgr/BTManServer/btmanserverburstatemachine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothmgmt/btmgr/BTManServer/btmanserverburstatemachine.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetoothmgmt/btmgr/BTManServer/btmanserverburstatemachine.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothmgmt/btmgr/BTManServer/btmanserverburstatemachine.h Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e bluetoothmgmt/btmgr/Inc/BTManServer.h --- a/bluetoothmgmt/btmgr/Inc/BTManServer.h Fri Mar 19 09:53:48 2010 +0200 +++ b/bluetoothmgmt/btmgr/Inc/BTManServer.h Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e irda/irdastack/irtranp/SCEP.CPP --- a/irda/irdastack/irtranp/SCEP.CPP Fri Mar 19 09:53:48 2010 +0200 +++ b/irda/irdastack/irtranp/SCEP.CPP Fri Apr 16 16:09:25 2010 +0300 @@ -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 0089b2f7ebd8 -r 907b2fb7aa8e irda/irdastack/irtranp/tranp.cpp --- a/irda/irdastack/irtranp/tranp.cpp Fri Mar 19 09:53:48 2010 +0200 +++ b/irda/irdastack/irtranp/tranp.cpp Fri Apr 16 16:09:25 2010 +0300 @@ -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; }