atext/server/src/atextmetadata.cpp
changeset 0 29b1cd4cb562
child 1 b4a7eebaaebf
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 /*
       
     2 * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Metadata for ATEXT
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 /*
       
    20  * Here is the plugin managing logic for the AT commands and hopefully also for
       
    21  * future needs:
       
    22  *
       
    23  * Three types of support:
       
    24  * 1) Master (M): Does not send to S if support found.
       
    25  * 2) Primary (P): Sends to all S if support found.
       
    26  * 3) Secondary (S): Process the command and give or not give reply, based on
       
    27  *    the following logic:
       
    28  *
       
    29  * => [If] M found, handle command and send reply, stop, [else]
       
    30  * [If] P found, handle command and send reply + send to N S {no reply}, stop, [else]
       
    31  * [If] > 1 S found, send to N S {no reply}, stop, [else]
       
    32  * [If] only 1 S found, handle command and send reply, stop, [else]
       
    33  * Write "ERROR" to client, complete message with KErrNone
       
    34  *
       
    35  * When incoming reply:
       
    36  * => If reply from M, write to client, stop, [else]
       
    37  * If reply from P, write to client, stop, [else]
       
    38  * If reply from S and M, P nor other S exist, write to client, stop, [else]
       
    39  * Complete message with KErrNone and empty string
       
    40  *
       
    41  * Note: Empty string and "ERROR" string are managed already in HandleCommand()
       
    42  */
       
    43 
       
    44 #include <ecom/ecom.h>
       
    45 #include <ecom/implementationInformation.h>
       
    46 #include <atextpluginbase.h>
       
    47 #include "atextclientsrv.h"
       
    48 #include "atextmetadata.h"
       
    49 #include "atextlisten.h"
       
    50 #include "utils.h"
       
    51 #include "debug.h"
       
    52 
       
    53 const TInt  KGranularity           = 4;
       
    54 const TInt8 KDefaultCarriageReturn = 13;
       
    55 const TInt8 KDefaultLineFeed       = 10;
       
    56 const TInt  KErrorMsgLen           = 9;  // 2+"ERROR"+2
       
    57 
       
    58 // ---------------------------------------------------------------------------
       
    59 // Two-phased constructor.
       
    60 // ---------------------------------------------------------------------------
       
    61 //
       
    62 CATExtMetadata* CATExtMetadata::NewL( REComSession& aEComSession,
       
    63                                       CATExtListen* aListener,
       
    64                                       MATExtPluginObserver& aObserver )
       
    65     {
       
    66     CATExtMetadata* self = NewLC( aEComSession, aListener, aObserver );
       
    67     CleanupStack::Pop( self );
       
    68     return self;
       
    69     }
       
    70 
       
    71 // ---------------------------------------------------------------------------
       
    72 // Two-phased constructor.
       
    73 // ---------------------------------------------------------------------------
       
    74 //
       
    75 CATExtMetadata* CATExtMetadata::NewLC( REComSession& aEComSession,
       
    76                                        CATExtListen* aListener,
       
    77                                        MATExtPluginObserver& aObserver )
       
    78     {
       
    79     CATExtMetadata* self = new (ELeave) CATExtMetadata( aEComSession,
       
    80                                                         aListener,
       
    81                                                         aObserver );
       
    82     CleanupStack::PushL( self );
       
    83     self->ConstructL();
       
    84     return self;
       
    85     }
       
    86 
       
    87 // ---------------------------------------------------------------------------
       
    88 // Destructor.
       
    89 // ---------------------------------------------------------------------------
       
    90 //
       
    91 CATExtMetadata::~CATExtMetadata()
       
    92     {
       
    93     ResetData();
       
    94     }
       
    95 
       
    96 // ---------------------------------------------------------------------------
       
    97 // Resets data to initial values
       
    98 // ---------------------------------------------------------------------------
       
    99 //
       
   100 void CATExtMetadata::ResetData()
       
   101     {
       
   102     TRACE_FUNC_ENTRY
       
   103     iShutdown = ETrue;
       
   104     DestroyPlugindata();
       
   105     DestroySupportdata( iSupport );
       
   106     DestroySupportdata( iSupportAux );
       
   107     iConnectionName.Close();
       
   108     iShutdown = EFalse;
       
   109     TRACE_FUNC_EXIT
       
   110     }
       
   111 
       
   112 // ---------------------------------------------------------------------------
       
   113 // Creates new implementation metadata based on a given interface UID and
       
   114 // connection. Uses AddImplementationL() to add new implementations for the
       
   115 // interface and sets connection identification name for reporting it to the
       
   116 // plugins on instantiation time.
       
   117 // ---------------------------------------------------------------------------
       
   118 //
       
   119 void CATExtMetadata::CreateImplementationMetadataL( TUid& aIfUid,
       
   120                                                     const TDesC8& aName )
       
   121     {
       
   122     TRACE_FUNC_ENTRY
       
   123     if ( iPluginData || iSupport || iSupportAux )
       
   124         {
       
   125         TRACE_FUNC_EXIT
       
   126         User::Leave( KErrGeneral );
       
   127         }
       
   128     iIfUid = aIfUid;
       
   129     iConnectionName.CreateL( aName );
       
   130     RImplInfoPtrArray implementations;
       
   131     CleanupResetDestroyClosePushL( implementations );
       
   132     iEComSession.ListImplementationsL( iIfUid, implementations );
       
   133     const TUint implCount = implementations.Count();
       
   134     TRACE_INFO((_L("Number of AT Ext: %d"), implCount))
       
   135     iSupport = new (ELeave) CArrayFixFlat<TATExtAtCmdSupport>( KGranularity );
       
   136     iSupportAux = new (ELeave) CArrayFixFlat<TATExtAtCmdSupport>( KGranularity );
       
   137     iPluginData = new (ELeave) CArrayFixFlat<TATExtPluginEntry>( KGranularity );
       
   138     // As iSupport, iSupportAux and iPluginData are needed by
       
   139     // AddImplementationL(), no ease way to use temporary variables here.
       
   140     // If error occurs here then deletion of this class is required.
       
   141     for ( TUint i=0; i<implCount; i++ )
       
   142         {
       
   143         AddImplementationL( implementations[i] );
       
   144         }
       
   145     CleanupStack::PopAndDestroy( &implementations );
       
   146 #if defined(_DEBUG) && defined( PRJ_PRINT_SUPPORT_DATA )
       
   147     PrintSupportData( iSupport );
       
   148     PrintSupportData( iSupportAux );
       
   149 #endif
       
   150     TRACE_FUNC_EXIT
       
   151     }
       
   152 
       
   153 // ---------------------------------------------------------------------------
       
   154 // Adds an implementation to the metadata based on a given ECOM implementation
       
   155 // information. This is used by the function CreateImplementationMetadataL()
       
   156 // and also by CATExtSession when its ECOM notification listener detects an
       
   157 // addition for a the same ECOM interface.
       
   158 // ---------------------------------------------------------------------------
       
   159 //
       
   160 void CATExtMetadata::AddImplementationL( CImplementationInformation* aImplInfo )
       
   161     {
       
   162     TRACE_FUNC_ENTRY
       
   163     if ( !aImplInfo )
       
   164         {
       
   165         TRACE_FUNC_EXIT
       
   166         User::Leave( KErrGeneral );
       
   167         }
       
   168     DoAddImplementationL( aImplInfo, aImplInfo->DataType() );
       
   169     DoAddImplementationL( aImplInfo, aImplInfo->OpaqueData() );
       
   170     TRACE_FUNC_EXIT
       
   171     }
       
   172 
       
   173 // ---------------------------------------------------------------------------
       
   174 // Removes an implementation from the support data by a given plugin UID.
       
   175 // ---------------------------------------------------------------------------
       
   176 //
       
   177 TInt CATExtMetadata::RemoveImplementation( TUid& aPluginUid,
       
   178                                            TBool aInstanceExists )
       
   179     {
       
   180     TRACE_FUNC_ENTRY
       
   181     if ( iShutdown )
       
   182         {
       
   183         TRACE_FUNC_EXIT
       
   184         return KErrNotReady;
       
   185         }
       
   186     DoRemoveImplementation( aPluginUid, iSupport );
       
   187     DoRemoveImplementation( aPluginUid, iSupportAux );
       
   188     TInt retVal = RemoveOnePlugindata( aPluginUid, aInstanceExists );
       
   189     TRACE_FUNC_EXIT
       
   190     return retVal;
       
   191     }
       
   192 
       
   193 // ---------------------------------------------------------------------------
       
   194 // Handles an AT command
       
   195 // ---------------------------------------------------------------------------
       
   196 //
       
   197 TInt CATExtMetadata::HandleCommand( const RMessage2& aMessage,
       
   198                                     TATExtCompletionInfo& aComplInfo )
       
   199     {
       
   200     TRACE_FUNC_ENTRY
       
   201     iCmdData.iCmdMessage = aMessage;
       
   202     if ( IsCommandHandling() )
       
   203         {
       
   204         TRACE_FUNC_EXIT
       
   205         return KErrInUse;
       
   206         }
       
   207     // Next pass the entry to command reader
       
   208     TInt retTemp = ReadCommandFromMessage( aMessage );
       
   209     if ( retTemp != KErrNone )
       
   210         {
       
   211         TRACE_FUNC_EXIT
       
   212         return retTemp;
       
   213         }
       
   214     TRACE_INFO(( _L8("Received command '%S'"), &iCmdData.iCmdBuffer ));
       
   215     // Now the command exists. Load the plugins for a command and check support.
       
   216     TRAPD( retTrap, CreateAndFindSupportL(iCmdData.iCmdBuffer,
       
   217                                           aMessage,
       
   218                                           aComplInfo ) );
       
   219     TRACE_FUNC_EXIT
       
   220     return retTrap;
       
   221     }
       
   222 
       
   223 // ---------------------------------------------------------------------------
       
   224 // Cancels an active handle command operation. Uses IsCommandHandling() and
       
   225 // CancelCommandOperation().
       
   226 // ---------------------------------------------------------------------------
       
   227 //
       
   228 TInt CATExtMetadata::CancelHandleCommand()
       
   229     {
       
   230     TRACE_FUNC_ENTRY
       
   231     if ( !IsCommandHandling() )
       
   232         {
       
   233         TRACE_FUNC_EXIT
       
   234         return KErrNotReady;
       
   235         }
       
   236     CancelCommandOperation( KErrCancel, ETrue );
       
   237     TRACE_FUNC_EXIT
       
   238     return KErrNone;
       
   239     }
       
   240 
       
   241 // ---------------------------------------------------------------------------
       
   242 // Gets the next part of a reply for HandleCommand(). Length of returned reply
       
   243 // must be the same as the one reported from NextReplyPartLength() for the
       
   244 // current reply.
       
   245 // ---------------------------------------------------------------------------
       
   246 //
       
   247 TInt CATExtMetadata::GetNextPartOfReply( const RMessage2& aMessage )
       
   248     {
       
   249     TRACE_FUNC_ENTRY
       
   250     if ( !iCmdData.iHandler || !iCmdData.iHandler->iInstance )
       
   251         {
       
   252         TRACE_FUNC_EXIT
       
   253         return KErrNotReady;
       
   254         }
       
   255     CATExtPluginBase& plugin = *iCmdData.iHandler->iInstance;
       
   256     TInt retTemp = plugin.GetNextPartOfReply( iCmdData.iCmdReplyBuffer );
       
   257     if ( retTemp!=KErrNone || iCmdData.iCmdReplyBuffer.Length()<=0 )
       
   258         {
       
   259         iCmdData.iCmdReplyBuffer.Close();
       
   260         TRACE_FUNC_EXIT
       
   261         return retTemp;
       
   262         }
       
   263     retTemp = WriteReplyBufferToClient(
       
   264         iCmdData.iCmdReplyBuffer,
       
   265         EATExtGetNextPartOfReplyParamReply,
       
   266         aMessage,
       
   267         ETrue,
       
   268         EATExtGetNextPartOfReplyParamLength );
       
   269     if ( retTemp != KErrNone )
       
   270         {
       
   271         iCmdData.iCmdReplyBuffer.Close();
       
   272         TRACE_FUNC_EXIT
       
   273         return retTemp;
       
   274         }
       
   275     aMessage.Complete( KErrNone );
       
   276     iCmdData.iCmdReplyBuffer.Close();
       
   277     TRACE_FUNC_EXIT
       
   278     return KErrNone;
       
   279     }
       
   280 
       
   281 // ---------------------------------------------------------------------------
       
   282 // Completes an URC processing message by a given plugin UID. Completion code
       
   283 // for the client message is the return code from a write with
       
   284 // WriteReplyBufferToClient()
       
   285 // ---------------------------------------------------------------------------
       
   286 //
       
   287 TInt CATExtMetadata::CompleteUrcMessage( const TDesC8& aAtCmd,
       
   288                                          CATExtPluginBase* aPlugin )
       
   289     {
       
   290     TRACE_FUNC_ENTRY
       
   291     TATExtPluginEntry* foundEntry = FindInstanceFromPlugindata( aPlugin );
       
   292     if ( !foundEntry )
       
   293         {
       
   294         TRACE_FUNC_EXIT
       
   295         return KErrGeneral;
       
   296         }
       
   297     if ( !foundEntry->iUrcMessage.Handle() )
       
   298         {
       
   299         TRACE_FUNC_EXIT
       
   300         return KErrBadHandle;
       
   301         }
       
   302     TInt retVal = WriteReplyBufferToClient( aAtCmd,
       
   303                                             EATExtReceiveUrcCmdParamBuf,
       
   304                                             foundEntry->iUrcMessage );
       
   305     foundEntry->iUrcMessage.Complete( retVal );
       
   306     TRACE_FUNC_EXIT
       
   307     return retVal;
       
   308     }
       
   309 
       
   310 // ---------------------------------------------------------------------------
       
   311 // Completes an AT command handling message. Also clears internal initialized
       
   312 // command hanlder data; see ClearInitializedCmdHandlerData().
       
   313 // ---------------------------------------------------------------------------
       
   314 //
       
   315 TInt CATExtMetadata::CompleteCommandMessage( CATExtPluginBase* aPlugin,
       
   316                                              TInt aError,
       
   317                                              TBool aErrorReply,
       
   318                                              TATExtensionReplyType aReplyType,
       
   319                                              TBool aMultiPart )
       
   320     {
       
   321     TRACE_FUNC_ENTRY
       
   322     // First check if aPlugin is set (the call comes from a plugin and not from
       
   323     // ATEXT) and if it is the instance is different than the currently
       
   324     // operating one.
       
   325     if ( aPlugin && iCmdData.iHandler && iCmdData.iHandler->iInstance!=aPlugin )
       
   326         {
       
   327         TRACE_FUNC_EXIT
       
   328         return KErrInUse;
       
   329         }
       
   330     // Next check if aPlugin is set (the call comes from a plugin and not from
       
   331     // ATEXT) and a reply is not needed. In this case do nothing as it is wrong
       
   332     // behavior from the plugin (a plugin must not complete messages where no
       
   333     // reply is expected; this is done by ATEXT)
       
   334     if ( aPlugin && !iCmdData.iReplyExpected )
       
   335         {
       
   336         TRACE_FUNC_EXIT
       
   337         return KErrAlreadyExists;
       
   338         }
       
   339     if ( !iCmdData.iCmdMessage.Handle() )
       
   340         {
       
   341         TRACE_FUNC_EXIT
       
   342         return KErrBadHandle;
       
   343         }
       
   344     // Finally write the data and complete the message
       
   345     TPckg<TATExtensionReplyType> replyType( aReplyType );
       
   346     TInt writeError = iCmdData.iCmdMessage.Write( EATExtHandleCmdParamReplyType,
       
   347                                                   replyType );
       
   348     TRACE_INFO(( _L("Write returned %d"), writeError ));
       
   349     if ( aError==KErrNone && writeError==KErrNone )
       
   350         {
       
   351         if ( iCmdData.iHandler )  // Can be NULL when invoked from inside ATEXT
       
   352             {
       
   353             iCmdData.iOldHandler = iCmdData.iHandler->iInstance;
       
   354             }
       
   355         if ( !aPlugin )
       
   356             {
       
   357             CreateEmptyOrErrorBuffer( iCmdData.iCmdReplyBuffer, aErrorReply );
       
   358             }
       
   359         if ( aMultiPart )
       
   360             {
       
   361             WriteReplyBufferToClient( iCmdData.iCmdReplyBuffer,
       
   362                                       EATExtHandleCmdParamReply,
       
   363                                       iCmdData.iCmdMessage,
       
   364                                       ETrue,
       
   365                                       EATExtHandleCmdParamLength );
       
   366             }
       
   367         else
       
   368             {
       
   369             WriteReplyBufferToClient( iCmdData.iCmdReplyBuffer,
       
   370                                       EATExtHandleCmdParamReply,
       
   371                                       iCmdData.iCmdMessage );
       
   372             }
       
   373         }
       
   374     iCmdData.iCmdStarted = EFalse;
       
   375     iCmdData.iReplyExpected = EFalse;
       
   376     iCmdData.iCmdMessage.Complete( aError );
       
   377     ClearInitializedCmdHandlerData( aMultiPart );
       
   378     TRACE_FUNC_EXIT
       
   379     return KErrNone;
       
   380     }
       
   381 
       
   382 // ---------------------------------------------------------------------------
       
   383 // Clears internal initialized command handler data. This is currently used
       
   384 // only by CompleteCommandMessage() and is called when the data is not needed
       
   385 // anymore. It also prepares the internal data for a new HandleCommand() call.
       
   386 // ---------------------------------------------------------------------------
       
   387 //
       
   388 TInt CATExtMetadata::ClearInitializedCmdHandlerData( TBool aMultiPart )
       
   389     {
       
   390     TRACE_FUNC_ENTRY
       
   391     if ( iCmdData.iCmdStarted )
       
   392         {
       
   393         TRACE_FUNC_EXIT
       
   394         return KErrNotReady;
       
   395         }
       
   396     iCmdData.iCmdBuffer.Close();
       
   397     iCmdData.iCmdReplyBuffer.Close();
       
   398     if ( !aMultiPart )
       
   399         {
       
   400         iCmdData.iHandler = NULL;
       
   401         }
       
   402     TRACE_FUNC_EXIT
       
   403     return KErrNone;
       
   404     }
       
   405 
       
   406 // ---------------------------------------------------------------------------
       
   407 // Gets the array of supported commands.
       
   408 // ---------------------------------------------------------------------------
       
   409 //
       
   410 TInt CATExtMetadata::GetSupportedCommands( CATExtPluginBase* aPlugin,
       
   411                                            RPointerArray<HBufC8>& aCmds )
       
   412     {
       
   413     TRACE_FUNC_ENTRY
       
   414     if ( !iSupport || !iSupportAux )
       
   415         {
       
   416         TRACE_FUNC_EXIT
       
   417         return KErrGeneral;
       
   418         }
       
   419     TATExtPluginEntry* foundEntry = FindInstanceFromPlugindata( aPlugin );
       
   420     if ( !foundEntry )
       
   421         {
       
   422         TRACE_FUNC_EXIT
       
   423         return KErrGeneral;
       
   424         }
       
   425     // Next create the array of supported commands
       
   426     TInt retVal = KErrNone;
       
   427     TBool firstSearch = ETrue;
       
   428     TInt supportFind = KErrNotFound;
       
   429     TBool findInAux = EFalse;
       
   430     for ( ;; )
       
   431         {
       
   432         HBufC8* foundCmd = GetNextSupportedCommand( firstSearch,
       
   433                                                     supportFind,
       
   434                                                     findInAux );
       
   435         if ( !foundCmd )
       
   436             {
       
   437             break;
       
   438             }
       
   439         retVal = aCmds.Append( foundCmd );
       
   440         if ( retVal != KErrNone )
       
   441             {
       
   442             break;
       
   443             }
       
   444         }
       
   445     TRACE_FUNC_EXIT
       
   446     return retVal;
       
   447     }
       
   448 
       
   449 // ---------------------------------------------------------------------------
       
   450 // Starts URC message receiving for plugin. Note that
       
   451 // MarkUrcHandlingOwnership() must be called immediately after this in order
       
   452 // for the messages to receive their destination.
       
   453 // ---------------------------------------------------------------------------
       
   454 //
       
   455 void CATExtMetadata::StartUrcReceivingL( const RMessage2& aMessage,
       
   456                                          TUid& aPluginUid )
       
   457     {
       
   458     TRACE_FUNC_ENTRY
       
   459     TATExtPluginEntry* foundEntry = FindUrcProcessingPlugin( aPluginUid );
       
   460     if ( !foundEntry )
       
   461         {
       
   462         TRACE_FUNC_EXIT
       
   463         User::Leave( KErrNotFound );
       
   464         }
       
   465     // Note: Let locked plugin pass here
       
   466     InstantiatePluginL( *foundEntry );
       
   467     foundEntry->iUrcMessage = aMessage;
       
   468     foundEntry->iInstance->ReceiveUnsolicitedResult();
       
   469     foundEntry->iUrcStarted = ETrue;
       
   470     TRACE_FUNC_EXIT
       
   471     }
       
   472 
       
   473 // ---------------------------------------------------------------------------
       
   474 // Cancels an active URC message receiving operation by a given plugin UID.
       
   475 // Uses CancelOneUrcOperation() to cancel if plugin UID found from plugin
       
   476 // data.
       
   477 // ---------------------------------------------------------------------------
       
   478 //
       
   479 TInt CATExtMetadata::CancelUrcReceiving( TUid& aPluginUid )
       
   480     {
       
   481     TRACE_FUNC_ENTRY
       
   482     TInt foundIndex = KErrNotFound;
       
   483     TATExtPluginEntry* foundEntry = FindUidFromPlugindata( aPluginUid,
       
   484                                                            foundIndex );
       
   485     if ( !foundEntry )
       
   486         {
       
   487         TRACE_FUNC_EXIT
       
   488         return KErrNotFound;
       
   489         }
       
   490     CancelOneUrcOperation( *foundEntry, KErrCancel, ETrue );
       
   491     TRACE_FUNC_EXIT
       
   492     return KErrNone;
       
   493     }
       
   494 
       
   495 // ---------------------------------------------------------------------------
       
   496 // Marks URC handling ownership for a plugin entry. Call to this function must
       
   497 // be done immediately after the call to StartUrcReceivingL().
       
   498 // ---------------------------------------------------------------------------
       
   499 //
       
   500 TInt CATExtMetadata::MarkUrcHandlingOwnership( const RMessage2& aMessage )
       
   501     {
       
   502     TRACE_FUNC_ENTRY
       
   503     if ( !iPluginData )
       
   504         {
       
   505         TRACE_FUNC_EXIT
       
   506         return KErrGeneral;
       
   507         }
       
   508     TInt i = 0;
       
   509     TInt count = iPluginData->Count();
       
   510     for ( i=0; i<count; i++ )
       
   511         {
       
   512         TATExtPluginEntry& entry = (*iPluginData)[i];
       
   513         if ( entry.iUrcStarted && !entry.iUrcOwned )
       
   514             {
       
   515             TPckg<TUid> pluginUid( entry.iPluginUid );
       
   516             TInt retTemp = aMessage.Write( EATExtMarkUrcHandlingOwnershipParamUid,
       
   517                                            pluginUid );
       
   518             TRACE_INFO(( _L("Write returned %d"), retTemp ));
       
   519             entry.iUrcOwned = ETrue;
       
   520             TRACE_FUNC_EXIT
       
   521             return KErrNone;
       
   522             }
       
   523         }
       
   524     TRACE_FUNC_EXIT
       
   525     return KErrNotFound;
       
   526     }
       
   527 
       
   528 // ---------------------------------------------------------------------------
       
   529 // Marks the access to a plugin data as "locked". This blocks all operations
       
   530 // where plugin function calls are to be done.
       
   531 // ---------------------------------------------------------------------------
       
   532 //
       
   533 TInt CATExtMetadata::LockPluginAccess( TUid& aPluginUid )
       
   534     {
       
   535     TRACE_FUNC_ENTRY
       
   536     TInt foundIndex = KErrNotFound;
       
   537     TATExtPluginEntry* foundEntry = FindUidFromPlugindata( aPluginUid,
       
   538                                                            foundIndex );
       
   539     if ( !foundEntry )
       
   540         {
       
   541         TRACE_FUNC_EXIT
       
   542         return KErrNotFound;
       
   543         }
       
   544     if ( foundEntry == iCmdData.iHandler )
       
   545         {
       
   546         CancelCommandOperation( KErrCancel );
       
   547         }
       
   548     CancelOneUrcOperation( *foundEntry, KErrCancel );
       
   549     foundEntry->iLocked = ETrue;
       
   550     TRACE_FUNC_EXIT
       
   551     return KErrNone;
       
   552     }
       
   553 
       
   554 // ---------------------------------------------------------------------------
       
   555 // Marks the access to a plugin data as "unlocked". This enables all
       
   556 // operations where plugin function call are to be done.
       
   557 // ---------------------------------------------------------------------------
       
   558 //
       
   559 TInt CATExtMetadata::UnlockPluginAccess( TUid& aPluginUid )
       
   560     {
       
   561     TRACE_FUNC_ENTRY
       
   562     TInt foundIndex = KErrNotFound;
       
   563     TATExtPluginEntry* foundEntry = FindUidFromPlugindata( aPluginUid,
       
   564                                                            foundIndex );
       
   565     if ( !foundEntry )
       
   566         {
       
   567         TRACE_FUNC_EXIT
       
   568         return KErrNotFound;
       
   569         }
       
   570     foundEntry->iLocked = EFalse;
       
   571     TRACE_FUNC_EXIT
       
   572     return KErrNone;
       
   573     }
       
   574 
       
   575 // ---------------------------------------------------------------------------
       
   576 // Searches for an instances from the support data's plugin data link and only
       
   577 // marks the instance as uninitialized. Note that this doesn't try to cancel
       
   578 // any of the current plugin operations and should be used only when a plugin
       
   579 // destroys itself.
       
   580 // ---------------------------------------------------------------------------
       
   581 //
       
   582 TInt CATExtMetadata::RemoveImplementationInstance( CATExtPluginBase* aInstance )
       
   583     {
       
   584     TRACE_FUNC_ENTRY
       
   585     if ( !aInstance )
       
   586         {
       
   587         TRACE_FUNC_EXIT
       
   588         return KErrGeneral;
       
   589         }
       
   590     TATExtPluginEntry* foundEntry = FindInstanceFromPlugindata( aInstance );
       
   591     if ( !foundEntry )
       
   592         {
       
   593         TRACE_FUNC_EXIT
       
   594         return KErrNotFound;
       
   595         }
       
   596     TInt retVal = RemoveImplementation( foundEntry->iPluginUid, EFalse );
       
   597     TRACE_FUNC_EXIT
       
   598     return retVal;
       
   599     }
       
   600 
       
   601 // ---------------------------------------------------------------------------
       
   602 // Checks if support data has been constructed from the plugin data.
       
   603 // ---------------------------------------------------------------------------
       
   604 //
       
   605 TBool CATExtMetadata::SupportExists()
       
   606     {
       
   607     TRACE_FUNC_ENTRY
       
   608     if ( (iSupport&&iSupport->Count()>0) ||
       
   609          (iSupportAux&&iSupportAux->Count()>0) )
       
   610         {
       
   611         TRACE_FUNC_EXIT
       
   612         return ETrue;
       
   613         }
       
   614     TRACE_FUNC_EXIT
       
   615     return EFalse;
       
   616     }
       
   617 
       
   618 // ---------------------------------------------------------------------------
       
   619 // Number of plugins with AT command handling support based on the information
       
   620 // in RSS files' AT command handling entries. This information is needed to
       
   621 // instantiate one or more listeners by the user of the client.
       
   622 // ---------------------------------------------------------------------------
       
   623 //
       
   624 TInt CATExtMetadata::NumberOfPlugins()
       
   625     {
       
   626     TRACE_FUNC_ENTRY
       
   627     if ( !iPluginData )
       
   628         {
       
   629         TRACE_FUNC_EXIT
       
   630         return KErrGeneral;
       
   631         }
       
   632     TInt pluginCount = iPluginData->Count();
       
   633     TRACE_FUNC_EXIT
       
   634     return pluginCount;
       
   635     }
       
   636 
       
   637 // ---------------------------------------------------------------------------
       
   638 // Sets the quiet mode to the required value. After this the mode is reported
       
   639 // to the plugins with ReportQuietModeChange().
       
   640 // ---------------------------------------------------------------------------
       
   641 //
       
   642 void CATExtMetadata::SetQuietMode( TBool aMode )
       
   643     {
       
   644     TRACE_FUNC_ENTRY
       
   645     iQuietMode = aMode;
       
   646     if ( iPluginData )
       
   647         {
       
   648         TInt i;
       
   649         TInt count = iPluginData->Count();
       
   650         for ( i=0; i<count; i++ )
       
   651             {
       
   652             TATExtPluginEntry& entry = (*iPluginData)[i];
       
   653             if ( entry.iLocked )
       
   654                 {
       
   655                 continue;
       
   656                 }
       
   657             TInt retTemp = InstantiatePlugin( entry );
       
   658             if ( retTemp != KErrNone )
       
   659                 {
       
   660                 continue;
       
   661                 }
       
   662             // Note: here two reports will be made if the plugin was not
       
   663             // instantiated but as the operatio is fast no new parameter will be
       
   664             // done to InstantiatePlugin() for instantiation reporting.
       
   665             entry.iInstance->ReportQuietModeChange( aMode );
       
   666             }
       
   667         }
       
   668     TRACE_FUNC_EXIT
       
   669     }
       
   670 
       
   671 // ---------------------------------------------------------------------------
       
   672 // Sets the verbose mode to the required value. After this the mode is
       
   673 // reported to the plugins with ReportVerboseModeChange().
       
   674 // ---------------------------------------------------------------------------
       
   675 //
       
   676 void CATExtMetadata::SetVerboseMode( TBool aMode )
       
   677     {
       
   678     TRACE_FUNC_ENTRY
       
   679     iVerboseMode = aMode;
       
   680     if ( iPluginData )
       
   681         {
       
   682         TInt i;
       
   683         TInt count = iPluginData->Count();
       
   684         for ( i=0; i<count; i++ )
       
   685             {
       
   686             TATExtPluginEntry& entry = (*iPluginData)[i];
       
   687             if ( entry.iLocked )
       
   688                 {
       
   689                 continue;
       
   690                 }
       
   691             TInt retTemp = InstantiatePlugin( entry );
       
   692             if ( retTemp != KErrNone )
       
   693                 {
       
   694                 continue;
       
   695                 }
       
   696             // Note: here two reports will be made if the plugin was not
       
   697             // instantiated but as the operatio is fast no new parameter will be
       
   698             // done to InstantiatePlugin() for instantiation reporting.
       
   699             entry.iInstance->ReportVerboseModeChange( aMode );
       
   700             }
       
   701         }
       
   702     TRACE_FUNC_EXIT
       
   703     }
       
   704 
       
   705 // ---------------------------------------------------------------------------
       
   706 // Sets new character value for a carriage return, line feed or backspace
       
   707 // character. After this its type and value are report to the plugins with
       
   708 // ReportCharacterChange().
       
   709 // ---------------------------------------------------------------------------
       
   710 //
       
   711 TInt CATExtMetadata::SetCharacterValue( TATExtensionCharType aCharType,
       
   712                                         TInt8 aNewChar )
       
   713     {
       
   714     TRACE_FUNC_ENTRY
       
   715     // First pick up the needed information for ATEXT
       
   716     TInt retVal = KErrNone;
       
   717     switch ( aCharType )
       
   718         {
       
   719         case ECharTypeCarriage:
       
   720             iCarriageReturn = aNewChar;
       
   721             break;
       
   722         case ECharTypeLineFeed:
       
   723             iLineFeed = aNewChar;
       
   724             break;
       
   725         case ECharTypeBackspace:
       
   726             iBackspace = aNewChar;
       
   727             break;
       
   728         default:
       
   729             retVal = KErrNotSupported;
       
   730             break;
       
   731         }
       
   732     if ( retVal==KErrNone && iPluginData )
       
   733         {
       
   734         // Next notify about character change
       
   735         TInt i;
       
   736         TInt count = iPluginData->Count();
       
   737         for ( i=0; i<count; i++ )
       
   738             {
       
   739             TATExtPluginEntry& entry = (*iPluginData)[i];
       
   740             if ( entry.iLocked )
       
   741                 {
       
   742                 continue;
       
   743                 }
       
   744             TInt retTemp = InstantiatePlugin( entry );
       
   745             if ( retTemp != KErrNone )
       
   746                 {
       
   747                 continue;
       
   748                 }
       
   749             // Note: here two reports will be made if the plugin was not
       
   750             // instantiated but as the operatio is fast no new parameter will be
       
   751             // done to InstantiatePlugin() for instantiation reporting.
       
   752             entry.iInstance->ReportCharacterChange( aCharType, aNewChar );
       
   753             }
       
   754         }
       
   755     TRACE_FUNC_EXIT
       
   756     return retVal;
       
   757     }
       
   758 
       
   759 // ---------------------------------------------------------------------------
       
   760 // Extracts the NVRAM settings from a pipe-character delimited NVRAM buffer
       
   761 // and sends the subsettings to all of the plugins with
       
   762 // ReportNvramStatusChange().
       
   763 // ---------------------------------------------------------------------------
       
   764 //
       
   765 TInt CATExtMetadata::BroadcastNvramStatusChange( const TDesC8& aNvram )
       
   766     {
       
   767     TRACE_FUNC_ENTRY
       
   768     if ( !iPluginData )
       
   769         {
       
   770         TRACE_FUNC_EXIT
       
   771         return KErrGeneral;
       
   772         }
       
   773     HBufC8* nvramEntry = NULL;
       
   774     TRAP_IGNORE( nvramEntry=HBufC8::NewMaxL(aNvram.Length()) );
       
   775     if ( !nvramEntry )
       
   776         {
       
   777         TRACE_FUNC_EXIT
       
   778         return KErrGeneral;
       
   779         }
       
   780     TInt i;
       
   781     TInt retVal = KErrNotFound;
       
   782     TInt count = iPluginData->Count();
       
   783     TPtr8 nvramEntryPtr = nvramEntry->Des();
       
   784     TInt startIndex = 0;   // Start of found subsetting
       
   785     TInt endIndex = 0;     // End of found subsetting
       
   786     while ( ExtractNextNvramSetting(aNvram,startIndex,endIndex)  )
       
   787         {
       
   788         // Report the subsetting to every plugin (and instantiate as every delta
       
   789         // change has to be signalled to every plugin).
       
   790         nvramEntryPtr.Copy( &aNvram[startIndex], endIndex-startIndex );
       
   791         for ( i=0; i<count; i++ )
       
   792             {
       
   793             TATExtPluginEntry& entry = (*iPluginData)[i];
       
   794             if ( entry.iLocked )
       
   795                 {
       
   796                 continue;
       
   797                 }
       
   798             TInt retTemp = InstantiatePlugin( entry );
       
   799             if ( retTemp != KErrNone )
       
   800                 {
       
   801                 continue;
       
   802                 }
       
   803             entry.iInstance->ReportNvramStatusChange( nvramEntryPtr );
       
   804             retVal = KErrNone;
       
   805             }
       
   806         }
       
   807     delete nvramEntry;
       
   808     TRACE_FUNC_EXIT
       
   809     return retVal;
       
   810     }
       
   811 
       
   812 // ---------------------------------------------------------------------------
       
   813 // Reports about external handle command error condition.
       
   814 // This is for cases when for example DUN decided the reply contained an
       
   815 // error condition but the plugin is still handling the command internally.
       
   816 // Example: "AT+TEST;+TEST2" was given in command line; "AT+TEST" returns
       
   817 // non-EReplyTypeError condition and "AT+TEST2" returns EReplyTypeError.
       
   818 // As the plugin(s) returning the non-EReplyTypeError may still have some
       
   819 // ongoing operation then these plugins are notified about the external
       
   820 // EReplyTypeError in command line processing. It is to be noted that
       
   821 // HandleCommandCancel() is not sufficient to stop the processing as the
       
   822 // command handling has already finished.
       
   823 // ---------------------------------------------------------------------------
       
   824 //
       
   825 TInt CATExtMetadata::ReportExternalHandleCommandError()
       
   826     {
       
   827     TRACE_FUNC_ENTRY
       
   828     if ( !iCmdData.iOldHandler )
       
   829         {
       
   830         TRACE_FUNC_EXIT
       
   831         return KErrNotFound;
       
   832         }
       
   833     iCmdData.iOldHandler->ReportExternalHandleCommandError();
       
   834     TRACE_FUNC_EXIT
       
   835     return KErrNone;
       
   836     }
       
   837 
       
   838 // ---------------------------------------------------------------------------
       
   839 // Reports about abort condition in command handling.
       
   840 // This is for cases when for example DUN decided an abort condition was
       
   841 // received from DTE (ITU-T V.250 5.6.1). This API is for notifying the
       
   842 // plugin that abort was requested. However the plugin currently handling
       
   843 // the command may ignore the request if it doesn't support abort for the
       
   844 // command or it may return the changed condition with
       
   845 // HandleCommandCompleted()
       
   846 // ---------------------------------------------------------------------------
       
   847 //
       
   848 TInt CATExtMetadata::ReportHandleCommandAbort( const RMessage2& aMessage )
       
   849     {
       
   850     TRACE_FUNC_ENTRY
       
   851     if ( !iCmdData.iHandler || !iCmdData.iHandler->iInstance )
       
   852         {
       
   853         TRACE_FUNC_EXIT
       
   854         return KErrNotReady;
       
   855         }
       
   856     // Uncomment the following line for abort API
       
   857 //    CATExtPluginBase& plugin = *iCmdData.iHandler->iInstance;
       
   858     // Remove the following line for abort API
       
   859     TInt retTemp = KErrNone;
       
   860     TBool stop = EFalse;
       
   861     // Uncomment the following line for abort API
       
   862 //    TInt retTemp = plugin.ReportHandleCommandAbort( stop );
       
   863     if ( retTemp != KErrNone )
       
   864         {
       
   865         TRACE_FUNC_EXIT
       
   866         return retTemp;
       
   867         }
       
   868     TPckg<TBool> stopPckg( stop );
       
   869     TInt retVal = aMessage.Write( EATExtReportHandleCommandAbortParamStop,
       
   870                                   stopPckg );
       
   871     TRACE_INFO(( _L("Write returned %d"), retVal ));
       
   872     TRACE_FUNC_EXIT
       
   873     return retVal;
       
   874     }
       
   875 
       
   876 // ---------------------------------------------------------------------------
       
   877 // Extracts the NVRAM settings from a pipe-character delimited NVRAM buffer
       
   878 // and sends the subsettings to all of the plugins with
       
   879 // ReportNvramStatusChange().
       
   880 // ---------------------------------------------------------------------------
       
   881 //
       
   882 TInt CATExtMetadata::GetNextSpecialCommand( const RMessage2& aMessage,
       
   883                                             TBool aFirstSearch )
       
   884     {
       
   885     TRACE_FUNC_ENTRY
       
   886     if ( !iSupportAux )
       
   887         {
       
   888         TRACE_FUNC_EXIT
       
   889         return KErrGeneral;
       
   890         }
       
   891     // If first search then start from index 0, othewise start from the
       
   892     // next index
       
   893     if ( aFirstSearch )
       
   894         {
       
   895         iSupportAuxFind = -1;
       
   896         }
       
   897     iSupportAuxFind++;
       
   898     TInt i;
       
   899     TInt count = iSupportAux->Count();
       
   900     TATExtAtCmdSupport* support = NULL;
       
   901     for ( i=iSupportAuxFind; i<count; i++ )
       
   902         {
       
   903         support = &(*iSupportAux)[i];
       
   904         if ( support->iEntries )
       
   905             {
       
   906             break;
       
   907             }
       
   908         }
       
   909     if ( i >= count )
       
   910         {
       
   911         TRACE_FUNC_EXIT
       
   912         return KErrNotFound;
       
   913         }
       
   914     TInt retTemp = WriteReplyBufferToClient( *support->iAtCmdBase,
       
   915                                              EATExtGetNextSpecialCmdParamCmd,
       
   916                                              aMessage );
       
   917     TRACE_INFO(( _L("First write returned %d"), retTemp ));
       
   918     TPckg<TBool> firstSearch( EFalse );
       
   919     retTemp = aMessage.Write( EATExtGetNextSpecialCmdParamFirst, firstSearch );
       
   920     TRACE_INFO(( _L("Second write returned %d"), retTemp ));
       
   921     TRACE_FUNC_EXIT
       
   922     return KErrNone;
       
   923     }
       
   924 
       
   925 // ---------------------------------------------------------------------------
       
   926 // CATExtMetadata::CATExtMetadata
       
   927 // ---------------------------------------------------------------------------
       
   928 //
       
   929 CATExtMetadata::CATExtMetadata( REComSession& aEComSession,
       
   930                                 CATExtListen* aListener,
       
   931                                 MATExtPluginObserver& aObserver ) :
       
   932     iEComSession( aEComSession ),
       
   933     iListener( aListener ),
       
   934     iObserver( aObserver )
       
   935     {
       
   936     Initialize();
       
   937     }
       
   938 
       
   939 // ---------------------------------------------------------------------------
       
   940 // CATExtMetadata::ConstructL
       
   941 // ---------------------------------------------------------------------------
       
   942 //
       
   943 void CATExtMetadata::ConstructL()
       
   944     {
       
   945     if ( !iListener )
       
   946         {
       
   947         User::Leave( KErrGeneral );
       
   948         }
       
   949     }
       
   950 
       
   951 // ---------------------------------------------------------------------------
       
   952 // Initializes this class
       
   953 // ---------------------------------------------------------------------------
       
   954 //
       
   955 void CATExtMetadata::Initialize()
       
   956     {
       
   957     // Don't initialize iListener here (it is set through NewL)
       
   958     // Don't initialize iCallback here (it is set through NewL)
       
   959     iIfUid = TUid::Null();
       
   960     iSupport = NULL;
       
   961     iSupportAux = NULL;
       
   962     iPluginData = NULL;
       
   963     iCmdData.iCmdStarted = EFalse;
       
   964     iCmdData.iReplyExpected = EFalse;
       
   965     iCmdData.iHandler = NULL;
       
   966     iCmdData.iOldHandler = NULL;
       
   967     iCarriageReturn = KDefaultCarriageReturn;
       
   968     iLineFeed = KDefaultLineFeed;
       
   969     iQuietMode = EFalse;
       
   970     iVerboseMode = ETrue;
       
   971     iSupportAuxFind = 0;
       
   972     iShutdown = EFalse;
       
   973     }
       
   974 
       
   975 // ---------------------------------------------------------------------------
       
   976 // Removes one plugin data entry by plugin UID
       
   977 // ---------------------------------------------------------------------------
       
   978 //
       
   979 TInt CATExtMetadata::RemoveOnePlugindata( TUid& aPluginUid,
       
   980                                           TBool aInstanceExists )
       
   981     {
       
   982     TRACE_FUNC_ENTRY
       
   983     TInt foundIndex = KErrNotFound;
       
   984     TATExtPluginEntry* foundEntry = FindUidFromPlugindata( aPluginUid,
       
   985                                                            foundIndex );
       
   986     if ( !foundEntry )
       
   987         {
       
   988         TRACE_FUNC_EXIT
       
   989         return KErrNotFound;
       
   990         }
       
   991     if ( !aInstanceExists )
       
   992         {
       
   993         foundEntry->iInstance = NULL;
       
   994         }
       
   995     if ( foundEntry == iCmdData.iHandler )
       
   996         {
       
   997         CancelCommandOperation( KErrCompletion );
       
   998         }
       
   999     CancelOneUrcOperation( *foundEntry, KErrCompletion );
       
  1000     delete foundEntry->iInstance;
       
  1001     foundEntry->iInstance = NULL;
       
  1002     iPluginData->Delete( foundIndex );
       
  1003     iPluginData->Compress();
       
  1004     UpdateRemovedPluginLinks( iSupport, foundIndex );
       
  1005     UpdateRemovedPluginLinks( iSupportAux, foundIndex );
       
  1006     TRACE_FUNC_EXIT
       
  1007     return KErrNone;
       
  1008     }
       
  1009 
       
  1010 // ---------------------------------------------------------------------------
       
  1011 // Updates removed plugin links
       
  1012 // ---------------------------------------------------------------------------
       
  1013 //
       
  1014 TInt CATExtMetadata::UpdateRemovedPluginLinks(
       
  1015     CArrayFixFlat<TATExtAtCmdSupport>* aSupport,
       
  1016     TInt aRemovedIndex )
       
  1017     {
       
  1018     TRACE_FUNC_ENTRY
       
  1019     if ( !aSupport )
       
  1020         {
       
  1021         TRACE_FUNC_EXIT
       
  1022         return KErrGeneral;
       
  1023         }
       
  1024     TInt i;
       
  1025     TInt j;
       
  1026     TInt supportCount = aSupport->Count();
       
  1027     for ( i=0; i<supportCount; i++ )
       
  1028         {
       
  1029         TATExtAtCmdSupport& support = (*aSupport)[i];
       
  1030         if ( !support.iEntries )
       
  1031             {
       
  1032             continue;
       
  1033             }
       
  1034         TInt entryCount = support.iEntries->Count();
       
  1035         for ( j=entryCount-1; j>=0; j-- )
       
  1036             {
       
  1037             TATExtOneCmdSupport& oneCmdSupport = (*support.iEntries)[j];
       
  1038             TInt entryIndex = oneCmdSupport.iEntryIndex;
       
  1039             if ( entryIndex > aRemovedIndex )
       
  1040                 {
       
  1041                 oneCmdSupport.iEntryIndex--;
       
  1042                 }
       
  1043             else if ( entryIndex == aRemovedIndex )
       
  1044                 {
       
  1045                 support.iEntries->Delete( j );
       
  1046                 }
       
  1047             }
       
  1048         }
       
  1049     TRACE_FUNC_EXIT
       
  1050     return KErrNone;
       
  1051     }
       
  1052 
       
  1053 // ---------------------------------------------------------------------------
       
  1054 // Completes command data
       
  1055 // ---------------------------------------------------------------------------
       
  1056 //
       
  1057 TInt CATExtMetadata::CompleteCommandData()
       
  1058     {
       
  1059     TRACE_FUNC_ENTRY
       
  1060     CompleteCommandMessage( NULL,
       
  1061                             KErrCompletion,
       
  1062                             EFalse,
       
  1063                             EReplyTypeUndefined,
       
  1064                             EFalse );
       
  1065     // It is possible that CompleteCommandMessage() didn't complete but there
       
  1066     // is still data set to non-null values. Force setting now.
       
  1067     iCmdData.iCmdStarted = EFalse;
       
  1068     iCmdData.iReplyExpected = EFalse;
       
  1069     iCmdData.iCmdBuffer.Close();
       
  1070     iCmdData.iCmdReplyBuffer.Close();
       
  1071     iCmdData.iHandler = NULL;
       
  1072     TRACE_FUNC_EXIT
       
  1073     return KErrNone;
       
  1074     }
       
  1075 
       
  1076 // ---------------------------------------------------------------------------
       
  1077 // Adds AT commands set to metadata. Used by function AddImplementationL().
       
  1078 // ---------------------------------------------------------------------------
       
  1079 //
       
  1080 void CATExtMetadata::DoAddImplementationL(
       
  1081     CImplementationInformation* aImplInfo,
       
  1082     const TDesC8& aAtCmdSet )
       
  1083     {
       
  1084     TRACE_FUNC_ENTRY
       
  1085     if ( !aImplInfo || !iPluginData || !iSupport || !iSupportAux )
       
  1086         {
       
  1087         TRACE_FUNC_EXIT
       
  1088         User::Leave( KErrGeneral );
       
  1089         }
       
  1090     TATExtSupportType type = ESupportTypeUndefined;
       
  1091     TInt start = 0;  // Start of found subcommand
       
  1092     TInt end = 0;    // End of found subcommand
       
  1093     HBufC8* parsedCmd = HBufC8::NewMaxLC( aAtCmdSet.Length() );
       
  1094     TPtr8 parsedCmdPtr = parsedCmd->Des();
       
  1095     while ( ExtractNextCommand(aAtCmdSet,start,end,type) == KErrNone )
       
  1096         {
       
  1097         if ( type == ESupportTypeUndefined )
       
  1098             {
       
  1099             continue;
       
  1100             }
       
  1101         parsedCmdPtr.Copy( &aAtCmdSet[start], end-start );
       
  1102         TUid pluginUid = aImplInfo->ImplementationUid();
       
  1103         TATExtCleanupInfo cleanupInfo;
       
  1104         TRAPD( retTrap, AddEntryToMetadataL(parsedCmdPtr,pluginUid,type,
       
  1105                                             cleanupInfo) );
       
  1106         if ( retTrap != KErrNone )
       
  1107             {
       
  1108             CleanPartialMetadata( cleanupInfo );
       
  1109             TRACE_FUNC_EXIT
       
  1110             User::Leave( retTrap );
       
  1111             }
       
  1112         TInt retTemp = iListener->AddPluginUid( pluginUid );
       
  1113         if ( retTemp != KErrNone )
       
  1114             {
       
  1115             TRACE_FUNC_EXIT
       
  1116             User::Leave( retTemp );
       
  1117             }
       
  1118         }
       
  1119     CleanupStack::PopAndDestroy( parsedCmd );
       
  1120     TRACE_FUNC_EXIT
       
  1121     }
       
  1122 
       
  1123 // ---------------------------------------------------------------------------
       
  1124 // Removes an implementation from the support data by a given plugin UID.
       
  1125 // Used by function RemoveImplementation().
       
  1126 // ---------------------------------------------------------------------------
       
  1127 //
       
  1128 TInt CATExtMetadata::DoRemoveImplementation(
       
  1129     TUid& aPluginUid,
       
  1130     CArrayFixFlat<TATExtAtCmdSupport>* aSupport )
       
  1131     {
       
  1132     TRACE_FUNC_ENTRY
       
  1133     if ( !aSupport )
       
  1134         {
       
  1135         TRACE_FUNC_EXIT
       
  1136         return KErrGeneral;
       
  1137         }
       
  1138     // 1. Find the UID from plugindata.
       
  1139     TInt foundIndex = KErrNotFound;
       
  1140     TATExtPluginEntry* foundEntry = FindUidFromPlugindata( aPluginUid,
       
  1141                                                            foundIndex );
       
  1142     if ( !foundEntry )
       
  1143         {
       
  1144         TRACE_FUNC_EXIT
       
  1145         return KErrNotFound;
       
  1146         }
       
  1147     // 2. Delete the entries from metadata which point to the found entry.
       
  1148     TInt i;
       
  1149     TInt j;
       
  1150     TInt supportCount = aSupport->Count();
       
  1151     for ( i=supportCount-1; i>=0; i-- )
       
  1152         {
       
  1153         TATExtAtCmdSupport& support = (*aSupport)[i];
       
  1154         if ( !support.iEntries )
       
  1155             {
       
  1156             continue;
       
  1157             }
       
  1158         TInt entryCount = support.iEntries->Count();
       
  1159         for ( j=entryCount-1; j>=0; j-- )
       
  1160             {
       
  1161             TInt entryIndex = (*support.iEntries)[j].iEntryIndex;
       
  1162             if ( &(*iPluginData)[entryIndex] == foundEntry )
       
  1163                 {
       
  1164                 support.iEntries->Delete( j );
       
  1165                 }
       
  1166             }
       
  1167         support.iEntries->Compress();
       
  1168         // 3. Remove the entries from metadata with zero length.
       
  1169         if ( support.iEntries->Count() == 0 )
       
  1170             {
       
  1171             aSupport->Delete( i );
       
  1172             }
       
  1173         }
       
  1174     aSupport->Compress();
       
  1175     TRACE_FUNC_EXIT
       
  1176     return KErrNone;
       
  1177     }
       
  1178 
       
  1179 // ---------------------------------------------------------------------------
       
  1180 // Checks whether AT command handling is active or not
       
  1181 // ---------------------------------------------------------------------------
       
  1182 //
       
  1183 TBool CATExtMetadata::IsCommandHandling()
       
  1184     {
       
  1185     TRACE_FUNC_ENTRY
       
  1186     if ( iCmdData.iCmdStarted ||
       
  1187         (iCmdData.iCmdMessage.Handle() && iCmdData.iCmdBuffer.Length()>0) ||
       
  1188         iCmdData.iCmdReplyBuffer.Length()>0 )
       
  1189         {
       
  1190         TRACE_FUNC_EXIT
       
  1191         return ETrue;
       
  1192         }
       
  1193     TRACE_FUNC_EXIT
       
  1194     return EFalse;
       
  1195     }
       
  1196 
       
  1197 // ---------------------------------------------------------------------------
       
  1198 // Destroys data related to plugins
       
  1199 // ---------------------------------------------------------------------------
       
  1200 //
       
  1201 TInt CATExtMetadata::DestroyPlugindata()
       
  1202     {
       
  1203     TRACE_FUNC_ENTRY
       
  1204     if ( !iPluginData )
       
  1205         {
       
  1206         TRACE_FUNC_EXIT
       
  1207         return KErrGeneral;
       
  1208         }
       
  1209     CancelCommandOperation( KErrServerTerminated );
       
  1210     // First cancel the plugindata operations before delete
       
  1211     TInt i;
       
  1212     TInt pluginCount = iPluginData->Count();
       
  1213     for ( i=0; i<pluginCount; i++ )
       
  1214         {
       
  1215         TATExtPluginEntry& entry = (*iPluginData)[i];
       
  1216         CancelOneUrcOperation( entry, KErrServerTerminated );
       
  1217         }
       
  1218     // Next delete the actual data
       
  1219     for ( i=0; i<pluginCount; i++ )
       
  1220         {
       
  1221         TATExtPluginEntry& entry = (*iPluginData)[i];
       
  1222         delete entry.iInstance;
       
  1223         entry.iInstance = NULL;
       
  1224         }
       
  1225     iPluginData->Reset();
       
  1226     delete iPluginData;
       
  1227     iPluginData = NULL;
       
  1228     iCmdData.iHandler = NULL;
       
  1229     iCmdData.iOldHandler = NULL;
       
  1230     TRACE_FUNC_EXIT
       
  1231     return KErrNone;
       
  1232     }
       
  1233 
       
  1234 // ---------------------------------------------------------------------------
       
  1235 // Cancels an active AT command handling operation by reinitializing internal
       
  1236 // data, completing the client request message and calling the plugin's
       
  1237 // HandleCommandCancel().
       
  1238 // ---------------------------------------------------------------------------
       
  1239 //
       
  1240 TInt CATExtMetadata::CancelCommandOperation( TInt aError, TBool aCheckLock )
       
  1241     {
       
  1242     TRACE_FUNC_ENTRY
       
  1243     if ( aCheckLock && iCmdData.iHandler && iCmdData.iHandler->iLocked )
       
  1244         {
       
  1245         TRACE_FUNC_EXIT
       
  1246         return KErrAccessDenied;
       
  1247         }
       
  1248     if ( iCmdData.iHandler && iCmdData.iHandler->iInstance )
       
  1249         {
       
  1250         iCmdData.iHandler->iInstance->HandleCommandCancel();
       
  1251         }
       
  1252     CompleteCommandMessage( NULL,
       
  1253                             aError,
       
  1254                             EFalse,
       
  1255                             EReplyTypeUndefined,
       
  1256                             EFalse );
       
  1257     TRACE_FUNC_EXIT
       
  1258     return KErrNone;
       
  1259     }
       
  1260 
       
  1261 // ---------------------------------------------------------------------------
       
  1262 // Cancels an active URC message receiving operation by a given plugin entry,
       
  1263 // completing the client request message and calling the plugin's
       
  1264 // ReceiveUnsolicitedResultCancel().
       
  1265 // ---------------------------------------------------------------------------
       
  1266 //
       
  1267 TInt CATExtMetadata::CancelOneUrcOperation( TATExtPluginEntry& aPluginEntry,
       
  1268                                             TInt aError,
       
  1269                                             TBool aCheckLock )
       
  1270     {
       
  1271     TRACE_FUNC_ENTRY
       
  1272     if ( aCheckLock && aPluginEntry.iLocked )
       
  1273         {
       
  1274         TRACE_FUNC_EXIT
       
  1275         return KErrAccessDenied;
       
  1276         }
       
  1277     aPluginEntry.iUrcStarted = EFalse;
       
  1278     if ( aPluginEntry.iInstance )
       
  1279         {
       
  1280         aPluginEntry.iInstance->ReceiveUnsolicitedResultCancel();
       
  1281         }
       
  1282     if ( aPluginEntry.iUrcMessage.Handle() )
       
  1283         {
       
  1284         aPluginEntry.iUrcMessage.Complete( aError );
       
  1285         }
       
  1286     // Note: Don't touch the iUrcOwned here
       
  1287     TRACE_FUNC_EXIT
       
  1288     return KErrNone;
       
  1289     }
       
  1290 
       
  1291 // ---------------------------------------------------------------------------
       
  1292 // Destroys data related to AT command support
       
  1293 // ---------------------------------------------------------------------------
       
  1294 //
       
  1295 TInt CATExtMetadata::DestroySupportdata(
       
  1296     CArrayFixFlat<TATExtAtCmdSupport>*& aSupport )
       
  1297     {
       
  1298     TRACE_FUNC_ENTRY
       
  1299     if ( !aSupport )
       
  1300         {
       
  1301         TRACE_FUNC_EXIT
       
  1302         return KErrGeneral;
       
  1303         }
       
  1304     // Next just remove the entries
       
  1305     TInt i;
       
  1306     TInt supportCount = aSupport->Count();
       
  1307     for ( i=0; i<supportCount; i++ )
       
  1308         {
       
  1309         TATExtAtCmdSupport& support = (*aSupport)[i];
       
  1310         delete support.iAtCmdBase;
       
  1311         support.iAtCmdBase = NULL;
       
  1312         if ( support.iEntries )
       
  1313             {
       
  1314             support.iEntries->Reset();
       
  1315             delete support.iEntries;
       
  1316             support.iEntries = NULL;
       
  1317             }
       
  1318         }
       
  1319     aSupport->Reset();
       
  1320     delete aSupport;
       
  1321     aSupport = NULL;
       
  1322     TRACE_FUNC_EXIT
       
  1323     return KErrNone;
       
  1324     }
       
  1325 
       
  1326 // ---------------------------------------------------------------------------
       
  1327 // Extracts one command from a pipe-character delimited command buffer (Note:
       
  1328 // This function is used to get the settings from a plugin RSS file)
       
  1329 // ---------------------------------------------------------------------------
       
  1330 //
       
  1331 TInt CATExtMetadata::ExtractNextCommand( const TDesC8& aCommands,
       
  1332                                          TInt& aStartIndex,
       
  1333                                          TInt& aEndIndex,
       
  1334                                          TATExtSupportType& aSupportType )
       
  1335     {
       
  1336     TRACE_FUNC_ENTRY
       
  1337     aSupportType = ESupportTypeUndefined;
       
  1338     // Skip data before command
       
  1339     TInt i;
       
  1340     TChar character;
       
  1341     TInt count = aCommands.Length();
       
  1342     for ( i=aEndIndex; i<count; i++ )
       
  1343         {
       
  1344         character = aCommands[i];
       
  1345         if ( character.IsPrint() && character!='|' )
       
  1346             {
       
  1347             break;
       
  1348             }
       
  1349         }
       
  1350     if ( i >= count )
       
  1351         {
       
  1352         TRACE_FUNC_EXIT
       
  1353         return KErrNotFound;
       
  1354         }
       
  1355     // Now the plugin type marker is found; check the plugin type
       
  1356     switch ( character )
       
  1357         {
       
  1358         case 'M':  // Master plugin
       
  1359         case 'm':
       
  1360             aSupportType = ESupportTypeMaster;
       
  1361             break;
       
  1362         case 'P':  // Primary plugin
       
  1363         case 'p':
       
  1364             aSupportType = ESupportTypePrimary;
       
  1365             break;
       
  1366         case 'S':  // Secondary plugin
       
  1367         case 's':
       
  1368             aSupportType = ESupportTypeSecondary;
       
  1369             break;
       
  1370         }
       
  1371     i++;
       
  1372     if ( i >= count )
       
  1373         {
       
  1374         TRACE_FUNC_EXIT
       
  1375         return KErrNotFound;
       
  1376         }
       
  1377     aStartIndex = i;
       
  1378     // Start of command found, next mark the end
       
  1379     while ( i < count )
       
  1380         {
       
  1381         character = aCommands[i];
       
  1382         if ( !character.IsPrint() || character=='|' )
       
  1383             {
       
  1384             break;
       
  1385             }
       
  1386         i++;
       
  1387         }
       
  1388     aEndIndex = i;
       
  1389     if ( aEndIndex-aStartIndex <= 0 )
       
  1390         {
       
  1391         TRACE_FUNC_EXIT
       
  1392         return KErrNotFound;
       
  1393         }
       
  1394     TRACE_FUNC_EXIT
       
  1395     return KErrNone;
       
  1396     }
       
  1397 
       
  1398 // ---------------------------------------------------------------------------
       
  1399 // Adds a new plugin entry to support data. If command to be added is not
       
  1400 // found from the support data then that command is inserted alphabetically to
       
  1401 // the support data. After this a search for the plugin UID is done; if the
       
  1402 // UID is not found then it is added to the plugin data and a new initialized
       
  1403 // data is created for that entry. Finally the added or new plugin entry is
       
  1404 // linked to the new or existing support entry.
       
  1405 // ---------------------------------------------------------------------------
       
  1406 //
       
  1407 void CATExtMetadata::AddEntryToMetadataL( TDes8& aAtCmdBase,
       
  1408                                           TUid& aPluginUid,
       
  1409                                           TATExtSupportType aSupportType,
       
  1410                                           TATExtCleanupInfo& aCleanupInfo )
       
  1411     {
       
  1412     TRACE_FUNC_ENTRY
       
  1413     if ( !iSupport || !iSupportAux || !iPluginData )
       
  1414         {
       
  1415         TRACE_FUNC_EXIT
       
  1416         User::Leave( KErrGeneral );
       
  1417         }
       
  1418     // First try to find the string with binary search.
       
  1419     // If found, add aUid.
       
  1420     // If not found, add aAtCmdBase, aPluginUid.
       
  1421     CArrayFixFlat<TATExtAtCmdSupport>* support = iSupport;
       
  1422     aCleanupInfo.iSupportCreated = EFalse;
       
  1423     aCleanupInfo.iSupportIndex = KErrNotFound;
       
  1424     aCleanupInfo.iEntryCreated = EFalse;
       
  1425     aCleanupInfo.iEntryIndex = KErrNotFound;
       
  1426     aCleanupInfo.iSupport = iSupport;
       
  1427     TBool findAux = EFalse;
       
  1428     TInt strLength = aAtCmdBase.Length();
       
  1429     if ( strLength>=3 && aAtCmdBase[strLength-1]=='*' )  // 3 for "AT*"
       
  1430         {
       
  1431         aAtCmdBase.SetLength( strLength-1 );
       
  1432         aCleanupInfo.iSupport = iSupportAux;
       
  1433         support = iSupportAux;
       
  1434         findAux = ETrue;
       
  1435         }
       
  1436     TInt foundPos = KErrNotFound;
       
  1437     TBool found = FindCommandFromMetadata( aAtCmdBase, foundPos, findAux, EFalse );
       
  1438     if ( !found )
       
  1439         {
       
  1440         // Not found. foundPos is the position where to add the new entry
       
  1441         TATExtAtCmdSupport newEntry;
       
  1442         foundPos = -foundPos;  // convert to positive
       
  1443         newEntry.iAtCmdBase = HBufC8::NewMaxLC( aAtCmdBase.Length() );
       
  1444         newEntry.iEntries = NULL;
       
  1445         TPtr8 atCmdPtr = newEntry.iAtCmdBase->Des();
       
  1446         atCmdPtr.Copy( aAtCmdBase );
       
  1447         support->InsertL( foundPos, newEntry );
       
  1448         CleanupStack::Pop( newEntry.iAtCmdBase );
       
  1449         aCleanupInfo.iSupportCreated = ETrue;
       
  1450         }
       
  1451     aCleanupInfo.iSupportIndex = foundPos;
       
  1452     // Next try to find the plugin UID from plugin data.
       
  1453     TInt foundIndex = KErrNotFound;
       
  1454     TATExtPluginEntry* foundEntry = FindUidFromPlugindata( aPluginUid,
       
  1455                                                            foundIndex );
       
  1456     if ( !foundEntry )
       
  1457         {
       
  1458         // Not found. Append new initialized entry.
       
  1459         TATExtPluginEntry pluginEntry;
       
  1460         pluginEntry.iPluginUid = aPluginUid;
       
  1461         pluginEntry.iInstance = NULL;
       
  1462         pluginEntry.iLocked = EFalse;
       
  1463         pluginEntry.iUrcStarted = EFalse;
       
  1464         pluginEntry.iUrcOwned = EFalse;
       
  1465         iPluginData->AppendL( pluginEntry );
       
  1466         aCleanupInfo.iEntryCreated = ETrue;
       
  1467         aCleanupInfo.iEntryIndex = iPluginData->Count() - 1;
       
  1468         foundIndex = aCleanupInfo.iEntryIndex;
       
  1469         foundEntry = &(*iPluginData)[foundIndex];
       
  1470         }
       
  1471     // Now foundEntry is either the found entry or a newly added entry.
       
  1472     // Make the iSupport metadata point to this.
       
  1473     TATExtAtCmdSupport& foundSupport = (*support)[foundPos];
       
  1474 #if defined( PRJ_OPTIMIZE_FOR_SPEED )
       
  1475     AddNewMetadataEntryLinkL( foundSupport.iEntries,
       
  1476                               foundIndex,
       
  1477                               aSupportType,
       
  1478                               foundSupport.iSearchHelper );
       
  1479 #else  // PRJ_OPTIMIZE_FOR_SPEED
       
  1480     TATExtSearchHelper searchHelper;
       
  1481     AddNewMetadataEntryLinkL( foundSupport.iEntries,
       
  1482                               foundIndex,
       
  1483                               aSupportType,
       
  1484                               searchHelper );
       
  1485 #endif  // PRJ_OPTIMIZE_FOR_SPEED
       
  1486     TRACE_FUNC_EXIT
       
  1487     }
       
  1488 
       
  1489 // ---------------------------------------------------------------------------
       
  1490 // Adds new plugin entry link from plugin support entry to plugin entry
       
  1491 // ---------------------------------------------------------------------------
       
  1492 //
       
  1493 TInt CATExtMetadata::AddNewMetadataEntryLinkL(
       
  1494     CArrayFixFlat<TATExtOneCmdSupport>*& aEntries,
       
  1495     TInt aEntryIndex,
       
  1496     TATExtSupportType aSupportType,
       
  1497     TATExtSearchHelper& aSearchHelper )
       
  1498     {
       
  1499     TRACE_FUNC_ENTRY
       
  1500     if ( !iPluginData || aEntryIndex<0 || aEntryIndex>=iPluginData->Count() )
       
  1501         {
       
  1502         TRACE_FUNC_EXIT
       
  1503         User::Leave( KErrGeneral );
       
  1504         }
       
  1505     if ( !aEntries )
       
  1506         {
       
  1507         aEntries = new (ELeave) CArrayFixFlat<TATExtOneCmdSupport>( KGranularity );
       
  1508         }
       
  1509     TATExtOneCmdSupport oneCmdSupport;
       
  1510     oneCmdSupport.iSupportType = aSupportType;
       
  1511     oneCmdSupport.iEntryIndex = aEntryIndex;
       
  1512     TInt retVal = KErrNotSupported;
       
  1513     switch ( aSupportType )
       
  1514         {
       
  1515         case ESupportTypeMaster:
       
  1516             {
       
  1517             retVal = AddNewMasterMetadataEntryLinkL( aEntries,
       
  1518                                                      aSearchHelper,
       
  1519                                                      oneCmdSupport );
       
  1520             }
       
  1521             break;
       
  1522         case ESupportTypePrimary:
       
  1523             {
       
  1524             retVal = AddNewPrimaryMetadataEntryLinkL( aEntries,
       
  1525                                                       aSearchHelper,
       
  1526                                                       oneCmdSupport );
       
  1527             }
       
  1528             break;
       
  1529         case ESupportTypeSecondary:
       
  1530             {
       
  1531             retVal = AddNewSecondaryMetadataEntryLinkL( aEntries,
       
  1532                                                         aSearchHelper,
       
  1533                                                         oneCmdSupport );
       
  1534             }
       
  1535             break;
       
  1536         default:
       
  1537             {
       
  1538             User::Leave( KErrNotSupported );
       
  1539             }
       
  1540         }
       
  1541     TRACE_FUNC_EXIT
       
  1542     return retVal;
       
  1543     }
       
  1544 
       
  1545 // ---------------------------------------------------------------------------
       
  1546 // Adds new master plugin entry link from plugin support entry to plugin entry
       
  1547 // ---------------------------------------------------------------------------
       
  1548 //
       
  1549 TInt CATExtMetadata::AddNewMasterMetadataEntryLinkL(
       
  1550     CArrayFixFlat<TATExtOneCmdSupport>* aEntries,
       
  1551     TATExtSearchHelper& aSearchHelper,
       
  1552     TATExtOneCmdSupport& aOneCmdSupport )
       
  1553     {
       
  1554     TRACE_FUNC_ENTRY
       
  1555     aEntries->InsertL( 0, aOneCmdSupport );
       
  1556     if ( aSearchHelper.iPrimaryIndex >= 0 )
       
  1557        {
       
  1558         aSearchHelper.iPrimaryIndex++;
       
  1559         }
       
  1560     if ( aSearchHelper.iSecondaryIndex >= 0 )
       
  1561         {
       
  1562         aSearchHelper.iSecondaryIndex++;
       
  1563         }
       
  1564     TRACE_FUNC_EXIT
       
  1565     return 0;
       
  1566     }
       
  1567 
       
  1568 // ---------------------------------------------------------------------------
       
  1569 // Adds new primary plugin entry link from plugin support entry to plugin
       
  1570 // entry
       
  1571 // ---------------------------------------------------------------------------
       
  1572 //
       
  1573 TInt CATExtMetadata::AddNewPrimaryMetadataEntryLinkL(
       
  1574     CArrayFixFlat<TATExtOneCmdSupport>* aEntries,
       
  1575     TATExtSearchHelper& aSearchHelper,
       
  1576     TATExtOneCmdSupport& aOneCmdSupport )
       
  1577     {
       
  1578     TRACE_FUNC_ENTRY
       
  1579     TInt i = aSearchHelper.iPrimaryIndex;
       
  1580     if ( i < 0 )
       
  1581         {
       
  1582         TInt count = aEntries->Count();
       
  1583         for ( i=0; i<count; i++ )
       
  1584             {
       
  1585             TATExtOneCmdSupport& oneCmdSupport = (*aEntries)[i];
       
  1586             if ( oneCmdSupport.iSupportType==ESupportTypePrimary ||
       
  1587                  oneCmdSupport.iSupportType==ESupportTypeSecondary )
       
  1588                 {
       
  1589                 break;
       
  1590                 }
       
  1591             }
       
  1592         aSearchHelper.iPrimaryIndex = i;
       
  1593         }
       
  1594     aEntries->InsertL( i, aOneCmdSupport );
       
  1595     if ( aSearchHelper.iSecondaryIndex >= 0 )
       
  1596         {
       
  1597         aSearchHelper.iSecondaryIndex++;
       
  1598         }
       
  1599     TRACE_FUNC_EXIT
       
  1600     return i;
       
  1601     }
       
  1602 
       
  1603 // ---------------------------------------------------------------------------
       
  1604 // Adds new secondary plugin entry link from plugin support entry to plugin
       
  1605 // entry. Search starts from the front as there could be multiple S plugins
       
  1606 // but only one or two M/P plugins.
       
  1607 // ---------------------------------------------------------------------------
       
  1608 //
       
  1609 TInt CATExtMetadata::AddNewSecondaryMetadataEntryLinkL(
       
  1610     CArrayFixFlat<TATExtOneCmdSupport>* aEntries,
       
  1611     TATExtSearchHelper& aSearchHelper,
       
  1612     TATExtOneCmdSupport& aOneCmdSupport )
       
  1613     {
       
  1614     TRACE_FUNC_ENTRY
       
  1615     TInt i = aSearchHelper.iSecondaryIndex;
       
  1616     if ( i < 0 )
       
  1617         {
       
  1618         TInt count = aEntries->Count();
       
  1619         for ( i=0; i<count; i++ )
       
  1620             {
       
  1621             TATExtOneCmdSupport& oneCmdSupport = (*aEntries)[i];
       
  1622             if ( oneCmdSupport.iSupportType == ESupportTypeSecondary )
       
  1623                 {
       
  1624                 break;
       
  1625                 }
       
  1626             }
       
  1627         aSearchHelper.iSecondaryIndex = i;
       
  1628         }
       
  1629     aEntries->InsertL( i, aOneCmdSupport );
       
  1630     TRACE_FUNC_EXIT
       
  1631     return i;
       
  1632     }
       
  1633 
       
  1634 // ---------------------------------------------------------------------------
       
  1635 // Cleans partial created metadata based on TATExtCleanupInfo
       
  1636 // ---------------------------------------------------------------------------
       
  1637 //
       
  1638 void CATExtMetadata::CleanPartialMetadata( TATExtCleanupInfo& aCleanupInfo )
       
  1639     {
       
  1640     TRACE_FUNC_ENTRY
       
  1641     TBool withinEntryLimits = EFalse;
       
  1642     TBool withinSupportLimits = EFalse;
       
  1643     CArrayFixFlat<TATExtAtCmdSupport>* support = aCleanupInfo.iSupport;
       
  1644     if ( aCleanupInfo.iEntryIndex>=0 &&
       
  1645          aCleanupInfo.iEntryIndex<support->Count() )
       
  1646         {
       
  1647         withinEntryLimits = ETrue;
       
  1648         }
       
  1649     if ( aCleanupInfo.iSupportIndex>=0 &&
       
  1650          aCleanupInfo.iSupportIndex<support->Count() )
       
  1651         {
       
  1652         withinSupportLimits = ETrue;
       
  1653         }
       
  1654     if ( aCleanupInfo.iEntryCreated && withinEntryLimits )
       
  1655         {
       
  1656         iPluginData->Delete( aCleanupInfo.iEntryIndex );
       
  1657         }
       
  1658     if ( aCleanupInfo.iSupportCreated && withinSupportLimits )
       
  1659         {
       
  1660         TInt deleteIndex = aCleanupInfo.iSupportIndex;
       
  1661         TATExtAtCmdSupport& supportData = (*support)[deleteIndex];
       
  1662         delete supportData.iAtCmdBase;
       
  1663         supportData.iAtCmdBase = NULL;
       
  1664         delete supportData.iEntries;
       
  1665         supportData.iEntries = NULL;
       
  1666         support->Delete( deleteIndex );
       
  1667         support->Compress();
       
  1668         }
       
  1669     TRACE_FUNC_EXIT
       
  1670     }
       
  1671 
       
  1672 // ---------------------------------------------------------------------------
       
  1673 // Prints the AT command plugin entries and information about them.
       
  1674 // For debugging/bug hunting only
       
  1675 // ---------------------------------------------------------------------------
       
  1676 //
       
  1677 #if defined(_DEBUG) && defined( PRJ_PRINT_SUPPORT_DATA )
       
  1678 TInt CATExtMetadata::PrintSupportData(
       
  1679     CArrayFixFlat<TATExtAtCmdSupport>* aSupport )
       
  1680     {
       
  1681     TRACE_FUNC_ENTRY
       
  1682     if ( !aSupport )
       
  1683         {
       
  1684         TRACE_FUNC_EXIT
       
  1685         return KErrGeneral;
       
  1686         }
       
  1687     TInt i;
       
  1688     TInt j;
       
  1689     TInt supportCount = aSupport->Count();
       
  1690     for ( i=0; i<supportCount; i++ )
       
  1691         {
       
  1692         TATExtAtCmdSupport& support = (*aSupport)[i];
       
  1693         if ( !support.iEntries )
       
  1694             {
       
  1695             continue;
       
  1696             }
       
  1697         TInt entryCount = support.iEntries->Count();
       
  1698         TRACE_INFO(( _L8("Support entry at index %d = '%S' (%d entries):"), i, &(*support.iAtCmdBase), entryCount ));
       
  1699         for ( j=0; j<entryCount; j++ )
       
  1700             {
       
  1701             TATExtOneCmdSupport& oneCmdSupport = (*support.iEntries)[j];
       
  1702             TInt entryIndex = oneCmdSupport.iEntryIndex;
       
  1703             TRACE_INFO(( _L8("\tPlugin entry at index %d = Type:%d, UID:0x%08X"), j, oneCmdSupport.iSupportType, (*iPluginData)[entryIndex].iPluginUid ));
       
  1704             }
       
  1705         }
       
  1706     TRACE_FUNC_EXIT
       
  1707     return KErrNone;
       
  1708     }
       
  1709 #endif
       
  1710 
       
  1711 // ---------------------------------------------------------------------------
       
  1712 // Prints the found AT command plugin entries and information about them.
       
  1713 // For debugging/bug hunting only
       
  1714 // ---------------------------------------------------------------------------
       
  1715 //
       
  1716 #if defined(_DEBUG) && defined( PRJ_PRINT_SUPPORT_DATA )
       
  1717 TInt CATExtMetadata::PrintFoundEntries(
       
  1718     CArrayFixFlat<TATExtOneCmdSupport>* aEntries )
       
  1719     {
       
  1720     TRACE_FUNC_ENTRY
       
  1721     if ( !aEntries )
       
  1722         {
       
  1723         TRACE_FUNC_EXIT
       
  1724         return KErrGeneral;
       
  1725         }
       
  1726     TInt i;
       
  1727     TInt count = aEntries->Count();
       
  1728     for ( i=0; i<count; i++ )
       
  1729         {
       
  1730         TATExtOneCmdSupport& entry = (*aEntries)[i];
       
  1731         TInt entryIndex = entry.iEntryIndex;
       
  1732         TRACE_INFO(( _L8("\tFound entry at index %d = Type:%d, UID:0x%08X"), i, entry.iSupportType, (*iPluginData)[entryIndex].iPluginUid ));
       
  1733         }
       
  1734     TRACE_FUNC_EXIT
       
  1735     return KErrNone;
       
  1736     }
       
  1737 #endif
       
  1738 
       
  1739 // ---------------------------------------------------------------------------
       
  1740 // Does a binary search for an AT command to find the AT command from the
       
  1741 // support data
       
  1742 // ---------------------------------------------------------------------------
       
  1743 //
       
  1744 TBool CATExtMetadata::FindCommandFromMetadata( TDesC8& aAtCmdBase,
       
  1745                                                TInt& aFoundIndex,
       
  1746                                                TBool aFindAuxCmd,
       
  1747                                                TBool aCheckAsterisk )
       
  1748     {
       
  1749     TRACE_FUNC_ENTRY
       
  1750     if ( !iSupport || !iSupportAux || (!aFindAuxCmd&&aCheckAsterisk) )
       
  1751         {
       
  1752         TRACE_FUNC_EXIT
       
  1753         return EFalse;
       
  1754         }
       
  1755     TInt result = 0;
       
  1756     TInt middle = 0;
       
  1757     TInt left = 0;
       
  1758     CArrayFixFlat<TATExtAtCmdSupport>* support = iSupport;
       
  1759     if ( aFindAuxCmd )
       
  1760         {
       
  1761         support = iSupportAux;
       
  1762         }
       
  1763     TInt right = support->Count() - 1;
       
  1764     while ( left <= right )
       
  1765         {
       
  1766         middle = ( left + right ) / 2;
       
  1767         HBufC8& compareStr = *(*support)[middle].iAtCmdBase;
       
  1768         TInt strLength = compareStr.Length();
       
  1769         if ( aCheckAsterisk )
       
  1770             {
       
  1771             TPtrC8 leftPart = aAtCmdBase.Left( strLength );
       
  1772             result = compareStr.Compare( leftPart );
       
  1773             }
       
  1774         else
       
  1775             {
       
  1776             result = compareStr.Compare( aAtCmdBase );
       
  1777             }
       
  1778         if ( result == 0 )  // iSupport == aAtCmd
       
  1779             {
       
  1780             aFoundIndex = middle;
       
  1781             TRACE_FUNC_EXIT
       
  1782             return ETrue;
       
  1783             }
       
  1784         else if ( result < 0 )  // iSupport < aAtCmd
       
  1785             {
       
  1786             left = middle + 1;
       
  1787             }
       
  1788         else  // iSupport > aAtCmd
       
  1789             {
       
  1790             right = middle - 1;
       
  1791             }
       
  1792         }
       
  1793     aFoundIndex = -left;
       
  1794     TRACE_FUNC_EXIT
       
  1795     return EFalse;
       
  1796     }
       
  1797 
       
  1798 // ---------------------------------------------------------------------------
       
  1799 // Finds the first plugin entry from a given plugin UID
       
  1800 // ---------------------------------------------------------------------------
       
  1801 //
       
  1802 TATExtPluginEntry* CATExtMetadata::FindUidFromPlugindata( TUid& aUid,
       
  1803                                                           TInt& aFoundIndex )
       
  1804     {
       
  1805     TRACE_FUNC_ENTRY
       
  1806     aFoundIndex = KErrNotFound;
       
  1807     if ( !iPluginData )
       
  1808         {
       
  1809         TRACE_FUNC_EXIT
       
  1810         return NULL;
       
  1811         }
       
  1812     TInt i;
       
  1813     TInt count = iPluginData->Count();
       
  1814     for ( i=0; i<count; i++ )
       
  1815         {
       
  1816         TATExtPluginEntry& entry = (*iPluginData)[i];
       
  1817         if ( entry.iPluginUid == aUid )
       
  1818             {
       
  1819             TRACE_FUNC_EXIT
       
  1820             aFoundIndex = i;
       
  1821             return &entry;
       
  1822             }
       
  1823         }
       
  1824     TRACE_FUNC_EXIT
       
  1825     return NULL;
       
  1826     }
       
  1827 
       
  1828 // ---------------------------------------------------------------------------
       
  1829 // Find the first plugin entry from a given plugin instance
       
  1830 // ---------------------------------------------------------------------------
       
  1831 //
       
  1832 TATExtPluginEntry* CATExtMetadata::FindInstanceFromPlugindata(
       
  1833     CATExtPluginBase* aInstance )
       
  1834     {
       
  1835     TRACE_FUNC_ENTRY
       
  1836     if ( !iPluginData )
       
  1837         {
       
  1838         TRACE_FUNC_EXIT
       
  1839         return NULL;
       
  1840         }
       
  1841     TInt i;
       
  1842     TInt count = iPluginData->Count();
       
  1843     for ( i=0; i<count; i++ )
       
  1844         {
       
  1845         TATExtPluginEntry& entry = (*iPluginData)[i];
       
  1846         if ( entry.iInstance == aInstance )
       
  1847             {
       
  1848             TRACE_FUNC_EXIT
       
  1849             return &entry;
       
  1850             }
       
  1851         }
       
  1852     TRACE_FUNC_EXIT
       
  1853     return NULL;
       
  1854     }
       
  1855 
       
  1856 // ---------------------------------------------------------------------------
       
  1857 // Finds an Urc message processing plugin. Must be used in synchronization
       
  1858 // with MarkUrcHandlingOwnership(). More information in aPluginUid parameter's
       
  1859 // explanation below.
       
  1860 // ---------------------------------------------------------------------------
       
  1861 //
       
  1862 TATExtPluginEntry* CATExtMetadata::FindUrcProcessingPlugin(
       
  1863     TUid& aPluginUid )
       
  1864     {
       
  1865     TRACE_FUNC_ENTRY
       
  1866     if ( !iPluginData )
       
  1867         {
       
  1868         TRACE_FUNC_EXIT
       
  1869         return NULL;
       
  1870         }
       
  1871     TInt i;
       
  1872     TInt count = iPluginData->Count();
       
  1873     for ( i=0; i<count; i++ )
       
  1874         {
       
  1875         TATExtPluginEntry& entry = (*iPluginData)[i];
       
  1876         if ( entry.iUrcMessage.Handle() )
       
  1877             {
       
  1878             continue;
       
  1879             }
       
  1880         // second run (after MarkUrcHandlingOwnership())
       
  1881         if ( aPluginUid != TUid::Null() )
       
  1882             {
       
  1883             if ( entry.iUrcOwned && entry.iPluginUid==aPluginUid )
       
  1884                 {
       
  1885                 TRACE_FUNC_EXIT
       
  1886                 return &entry;
       
  1887                 }
       
  1888             }
       
  1889         // first run (before MarkUrcHandlingOwnership())
       
  1890         else if ( !entry.iUrcStarted && !entry.iUrcOwned )
       
  1891             {
       
  1892             TRACE_FUNC_EXIT
       
  1893             return &entry;
       
  1894             }
       
  1895         }
       
  1896     TRACE_FUNC_EXIT
       
  1897     return NULL;
       
  1898     }
       
  1899 
       
  1900 // ---------------------------------------------------------------------------
       
  1901 // Extracts the base command from a given AT command to find support with
       
  1902 // DoCreateAndFindSupportL()
       
  1903 // ---------------------------------------------------------------------------
       
  1904 //
       
  1905 void CATExtMetadata::CreateAndFindSupportL(
       
  1906     TDesC8& aAtCmdFull,
       
  1907     const RMessage2& aMessage,
       
  1908     TATExtCompletionInfo& aComplInfo )
       
  1909     {
       
  1910     TRACE_FUNC_ENTRY
       
  1911     // First extract the base of AT command from aAtCmdFull
       
  1912     // ('=' and everything after that)
       
  1913     TInt newLength = aAtCmdFull.Length();
       
  1914     TInt foundPos = aAtCmdFull.Locate( '=' );
       
  1915     if ( foundPos >= 2 )  // After "AT"
       
  1916         {
       
  1917         newLength = foundPos;
       
  1918         }
       
  1919     else if ( newLength >= 1 )
       
  1920         {
       
  1921         // There was no '=' so check if the last character is '?'.
       
  1922         // If it is then remove it.
       
  1923         if ( aAtCmdFull[newLength-1] == '?' )
       
  1924             {
       
  1925             newLength--;
       
  1926             }
       
  1927         }
       
  1928     HBufC8* baseCmd = HBufC8::NewMaxLC( newLength );
       
  1929     TPtr8 baseCmdPtr = baseCmd->Des();
       
  1930     baseCmdPtr.Copy( &aAtCmdFull[0], newLength );
       
  1931     // Now the baseCmd has the base command. Use it to find the support.
       
  1932     DoCreateAndFindSupportL( *baseCmd,
       
  1933                              aAtCmdFull,
       
  1934                              aMessage,
       
  1935                              aComplInfo );
       
  1936     CleanupStack::PopAndDestroy( baseCmd );
       
  1937     TRACE_FUNC_EXIT
       
  1938     }
       
  1939 
       
  1940 // ---------------------------------------------------------------------------
       
  1941 // Creates AT command support and finds the given AT command from the created
       
  1942 // support data
       
  1943 // ---------------------------------------------------------------------------
       
  1944 //
       
  1945 void CATExtMetadata::DoCreateAndFindSupportL(
       
  1946     TDesC8& aAtCmdBase,
       
  1947     TDesC8& aAtCmdFull,
       
  1948     const RMessage2& aMessage,
       
  1949     TATExtCompletionInfo& aComplInfo )
       
  1950     {
       
  1951     TRACE_FUNC_ENTRY
       
  1952     // Note: don't set iCmdData.iOldHandler to NULL here as the sequence can
       
  1953     // invoke this function again before ReportExternalHandleCommandError().
       
  1954     // Get array of supported plugins for the base command
       
  1955     CArrayFixFlat<TATExtOneCmdSupport>* support;
       
  1956     support = FindEntriesForCommandLC( aAtCmdBase );
       
  1957     if ( !support )
       
  1958         {
       
  1959         aComplInfo.iProcessed = EFalse;
       
  1960         aComplInfo.iReplyExpected = ETrue;
       
  1961         CreateSelfReplyData( aMessage );
       
  1962         CleanupStack::PopAndDestroy();
       
  1963         TRACE_FUNC_EXIT
       
  1964         return;
       
  1965         }
       
  1966     TATExtEntrySupport entrySupport( aAtCmdFull, aMessage, support );
       
  1967     TInt i;
       
  1968     aComplInfo.iProcessed = EFalse;
       
  1969     TInt count = support->Count();
       
  1970     for ( i=0; i<count; i++ )
       
  1971         {
       
  1972         TBool supported = EFalse;
       
  1973         TATExtOneCmdSupport& oneCmdSupport = (*support)[i];
       
  1974         entrySupport.iEntry = &(*iPluginData)[oneCmdSupport.iEntryIndex];
       
  1975         if ( oneCmdSupport.iSupportType == ESupportTypeMaster )
       
  1976             {
       
  1977             supported = HandleMasterPluginSupportL(
       
  1978                 entrySupport,
       
  1979                 aComplInfo.iReplyExpected );
       
  1980             }
       
  1981         else if ( oneCmdSupport.iSupportType == ESupportTypePrimary )
       
  1982             {
       
  1983             supported = HandlePrimaryPluginSupportL(
       
  1984                 entrySupport,
       
  1985                 i+1,
       
  1986                 aComplInfo.iReplyExpected );
       
  1987             }
       
  1988         else if ( oneCmdSupport.iSupportType == ESupportTypeSecondary )
       
  1989             {
       
  1990             supported = HandleSecondaryPluginSupportL(
       
  1991                 entrySupport,
       
  1992                 i+1,
       
  1993                 aComplInfo.iReplyExpected );
       
  1994             }
       
  1995         if ( supported )
       
  1996             {
       
  1997             aComplInfo.iProcessed = ETrue;
       
  1998             break;
       
  1999             }
       
  2000         }
       
  2001     CleanupStack::PopAndDestroy( support );
       
  2002     if ( !aComplInfo.iProcessed || !aComplInfo.iReplyExpected )
       
  2003         {
       
  2004         CreateSelfReplyData( aMessage );
       
  2005         }
       
  2006     TRACE_FUNC_EXIT
       
  2007     }
       
  2008 
       
  2009 // ---------------------------------------------------------------------------
       
  2010 // Prepares internal data for completion with "" or "ERROR" messages.
       
  2011 // More explation in CreateEmptyOrErrorBuffer().
       
  2012 // ---------------------------------------------------------------------------
       
  2013 //
       
  2014 void CATExtMetadata::CreateSelfReplyData( const RMessage2& aMessage )
       
  2015     {
       
  2016     TRACE_FUNC_ENTRY
       
  2017     // "ERROR" or "" needed; initialize
       
  2018     iCmdData.iCmdStarted = ETrue;
       
  2019     iCmdData.iCmdMessage = aMessage;
       
  2020     iCmdData.iHandler = NULL;
       
  2021     TRACE_FUNC_EXIT
       
  2022     }
       
  2023 
       
  2024 // ---------------------------------------------------------------------------
       
  2025 // Handles support when a master plugin is detected in the plugin data via
       
  2026 // support data's link (support for a full AT command). If a master plugin is
       
  2027 // detected then reply is detected from that plugin. No further sending to
       
  2028 // primary or secondary plugins is repformed.
       
  2029 // ---------------------------------------------------------------------------
       
  2030 //
       
  2031 TBool CATExtMetadata::HandleMasterPluginSupportL(
       
  2032     TATExtEntrySupport& aEntrySupport,
       
  2033     TBool& aReplyExpected )
       
  2034     {
       
  2035     TRACE_FUNC_ENTRY
       
  2036     aReplyExpected = EFalse;
       
  2037     TBool supported = HandleCommandSupportL( aEntrySupport );
       
  2038     if ( !supported )
       
  2039         {
       
  2040         TRACE_FUNC_EXIT
       
  2041         return EFalse;
       
  2042         }
       
  2043     iCmdData.iReplyExpected = ETrue;  // Set before HandleCommandL()
       
  2044     HandleCommandL( aEntrySupport, ETrue );
       
  2045     aReplyExpected = ETrue;
       
  2046     TRACE_FUNC_EXIT
       
  2047     return ETrue;
       
  2048     }
       
  2049 
       
  2050 // ---------------------------------------------------------------------------
       
  2051 // Handles support when a primary plugin is detect in the plugin data via
       
  2052 // support data's link. If a primary plugin is detected then reply is expected
       
  2053 // from that plugin. Also if one or more secondary plugins are detected then
       
  2054 // no reply is expected from them.
       
  2055 // ---------------------------------------------------------------------------
       
  2056 //
       
  2057 TBool CATExtMetadata::HandlePrimaryPluginSupportL(
       
  2058     TATExtEntrySupport& aEntrySupport,
       
  2059     TInt aStartIndex,
       
  2060     TBool& aReplyExpected )
       
  2061     {
       
  2062     TRACE_FUNC_ENTRY
       
  2063     aReplyExpected = EFalse;
       
  2064     TBool supported = HandleCommandSupportL( aEntrySupport );
       
  2065     if ( !supported )
       
  2066         {
       
  2067         TRACE_FUNC_EXIT
       
  2068         return EFalse;
       
  2069         }
       
  2070     // If HandleCommand() is implemented synchronously, the command must be
       
  2071     // saved before executing as CompleteCommandMessage() closes the string
       
  2072     HBufC8* atCmdFull = HBufC8::NewMaxLC( aEntrySupport.iAtCmdFull.Length() );
       
  2073     TPtr8 atCmdFullPtr = atCmdFull->Des();
       
  2074     atCmdFullPtr.Copy( aEntrySupport.iAtCmdFull );
       
  2075     // Now execute the HandleCommand()
       
  2076     iCmdData.iReplyExpected = ETrue;  // Set before HandleCommandL()
       
  2077     HandleCommandL( aEntrySupport, ETrue );
       
  2078     aEntrySupport.iStartIndex = aStartIndex;
       
  2079     SendToMultipleSecondaryL( aEntrySupport, atCmdFull );
       
  2080     CleanupStack::PopAndDestroy( atCmdFull );
       
  2081     aReplyExpected = ETrue;
       
  2082     TRACE_FUNC_EXIT
       
  2083     return ETrue;
       
  2084     }
       
  2085 
       
  2086 // ---------------------------------------------------------------------------
       
  2087 // Handles support when a secondary plugin is detected in the plugin data via
       
  2088 // support data's link. If only one secondary plugin is detected then reply is
       
  2089 // expected from that plugin. Instead, if more than one secondary plugins are
       
  2090 // detected then no reply is expected from them.
       
  2091 // ---------------------------------------------------------------------------
       
  2092 //
       
  2093 TBool CATExtMetadata::HandleSecondaryPluginSupportL(
       
  2094     TATExtEntrySupport& aEntrySupport,
       
  2095     TInt aStartIndex,
       
  2096     TBool& aReplyExpected )
       
  2097     {
       
  2098     TRACE_FUNC_ENTRY
       
  2099     aReplyExpected = EFalse;
       
  2100     TBool supported = HandleCommandSupportL( aEntrySupport );
       
  2101     if ( !supported )
       
  2102         {
       
  2103         TRACE_FUNC_EXIT
       
  2104         return EFalse;
       
  2105         }
       
  2106     TATExtEntrySupport nextSupport = aEntrySupport;
       
  2107     nextSupport.iStartIndex = aStartIndex;
       
  2108     TBool entryFound = FindFirstSecondarySupportL( nextSupport );
       
  2109     if ( entryFound )
       
  2110         {
       
  2111         // Entry found; send all without reply request
       
  2112         // If HandleCommand() is implemented synchronously, the command must be
       
  2113         // saved before executing as CompleteCommandMessage() closes the string
       
  2114         HBufC8* atCmdFull = HBufC8::NewMaxLC( aEntrySupport.iAtCmdFull.Length() );
       
  2115         TPtr8 atCmdFullPtr = atCmdFull->Des();
       
  2116         atCmdFullPtr.Copy( aEntrySupport.iAtCmdFull );
       
  2117         // Now execute the HandleCommand()
       
  2118         HandleCommandL( aEntrySupport, EFalse );
       
  2119         SendToMultipleSecondaryL( nextSupport, atCmdFull );
       
  2120         CleanupStack::PopAndDestroy( atCmdFull );
       
  2121         }
       
  2122     else
       
  2123         {
       
  2124         // No entry found; send one with reply request
       
  2125         iCmdData.iReplyExpected = ETrue;  // Set before HandleCommandL()
       
  2126         HandleCommandL( aEntrySupport, ETrue );
       
  2127         aReplyExpected = ETrue;
       
  2128         }
       
  2129     TRACE_FUNC_EXIT
       
  2130     return ETrue;
       
  2131     }
       
  2132 
       
  2133 // ---------------------------------------------------------------------------
       
  2134 // Finds support entries from support data for a given base AT command
       
  2135 // ---------------------------------------------------------------------------
       
  2136 //
       
  2137 CArrayFixFlat<TATExtOneCmdSupport>* CATExtMetadata::FindEntriesForCommandLC(
       
  2138     TDesC8& aAtCmdBase )
       
  2139     {
       
  2140     TRACE_FUNC_ENTRY
       
  2141     TBool found;
       
  2142     TInt foundPos;
       
  2143     CArrayFixFlat<TATExtOneCmdSupport>* support =
       
  2144         new (ELeave) CArrayFixFlat<TATExtOneCmdSupport>( KGranularity );
       
  2145     CleanupStack::PushL( support );
       
  2146     // First find normal data to which to add the aux entries
       
  2147     found = FindCommandFromMetadata( aAtCmdBase, foundPos, EFalse, EFalse );
       
  2148     if ( found )
       
  2149         {
       
  2150         CArrayFixFlat<TATExtOneCmdSupport>* entries =
       
  2151             (*iSupport)[foundPos].iEntries;
       
  2152         support->AppendL( &(*entries)[0], entries->Count() );
       
  2153         }
       
  2154     // Next add the aux links
       
  2155     found = FindCommandFromMetadata( aAtCmdBase, foundPos, ETrue, ETrue );
       
  2156     if ( found )
       
  2157         {
       
  2158         CArrayFixFlat<TATExtOneCmdSupport>* entries =
       
  2159             (*iSupportAux)[foundPos].iEntries;
       
  2160         TATExtSearchHelper searchHelper;
       
  2161         TInt i;
       
  2162         TInt count = entries->Count();
       
  2163         for ( i=0; i<count; i++ )
       
  2164             {
       
  2165             TATExtOneCmdSupport& entry = (*entries)[i];
       
  2166             AddNewMetadataEntryLinkL( support,
       
  2167                                       entry.iEntryIndex,
       
  2168                                       entry.iSupportType,
       
  2169                                       searchHelper );
       
  2170             }
       
  2171         }
       
  2172     // Now, as the normal data was inserted *before* the auxiliary data, the
       
  2173     // auxiliary data is in front of the created "support" array for each M, P
       
  2174     // and S entry. This insertion is faster than the other way around as there
       
  2175     // can be multiple S plugins for the same command but usually much less
       
  2176     // auxiliary entries for the same command.
       
  2177 #if defined(_DEBUG) && defined( PRJ_PRINT_SUPPORT_DATA )
       
  2178     PrintFoundEntries( support );
       
  2179 #endif
       
  2180     if ( support->Count() > 0 )
       
  2181         {
       
  2182         TRACE_FUNC_EXIT
       
  2183         return support;
       
  2184         }
       
  2185     TRACE_FUNC_EXIT
       
  2186     return NULL;
       
  2187     }
       
  2188 
       
  2189 // ---------------------------------------------------------------------------
       
  2190 // Instantiates plugin support
       
  2191 // ---------------------------------------------------------------------------
       
  2192 //
       
  2193 void CATExtMetadata::InstantiatePluginSupportL(
       
  2194     TATExtEntrySupport& aEntrySupport )
       
  2195     {
       
  2196     TRACE_FUNC_ENTRY
       
  2197     if ( aEntrySupport.iEntry )
       
  2198         {
       
  2199         InstantiatePluginL( *aEntrySupport.iEntry );
       
  2200         }
       
  2201     TRACE_FUNC_EXIT
       
  2202     }
       
  2203 
       
  2204 // ---------------------------------------------------------------------------
       
  2205 // Instantiates a plugin
       
  2206 // ---------------------------------------------------------------------------
       
  2207 //
       
  2208 void CATExtMetadata::InstantiatePluginL( TATExtPluginEntry& aPluginEntry )
       
  2209     {
       
  2210     TRACE_FUNC_ENTRY
       
  2211     if ( !aPluginEntry.iInstance )
       
  2212          {
       
  2213          TUid pluginUid = aPluginEntry.iPluginUid;
       
  2214          CATExtPluginBase* plugin = CATExtPluginBase::NewL( pluginUid,
       
  2215                                                             iObserver,
       
  2216                                                             iConnectionName );
       
  2217          plugin->ReportQuietModeChange( iQuietMode );
       
  2218          plugin->ReportVerboseModeChange( iVerboseMode );
       
  2219          plugin->ReportCharacterChange( ECharTypeCarriage, iCarriageReturn );
       
  2220          plugin->ReportCharacterChange( ECharTypeLineFeed, iLineFeed );
       
  2221          plugin->ReportCharacterChange( ECharTypeBackspace, iBackspace );
       
  2222          aPluginEntry.iInstance = plugin;
       
  2223          }
       
  2224     TRACE_FUNC_EXIT
       
  2225     }
       
  2226 
       
  2227 // ---------------------------------------------------------------------------
       
  2228 // Instantiates a plugin
       
  2229 // ---------------------------------------------------------------------------
       
  2230 //
       
  2231 TInt CATExtMetadata::InstantiatePlugin( TATExtPluginEntry& aPluginEntry )
       
  2232     {
       
  2233     TRACE_FUNC_ENTRY
       
  2234     TRAPD( retTrap, InstantiatePluginL(aPluginEntry) );
       
  2235     TRACE_FUNC_EXIT
       
  2236     return retTrap;
       
  2237     }
       
  2238 
       
  2239 // ---------------------------------------------------------------------------
       
  2240 // Handles an AT command support request
       
  2241 // ---------------------------------------------------------------------------
       
  2242 TBool CATExtMetadata::HandleCommandSupportL( TATExtEntrySupport& aEntrySupport,
       
  2243                                              const TDesC8* aAtCmdFull )
       
  2244     {
       
  2245     TRACE_FUNC_ENTRY
       
  2246     InstantiatePluginSupportL( aEntrySupport );
       
  2247     TBool supported = EFalse;
       
  2248     if ( aEntrySupport.iEntry->iLocked )
       
  2249         {
       
  2250         TRACE_FUNC_EXIT
       
  2251         User::Leave( KErrAccessDenied );
       
  2252         }
       
  2253     if ( !aAtCmdFull )
       
  2254         {
       
  2255         supported = aEntrySupport.iEntry->iInstance->IsCommandSupported(
       
  2256             aEntrySupport.iAtCmdFull );
       
  2257         }
       
  2258     else
       
  2259         {
       
  2260         supported = aEntrySupport.iEntry->iInstance->IsCommandSupported(
       
  2261             *aAtCmdFull );
       
  2262         }
       
  2263     TRACE_FUNC_EXIT
       
  2264     return supported;
       
  2265     }
       
  2266 
       
  2267 // ---------------------------------------------------------------------------
       
  2268 // Handles an AT command
       
  2269 // ---------------------------------------------------------------------------
       
  2270 void CATExtMetadata::HandleCommandL( TATExtEntrySupport& aEntrySupport,
       
  2271                                      TBool aReplyNeeded,
       
  2272                                      const TDesC8* aAtCmdFull )
       
  2273     {
       
  2274     TRACE_FUNC_ENTRY
       
  2275     if ( !aEntrySupport.iEntry || !aEntrySupport.iEntry->iInstance )
       
  2276         {
       
  2277         TRACE_FUNC_EXIT
       
  2278         User::Leave( KErrGeneral );
       
  2279         }
       
  2280     if ( aEntrySupport.iEntry->iLocked )
       
  2281         {
       
  2282         TRACE_FUNC_EXIT
       
  2283         User::Leave( KErrAccessDenied );
       
  2284         }
       
  2285     // As HandleCommand() could complete the message synchronously, set the
       
  2286     // iCmdData before the call
       
  2287     if ( aReplyNeeded )
       
  2288         {
       
  2289         iCmdData.iCmdStarted = ETrue;
       
  2290         iCmdData.iCmdMessage = aEntrySupport.iMessage;
       
  2291         iCmdData.iHandler = aEntrySupport.iEntry;
       
  2292         }
       
  2293     // No "else" here as HandleCommandL() is used also with secondary plugins
       
  2294     if ( !aAtCmdFull )
       
  2295         {
       
  2296         TRACE_INFO(( _L8("Handling command '%S' for UID:0x%08X, aReplyNeeded=%d..."), &iCmdData.iCmdBuffer, aEntrySupport.iEntry->iPluginUid, aReplyNeeded ));
       
  2297         aEntrySupport.iEntry->iInstance->HandleCommand(
       
  2298             iCmdData.iCmdBuffer,
       
  2299             iCmdData.iCmdReplyBuffer,
       
  2300             aReplyNeeded );
       
  2301         }
       
  2302     else
       
  2303         {
       
  2304         TRACE_INFO(( _L8("Handling command '%S' for UID:0x%08X, aReplyNeeded=%d..."), &(*aAtCmdFull), aEntrySupport.iEntry->iPluginUid, aReplyNeeded ));
       
  2305         aEntrySupport.iEntry->iInstance->HandleCommand(
       
  2306             *aAtCmdFull,
       
  2307             iCmdData.iCmdReplyBuffer,
       
  2308             aReplyNeeded );
       
  2309         }
       
  2310     TRACE_FUNC_EXIT
       
  2311     }
       
  2312 
       
  2313 // ---------------------------------------------------------------------------
       
  2314 // Sends an AT commands to multiple secondary plugins, starting from a given
       
  2315 // position.
       
  2316 // ---------------------------------------------------------------------------
       
  2317 //
       
  2318 void CATExtMetadata::SendToMultipleSecondaryL(
       
  2319     TATExtEntrySupport& aEntrySupport,
       
  2320     const TDesC8* aAtCmdFull )
       
  2321     {
       
  2322     TRACE_FUNC_ENTRY
       
  2323     if ( !aEntrySupport.iSupport )
       
  2324         {
       
  2325         TRACE_FUNC_EXIT
       
  2326         User::Leave( KErrGeneral );
       
  2327         }
       
  2328     TInt i;
       
  2329     TInt count = aEntrySupport.iSupport->Count();
       
  2330     for ( i=aEntrySupport.iStartIndex; i<count; i++ )
       
  2331         {
       
  2332         TATExtOneCmdSupport& oneCmdSupport = (*aEntrySupport.iSupport)[i];
       
  2333         if ( oneCmdSupport.iSupportType != ESupportTypeSecondary )
       
  2334             {
       
  2335             continue;
       
  2336             }
       
  2337         aEntrySupport.iEntry = &(*iPluginData)[i];
       
  2338         TBool supported = HandleCommandSupportL( aEntrySupport, aAtCmdFull );
       
  2339         if ( supported )
       
  2340             {
       
  2341             HandleCommandL( aEntrySupport, EFalse, aAtCmdFull );
       
  2342             }
       
  2343         }
       
  2344     TRACE_FUNC_EXIT
       
  2345     }
       
  2346 
       
  2347 // ---------------------------------------------------------------------------
       
  2348 // Finds the first secondary plugin support from a given starting position
       
  2349 // ---------------------------------------------------------------------------
       
  2350 //
       
  2351 TBool CATExtMetadata::FindFirstSecondarySupportL(
       
  2352     TATExtEntrySupport& aEntrySupport )
       
  2353     {
       
  2354     TRACE_FUNC_ENTRY
       
  2355     if ( !aEntrySupport.iSupport )
       
  2356         {
       
  2357         TRACE_FUNC_EXIT
       
  2358         User::Leave( KErrGeneral );
       
  2359         }
       
  2360     TInt i;
       
  2361     TInt count = aEntrySupport.iSupport->Count();
       
  2362     for ( i=aEntrySupport.iStartIndex; i<count; i++ )
       
  2363         {
       
  2364         TATExtOneCmdSupport& oneCmdSupport = (*aEntrySupport.iSupport)[i];
       
  2365         if ( oneCmdSupport.iSupportType != ESupportTypeSecondary )
       
  2366             {
       
  2367             continue;
       
  2368             }
       
  2369         aEntrySupport.iEntry = &(*iPluginData)[i];
       
  2370         TBool supported = HandleCommandSupportL( aEntrySupport );
       
  2371         if ( supported )
       
  2372             {
       
  2373             TRACE_FUNC_EXIT
       
  2374             return ETrue;
       
  2375             }
       
  2376         }
       
  2377     TRACE_FUNC_EXIT
       
  2378     return EFalse;
       
  2379     }
       
  2380 
       
  2381 // ---------------------------------------------------------------------------
       
  2382 // Extracts one NVRAM entry from a pipe-character delimited NVRAM buffer
       
  2383 // ---------------------------------------------------------------------------
       
  2384 //
       
  2385 TBool CATExtMetadata::ExtractNextNvramSetting( const TDesC8& aNvram,
       
  2386                                                TInt& aStartIndex,
       
  2387                                                TInt& aEndIndex )
       
  2388     {
       
  2389     TRACE_FUNC_ENTRY
       
  2390     // Skip data before command
       
  2391     TInt i;
       
  2392     TChar character;
       
  2393     TInt count = aNvram.Length();
       
  2394     for ( i=aEndIndex; i<count; i++ )
       
  2395         {
       
  2396         character = aNvram[i];
       
  2397         if ( character.IsPrint() && character!='|' )
       
  2398             {
       
  2399             break;
       
  2400             }
       
  2401         }
       
  2402     if ( i >= count )
       
  2403         {
       
  2404         TRACE_FUNC_EXIT
       
  2405         return EFalse;
       
  2406         }
       
  2407     aStartIndex = i;
       
  2408     // Start of command found, next mark the end
       
  2409     while ( i < count )
       
  2410         {
       
  2411         character = aNvram[i];
       
  2412         if ( !character.IsPrint() || character=='|' )
       
  2413             {
       
  2414             break;
       
  2415             }
       
  2416         i++;
       
  2417         }
       
  2418     aEndIndex = i;
       
  2419     if ( aEndIndex-aStartIndex <= 0 )
       
  2420         {
       
  2421         TRACE_FUNC_EXIT
       
  2422         return EFalse;
       
  2423         }
       
  2424     TRACE_FUNC_EXIT
       
  2425     return ETrue;
       
  2426     }
       
  2427 
       
  2428 // ---------------------------------------------------------------------------
       
  2429 // Gets the next command from support or auxiliary support data.
       
  2430 // ---------------------------------------------------------------------------
       
  2431 //
       
  2432 HBufC8* CATExtMetadata::GetNextSupportedCommand( TBool& aFirstSearch,
       
  2433                                                  TInt& aSupportFind,
       
  2434                                                  TBool& aFindInAux )
       
  2435     {
       
  2436     TRACE_FUNC_ENTRY
       
  2437     // If first search then start from index 0, othewise start from the
       
  2438     // next index
       
  2439     if ( aFirstSearch )
       
  2440         {
       
  2441         aSupportFind = -1;
       
  2442         aFindInAux = EFalse;
       
  2443         }
       
  2444     aSupportFind++;
       
  2445     aFirstSearch = EFalse;
       
  2446     CArrayFixFlat<TATExtAtCmdSupport>* support = iSupport;
       
  2447     if ( !aFindInAux )
       
  2448         {
       
  2449         if ( aSupportFind >= support->Count() )
       
  2450             {
       
  2451             aSupportFind = 0;
       
  2452             aFindInAux = ETrue;
       
  2453             support = iSupportAux;
       
  2454             if ( aSupportFind >= support->Count() )
       
  2455                 {
       
  2456                 TRACE_FUNC_EXIT
       
  2457                 return NULL;
       
  2458                 }
       
  2459             }
       
  2460         }
       
  2461     else
       
  2462         {
       
  2463         support = iSupportAux;
       
  2464         if ( aSupportFind >= support->Count() )
       
  2465             {
       
  2466             TRACE_FUNC_EXIT
       
  2467             return NULL;
       
  2468             }
       
  2469         }
       
  2470     TATExtAtCmdSupport& supportEntry = (*support)[aSupportFind];
       
  2471     HBufC8& atCmdBase = *supportEntry.iAtCmdBase;
       
  2472     HBufC8* newBuffer = HBufC8::NewMax( atCmdBase.Length() );
       
  2473     if ( newBuffer )
       
  2474         {
       
  2475         newBuffer->Des().Copy( atCmdBase );
       
  2476         }
       
  2477     TRACE_FUNC_EXIT
       
  2478     return newBuffer;
       
  2479     }
       
  2480 
       
  2481 // ---------------------------------------------------------------------------
       
  2482 // Reads an AT command from a client request message and creates buffer
       
  2483 // locally. For HandleCommand().
       
  2484 // ---------------------------------------------------------------------------
       
  2485 //
       
  2486 TInt CATExtMetadata::ReadCommandFromMessage( const RMessage2& aMessage )
       
  2487     {
       
  2488     TRACE_FUNC_ENTRY
       
  2489     // Read AT command from message, stop if error encountered
       
  2490     TInt desLength = aMessage.GetDesLength( EATExtHandleCmdParamCmd );
       
  2491     if ( desLength <= 0 )
       
  2492         {
       
  2493         TRACE_FUNC_EXIT
       
  2494         return KErrArgument;
       
  2495         }
       
  2496     TInt retTemp = iCmdData.iCmdBuffer.Create( desLength );
       
  2497     if ( retTemp != KErrNone )
       
  2498         {
       
  2499         TRACE_FUNC_EXIT
       
  2500         return retTemp;
       
  2501         }
       
  2502     retTemp = aMessage.Read( EATExtHandleCmdParamCmd, iCmdData.iCmdBuffer );
       
  2503     TRACE_INFO(( _L("Read returned %d"), retTemp ));
       
  2504     if ( retTemp != KErrNone )
       
  2505         {
       
  2506         iCmdData.iCmdBuffer.Close();
       
  2507         TRACE_FUNC_EXIT
       
  2508         return retTemp;
       
  2509         }
       
  2510     TRACE_FUNC_EXIT
       
  2511     return retTemp;
       
  2512     }
       
  2513 
       
  2514 // ---------------------------------------------------------------------------
       
  2515 // Creates a buffer with "ERROR" or "" string in it; needed for creating a
       
  2516 // reply to an unknown command (i.e. when no plugin supports the "base" part
       
  2517 // of a command) or to the case when plugin support exists but reply is not
       
  2518 // expected from them.
       
  2519 // ---------------------------------------------------------------------------
       
  2520 //
       
  2521 TInt CATExtMetadata::CreateEmptyOrErrorBuffer( RBuf8& aBuffer,
       
  2522                                                TBool aErrorReply )
       
  2523     {
       
  2524     TRACE_FUNC_ENTRY
       
  2525     // Note: The behavior of RBuf8 is awkward. It is not possible to query
       
  2526     // the "allocation status". Comparing the length to zero always returns
       
  2527     // true even if RBuf8::Create() was not called. Here we should do the
       
  2528     // following: If allocated and zero length, return with KErrNone. Otherwise
       
  2529     // if not allocated create the buffer and return with RBuf::Create()'s
       
  2530     // return code. We have to hack here so let's expect the buffer is not
       
  2531     // allocated when calling this function.
       
  2532     if ( !aErrorReply )
       
  2533         {
       
  2534         TInt retTemp = aBuffer.Create( KNullDesC8 );
       
  2535         TRACE_FUNC_EXIT
       
  2536         return retTemp;
       
  2537         }
       
  2538     TInt retVal = KErrNone;
       
  2539     TBuf8<KErrorMsgLen> errorBuffer;
       
  2540     if ( !iQuietMode )
       
  2541         {
       
  2542         if ( iVerboseMode )
       
  2543             {
       
  2544             _LIT8( KVerboseError, "ERROR" );
       
  2545             errorBuffer.Append( iCarriageReturn );
       
  2546             errorBuffer.Append( iLineFeed );
       
  2547             errorBuffer.Append( KVerboseError );
       
  2548             errorBuffer.Append( iCarriageReturn );
       
  2549             errorBuffer.Append( iLineFeed );
       
  2550             }
       
  2551         else
       
  2552             {
       
  2553             _LIT8( KNumericError, "4" );
       
  2554             errorBuffer.Append( KNumericError );
       
  2555             errorBuffer.Append( iCarriageReturn );
       
  2556             }
       
  2557         }
       
  2558     retVal = aBuffer.Create( errorBuffer );
       
  2559     TRACE_FUNC_EXIT
       
  2560     return retVal;
       
  2561     }
       
  2562 
       
  2563 // ---------------------------------------------------------------------------
       
  2564 // Writes specified input reply buffer to a client request message at given
       
  2565 // message slot number.
       
  2566 // ---------------------------------------------------------------------------
       
  2567 //
       
  2568 TInt CATExtMetadata::WriteReplyBufferToClient( const TDesC8& aBuffer,
       
  2569                                                TInt aDataSlot,
       
  2570                                                const RMessage2& aMessage,
       
  2571                                                TBool aReportNextLength,
       
  2572                                                TInt aLengthSlot )
       
  2573     {
       
  2574     TRACE_FUNC_ENTRY
       
  2575     TInt maxLength = aMessage.GetDesMaxLength( aDataSlot );
       
  2576     if ( aBuffer.Length() > maxLength )
       
  2577         {
       
  2578         TRACE_FUNC_EXIT
       
  2579         return KErrTooBig;
       
  2580         }
       
  2581     TInt retTemp = aMessage.Write( aDataSlot, aBuffer );
       
  2582     TRACE_INFO(( _L("First write returned %d"), retTemp ));
       
  2583     if ( retTemp != KErrNone )
       
  2584         {
       
  2585         TRACE_FUNC_EXIT
       
  2586         return retTemp;
       
  2587         }
       
  2588     if ( aReportNextLength && iCmdData.iHandler &&
       
  2589          iCmdData.iHandler->iInstance )  // optional
       
  2590         {
       
  2591         CATExtPluginBase& plugin = *iCmdData.iHandler->iInstance;
       
  2592         TInt nextPartLength = plugin.NextReplyPartLength();
       
  2593         if ( nextPartLength <= 0 )
       
  2594             {
       
  2595             iCmdData.iHandler = NULL;
       
  2596             }
       
  2597         TPckg<TInt> nextPartLengthPckg( nextPartLength );
       
  2598         retTemp = aMessage.Write( aLengthSlot, nextPartLengthPckg );
       
  2599         TRACE_INFO(( _L("Second write returned %d"), retTemp ));
       
  2600         if ( retTemp != KErrNone )
       
  2601             {
       
  2602             TRACE_FUNC_EXIT
       
  2603             return retTemp;
       
  2604             }
       
  2605         }
       
  2606     TRACE_FUNC_EXIT
       
  2607     return KErrNone;
       
  2608     }