localconnectivityservice/dun/atext/src/DunAtCmdHandler.cpp
branchRCL_3
changeset 38 3dcb815346df
parent 37 7e0ecb5b116a
equal deleted inserted replaced
37:7e0ecb5b116a 38:3dcb815346df
    21  *   Thus the ATEXT plugins don't need to check for case. The conversion to
    21  *   Thus the ATEXT plugins don't need to check for case. The conversion to
    22  *   upper case form stops when carriage return or '=' character is found.
    22  *   upper case form stops when carriage return or '=' character is found.
    23  */
    23  */
    24 
    24 
    25 /*
    25 /*
       
    26  * This file has the following functionality:
       
    27  * 1) Line buffer filler:
       
    28  *    AddDataForParsing(), ManagePartialCommand(), ExtractLineFromInputBuffer(),
       
    29  *    etc. This buffer is used for parsing. These functions are used for
       
    30  *    splitter-combiner logic described below. CDunAtCmdPusher is used
       
    31  *    separately for each element in the line buffer.
       
    32  * 2) Parser and splitter-combiner to handle the separater elements (subcommands)
       
    33  *    in the line buffer. When end of line is detected, iEndIndex is used to
       
    34  *    extract the next line in iInput to the line buffer (ManageEndOfCmdHandling()
       
    35  *    and ExtractLineFromInputBuffer()).
       
    36  * 3) When end of iEndIndex is found (ExtractLineFromInputBuffer()), more data
       
    37  *    is asked from CDunUpstream.
       
    38  * Note: There is separate handling for "one character input data" and "A/"
       
    39  * command handling which should be supported only for one line based data
       
    40  * (ManagePartialCommand()).
       
    41  */
       
    42 
       
    43 /*
    26  * The AT command handling is splitted to two parts on high level:
    44  * The AT command handling is splitted to two parts on high level:
    27  * 1) Splitter: splitting the sub-commands in a command line to multiple ones
    45  * 1) Splitter: splitting the sub-commands in a command line to multiple ones
    28  *    for ATEXT to process.
    46  *    for ATEXT to process.
    29  * 2) Combiner: combining the replies coming from ATEXT using a filter
    47  * 2) Combiner: combining the replies coming from ATEXT using a filter
    30  *    (the filter categories are explained in DunAtCmdPusher.cpp)
    48  *    (the filter categories are explained in DunAtCmdPusher.cpp)
       
    49  */
       
    50 
       
    51 /*
       
    52  * Note1: This file uses AT command parsing based on heuristics.
       
    53  * Refer to test specification if planning to change the heuristic.
       
    54  * Note2: Input buffer management (ExtractLineFromInputBuffer()) can be tested
       
    55  * with non-line based terminals such as HyperTerminal or Realterm.
    31  */
    56  */
    32 
    57 
    33 #include "DunAtCmdHandler.h"
    58 #include "DunAtCmdHandler.h"
    34 #include "DunAtUrcHandler.h"
    59 #include "DunAtUrcHandler.h"
    35 #include "DunDownstream.h"
    60 #include "DunDownstream.h"
   137     FTRACE(FPrint( _L("CDunAtCmdHandler::AddCmdModeCallback() complete" ) ));
   162     FTRACE(FPrint( _L("CDunAtCmdHandler::AddCmdModeCallback() complete" ) ));
   138     return KErrNone;
   163     return KErrNone;
   139     }
   164     }
   140 
   165 
   141 // ---------------------------------------------------------------------------
   166 // ---------------------------------------------------------------------------
   142 // Parses an AT command
   167 // Adds data for parsing and parses if necessary
   143 // ---------------------------------------------------------------------------
   168 // ---------------------------------------------------------------------------
   144 //
   169 //
   145 EXPORT_C TInt CDunAtCmdHandler::ParseCommand( TDesC8& aCommand,
   170 EXPORT_C TInt CDunAtCmdHandler::AddDataForParsing( TDesC8& aInput,
   146                                               TBool& aPartialInput )
   171                                                    TBool& aMoreNeeded )
   147     {
   172     {
   148     FTRACE(FPrint( _L("CDunAtCmdHandler::ParseCommand()") ));
   173     FTRACE(FPrint( _L("CDunAtCmdHandler::AddDataForParsing()") ));
   149     FTRACE(FPrint( _L("CDunAtCmdHandler::ParseCommand() received:") ));
   174     FTRACE(FPrint( _L("CDunAtCmdHandler::AddDataForParsing() received (%d bytes):"), aInput.Length() ));
   150     FTRACE(FPrintRaw(aCommand) );
   175     FTRACE(FPrintRaw(aInput) );
   151     TBool editorMode = iCmdPusher->EditorMode();
   176     TBool editorMode = iCmdPusher->EditorMode();
   152     if ( editorMode )
   177     if ( editorMode )
   153         {
   178         {
   154         // Note: return here with "no partial input" and some error to fool
   179         // Note: return here with "no more data needed" and some error to fool
   155         // CDunUpstream into not reissuing the read request.
   180         // CDunUpstream into not reissuing the read request.
   156         iCmdPusher->IssueRequest( aCommand, EFalse );
   181         iCmdPusher->IssueRequest( aInput, EFalse );
   157         aPartialInput = EFalse;
   182         aMoreNeeded = EFalse;
   158         return KErrGeneral;
   183         return KErrGeneral;
   159         }
   184         }
   160     iCommand = &aCommand;  // iCommand only for normal mode
   185     iInput = &aInput;  // iInput only for normal mode
   161     // Manage partial AT command
   186     // Manage partial AT command
   162     TBool needsCarriage = ETrue;
   187     TBool moreNeeded = ManagePartialCommand();
   163     TBool okToExit = ManagePartialCommand( aCommand, needsCarriage );
   188     if ( moreNeeded )
   164     if ( okToExit )
   189         {
   165         {
   190         aMoreNeeded = ETrue;
   166         FTRACE(FPrint( _L("CDunAtCmdHandler::ParseCommand() (ok to exit) complete") ));
   191         FTRACE(FPrint( _L("CDunAtCmdHandler::AddDataForParsing() (more partial) complete") ));
   167         aPartialInput = ETrue;
       
   168         return KErrNone;
   192         return KErrNone;
   169         }
   193         }
   170     if ( iHandleState != EDunStateIdle )
   194     if ( iHandleState != EDunStateIdle )
   171         {
   195         {
   172         aPartialInput = EFalse;
   196         aMoreNeeded = EFalse;
   173         ResetParseBuffers();
   197         ManageEndOfCmdHandling( EFalse, EFalse );
   174         FTRACE(FPrint( _L("CDunAtCmdHandler::ParseCommand() (not ready) complete") ));
   198         FTRACE(FPrint( _L("CDunAtCmdHandler::AddDataForParsing() (not ready) complete") ));
   175         return KErrNotReady;
   199         return KErrNotReady;
   176         }
   200         }
   177     TBool pushStarted = HandleASlashCommand();
   201     TBool pushStarted = HandleASlashCommand();
   178     if ( pushStarted )
   202     if ( pushStarted )
   179         {
   203         {
   180         // Note: return here with "partial input" status to fool CDunUpstream
   204         // Note: return here with "partial input" status to fool CDunUpstream
   181         // into reissuing the read request. The AT command has not really
   205         // into reissuing the read request. The AT command has not really
   182         // started yet so this is necessary.
   206         // started yet so this is necessary.
   183         aPartialInput = ETrue;
   207         aMoreNeeded = ETrue;
   184         ResetParseBuffers();
   208         ManageEndOfCmdHandling( EFalse, EFalse );
   185         FTRACE(FPrint( _L("CDunAtCmdHandler::ParseCommand() (A/) complete") ));
   209         FTRACE(FPrint( _L("CDunAtCmdHandler::AddDataForParsing() (A/) complete") ));
   186         return KErrNone;
   210         return KErrNone;
   187         }
   211         }
   188     FTRACE(FPrint( _L("CDunAtCmdHandler::ParseCommand() received total:") ));
       
   189     FTRACE(FPrintRaw(iInputBuffer) );
       
   190     iHandleState = EDunStateAtCmdHandling;
   212     iHandleState = EDunStateAtCmdHandling;
   191     iUpstream->NotifyAtCmdHandlingStart();
       
   192     iDecodeInfo.iFirstDecode = ETrue;
   213     iDecodeInfo.iFirstDecode = ETrue;
   193     iDecodeInfo.iDecodeIndex = 0;
   214     iDecodeInfo.iDecodeIndex = 0;
   194     HandleNextDecodedCommand();
   215     iDecodeInfo.iPrevExists = EFalse;
   195     FTRACE(FPrint( _L("CDunAtCmdHandler::ParseCommand() complete") ));
   216     iParseInfo.iLimit = KErrNotFound;
   196     aPartialInput = EFalse;
   217     iParseInfo.iSendBuffer.Zero();
       
   218     iEditorModeInfo.iContentFound = EFalse;
       
   219     HandleNextSubCommand();
       
   220     FTRACE(FPrint( _L("CDunAtCmdHandler::AddDataForParsing() complete") ));
       
   221     aMoreNeeded = EFalse;
   197     return KErrNone;
   222     return KErrNone;
   198     }
   223     }
   199 
   224 
   200 // ---------------------------------------------------------------------------
   225 // ---------------------------------------------------------------------------
   201 // Manages request to abort command handling
   226 // Manages request to abort command handling
   209     FTRACE(FPrint( _L("CDunAtCmdHandler::ManageAbortRequest() complete") ));
   234     FTRACE(FPrint( _L("CDunAtCmdHandler::ManageAbortRequest() complete") ));
   210     return retVal;
   235     return retVal;
   211     }
   236     }
   212 
   237 
   213 // ---------------------------------------------------------------------------
   238 // ---------------------------------------------------------------------------
   214 // Sets end of command line marker on for the possible series of AT commands.
       
   215 // ---------------------------------------------------------------------------
       
   216 //
       
   217 EXPORT_C void CDunAtCmdHandler::SetEndOfCmdLine( TBool aClearInput )
       
   218     {
       
   219     FTRACE(FPrint( _L("CDunAtCmdHandler::SetEndOfCmdLine()") ));
       
   220     ManageEndOfCmdHandling( EFalse, ETrue, aClearInput );
       
   221     FTRACE(FPrint( _L("CDunAtCmdHandler::SetEndOfCmdLine() complete") ));
       
   222     }
       
   223 
       
   224 // ---------------------------------------------------------------------------
       
   225 // Sends a character to be echoed
   239 // Sends a character to be echoed
   226 // ---------------------------------------------------------------------------
   240 // ---------------------------------------------------------------------------
   227 //
   241 //
   228 EXPORT_C TInt CDunAtCmdHandler::SendEchoCharacter( const TDesC8* aInput,
   242 EXPORT_C TInt CDunAtCmdHandler::SendEchoCharacter( const TDesC8* aInput,
   229                                                    MDunAtCmdEchoer* aCallback )
   243                                                    MDunAtCmdEchoer* aCallback )
   248         return KErrNotReady;
   262         return KErrNotReady;
   249         }
   263         }
   250     iCmdPusher->Stop();
   264     iCmdPusher->Stop();
   251     // The line below is used in the case when this function is called by
   265     // The line below is used in the case when this function is called by
   252     // CDunUpstream as a result of "data mode ON" change notification.
   266     // CDunUpstream as a result of "data mode ON" change notification.
   253     // In this case it is possible that HandleNextDecodedCommand() returns
   267     // In this case it is possible that HandleNextSubCommand() returns
   254     // without resetting the iInputBuffer because of the way it checks the
   268     // without resetting the iSendBuffer because of the way it checks the
   255     // iHandleState.
   269     // iHandleState.
   256     ManageEndOfCmdHandling( EFalse, ETrue, ETrue );
   270     ManageEndOfCmdHandling( ETrue, EFalse );
   257     FTRACE(FPrint( _L("CDunAtCmdHandler::Stop() complete") ));
   271     FTRACE(FPrint( _L("CDunAtCmdHandler::Stop() complete") ));
   258     return KErrNone;
   272     return KErrNone;
   259     }
   273     }
   260 
   274 
   261 // ---------------------------------------------------------------------------
   275 // ---------------------------------------------------------------------------
   372     // Don't initialize iConnectionName here (it is set through NewL)
   386     // Don't initialize iConnectionName here (it is set through NewL)
   373     iHandleState = EDunStateIdle;
   387     iHandleState = EDunStateIdle;
   374     iCarriageReturn = 0;
   388     iCarriageReturn = 0;
   375     iLineFeed = 0;
   389     iLineFeed = 0;
   376     iBackspace = 0;
   390     iBackspace = 0;
   377     iCommand = NULL;
   391     iInput = NULL;
   378     iDecodeInfo.iFirstDecode = ETrue;
   392     iDecodeInfo.iFirstDecode = ETrue;
   379     iDecodeInfo.iDecodeIndex = KErrNotFound;
   393     iDecodeInfo.iDecodeIndex = KErrNotFound;
   380     iDecodeInfo.iExtendedIndex = KErrNotFound;
   394     iDecodeInfo.iExtendedIndex = KErrNotFound;
   381     iDecodeInfo.iPrevChar = 0;
   395     iDecodeInfo.iPrevChar = 0;
   382     iDecodeInfo.iPrevExists = EFalse;
   396     iDecodeInfo.iPrevExists = EFalse;
   383     iDecodeInfo.iAssignFound = EFalse;
   397     iDecodeInfo.iAssignFound = EFalse;
   384     iDecodeInfo.iInQuotes = EFalse;
   398     iDecodeInfo.iInQuotes = EFalse;
   385     iDecodeInfo.iSpecialFound = EFalse;
   399     iDecodeInfo.iSpecialFound = EFalse;
       
   400     iDecodeInfo.iCmdsHandled = 0;
   386     iEditorModeInfo.iContentFound = EFalse;
   401     iEditorModeInfo.iContentFound = EFalse;
   387     iCmdPusher = NULL;
   402     iCmdPusher = NULL;
   388     iEcomListen = NULL;
   403     iEcomListen = NULL;
   389     iModeListen = NULL;
   404     iModeListen = NULL;
   390     iNvramListen = NULL;
   405     iNvramListen = NULL;
   433     FTRACE(FPrint( _L("CDunAtCmdHandler::CreateSpecialCommandsL()") ));
   448     FTRACE(FPrint( _L("CDunAtCmdHandler::CreateSpecialCommandsL()") ));
   434     TInt retTemp = KErrNone;
   449     TInt retTemp = KErrNone;
   435     TBool firstSearch = ETrue;
   450     TBool firstSearch = ETrue;
   436     for ( ;; )
   451     for ( ;; )
   437         {
   452         {
   438         retTemp = iAtCmdExt.GetNextSpecialCommand( iInputBuffer, firstSearch );
   453         // Let's borrow iLineBuffer for this purpose
       
   454         retTemp = iAtCmdExt.GetNextSpecialCommand( iLineBuffer, firstSearch );
   439         if ( retTemp != KErrNone )
   455         if ( retTemp != KErrNone )
   440             {
   456             {
   441             break;
   457             break;
   442             }
   458             }
   443         HBufC8* specialCmd = HBufC8::NewMaxLC( iInputBuffer.Length() );
   459         TInt lineLength = iLineBuffer.Length();
   444         TPtr8 specialCmdPtr = specialCmd->Des();
   460         HBufC8* specialCmd = HBufC8::NewMaxLC( lineLength );
   445         specialCmdPtr.Copy( iInputBuffer );
   461         *specialCmd = iLineBuffer;
   446         specialCmdPtr.UpperCase();
       
   447         iSpecials.AppendL( specialCmd );
   462         iSpecials.AppendL( specialCmd );
   448         CleanupStack::Pop( specialCmd );
   463         CleanupStack::Pop( specialCmd );
   449         }
   464         }
   450     iInputBuffer.Zero();
   465     iLineBuffer.Zero();
   451     FTRACE(FPrint( _L("CDunAtCmdHandler::CreateSpecialCommandsL() complete") ));
   466     FTRACE(FPrint( _L("CDunAtCmdHandler::CreateSpecialCommandsL() complete") ));
   452     }
   467     }
   453 
   468 
   454 // ---------------------------------------------------------------------------
   469 // ---------------------------------------------------------------------------
   455 // Recreates special command data.
   470 // Recreates special command data.
   510 // ---------------------------------------------------------------------------
   525 // ---------------------------------------------------------------------------
   511 //
   526 //
   512 TBool CDunAtCmdHandler::RegenerateOkReply()
   527 TBool CDunAtCmdHandler::RegenerateOkReply()
   513     {
   528     {
   514     FTRACE(FPrint( _L("CDunAtCmdHandler::RegenerateOkReply()") ));
   529     FTRACE(FPrint( _L("CDunAtCmdHandler::RegenerateOkReply()") ));
       
   530     if ( iDownstream->IsDataInQueue(&iOkBuffer) )
       
   531         {
       
   532         FTRACE(FPrint( _L("CDunAtCmdHandler::RegenerateOkReply() (in queue!) complete") ));
       
   533         return iQuietOn;
       
   534         }
   515     iOkBuffer.Zero();
   535     iOkBuffer.Zero();
   516     if ( iQuietOn )
   536     if ( iQuietOn )
   517         {
   537         {
   518         FTRACE(FPrint( _L("CDunAtCmdHandler::RegenerateOkReply() (quiet) complete") ));
   538         FTRACE(FPrint( _L("CDunAtCmdHandler::RegenerateOkReply() (quiet) complete") ));
   519         return ETrue;
   539         return ETrue;
   542 // ---------------------------------------------------------------------------
   562 // ---------------------------------------------------------------------------
   543 //
   563 //
   544 TBool CDunAtCmdHandler::RegenerateErrorReply()
   564 TBool CDunAtCmdHandler::RegenerateErrorReply()
   545     {
   565     {
   546     FTRACE(FPrint( _L("CDunAtCmdHandler::RegenerateErrorReply()") ));
   566     FTRACE(FPrint( _L("CDunAtCmdHandler::RegenerateErrorReply()") ));
       
   567     if ( iDownstream->IsDataInQueue(&iErrorBuffer) )
       
   568         {
       
   569         FTRACE(FPrint( _L("CDunAtCmdHandler::RegenerateErrorReply() (in queue!) complete") ));
       
   570         return iQuietOn;
       
   571         }
   547     iErrorBuffer.Zero();
   572     iErrorBuffer.Zero();
   548     if ( iQuietOn )
   573     if ( iQuietOn )
   549         {
   574         {
   550         FTRACE(FPrint( _L("CDunAtCmdHandler::RegenerateErrorReply() (quiet) complete") ));
   575         FTRACE(FPrint( _L("CDunAtCmdHandler::RegenerateErrorReply() (quiet) complete") ));
   551         return ETrue;
   576         return ETrue;
   632 
   657 
   633 // ---------------------------------------------------------------------------
   658 // ---------------------------------------------------------------------------
   634 // Manages partial AT command
   659 // Manages partial AT command
   635 // ---------------------------------------------------------------------------
   660 // ---------------------------------------------------------------------------
   636 //
   661 //
   637 TBool CDunAtCmdHandler::ManagePartialCommand( TDesC8& aCommand,
   662 TBool CDunAtCmdHandler::ManagePartialCommand()
   638                                               TBool& aNeedsCarriage )
       
   639     {
   663     {
   640     FTRACE(FPrint( _L("CDunAtCmdHandler::ManagePartialCommand()") ));
   664     FTRACE(FPrint( _L("CDunAtCmdHandler::ManagePartialCommand()") ));
   641     aNeedsCarriage = ETrue;
       
   642     // Check length of command
       
   643     if ( aCommand.Length() == 0 )
       
   644         {
       
   645         FTRACE(FPrint( _L("CDunAtCmdHandler::ManagePartialCommand() (length zero) complete") ));
       
   646         return ETrue;
       
   647         }
       
   648     // Check one character (or unit) based input data
   665     // Check one character (or unit) based input data
   649     if ( aCommand.Length() == KDunChSetMaxCharLen )
   666     if ( iInput->Length() == KDunChSetMaxCharLen )
   650         {
   667         {
   651         EchoCommand( aCommand );
   668         EchoCommand();
   652         // Handle backspace and cancel characters
   669         // Handle backspace and cancel characters
   653         TBool found = HandleSpecialCharacters( aCommand );
   670         TBool found = HandleSpecialCharacters();
   654         if ( found )
   671         if ( found )
   655             {
   672             {
   656             FTRACE(FPrint( _L("CDunAtCmdHandler::ManagePartialCommand() (special) complete") ));
   673             FTRACE(FPrint( _L("CDunAtCmdHandler::ManagePartialCommand() (special) complete") ));
   657             return ETrue;
   674             return ETrue;
   658             }
   675             }
   659         }
   676         }
   660     TBool endFound = EFalse;
   677     TBool moreNeeded = ExtractLineFromInputBuffer();
   661     TBool overflow = AppendCommandToInputBuffer( aCommand, endFound );
   678     if ( moreNeeded )
   662     if ( overflow )
   679         {
   663         {
   680         // More data is not needed with "A/" (no carriage return), check that
   664         // Overflow occurred so return ETrue (consumed) to skip all the rest
   681         // special case here, otherwise continue processing
   665         // characters until carriage return is found
   682         if ( !IsASlashCommand() )
   666         FTRACE(FPrint( _L("CDunAtCmdHandler::ManagePartialCommand() (overflow) complete") ));
   683             {
   667         return ETrue;
   684             FTRACE(FPrint( _L("CDunAtCmdHandler::ManagePartialCommand() (more) complete") ));
       
   685             return ETrue;
       
   686             }
   668         }
   687         }
   669     // If something went wrong, do nothing (return consumed)
   688     // If something went wrong, do nothing (return consumed)
   670     if ( iInputBuffer.Length() <= 0 )
   689     if ( iLineBuffer.Length() <= 0 )
   671         {
   690         {
   672         FTRACE(FPrint( _L("CDunAtCmdHandler::ManagePartialCommand() (length) complete") ));
   691         FTRACE(FPrint( _L("CDunAtCmdHandler::ManagePartialCommand() (length) complete") ));
   673         return ETrue;
   692         return ETrue;
   674         }
   693         }
   675     // If "A/", no carriage return is needed, check that now
   694     // For other commands, just return with consumed
   676     if ( IsASlashCommand() )
       
   677         {
       
   678         aNeedsCarriage = EFalse;
       
   679         FTRACE(FPrint( _L("CDunAtCmdHandler::ManagePartialCommand() (A/) complete") ));
       
   680         return EFalse;
       
   681         }
       
   682     // For other commands and if no end, just return with consumed
       
   683     if ( !endFound )
       
   684         {
       
   685         FTRACE(FPrint( _L("CDunAtCmdHandler::ManagePartialCommand() (void) complete") ));
       
   686         return ETrue;
       
   687         }
       
   688     FTRACE(FPrint( _L("CDunAtCmdHandler::ManagePartialCommand() complete") ));
   695     FTRACE(FPrint( _L("CDunAtCmdHandler::ManagePartialCommand() complete") ));
   689     return EFalse;
   696     return EFalse;
   690     }
   697     }
   691 
   698 
   692 // ---------------------------------------------------------------------------
   699 // ---------------------------------------------------------------------------
   693 // Echoes a command if echo is on
   700 // Echoes a command if echo is on
   694 // ---------------------------------------------------------------------------
   701 // ---------------------------------------------------------------------------
   695 //
   702 //
   696 TBool CDunAtCmdHandler::EchoCommand( TDesC8& aDes )
   703 TBool CDunAtCmdHandler::EchoCommand()
   697     {
   704     {
   698     FTRACE(FPrint( _L("CDunAtCmdHandler::EchoCommand()") ));
   705     FTRACE(FPrint( _L("CDunAtCmdHandler::EchoCommand()") ));
   699     if ( aDes.Length() > KDunChSetMaxCharLen )
   706     if ( iInput->Length() > KDunChSetMaxCharLen )
   700         {
   707         {
   701         FTRACE(FPrint( _L("CDunAtCmdHandler::EchoCommand() (wrong length) complete") ));
   708         FTRACE(FPrint( _L("CDunAtCmdHandler::EchoCommand() (wrong length) complete") ));
   702         return EFalse;
   709         return EFalse;
   703         }
   710         }
   704     if ( iEchoOn )
   711     if ( iEchoOn )
   705         {
   712         {
   706         iEchoBuffer.Copy( aDes );
   713         if ( iDownstream->IsDataInQueue(&iEchoBuffer) )
       
   714             {
       
   715             FTRACE(FPrint( _L("CDunAtCmdHandler::EchoCommand() (in queue!) complete") ));
       
   716             return EFalse;
       
   717             }
       
   718         iEchoBuffer.Copy( *iInput );
   707         iDownstream->NotifyDataPushRequest( &iEchoBuffer, NULL );
   719         iDownstream->NotifyDataPushRequest( &iEchoBuffer, NULL );
   708         FTRACE(FPrint( _L("CDunAtCmdHandler::EchoCommand() complete") ));
   720         FTRACE(FPrint( _L("CDunAtCmdHandler::EchoCommand() complete") ));
   709         return ETrue;
   721         return ETrue;
   710         }
   722         }
   711     FTRACE(FPrint( _L("CDunAtCmdHandler::EchoCommand() (not started) complete") ));
   723     FTRACE(FPrint( _L("CDunAtCmdHandler::EchoCommand() (not started) complete") ));
   714 
   726 
   715 // ---------------------------------------------------------------------------
   727 // ---------------------------------------------------------------------------
   716 // Handles backspace and cancel characters
   728 // Handles backspace and cancel characters
   717 // ---------------------------------------------------------------------------
   729 // ---------------------------------------------------------------------------
   718 //
   730 //
   719 TBool CDunAtCmdHandler::HandleSpecialCharacters( TDesC8& aCommand )
   731 TBool CDunAtCmdHandler::HandleSpecialCharacters()
   720     {
   732     {
   721     FTRACE(FPrint( _L("CDunAtCmdHandler::HandleSpecialCharacters()") ));
   733     FTRACE(FPrint( _L("CDunAtCmdHandler::HandleSpecialCharacters()") ));
   722     if ( aCommand.Length() != KDunChSetMaxCharLen )
   734     if ( iInput->Length() != KDunChSetMaxCharLen )
   723         {
   735         {
   724         FTRACE(FPrint( _L("CDunAtCmdHandler::HandleSpecialCharacters() (wrong length) complete") ));
   736         FTRACE(FPrint( _L("CDunAtCmdHandler::HandleSpecialCharacters() (wrong length) complete") ));
   725         return EFalse;
   737         return EFalse;
   726         }
   738         }
   727     if ( aCommand[0] == iBackspace )
   739     if ( (*iInput)[0] == iBackspace )
   728         {
   740         {
   729         TInt bufferLength = iInputBuffer.Length();
   741         TInt lineLength = iLineBuffer.Length();
   730         if ( bufferLength > 0 )
   742         if ( lineLength > 0 )
   731             {
   743             {
   732             iInputBuffer.SetLength( bufferLength-1 );
   744             iLineBuffer.SetLength( lineLength-1 );
   733             }
   745             }
   734         FTRACE(FPrint( _L("CDunAtCmdHandler::HandleSpecialCharacters() (backspace) complete") ));
   746         FTRACE(FPrint( _L("CDunAtCmdHandler::HandleSpecialCharacters() (backspace) complete") ));
   735         return ETrue;
   747         return ETrue;
   736         }
   748         }
   737     if ( aCommand[0] == KDunCancel )
   749     if ( (*iInput)[0] == KDunCancel )
   738         {
   750         {
   739         ResetParseBuffers();  // More processing here?
   751         ManageEndOfCmdHandling( EFalse, EFalse );
   740         FTRACE(FPrint( _L("CDunAtCmdHandler::HandleSpecialCharacters() (cancel) complete") ));
   752         FTRACE(FPrint( _L("CDunAtCmdHandler::HandleSpecialCharacters() (cancel) complete") ));
   741         return ETrue;
   753         return ETrue;
   742         }
   754         }
   743     FTRACE(FPrint( _L("CDunAtCmdHandler::HandleSpecialCharacters() complete") ));
   755     FTRACE(FPrint( _L("CDunAtCmdHandler::HandleSpecialCharacters() complete") ));
   744     return EFalse;
   756     return EFalse;
   745     }
   757     }
   746 
   758 
   747 // ---------------------------------------------------------------------------
   759 // ---------------------------------------------------------------------------
   748 // Appends command to parse buffer
   760 // Extracts line from input buffer to line buffer
   749 // ---------------------------------------------------------------------------
   761 // ---------------------------------------------------------------------------
   750 //
   762 //
   751 TBool CDunAtCmdHandler::AppendCommandToInputBuffer( TDesC8& aCommand,
   763 TBool CDunAtCmdHandler::ExtractLineFromInputBuffer()
   752                                                     TBool& aEndFound )
   764     {
   753     {
   765     FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractLineFromInputBuffer()") ));
   754     FTRACE(FPrint( _L("CDunAtCmdHandler::AppendCommandToInputBuffer()") ));
   766     FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractLineFromInputBuffer() before (%d bytes):"), iLineBuffer.Length() ));
   755     aEndFound = EFalse;
   767     FTRACE(FPrintRaw(iLineBuffer) );
   756     TInt cmdBufIndex = 0;
   768     // Case1: If no data in iLineBuffer and end-of-line character in iInputBuffer[start]:
   757     TInt cmdBufLim = aCommand.Length();
   769     //     - Skip end-of-line characters, find start-of-line condition, find end-of-line character
   758     while ( cmdBufIndex < cmdBufLim )
   770     //     - If partial line found (start-of-line condition and no end-of-line character):
   759         {
   771     //           - Save partial line to iLineBuffer
   760         if ( iInputBuffer.Length() == iInputBuffer.MaxLength() )
   772     //           - Set iEndIndex to end of iInputBuffer
   761             {
   773     //     - If full line found (start-of-line condition and end-of-line character):
   762             // 1) If output is full and end found from input
   774     //           - Save full line to iLineBuffer
   763             //    -> reset buffers and overflow found
   775     //           - Skip multiple end-of-line characters until next start-of-line
   764             // 2) If output is full and end not found from input
   776     //             condition or end of iInputBuffer -> save this position to iEndIndex
   765             //    -> don't reset buffers and overflow found
   777     // Case2: If no data in iLineBuffer and non-end-of-line character in iInputBuffer[start]:
   766             TInt foundIndex = FindEndOfCommand( aCommand );
   778     //     - Find end-of-line character
   767             if ( foundIndex >= 0 )
   779     //     - If partial line found (no end-of-line character):
   768                 {
   780     //           - Save partial line to iLineBuffer
   769                 aEndFound = ETrue;
   781     //           - Set iEndIndex to end of iLineBuffer
   770                 ResetParseBuffers();
   782     //     - If full line found (end-of-line character):
   771                 FTRACE(FPrint( _L("CDunAtCmdHandler::AppendCommandToInputBuffer() (reset) complete") ));
   783     //           - Save full line to iLineBuffer
   772                 }
   784     //           - Skip multiple end-of-line characters until next start-of-line
   773             FTRACE(FPrint( _L("CDunAtCmdHandler::AppendCommandToInputBuffer() (overflow) complete") ));
   785     //             condition or end of iInputBuffer -> save this position to iEndIndex
       
   786     // Case3: If data in iLineBuffer and end-of-line character in iInputBuffer[start]:
       
   787     //     - Skip end-of-line characters
       
   788     //     - Keep string currently in iLineBuffer
       
   789     //     - Skip end-of-line characters until non-end-of-line or end of
       
   790     //       iInputBuffer -> save this position to iEndIndex
       
   791     // Case4: If data in iLineBuffer and non-end-of-line character in iInputBuffer[start]:
       
   792     //     - Processed the same way as Case1, however "Skip end-of-line characters" does
       
   793     //       not have any effect
       
   794     if ( iInput->Length() <= 0 )
       
   795         {
       
   796         FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractLineFromInputBuffer() (wrong length) complete") ));
       
   797         return ETrue;
       
   798         }
       
   799     TBool moreNeeded = ETrue;
       
   800     TBool copyNeeded = EFalse;
       
   801     TInt copyLength = KErrNotFound;
       
   802     TInt lineLength = iLineBuffer.Length();
       
   803     TInt lineMaxLength = iLineBuffer.MaxLength();
       
   804     TInt freeLineSpace = lineMaxLength - lineLength;
       
   805     TInt inputLength = iInput->Length();
       
   806     TInt startIndex = ( iEndIndex>=0 ) ? iEndIndex : 0;
       
   807     if ( startIndex >= inputLength )
       
   808         {
       
   809         iEndIndex = KErrNotFound;
       
   810         FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractLineFromInputBuffer() (input end) complete") ));
       
   811         return ETrue;
       
   812         }
       
   813     // Cases here:
       
   814     // Case1: If no data in iLineBuffer and end-of-line character in iInputBuffer[start]
       
   815     // Case2: If no data in iLineBuffer and non-end-of-line character in iInputBuffer[start]
       
   816     // Case3: If data in iLineBuffer and end-of-line character in iInputBuffer[start]
       
   817     // Case4: If data in iLineBuffer and non-end-of-line character in iInputBuffer[start]
       
   818     // Summary: Cases 1, 2 and 4 can be combined. Case 3 needs a separate check.
       
   819     TChar character = (*iInput)[startIndex];
       
   820     TBool endOfLine = IsEndOfLine(character);
       
   821     if ( lineLength>0 && endOfLine )
       
   822         {
       
   823         moreNeeded = HandleSpecialBufferManagement( startIndex,
       
   824                                                     copyLength,
       
   825                                                     copyNeeded );
       
   826         }
       
   827     else
       
   828         {
       
   829         moreNeeded = HandleGenericBufferManagement( startIndex,
       
   830                                                     copyLength,
       
   831                                                     copyNeeded );
       
   832         }
       
   833     if ( copyNeeded && copyLength>0 )
       
   834         {
       
   835         // Check the case copyLength does not fit to iLineBuffer
       
   836         // This case should be handled by returning "more data needed"
       
   837         // Also reset the iLineBuffer to ensure the handling doesn't stuck
       
   838         // for rest of the commands (usability case)
       
   839         if ( copyLength > freeLineSpace )
       
   840             {
       
   841             iLineBuffer.Zero();
       
   842             iEndIndex = KErrNotFound;
       
   843             FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractLineFromInputBuffer() after (%d bytes):"), iLineBuffer.Length() ));
       
   844             FTRACE(FPrintRaw(iLineBuffer) );
       
   845             FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractLineFromInputBuffer() (overflow) complete") ));
   774             return ETrue;
   846             return ETrue;
   775             }
   847             }
   776         TChar character = aCommand[cmdBufIndex];
   848         iLineBuffer.Append( &(*iInput)[startIndex], copyLength );
   777         if ( IsEndOfCommand(character) )
   849         FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractLineFromInputBuffer() after (%d bytes):"), iLineBuffer.Length() ));
   778             {
   850         FTRACE(FPrintRaw(iLineBuffer) );
   779             aEndFound = ETrue;
   851         }
   780             iEndIndex = cmdBufIndex;
   852     if ( moreNeeded )
       
   853         {
       
   854         iEndIndex = KErrNotFound;
       
   855         FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractLineFromInputBuffer() (more needed) complete") ));
       
   856         return ETrue;
       
   857         }
       
   858     FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractLineFromInputBuffer() (line found) complete") ));
       
   859     return EFalse;
       
   860     }
       
   861 
       
   862 // ---------------------------------------------------------------------------
       
   863 // Handles generic buffer management
       
   864 // (explanation in ExtractLineFromInputBuffer())
       
   865 // ---------------------------------------------------------------------------
       
   866 //
       
   867 TBool CDunAtCmdHandler::HandleGenericBufferManagement( TInt& aStartIndex,
       
   868                                                        TInt& aCopyLength,
       
   869                                                        TBool& aCopyNeeded )
       
   870     {
       
   871     FTRACE(FPrint( _L("CDunAtCmdHandler::HandleGenericBufferManagement()") ));
       
   872     TInt inputLength = iInput->Length();
       
   873     TInt currentIndex = SkipEndOfLineCharacters( aStartIndex );
       
   874     if ( currentIndex >= inputLength )
       
   875         {
       
   876         // No data in iLineBuffer and only end-of-lines in new buffer
       
   877         // return with "need more data"
       
   878         iEndIndex = inputLength;
       
   879         aCopyLength = 0;
       
   880         aCopyNeeded = EFalse;
       
   881         FTRACE(FPrint( _L("CDunAtCmdHandler::HandleGenericBufferManagement() (new end for old no data) complete") ));
       
   882         return ETrue;
       
   883         }
       
   884     // No data in iLineBuffer and non-end-of-line character found
       
   885     // Try to find the first start-of-line condition
       
   886     TInt lineLength = iLineBuffer.Length();
       
   887     if ( lineLength == 0 )
       
   888         {
       
   889         currentIndex = SkipSubCommandDelimiterCharacters( aStartIndex );
       
   890         if ( currentIndex >= inputLength )
       
   891             {
       
   892             // No data in iLineBuffer and only end-of-lines+delimiter in new buffer
       
   893             // return with "need more data"
       
   894             iEndIndex = inputLength;
       
   895             aCopyLength = 0;
       
   896             aCopyNeeded = EFalse;
       
   897             FTRACE(FPrint( _L("CDunAtCmdHandler::HandleGenericBufferManagement() (new end+delim for old no data) complete") ));
       
   898             return ETrue;
       
   899             }
       
   900         }
       
   901     aStartIndex = currentIndex;
       
   902     // No data in iLineBuffer and other than end-of-line or delimiter character found
       
   903     // Variable currentIndex is now the start of new command
       
   904     // Next try to find the end of the command
       
   905     TInt endIndex = FindEndOfLine( aStartIndex );
       
   906     if ( endIndex >= inputLength )
       
   907         {
       
   908         // No data in iLineBuffer and start of command found without end
       
   909         // return with "need more data"
       
   910         iEndIndex = inputLength;
       
   911         aCopyLength = inputLength - aStartIndex;
       
   912         aCopyNeeded = ETrue;
       
   913         FTRACE(FPrint( _L("CDunAtCmdHandler::HandleGenericBufferManagement() (start but no end for old no data) complete") ));
       
   914         return ETrue;
       
   915         }
       
   916     // No data in iLineBuffer and end-of-line character found
       
   917     // Try to skip possible multiple end-of-line characters
       
   918     currentIndex = SkipEndOfLineCharacters( endIndex );
       
   919     // Variable currentIndex is now either start of next command or end of iInput
       
   920     // Note that this requires that Case 2 must skip the possible IsDelimiterCharacter()s
       
   921     iEndIndex = currentIndex;
       
   922     aCopyLength = endIndex - aStartIndex;
       
   923     aCopyNeeded = ETrue;
       
   924     FTRACE(FPrint( _L("CDunAtCmdHandler::HandleGenericBufferManagement() (line found) complete") ));
       
   925     return EFalse;
       
   926     }
       
   927 
       
   928 // ---------------------------------------------------------------------------
       
   929 // Handles special buffer management
       
   930 // (explanation in ExtractLineFromInputBuffer())
       
   931 // ---------------------------------------------------------------------------
       
   932 //
       
   933 TBool CDunAtCmdHandler::HandleSpecialBufferManagement( TInt aStartIndex,
       
   934                                                        TInt& aCopyLength,
       
   935                                                        TBool& aCopyNeeded )
       
   936     {
       
   937     FTRACE(FPrint( _L("CDunAtCmdHandler::HandleSpecialBufferManagement()") ));
       
   938     TInt currentIndex = SkipEndOfLineCharacters( aStartIndex );
       
   939     // Variable currentIndex is now either start of next command or end of iInput
       
   940     iEndIndex = currentIndex;
       
   941     aCopyLength = 0;
       
   942     aCopyNeeded = EFalse;
       
   943     FTRACE(FPrint( _L("CDunAtCmdHandler::HandleSpecialBufferManagement() complete") ));
       
   944     return EFalse;
       
   945     }
       
   946 
       
   947 // ---------------------------------------------------------------------------
       
   948 // Skips end-of-line characters
       
   949 // ---------------------------------------------------------------------------
       
   950 //
       
   951 TInt CDunAtCmdHandler::SkipEndOfLineCharacters( TInt aStartIndex )
       
   952     {
       
   953     FTRACE(FPrint( _L("CDunAtCmdHandler::SkipEndOfLineCharacters()") ));
       
   954     TInt foundIndex = iInput->Length();
       
   955     TInt inputLength = foundIndex;
       
   956     for ( TInt i=aStartIndex; i<inputLength; i++ )
       
   957         {
       
   958         TChar character = (*iInput)[i];
       
   959         if ( !IsEndOfLine(character) )
       
   960             {
       
   961             foundIndex = i;
   781             break;
   962             break;
   782             }
   963             }
   783         iInputBuffer.Append( aCommand[cmdBufIndex] );
   964         }
   784         cmdBufIndex++;
   965     FTRACE(FPrint( _L("CDunAtCmdHandler::SkipEndOfLineCharacters() complete") ));
   785         }
   966     return foundIndex;
   786     FTRACE(FPrint( _L("CDunAtCmdHandler::AppendCommandToInputBuffer() complete") ));
   967     }
   787     return EFalse;
   968 
   788     }
   969 // ---------------------------------------------------------------------------
   789 
   970 // Skips subcommand delimiter characters
   790 // ---------------------------------------------------------------------------
   971 // ---------------------------------------------------------------------------
   791 // Handles next decoded command from input buffer
   972 //
   792 // ---------------------------------------------------------------------------
   973 TInt CDunAtCmdHandler::SkipSubCommandDelimiterCharacters( TInt aStartIndex )
   793 //
   974     {
   794 TBool CDunAtCmdHandler::HandleNextDecodedCommand()
   975     FTRACE(FPrint( _L("CDunAtCmdHandler::SkipSubCommandDelimiterCharacters()") ));
   795     {
   976     TInt inputLength = iInput->Length();
   796     FTRACE(FPrint( _L("CDunAtCmdHandler::HandleNextDecodedCommand()") ));
   977     TInt foundIndex = inputLength;
       
   978     for ( TInt i=aStartIndex; i<inputLength; i++ )
       
   979         {
       
   980         TChar character = (*iInput)[i];
       
   981         if ( !IsDelimiterCharacter(character) )
       
   982             {
       
   983             foundIndex = i;
       
   984             break;
       
   985             }
       
   986         }
       
   987     FTRACE(FPrint( _L("CDunAtCmdHandler::SkipSubCommandDelimiterCharacters() complete") ));
       
   988     return foundIndex;
       
   989     }
       
   990 
       
   991 // ---------------------------------------------------------------------------
       
   992 // Finds the end of the line
       
   993 // ---------------------------------------------------------------------------
       
   994 //
       
   995 TInt CDunAtCmdHandler::FindEndOfLine( TInt aStartIndex )
       
   996     {
       
   997     FTRACE(FPrint( _L("CDunAtCmdHandler::FindEndOfLine()") ));
       
   998     TInt inputLength = iInput->Length();
       
   999     TInt foundIndex = inputLength;
       
  1000     for ( TInt i=aStartIndex; i<inputLength; i++ )
       
  1001         {
       
  1002         TChar character = (*iInput)[i];
       
  1003         // Checking for IsDelimiterCharacter() here needs more logic (a parser).
       
  1004         // Just check with "IsEndOfLine()"
       
  1005         if ( IsEndOfLine(character) )
       
  1006             {
       
  1007             foundIndex = i;
       
  1008             break;
       
  1009             }
       
  1010         }
       
  1011     FTRACE(FPrint( _L("CDunAtCmdHandler::FindEndOfLine() complete") ));
       
  1012     return foundIndex;
       
  1013     }
       
  1014 
       
  1015 // ---------------------------------------------------------------------------
       
  1016 // Handles next subcommand from line buffer
       
  1017 // ---------------------------------------------------------------------------
       
  1018 //
       
  1019 TBool CDunAtCmdHandler::HandleNextSubCommand()
       
  1020     {
       
  1021     FTRACE(FPrint( _L("CDunAtCmdHandler::HandleNextSubCommand()") ));
   797     if ( iHandleState != EDunStateAtCmdHandling )
  1022     if ( iHandleState != EDunStateAtCmdHandling )
   798         {
  1023         {
   799         FTRACE(FPrint( _L("CDunAtCmdHandler::HandleNextDecodedCommand() (not ready) complete") ));
  1024         FTRACE(FPrint( _L("CDunAtCmdHandler::HandleNextSubCommand() (not ready) complete") ));
   800         return ETrue;
  1025         return EFalse;
   801         }
  1026         }
   802     TBool extracted = ExtractNextDecodedCommand();
  1027     TBool extracted = ExtractNextSubCommand();
   803     if ( !extracted )
  1028     if ( !extracted )
   804         {
  1029         {
   805         ManageEndOfCmdHandling( ETrue, ETrue, ETrue );
  1030         ManageEndOfCmdHandling( ETrue, ETrue );
   806         FTRACE(FPrint( _L("CDunAtCmdHandler::HandleNextDecodedCommand() (last) complete") ));
  1031         FTRACE(FPrint( _L("CDunAtCmdHandler::HandleNextSubCommand() (last) complete") ));
   807         return ETrue;
  1032         return EFalse;
   808         }
  1033         }
   809     // Next convert the decoded AT command to uppercase
  1034     // Next convert the decoded AT command to uppercase
   810     // Don't check for case status -> let mixed cases pass
  1035     // Don't check for case status -> let mixed cases pass
   811     iParseInfo.iSendBuffer.Copy( iDecodeInfo.iDecodeBuffer );
  1036     TInt oldLength = iParseInfo.iSendBuffer.Length();
   812     TInt maxLength = iParseInfo.iSendBuffer.MaxLength();
  1037     iParseInfo.iSendBuffer.SetLength( iParseInfo.iLimit );
   813     TPtr8 upperDes( &iParseInfo.iSendBuffer[0], iParseInfo.iLimit, maxLength );
  1038     iParseInfo.iSendBuffer.UpperCase();
   814     upperDes.UpperCase();
  1039     iParseInfo.iSendBuffer.SetLength( oldLength );
   815     // Next always send the command to ATEXT
  1040     // Next always send the command to ATEXT
   816     iCmdPusher->IssueRequest( iParseInfo.iSendBuffer );
  1041     iCmdPusher->IssueRequest( iParseInfo.iSendBuffer );
   817     FTRACE(FPrint( _L("CDunAtCmdHandler::HandleNextDecodedCommand() complete") ));
  1042     FTRACE(FPrint( _L("CDunAtCmdHandler::HandleNextSubCommand() complete") ));
   818     return EFalse;
  1043     return ETrue;
   819     }
       
   820 
       
   821 // ---------------------------------------------------------------------------
       
   822 // Finds the start of the next command
       
   823 // ---------------------------------------------------------------------------
       
   824 //
       
   825 TInt CDunAtCmdHandler::FindStartOfNextCommand()
       
   826     {
       
   827     FTRACE(FPrint( _L("CDunAtCmdHandler::FindStartOfNextCommand()") ));
       
   828     // Note: here we need to avoid internal recursion when parsing the
       
   829     // multiple IsEndOfCommand() and IsDelimiterCharacter() markers inside the
       
   830     // same upstream block.
       
   831     // Skip all the extra markers except the one we already know to exist.
       
   832     TInt i;
       
   833     TInt startVal = iEndIndex + 1;
       
   834     TInt foundIndex = KErrNotFound;
       
   835     TInt count = iCommand->Length();
       
   836     for ( i=startVal; i<count; i++ )
       
   837         {
       
   838         TChar character = (*iCommand)[i];
       
   839         if ( !(IsEndOfCommand(character)||IsDelimiterCharacter(character)) )
       
   840             {
       
   841             foundIndex = i;
       
   842             break;
       
   843             }
       
   844         }
       
   845     FTRACE(FPrint( _L("CDunAtCmdHandler::FindStartOfNextCommand() complete") ));
       
   846     return foundIndex;
       
   847     }
  1044     }
   848 
  1045 
   849 // ---------------------------------------------------------------------------
  1046 // ---------------------------------------------------------------------------
   850 // Manages end of AT command handling
  1047 // Manages end of AT command handling
   851 // ---------------------------------------------------------------------------
  1048 // ---------------------------------------------------------------------------
   852 //
  1049 //
   853 void CDunAtCmdHandler::ManageEndOfCmdHandling( TBool aNotifyExternal,
  1050 void CDunAtCmdHandler::ManageEndOfCmdHandling( TBool aNotifyLocal,
   854                                                TBool aNotifyLocal,
  1051                                                TBool aNotifyExternal )
   855                                                TBool aClearInput )
       
   856     {
  1052     {
   857     FTRACE(FPrint( _L("CDunAtCmdHandler::ManageEndOfCmdHandling()") ));
  1053     FTRACE(FPrint( _L("CDunAtCmdHandler::ManageEndOfCmdHandling()") ));
   858     if ( iInputBuffer.Length() > 0 )
  1054     FTRACE(FPrint( _L("CDunAtCmdHandler::ManageEndOfCmdHandling() (loc=%d, ext=%d)"), aNotifyLocal, aNotifyExternal ));
   859         {
  1055     // If iEndIndex is (>=0 && <iInput.Length()) it means more data waits in
   860         iLastBuffer.Copy( iInputBuffer );
  1056     // iInput that didn't fit in iInputBuffer.
   861         }
  1057     TInt cmdLength = iInput->Length();
   862     ResetParseBuffers( aClearInput );
  1058     TBool subBlock = ( iEndIndex>=0&&iEndIndex<cmdLength ) ? ETrue : EFalse;
       
  1059     if ( iLineBuffer.Length()>0 && !subBlock )
       
  1060         {
       
  1061         // Line buffer set and no partial subblock, copy to lastbuffer
       
  1062         iLastBuffer.Copy( iLineBuffer );
       
  1063         }
       
  1064     iLineBuffer.Zero();
       
  1065     iDecodeInfo.iFirstDecode = ETrue;
       
  1066     iDecodeInfo.iDecodeIndex = 0;
       
  1067     iDecodeInfo.iPrevExists = EFalse;
       
  1068     iParseInfo.iLimit = KErrNotFound;
       
  1069     iParseInfo.iSendBuffer.Zero();
       
  1070     iEditorModeInfo.iContentFound = EFalse;
   863     iHandleState = EDunStateIdle;
  1071     iHandleState = EDunStateIdle;
   864     if ( aNotifyLocal )
  1072     if ( aNotifyLocal )
   865         {
  1073         {
   866         iCmdPusher->SetEndOfCmdLine();
  1074         iCmdPusher->SetEndOfCmdLine();
   867         }
  1075         }
   868     if ( !aNotifyExternal )
  1076     // iEndIndex must not be reset to KErrNotFound only when
   869         {
  1077     // ExtractLineFromInputBuffer() found the next line
   870         FTRACE(FPrint( _L("CDunAtCmdHandler::ManageEndOfCmdHandling() (no external) complete") ));
  1078     // (when moreNeeded is EFalse)
   871         return;
  1079     TBool resetIndex = ETrue;
   872         }
  1080     if ( aNotifyExternal )
   873     TInt foundIndex = FindStartOfNextCommand();
  1081         {
   874     iUpstream->NotifyAtCmdHandlingEnd( foundIndex );
  1082         TBool moreNeeded = ExtractLineFromInputBuffer();
       
  1083         if ( moreNeeded )
       
  1084             {
       
  1085             iUpstream->NotifyParserNeedsMoreData();
       
  1086             }
       
  1087         else
       
  1088             {
       
  1089             // AppendBlockToInputBuffer() was able to fill with known end, handle next
       
  1090             iHandleState = EDunStateAtCmdHandling;
       
  1091             HandleNextSubCommand();
       
  1092             resetIndex = EFalse;
       
  1093             }
       
  1094         }
       
  1095     if ( resetIndex )
       
  1096         {
       
  1097         iEndIndex = KErrNotFound;
       
  1098         }
   875     FTRACE(FPrint( _L("CDunAtCmdHandler::ManageEndOfCmdHandling() complete") ));
  1099     FTRACE(FPrint( _L("CDunAtCmdHandler::ManageEndOfCmdHandling() complete") ));
   876     }
  1100     }
   877 
  1101 
   878 // ---------------------------------------------------------------------------
  1102 // ---------------------------------------------------------------------------
   879 // Extracts next decoded command from input buffer to decode buffer
  1103 // Extracts next subcommand from line buffer to send buffer
   880 // ---------------------------------------------------------------------------
  1104 // ---------------------------------------------------------------------------
   881 //
  1105 //
   882 TBool CDunAtCmdHandler::ExtractNextDecodedCommand( TBool aPeek )
  1106 TBool CDunAtCmdHandler::ExtractNextSubCommand( TBool aPeek )
   883     {
  1107     {
   884     FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractNextDecodedCommand()") ));
  1108     FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractNextSubCommand()") ));
       
  1109     TDunDecodeInfo oldInfo = iDecodeInfo;
   885     iParseInfo.iLimit = KErrNotFound;
  1110     iParseInfo.iLimit = KErrNotFound;
   886     TDunDecodeInfo oldInfo = iDecodeInfo;
  1111     iParseInfo.iSendBuffer.Zero();
   887     iDecodeInfo.iDecodeBuffer.Zero();
  1112     // Find start of subcommand from line buffer
   888     // Find start of decode command from input buffer
  1113     TInt startIndex = FindStartOfSubCommand();
   889     TInt startIndex = iDecodeInfo.iDecodeIndex;
       
   890     startIndex = FindStartOfDecodedCommand( iInputBuffer, startIndex );
       
   891     if ( startIndex < 0 )
  1114     if ( startIndex < 0 )
   892         {
  1115         {
   893         RestoreOldDecodeInfo( aPeek, oldInfo );
  1116         RestoreOldDecodeInfo( aPeek, oldInfo );
   894         FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractNextDecodedCommand() (no start) complete") ));
  1117         FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractNextDecodedCommand() (no start) complete") ));
   895         return EFalse;
  1118         return EFalse;
   896         }
  1119         }
   897     // Find end of decode command from input buffer
  1120     iDecodeInfo.iDecodeIndex = startIndex;
   898     TBool specialCmd = EFalse;
  1121     TBool specialCmd = EFalse;
   899     TInt endIndex = KErrNotFound;
  1122     TInt endIndex = KErrNotFound;
   900     specialCmd = CheckSpecialCommand( startIndex, endIndex );
  1123     specialCmd = CheckSpecialCommand( endIndex );
   901     if ( !specialCmd )
  1124     if ( !specialCmd )
   902         {
  1125         {
   903         FindSubCommand( startIndex, endIndex );
  1126         FindSubCommand( endIndex );
   904         }
  1127         }
   905     if ( endIndex < startIndex )
  1128     TInt lineLength = iLineBuffer.Length();
       
  1129     TBool inStartLimits = ( startIndex >= 0 && startIndex < lineLength ) ? ETrue : EFalse;
       
  1130     TBool inEndLimits   = ( endIndex   >= 0 && endIndex   < lineLength ) ? ETrue : EFalse;
       
  1131     if ( !inStartLimits || !inEndLimits )
   906         {
  1132         {
   907         RestoreOldDecodeInfo( aPeek, oldInfo );
  1133         RestoreOldDecodeInfo( aPeek, oldInfo );
   908         FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractNextDecodedCommand() (no end) complete") ));
  1134         FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractNextSubCommand() (no end) complete") ));
   909         return EFalse;
  1135         return EFalse;
   910         }
  1136         }
   911     TInt cmdLength = endIndex - startIndex + 1;
  1137     TInt cmdLength = endIndex - startIndex + 1;
   912     // If the limit was not already set then do it now
  1138     // If the limit was not already set then do it now
   913     if ( iParseInfo.iLimit < 0 )
  1139     if ( iParseInfo.iLimit < 0 )
   915         iParseInfo.iLimit = cmdLength;
  1141         iParseInfo.iLimit = cmdLength;
   916         }
  1142         }
   917     // Next create a new command
  1143     // Next create a new command
   918     if ( !iDecodeInfo.iFirstDecode )
  1144     if ( !iDecodeInfo.iFirstDecode )
   919         {
  1145         {
   920         _LIT( KAtMsg, "AT" );
  1146         _LIT( KAtPrefix, "AT" );
   921         iDecodeInfo.iDecodeBuffer.Append( KAtMsg );
  1147         iParseInfo.iSendBuffer.Append( KAtPrefix );
   922         if ( !specialCmd )  // Already added with CheckSpecialCommand()
  1148         if ( !specialCmd )  // Already added with CheckSpecialCommand()
   923             {
  1149             {
   924             iParseInfo.iLimit += 2;  // Length of "AT"
  1150             iParseInfo.iLimit += 2;  // Length of "AT"
   925             }
  1151             }
   926         // Note: The length of iDecodeBuffer is not exceeded here because "AT"
  1152         // Note: The length of iDecodeBuffer is not exceeded here because "AT"
   927         // is added only for the second commands after that.
  1153         // is added only for the second commands after that.
   928         }
  1154         }
   929     TPtrC8 decodedCmd = iInputBuffer.Mid( startIndex, cmdLength );
  1155     iParseInfo.iSendBuffer.Append( &iLineBuffer[startIndex], cmdLength );
   930     iDecodeInfo.iDecodeBuffer.Append( decodedCmd );
  1156     // Change settings for the next decode round
   931     // Set index for next round
       
   932     iDecodeInfo.iFirstDecode = EFalse;
  1157     iDecodeInfo.iFirstDecode = EFalse;
   933     iDecodeInfo.iDecodeIndex = endIndex + 1;
  1158     iDecodeInfo.iDecodeIndex = endIndex + 1;
   934     RestoreOldDecodeInfo( aPeek, oldInfo );
  1159     RestoreOldDecodeInfo( aPeek, oldInfo );
   935     FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractNextDecodedCommand() complete") ));
  1160     if ( !aPeek )
       
  1161         {
       
  1162         iDecodeInfo.iCmdsHandled++;
       
  1163         FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractNextSubCommand() (handled=%d)"), iDecodeInfo.iCmdsHandled ));
       
  1164         }
       
  1165     FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractNextSubCommand() complete") ));
   936     return ETrue;
  1166     return ETrue;
       
  1167     }
       
  1168 
       
  1169 // ---------------------------------------------------------------------------
       
  1170 // Finds the start of subcommand from line buffer
       
  1171 // ---------------------------------------------------------------------------
       
  1172 //
       
  1173 TBool CDunAtCmdHandler::FindStartOfSubCommand()
       
  1174     {
       
  1175     FTRACE(FPrint( _L("CDunAtCmdHandler::FindStartOfSubCommand()") ));
       
  1176     TInt i;
       
  1177     TInt foundIndex = KErrNotFound;
       
  1178     TInt lineLength = iLineBuffer.Length();
       
  1179     for ( i=iDecodeInfo.iDecodeIndex; i<lineLength; i++ )
       
  1180         {
       
  1181         TChar character = iLineBuffer[i];
       
  1182         if ( !IsDelimiterCharacter(character) )
       
  1183             {
       
  1184             foundIndex = i;
       
  1185             break;
       
  1186             }
       
  1187         }
       
  1188     FTRACE(FPrint( _L("CDunAtCmdHandler::FindStartOfSubCommand() complete") ));
       
  1189     return foundIndex;
   937     }
  1190     }
   938 
  1191 
   939 // ---------------------------------------------------------------------------
  1192 // ---------------------------------------------------------------------------
   940 // Restores old decode info. For ExtractNextDecodedCommand() when aPeeks is
  1193 // Restores old decode info. For ExtractNextDecodedCommand() when aPeeks is
   941 // ETrue.
  1194 // ETrue.
   952         }
  1205         }
   953     FTRACE(FPrint( _L("CDunAtCmdHandler::RestoreOldDecodeInfo() complete") ));
  1206     FTRACE(FPrint( _L("CDunAtCmdHandler::RestoreOldDecodeInfo() complete") ));
   954     }
  1207     }
   955 
  1208 
   956 // ---------------------------------------------------------------------------
  1209 // ---------------------------------------------------------------------------
   957 // Finds end of an AT command
  1210 // Tests for end of AT command line
   958 // ---------------------------------------------------------------------------
  1211 // ---------------------------------------------------------------------------
   959 //
  1212 //
   960 TInt CDunAtCmdHandler::FindEndOfCommand( TDesC8& aDes, TInt aStartIndex )
  1213 TBool CDunAtCmdHandler::IsEndOfLine( TChar& aCharacter )
   961     {
       
   962     FTRACE(FPrint( _L("CDunAtCmdHandler::FindEndOfCommand()") ));
       
   963     TInt i;
       
   964     TInt length = aDes.Length();
       
   965     for ( i=aStartIndex; i<length; i++ )
       
   966         {
       
   967         TChar character = aDes[i];
       
   968         if ( IsEndOfCommand(character) )
       
   969             {
       
   970             FTRACE(FPrint( _L("CDunAtCmdHandler::FindEndOfCommand() complete (%d)"), i ));
       
   971             return i;
       
   972             }
       
   973         }
       
   974     FTRACE(FPrint( _L("CDunAtCmdHandler::FindEndOfCommand() (not found) complete") ));
       
   975     return KErrNotFound;
       
   976     }
       
   977 
       
   978 // ---------------------------------------------------------------------------
       
   979 // Tests for end of AT command character
       
   980 // ---------------------------------------------------------------------------
       
   981 //
       
   982 TBool CDunAtCmdHandler::IsEndOfCommand( TChar& aCharacter )
       
   983     {
  1214     {
   984     FTRACE(FPrint( _L("CDunAtCmdHandler::IsEndOfCommand()") ));
  1215     FTRACE(FPrint( _L("CDunAtCmdHandler::IsEndOfCommand()") ));
   985     if ( aCharacter==iCarriageReturn || aCharacter==iLineFeed )
  1216     if ( aCharacter==iCarriageReturn || aCharacter==iLineFeed )
   986         {
  1217         {
   987         FTRACE(FPrint( _L("CDunAtCmdHandler::IsEndOfCommand() (found) complete") ));
  1218         FTRACE(FPrint( _L("CDunAtCmdHandler::IsEndOfCommand() (found) complete") ));
   988         return ETrue;
  1219         return ETrue;
   989         }
  1220         }
   990     FTRACE(FPrint( _L("CDunAtCmdHandler::IsEndOfCommand() (not found) complete") ));
  1221     FTRACE(FPrint( _L("CDunAtCmdHandler::IsEndOfCommand() (not found) complete") ));
   991     return EFalse;
  1222     return EFalse;
   992     }
       
   993 
       
   994 // ---------------------------------------------------------------------------
       
   995 // Finds start of a decoded AT command
       
   996 // ---------------------------------------------------------------------------
       
   997 //
       
   998 TInt CDunAtCmdHandler::FindStartOfDecodedCommand( TDesC8& aDes,
       
   999                                                   TInt aStartIndex )
       
  1000     {
       
  1001     FTRACE(FPrint( _L("CDunAtCmdHandler::FindStartOfDecodedCommand()") ));
       
  1002     TInt i;
       
  1003     TInt count = aDes.Length();
       
  1004     for ( i=aStartIndex; i<count; i++ )
       
  1005         {
       
  1006         TChar character = aDes[i];
       
  1007         if ( !IsDelimiterCharacter(character) )
       
  1008             {
       
  1009             FTRACE(FPrint( _L("CDunAtCmdHandler::FindStartOfDecodedCommand() complete (%d)"), i ));
       
  1010             return i;
       
  1011             }
       
  1012         }
       
  1013     FTRACE(FPrint( _L("CDunAtCmdHandler::FindStartOfDecodedCommand() (not found) complete") ));
       
  1014     return KErrNotFound;
       
  1015     }
  1223     }
  1016 
  1224 
  1017 // ---------------------------------------------------------------------------
  1225 // ---------------------------------------------------------------------------
  1018 // Checks if character is delimiter character
  1226 // Checks if character is delimiter character
  1019 // ---------------------------------------------------------------------------
  1227 // ---------------------------------------------------------------------------
  1050 
  1258 
  1051 // ---------------------------------------------------------------------------
  1259 // ---------------------------------------------------------------------------
  1052 // Checks special command
  1260 // Checks special command
  1053 // ---------------------------------------------------------------------------
  1261 // ---------------------------------------------------------------------------
  1054 //
  1262 //
  1055 TBool CDunAtCmdHandler::CheckSpecialCommand( TInt aStartIndex,
  1263 TBool CDunAtCmdHandler::CheckSpecialCommand( TInt& aEndIndex )
  1056                                              TInt& aEndIndex )
       
  1057     {
  1264     {
  1058     FTRACE(FPrint( _L("CDunAtCmdHandler::CheckSpecialCommand()") ));
  1265     FTRACE(FPrint( _L("CDunAtCmdHandler::CheckSpecialCommand()") ));
  1059     TInt atMsgLen = 0;
  1266     TInt atPrefixLen = 0;
  1060     TInt newLength = iInputBuffer.Length() - aStartIndex;
  1267     TInt startIndex = iDecodeInfo.iDecodeIndex;
  1061     TBuf8<KDunInputBufLength> upperBuf;
  1268     TInt newLength = iLineBuffer.Length() - startIndex;
       
  1269     TBuf8<KDunLineBufLength> upperBuf;
  1062     if ( !iDecodeInfo.iFirstDecode )
  1270     if ( !iDecodeInfo.iFirstDecode )
  1063         {
  1271         {
  1064         // For cases such as "ATM1L3DT*99#" "DT" must have "AT"
  1272         // For cases such as "ATM1L3DT*99#" "DT" must have "AT"
  1065         _LIT8( KATMsg, "AT" );
  1273         _LIT8( KAtPrefix, "AT" );
  1066         upperBuf.Copy( KATMsg );
  1274         upperBuf.Copy( KAtPrefix );
  1067         atMsgLen = 2;  // "AT"
  1275         atPrefixLen = 2;  // "AT"
  1068         newLength += atMsgLen;
  1276         newLength += atPrefixLen;
  1069         }
  1277         }
  1070     upperBuf.Append( &iInputBuffer[aStartIndex], newLength );
  1278     upperBuf.Append( &iLineBuffer[startIndex], newLength );
  1071     upperBuf.UpperCase();
  1279     upperBuf.UpperCase();
  1072     TInt i;
  1280     TInt i;
  1073     TInt count = iSpecials.Count();
  1281     TInt count = iSpecials.Count();
  1074     for ( i=0; i<count; i++ )
  1282     for ( i=0; i<count; i++ )
  1075         {
  1283         {
  1087         TInt cmpResult = upperBuf.Compare( *specialCmd );
  1295         TInt cmpResult = upperBuf.Compare( *specialCmd );
  1088         upperBuf.SetLength( origLength );
  1296         upperBuf.SetLength( origLength );
  1089         if ( cmpResult == 0 )
  1297         if ( cmpResult == 0 )
  1090             {
  1298             {
  1091             iParseInfo.iLimit = specialLength;
  1299             iParseInfo.iLimit = specialLength;
  1092             aEndIndex = (origLength-1) + aStartIndex - atMsgLen;
  1300             aEndIndex = (origLength-1) + startIndex - atPrefixLen;
  1093             FTRACE(FPrint( _L("CDunAtCmdHandler::CheckSpecialCommand() complete") ));
  1301             FTRACE(FPrint( _L("CDunAtCmdHandler::CheckSpecialCommand() complete") ));
  1094             return ETrue;
  1302             return ETrue;
  1095             }
  1303             }
  1096         }
  1304         }
  1097     FTRACE(FPrint( _L("CDunAtCmdHandler::CheckSpecialCommand() (not found) complete") ));
  1305     FTRACE(FPrint( _L("CDunAtCmdHandler::CheckSpecialCommand() (not found) complete") ));
  1189         }
  1397         }
  1190     if ( extendedIndex == expectedIndex )
  1398     if ( extendedIndex == expectedIndex )
  1191         {
  1399         {
  1192         iDecodeInfo.iExtendedIndex = aEndIndex;
  1400         iDecodeInfo.iExtendedIndex = aEndIndex;
  1193         SaveFoundCharDecodeState( aCharacter );
  1401         SaveFoundCharDecodeState( aCharacter );
  1194         FTRACE(FPrint( _L("CDunAtCmdHandler::IsExtendedBorder() (no border) complete") ));
  1402         FTRACE(FPrint( _L("CDunAtCmdHandler::IsExtendedBorder() (no border normal) complete") ));
  1195         return EFalse;
  1403         return EFalse;
       
  1404         }
       
  1405     // Now suspect border found so peek the next character after the suspected
       
  1406     // extended character. If it is not alphabetical character, return with EFalse.
       
  1407     // This case is to detect the cases such as "AT+VTS={*,3000}", where '*' would
       
  1408     // be the start of the next command in normal cases.
       
  1409     TInt peekIndex = aEndIndex + 1;
       
  1410     TInt lineLength = iLineBuffer.Length();
       
  1411     if ( peekIndex < lineLength )
       
  1412         {
       
  1413         TChar nextCharacter = iLineBuffer[peekIndex];
       
  1414         if ( !nextCharacter.IsAlpha() )
       
  1415             {
       
  1416             SaveFoundCharDecodeState( aCharacter );
       
  1417             FTRACE(FPrint( _L("CDunAtCmdHandler::IsExtendedBorder() (no border special) complete") ));
       
  1418             return EFalse;
       
  1419             }
  1196         }
  1420         }
  1197     aEndIndex--;
  1421     aEndIndex--;
  1198     FTRACE(FPrint( _L("CDunAtCmdHandler::IsExtendedBorder() (border) complete") ));
  1422     FTRACE(FPrint( _L("CDunAtCmdHandler::IsExtendedBorder() (border) complete") ));
  1199     return ETrue;
  1423     return ETrue;
  1200     }
  1424     }
  1265 
  1489 
  1266 // ---------------------------------------------------------------------------
  1490 // ---------------------------------------------------------------------------
  1267 // Finds subcommand
  1491 // Finds subcommand
  1268 // ---------------------------------------------------------------------------
  1492 // ---------------------------------------------------------------------------
  1269 //
  1493 //
  1270 TInt CDunAtCmdHandler::FindSubCommand( TInt aStartIndex, TInt& aEndIndex )
  1494 TInt CDunAtCmdHandler::FindSubCommand( TInt& aEndIndex )
  1271     {
  1495     {
  1272     FTRACE(FPrint( _L("CDunAtCmdHandler::FindSubCommand()") ));
  1496     FTRACE(FPrint( _L("CDunAtCmdHandler::FindSubCommand()") ));
  1273     aEndIndex = aStartIndex;
  1497     TInt startIndex = iDecodeInfo.iDecodeIndex;
       
  1498     aEndIndex = startIndex;
  1274     TBool found = EFalse;
  1499     TBool found = EFalse;
  1275     TInt length = iInputBuffer.Length();
  1500     TInt lineLength = iLineBuffer.Length();
  1276     iDecodeInfo.iAssignFound = EFalse;
  1501     iDecodeInfo.iAssignFound = EFalse;
  1277     iDecodeInfo.iInQuotes = EFalse;
  1502     iDecodeInfo.iInQuotes = EFalse;
  1278     iDecodeInfo.iExtendedIndex = KErrNotFound;
  1503     iDecodeInfo.iExtendedIndex = KErrNotFound;
  1279     SaveNotFoundCharDecodeState();
  1504     SaveNotFoundCharDecodeState();
  1280     iAtSpecialCmdHandler->ResetComparisonBuffer();  // just to be sure
  1505     iAtSpecialCmdHandler->ResetComparisonBuffer();  // just to be sure
  1281     for ( ; aEndIndex<length; aEndIndex++ )
  1506     for ( ; aEndIndex<lineLength; aEndIndex++ )
  1282         {
  1507         {
  1283         TChar character = iInputBuffer[aEndIndex];
  1508         TChar character = iLineBuffer[aEndIndex];
  1284         found = FindSubCommandQuotes( character, aStartIndex, aEndIndex );
  1509         found = FindSubCommandQuotes( character, startIndex, aEndIndex );
  1285         if ( found )
  1510         if ( found )
  1286             {
  1511             {
  1287             continue;
  1512             continue;
  1288             }
  1513             }
  1289         if ( character == '?' )
  1514         if ( character == '?' )
  1302         // The check below detects the following type of cases:
  1527         // The check below detects the following type of cases:
  1303         // ATCMD+CMD [first + as delimiter]
  1528         // ATCMD+CMD [first + as delimiter]
  1304         // AT+CMD+CMD [second + as delimiter]
  1529         // AT+CMD+CMD [second + as delimiter]
  1305         if ( IsExtendedCharacter(character) )
  1530         if ( IsExtendedCharacter(character) )
  1306             {
  1531             {
  1307             found = IsExtendedBorder( character, aStartIndex, aEndIndex );
  1532             found = IsExtendedBorder( character, startIndex, aEndIndex );
  1308             if ( !found )
  1533             if ( !found )
  1309                 {
  1534                 {
  1310                 continue;
  1535                 continue;
  1311                 }
  1536                 }
  1312             FTRACE(FPrint( _L("CDunAtCmdHandler::FindSubCommand() (extended) complete") ));
  1537             FTRACE(FPrint( _L("CDunAtCmdHandler::FindSubCommand() (extended) complete") ));
  1330 // ---------------------------------------------------------------------------
  1555 // ---------------------------------------------------------------------------
  1331 //
  1556 //
  1332 TBool CDunAtCmdHandler::IsASlashCommand()
  1557 TBool CDunAtCmdHandler::IsASlashCommand()
  1333     {
  1558     {
  1334     FTRACE(FPrint( _L("CDunAtCmdHandler::IsASlashCommand()") ));
  1559     FTRACE(FPrint( _L("CDunAtCmdHandler::IsASlashCommand()") ));
  1335     if ( iInputBuffer.Length() == 2 )
  1560     if ( iLineBuffer.Length() == 2 )
  1336         {
  1561         {
  1337         if ( iInputBuffer[1] == '/' &&
  1562         if ( iLineBuffer[1] == '/' &&
  1338             (iInputBuffer[0] == 'A' || iInputBuffer[0] == 'a') )
  1563             (iLineBuffer[0] == 'A' || iLineBuffer[0] == 'a') )
  1339             {
  1564             {
  1340             FTRACE(FPrint( _L("CDunAtCmdHandler::IsASlashCommand() (found) complete") ));
  1565             FTRACE(FPrint( _L("CDunAtCmdHandler::IsASlashCommand() (found) complete") ));
  1341             return ETrue;
  1566             return ETrue;
  1342             }
  1567             }
  1343         }
  1568         }
  1356     if ( !IsASlashCommand() )
  1581     if ( !IsASlashCommand() )
  1357         {
  1582         {
  1358         FTRACE(FPrint( _L("CDunAtCmdHandler::HandleASlashCommand() (no push) complete") ));
  1583         FTRACE(FPrint( _L("CDunAtCmdHandler::HandleASlashCommand() (no push) complete") ));
  1359         return EFalse;
  1584         return EFalse;
  1360         }
  1585         }
       
  1586     iEndIndex = iInput->Length();  // Causes skipping of last '/' in ManageEndOfCmdHandling()
  1361     // If "A/" command and last buffer exist, set the last buffer as the current buffer
  1587     // If "A/" command and last buffer exist, set the last buffer as the current buffer
  1362     if ( iLastBuffer.Length() > 0 )
  1588     if ( iLastBuffer.Length() > 0 )
  1363         {
  1589         {
  1364         iInputBuffer.Copy( iLastBuffer );
  1590         iLineBuffer.Copy( iLastBuffer );
  1365         FTRACE(FPrint( _L("CDunAtCmdHandler::HandleASlashCommand() (copy) complete") ));
  1591         FTRACE(FPrint( _L("CDunAtCmdHandler::HandleASlashCommand() (copy) complete") ));
  1366         return EFalse;
  1592         return EFalse;
  1367         }
  1593         }
  1368     // Last buffer not set so return "ERROR" if quiet mode not on
  1594     // Last buffer not set so return "ERROR"
  1369     if ( iQuietOn )
       
  1370         {
       
  1371         FTRACE(FPrint( _L("CDunAtCmdHandler::HandleASlashCommand() (quiet) complete") ));
       
  1372         return EFalse;
       
  1373         }
       
  1374     iDownstream->NotifyDataPushRequest( &iErrorBuffer, NULL );
  1595     iDownstream->NotifyDataPushRequest( &iErrorBuffer, NULL );
  1375     FTRACE(FPrint( _L("CDunAtCmdHandler::HandleASlashCommand() complete") ));
  1596     FTRACE(FPrint( _L("CDunAtCmdHandler::HandleASlashCommand() complete") ));
  1376     return ETrue;
  1597     return ETrue;
  1377     }
       
  1378 
       
  1379 // ---------------------------------------------------------------------------
       
  1380 // Resets parse buffers
       
  1381 // ---------------------------------------------------------------------------
       
  1382 //
       
  1383 void CDunAtCmdHandler::ResetParseBuffers( TBool aClearInput )
       
  1384     {
       
  1385     FTRACE(FPrint( _L("CDunAtCmdHandler::ResetParseBuffers()") ));
       
  1386     if ( aClearInput )
       
  1387         {
       
  1388         iInputBuffer.Zero();
       
  1389         }
       
  1390     iDecodeInfo.iFirstDecode = ETrue;
       
  1391     iDecodeInfo.iDecodeIndex = 0;
       
  1392     iDecodeInfo.iPrevExists = EFalse;
       
  1393     iDecodeInfo.iDecodeBuffer.Zero();
       
  1394     FTRACE(FPrint( _L("CDunAtCmdHandler::ResetParseBuffers() complete") ));
       
  1395     }
  1598     }
  1396 
  1599 
  1397 // ---------------------------------------------------------------------------
  1600 // ---------------------------------------------------------------------------
  1398 // Manages command mode change
  1601 // Manages command mode change
  1399 // ---------------------------------------------------------------------------
  1602 // ---------------------------------------------------------------------------
  1583     // When end of input notify CDunUpstream to reissue the read request.
  1786     // When end of input notify CDunUpstream to reissue the read request.
  1584     TBool nextContentFound = FindNextContent( aStart );
  1787     TBool nextContentFound = FindNextContent( aStart );
  1585     if ( !nextContentFound )
  1788     if ( !nextContentFound )
  1586         {
  1789         {
  1587         iUpstream->NotifyEditorModeReply( aStart );
  1790         iUpstream->NotifyEditorModeReply( aStart );
  1588         FTRACE(FPrint( _L("CDunAtCmdHandler::NotifyEditorModeReply() complete") ));
  1791         FTRACE(FPrint( _L("CDunAtCmdHandler::ManageEditorModeReply() complete") ));
  1589         return KErrNone;
  1792         return KErrNone;
  1590         }
  1793         }
  1591     // In block mode end the block mode by sending <ESC> and hope it works.
  1794     // In block mode end the block mode by sending <ESC> and hope it works.
  1592     iEscapeBuffer.Zero();
  1795     iEscapeBuffer.Zero();
  1593     iEscapeBuffer.Append( KDunEscape );
  1796     iEscapeBuffer.Append( KDunEscape );
  1606     if ( !aStart )
  1809     if ( !aStart )
  1607         {
  1810         {
  1608         FTRACE(FPrint( _L("CDunAtCmdHandler::FindNextContent() (skip) complete" ) ));
  1811         FTRACE(FPrint( _L("CDunAtCmdHandler::FindNextContent() (skip) complete" ) ));
  1609         return iEditorModeInfo.iContentFound;
  1812         return iEditorModeInfo.iContentFound;
  1610         }
  1813         }
  1611     iEditorModeInfo.iContentFound = EFalse;
  1814     // If iEndIndex is (>=0 && <iInput.Length()) it means more data waits in
  1612     TInt foundCmdIndex = KErrNotFound;
  1815     // iInput that didn't fit in iInputBuffer. Only check FindStartOfCommand()
  1613     TBool nextContentFound = ExtractNextDecodedCommand( ETrue );  // peek
  1816     // if iEndIndex < 0, meaning more data is needed from CDunUpstream.
  1614     if ( !nextContentFound )
  1817     TBool contentFound = EFalse;
  1615         {
  1818     TInt cmdLength = iInput->Length();
  1616         // Check the next subblock
  1819     TBool subBlock = ( iEndIndex>=0&&iEndIndex<cmdLength ) ? ETrue : EFalse;
  1617         foundCmdIndex = FindStartOfNextCommand();
  1820     if ( subBlock )
  1618         }
  1821         {
  1619     if ( !nextContentFound && foundCmdIndex<0 )
  1822         contentFound = ETrue;
  1620         {
  1823         }
  1621         FTRACE(FPrint( _L("CDunAtCmdHandler::FindNextContent() (not found) complete") ));
  1824     if ( !contentFound )
  1622         return EFalse;
  1825         {
  1623         }
  1826         contentFound = ExtractNextSubCommand( ETrue );  // peek
  1624     iEditorModeInfo.iContentFound = ETrue;
  1827         }
       
  1828     iEditorModeInfo.iContentFound = contentFound;
  1625     FTRACE(FPrint( _L("CDunAtCmdHandler::FindNextContent() complete" ) ));
  1829     FTRACE(FPrint( _L("CDunAtCmdHandler::FindNextContent() complete" ) ));
  1626     return ETrue;
  1830     return contentFound;
  1627     }
  1831     }
  1628 
  1832 
  1629 // ---------------------------------------------------------------------------
  1833 // ---------------------------------------------------------------------------
  1630 // From class MDunAtCmdPusher.
  1834 // From class MDunAtCmdPusher.
  1631 // Notifies about end of AT command processing. This is after all reply data
  1835 // Notifies about end of AT command processing. This is after all reply data
  1640         {
  1844         {
  1641         ManageEditorModeReply( ETrue );
  1845         ManageEditorModeReply( ETrue );
  1642         FTRACE(FPrint( _L("CDunAtCmdHandler::NotifyEndOfProcessing() (editor) complete" ) ));
  1846         FTRACE(FPrint( _L("CDunAtCmdHandler::NotifyEndOfProcessing() (editor) complete" ) ));
  1643         return KErrNone;
  1847         return KErrNone;
  1644         }
  1848         }
  1645     HandleNextDecodedCommand();
  1849     HandleNextSubCommand();
  1646     FTRACE(FPrint( _L("CDunAtCmdHandler::NotifyEndOfProcessing() complete" ) ));
  1850     FTRACE(FPrint( _L("CDunAtCmdHandler::NotifyEndOfProcessing() complete" ) ));
  1647     return KErrNone;
  1851     return KErrNone;
  1648     }
  1852     }
  1649 
  1853 
  1650 // ---------------------------------------------------------------------------
  1854 // ---------------------------------------------------------------------------
  1651 // From class MDunAtCmdPusher.
  1855 // From class MDunAtCmdPusher.
  1652 // Notifies about request to stop AT command handling for the rest of the
  1856 // Notifies about request to stop AT command handling for the rest of the
  1653 // command line data
  1857 // command line data
  1654 // ---------------------------------------------------------------------------
  1858 // ---------------------------------------------------------------------------
  1655 //
  1859 //
  1656 TInt CDunAtCmdHandler::NotifyEndOfCmdLineProcessing()
  1860 void CDunAtCmdHandler::NotifyEndOfCmdLineProcessing()
  1657     {
  1861     {
  1658     FTRACE(FPrint( _L("CDunAtCmdHandler::NotifyEndOfCmdLineProcessing()" ) ));
  1862     FTRACE(FPrint( _L("CDunAtCmdHandler::NotifyEndOfCmdLineProcessing()" ) ));
  1659     TInt retVal = Stop();
  1863     ManageEndOfCmdHandling( ETrue, ETrue );
  1660     ManageEndOfCmdHandling( ETrue, EFalse, ETrue );
       
  1661     FTRACE(FPrint( _L("CDunAtCmdHandler::NotifyEndOfCmdLineProcessing() complete" ) ));
  1864     FTRACE(FPrint( _L("CDunAtCmdHandler::NotifyEndOfCmdLineProcessing() complete" ) ));
  1662     return retVal;
       
  1663     }
  1865     }
  1664 
  1866 
  1665 // ---------------------------------------------------------------------------
  1867 // ---------------------------------------------------------------------------
  1666 // From class MDunAtCmdPusher.
  1868 // From class MDunAtCmdPusher.
  1667 // Notifies about request to peek for the next command
  1869 // Notifies about request to peek for the next command
  1668 // ---------------------------------------------------------------------------
  1870 // ---------------------------------------------------------------------------
  1669 //
  1871 //
  1670 TBool CDunAtCmdHandler::NotifyNextCommandPeekRequest()
  1872 TBool CDunAtCmdHandler::NotifyNextCommandPeekRequest()
  1671     {
  1873     {
  1672     FTRACE(FPrint( _L("CDunAtCmdHandler::NotifyNextCommandPeekRequest()") ));
  1874     FTRACE(FPrint( _L("CDunAtCmdHandler::NotifyNextCommandPeekRequest()") ));
  1673     TBool extracted = ExtractNextDecodedCommand( ETrue );
  1875     TBool extracted = ExtractNextSubCommand( ETrue );
  1674     FTRACE(FPrint( _L("CDunAtCmdHandler::NotifyNextCommandPeekRequest() complete") ));
  1876     FTRACE(FPrint( _L("CDunAtCmdHandler::NotifyNextCommandPeekRequest() complete") ));
  1675     return extracted;
  1877     return extracted;
  1676     }
  1878     }
  1677 
  1879 
  1678 // ---------------------------------------------------------------------------
  1880 // ---------------------------------------------------------------------------