cbsatplugin/atmisccmdplugin/src/cmgwcommandhandler.cpp
changeset 45 b0aebde9b1fb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cbsatplugin/atmisccmdplugin/src/cmgwcommandhandler.cpp	Mon Jul 12 19:25:26 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;
+    }
+
+