diff -r 0b2439c3e397 -r 4545c04e61e1 cbsatplugin/atmisccmdplugin/src/cmgwcommandhandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cbsatplugin/atmisccmdplugin/src/cmgwcommandhandler.cpp Wed Aug 18 09:59:05 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 +#include +#include + +#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=, + */ +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; + } + +