localconnectivityservice/dun/atext/src/DunAtCmdHandler.cpp
changeset 52 866b4af7ffbe
parent 37 d9d8313203af
child 54 4dc88a4ac6f4
equal deleted inserted replaced
51:64200268cac2 52:866b4af7ffbe
    51 /*
    51 /*
    52  * Note1: This file uses AT command parsing based on heuristics.
    52  * Note1: This file uses AT command parsing based on heuristics.
    53  * Refer to test specification if planning to change the heuristic.
    53  * Refer to test specification if planning to change the heuristic.
    54  * Note2: Input buffer management (ExtractLineFromInputBuffer()) can be tested
    54  * Note2: Input buffer management (ExtractLineFromInputBuffer()) can be tested
    55  * with non-line based terminals such as HyperTerminal or Realterm.
    55  * with non-line based terminals such as HyperTerminal or Realterm.
       
    56  * Note3: If there is a need to handle commands with random data, the extended
       
    57  * command checking can interfere with the character set of this random data.
       
    58  * Best way to handle this random data is to create a handler for these commands
       
    59  * which skips the valid "not to be parsed" data or use quotes. For these cases
       
    60  * the CDunAtSpecialCmdHandler could be extended.
    56  */
    61  */
    57 
    62 
    58 #include "DunAtCmdHandler.h"
    63 #include "DunAtCmdHandler.h"
    59 #include "DunAtUrcHandler.h"
    64 #include "DunAtUrcHandler.h"
    60 #include "DunDownstream.h"
    65 #include "DunDownstream.h"
   976     TInt inputLength = iInput->Length();
   981     TInt inputLength = iInput->Length();
   977     TInt foundIndex = inputLength;
   982     TInt foundIndex = inputLength;
   978     for ( TInt i=aStartIndex; i<inputLength; i++ )
   983     for ( TInt i=aStartIndex; i<inputLength; i++ )
   979         {
   984         {
   980         TChar character = (*iInput)[i];
   985         TChar character = (*iInput)[i];
   981         if ( !IsDelimiterCharacter(character) )
   986         if ( !IsDelimiterCharacter(character,ETrue,ETrue) )
   982             {
   987             {
   983             foundIndex = i;
   988             foundIndex = i;
   984             break;
   989             break;
   985             }
   990             }
   986         }
   991         }
  1160     if ( !aPeek )
  1165     if ( !aPeek )
  1161         {
  1166         {
  1162         iDecodeInfo.iCmdsHandled++;
  1167         iDecodeInfo.iCmdsHandled++;
  1163         FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractNextSubCommand() (handled=%d)"), iDecodeInfo.iCmdsHandled ));
  1168         FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractNextSubCommand() (handled=%d)"), iDecodeInfo.iCmdsHandled ));
  1164         }
  1169         }
       
  1170     FTRACE(FPrint( _L("CDunAtCmdPusher::ExtractNextSubCommand() extracted:") ));
       
  1171     FTRACE(FPrintRaw(iParseInfo.iSendBuffer) );
  1165     FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractNextSubCommand() complete") ));
  1172     FTRACE(FPrint( _L("CDunAtCmdHandler::ExtractNextSubCommand() complete") ));
  1166     return ETrue;
  1173     return ETrue;
  1167     }
  1174     }
  1168 
  1175 
  1169 // ---------------------------------------------------------------------------
  1176 // ---------------------------------------------------------------------------
  1177     TInt foundIndex = KErrNotFound;
  1184     TInt foundIndex = KErrNotFound;
  1178     TInt lineLength = iLineBuffer.Length();
  1185     TInt lineLength = iLineBuffer.Length();
  1179     for ( i=iDecodeInfo.iDecodeIndex; i<lineLength; i++ )
  1186     for ( i=iDecodeInfo.iDecodeIndex; i<lineLength; i++ )
  1180         {
  1187         {
  1181         TChar character = iLineBuffer[i];
  1188         TChar character = iLineBuffer[i];
  1182         if ( !IsDelimiterCharacter(character) )
  1189         if ( !IsDelimiterCharacter(character,ETrue,ETrue) )
  1183             {
  1190             {
  1184             foundIndex = i;
  1191             foundIndex = i;
  1185             break;
  1192             break;
  1186             }
  1193             }
  1187         }
  1194         }
  1224 
  1231 
  1225 // ---------------------------------------------------------------------------
  1232 // ---------------------------------------------------------------------------
  1226 // Checks if character is delimiter character
  1233 // Checks if character is delimiter character
  1227 // ---------------------------------------------------------------------------
  1234 // ---------------------------------------------------------------------------
  1228 //
  1235 //
  1229 TBool CDunAtCmdHandler::IsDelimiterCharacter( TChar aCharacter )
  1236 TBool CDunAtCmdHandler::IsDelimiterCharacter( TChar aCharacter,
       
  1237                                               TBool aBasic,
       
  1238                                               TBool aExtended )
  1230     {
  1239     {
  1231     FTRACE(FPrint( _L("CDunAtCmdHandler::IsDelimiterCharacter()") ));
  1240     FTRACE(FPrint( _L("CDunAtCmdHandler::IsDelimiterCharacter()") ));
  1232     if ( aCharacter.IsSpace() || aCharacter==';' || aCharacter==0x00 )
  1241    if ( aBasic && ( aCharacter.IsSpace()||aCharacter==0x00) )
  1233         {
  1242         {
  1234         FTRACE(FPrint( _L("CDunAtCmdHandler::IsDelimiterCharacter() complete") ));
  1243         FTRACE(FPrint( _L("CDunAtCmdHandler::IsDelimiterCharacter() complete") ));
       
  1244         return ETrue;
       
  1245         }
       
  1246    if ( aExtended && aCharacter == ';' )
       
  1247         {
       
  1248         FTRACE(FPrint( _L("CDunAtCmdHandler::IsDelimiterCharacter() (extended) complete") ));
  1235         return ETrue;
  1249         return ETrue;
  1236         }
  1250         }
  1237     FTRACE(FPrint( _L("CDunAtCmdHandler::IsDelimiterCharacter() (not delimiter) complete") ));
  1251     FTRACE(FPrint( _L("CDunAtCmdHandler::IsDelimiterCharacter() (not delimiter) complete") ));
  1238     return EFalse;
  1252     return EFalse;
  1239     }
  1253     }
  1243 // ---------------------------------------------------------------------------
  1257 // ---------------------------------------------------------------------------
  1244 //
  1258 //
  1245 TBool CDunAtCmdHandler::IsExtendedCharacter( TChar aCharacter )
  1259 TBool CDunAtCmdHandler::IsExtendedCharacter( TChar aCharacter )
  1246     {
  1260     {
  1247     FTRACE(FPrint( _L("CDunAtCmdHandler::IsExtendedCharacter()") ));
  1261     FTRACE(FPrint( _L("CDunAtCmdHandler::IsExtendedCharacter()") ));
       
  1262     // Extended characters supported by this function (parser understands these)
       
  1263     // '+': Universal; mentioned in 3GPP TS 27.007, 3GPP TS 27.005, ITU-T V.250
       
  1264     // '&': Mentioned in ITU-T V.250 and in some "de facto" commands
       
  1265     // '%': Used by some old Hayes modems, left just in case
       
  1266     // '\': Used by some old Hayes modems, left just in case
       
  1267     // '*': Used by some old Hayes modems, AT&T and others
       
  1268     // '#': Used by some old Hayes modems, left just in case
       
  1269     // '$': Used by AT&T and Qualcomm
       
  1270     // '^': Used by China Mobile
       
  1271     // [please maintain this list here for quick reference]
  1248     if ( aCharacter=='+'  || aCharacter=='&' || aCharacter=='%' ||
  1272     if ( aCharacter=='+'  || aCharacter=='&' || aCharacter=='%' ||
  1249          aCharacter=='\\' || aCharacter=='*' || aCharacter=='#' ||
  1273          aCharacter=='\\' || aCharacter=='*' || aCharacter=='#' ||
  1250          aCharacter=='$'  || aCharacter=='^' )
  1274          aCharacter=='$'  || aCharacter=='^' )
  1251         {
  1275         {
  1252         FTRACE(FPrint( _L("CDunAtCmdHandler::IsExtendedCharacter() complete") ));
  1276         FTRACE(FPrint( _L("CDunAtCmdHandler::IsExtendedCharacter() complete") ));
  1375         SaveNotFoundCharDecodeState();
  1399         SaveNotFoundCharDecodeState();
  1376         FTRACE(FPrint( _L("CDunAtCmdHandler::FindSubCommandQuotes() (in quotes) complete") ));
  1400         FTRACE(FPrint( _L("CDunAtCmdHandler::FindSubCommandQuotes() (in quotes) complete") ));
  1377         return ETrue;
  1401         return ETrue;
  1378         }
  1402         }
  1379     FTRACE(FPrint( _L("CDunAtCmdHandler::FindSubCommandQuotes() (not found) complete") ));
  1403     FTRACE(FPrint( _L("CDunAtCmdHandler::FindSubCommandQuotes() (not found) complete") ));
       
  1404     return EFalse;
       
  1405     }
       
  1406 
       
  1407 // ---------------------------------------------------------------------------
       
  1408 // Check if in basic command delimiter skip zone
       
  1409 // ---------------------------------------------------------------------------
       
  1410 //
       
  1411 TBool CDunAtCmdHandler::IsBasicDelimiterSkipZone( TChar aCharacter,
       
  1412                                                   TInt& aEndIndex )
       
  1413     {
       
  1414     FTRACE(FPrint( _L("CDunAtCmdHandler::IsBasicDelimiterSkipZone()") ));
       
  1415     if ( !IsDelimiterCharacter(aCharacter,ETrue,EFalse) )
       
  1416         {
       
  1417         FTRACE(FPrint( _L("CDunAtCmdHandler::IsBasicDelimiterSkipZone() complete") ));
       
  1418         return EFalse;
       
  1419         }
       
  1420     // Check the case after '='
       
  1421     if ( iDecodeInfo.iAssignFound )
       
  1422         {
       
  1423         FTRACE(FPrint( _L("CDunAtCmdHandler::IsBasicDelimiterSkipZone() (after =) complete") ));
       
  1424         return ETrue;
       
  1425         }
       
  1426     // Check the case before '='
       
  1427     TInt peekIndex = aEndIndex + 1;
       
  1428     TInt lineLength = iLineBuffer.Length();
       
  1429     for ( ; peekIndex<lineLength; peekIndex++ )
       
  1430         {
       
  1431         TChar peekCharacter = iLineBuffer[peekIndex];
       
  1432         if ( peekCharacter=='?' || peekCharacter=='=' )
       
  1433             {
       
  1434             aEndIndex = peekIndex;
       
  1435             FTRACE(FPrint( _L("CDunAtCmdHandler::IsBasicDelimiterSkipZone() (? or =) complete") ));
       
  1436             return ETrue;
       
  1437             }
       
  1438         if ( !IsDelimiterCharacter(peekCharacter,ETrue,EFalse) )
       
  1439             {
       
  1440             break;
       
  1441             }
       
  1442         }
       
  1443     FTRACE(FPrint( _L("CDunAtCmdHandler::IsBasicDelimiterSkipZone() complete") ));
  1380     return EFalse;
  1444     return EFalse;
  1381     }
  1445     }
  1382 
  1446 
  1383 // ---------------------------------------------------------------------------
  1447 // ---------------------------------------------------------------------------
  1384 // Check if in next subcommand's extended border
  1448 // Check if in next subcommand's extended border
  1434     if ( iDecodeInfo.iAssignFound && !iDecodeInfo.iInQuotes )
  1498     if ( iDecodeInfo.iAssignFound && !iDecodeInfo.iInQuotes )
  1435         {
  1499         {
  1436         // Check the special case when assigning a number with "basic" command
  1500         // Check the special case when assigning a number with "basic" command
  1437         // and there is no delimiter after it. In this case <Numeric>|<Alpha>
  1501         // and there is no delimiter after it. In this case <Numeric>|<Alpha>
  1438         // border must be detected but only for a "basic" command, not for
  1502         // border must be detected but only for a "basic" command, not for
  1439         // extended.
  1503         // extended. This type of case is in active use in initialization
       
  1504         // strings where "ATS7=60L1M1X3" is one example
  1440         if ( iDecodeInfo.iExtendedIndex<0    && iDecodeInfo.iPrevExists &&
  1505         if ( iDecodeInfo.iExtendedIndex<0    && iDecodeInfo.iPrevExists &&
  1441              iDecodeInfo.iPrevChar.IsDigit() && aCharacter.IsAlpha() )
  1506              iDecodeInfo.iPrevChar.IsDigit() && aCharacter.IsAlpha() )
  1442             {
  1507             {
  1443             aEndIndex--;
  1508             aEndIndex--;
  1444             FTRACE(FPrint( _L("CDunAtCmdHandler::FindSubCommandAlphaBorder() (N|A) complete") ));
  1509             FTRACE(FPrint( _L("CDunAtCmdHandler::FindSubCommandAlphaBorder() (N|A) complete") ));
  1495     {
  1560     {
  1496     FTRACE(FPrint( _L("CDunAtCmdHandler::FindSubCommand()") ));
  1561     FTRACE(FPrint( _L("CDunAtCmdHandler::FindSubCommand()") ));
  1497     TInt startIndex = iDecodeInfo.iDecodeIndex;
  1562     TInt startIndex = iDecodeInfo.iDecodeIndex;
  1498     aEndIndex = startIndex;
  1563     aEndIndex = startIndex;
  1499     TBool found = EFalse;
  1564     TBool found = EFalse;
       
  1565     TBool skipZone = EFalse;
  1500     TInt lineLength = iLineBuffer.Length();
  1566     TInt lineLength = iLineBuffer.Length();
  1501     iDecodeInfo.iAssignFound = EFalse;
  1567     iDecodeInfo.iAssignFound = EFalse;
  1502     iDecodeInfo.iInQuotes = EFalse;
  1568     iDecodeInfo.iInQuotes = EFalse;
  1503     iDecodeInfo.iExtendedIndex = KErrNotFound;
  1569     iDecodeInfo.iExtendedIndex = KErrNotFound;
  1504     SaveNotFoundCharDecodeState();
  1570     SaveNotFoundCharDecodeState();
  1505     iAtSpecialCmdHandler->ResetComparisonBuffer();  // just to be sure
  1571     iAtSpecialCmdHandler->ResetComparisonBuffer();  // just to be sure
  1506     for ( ; aEndIndex<lineLength; aEndIndex++ )
  1572     for ( ; aEndIndex<lineLength; aEndIndex++ )
  1507         {
  1573         {
  1508         TChar character = iLineBuffer[aEndIndex];
  1574         TChar character = iLineBuffer[aEndIndex];
       
  1575         // Skip '=', quotes and data in quotes
  1509         found = FindSubCommandQuotes( character, startIndex, aEndIndex );
  1576         found = FindSubCommandQuotes( character, startIndex, aEndIndex );
  1510         if ( found )
  1577         if ( found )
  1511             {
  1578             {
  1512             continue;
  1579             continue;
  1513             }
  1580             }
       
  1581         // Skip basic command delimiter in the following cases:
       
  1582         // "ATCOMMAND    ?"
       
  1583         // "AT+COMMAND   ="
       
  1584         // "AT+COMMAND=PARAM1,     PARAM2"
       
  1585         skipZone = IsBasicDelimiterSkipZone( character, aEndIndex );
       
  1586         if ( skipZone )
       
  1587             {
       
  1588             continue;
       
  1589             }
       
  1590         // If '?', stop immediately
  1514         if ( character == '?' )
  1591         if ( character == '?' )
  1515             {
  1592             {
  1516             FTRACE(FPrint( _L("CDunAtCmdHandler::FindSubCommand() (?) complete") ));
  1593             FTRACE(FPrint( _L("CDunAtCmdHandler::FindSubCommand() (?) complete") ));
  1517             return KErrNone;
  1594             return KErrNone;
  1518             }
  1595             }
  1519         // The check below detects the following type of cases:
  1596         // The check below detects the following type of cases:
  1520         // ATCMD<delimiter>
  1597         // ATCMD<delimiter>
  1521         if ( IsDelimiterCharacter(character) )
  1598         if ( IsDelimiterCharacter(character,ETrue,ETrue) )
  1522             {
  1599             {
  1523             aEndIndex--;
  1600             aEndIndex--;
  1524             FTRACE(FPrint( _L("CDunAtCmdHandler::FindSubCommand() (delimiter) complete") ));
  1601             FTRACE(FPrint( _L("CDunAtCmdHandler::FindSubCommand() (delimiter) complete") ));
  1525             return KErrNone;
  1602             return KErrNone;
  1526             }
  1603             }