cbsatplugin/atmisccmdplugin/src/cmgwcommandhandler.cpp
changeset 45 b0aebde9b1fb
equal deleted inserted replaced
44:6d10bd0d821a 45:b0aebde9b1fb
       
     1 /*
       
     2  * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3  * All rights reserved.
       
     4  * This component and the accompanying materials are made available
       
     5  * under the terms of "Eclipse Public License v1.0"
       
     6  * which accompanies this distribution, and is available
       
     7  * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8  * Initial Contributors:
       
     9  * Nokia Corporation - initial contribution.
       
    10  *
       
    11  * Contributors:
       
    12  * Description :
       
    13  *
       
    14  */
       
    15 
       
    16 #include "cmgwcommandhandler.h"
       
    17 #include <mmretrieve.h>
       
    18 #include <mmlist.h> 
       
    19 #include <exterror.h>
       
    20 
       
    21 #include "atmisccmdpluginconsts.h"
       
    22 #include "debug.h"
       
    23 
       
    24 const TUint KEOT = 26;    // End of Transmission
       
    25 const TUint KESC = 27;   // Escape
       
    26 
       
    27 const TUint8 KSCATonBitMask = 0x70;
       
    28 const TUint8 KSCANpiBitMask = 0x0F;
       
    29 
       
    30 CCMGWCommandHandler* CCMGWCommandHandler::NewL(MATMiscCmdPlugin* aCallback, TAtCommandParser& aATCmdParser, RMobilePhone& aPhone)
       
    31     {
       
    32     TRACE_FUNC_ENTRY
       
    33     CCMGWCommandHandler* self = new (ELeave) CCMGWCommandHandler(aCallback, aATCmdParser, aPhone);
       
    34     CleanupStack::PushL(self);
       
    35     self->ConstructL();
       
    36     CleanupStack::Pop(self);
       
    37     TRACE_FUNC_EXIT
       
    38     return self;
       
    39     }
       
    40 
       
    41 CCMGWCommandHandler::CCMGWCommandHandler(MATMiscCmdPlugin* aCallback, TAtCommandParser& aATCmdParser, RMobilePhone& aPhone) :
       
    42     CATCmdAsyncBase(aCallback, aATCmdParser, aPhone),
       
    43     iEntryPckg(iEntry)
       
    44     {
       
    45     TRACE_FUNC_ENTRY
       
    46     TRACE_FUNC_EXIT
       
    47     }
       
    48 
       
    49 void CCMGWCommandHandler::ConstructL()
       
    50     {
       
    51     TRACE_FUNC_ENTRY
       
    52     iReply.CreateL(KDefaultCmdBufLength);
       
    53     iTPDU.CreateL(KDefaultCmdBufLength);
       
    54     
       
    55     User::LeaveIfError( iMobileSmsMessaging.Open(iPhone) );
       
    56 
       
    57     TInt err = iMobileSmsStore.Open(iMobileSmsMessaging, KETelIccSmsStore);
       
    58     if (err != KErrNone)
       
    59         {
       
    60         iState = ECMGWStateSimStoreNotSupported;
       
    61         }
       
    62     iRetrieveMobilePhoneSmspList = CRetrieveMobilePhoneSmspList::NewL(iMobileSmsMessaging);
       
    63 
       
    64     TRACE_FUNC_EXIT
       
    65     }
       
    66 
       
    67 CCMGWCommandHandler::~CCMGWCommandHandler()
       
    68     {
       
    69     TRACE_FUNC_ENTRY
       
    70     Cancel();
       
    71     delete iRetrieveMobilePhoneSmspList;
       
    72     delete iMobilePhoneSmspList;
       
    73     iMobileSmsStore.Close();
       
    74     iMobileSmsMessaging.Close();
       
    75     iReply.Close();
       
    76     iTPDU.Close();
       
    77     TRACE_FUNC_EXIT
       
    78     }
       
    79 
       
    80 /**
       
    81  * Set message format
       
    82  * 0: PDU mode
       
    83  * 1: Text mode - not supported
       
    84  */
       
    85 void CCMGWCommandHandler::SetMessageFormat(TInt aFormat)
       
    86     {
       
    87     TRACE_FUNC_ENTRY
       
    88     if (aFormat == 0 || aFormat == 1)
       
    89         {
       
    90         iMsgFormat = aFormat;
       
    91         }
       
    92     Trace(_L("Message format: %d"), iMsgFormat);
       
    93     TRACE_FUNC_ENTRY
       
    94     }
       
    95 
       
    96 void CCMGWCommandHandler::HandleCommand(const TDesC8& aCmd, RBuf8& /*aReply*/, TBool /*aReplyNeeded*/)
       
    97     {
       
    98     TRACE_FUNC_ENTRY
       
    99     
       
   100     if (iMsgFormat == 1 || iState == ECMGWStateSimStoreNotSupported )
       
   101         {
       
   102         // Reply "ERROR" if text mode is set
       
   103         // Reply "ERROR" if SIM store is not supported
       
   104         iCallback->CreateReplyAndComplete( EReplyTypeError );
       
   105         TRACE_FUNC_EXIT
       
   106         return;
       
   107         }
       
   108     
       
   109     TInt err = KErrNone;
       
   110     
       
   111     TAtCommandParser::TCommandHandlerType cmdHandlerType = iATCmdParser.CommandHandlerType();
       
   112     
       
   113     switch (cmdHandlerType)
       
   114         {
       
   115         case (TAtCommandParser::ECmdHandlerTypeTest):
       
   116             {
       
   117             iCallback->CreateReplyAndComplete( EReplyTypeOk );
       
   118             break;
       
   119             }
       
   120         case (TAtCommandParser::ECmdHandlerTypeSet): 
       
   121             {
       
   122             switch(iState)
       
   123                 {
       
   124                 case ECMGWStateIdle:
       
   125                     {
       
   126                     // Parse parameters
       
   127                     err = ParseParameters();
       
   128                     if (err == KErrNone)
       
   129                         {
       
   130                         Trace(_L("Parse parameters OK."));
       
   131                         Trace(_L("Length = %d"), iTPDULength);
       
   132                         Trace(_L("stat = %d"), iTPDUStat);
       
   133                         
       
   134                         iTPDU.Zero();
       
   135                         iState = ECMGWStateEditMode;
       
   136                         iCallback->CreateReplyAndComplete( EReplyTypeEditor );
       
   137                         }
       
   138                     else
       
   139                         {
       
   140                         // Syntax error
       
   141                         Trace(_L("Syntax error. err = %d"), err);
       
   142                         iState = ECMGWStateIdle;
       
   143                         iCallback->CreateReplyAndComplete(EReplyTypeError);
       
   144                         }
       
   145                     break;
       
   146                     }
       
   147                 case ECMGWStateEditMode:   // Edit state
       
   148                     {
       
   149                     HandleEditModeCommand(aCmd);
       
   150                     break;
       
   151                     }
       
   152                 default:    // Other states
       
   153                     {
       
   154                     Cancel();
       
   155                     iCallback->CreateReplyAndComplete( EReplyTypeError );
       
   156                     }
       
   157                 }
       
   158             break;
       
   159             }
       
   160         default:
       
   161             {
       
   162             iCallback->CreateReplyAndComplete( EReplyTypeError );
       
   163             break;
       
   164             }
       
   165         }
       
   166     
       
   167     TRACE_FUNC_EXIT
       
   168     }
       
   169 
       
   170 void CCMGWCommandHandler::HandleEditModeCommand( const TDesC8& aCmd )
       
   171     {
       
   172     TRACE_FUNC_ENTRY
       
   173     
       
   174     TInt err = KErrNone;
       
   175     TUint8 cmdCharVal = 0;
       
   176     if (aCmd.Length())
       
   177         {
       
   178         cmdCharVal = aCmd[0];
       
   179         }
       
   180 
       
   181     switch ( cmdCharVal ) 
       
   182         {
       
   183         case KEOT:  // End of Transmission: Now write the message
       
   184             {
       
   185             // Extract SCA fro PDU
       
   186             err = ExtractSCA();
       
   187             if (err == KErrNotFound)
       
   188                 {
       
   189                 // SCA not provided by client
       
   190                 if (iMobileSmspEntry.iServiceCentre.iTelNumber.Length() == 0)
       
   191                     {
       
   192                     // Retrieve SMS parameter list
       
   193                     iRetrieveMobilePhoneSmspList->Start(iStatus);
       
   194                     iState = ECMGWStateRetrieveSCA;
       
   195                     SetActive();
       
   196                     }
       
   197                 else
       
   198                     {
       
   199                     // Got the SCA from SIM params already - self complete
       
   200                     iServiceCentre = iMobileSmspEntry.iServiceCentre;
       
   201                     
       
   202                     TRequestStatus* status = &iStatus;
       
   203                     User::RequestComplete(status, KErrNone);
       
   204                     iState = ECMGWStatePreparePDU;
       
   205                     SetActive();
       
   206                     }
       
   207                 }
       
   208             else if( err == KErrNone )
       
   209                 {
       
   210                 // Got the SCA from client (in iService Centre) - self complete
       
   211                 TRequestStatus* status = &iStatus;
       
   212                 User::RequestComplete(status, KErrNone);
       
   213                 iState = ECMGWStatePreparePDU;
       
   214                 SetActive();            
       
   215                 }
       
   216             else
       
   217                 {
       
   218                 // Extract SCA failed
       
   219                 iState = ECMGWStateIdle;
       
   220                 iCallback->CreateCMSReplyAndComplete(KErrGsmSMSInvalidPDUModeParameter);
       
   221                 }
       
   222              break;
       
   223             }
       
   224         case KESC:  // Escape
       
   225             {
       
   226             iState = ECMGWStateIdle;
       
   227             iCallback->CreateReplyAndComplete( EReplyTypeOk );
       
   228             break;
       
   229             }
       
   230         default:    // Still entering PDU data
       
   231             {
       
   232             iTPDU.Append( aCmd );
       
   233             iCallback->CreateReplyAndComplete( EReplyTypeEditor );
       
   234             break;
       
   235             }
       
   236         }
       
   237     
       
   238     TRACE_FUNC_EXIT
       
   239     }
       
   240 
       
   241 void CCMGWCommandHandler::RunL()
       
   242     {
       
   243     TRACE_FUNC_ENTRY
       
   244     
       
   245     iReply.Zero();
       
   246     TInt err = iStatus.Int();
       
   247     Trace(_L("State = %d, err = %d"), iState, err);
       
   248     
       
   249     if (err == KErrNone)
       
   250         {
       
   251         switch (iState)
       
   252             {
       
   253             case ECMGWStateRetrieveSCA:
       
   254                 {
       
   255                 // Got SCA from SIM params - update iServiceCentre
       
   256                 iMobilePhoneSmspList = iRetrieveMobilePhoneSmspList->RetrieveListL();
       
   257                 iMobileSmspEntry = iMobilePhoneSmspList->GetEntryL(0);
       
   258                 iServiceCentre = iMobileSmspEntry.iServiceCentre;
       
   259                 
       
   260                 // Complete self to send PDU in next state
       
   261                 TRequestStatus* status = &iStatus;
       
   262                 User::RequestComplete(status, KErrNone);
       
   263                 iState = ECMGWStatePreparePDU;
       
   264                 SetActive();
       
   265                 }
       
   266                 break;
       
   267             case ECMGWStatePreparePDU:
       
   268                 {
       
   269                 // Create an SMS entry from PDU
       
   270                 iEntry.iServiceCentre = iServiceCentre;
       
   271                 
       
   272                 err = CreateSmsEntry();
       
   273                 if (err == KErrNone)
       
   274                     {
       
   275                     Trace(_L("Create SMS entry OK."));
       
   276                     Trace(_L("Service center: %S"),
       
   277                             &iEntry.iServiceCentre.iTelNumber);
       
   278                     Trace(_L("Type of number: %d"),
       
   279                             iEntry.iServiceCentre.iTypeOfNumber);
       
   280                     Trace(_L("Number plan: %d"),
       
   281                             iEntry.iServiceCentre.iNumberPlan);
       
   282                     Trace(_L("Message status: %d"), iEntry.iMsgStatus);
       
   283 
       
   284                     // Start to write PDU
       
   285                     iEntry.iIndex = -1;
       
   286                     iMobileSmsStore.Write(iStatus, iEntryPckg);
       
   287                     iState = ECMGWStateWritePDU;
       
   288                     SetActive();
       
   289                     }
       
   290                 else
       
   291                     {
       
   292                     // Create failed
       
   293                     iState = ECMGWStateIdle;
       
   294                     iCallback->CreateCMSReplyAndComplete(KErrGsmSMSInvalidPDUModeParameter);
       
   295                     }                
       
   296                 break;
       
   297                 }
       
   298             case ECMGWStateWritePDU:
       
   299                 {
       
   300                 Trace(_L("Write successful. Index = %d"), iEntry.iIndex);
       
   301                 
       
   302                 iReply.Append(KCRLF);
       
   303                 iReply.Append(KAtCMGW);
       
   304                 iReply.AppendNum(iEntry.iIndex);
       
   305                 iState = ECMGWStateIdle;
       
   306                 iCallback->CreateReplyAndComplete(EReplyTypeOk, iReply);
       
   307                 }
       
   308                 break;
       
   309             default:
       
   310                 iState = ECMGWStateIdle;
       
   311                 iCallback->CreateReplyAndComplete(EReplyTypeError);
       
   312                 break;
       
   313             }
       
   314         }
       
   315     else
       
   316         {
       
   317         iState = ECMGWStateIdle;
       
   318         iCallback->CreateCMSReplyAndComplete(err);
       
   319         }
       
   320     
       
   321     TRACE_FUNC_EXIT
       
   322     }
       
   323 
       
   324 TInt CCMGWCommandHandler::RunError(TInt aError)
       
   325     {
       
   326     TRACE_FUNC_ENTRY
       
   327     
       
   328     delete iMobilePhoneSmspList;
       
   329     iMobilePhoneSmspList = NULL;
       
   330     iState = ECMGWStateIdle;
       
   331     iCallback->CreateCMSReplyAndComplete(aError);
       
   332     
       
   333     TRACE_FUNC_EXIT
       
   334     return KErrNone;
       
   335     }
       
   336 
       
   337 void CCMGWCommandHandler::DoCancel() 
       
   338     {
       
   339     TRACE_FUNC_ENTRY
       
   340     
       
   341     switch (iState)
       
   342         {
       
   343         case ECMGWStateRetrieveSCA:
       
   344             {
       
   345             iRetrieveMobilePhoneSmspList->Cancel();
       
   346             break;
       
   347             }
       
   348         case ECMGWStateWritePDU:
       
   349             {
       
   350             iMobileSmsStore.CancelAsyncRequest(EMobilePhoneStoreWrite);
       
   351             break;
       
   352             }
       
   353         }
       
   354     iState = ECMGWStateIdle;
       
   355     
       
   356     TRACE_FUNC_EXIT
       
   357     }
       
   358 /**
       
   359  * Parse parameters of +CMGW=<length>,<stat>
       
   360  */
       
   361 TInt CCMGWCommandHandler::ParseParameters()
       
   362     {
       
   363     TRACE_FUNC_ENTRY
       
   364     
       
   365     TInt ret = KErrNone;
       
   366     iTPDULength = 0;
       
   367     iTPDUStat = 0; // default value
       
   368     TInt otherParams = 0;
       
   369     // Get length
       
   370     TInt retLength = iATCmdParser.NextIntParam(iTPDULength);
       
   371     // Get status
       
   372     TInt retStat = iATCmdParser.NextIntParam(iTPDUStat);
       
   373     // Get other parameters
       
   374     TInt retOther = iATCmdParser.NextIntParam(otherParams);
       
   375     // syntax error happens if
       
   376     // a)there is no param 1
       
   377     // b)there are 3 params
       
   378     // c)param 2 is not 0,1,2 or 3
       
   379     TBool noParam1 = (retLength != KErrNone);
       
   380     TBool badParam2 = (retStat == KErrGeneral);
       
   381     TBool tooManyParams = (retOther != KErrNotFound);
       
   382     
       
   383     if (noParam1 || badParam2 || tooManyParams)
       
   384         {
       
   385         ret = KErrArgument;
       
   386         }
       
   387     else
       
   388         {
       
   389         switch (iTPDUStat)
       
   390             {
       
   391             case 0:
       
   392                 // to receive unread message
       
   393                 iMessageStatus = RMobileSmsStore::EStoredMessageUnread;
       
   394                 break;
       
   395             case 1:
       
   396                 // to receive read message
       
   397                 iMessageStatus = RMobileSmsStore::EStoredMessageRead;
       
   398                 break;
       
   399             case 2:
       
   400                 // Unsent is not supported in this version
       
   401                 ret = KErrNotSupported;
       
   402                 break;
       
   403             case 3:
       
   404                 // Sent is not supported in this version
       
   405                 ret = KErrNotSupported;
       
   406                 break;
       
   407             default:
       
   408                 ret = KErrArgument;
       
   409                 break;
       
   410             }
       
   411         iEntry.iMsgStatus = iMessageStatus;
       
   412         }
       
   413     
       
   414     TRACE_FUNC_EXIT
       
   415     return ret;
       
   416     }
       
   417 
       
   418 /**
       
   419  * Create an SMS entry from the PDU string
       
   420  */
       
   421 TInt CCMGWCommandHandler::CreateSmsEntry()
       
   422     {
       
   423     TRACE_FUNC_ENTRY
       
   424     
       
   425     TInt err = KErrNone;
       
   426     
       
   427     // Check the length
       
   428     if (iTPDU.Length() != (iSCALength+iTPDULength+1)*2)
       
   429         {
       
   430         TRACE_FUNC_EXIT
       
   431         return KErrArgument;
       
   432         }
       
   433     
       
   434     RBuf8 buf;
       
   435     err = buf.Create(iTPDULength);
       
   436     if (err != KErrNone)
       
   437         {
       
   438         TRACE_FUNC_EXIT
       
   439         return err;
       
   440         }
       
   441     // Convert to binary format
       
   442     for(TInt i=(iSCALength+1)*2; i< iTPDU.Length(); i+=2)
       
   443         {
       
   444         TLex8 lex(iTPDU.Mid(i, 2));
       
   445         TUint8 val = 0;
       
   446         err = lex.Val(val, EHex);
       
   447         if (err != KErrNone)
       
   448             {
       
   449             buf.Close();
       
   450             TRACE_FUNC_EXIT
       
   451             return err;
       
   452             }
       
   453         buf.Append(val);
       
   454         }
       
   455     iEntry.iMsgData.Copy(buf);
       
   456     
       
   457     buf.Close();
       
   458     TRACE_FUNC_EXIT
       
   459     return KErrNone;
       
   460     }
       
   461 
       
   462 /**
       
   463  * Extract the SMS service center address from the head of PDU string
       
   464  */
       
   465 TInt CCMGWCommandHandler::ExtractSCA()
       
   466     {
       
   467     TRACE_FUNC_ENTRY
       
   468     
       
   469     TInt err = KErrNone;
       
   470     TLex8 lex;
       
   471     RMobilePhone::TMobileAddress sca;
       
   472     // SCA length
       
   473     lex.Assign(iTPDU.Left(2));
       
   474     err = lex.Val(iSCALength, EHex); 
       
   475     if (err != KErrNone)
       
   476         {
       
   477         TRACE_FUNC_EXIT
       
   478         return err;
       
   479         }
       
   480     TInt length = iTPDU.Length();
       
   481     if (iSCALength == 0)
       
   482         {
       
   483         // Service center is not found in PDU
       
   484         err = KErrNotFound;
       
   485         }
       
   486     else if (iSCALength > (length-2)/2)
       
   487         {
       
   488         // Service certer length error
       
   489         err = KErrArgument;
       
   490         }
       
   491     else
       
   492         {
       
   493         // SCA is given
       
   494         // Parse SCA TON and NPI
       
   495         TUint8 val = 0;
       
   496         lex.Assign(iTPDU.Mid(2,2));
       
   497         err = lex.Val(val, EHex);
       
   498         if (err != KErrNone)
       
   499             {
       
   500             TRACE_FUNC_EXIT
       
   501             return err;
       
   502             }
       
   503         TUint8 ton = (val&KSCATonBitMask)>>4;
       
   504         TUint8 npi = val&KSCANpiBitMask;
       
   505         switch (ton) // TON
       
   506             {
       
   507             case 0: // 000
       
   508                 sca.iTypeOfNumber = RMobilePhone::EUnknownNumber;
       
   509                 break;
       
   510             case 1: // 001
       
   511                 sca.iTypeOfNumber = RMobilePhone::EInternationalNumber;
       
   512                 sca.iTelNumber.Append('+');
       
   513                 break;
       
   514             case 2: // 010
       
   515                 sca.iTypeOfNumber = RMobilePhone::ENationalNumber;
       
   516                 break;
       
   517             default: 
       
   518                 // CMCC doesn't support other types
       
   519                 TRACE_FUNC_EXIT
       
   520                 return KErrArgument;
       
   521             }
       
   522         switch (npi) // NPI
       
   523             {
       
   524             case 0: // 0000
       
   525                 sca.iNumberPlan = RMobilePhone::EUnknownNumberingPlan;
       
   526                 break;
       
   527             case 1: // 0001
       
   528                 sca.iNumberPlan = RMobilePhone::EIsdnNumberPlan;
       
   529                 break;
       
   530             default:
       
   531                 // CMCC doesn't support other number plans
       
   532                 TRACE_FUNC_EXIT
       
   533                 return KErrArgument;
       
   534             }
       
   535         // Extract SCA number
       
   536         for (TInt i=4; i<(iSCALength+1)*2; i+=2)
       
   537             {
       
   538             sca.iTelNumber.Append(iTPDU[i+1]);
       
   539             sca.iTelNumber.Append(iTPDU[i]);
       
   540             }
       
   541         if(sca.iTelNumber[sca.iTelNumber.Length()-1] == 'F' 
       
   542                 || sca.iTelNumber[sca.iTelNumber.Length()-1] == 'f')
       
   543             {
       
   544             sca.iTelNumber.Delete(sca.iTelNumber.Length()-1, 1);
       
   545             }
       
   546         iServiceCentre = sca;
       
   547         }
       
   548     TRACE_FUNC_EXIT
       
   549     return err;
       
   550     }
       
   551 
       
   552