--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/atext/server/src/atextmetadata.cpp Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,2608 @@
+/*
+* Copyright (c) 2008-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: Metadata for ATEXT
+*
+*/
+
+
+/*
+ * Here is the plugin managing logic for the AT commands and hopefully also for
+ * future needs:
+ *
+ * Three types of support:
+ * 1) Master (M): Does not send to S if support found.
+ * 2) Primary (P): Sends to all S if support found.
+ * 3) Secondary (S): Process the command and give or not give reply, based on
+ * the following logic:
+ *
+ * => [If] M found, handle command and send reply, stop, [else]
+ * [If] P found, handle command and send reply + send to N S {no reply}, stop, [else]
+ * [If] > 1 S found, send to N S {no reply}, stop, [else]
+ * [If] only 1 S found, handle command and send reply, stop, [else]
+ * Write "ERROR" to client, complete message with KErrNone
+ *
+ * When incoming reply:
+ * => If reply from M, write to client, stop, [else]
+ * If reply from P, write to client, stop, [else]
+ * If reply from S and M, P nor other S exist, write to client, stop, [else]
+ * Complete message with KErrNone and empty string
+ *
+ * Note: Empty string and "ERROR" string are managed already in HandleCommand()
+ */
+
+#include <ecom/ecom.h>
+#include <ecom/implementationInformation.h>
+#include <atextpluginbase.h>
+#include "atextclientsrv.h"
+#include "atextmetadata.h"
+#include "atextlisten.h"
+#include "utils.h"
+#include "debug.h"
+
+const TInt KGranularity = 4;
+const TInt8 KDefaultCarriageReturn = 13;
+const TInt8 KDefaultLineFeed = 10;
+const TInt KErrorMsgLen = 9; // 2+"ERROR"+2
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CATExtMetadata* CATExtMetadata::NewL( REComSession& aEComSession,
+ CATExtListen* aListener,
+ MATExtPluginObserver& aObserver )
+ {
+ CATExtMetadata* self = NewLC( aEComSession, aListener, aObserver );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CATExtMetadata* CATExtMetadata::NewLC( REComSession& aEComSession,
+ CATExtListen* aListener,
+ MATExtPluginObserver& aObserver )
+ {
+ CATExtMetadata* self = new (ELeave) CATExtMetadata( aEComSession,
+ aListener,
+ aObserver );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CATExtMetadata::~CATExtMetadata()
+ {
+ ResetData();
+ }
+
+// ---------------------------------------------------------------------------
+// Resets data to initial values
+// ---------------------------------------------------------------------------
+//
+void CATExtMetadata::ResetData()
+ {
+ TRACE_FUNC_ENTRY
+ iShutdown = ETrue;
+ DestroyPlugindata();
+ DestroySupportdata( iSupport );
+ DestroySupportdata( iSupportAux );
+ iConnectionName.Close();
+ iShutdown = EFalse;
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------------
+// Creates new implementation metadata based on a given interface UID and
+// connection. Uses AddImplementationL() to add new implementations for the
+// interface and sets connection identification name for reporting it to the
+// plugins on instantiation time.
+// ---------------------------------------------------------------------------
+//
+void CATExtMetadata::CreateImplementationMetadataL( TUid& aIfUid,
+ const TDesC8& aName )
+ {
+ TRACE_FUNC_ENTRY
+ if ( iPluginData || iSupport || iSupportAux )
+ {
+ TRACE_FUNC_EXIT
+ User::Leave( KErrGeneral );
+ }
+ iIfUid = aIfUid;
+ iConnectionName.CreateL( aName );
+ RImplInfoPtrArray implementations;
+ CleanupResetDestroyClosePushL( implementations );
+ iEComSession.ListImplementationsL( iIfUid, implementations );
+ const TUint implCount = implementations.Count();
+ TRACE_INFO((_L("Number of AT Ext: %d"), implCount))
+ iSupport = new (ELeave) CArrayFixFlat<TATExtAtCmdSupport>( KGranularity );
+ iSupportAux = new (ELeave) CArrayFixFlat<TATExtAtCmdSupport>( KGranularity );
+ iPluginData = new (ELeave) CArrayFixFlat<TATExtPluginEntry>( KGranularity );
+ // As iSupport, iSupportAux and iPluginData are needed by
+ // AddImplementationL(), no ease way to use temporary variables here.
+ // If error occurs here then deletion of this class is required.
+ for ( TUint i=0; i<implCount; i++ )
+ {
+ AddImplementationL( implementations[i] );
+ }
+ CleanupStack::PopAndDestroy( &implementations );
+#if defined(_DEBUG) && defined( PRJ_PRINT_SUPPORT_DATA )
+ PrintSupportData( iSupport );
+ PrintSupportData( iSupportAux );
+#endif
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------------
+// Adds an implementation to the metadata based on a given ECOM implementation
+// information. This is used by the function CreateImplementationMetadataL()
+// and also by CATExtSession when its ECOM notification listener detects an
+// addition for a the same ECOM interface.
+// ---------------------------------------------------------------------------
+//
+void CATExtMetadata::AddImplementationL( CImplementationInformation* aImplInfo )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !aImplInfo )
+ {
+ TRACE_FUNC_EXIT
+ User::Leave( KErrGeneral );
+ }
+ DoAddImplementationL( aImplInfo, aImplInfo->DataType() );
+ DoAddImplementationL( aImplInfo, aImplInfo->OpaqueData() );
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------------
+// Removes an implementation from the support data by a given plugin UID.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::RemoveImplementation( TUid& aPluginUid,
+ TBool aInstanceExists )
+ {
+ TRACE_FUNC_ENTRY
+ if ( iShutdown )
+ {
+ TRACE_FUNC_EXIT
+ return KErrNotReady;
+ }
+ DoRemoveImplementation( aPluginUid, iSupport );
+ DoRemoveImplementation( aPluginUid, iSupportAux );
+ TInt retVal = RemoveOnePlugindata( aPluginUid, aInstanceExists );
+ TRACE_FUNC_EXIT
+ return retVal;
+ }
+
+// ---------------------------------------------------------------------------
+// Handles an AT command
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::HandleCommand( const RMessage2& aMessage,
+ TATExtCompletionInfo& aComplInfo )
+ {
+ TRACE_FUNC_ENTRY
+ iCmdData.iCmdMessage = aMessage;
+ if ( IsCommandHandling() )
+ {
+ TRACE_FUNC_EXIT
+ return KErrInUse;
+ }
+ // Next pass the entry to command reader
+ TInt retTemp = ReadCommandFromMessage( aMessage );
+ if ( retTemp != KErrNone )
+ {
+ TRACE_FUNC_EXIT
+ return retTemp;
+ }
+ TRACE_INFO(( _L8("Received command '%S'"), &iCmdData.iCmdBuffer ));
+ // Now the command exists. Load the plugins for a command and check support.
+ TRAPD( retTrap, CreateAndFindSupportL(iCmdData.iCmdBuffer,
+ aMessage,
+ aComplInfo ) );
+ TRACE_FUNC_EXIT
+ return retTrap;
+ }
+
+// ---------------------------------------------------------------------------
+// Cancels an active handle command operation. Uses IsCommandHandling() and
+// CancelCommandOperation().
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::CancelHandleCommand()
+ {
+ TRACE_FUNC_ENTRY
+ if ( !IsCommandHandling() )
+ {
+ TRACE_FUNC_EXIT
+ return KErrNotReady;
+ }
+ CancelCommandOperation( KErrCancel, ETrue );
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Gets the next part of a reply for HandleCommand(). Length of returned reply
+// must be the same as the one reported from NextReplyPartLength() for the
+// current reply.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::GetNextPartOfReply( const RMessage2& aMessage )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !iCmdData.iHandler || !iCmdData.iHandler->iInstance )
+ {
+ TRACE_FUNC_EXIT
+ return KErrNotReady;
+ }
+ CATExtPluginBase& plugin = *iCmdData.iHandler->iInstance;
+ TInt retTemp = plugin.GetNextPartOfReply( iCmdData.iCmdReplyBuffer );
+ if ( retTemp!=KErrNone || iCmdData.iCmdReplyBuffer.Length()<=0 )
+ {
+ iCmdData.iCmdReplyBuffer.Close();
+ TRACE_FUNC_EXIT
+ return retTemp;
+ }
+ retTemp = WriteReplyBufferToClient(
+ iCmdData.iCmdReplyBuffer,
+ EATExtGetNextPartOfReplyParamReply,
+ aMessage,
+ ETrue,
+ EATExtGetNextPartOfReplyParamLength );
+ if ( retTemp != KErrNone )
+ {
+ iCmdData.iCmdReplyBuffer.Close();
+ TRACE_FUNC_EXIT
+ return retTemp;
+ }
+ aMessage.Complete( KErrNone );
+ iCmdData.iCmdReplyBuffer.Close();
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Completes an URC processing message by a given plugin UID. Completion code
+// for the client message is the return code from a write with
+// WriteReplyBufferToClient()
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::CompleteUrcMessage( const TDesC8& aAtCmd,
+ CATExtPluginBase* aPlugin )
+ {
+ TRACE_FUNC_ENTRY
+ TATExtPluginEntry* foundEntry = FindInstanceFromPlugindata( aPlugin );
+ if ( !foundEntry )
+ {
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ if ( !foundEntry->iUrcMessage.Handle() )
+ {
+ TRACE_FUNC_EXIT
+ return KErrBadHandle;
+ }
+ TInt retVal = WriteReplyBufferToClient( aAtCmd,
+ EATExtReceiveUrcCmdParamBuf,
+ foundEntry->iUrcMessage );
+ foundEntry->iUrcMessage.Complete( retVal );
+ TRACE_FUNC_EXIT
+ return retVal;
+ }
+
+// ---------------------------------------------------------------------------
+// Completes an AT command handling message. Also clears internal initialized
+// command hanlder data; see ClearInitializedCmdHandlerData().
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::CompleteCommandMessage( CATExtPluginBase* aPlugin,
+ TInt aError,
+ TBool aErrorReply,
+ TATExtensionReplyType aReplyType,
+ TBool aMultiPart )
+ {
+ TRACE_FUNC_ENTRY
+ // First check if aPlugin is set (the call comes from a plugin and not from
+ // ATEXT) and if it is the instance is different than the currently
+ // operating one.
+ if ( aPlugin && iCmdData.iHandler && iCmdData.iHandler->iInstance!=aPlugin )
+ {
+ TRACE_FUNC_EXIT
+ return KErrInUse;
+ }
+ // Next check if aPlugin is set (the call comes from a plugin and not from
+ // ATEXT) and a reply is not needed. In this case do nothing as it is wrong
+ // behavior from the plugin (a plugin must not complete messages where no
+ // reply is expected; this is done by ATEXT)
+ if ( aPlugin && !iCmdData.iReplyExpected )
+ {
+ TRACE_FUNC_EXIT
+ return KErrAlreadyExists;
+ }
+ if ( !iCmdData.iCmdMessage.Handle() )
+ {
+ TRACE_FUNC_EXIT
+ return KErrBadHandle;
+ }
+ // Finally write the data and complete the message
+ TPckg<TATExtensionReplyType> replyType( aReplyType );
+ TInt writeError = iCmdData.iCmdMessage.Write( EATExtHandleCmdParamReplyType,
+ replyType );
+ TRACE_INFO(( _L("Write returned %d"), writeError ));
+ if ( aError==KErrNone && writeError==KErrNone )
+ {
+ if ( iCmdData.iHandler ) // Can be NULL when invoked from inside ATEXT
+ {
+ iCmdData.iOldHandler = iCmdData.iHandler->iInstance;
+ }
+ if ( !aPlugin )
+ {
+ CreateEmptyOrErrorBuffer( iCmdData.iCmdReplyBuffer, aErrorReply );
+ }
+ if ( aMultiPart )
+ {
+ WriteReplyBufferToClient( iCmdData.iCmdReplyBuffer,
+ EATExtHandleCmdParamReply,
+ iCmdData.iCmdMessage,
+ ETrue,
+ EATExtHandleCmdParamLength );
+ }
+ else
+ {
+ WriteReplyBufferToClient( iCmdData.iCmdReplyBuffer,
+ EATExtHandleCmdParamReply,
+ iCmdData.iCmdMessage );
+ }
+ }
+ iCmdData.iCmdStarted = EFalse;
+ iCmdData.iReplyExpected = EFalse;
+ iCmdData.iCmdMessage.Complete( aError );
+ ClearInitializedCmdHandlerData( aMultiPart );
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Clears internal initialized command handler data. This is currently used
+// only by CompleteCommandMessage() and is called when the data is not needed
+// anymore. It also prepares the internal data for a new HandleCommand() call.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::ClearInitializedCmdHandlerData( TBool aMultiPart )
+ {
+ TRACE_FUNC_ENTRY
+ if ( iCmdData.iCmdStarted )
+ {
+ TRACE_FUNC_EXIT
+ return KErrNotReady;
+ }
+ iCmdData.iCmdBuffer.Close();
+ iCmdData.iCmdReplyBuffer.Close();
+ if ( !aMultiPart )
+ {
+ iCmdData.iHandler = NULL;
+ }
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Gets the array of supported commands.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::GetSupportedCommands( CATExtPluginBase* aPlugin,
+ RPointerArray<HBufC8>& aCmds )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !iSupport || !iSupportAux )
+ {
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ TATExtPluginEntry* foundEntry = FindInstanceFromPlugindata( aPlugin );
+ if ( !foundEntry )
+ {
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ // Next create the array of supported commands
+ TInt retVal = KErrNone;
+ TBool firstSearch = ETrue;
+ TInt supportFind = KErrNotFound;
+ TBool findInAux = EFalse;
+ for ( ;; )
+ {
+ HBufC8* foundCmd = GetNextSupportedCommand( firstSearch,
+ supportFind,
+ findInAux );
+ if ( !foundCmd )
+ {
+ break;
+ }
+ retVal = aCmds.Append( foundCmd );
+ if ( retVal != KErrNone )
+ {
+ break;
+ }
+ }
+ TRACE_FUNC_EXIT
+ return retVal;
+ }
+
+// ---------------------------------------------------------------------------
+// Starts URC message receiving for plugin. Note that
+// MarkUrcHandlingOwnership() must be called immediately after this in order
+// for the messages to receive their destination.
+// ---------------------------------------------------------------------------
+//
+void CATExtMetadata::StartUrcReceivingL( const RMessage2& aMessage,
+ TUid& aPluginUid )
+ {
+ TRACE_FUNC_ENTRY
+ TATExtPluginEntry* foundEntry = FindUrcProcessingPlugin( aPluginUid );
+ if ( !foundEntry )
+ {
+ TRACE_FUNC_EXIT
+ User::Leave( KErrNotFound );
+ }
+ // Note: Let locked plugin pass here
+ InstantiatePluginL( *foundEntry );
+ foundEntry->iUrcMessage = aMessage;
+ foundEntry->iInstance->ReceiveUnsolicitedResult();
+ foundEntry->iUrcStarted = ETrue;
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------------
+// Cancels an active URC message receiving operation by a given plugin UID.
+// Uses CancelOneUrcOperation() to cancel if plugin UID found from plugin
+// data.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::CancelUrcReceiving( TUid& aPluginUid )
+ {
+ TRACE_FUNC_ENTRY
+ TInt foundIndex = KErrNotFound;
+ TATExtPluginEntry* foundEntry = FindUidFromPlugindata( aPluginUid,
+ foundIndex );
+ if ( !foundEntry )
+ {
+ TRACE_FUNC_EXIT
+ return KErrNotFound;
+ }
+ CancelOneUrcOperation( *foundEntry, KErrCancel, ETrue );
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Marks URC handling ownership for a plugin entry. Call to this function must
+// be done immediately after the call to StartUrcReceivingL().
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::MarkUrcHandlingOwnership( const RMessage2& aMessage )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !iPluginData )
+ {
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ TInt i = 0;
+ TInt count = iPluginData->Count();
+ for ( i=0; i<count; i++ )
+ {
+ TATExtPluginEntry& entry = (*iPluginData)[i];
+ if ( entry.iUrcStarted && !entry.iUrcOwned )
+ {
+ TPckg<TUid> pluginUid( entry.iPluginUid );
+ TInt retTemp = aMessage.Write( EATExtMarkUrcHandlingOwnershipParamUid,
+ pluginUid );
+ TRACE_INFO(( _L("Write returned %d"), retTemp ));
+ entry.iUrcOwned = ETrue;
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+ }
+ TRACE_FUNC_EXIT
+ return KErrNotFound;
+ }
+
+// ---------------------------------------------------------------------------
+// Marks the access to a plugin data as "locked". This blocks all operations
+// where plugin function calls are to be done.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::LockPluginAccess( TUid& aPluginUid )
+ {
+ TRACE_FUNC_ENTRY
+ TInt foundIndex = KErrNotFound;
+ TATExtPluginEntry* foundEntry = FindUidFromPlugindata( aPluginUid,
+ foundIndex );
+ if ( !foundEntry )
+ {
+ TRACE_FUNC_EXIT
+ return KErrNotFound;
+ }
+ if ( foundEntry == iCmdData.iHandler )
+ {
+ CancelCommandOperation( KErrCancel );
+ }
+ CancelOneUrcOperation( *foundEntry, KErrCancel );
+ foundEntry->iLocked = ETrue;
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Marks the access to a plugin data as "unlocked". This enables all
+// operations where plugin function call are to be done.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::UnlockPluginAccess( TUid& aPluginUid )
+ {
+ TRACE_FUNC_ENTRY
+ TInt foundIndex = KErrNotFound;
+ TATExtPluginEntry* foundEntry = FindUidFromPlugindata( aPluginUid,
+ foundIndex );
+ if ( !foundEntry )
+ {
+ TRACE_FUNC_EXIT
+ return KErrNotFound;
+ }
+ foundEntry->iLocked = EFalse;
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Searches for an instances from the support data's plugin data link and only
+// marks the instance as uninitialized. Note that this doesn't try to cancel
+// any of the current plugin operations and should be used only when a plugin
+// destroys itself.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::RemoveImplementationInstance( CATExtPluginBase* aInstance )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !aInstance )
+ {
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ TATExtPluginEntry* foundEntry = FindInstanceFromPlugindata( aInstance );
+ if ( !foundEntry )
+ {
+ TRACE_FUNC_EXIT
+ return KErrNotFound;
+ }
+ TInt retVal = RemoveImplementation( foundEntry->iPluginUid, EFalse );
+ TRACE_FUNC_EXIT
+ return retVal;
+ }
+
+// ---------------------------------------------------------------------------
+// Checks if support data has been constructed from the plugin data.
+// ---------------------------------------------------------------------------
+//
+TBool CATExtMetadata::SupportExists()
+ {
+ TRACE_FUNC_ENTRY
+ if ( (iSupport&&iSupport->Count()>0) ||
+ (iSupportAux&&iSupportAux->Count()>0) )
+ {
+ TRACE_FUNC_EXIT
+ return ETrue;
+ }
+ TRACE_FUNC_EXIT
+ return EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// Number of plugins with AT command handling support based on the information
+// in RSS files' AT command handling entries. This information is needed to
+// instantiate one or more listeners by the user of the client.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::NumberOfPlugins()
+ {
+ TRACE_FUNC_ENTRY
+ if ( !iPluginData )
+ {
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ TInt pluginCount = iPluginData->Count();
+ TRACE_FUNC_EXIT
+ return pluginCount;
+ }
+
+// ---------------------------------------------------------------------------
+// Sets the quiet mode to the required value. After this the mode is reported
+// to the plugins with ReportQuietModeChange().
+// ---------------------------------------------------------------------------
+//
+void CATExtMetadata::SetQuietMode( TBool aMode )
+ {
+ TRACE_FUNC_ENTRY
+ iQuietMode = aMode;
+ if ( iPluginData )
+ {
+ TInt i;
+ TInt count = iPluginData->Count();
+ for ( i=0; i<count; i++ )
+ {
+ TATExtPluginEntry& entry = (*iPluginData)[i];
+ if ( entry.iLocked )
+ {
+ continue;
+ }
+ TInt retTemp = InstantiatePlugin( entry );
+ if ( retTemp != KErrNone )
+ {
+ continue;
+ }
+ // Note: here two reports will be made if the plugin was not
+ // instantiated but as the operatio is fast no new parameter will be
+ // done to InstantiatePlugin() for instantiation reporting.
+ entry.iInstance->ReportQuietModeChange( aMode );
+ }
+ }
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------------
+// Sets the verbose mode to the required value. After this the mode is
+// reported to the plugins with ReportVerboseModeChange().
+// ---------------------------------------------------------------------------
+//
+void CATExtMetadata::SetVerboseMode( TBool aMode )
+ {
+ TRACE_FUNC_ENTRY
+ iVerboseMode = aMode;
+ if ( iPluginData )
+ {
+ TInt i;
+ TInt count = iPluginData->Count();
+ for ( i=0; i<count; i++ )
+ {
+ TATExtPluginEntry& entry = (*iPluginData)[i];
+ if ( entry.iLocked )
+ {
+ continue;
+ }
+ TInt retTemp = InstantiatePlugin( entry );
+ if ( retTemp != KErrNone )
+ {
+ continue;
+ }
+ // Note: here two reports will be made if the plugin was not
+ // instantiated but as the operatio is fast no new parameter will be
+ // done to InstantiatePlugin() for instantiation reporting.
+ entry.iInstance->ReportVerboseModeChange( aMode );
+ }
+ }
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------------
+// Sets new character value for a carriage return, line feed or backspace
+// character. After this its type and value are report to the plugins with
+// ReportCharacterChange().
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::SetCharacterValue( TATExtensionCharType aCharType,
+ TInt8 aNewChar )
+ {
+ TRACE_FUNC_ENTRY
+ // First pick up the needed information for ATEXT
+ TInt retVal = KErrNone;
+ switch ( aCharType )
+ {
+ case ECharTypeCarriage:
+ iCarriageReturn = aNewChar;
+ break;
+ case ECharTypeLineFeed:
+ iLineFeed = aNewChar;
+ break;
+ case ECharTypeBackspace:
+ iBackspace = aNewChar;
+ break;
+ default:
+ retVal = KErrNotSupported;
+ break;
+ }
+ if ( retVal==KErrNone && iPluginData )
+ {
+ // Next notify about character change
+ TInt i;
+ TInt count = iPluginData->Count();
+ for ( i=0; i<count; i++ )
+ {
+ TATExtPluginEntry& entry = (*iPluginData)[i];
+ if ( entry.iLocked )
+ {
+ continue;
+ }
+ TInt retTemp = InstantiatePlugin( entry );
+ if ( retTemp != KErrNone )
+ {
+ continue;
+ }
+ // Note: here two reports will be made if the plugin was not
+ // instantiated but as the operatio is fast no new parameter will be
+ // done to InstantiatePlugin() for instantiation reporting.
+ entry.iInstance->ReportCharacterChange( aCharType, aNewChar );
+ }
+ }
+ TRACE_FUNC_EXIT
+ return retVal;
+ }
+
+// ---------------------------------------------------------------------------
+// Extracts the NVRAM settings from a pipe-character delimited NVRAM buffer
+// and sends the subsettings to all of the plugins with
+// ReportNvramStatusChange().
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::BroadcastNvramStatusChange( const TDesC8& aNvram )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !iPluginData )
+ {
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ HBufC8* nvramEntry = NULL;
+ TRAP_IGNORE( nvramEntry=HBufC8::NewMaxL(aNvram.Length()) );
+ if ( !nvramEntry )
+ {
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ TInt i;
+ TInt retVal = KErrNotFound;
+ TInt count = iPluginData->Count();
+ TPtr8 nvramEntryPtr = nvramEntry->Des();
+ TInt startIndex = 0; // Start of found subsetting
+ TInt endIndex = 0; // End of found subsetting
+ while ( ExtractNextNvramSetting(aNvram,startIndex,endIndex) )
+ {
+ // Report the subsetting to every plugin (and instantiate as every delta
+ // change has to be signalled to every plugin).
+ nvramEntryPtr.Copy( &aNvram[startIndex], endIndex-startIndex );
+ for ( i=0; i<count; i++ )
+ {
+ TATExtPluginEntry& entry = (*iPluginData)[i];
+ if ( entry.iLocked )
+ {
+ continue;
+ }
+ TInt retTemp = InstantiatePlugin( entry );
+ if ( retTemp != KErrNone )
+ {
+ continue;
+ }
+ entry.iInstance->ReportNvramStatusChange( nvramEntryPtr );
+ retVal = KErrNone;
+ }
+ }
+ delete nvramEntry;
+ TRACE_FUNC_EXIT
+ return retVal;
+ }
+
+// ---------------------------------------------------------------------------
+// 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.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::ReportExternalHandleCommandError()
+ {
+ TRACE_FUNC_ENTRY
+ if ( !iCmdData.iOldHandler )
+ {
+ TRACE_FUNC_EXIT
+ return KErrNotFound;
+ }
+ iCmdData.iOldHandler->ReportExternalHandleCommandError();
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Reports about abort condition in command handling.
+// This is for cases when for example DUN decided an abort condition was
+// received from DTE (ITU-T V.250 5.6.1). This API is for notifying the
+// plugin that abort was requested. However the plugin currently handling
+// the command may ignore the request if it doesn't support abort for the
+// command or it may return the changed condition with
+// HandleCommandCompleted()
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::ReportHandleCommandAbort( const RMessage2& aMessage )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !iCmdData.iHandler || !iCmdData.iHandler->iInstance )
+ {
+ TRACE_FUNC_EXIT
+ return KErrNotReady;
+ }
+ // Uncomment the following line for abort API
+// CATExtPluginBase& plugin = *iCmdData.iHandler->iInstance;
+ // Remove the following line for abort API
+ TInt retTemp = KErrNone;
+ TBool stop = EFalse;
+ // Uncomment the following line for abort API
+// TInt retTemp = plugin.ReportHandleCommandAbort( stop );
+ if ( retTemp != KErrNone )
+ {
+ TRACE_FUNC_EXIT
+ return retTemp;
+ }
+ TPckg<TBool> stopPckg( stop );
+ TInt retVal = aMessage.Write( EATExtReportHandleCommandAbortParamStop,
+ stopPckg );
+ TRACE_INFO(( _L("Write returned %d"), retVal ));
+ TRACE_FUNC_EXIT
+ return retVal;
+ }
+
+// ---------------------------------------------------------------------------
+// Extracts the NVRAM settings from a pipe-character delimited NVRAM buffer
+// and sends the subsettings to all of the plugins with
+// ReportNvramStatusChange().
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::GetNextSpecialCommand( const RMessage2& aMessage,
+ TBool aFirstSearch )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !iSupportAux )
+ {
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ // If first search then start from index 0, othewise start from the
+ // next index
+ if ( aFirstSearch )
+ {
+ iSupportAuxFind = -1;
+ }
+ iSupportAuxFind++;
+ TInt i;
+ TInt count = iSupportAux->Count();
+ TATExtAtCmdSupport* support = NULL;
+ for ( i=iSupportAuxFind; i<count; i++ )
+ {
+ support = &(*iSupportAux)[i];
+ if ( support->iEntries )
+ {
+ break;
+ }
+ }
+ if ( i >= count )
+ {
+ TRACE_FUNC_EXIT
+ return KErrNotFound;
+ }
+ TInt retTemp = WriteReplyBufferToClient( *support->iAtCmdBase,
+ EATExtGetNextSpecialCmdParamCmd,
+ aMessage );
+ TRACE_INFO(( _L("First write returned %d"), retTemp ));
+ TPckg<TBool> firstSearch( EFalse );
+ retTemp = aMessage.Write( EATExtGetNextSpecialCmdParamFirst, firstSearch );
+ TRACE_INFO(( _L("Second write returned %d"), retTemp ));
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CATExtMetadata::CATExtMetadata
+// ---------------------------------------------------------------------------
+//
+CATExtMetadata::CATExtMetadata( REComSession& aEComSession,
+ CATExtListen* aListener,
+ MATExtPluginObserver& aObserver ) :
+ iEComSession( aEComSession ),
+ iListener( aListener ),
+ iObserver( aObserver )
+ {
+ Initialize();
+ }
+
+// ---------------------------------------------------------------------------
+// CATExtMetadata::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CATExtMetadata::ConstructL()
+ {
+ if ( !iListener )
+ {
+ User::Leave( KErrGeneral );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Initializes this class
+// ---------------------------------------------------------------------------
+//
+void CATExtMetadata::Initialize()
+ {
+ // Don't initialize iListener here (it is set through NewL)
+ // Don't initialize iCallback here (it is set through NewL)
+ iIfUid = TUid::Null();
+ iSupport = NULL;
+ iSupportAux = NULL;
+ iPluginData = NULL;
+ iCmdData.iCmdStarted = EFalse;
+ iCmdData.iReplyExpected = EFalse;
+ iCmdData.iHandler = NULL;
+ iCmdData.iOldHandler = NULL;
+ iCarriageReturn = KDefaultCarriageReturn;
+ iLineFeed = KDefaultLineFeed;
+ iQuietMode = EFalse;
+ iVerboseMode = ETrue;
+ iSupportAuxFind = 0;
+ iShutdown = EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// Removes one plugin data entry by plugin UID
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::RemoveOnePlugindata( TUid& aPluginUid,
+ TBool aInstanceExists )
+ {
+ TRACE_FUNC_ENTRY
+ TInt foundIndex = KErrNotFound;
+ TATExtPluginEntry* foundEntry = FindUidFromPlugindata( aPluginUid,
+ foundIndex );
+ if ( !foundEntry )
+ {
+ TRACE_FUNC_EXIT
+ return KErrNotFound;
+ }
+ if ( !aInstanceExists )
+ {
+ foundEntry->iInstance = NULL;
+ }
+ if ( foundEntry == iCmdData.iHandler )
+ {
+ CancelCommandOperation( KErrCompletion );
+ }
+ CancelOneUrcOperation( *foundEntry, KErrCompletion );
+ delete foundEntry->iInstance;
+ foundEntry->iInstance = NULL;
+ iPluginData->Delete( foundIndex );
+ iPluginData->Compress();
+ UpdateRemovedPluginLinks( iSupport, foundIndex );
+ UpdateRemovedPluginLinks( iSupportAux, foundIndex );
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Updates removed plugin links
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::UpdateRemovedPluginLinks(
+ CArrayFixFlat<TATExtAtCmdSupport>* aSupport,
+ TInt aRemovedIndex )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !aSupport )
+ {
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ TInt i;
+ TInt j;
+ TInt supportCount = aSupport->Count();
+ for ( i=0; i<supportCount; i++ )
+ {
+ TATExtAtCmdSupport& support = (*aSupport)[i];
+ if ( !support.iEntries )
+ {
+ continue;
+ }
+ TInt entryCount = support.iEntries->Count();
+ for ( j=entryCount-1; j>=0; j-- )
+ {
+ TATExtOneCmdSupport& oneCmdSupport = (*support.iEntries)[j];
+ TInt entryIndex = oneCmdSupport.iEntryIndex;
+ if ( entryIndex > aRemovedIndex )
+ {
+ oneCmdSupport.iEntryIndex--;
+ }
+ else if ( entryIndex == aRemovedIndex )
+ {
+ support.iEntries->Delete( j );
+ }
+ }
+ }
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Completes command data
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::CompleteCommandData()
+ {
+ TRACE_FUNC_ENTRY
+ CompleteCommandMessage( NULL,
+ KErrCompletion,
+ EFalse,
+ EReplyTypeUndefined,
+ EFalse );
+ // It is possible that CompleteCommandMessage() didn't complete but there
+ // is still data set to non-null values. Force setting now.
+ iCmdData.iCmdStarted = EFalse;
+ iCmdData.iReplyExpected = EFalse;
+ iCmdData.iCmdBuffer.Close();
+ iCmdData.iCmdReplyBuffer.Close();
+ iCmdData.iHandler = NULL;
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Adds AT commands set to metadata. Used by function AddImplementationL().
+// ---------------------------------------------------------------------------
+//
+void CATExtMetadata::DoAddImplementationL(
+ CImplementationInformation* aImplInfo,
+ const TDesC8& aAtCmdSet )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !aImplInfo || !iPluginData || !iSupport || !iSupportAux )
+ {
+ TRACE_FUNC_EXIT
+ User::Leave( KErrGeneral );
+ }
+ TATExtSupportType type = ESupportTypeUndefined;
+ TInt start = 0; // Start of found subcommand
+ TInt end = 0; // End of found subcommand
+ HBufC8* parsedCmd = HBufC8::NewMaxLC( aAtCmdSet.Length() );
+ TPtr8 parsedCmdPtr = parsedCmd->Des();
+ while ( ExtractNextCommand(aAtCmdSet,start,end,type) == KErrNone )
+ {
+ if ( type == ESupportTypeUndefined )
+ {
+ continue;
+ }
+ parsedCmdPtr.Copy( &aAtCmdSet[start], end-start );
+ TUid pluginUid = aImplInfo->ImplementationUid();
+ TATExtCleanupInfo cleanupInfo;
+ TRAPD( retTrap, AddEntryToMetadataL(parsedCmdPtr,pluginUid,type,
+ cleanupInfo) );
+ if ( retTrap != KErrNone )
+ {
+ CleanPartialMetadata( cleanupInfo );
+ TRACE_FUNC_EXIT
+ User::Leave( retTrap );
+ }
+ TInt retTemp = iListener->AddPluginUid( pluginUid );
+ if ( retTemp != KErrNone )
+ {
+ TRACE_FUNC_EXIT
+ User::Leave( retTemp );
+ }
+ }
+ CleanupStack::PopAndDestroy( parsedCmd );
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------------
+// Removes an implementation from the support data by a given plugin UID.
+// Used by function RemoveImplementation().
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::DoRemoveImplementation(
+ TUid& aPluginUid,
+ CArrayFixFlat<TATExtAtCmdSupport>* aSupport )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !aSupport )
+ {
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ // 1. Find the UID from plugindata.
+ TInt foundIndex = KErrNotFound;
+ TATExtPluginEntry* foundEntry = FindUidFromPlugindata( aPluginUid,
+ foundIndex );
+ if ( !foundEntry )
+ {
+ TRACE_FUNC_EXIT
+ return KErrNotFound;
+ }
+ // 2. Delete the entries from metadata which point to the found entry.
+ TInt i;
+ TInt j;
+ TInt supportCount = aSupport->Count();
+ for ( i=supportCount-1; i>=0; i-- )
+ {
+ TATExtAtCmdSupport& support = (*aSupport)[i];
+ if ( !support.iEntries )
+ {
+ continue;
+ }
+ TInt entryCount = support.iEntries->Count();
+ for ( j=entryCount-1; j>=0; j-- )
+ {
+ TInt entryIndex = (*support.iEntries)[j].iEntryIndex;
+ if ( &(*iPluginData)[entryIndex] == foundEntry )
+ {
+ support.iEntries->Delete( j );
+ }
+ }
+ support.iEntries->Compress();
+ // 3. Remove the entries from metadata with zero length.
+ if ( support.iEntries->Count() == 0 )
+ {
+ aSupport->Delete( i );
+ }
+ }
+ aSupport->Compress();
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Checks whether AT command handling is active or not
+// ---------------------------------------------------------------------------
+//
+TBool CATExtMetadata::IsCommandHandling()
+ {
+ TRACE_FUNC_ENTRY
+ if ( iCmdData.iCmdStarted ||
+ (iCmdData.iCmdMessage.Handle() && iCmdData.iCmdBuffer.Length()>0) ||
+ iCmdData.iCmdReplyBuffer.Length()>0 )
+ {
+ TRACE_FUNC_EXIT
+ return ETrue;
+ }
+ TRACE_FUNC_EXIT
+ return EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// Destroys data related to plugins
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::DestroyPlugindata()
+ {
+ TRACE_FUNC_ENTRY
+ if ( !iPluginData )
+ {
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ CancelCommandOperation( KErrServerTerminated );
+ // First cancel the plugindata operations before delete
+ TInt i;
+ TInt pluginCount = iPluginData->Count();
+ for ( i=0; i<pluginCount; i++ )
+ {
+ TATExtPluginEntry& entry = (*iPluginData)[i];
+ CancelOneUrcOperation( entry, KErrServerTerminated );
+ }
+ // Next delete the actual data
+ for ( i=0; i<pluginCount; i++ )
+ {
+ TATExtPluginEntry& entry = (*iPluginData)[i];
+ delete entry.iInstance;
+ entry.iInstance = NULL;
+ }
+ iPluginData->Reset();
+ delete iPluginData;
+ iPluginData = NULL;
+ iCmdData.iHandler = NULL;
+ iCmdData.iOldHandler = NULL;
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Cancels an active AT command handling operation by reinitializing internal
+// data, completing the client request message and calling the plugin's
+// HandleCommandCancel().
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::CancelCommandOperation( TInt aError, TBool aCheckLock )
+ {
+ TRACE_FUNC_ENTRY
+ if ( aCheckLock && iCmdData.iHandler && iCmdData.iHandler->iLocked )
+ {
+ TRACE_FUNC_EXIT
+ return KErrAccessDenied;
+ }
+ if ( iCmdData.iHandler && iCmdData.iHandler->iInstance )
+ {
+ iCmdData.iHandler->iInstance->HandleCommandCancel();
+ }
+ CompleteCommandMessage( NULL,
+ aError,
+ EFalse,
+ EReplyTypeUndefined,
+ EFalse );
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Cancels an active URC message receiving operation by a given plugin entry,
+// completing the client request message and calling the plugin's
+// ReceiveUnsolicitedResultCancel().
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::CancelOneUrcOperation( TATExtPluginEntry& aPluginEntry,
+ TInt aError,
+ TBool aCheckLock )
+ {
+ TRACE_FUNC_ENTRY
+ if ( aCheckLock && aPluginEntry.iLocked )
+ {
+ TRACE_FUNC_EXIT
+ return KErrAccessDenied;
+ }
+ aPluginEntry.iUrcStarted = EFalse;
+ if ( aPluginEntry.iInstance )
+ {
+ aPluginEntry.iInstance->ReceiveUnsolicitedResultCancel();
+ }
+ if ( aPluginEntry.iUrcMessage.Handle() )
+ {
+ aPluginEntry.iUrcMessage.Complete( aError );
+ }
+ // Note: Don't touch the iUrcOwned here
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Destroys data related to AT command support
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::DestroySupportdata(
+ CArrayFixFlat<TATExtAtCmdSupport>*& aSupport )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !aSupport )
+ {
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ // Next just remove the entries
+ TInt i;
+ TInt supportCount = aSupport->Count();
+ for ( i=0; i<supportCount; i++ )
+ {
+ TATExtAtCmdSupport& support = (*aSupport)[i];
+ delete support.iAtCmdBase;
+ support.iAtCmdBase = NULL;
+ if ( support.iEntries )
+ {
+ support.iEntries->Reset();
+ delete support.iEntries;
+ support.iEntries = NULL;
+ }
+ }
+ aSupport->Reset();
+ delete aSupport;
+ aSupport = NULL;
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Extracts one command from a pipe-character delimited command buffer (Note:
+// This function is used to get the settings from a plugin RSS file)
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::ExtractNextCommand( const TDesC8& aCommands,
+ TInt& aStartIndex,
+ TInt& aEndIndex,
+ TATExtSupportType& aSupportType )
+ {
+ TRACE_FUNC_ENTRY
+ aSupportType = ESupportTypeUndefined;
+ // Skip data before command
+ TInt i;
+ TChar character;
+ TInt count = aCommands.Length();
+ for ( i=aEndIndex; i<count; i++ )
+ {
+ character = aCommands[i];
+ if ( character.IsPrint() && character!='|' )
+ {
+ break;
+ }
+ }
+ if ( i >= count )
+ {
+ TRACE_FUNC_EXIT
+ return KErrNotFound;
+ }
+ // Now the plugin type marker is found; check the plugin type
+ switch ( character )
+ {
+ case 'M': // Master plugin
+ case 'm':
+ aSupportType = ESupportTypeMaster;
+ break;
+ case 'P': // Primary plugin
+ case 'p':
+ aSupportType = ESupportTypePrimary;
+ break;
+ case 'S': // Secondary plugin
+ case 's':
+ aSupportType = ESupportTypeSecondary;
+ break;
+ }
+ i++;
+ if ( i >= count )
+ {
+ TRACE_FUNC_EXIT
+ return KErrNotFound;
+ }
+ aStartIndex = i;
+ // Start of command found, next mark the end
+ while ( i < count )
+ {
+ character = aCommands[i];
+ if ( !character.IsPrint() || character=='|' )
+ {
+ break;
+ }
+ i++;
+ }
+ aEndIndex = i;
+ if ( aEndIndex-aStartIndex <= 0 )
+ {
+ TRACE_FUNC_EXIT
+ return KErrNotFound;
+ }
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// Adds a new plugin entry to support data. If command to be added is not
+// found from the support data then that command is inserted alphabetically to
+// the support data. After this a search for the plugin UID is done; if the
+// UID is not found then it is added to the plugin data and a new initialized
+// data is created for that entry. Finally the added or new plugin entry is
+// linked to the new or existing support entry.
+// ---------------------------------------------------------------------------
+//
+void CATExtMetadata::AddEntryToMetadataL( TDes8& aAtCmdBase,
+ TUid& aPluginUid,
+ TATExtSupportType aSupportType,
+ TATExtCleanupInfo& aCleanupInfo )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !iSupport || !iSupportAux || !iPluginData )
+ {
+ TRACE_FUNC_EXIT
+ User::Leave( KErrGeneral );
+ }
+ // First try to find the string with binary search.
+ // If found, add aUid.
+ // If not found, add aAtCmdBase, aPluginUid.
+ CArrayFixFlat<TATExtAtCmdSupport>* support = iSupport;
+ aCleanupInfo.iSupportCreated = EFalse;
+ aCleanupInfo.iSupportIndex = KErrNotFound;
+ aCleanupInfo.iEntryCreated = EFalse;
+ aCleanupInfo.iEntryIndex = KErrNotFound;
+ aCleanupInfo.iSupport = iSupport;
+ TBool findAux = EFalse;
+ TInt strLength = aAtCmdBase.Length();
+ if ( strLength>=3 && aAtCmdBase[strLength-1]=='*' ) // 3 for "AT*"
+ {
+ aAtCmdBase.SetLength( strLength-1 );
+ aCleanupInfo.iSupport = iSupportAux;
+ support = iSupportAux;
+ findAux = ETrue;
+ }
+ TInt foundPos = KErrNotFound;
+ TBool found = FindCommandFromMetadata( aAtCmdBase, foundPos, findAux, EFalse );
+ if ( !found )
+ {
+ // Not found. foundPos is the position where to add the new entry
+ TATExtAtCmdSupport newEntry;
+ foundPos = -foundPos; // convert to positive
+ newEntry.iAtCmdBase = HBufC8::NewMaxLC( aAtCmdBase.Length() );
+ newEntry.iEntries = NULL;
+ TPtr8 atCmdPtr = newEntry.iAtCmdBase->Des();
+ atCmdPtr.Copy( aAtCmdBase );
+ support->InsertL( foundPos, newEntry );
+ CleanupStack::Pop( newEntry.iAtCmdBase );
+ aCleanupInfo.iSupportCreated = ETrue;
+ }
+ aCleanupInfo.iSupportIndex = foundPos;
+ // Next try to find the plugin UID from plugin data.
+ TInt foundIndex = KErrNotFound;
+ TATExtPluginEntry* foundEntry = FindUidFromPlugindata( aPluginUid,
+ foundIndex );
+ if ( !foundEntry )
+ {
+ // Not found. Append new initialized entry.
+ TATExtPluginEntry pluginEntry;
+ pluginEntry.iPluginUid = aPluginUid;
+ pluginEntry.iInstance = NULL;
+ pluginEntry.iLocked = EFalse;
+ pluginEntry.iUrcStarted = EFalse;
+ pluginEntry.iUrcOwned = EFalse;
+ iPluginData->AppendL( pluginEntry );
+ aCleanupInfo.iEntryCreated = ETrue;
+ aCleanupInfo.iEntryIndex = iPluginData->Count() - 1;
+ foundIndex = aCleanupInfo.iEntryIndex;
+ foundEntry = &(*iPluginData)[foundIndex];
+ }
+ // Now foundEntry is either the found entry or a newly added entry.
+ // Make the iSupport metadata point to this.
+ TATExtAtCmdSupport& foundSupport = (*support)[foundPos];
+#if defined( PRJ_OPTIMIZE_FOR_SPEED )
+ AddNewMetadataEntryLinkL( foundSupport.iEntries,
+ foundIndex,
+ aSupportType,
+ foundSupport.iSearchHelper );
+#else // PRJ_OPTIMIZE_FOR_SPEED
+ TATExtSearchHelper searchHelper;
+ AddNewMetadataEntryLinkL( foundSupport.iEntries,
+ foundIndex,
+ aSupportType,
+ searchHelper );
+#endif // PRJ_OPTIMIZE_FOR_SPEED
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------------
+// Adds new plugin entry link from plugin support entry to plugin entry
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::AddNewMetadataEntryLinkL(
+ CArrayFixFlat<TATExtOneCmdSupport>*& aEntries,
+ TInt aEntryIndex,
+ TATExtSupportType aSupportType,
+ TATExtSearchHelper& aSearchHelper )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !iPluginData || aEntryIndex<0 || aEntryIndex>=iPluginData->Count() )
+ {
+ TRACE_FUNC_EXIT
+ User::Leave( KErrGeneral );
+ }
+ if ( !aEntries )
+ {
+ aEntries = new (ELeave) CArrayFixFlat<TATExtOneCmdSupport>( KGranularity );
+ }
+ TATExtOneCmdSupport oneCmdSupport;
+ oneCmdSupport.iSupportType = aSupportType;
+ oneCmdSupport.iEntryIndex = aEntryIndex;
+ TInt retVal = KErrNotSupported;
+ switch ( aSupportType )
+ {
+ case ESupportTypeMaster:
+ {
+ retVal = AddNewMasterMetadataEntryLinkL( aEntries,
+ aSearchHelper,
+ oneCmdSupport );
+ }
+ break;
+ case ESupportTypePrimary:
+ {
+ retVal = AddNewPrimaryMetadataEntryLinkL( aEntries,
+ aSearchHelper,
+ oneCmdSupport );
+ }
+ break;
+ case ESupportTypeSecondary:
+ {
+ retVal = AddNewSecondaryMetadataEntryLinkL( aEntries,
+ aSearchHelper,
+ oneCmdSupport );
+ }
+ break;
+ default:
+ {
+ User::Leave( KErrNotSupported );
+ }
+ }
+ TRACE_FUNC_EXIT
+ return retVal;
+ }
+
+// ---------------------------------------------------------------------------
+// Adds new master plugin entry link from plugin support entry to plugin entry
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::AddNewMasterMetadataEntryLinkL(
+ CArrayFixFlat<TATExtOneCmdSupport>* aEntries,
+ TATExtSearchHelper& aSearchHelper,
+ TATExtOneCmdSupport& aOneCmdSupport )
+ {
+ TRACE_FUNC_ENTRY
+ aEntries->InsertL( 0, aOneCmdSupport );
+ if ( aSearchHelper.iPrimaryIndex >= 0 )
+ {
+ aSearchHelper.iPrimaryIndex++;
+ }
+ if ( aSearchHelper.iSecondaryIndex >= 0 )
+ {
+ aSearchHelper.iSecondaryIndex++;
+ }
+ TRACE_FUNC_EXIT
+ return 0;
+ }
+
+// ---------------------------------------------------------------------------
+// Adds new primary plugin entry link from plugin support entry to plugin
+// entry
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::AddNewPrimaryMetadataEntryLinkL(
+ CArrayFixFlat<TATExtOneCmdSupport>* aEntries,
+ TATExtSearchHelper& aSearchHelper,
+ TATExtOneCmdSupport& aOneCmdSupport )
+ {
+ TRACE_FUNC_ENTRY
+ TInt i = aSearchHelper.iPrimaryIndex;
+ if ( i < 0 )
+ {
+ TInt count = aEntries->Count();
+ for ( i=0; i<count; i++ )
+ {
+ TATExtOneCmdSupport& oneCmdSupport = (*aEntries)[i];
+ if ( oneCmdSupport.iSupportType==ESupportTypePrimary ||
+ oneCmdSupport.iSupportType==ESupportTypeSecondary )
+ {
+ break;
+ }
+ }
+ aSearchHelper.iPrimaryIndex = i;
+ }
+ aEntries->InsertL( i, aOneCmdSupport );
+ if ( aSearchHelper.iSecondaryIndex >= 0 )
+ {
+ aSearchHelper.iSecondaryIndex++;
+ }
+ TRACE_FUNC_EXIT
+ return i;
+ }
+
+// ---------------------------------------------------------------------------
+// Adds new secondary plugin entry link from plugin support entry to plugin
+// entry. Search starts from the front as there could be multiple S plugins
+// but only one or two M/P plugins.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::AddNewSecondaryMetadataEntryLinkL(
+ CArrayFixFlat<TATExtOneCmdSupport>* aEntries,
+ TATExtSearchHelper& aSearchHelper,
+ TATExtOneCmdSupport& aOneCmdSupport )
+ {
+ TRACE_FUNC_ENTRY
+ TInt i = aSearchHelper.iSecondaryIndex;
+ if ( i < 0 )
+ {
+ TInt count = aEntries->Count();
+ for ( i=0; i<count; i++ )
+ {
+ TATExtOneCmdSupport& oneCmdSupport = (*aEntries)[i];
+ if ( oneCmdSupport.iSupportType == ESupportTypeSecondary )
+ {
+ break;
+ }
+ }
+ aSearchHelper.iSecondaryIndex = i;
+ }
+ aEntries->InsertL( i, aOneCmdSupport );
+ TRACE_FUNC_EXIT
+ return i;
+ }
+
+// ---------------------------------------------------------------------------
+// Cleans partial created metadata based on TATExtCleanupInfo
+// ---------------------------------------------------------------------------
+//
+void CATExtMetadata::CleanPartialMetadata( TATExtCleanupInfo& aCleanupInfo )
+ {
+ TRACE_FUNC_ENTRY
+ TBool withinEntryLimits = EFalse;
+ TBool withinSupportLimits = EFalse;
+ CArrayFixFlat<TATExtAtCmdSupport>* support = aCleanupInfo.iSupport;
+ if ( aCleanupInfo.iEntryIndex>=0 &&
+ aCleanupInfo.iEntryIndex<support->Count() )
+ {
+ withinEntryLimits = ETrue;
+ }
+ if ( aCleanupInfo.iSupportIndex>=0 &&
+ aCleanupInfo.iSupportIndex<support->Count() )
+ {
+ withinSupportLimits = ETrue;
+ }
+ if ( aCleanupInfo.iEntryCreated && withinEntryLimits )
+ {
+ iPluginData->Delete( aCleanupInfo.iEntryIndex );
+ }
+ if ( aCleanupInfo.iSupportCreated && withinSupportLimits )
+ {
+ TInt deleteIndex = aCleanupInfo.iSupportIndex;
+ TATExtAtCmdSupport& supportData = (*support)[deleteIndex];
+ delete supportData.iAtCmdBase;
+ supportData.iAtCmdBase = NULL;
+ delete supportData.iEntries;
+ supportData.iEntries = NULL;
+ support->Delete( deleteIndex );
+ support->Compress();
+ }
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------------
+// Prints the AT command plugin entries and information about them.
+// For debugging/bug hunting only
+// ---------------------------------------------------------------------------
+//
+#if defined(_DEBUG) && defined( PRJ_PRINT_SUPPORT_DATA )
+TInt CATExtMetadata::PrintSupportData(
+ CArrayFixFlat<TATExtAtCmdSupport>* aSupport )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !aSupport )
+ {
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ TInt i;
+ TInt j;
+ TInt supportCount = aSupport->Count();
+ for ( i=0; i<supportCount; i++ )
+ {
+ TATExtAtCmdSupport& support = (*aSupport)[i];
+ if ( !support.iEntries )
+ {
+ continue;
+ }
+ TInt entryCount = support.iEntries->Count();
+ TRACE_INFO(( _L8("Support entry at index %d = '%S' (%d entries):"), i, &(*support.iAtCmdBase), entryCount ));
+ for ( j=0; j<entryCount; j++ )
+ {
+ TATExtOneCmdSupport& oneCmdSupport = (*support.iEntries)[j];
+ TInt entryIndex = oneCmdSupport.iEntryIndex;
+ TRACE_INFO(( _L8("\tPlugin entry at index %d = Type:%d, UID:0x%08X"), j, oneCmdSupport.iSupportType, (*iPluginData)[entryIndex].iPluginUid ));
+ }
+ }
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+#endif
+
+// ---------------------------------------------------------------------------
+// Prints the found AT command plugin entries and information about them.
+// For debugging/bug hunting only
+// ---------------------------------------------------------------------------
+//
+#if defined(_DEBUG) && defined( PRJ_PRINT_SUPPORT_DATA )
+TInt CATExtMetadata::PrintFoundEntries(
+ CArrayFixFlat<TATExtOneCmdSupport>* aEntries )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !aEntries )
+ {
+ TRACE_FUNC_EXIT
+ return KErrGeneral;
+ }
+ TInt i;
+ TInt count = aEntries->Count();
+ for ( i=0; i<count; i++ )
+ {
+ TATExtOneCmdSupport& entry = (*aEntries)[i];
+ TInt entryIndex = entry.iEntryIndex;
+ TRACE_INFO(( _L8("\tFound entry at index %d = Type:%d, UID:0x%08X"), i, entry.iSupportType, (*iPluginData)[entryIndex].iPluginUid ));
+ }
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+#endif
+
+// ---------------------------------------------------------------------------
+// Does a binary search for an AT command to find the AT command from the
+// support data
+// ---------------------------------------------------------------------------
+//
+TBool CATExtMetadata::FindCommandFromMetadata( TDesC8& aAtCmdBase,
+ TInt& aFoundIndex,
+ TBool aFindAuxCmd,
+ TBool aCheckAsterisk )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !iSupport || !iSupportAux || (!aFindAuxCmd&&aCheckAsterisk) )
+ {
+ TRACE_FUNC_EXIT
+ return EFalse;
+ }
+ TInt result = 0;
+ TInt middle = 0;
+ TInt left = 0;
+ CArrayFixFlat<TATExtAtCmdSupport>* support = iSupport;
+ if ( aFindAuxCmd )
+ {
+ support = iSupportAux;
+ }
+ TInt right = support->Count() - 1;
+ while ( left <= right )
+ {
+ middle = ( left + right ) / 2;
+ HBufC8& compareStr = *(*support)[middle].iAtCmdBase;
+ TInt strLength = compareStr.Length();
+ if ( aCheckAsterisk )
+ {
+ TPtrC8 leftPart = aAtCmdBase.Left( strLength );
+ result = compareStr.Compare( leftPart );
+ }
+ else
+ {
+ result = compareStr.Compare( aAtCmdBase );
+ }
+ if ( result == 0 ) // iSupport == aAtCmd
+ {
+ aFoundIndex = middle;
+ TRACE_FUNC_EXIT
+ return ETrue;
+ }
+ else if ( result < 0 ) // iSupport < aAtCmd
+ {
+ left = middle + 1;
+ }
+ else // iSupport > aAtCmd
+ {
+ right = middle - 1;
+ }
+ }
+ aFoundIndex = -left;
+ TRACE_FUNC_EXIT
+ return EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// Finds the first plugin entry from a given plugin UID
+// ---------------------------------------------------------------------------
+//
+TATExtPluginEntry* CATExtMetadata::FindUidFromPlugindata( TUid& aUid,
+ TInt& aFoundIndex )
+ {
+ TRACE_FUNC_ENTRY
+ aFoundIndex = KErrNotFound;
+ if ( !iPluginData )
+ {
+ TRACE_FUNC_EXIT
+ return NULL;
+ }
+ TInt i;
+ TInt count = iPluginData->Count();
+ for ( i=0; i<count; i++ )
+ {
+ TATExtPluginEntry& entry = (*iPluginData)[i];
+ if ( entry.iPluginUid == aUid )
+ {
+ TRACE_FUNC_EXIT
+ aFoundIndex = i;
+ return &entry;
+ }
+ }
+ TRACE_FUNC_EXIT
+ return NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// Find the first plugin entry from a given plugin instance
+// ---------------------------------------------------------------------------
+//
+TATExtPluginEntry* CATExtMetadata::FindInstanceFromPlugindata(
+ CATExtPluginBase* aInstance )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !iPluginData )
+ {
+ TRACE_FUNC_EXIT
+ return NULL;
+ }
+ TInt i;
+ TInt count = iPluginData->Count();
+ for ( i=0; i<count; i++ )
+ {
+ TATExtPluginEntry& entry = (*iPluginData)[i];
+ if ( entry.iInstance == aInstance )
+ {
+ TRACE_FUNC_EXIT
+ return &entry;
+ }
+ }
+ TRACE_FUNC_EXIT
+ return NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// Finds an Urc message processing plugin. Must be used in synchronization
+// with MarkUrcHandlingOwnership(). More information in aPluginUid parameter's
+// explanation below.
+// ---------------------------------------------------------------------------
+//
+TATExtPluginEntry* CATExtMetadata::FindUrcProcessingPlugin(
+ TUid& aPluginUid )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !iPluginData )
+ {
+ TRACE_FUNC_EXIT
+ return NULL;
+ }
+ TInt i;
+ TInt count = iPluginData->Count();
+ for ( i=0; i<count; i++ )
+ {
+ TATExtPluginEntry& entry = (*iPluginData)[i];
+ if ( entry.iUrcMessage.Handle() )
+ {
+ continue;
+ }
+ // second run (after MarkUrcHandlingOwnership())
+ if ( aPluginUid != TUid::Null() )
+ {
+ if ( entry.iUrcOwned && entry.iPluginUid==aPluginUid )
+ {
+ TRACE_FUNC_EXIT
+ return &entry;
+ }
+ }
+ // first run (before MarkUrcHandlingOwnership())
+ else if ( !entry.iUrcStarted && !entry.iUrcOwned )
+ {
+ TRACE_FUNC_EXIT
+ return &entry;
+ }
+ }
+ TRACE_FUNC_EXIT
+ return NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// Extracts the base command from a given AT command to find support with
+// DoCreateAndFindSupportL()
+// ---------------------------------------------------------------------------
+//
+void CATExtMetadata::CreateAndFindSupportL(
+ TDesC8& aAtCmdFull,
+ const RMessage2& aMessage,
+ TATExtCompletionInfo& aComplInfo )
+ {
+ TRACE_FUNC_ENTRY
+ // First extract the base of AT command from aAtCmdFull
+ // ('=' and everything after that)
+ TInt newLength = aAtCmdFull.Length();
+ TInt foundPos = aAtCmdFull.Locate( '=' );
+ if ( foundPos >= 2 ) // After "AT"
+ {
+ newLength = foundPos;
+ }
+ else if ( newLength >= 1 )
+ {
+ // There was no '=' so check if the last character is '?'.
+ // If it is then remove it.
+ if ( aAtCmdFull[newLength-1] == '?' )
+ {
+ newLength--;
+ }
+ }
+ HBufC8* baseCmd = HBufC8::NewMaxLC( newLength );
+ TPtr8 baseCmdPtr = baseCmd->Des();
+ baseCmdPtr.Copy( &aAtCmdFull[0], newLength );
+ // Now the baseCmd has the base command. Use it to find the support.
+ DoCreateAndFindSupportL( *baseCmd,
+ aAtCmdFull,
+ aMessage,
+ aComplInfo );
+ CleanupStack::PopAndDestroy( baseCmd );
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------------
+// Creates AT command support and finds the given AT command from the created
+// support data
+// ---------------------------------------------------------------------------
+//
+void CATExtMetadata::DoCreateAndFindSupportL(
+ TDesC8& aAtCmdBase,
+ TDesC8& aAtCmdFull,
+ const RMessage2& aMessage,
+ TATExtCompletionInfo& aComplInfo )
+ {
+ TRACE_FUNC_ENTRY
+ // Note: don't set iCmdData.iOldHandler to NULL here as the sequence can
+ // invoke this function again before ReportExternalHandleCommandError().
+ // Get array of supported plugins for the base command
+ CArrayFixFlat<TATExtOneCmdSupport>* support;
+ support = FindEntriesForCommandLC( aAtCmdBase );
+ if ( !support )
+ {
+ aComplInfo.iProcessed = EFalse;
+ aComplInfo.iReplyExpected = ETrue;
+ CreateSelfReplyData( aMessage );
+ CleanupStack::PopAndDestroy();
+ TRACE_FUNC_EXIT
+ return;
+ }
+ TATExtEntrySupport entrySupport( aAtCmdFull, aMessage, support );
+ TInt i;
+ aComplInfo.iProcessed = EFalse;
+ TInt count = support->Count();
+ for ( i=0; i<count; i++ )
+ {
+ TBool supported = EFalse;
+ TATExtOneCmdSupport& oneCmdSupport = (*support)[i];
+ entrySupport.iEntry = &(*iPluginData)[oneCmdSupport.iEntryIndex];
+ if ( oneCmdSupport.iSupportType == ESupportTypeMaster )
+ {
+ supported = HandleMasterPluginSupportL(
+ entrySupport,
+ aComplInfo.iReplyExpected );
+ }
+ else if ( oneCmdSupport.iSupportType == ESupportTypePrimary )
+ {
+ supported = HandlePrimaryPluginSupportL(
+ entrySupport,
+ i+1,
+ aComplInfo.iReplyExpected );
+ }
+ else if ( oneCmdSupport.iSupportType == ESupportTypeSecondary )
+ {
+ supported = HandleSecondaryPluginSupportL(
+ entrySupport,
+ i+1,
+ aComplInfo.iReplyExpected );
+ }
+ if ( supported )
+ {
+ aComplInfo.iProcessed = ETrue;
+ break;
+ }
+ }
+ CleanupStack::PopAndDestroy( support );
+ if ( !aComplInfo.iProcessed || !aComplInfo.iReplyExpected )
+ {
+ CreateSelfReplyData( aMessage );
+ }
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------------
+// Prepares internal data for completion with "" or "ERROR" messages.
+// More explation in CreateEmptyOrErrorBuffer().
+// ---------------------------------------------------------------------------
+//
+void CATExtMetadata::CreateSelfReplyData( const RMessage2& aMessage )
+ {
+ TRACE_FUNC_ENTRY
+ // "ERROR" or "" needed; initialize
+ iCmdData.iCmdStarted = ETrue;
+ iCmdData.iCmdMessage = aMessage;
+ iCmdData.iHandler = NULL;
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------------
+// Handles support when a master plugin is detected in the plugin data via
+// support data's link (support for a full AT command). If a master plugin is
+// detected then reply is detected from that plugin. No further sending to
+// primary or secondary plugins is repformed.
+// ---------------------------------------------------------------------------
+//
+TBool CATExtMetadata::HandleMasterPluginSupportL(
+ TATExtEntrySupport& aEntrySupport,
+ TBool& aReplyExpected )
+ {
+ TRACE_FUNC_ENTRY
+ aReplyExpected = EFalse;
+ TBool supported = HandleCommandSupportL( aEntrySupport );
+ if ( !supported )
+ {
+ TRACE_FUNC_EXIT
+ return EFalse;
+ }
+ iCmdData.iReplyExpected = ETrue; // Set before HandleCommandL()
+ HandleCommandL( aEntrySupport, ETrue );
+ aReplyExpected = ETrue;
+ TRACE_FUNC_EXIT
+ return ETrue;
+ }
+
+// ---------------------------------------------------------------------------
+// Handles support when a primary plugin is detect in the plugin data via
+// support data's link. If a primary plugin is detected then reply is expected
+// from that plugin. Also if one or more secondary plugins are detected then
+// no reply is expected from them.
+// ---------------------------------------------------------------------------
+//
+TBool CATExtMetadata::HandlePrimaryPluginSupportL(
+ TATExtEntrySupport& aEntrySupport,
+ TInt aStartIndex,
+ TBool& aReplyExpected )
+ {
+ TRACE_FUNC_ENTRY
+ aReplyExpected = EFalse;
+ TBool supported = HandleCommandSupportL( aEntrySupport );
+ if ( !supported )
+ {
+ TRACE_FUNC_EXIT
+ return EFalse;
+ }
+ // If HandleCommand() is implemented synchronously, the command must be
+ // saved before executing as CompleteCommandMessage() closes the string
+ HBufC8* atCmdFull = HBufC8::NewMaxLC( aEntrySupport.iAtCmdFull.Length() );
+ TPtr8 atCmdFullPtr = atCmdFull->Des();
+ atCmdFullPtr.Copy( aEntrySupport.iAtCmdFull );
+ // Now execute the HandleCommand()
+ iCmdData.iReplyExpected = ETrue; // Set before HandleCommandL()
+ HandleCommandL( aEntrySupport, ETrue );
+ aEntrySupport.iStartIndex = aStartIndex;
+ SendToMultipleSecondaryL( aEntrySupport, atCmdFull );
+ CleanupStack::PopAndDestroy( atCmdFull );
+ aReplyExpected = ETrue;
+ TRACE_FUNC_EXIT
+ return ETrue;
+ }
+
+// ---------------------------------------------------------------------------
+// Handles support when a secondary plugin is detected in the plugin data via
+// support data's link. If only one secondary plugin is detected then reply is
+// expected from that plugin. Instead, if more than one secondary plugins are
+// detected then no reply is expected from them.
+// ---------------------------------------------------------------------------
+//
+TBool CATExtMetadata::HandleSecondaryPluginSupportL(
+ TATExtEntrySupport& aEntrySupport,
+ TInt aStartIndex,
+ TBool& aReplyExpected )
+ {
+ TRACE_FUNC_ENTRY
+ aReplyExpected = EFalse;
+ TBool supported = HandleCommandSupportL( aEntrySupport );
+ if ( !supported )
+ {
+ TRACE_FUNC_EXIT
+ return EFalse;
+ }
+ TATExtEntrySupport nextSupport = aEntrySupport;
+ nextSupport.iStartIndex = aStartIndex;
+ TBool entryFound = FindFirstSecondarySupportL( nextSupport );
+ if ( entryFound )
+ {
+ // Entry found; send all without reply request
+ // If HandleCommand() is implemented synchronously, the command must be
+ // saved before executing as CompleteCommandMessage() closes the string
+ HBufC8* atCmdFull = HBufC8::NewMaxLC( aEntrySupport.iAtCmdFull.Length() );
+ TPtr8 atCmdFullPtr = atCmdFull->Des();
+ atCmdFullPtr.Copy( aEntrySupport.iAtCmdFull );
+ // Now execute the HandleCommand()
+ HandleCommandL( aEntrySupport, EFalse );
+ SendToMultipleSecondaryL( nextSupport, atCmdFull );
+ CleanupStack::PopAndDestroy( atCmdFull );
+ }
+ else
+ {
+ // No entry found; send one with reply request
+ iCmdData.iReplyExpected = ETrue; // Set before HandleCommandL()
+ HandleCommandL( aEntrySupport, ETrue );
+ aReplyExpected = ETrue;
+ }
+ TRACE_FUNC_EXIT
+ return ETrue;
+ }
+
+// ---------------------------------------------------------------------------
+// Finds support entries from support data for a given base AT command
+// ---------------------------------------------------------------------------
+//
+CArrayFixFlat<TATExtOneCmdSupport>* CATExtMetadata::FindEntriesForCommandLC(
+ TDesC8& aAtCmdBase )
+ {
+ TRACE_FUNC_ENTRY
+ TBool found;
+ TInt foundPos;
+ CArrayFixFlat<TATExtOneCmdSupport>* support =
+ new (ELeave) CArrayFixFlat<TATExtOneCmdSupport>( KGranularity );
+ CleanupStack::PushL( support );
+ // First find normal data to which to add the aux entries
+ found = FindCommandFromMetadata( aAtCmdBase, foundPos, EFalse, EFalse );
+ if ( found )
+ {
+ CArrayFixFlat<TATExtOneCmdSupport>* entries =
+ (*iSupport)[foundPos].iEntries;
+ support->AppendL( &(*entries)[0], entries->Count() );
+ }
+ // Next add the aux links
+ found = FindCommandFromMetadata( aAtCmdBase, foundPos, ETrue, ETrue );
+ if ( found )
+ {
+ CArrayFixFlat<TATExtOneCmdSupport>* entries =
+ (*iSupportAux)[foundPos].iEntries;
+ TATExtSearchHelper searchHelper;
+ TInt i;
+ TInt count = entries->Count();
+ for ( i=0; i<count; i++ )
+ {
+ TATExtOneCmdSupport& entry = (*entries)[i];
+ AddNewMetadataEntryLinkL( support,
+ entry.iEntryIndex,
+ entry.iSupportType,
+ searchHelper );
+ }
+ }
+ // Now, as the normal data was inserted *before* the auxiliary data, the
+ // auxiliary data is in front of the created "support" array for each M, P
+ // and S entry. This insertion is faster than the other way around as there
+ // can be multiple S plugins for the same command but usually much less
+ // auxiliary entries for the same command.
+#if defined(_DEBUG) && defined( PRJ_PRINT_SUPPORT_DATA )
+ PrintFoundEntries( support );
+#endif
+ if ( support->Count() > 0 )
+ {
+ TRACE_FUNC_EXIT
+ return support;
+ }
+ TRACE_FUNC_EXIT
+ return NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// Instantiates plugin support
+// ---------------------------------------------------------------------------
+//
+void CATExtMetadata::InstantiatePluginSupportL(
+ TATExtEntrySupport& aEntrySupport )
+ {
+ TRACE_FUNC_ENTRY
+ if ( aEntrySupport.iEntry )
+ {
+ InstantiatePluginL( *aEntrySupport.iEntry );
+ }
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------------
+// Instantiates a plugin
+// ---------------------------------------------------------------------------
+//
+void CATExtMetadata::InstantiatePluginL( TATExtPluginEntry& aPluginEntry )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !aPluginEntry.iInstance )
+ {
+ TUid pluginUid = aPluginEntry.iPluginUid;
+ CATExtPluginBase* plugin = CATExtPluginBase::NewL( pluginUid,
+ iObserver,
+ iConnectionName );
+ plugin->ReportQuietModeChange( iQuietMode );
+ plugin->ReportVerboseModeChange( iVerboseMode );
+ plugin->ReportCharacterChange( ECharTypeCarriage, iCarriageReturn );
+ plugin->ReportCharacterChange( ECharTypeLineFeed, iLineFeed );
+ plugin->ReportCharacterChange( ECharTypeBackspace, iBackspace );
+ aPluginEntry.iInstance = plugin;
+ }
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------------
+// Instantiates a plugin
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::InstantiatePlugin( TATExtPluginEntry& aPluginEntry )
+ {
+ TRACE_FUNC_ENTRY
+ TRAPD( retTrap, InstantiatePluginL(aPluginEntry) );
+ TRACE_FUNC_EXIT
+ return retTrap;
+ }
+
+// ---------------------------------------------------------------------------
+// Handles an AT command support request
+// ---------------------------------------------------------------------------
+TBool CATExtMetadata::HandleCommandSupportL( TATExtEntrySupport& aEntrySupport,
+ const TDesC8* aAtCmdFull )
+ {
+ TRACE_FUNC_ENTRY
+ InstantiatePluginSupportL( aEntrySupport );
+ TBool supported = EFalse;
+ if ( aEntrySupport.iEntry->iLocked )
+ {
+ TRACE_FUNC_EXIT
+ User::Leave( KErrAccessDenied );
+ }
+ if ( !aAtCmdFull )
+ {
+ supported = aEntrySupport.iEntry->iInstance->IsCommandSupported(
+ aEntrySupport.iAtCmdFull );
+ }
+ else
+ {
+ supported = aEntrySupport.iEntry->iInstance->IsCommandSupported(
+ *aAtCmdFull );
+ }
+ TRACE_FUNC_EXIT
+ return supported;
+ }
+
+// ---------------------------------------------------------------------------
+// Handles an AT command
+// ---------------------------------------------------------------------------
+void CATExtMetadata::HandleCommandL( TATExtEntrySupport& aEntrySupport,
+ TBool aReplyNeeded,
+ const TDesC8* aAtCmdFull )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !aEntrySupport.iEntry || !aEntrySupport.iEntry->iInstance )
+ {
+ TRACE_FUNC_EXIT
+ User::Leave( KErrGeneral );
+ }
+ if ( aEntrySupport.iEntry->iLocked )
+ {
+ TRACE_FUNC_EXIT
+ User::Leave( KErrAccessDenied );
+ }
+ // As HandleCommand() could complete the message synchronously, set the
+ // iCmdData before the call
+ if ( aReplyNeeded )
+ {
+ iCmdData.iCmdStarted = ETrue;
+ iCmdData.iCmdMessage = aEntrySupport.iMessage;
+ iCmdData.iHandler = aEntrySupport.iEntry;
+ }
+ // No "else" here as HandleCommandL() is used also with secondary plugins
+ if ( !aAtCmdFull )
+ {
+ TRACE_INFO(( _L8("Handling command '%S' for UID:0x%08X, aReplyNeeded=%d..."), &iCmdData.iCmdBuffer, aEntrySupport.iEntry->iPluginUid, aReplyNeeded ));
+ aEntrySupport.iEntry->iInstance->HandleCommand(
+ iCmdData.iCmdBuffer,
+ iCmdData.iCmdReplyBuffer,
+ aReplyNeeded );
+ }
+ else
+ {
+ TRACE_INFO(( _L8("Handling command '%S' for UID:0x%08X, aReplyNeeded=%d..."), &(*aAtCmdFull), aEntrySupport.iEntry->iPluginUid, aReplyNeeded ));
+ aEntrySupport.iEntry->iInstance->HandleCommand(
+ *aAtCmdFull,
+ iCmdData.iCmdReplyBuffer,
+ aReplyNeeded );
+ }
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------------
+// Sends an AT commands to multiple secondary plugins, starting from a given
+// position.
+// ---------------------------------------------------------------------------
+//
+void CATExtMetadata::SendToMultipleSecondaryL(
+ TATExtEntrySupport& aEntrySupport,
+ const TDesC8* aAtCmdFull )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !aEntrySupport.iSupport )
+ {
+ TRACE_FUNC_EXIT
+ User::Leave( KErrGeneral );
+ }
+ TInt i;
+ TInt count = aEntrySupport.iSupport->Count();
+ for ( i=aEntrySupport.iStartIndex; i<count; i++ )
+ {
+ TATExtOneCmdSupport& oneCmdSupport = (*aEntrySupport.iSupport)[i];
+ if ( oneCmdSupport.iSupportType != ESupportTypeSecondary )
+ {
+ continue;
+ }
+ aEntrySupport.iEntry = &(*iPluginData)[i];
+ TBool supported = HandleCommandSupportL( aEntrySupport, aAtCmdFull );
+ if ( supported )
+ {
+ HandleCommandL( aEntrySupport, EFalse, aAtCmdFull );
+ }
+ }
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------------
+// Finds the first secondary plugin support from a given starting position
+// ---------------------------------------------------------------------------
+//
+TBool CATExtMetadata::FindFirstSecondarySupportL(
+ TATExtEntrySupport& aEntrySupport )
+ {
+ TRACE_FUNC_ENTRY
+ if ( !aEntrySupport.iSupport )
+ {
+ TRACE_FUNC_EXIT
+ User::Leave( KErrGeneral );
+ }
+ TInt i;
+ TInt count = aEntrySupport.iSupport->Count();
+ for ( i=aEntrySupport.iStartIndex; i<count; i++ )
+ {
+ TATExtOneCmdSupport& oneCmdSupport = (*aEntrySupport.iSupport)[i];
+ if ( oneCmdSupport.iSupportType != ESupportTypeSecondary )
+ {
+ continue;
+ }
+ aEntrySupport.iEntry = &(*iPluginData)[i];
+ TBool supported = HandleCommandSupportL( aEntrySupport );
+ if ( supported )
+ {
+ TRACE_FUNC_EXIT
+ return ETrue;
+ }
+ }
+ TRACE_FUNC_EXIT
+ return EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// Extracts one NVRAM entry from a pipe-character delimited NVRAM buffer
+// ---------------------------------------------------------------------------
+//
+TBool CATExtMetadata::ExtractNextNvramSetting( const TDesC8& aNvram,
+ TInt& aStartIndex,
+ TInt& aEndIndex )
+ {
+ TRACE_FUNC_ENTRY
+ // Skip data before command
+ TInt i;
+ TChar character;
+ TInt count = aNvram.Length();
+ for ( i=aEndIndex; i<count; i++ )
+ {
+ character = aNvram[i];
+ if ( character.IsPrint() && character!='|' )
+ {
+ break;
+ }
+ }
+ if ( i >= count )
+ {
+ TRACE_FUNC_EXIT
+ return EFalse;
+ }
+ aStartIndex = i;
+ // Start of command found, next mark the end
+ while ( i < count )
+ {
+ character = aNvram[i];
+ if ( !character.IsPrint() || character=='|' )
+ {
+ break;
+ }
+ i++;
+ }
+ aEndIndex = i;
+ if ( aEndIndex-aStartIndex <= 0 )
+ {
+ TRACE_FUNC_EXIT
+ return EFalse;
+ }
+ TRACE_FUNC_EXIT
+ return ETrue;
+ }
+
+// ---------------------------------------------------------------------------
+// Gets the next command from support or auxiliary support data.
+// ---------------------------------------------------------------------------
+//
+HBufC8* CATExtMetadata::GetNextSupportedCommand( TBool& aFirstSearch,
+ TInt& aSupportFind,
+ TBool& aFindInAux )
+ {
+ TRACE_FUNC_ENTRY
+ // If first search then start from index 0, othewise start from the
+ // next index
+ if ( aFirstSearch )
+ {
+ aSupportFind = -1;
+ aFindInAux = EFalse;
+ }
+ aSupportFind++;
+ aFirstSearch = EFalse;
+ CArrayFixFlat<TATExtAtCmdSupport>* support = iSupport;
+ if ( !aFindInAux )
+ {
+ if ( aSupportFind >= support->Count() )
+ {
+ aSupportFind = 0;
+ aFindInAux = ETrue;
+ support = iSupportAux;
+ if ( aSupportFind >= support->Count() )
+ {
+ TRACE_FUNC_EXIT
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ support = iSupportAux;
+ if ( aSupportFind >= support->Count() )
+ {
+ TRACE_FUNC_EXIT
+ return NULL;
+ }
+ }
+ TATExtAtCmdSupport& supportEntry = (*support)[aSupportFind];
+ HBufC8& atCmdBase = *supportEntry.iAtCmdBase;
+ HBufC8* newBuffer = HBufC8::NewMax( atCmdBase.Length() );
+ if ( newBuffer )
+ {
+ newBuffer->Des().Copy( atCmdBase );
+ }
+ TRACE_FUNC_EXIT
+ return newBuffer;
+ }
+
+// ---------------------------------------------------------------------------
+// Reads an AT command from a client request message and creates buffer
+// locally. For HandleCommand().
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::ReadCommandFromMessage( const RMessage2& aMessage )
+ {
+ TRACE_FUNC_ENTRY
+ // Read AT command from message, stop if error encountered
+ TInt desLength = aMessage.GetDesLength( EATExtHandleCmdParamCmd );
+ if ( desLength <= 0 )
+ {
+ TRACE_FUNC_EXIT
+ return KErrArgument;
+ }
+ TInt retTemp = iCmdData.iCmdBuffer.Create( desLength );
+ if ( retTemp != KErrNone )
+ {
+ TRACE_FUNC_EXIT
+ return retTemp;
+ }
+ retTemp = aMessage.Read( EATExtHandleCmdParamCmd, iCmdData.iCmdBuffer );
+ TRACE_INFO(( _L("Read returned %d"), retTemp ));
+ if ( retTemp != KErrNone )
+ {
+ iCmdData.iCmdBuffer.Close();
+ TRACE_FUNC_EXIT
+ return retTemp;
+ }
+ TRACE_FUNC_EXIT
+ return retTemp;
+ }
+
+// ---------------------------------------------------------------------------
+// Creates a buffer with "ERROR" or "" string in it; needed for creating a
+// reply to an unknown command (i.e. when no plugin supports the "base" part
+// of a command) or to the case when plugin support exists but reply is not
+// expected from them.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::CreateEmptyOrErrorBuffer( RBuf8& aBuffer,
+ TBool aErrorReply )
+ {
+ TRACE_FUNC_ENTRY
+ // Note: The behavior of RBuf8 is awkward. It is not possible to query
+ // the "allocation status". Comparing the length to zero always returns
+ // true even if RBuf8::Create() was not called. Here we should do the
+ // following: If allocated and zero length, return with KErrNone. Otherwise
+ // if not allocated create the buffer and return with RBuf::Create()'s
+ // return code. We have to hack here so let's expect the buffer is not
+ // allocated when calling this function.
+ if ( !aErrorReply )
+ {
+ TInt retTemp = aBuffer.Create( KNullDesC8 );
+ TRACE_FUNC_EXIT
+ return retTemp;
+ }
+ TInt retVal = KErrNone;
+ TBuf8<KErrorMsgLen> errorBuffer;
+ if ( !iQuietMode )
+ {
+ if ( iVerboseMode )
+ {
+ _LIT8( KVerboseError, "ERROR" );
+ errorBuffer.Append( iCarriageReturn );
+ errorBuffer.Append( iLineFeed );
+ errorBuffer.Append( KVerboseError );
+ errorBuffer.Append( iCarriageReturn );
+ errorBuffer.Append( iLineFeed );
+ }
+ else
+ {
+ _LIT8( KNumericError, "4" );
+ errorBuffer.Append( KNumericError );
+ errorBuffer.Append( iCarriageReturn );
+ }
+ }
+ retVal = aBuffer.Create( errorBuffer );
+ TRACE_FUNC_EXIT
+ return retVal;
+ }
+
+// ---------------------------------------------------------------------------
+// Writes specified input reply buffer to a client request message at given
+// message slot number.
+// ---------------------------------------------------------------------------
+//
+TInt CATExtMetadata::WriteReplyBufferToClient( const TDesC8& aBuffer,
+ TInt aDataSlot,
+ const RMessage2& aMessage,
+ TBool aReportNextLength,
+ TInt aLengthSlot )
+ {
+ TRACE_FUNC_ENTRY
+ TInt maxLength = aMessage.GetDesMaxLength( aDataSlot );
+ if ( aBuffer.Length() > maxLength )
+ {
+ TRACE_FUNC_EXIT
+ return KErrTooBig;
+ }
+ TInt retTemp = aMessage.Write( aDataSlot, aBuffer );
+ TRACE_INFO(( _L("First write returned %d"), retTemp ));
+ if ( retTemp != KErrNone )
+ {
+ TRACE_FUNC_EXIT
+ return retTemp;
+ }
+ if ( aReportNextLength && iCmdData.iHandler &&
+ iCmdData.iHandler->iInstance ) // optional
+ {
+ CATExtPluginBase& plugin = *iCmdData.iHandler->iInstance;
+ TInt nextPartLength = plugin.NextReplyPartLength();
+ if ( nextPartLength <= 0 )
+ {
+ iCmdData.iHandler = NULL;
+ }
+ TPckg<TInt> nextPartLengthPckg( nextPartLength );
+ retTemp = aMessage.Write( aLengthSlot, nextPartLengthPckg );
+ TRACE_INFO(( _L("Second write returned %d"), retTemp ));
+ if ( retTemp != KErrNone )
+ {
+ TRACE_FUNC_EXIT
+ return retTemp;
+ }
+ }
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }