--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cbsatplugin/atmisccmdplugin/src/cmgwcommandhandler.cpp Thu Aug 19 10:05:41 2010 +0300
@@ -0,0 +1,552 @@
+/*
+ * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of "Eclipse Public License v1.0"
+ * which accompanies this distribution, and is available
+ * at the URL "http://www.eclipse.org/legal/epl-v10.html".
+ * Initial Contributors:
+ * Nokia Corporation - initial contribution.
+ *
+ * Contributors:
+ * Description :
+ *
+ */
+
+#include "cmgwcommandhandler.h"
+#include <mmretrieve.h>
+#include <mmlist.h>
+#include <exterror.h>
+
+#include "atmisccmdpluginconsts.h"
+#include "debug.h"
+
+const TUint KEOT = 26; // End of Transmission
+const TUint KESC = 27; // Escape
+
+const TUint8 KSCATonBitMask = 0x70;
+const TUint8 KSCANpiBitMask = 0x0F;
+
+CCMGWCommandHandler* CCMGWCommandHandler::NewL(MATMiscCmdPlugin* aCallback, TAtCommandParser& aATCmdParser, RMobilePhone& aPhone)
+ {
+ TRACE_FUNC_ENTRY
+ CCMGWCommandHandler* self = new (ELeave) CCMGWCommandHandler(aCallback, aATCmdParser, aPhone);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ TRACE_FUNC_EXIT
+ return self;
+ }
+
+CCMGWCommandHandler::CCMGWCommandHandler(MATMiscCmdPlugin* aCallback, TAtCommandParser& aATCmdParser, RMobilePhone& aPhone) :
+ CATCmdAsyncBase(aCallback, aATCmdParser, aPhone),
+ iEntryPckg(iEntry)
+ {
+ TRACE_FUNC_ENTRY
+ TRACE_FUNC_EXIT
+ }
+
+void CCMGWCommandHandler::ConstructL()
+ {
+ TRACE_FUNC_ENTRY
+ iReply.CreateL(KDefaultCmdBufLength);
+ iTPDU.CreateL(KDefaultCmdBufLength);
+
+ User::LeaveIfError( iMobileSmsMessaging.Open(iPhone) );
+
+ TInt err = iMobileSmsStore.Open(iMobileSmsMessaging, KETelIccSmsStore);
+ if (err != KErrNone)
+ {
+ iState = ECMGWStateSimStoreNotSupported;
+ }
+ iRetrieveMobilePhoneSmspList = CRetrieveMobilePhoneSmspList::NewL(iMobileSmsMessaging);
+
+ TRACE_FUNC_EXIT
+ }
+
+CCMGWCommandHandler::~CCMGWCommandHandler()
+ {
+ TRACE_FUNC_ENTRY
+ Cancel();
+ delete iRetrieveMobilePhoneSmspList;
+ delete iMobilePhoneSmspList;
+ iMobileSmsStore.Close();
+ iMobileSmsMessaging.Close();
+ iReply.Close();
+ iTPDU.Close();
+ TRACE_FUNC_EXIT
+ }
+
+/**
+ * Set message format
+ * 0: PDU mode
+ * 1: Text mode - not supported
+ */
+void CCMGWCommandHandler::SetMessageFormat(TInt aFormat)
+ {
+ TRACE_FUNC_ENTRY
+ if (aFormat == 0 || aFormat == 1)
+ {
+ iMsgFormat = aFormat;
+ }
+ Trace(_L("Message format: %d"), iMsgFormat);
+ TRACE_FUNC_ENTRY
+ }
+
+void CCMGWCommandHandler::HandleCommand(const TDesC8& aCmd, RBuf8& /*aReply*/, TBool /*aReplyNeeded*/)
+ {
+ TRACE_FUNC_ENTRY
+
+ if (iMsgFormat == 1 || iState == ECMGWStateSimStoreNotSupported )
+ {
+ // Reply "ERROR" if text mode is set
+ // Reply "ERROR" if SIM store is not supported
+ iCallback->CreateReplyAndComplete( EReplyTypeError );
+ TRACE_FUNC_EXIT
+ return;
+ }
+
+ TInt err = KErrNone;
+
+ TAtCommandParser::TCommandHandlerType cmdHandlerType = iATCmdParser.CommandHandlerType();
+
+ switch (cmdHandlerType)
+ {
+ case (TAtCommandParser::ECmdHandlerTypeTest):
+ {
+ iCallback->CreateReplyAndComplete( EReplyTypeOk );
+ break;
+ }
+ case (TAtCommandParser::ECmdHandlerTypeSet):
+ {
+ switch(iState)
+ {
+ case ECMGWStateIdle:
+ {
+ // Parse parameters
+ err = ParseParameters();
+ if (err == KErrNone)
+ {
+ Trace(_L("Parse parameters OK."));
+ Trace(_L("Length = %d"), iTPDULength);
+ Trace(_L("stat = %d"), iTPDUStat);
+
+ iTPDU.Zero();
+ iState = ECMGWStateEditMode;
+ iCallback->CreateReplyAndComplete( EReplyTypeEditor );
+ }
+ else
+ {
+ // Syntax error
+ Trace(_L("Syntax error. err = %d"), err);
+ iState = ECMGWStateIdle;
+ iCallback->CreateReplyAndComplete(EReplyTypeError);
+ }
+ break;
+ }
+ case ECMGWStateEditMode: // Edit state
+ {
+ HandleEditModeCommand(aCmd);
+ break;
+ }
+ default: // Other states
+ {
+ Cancel();
+ iCallback->CreateReplyAndComplete( EReplyTypeError );
+ }
+ }
+ break;
+ }
+ default:
+ {
+ iCallback->CreateReplyAndComplete( EReplyTypeError );
+ break;
+ }
+ }
+
+ TRACE_FUNC_EXIT
+ }
+
+void CCMGWCommandHandler::HandleEditModeCommand( const TDesC8& aCmd )
+ {
+ TRACE_FUNC_ENTRY
+
+ TInt err = KErrNone;
+ TUint8 cmdCharVal = 0;
+ if (aCmd.Length())
+ {
+ cmdCharVal = aCmd[0];
+ }
+
+ switch ( cmdCharVal )
+ {
+ case KEOT: // End of Transmission: Now write the message
+ {
+ // Extract SCA fro PDU
+ err = ExtractSCA();
+ if (err == KErrNotFound)
+ {
+ // SCA not provided by client
+ if (iMobileSmspEntry.iServiceCentre.iTelNumber.Length() == 0)
+ {
+ // Retrieve SMS parameter list
+ iRetrieveMobilePhoneSmspList->Start(iStatus);
+ iState = ECMGWStateRetrieveSCA;
+ SetActive();
+ }
+ else
+ {
+ // Got the SCA from SIM params already - self complete
+ iServiceCentre = iMobileSmspEntry.iServiceCentre;
+
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ iState = ECMGWStatePreparePDU;
+ SetActive();
+ }
+ }
+ else if( err == KErrNone )
+ {
+ // Got the SCA from client (in iService Centre) - self complete
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ iState = ECMGWStatePreparePDU;
+ SetActive();
+ }
+ else
+ {
+ // Extract SCA failed
+ iState = ECMGWStateIdle;
+ iCallback->CreateCMSReplyAndComplete(KErrGsmSMSInvalidPDUModeParameter);
+ }
+ break;
+ }
+ case KESC: // Escape
+ {
+ iState = ECMGWStateIdle;
+ iCallback->CreateReplyAndComplete( EReplyTypeOk );
+ break;
+ }
+ default: // Still entering PDU data
+ {
+ iTPDU.Append( aCmd );
+ iCallback->CreateReplyAndComplete( EReplyTypeEditor );
+ break;
+ }
+ }
+
+ TRACE_FUNC_EXIT
+ }
+
+void CCMGWCommandHandler::RunL()
+ {
+ TRACE_FUNC_ENTRY
+
+ iReply.Zero();
+ TInt err = iStatus.Int();
+ Trace(_L("State = %d, err = %d"), iState, err);
+
+ if (err == KErrNone)
+ {
+ switch (iState)
+ {
+ case ECMGWStateRetrieveSCA:
+ {
+ // Got SCA from SIM params - update iServiceCentre
+ iMobilePhoneSmspList = iRetrieveMobilePhoneSmspList->RetrieveListL();
+ iMobileSmspEntry = iMobilePhoneSmspList->GetEntryL(0);
+ iServiceCentre = iMobileSmspEntry.iServiceCentre;
+
+ // Complete self to send PDU in next state
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ iState = ECMGWStatePreparePDU;
+ SetActive();
+ }
+ break;
+ case ECMGWStatePreparePDU:
+ {
+ // Create an SMS entry from PDU
+ iEntry.iServiceCentre = iServiceCentre;
+
+ err = CreateSmsEntry();
+ if (err == KErrNone)
+ {
+ Trace(_L("Create SMS entry OK."));
+ Trace(_L("Service center: %S"),
+ &iEntry.iServiceCentre.iTelNumber);
+ Trace(_L("Type of number: %d"),
+ iEntry.iServiceCentre.iTypeOfNumber);
+ Trace(_L("Number plan: %d"),
+ iEntry.iServiceCentre.iNumberPlan);
+ Trace(_L("Message status: %d"), iEntry.iMsgStatus);
+
+ // Start to write PDU
+ iEntry.iIndex = -1;
+ iMobileSmsStore.Write(iStatus, iEntryPckg);
+ iState = ECMGWStateWritePDU;
+ SetActive();
+ }
+ else
+ {
+ // Create failed
+ iState = ECMGWStateIdle;
+ iCallback->CreateCMSReplyAndComplete(KErrGsmSMSInvalidPDUModeParameter);
+ }
+ break;
+ }
+ case ECMGWStateWritePDU:
+ {
+ Trace(_L("Write successful. Index = %d"), iEntry.iIndex);
+
+ iReply.Append(KCRLF);
+ iReply.Append(KAtCMGW);
+ iReply.AppendNum(iEntry.iIndex);
+ iState = ECMGWStateIdle;
+ iCallback->CreateReplyAndComplete(EReplyTypeOk, iReply);
+ }
+ break;
+ default:
+ iState = ECMGWStateIdle;
+ iCallback->CreateReplyAndComplete(EReplyTypeError);
+ break;
+ }
+ }
+ else
+ {
+ iState = ECMGWStateIdle;
+ iCallback->CreateCMSReplyAndComplete(err);
+ }
+
+ TRACE_FUNC_EXIT
+ }
+
+TInt CCMGWCommandHandler::RunError(TInt aError)
+ {
+ TRACE_FUNC_ENTRY
+
+ delete iMobilePhoneSmspList;
+ iMobilePhoneSmspList = NULL;
+ iState = ECMGWStateIdle;
+ iCallback->CreateCMSReplyAndComplete(aError);
+
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+void CCMGWCommandHandler::DoCancel()
+ {
+ TRACE_FUNC_ENTRY
+
+ switch (iState)
+ {
+ case ECMGWStateRetrieveSCA:
+ {
+ iRetrieveMobilePhoneSmspList->Cancel();
+ break;
+ }
+ case ECMGWStateWritePDU:
+ {
+ iMobileSmsStore.CancelAsyncRequest(EMobilePhoneStoreWrite);
+ break;
+ }
+ }
+ iState = ECMGWStateIdle;
+
+ TRACE_FUNC_EXIT
+ }
+/**
+ * Parse parameters of +CMGW=<length>,<stat>
+ */
+TInt CCMGWCommandHandler::ParseParameters()
+ {
+ TRACE_FUNC_ENTRY
+
+ TInt ret = KErrNone;
+ iTPDULength = 0;
+ iTPDUStat = 0; // default value
+ TInt otherParams = 0;
+ // Get length
+ TInt retLength = iATCmdParser.NextIntParam(iTPDULength);
+ // Get status
+ TInt retStat = iATCmdParser.NextIntParam(iTPDUStat);
+ // Get other parameters
+ TInt retOther = iATCmdParser.NextIntParam(otherParams);
+ // syntax error happens if
+ // a)there is no param 1
+ // b)there are 3 params
+ // c)param 2 is not 0,1,2 or 3
+ TBool noParam1 = (retLength != KErrNone);
+ TBool badParam2 = (retStat == KErrGeneral);
+ TBool tooManyParams = (retOther != KErrNotFound);
+
+ if (noParam1 || badParam2 || tooManyParams)
+ {
+ ret = KErrArgument;
+ }
+ else
+ {
+ switch (iTPDUStat)
+ {
+ case 0:
+ // to receive unread message
+ iMessageStatus = RMobileSmsStore::EStoredMessageUnread;
+ break;
+ case 1:
+ // to receive read message
+ iMessageStatus = RMobileSmsStore::EStoredMessageRead;
+ break;
+ case 2:
+ // Unsent is not supported in this version
+ ret = KErrNotSupported;
+ break;
+ case 3:
+ // Sent is not supported in this version
+ ret = KErrNotSupported;
+ break;
+ default:
+ ret = KErrArgument;
+ break;
+ }
+ iEntry.iMsgStatus = iMessageStatus;
+ }
+
+ TRACE_FUNC_EXIT
+ return ret;
+ }
+
+/**
+ * Create an SMS entry from the PDU string
+ */
+TInt CCMGWCommandHandler::CreateSmsEntry()
+ {
+ TRACE_FUNC_ENTRY
+
+ TInt err = KErrNone;
+
+ // Check the length
+ if (iTPDU.Length() != (iSCALength+iTPDULength+1)*2)
+ {
+ TRACE_FUNC_EXIT
+ return KErrArgument;
+ }
+
+ RBuf8 buf;
+ err = buf.Create(iTPDULength);
+ if (err != KErrNone)
+ {
+ TRACE_FUNC_EXIT
+ return err;
+ }
+ // Convert to binary format
+ for(TInt i=(iSCALength+1)*2; i< iTPDU.Length(); i+=2)
+ {
+ TLex8 lex(iTPDU.Mid(i, 2));
+ TUint8 val = 0;
+ err = lex.Val(val, EHex);
+ if (err != KErrNone)
+ {
+ buf.Close();
+ TRACE_FUNC_EXIT
+ return err;
+ }
+ buf.Append(val);
+ }
+ iEntry.iMsgData.Copy(buf);
+
+ buf.Close();
+ TRACE_FUNC_EXIT
+ return KErrNone;
+ }
+
+/**
+ * Extract the SMS service center address from the head of PDU string
+ */
+TInt CCMGWCommandHandler::ExtractSCA()
+ {
+ TRACE_FUNC_ENTRY
+
+ TInt err = KErrNone;
+ TLex8 lex;
+ RMobilePhone::TMobileAddress sca;
+ // SCA length
+ lex.Assign(iTPDU.Left(2));
+ err = lex.Val(iSCALength, EHex);
+ if (err != KErrNone)
+ {
+ TRACE_FUNC_EXIT
+ return err;
+ }
+ TInt length = iTPDU.Length();
+ if (iSCALength == 0)
+ {
+ // Service center is not found in PDU
+ err = KErrNotFound;
+ }
+ else if (iSCALength > (length-2)/2)
+ {
+ // Service certer length error
+ err = KErrArgument;
+ }
+ else
+ {
+ // SCA is given
+ // Parse SCA TON and NPI
+ TUint8 val = 0;
+ lex.Assign(iTPDU.Mid(2,2));
+ err = lex.Val(val, EHex);
+ if (err != KErrNone)
+ {
+ TRACE_FUNC_EXIT
+ return err;
+ }
+ TUint8 ton = (val&KSCATonBitMask)>>4;
+ TUint8 npi = val&KSCANpiBitMask;
+ switch (ton) // TON
+ {
+ case 0: // 000
+ sca.iTypeOfNumber = RMobilePhone::EUnknownNumber;
+ break;
+ case 1: // 001
+ sca.iTypeOfNumber = RMobilePhone::EInternationalNumber;
+ sca.iTelNumber.Append('+');
+ break;
+ case 2: // 010
+ sca.iTypeOfNumber = RMobilePhone::ENationalNumber;
+ break;
+ default:
+ // CMCC doesn't support other types
+ TRACE_FUNC_EXIT
+ return KErrArgument;
+ }
+ switch (npi) // NPI
+ {
+ case 0: // 0000
+ sca.iNumberPlan = RMobilePhone::EUnknownNumberingPlan;
+ break;
+ case 1: // 0001
+ sca.iNumberPlan = RMobilePhone::EIsdnNumberPlan;
+ break;
+ default:
+ // CMCC doesn't support other number plans
+ TRACE_FUNC_EXIT
+ return KErrArgument;
+ }
+ // Extract SCA number
+ for (TInt i=4; i<(iSCALength+1)*2; i+=2)
+ {
+ sca.iTelNumber.Append(iTPDU[i+1]);
+ sca.iTelNumber.Append(iTPDU[i]);
+ }
+ if(sca.iTelNumber[sca.iTelNumber.Length()-1] == 'F'
+ || sca.iTelNumber[sca.iTelNumber.Length()-1] == 'f')
+ {
+ sca.iTelNumber.Delete(sca.iTelNumber.Length()-1, 1);
+ }
+ iServiceCentre = sca;
+ }
+ TRACE_FUNC_EXIT
+ return err;
+ }
+
+