/*
* 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"
* 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): Sends to all O if support found. Panics if > 1 M.
* 2) Partial (P): Sends to all O if support found. Replies "ERROR" if two P supports.
* 3) Observer (O): Process the command and give or not give reply, based on
* the following logic:
*
* => [If] M found, handle command and send reply + send to N O {no reply}, stop, [else]
* [If] P found, handle command and send reply + send to N O {no reply}, stop, [else]
* [If] > 1 O found, send to N O {no reply}, stop, [else]
* [If] only 1 O 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 O and M, P nor other O 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;
}
// First check if in editor mode
if ( iCmdData.iEditorHandler )
{
iCmdData.iReplyExpected = EFalse;
iCmdData.iHandler = iCmdData.iEditorHandler;
iCmdData.iHandler->iInstance->HandleCommand( iCmdData.iCmdBuffer,
iCmdData.iCmdReplyBuffer,
EFalse );
aComplInfo.iProcessed = ETrue;
aComplInfo.iReplyExpected = ETrue;
// Note: The aComplInfo.iReplyExpected is used only for normal mode and
// is set to ETrue here to skip a check in CATExtSession::IpcHandleCommand().
TRACE_FUNC_EXIT
return KErrNone;
}
// Not in editor so handle in normal mode
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;
}
if ( !iCmdData.iCmdMessage.Handle() )
{
TRACE_FUNC_EXIT
return KErrBadHandle;
}
TBool startOfEditor = EFalse;
if ( aReplyType == EReplyTypeEditor)
{
// If completion is for editor command then set iCmdData.iEditorHandler
// for the first time only
if ( !iCmdData.iEditorHandler )
{
iCmdData.iEditorHandler = FindInstanceFromPlugindata( aPlugin );
iCmdData.iReplyExpected = ETrue; // reply expected when first reply in editor mode
startOfEditor = ETrue;
}
}
else
{
// If completion was something else than EReplyTypeEditor then just end
// editor mode (no need to check iEditorHandler)
if ( iCmdData.iEditorHandler )
{
iCmdData.iReplyExpected = ETrue; // reply expected when last reply in editor mode
}
iCmdData.iEditorHandler = NULL;
}
// 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 && !iCmdData.iEditorHandler )
{
TRACE_FUNC_EXIT
return KErrAlreadyExists;
}
// 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 );
}
WriteHandleCmdReplyBuffer( aMultiPart, startOfEditor );
}
iCmdData.iCmdStarted = EFalse;
iCmdData.iReplyExpected = EFalse;
iCmdData.iCmdMessage.Complete( aError );
ClearInitializedCmdHandlerData( aMultiPart );
TRACE_FUNC_EXIT
return KErrNone;
}
// ---------------------------------------------------------------------------
// Writes multipart or single part reply buffer to client for handle.
// Used for creating a reply for HandleCommand().
// ---------------------------------------------------------------------------
//
TInt CATExtMetadata::WriteHandleCmdReplyBuffer( TBool aMultiPart,
TBool aStartOfEditor )
{
TRACE_FUNC_ENTRY
if ( iCmdData.iEditorHandler && !aStartOfEditor )
{
TRACE_FUNC_EXIT
return KErrNotReady;
}
if ( aMultiPart )
{
WriteReplyBufferToClient( iCmdData.iCmdReplyBuffer,
EATExtHandleCmdParamReply,
iCmdData.iCmdMessage,
ETrue,
EATExtHandleCmdParamLength );
}
else
{
WriteReplyBufferToClient( iCmdData.iCmdReplyBuffer,
EATExtHandleCmdParamReply,
iCmdData.iCmdMessage );
}
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;
iCmdData.iEditorHandler = 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;
iCmdData.iEditorHandler = 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();
iCmdData.iEditorHandler = NULL;
}
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': // Partial plugin
case 'p':
aSupportType = ESupportTypePartial;
break;
case 'O': // Observer plugin
case 'o':
aSupportType = ESupportTypeObserver;
break;
default:
_LIT( KPluginType, "PluginType" );
User::Panic( KPluginType, EPanicCategoryType );
}
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 ESupportTypePartial:
{
retVal = AddNewPartialMetadataEntryLinkL( aEntries,
aSearchHelper,
oneCmdSupport );
}
break;
case ESupportTypeObserver:
{
retVal = AddNewObserverMetadataEntryLinkL( 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
if ( aEntries->Count() > 0 )
{
TATExtOneCmdSupport& oneCmdSupport = (*aEntries)[0];
if ( oneCmdSupport.iSupportType == ESupportTypePartial )
{
_LIT( KAddMIsP, "AddMIsP" );
User::Panic( KAddMIsP, EPanicCategoryAddMIsP );
}
if ( oneCmdSupport.iSupportType == ESupportTypeMaster )
{
_LIT( KAddMIsM, "AddMIsM" );
User::Panic( KAddMIsM, EPanicCategoryAddMIsM );
}
}
aEntries->InsertL( 0, aOneCmdSupport );
if ( aSearchHelper.iPartialIndex >= 0 )
{
aSearchHelper.iPartialIndex++;
}
if ( aSearchHelper.iObserverIndex >= 0 )
{
aSearchHelper.iObserverIndex++;
}
TRACE_FUNC_EXIT
return 0;
}
// ---------------------------------------------------------------------------
// Adds new partial plugin entry link from plugin support entry to plugin
// entry
// ---------------------------------------------------------------------------
//
TInt CATExtMetadata::AddNewPartialMetadataEntryLinkL(
CArrayFixFlat<TATExtOneCmdSupport>* aEntries,
TATExtSearchHelper& aSearchHelper,
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 )
{
TInt count = aEntries->Count();
for ( i=0; i<count; i++ )
{
TATExtOneCmdSupport& oneCmdSupport = (*aEntries)[i];
if ( oneCmdSupport.iSupportType==ESupportTypePartial ||
oneCmdSupport.iSupportType==ESupportTypeObserver )
{
break;
}
}
aSearchHelper.iPartialIndex = i;
}
aEntries->InsertL( i, aOneCmdSupport );
if ( aSearchHelper.iObserverIndex >= 0 )
{
aSearchHelper.iObserverIndex++;
}
TRACE_FUNC_EXIT
return i;
}
// ---------------------------------------------------------------------------
// Adds new observer plugin entry link from plugin support entry to plugin
// entry. Search starts from the front as there could be multiple O plugins
// but only one or two M/P plugins.
// ---------------------------------------------------------------------------
//
TInt CATExtMetadata::AddNewObserverMetadataEntryLinkL(
CArrayFixFlat<TATExtOneCmdSupport>* aEntries,
TATExtSearchHelper& aSearchHelper,
TATExtOneCmdSupport& aOneCmdSupport )
{
TRACE_FUNC_ENTRY
TInt i = aSearchHelper.iObserverIndex;
if ( i < 0 )
{
TInt count = aEntries->Count();
for ( i=0; i<count; i++ )
{
TATExtOneCmdSupport& oneCmdSupport = (*aEntries)[i];
if ( oneCmdSupport.iSupportType == ESupportTypeObserver )
{
break;
}
}
aSearchHelper.iObserverIndex = 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 fullLength = aAtCmdFull.Length();
TInt newLength = fullLength;
TInt findIndex = KErrNotFound;
TInt foundPos = aAtCmdFull.Locate( '=' );
TRACE_INFO(( _L8("Base length before = %d"), fullLength ));
if ( foundPos >= 2 ) // After "AT"
{
findIndex = foundPos - 1;
newLength = foundPos;
}
else if ( fullLength >= 3 ) // At least "AT?"
{
// There was no '=' so check if the last character is '?'.
// If it is then remove it.
TInt lastIndex = fullLength - 1;
if ( aAtCmdFull[lastIndex] == '?' )
{
findIndex = lastIndex - 1;
newLength = fullLength - 1;
}
}
// Next correct newLength so that it doesn't contain the space(s)
for ( ; findIndex>=2; findIndex--,newLength-- )
{
TChar character = aAtCmdFull[findIndex];
if ( !(character.IsSpace()||character==0x00) )
{
break;
}
}
TRACE_INFO(( _L8("Base length after = %d"), 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,
const_cast<RMessage2&>(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 = HandleMasterAndPartialPluginSupportL(
entrySupport,
i+1,
aComplInfo.iReplyExpected );
}
else if ( oneCmdSupport.iSupportType == ESupportTypePartial )
{
supported = FindExclusivePartialSupportL( entrySupport );
if ( !supported )
{
break;
}
supported = HandleMasterAndPartialPluginSupportL(
entrySupport,
i+1,
aComplInfo.iReplyExpected );
}
else if ( oneCmdSupport.iSupportType == ESupportTypeObserver )
{
supported = HandleObserverPluginSupportL(
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 or partial plugin is detected in the plugin
// data via support data's link. If a partial or master plugin is detected
// then reply is expected from that plugin. Also if one or more observer
// plugins are detected then no reply is expected from them.
// ---------------------------------------------------------------------------
//
TBool CATExtMetadata::HandleMasterAndPartialPluginSupportL(
TATExtEntrySupport& aEntrySupport,
TInt aStartIndex,
TBool& aReplyExpected )
{
TRACE_FUNC_ENTRY
aReplyExpected = EFalse;
if ( !aEntrySupport.iSupportFound )
{
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 );
// First send the entry to the observers
TATExtEntrySupport handleCommandEntry = aEntrySupport;
aEntrySupport.iStartIndex = aStartIndex;
SendToMultipleObserverL( aEntrySupport, atCmdFull );
aEntrySupport = handleCommandEntry;
// Now execute the HandleCommand()
iCmdData.iReplyExpected = ETrue; // Set before HandleCommandL()
HandleCommandL( aEntrySupport, ETrue );
CleanupStack::PopAndDestroy( atCmdFull );
aReplyExpected = ETrue;
TRACE_FUNC_EXIT
return ETrue;
}
// ---------------------------------------------------------------------------
// Handles support when a observer plugin is detected in the plugin data via
// support data's link. If only one observer plugin is detected then reply is
// expected from that plugin. Instead, if more than one observer plugins are
// detected then no reply is expected from them.
// ---------------------------------------------------------------------------
//
TBool CATExtMetadata::HandleObserverPluginSupportL(
TATExtEntrySupport& aEntrySupport,
TInt aStartIndex,
TBool& aReplyExpected )
{
TRACE_FUNC_ENTRY
aReplyExpected = EFalse;
if ( !aEntrySupport.iSupportFound )
{
TBool supported = HandleCommandSupportL( aEntrySupport );
if ( !supported )
{
TRACE_FUNC_EXIT
return EFalse;
}
}
TATExtEntrySupport nextSupport = aEntrySupport;
nextSupport.iStartIndex = aStartIndex;
TBool entryFound = FindFirstObserverSupportL( 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()
SendToMultipleObserverL( nextSupport, atCmdFull );
HandleCommandL( aEntrySupport, EFalse );
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 exclusive partial plugin support
// ---------------------------------------------------------------------------
//
TBool CATExtMetadata::FindExclusivePartialSupportL(
TATExtEntrySupport& aEntrySupport )
{
TRACE_FUNC_ENTRY
TInt i;
TInt supports;
TInt count = aEntrySupport.iSupport->Count();
for ( i=0,supports=0; i<count; i++ )
{
TATExtOneCmdSupport& oneCmdSupport = (*aEntrySupport.iSupport)[i];
if ( oneCmdSupport.iSupportType == ESupportTypePartial )
{
aEntrySupport.iSupportFound = EFalse;
aEntrySupport.iEntry = &(*iPluginData)[oneCmdSupport.iEntryIndex];
TBool supported = HandleCommandSupportL( aEntrySupport );
if ( supported )
{
aEntrySupport.iSupportFound = ETrue;
supports++;
}
if ( supports != 1 )
{
TRACE_FUNC_EXIT
return EFalse;
}
}
}
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 O entry. This insertion is faster than the other way around as there
// can be multiple O 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;
iCmdData.iEditorHandler = NULL;
}
// No "else" here as HandleCommandL() is used also with observer 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 observer plugins, starting from a given
// position.
// ---------------------------------------------------------------------------
//
void CATExtMetadata::SendToMultipleObserverL(
TATExtEntrySupport& aEntrySupport,
const TDesC8* aAtCmdFull )
{
TRACE_FUNC_ENTRY
if ( !aEntrySupport.iSupport )
{
TRACE_FUNC_EXIT
User::Leave( KErrGeneral );
}
if ( !aEntrySupport.iSupportFound )
{
// No initial support found -> do nothing
TRACE_FUNC_EXIT
return;
}
TInt i;
TInt count = aEntrySupport.iSupport->Count();
for ( i=aEntrySupport.iStartIndex; i<count; i++ )
{
TATExtOneCmdSupport& oneCmdSupport = (*aEntrySupport.iSupport)[i];
if ( oneCmdSupport.iSupportType != ESupportTypeObserver )
{
continue;
}
aEntrySupport.iEntry = &(*iPluginData)[oneCmdSupport.iEntryIndex];
TBool supported = HandleCommandSupportL( aEntrySupport, aAtCmdFull );
if ( supported )
{
HandleCommandL( aEntrySupport, EFalse, aAtCmdFull );
aEntrySupport.iSupportFound = ETrue;
}
if ( i < count-1 )
{
aEntrySupport.iSupportFound = EFalse;
}
}
TRACE_FUNC_EXIT
}
// ---------------------------------------------------------------------------
// Finds the first observer plugin support from a given starting position
// ---------------------------------------------------------------------------
//
TBool CATExtMetadata::FindFirstObserverSupportL(
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 != ESupportTypeObserver )
{
continue;
}
aEntrySupport.iSupportFound = EFalse;
aEntrySupport.iEntry = &(*iPluginData)[oneCmdSupport.iEntryIndex];
TBool supported = HandleCommandSupportL( aEntrySupport );
if ( supported )
{
aEntrySupport.iSupportFound = ETrue;
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;
}
// ---------------------------------------------------------------------------
// Assignment operator for ease of usage
// ---------------------------------------------------------------------------
//
TATExtEntrySupport& TATExtEntrySupport::operator=( TATExtEntrySupport& aEntrySupport )
{
if ( &aEntrySupport == this )
{
return aEntrySupport;
}
iAtCmdFull = aEntrySupport.iAtCmdFull;
iMessage = aEntrySupport.iMessage;
iSupport = aEntrySupport.iSupport;
iEntry = aEntrySupport.iEntry;
iStartIndex = aEntrySupport.iStartIndex;
iSupportFound = aEntrySupport.iSupportFound;
return *this;
}