/*
* Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "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:
*
*/



//  EXTERNAL RESOURCES

//  Include Files
#include <ctsy/serviceapi/mmtsy_ipcdefs.h>
#include <ctsy/pluginapi/cmmdatapackage.h>
#include <ctsy/serviceapi/ctsysatmessagingbase.h>
#include <etelsat.h>  // for sat mo sm control error values
#include <ctsy/serviceapi/gsmerror.h> // for sat mo sm control error values
#include <etelmmerr.h>
#include <tisi.h>
#include <smsisi.h>
#include <gsmuelem.h> // for tsmsfirstoctet
#include <ctsy/rmmcustomapi.h>
#include "cmmsmsmesshandler.h"
#include "cmmnetmesshandler.h"
#include "cmmsmsgsmaddress.h"
#include "cmmstaticutility.h"
#include "cmmmessagerouter.h"
#include "cmmphonemesshandler.h"
#include "tsylogger.h"
#include "cmmphonetsender.h"

#include "OstTraceDefinitions.h"
#ifdef OST_TRACE_COMPILER_IN_USE
#include "cmmsmsmesshandlerTraces.h"
#endif

//  External Data Structures
//  none

//  External Function Prototypes
//  none

//  LOCAL CONSTANTS AND MACROS
const TUint8 KSmsPadding( 0x00 ); // Filler byte for ISI messages
// const TUint8 KUnicodeCharLength( 2 ); Compiler warning removal

// The following constanst are for extracting information from TPDU
// See 3GPP 23.040.

// For submit and command types
const TUint8 KTpduIndexMessageParameters( 0 );
const TUint8 KTpduIndexMessageReference( 1 );

// SMS submit type specific costanst
const TUint8 KTpduSubmitIndexDestinationAddressLength( 2 );
const TUint8 KTpduSubmitIndexProtocolIdentifier( 4 );
const TUint8 KTpduSubmitIndexDataCodingScheme( 5 );
const TUint8 KTpduSubmitIndexValidityperiod( 6 );
// User data length index when no validity period
const TUint8 KTpduSubmitIndexUserDataLengthIfNoTpVp( 6 );
// User data length index when validity period length is 1
const TUint8 KTpduSubmitIndexUserDataLengthVpfRelative( 7 );
// User data length index when validity period length is 7
const TUint8 KTpduSubmitIndexUserDataLengthVpfAbsoluteEnchanced( 13 );

// SMS command type specific constants
const TUint8 KTpduCommandIndexProtocolIdentifier( 2 );
const TUint8 KTpduCommandIndexType( 3 );
const TUint8 KTpduCommandIndexMessageNumber( 4 );
const TUint8 KTpduCommandIndexDestinationAddressLength( 5 );
const TUint8 KTpduCommandIndexUserDataLength( 7 );

// const TUint8 KSizeOfAlphaTag( 34 ); Compiler warning removal
const TUint8 KSmsScTimeStampMaxLength( 7 );

// Constanst for SMS parameters
const TUint8 KSmsMandatoryParamsLength( 28 );
const TUint8 KSmsMaxAddressLength( 12 );
const TUint8 KSmsParamsParamIndicatorOffset( 0 );
const TUint8 KSmsParamsDestAddressOffset( 1 );
const TUint8 KSmsParamsScAddressOffset( 13 );
const TUint8 KSmsParamsProtocolIdOffset( 25 );
const TUint8 KSmsParamsDcsOffset( 26 );
const TUint8 KSmsParamsValidityPeriodOffset( 27 );
const TUint8 KSizeOfAlphaTag( 62 );

const TUint8 KShift8( 8 );
const TUint16 KSmsResIdMoSmInitDisable( 0 ); // SMS_RES_ID_MO_SM_INIT_DISABLE

//  MODULE DATA STRUCTURES

//  Local Data Structures
//  none

//  Local Function Prototypes
//  none

//  LOCAL FUNCTIONS
//  none

//  MEMBER FUNCTIONS

//=============================================================================


// -----------------------------------------------------------------------------
// CMmSmsMessHandler::CMmSmsMessHandler
// C++ default constructor
// -----------------------------------------------------------------------------
//
CMmSmsMessHandler::CMmSmsMessHandler()
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::CMmSmsMessHandler: constructor.");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_CMMSMSMESSHANDLER_TD, "CMmSmsMessHandler::CMmSmsMessHandler" );
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::CMmSmsMessHandler
// C++ default destructor
// -----------------------------------------------------------------------------
//
CMmSmsMessHandler::~CMmSmsMessHandler()
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::CMmSmsMessHandler: destructor.");
OstTrace0( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_CMMSMSMESSHANDLER_TD, "CMmSmsMessHandler::~CMmSmsMessHandler" );
    // Delete arrays
    if( iSmsListArray )
        {
        iSmsListArray->ResetAndDestroy();
        delete iSmsListArray;
        }

    if( iSmspListArray )
        {
        iSmspListArray->ResetAndDestroy();
        delete iSmspListArray;
        }
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::NewL
// Creates a new Gsm specific SmsMessageHandler object instance
// -----------------------------------------------------------------------------
//
CMmSmsMessHandler* CMmSmsMessHandler::NewL(
    CMmPhoNetSender* aPhoNetSender,      // pointer to PhoNet sender
    CMmPhoNetReceiver* aPhoNetReceiver,  // pointer to PhoNet receiver
    CMmMessageRouter* aMessageRouter,    // pointer to Message router
    CMmUiccMessHandler* aUiccMessHandler // pointer to UICC message handler
    )
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::NewL");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_NEWL_TD, "CMmSmsMessHandler::NewL" );
    CMmSmsMessHandler* smsMessHandler = new ( ELeave ) CMmSmsMessHandler();

    CleanupStack::PushL( smsMessHandler );
    smsMessHandler->iPhoNetSender = aPhoNetSender;
    smsMessHandler->iPhonetReceiver = aPhoNetReceiver;
    smsMessHandler->iMessageRouter = aMessageRouter;
    smsMessHandler->iMmUiccMessHandler = aUiccMessHandler;
    smsMessHandler->ConstructL();
    aPhoNetReceiver->RegisterL( smsMessHandler, PN_SMS );
    CleanupStack::Pop( smsMessHandler );

    return smsMessHandler;
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::ConstructL
// Initialises object attributes
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::ConstructL()
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::ConstructL");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_CONSTRUCTL_TD, "CMmSmsMessHandler::ConstructL" );
    iSmsListArray = new ( ELeave ) CArrayPtrFlat<TSmsMsg>( 1 );
    iSmspListArray = new ( ELeave ) CArrayPtrFlat<TSmsParameters>( 1 );

    iReceivedClass2ToBeReSent = EFalse;
    // default bearer setting is "CS preferred"
    iMobileSmsBearer = RMobileSmsMessaging::ESmsBearerCircuitPreferred;

    // Reading of SMSP entries starts from record 1
    iSmspRecordNumber = 1;
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::ReceiveMessageL
// Called by PhonetReceiver when an ISI message has been received
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::ReceiveMessageL( const TIsiReceiveC& aIsiMessage )
    {
    TUint8 resource( aIsiMessage.Get8bit( ISI_HEADER_OFFSET_RESOURCEID ) );
    TUint8 messageId( aIsiMessage.Get8bit( ISI_HEADER_OFFSET_MESSAGEID ) );

TFLOGSTRING3("TSY: CMmSmsMessHandler::ReceiveMessageL - resource: %d, msgId: %d", resource, messageId);
OstTraceExt2( TRACE_NORMAL, CMMSMSMESSHANDLER_RECEIVEMESSAGEL_TD,"CMmSmsMessHandler::ReceiveMessageL;resource=%hhu;messageId=%hhu", resource, messageId );

    switch ( resource )
        {
        case PN_SMS:
            {
            switch( messageId )
                {
                case SMS_MESSAGE_SEND_RESP:
                    {
                    // check transaction id type
                    TUint8 traId( aIsiMessage.Get8bit(
                        ISI_HEADER_OFFSET_TRANSID ) );
                    if ( ESmsMessagingSendMessage == traId )
                        {
                        // SMS Messaging-originated SendSMS
                        SmsMessageSendResp( aIsiMessage,
                            EMobileSmsMessagingSendMessage );
                        }
                    else if ( ESmsMessagingSendNoFdnMessage == traId )
                        {
                        SmsMessageSendResp( aIsiMessage,
                            EMobileSmsMessagingSendMessageNoFdnCheck );
                        }
                    else if ( ESmsMessagingSendSatMessage == traId )
                        {
                        // SAT-originated SendSMS
                        SmsMessageSendResp( aIsiMessage,
                            EMmTsySmsSendSatMessage );
                        }
                    else
                        {
TFLOGSTRING2("TSY:CMmSmsMessHandler::ReceiveMessageL:Unexpected transId=%d in SMS_MESSAGE_SEND_RESP.",traId);
OstTraceExt1( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_RECEIVEMESSAGEL_TD, "CMmSmsMessHandler::ReceiveMessageL;traId=%hhu", traId );
                        }
                    break;
                    }
                case SMS_RECEIVE_MESSAGE_RESP:
                    {
                    SmsReceiveMessageResp( aIsiMessage );
                    break;
                    }
                case SMS_RECEIVED_MSG_IND:
                    {
                    SmsReceivedMsgInd( aIsiMessage );
                    break;
                    }
                case SMS_RECEIVED_MSG_REPORT_RESP:
                    {
                    SmsReceivedMsgReportResp( aIsiMessage );
                    break;
                    }
                case SMS_SETTINGS_UPDATE_RESP :
                    {
                    SmsSettingsUpdateResp( aIsiMessage );
                    break;
                    }
                case SMS_RESOURCE_CONF_IND:
                    {
                	  SmsResourceConfInd( aIsiMessage );
                	  break;
                    }
                default:
                    {
TFLOGSTRING2("TSY: CMmSmsMessHandler::ReceiveMessageL - PN_SMS - unknown msgId: %d", messageId);
OstTraceExt1( TRACE_NORMAL,  DUP2_CMMSMSMESSHANDLER_RECEIVEMESSAGEL_TD, "CMmSmsMessHandler::ReceiveMessageL;messageId=%hhu", messageId );
                    // No handler methods for ISI-message found.
                    break;
                    }
                }
            break;
            }
        default:
            {
TFLOGSTRING2("TSY: CMmSmsMessHandler::ReceiveMessageL - unknown resource: %d", resource);
OstTraceExt1( TRACE_NORMAL,  DUP6_CMMSMSMESSHANDLER_RECEIVEMESSAGEL_TD, "CMmSmsMessHandler::ReceiveMessageL;resource=%hhu", resource );
            // No handler methods for ISI-message found.
            break;
            }
        }
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::SmsMessageSendReq
// Creates request for SMS message sending
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::SmsMessageSendReq(
    TUint8 aTransactionId,              // Transaction ID
    const CMmDataPackage* aDataPackage, // Packed data
    TBool aSmsCheckDisableFdn )         // Add SMS_SB_CHECK_INFO with
                                        // SMS_CHECK_DISABLE_FDN

    {
TFLOGSTRING2("TSY: CMmSmsMessHandler::SmsMessageSendReq. Transaction ID: %d", aTransactionId);
OstTraceExt1( TRACE_NORMAL,DUP18_CMMSMSMESSHANDLER_SMSMESSAGESENDREQ_TD,"CMmSmsMessHandler::SmsMessageSendReq;aTransactionId=%hhu", aTransactionId );

    TInt ret( KErrNone );
    TUint8 subBlockId( 0 );

    // Structure for all SMS parameters and user data
    TSendSmsDataAndAttributes sendData;
    // Structure for message attributes
    RMobileSmsMessaging::TMobileSmsSendAttributesV1* msgAttr;
    // Buffer for TPDU
    TBuf8<RMobileSmsMessaging::KGsmTpduSize> msgData;

    aDataPackage->UnPackData( sendData );
    msgAttr = sendData.iAttributes;

    // Check TPDU length
    if ( RMobileSmsMessaging::KGsmTpduSize >= sendData.iMsgData->Length() )
        {
        msgData.Append( *sendData.iMsgData );

        // Get TP-MTI (TP-Message-Type-Indicator) from first octet of TPDU
        TUint8 tpMti( msgData[KTpduIndexMessageParameters] &
            TSmsFirstOctet::ESmsMTIMask );
        if ( TSmsFirstOctet::ESmsMTISubmitOrSubmitReport == tpMti )
            {
            subBlockId = SMS_SB_SUBMIT;
            }
        else if ( TSmsFirstOctet::ESmsMTIStatusReportOrCommand == tpMti )
            {
            subBlockId = SMS_SB_COMMAND;
            }
        else // Message type not supported
            {
            ret = CMmStaticUtility::EpocErrorCode(
                KErrArgument,
                KErrGsmSMSTpduNotSupported );
TFLOGSTRING2("TSY: CMmSmsMessHandler::SmsMessageSendReq. Error! SMS type not supported: %d", tpMti);
OstTraceExt1( TRACE_NORMAL,  DUP3_CMMSMSMESSHANDLER_SMSMESSAGESENDREQ_TD, "CMmSmsMessHandler::SmsMessageSendReq.Error! SMS type not supported;tpMti=%hhu", tpMti );
            }
        }
    else
        {
        // TPDU too long
        ret = CMmStaticUtility::EpocErrorCode(
            KErrArgument,
            KErrGsmSMSTpduNotSupported );
TFLOGSTRING2("TSY: CMmSmsMessHandler::SmsMessageSendReq. Error! TPDU too long: %d", sendData.iMsgData->Length());
OstTrace1( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_SMSMESSAGESENDREQ_TD, "CMmSmsMessHandler::SmsMessageSendReq.Error! TPDU too long;sendData.iMsgData->Length()=%d", sendData.iMsgData->Length() );
        }

    // Check the format of TPDU and data buffer
    if ( ! ( RMobileSmsMessaging::KSmsDataFormat & msgAttr->iFlags &&
        RMobileSmsMessaging::EFormatGsmTpdu & msgAttr->iDataFormat ) )
        {
        ret = CMmStaticUtility::EpocErrorCode(
            KErrArgument,
            KErrGsmSMSTpduNotSupported );
TFLOGSTRING3("TSY: CMmSmsMessHandler::SmsMessageSendReq. Error! Invalid TPDU format (%d) or data buffer format (%d)", msgAttr->iFlags, msgAttr->iDataFormat );
OstTraceExt2( TRACE_NORMAL,  DUP2_CMMSMSMESSHANDLER_SMSMESSAGESENDREQ_TD, "CMmSmsMessHandler::SmsMessageSendReq.Error!;msgAttr->iFlags=%d;msgAttr->iDataFormat=%hhu", msgAttr->iFlags, msgAttr->iDataFormat );
        }

#if (NCP_COMMON_S60_VERSION_SUPPORT>S60_VERSION_32)
    // Check whether there is SMS sending ongoing.
    if ( iSMSSendingOngoing )
        {
        ret = KErrServerBusy;
TFLOGSTRING("TSY: CMmSmsMessHandler::SmsMessageSendReq. SMS sending failed, server busy!" );
OstTrace0( TRACE_NORMAL,  DUP17_CMMSMSMESSHANDLER_SMSMESSAGESENDREQ_TD, "CMmSmsMessHandler::SmsMessageSendReq. SMS sending failed, server busy!" );
        }
#endif // NCP_COMMON_S60_VERSION_SUPPORT

    if ( KErrNone == ret )
        {
        // Create and send SMS_MESSAGE_SEND_REQ message with needed subblocks
        ret = CreateSmsMessageSendReq(
            aTransactionId,
            msgAttr,
            msgData,
            subBlockId,
            aSmsCheckDisableFdn );
        }

    return ret;
    }


// -----------------------------------------------------------------------------
// CMmSmsMessHandler::CreateSmsMessageSendReq
// Construct a SMS_MESSAGE_SEND_REQ ISI message with needed subblocks
// for SMS message send request to SMS server
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::CreateSmsMessageSendReq(
    TUint8 aTransactionId,
    RMobileSmsMessaging::TMobileSmsSendAttributesV1* aMsgAttr,
    const TDesC8& aMsgData,
    TUint8 aSubblockId,
    TBool aSmsCheckDisableFdn )         // Add SMS_SB_CHECK_INFO with
                                        // SMS_CHECK_DISABLE_FDN

    {
    // Structure of the message, depending on the TP-MTI:
    // SMS_MESSAGE_SEND_REQ (8 bytes + sub blocks, total max. 212)
    //  |
    //  |- SMS_SB_SUBMIT (mandatory, 8 bytes)
    //  |
    //  |- SMS_SB_ADDRESS (destination address, mandatory, max. 20 bytes)
    //  |
    //  |- SMS_SB_ADDRESS (service center address, mandatory, max. 20 bytes)
    //  |
    //  |- SMS_SB_USER_DATA (optional, max. 148 bytes)
    //  |
    //  |- SMS_SB_VALIDITY_PERIOD (optional, max. 12 bytes)
    //
    // or
    //
    // SMS_MESSAGE_SEND_REQ (8 bytes + sub blocks, total max. 220)
    //  |
    //  |- SMS_SB_COMMAND (mandatory, 12 bytes)
    //  |
    //  |- SMS_SB_ADDRESS (destination address, mandatory, max. 20 bytes)
    //  |
    //  |- SMS_SB_ADDRESS (service center address, mandatory, max. 20 bytes)
    //  |
    //  |- SMS_SB_USER_DATA (optional, max. 174 bytes)

TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. Subblock ID: %d", aSubblockId);
OstTraceExt1( TRACE_NORMAL,  DUP9_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ_TD, "CMmSmsMessHandler::CreateSmsMessageSendReq;aSubblockId=%hhu", aSubblockId );

    TInt ret( KErrNone );
    TUint8 addressLength( 0 );
    ret = GetDestAddressLength( aMsgData, aSubblockId, addressLength );

    // Destination address is OK. Create ISI message and needed subblocks
    if ( KErrNone == ret )
        {
        TUint8 moreMsgToSend( 0 );
        TUint8 smsRoute( SMS_ROUTE_DEFAULT );
        TUint8 tpVpLength( 0 );
        TUint8 tpVpf( 0 );
        TUint8 tpUdl( 0 );
        TUint8 tpUserDataLengthIndex( KTpduSubmitIndexUserDataLengthIfNoTpVp );
        TUint8 tpUserDataIndex( 0 );
        TUint8 tpDaIndex( KTpduSubmitIndexDestinationAddressLength );
        TUint8 tpDcs( 0 );
        TUint8 msgOffset( ISI_HEADER_SIZE + SIZE_SMS_MESSAGE_SEND_REQ );
        TUint8 numOfSubblocks( 3 ); // 3 mandatory subblocks
        TBool defaultAlphabet( EFalse ); // Data coding type, true if 7-bit

        // Check if more to send parameter is included
        if ( RMobileSmsMessaging::KMoreToSend & aMsgAttr->iFlags )
            {
            moreMsgToSend = static_cast<TUint8>( aMsgAttr->iMore );
            }

        // Set the bearer
        if ( RMobileSmsMessaging::ESmsBearerPacketOnly == iMobileSmsBearer )
            {
            smsRoute = SMS_ROUTE_PS;
            }
        else if ( RMobileSmsMessaging::ESmsBearerCircuitOnly ==
            iMobileSmsBearer )
            {
            smsRoute = SMS_ROUTE_CS;
            }
        // No else. SMS_ROUTE_DEFAULT is used. The route is used that is
        // available and preferred by PP-bits or prior client settings

        // Create SMS_MESSAGE_SEND_REQ message
        TIsiSend isiMsg( iPhoNetSender->SendBufferDes() );
        isiMsg.Set8bit( ISI_HEADER_OFFSET_RESOURCEID, PN_SMS );
        isiMsg.Set8bit(
            ISI_HEADER_SIZE + SMS_MESSAGE_SEND_REQ_OFFSET_TRANSID,
            aTransactionId );
        isiMsg.Set8bit(
            ISI_HEADER_SIZE + SMS_MESSAGE_SEND_REQ_OFFSET_MESSAGEID,
            SMS_MESSAGE_SEND_REQ );
        isiMsg.Set8bit(
            ISI_HEADER_SIZE + SMS_MESSAGE_SEND_REQ_OFFSET_MOREMESSAGESTOSEND,
            moreMsgToSend );
        isiMsg.Set8bit(
            ISI_HEADER_SIZE + SMS_MESSAGE_SEND_REQ_OFFSET_SMSROUTE,
            smsRoute );
        // Set repeatedMessage to FALSE. Tsy doesn't know if message is tried
        // to send first or second time.
        isiMsg.Set8bit(
            ISI_HEADER_SIZE + SMS_MESSAGE_SEND_REQ_OFFSET_REPEATEDMESSAGE,
            EFalse );
        // Filler, two bytes
        isiMsg.Set16bit(
            ISI_HEADER_SIZE + SMS_MESSAGE_SEND_REQ_OFFSET_FILLERBYTE1,
            0 );

TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_MESSAGE_SEND_REQ created. Message offset: %d", msgOffset );
TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. More messages to be sent: %d", moreMsgToSend);
TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. SMS route: %d", smsRoute);
OstTraceExt3( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ_TD, "CMmSmsMessHandler::CreateSmsMessageSendReq;msgOffset=%hhu;moreMsgToSend=%hhu;smsRoute=%hhu", msgOffset, moreMsgToSend, smsRoute );

        // Create SMS_SB_SUBMIT subblock
        if ( SMS_SB_SUBMIT == aSubblockId )
            {
            msgOffset += BuildSmsSbSubmit( aMsgData, isiMsg, addressLength, msgOffset );
TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_SUBMIT created. Message offset: %d", msgOffset );
OstTraceExt1( TRACE_NORMAL,  DUP2_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ_TD, "CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_SUBMIT created.;msgOffset=%hhu", msgOffset );
            // Set needed TPDU index values that depends on SMS type, VP existence
            // and destination address length. Those parameters are needed when
            // creating subblocks SMS_DESTINATION_ADDRESS, SMS_SB_VALIDITY_PERIOD
            // and SMS_SB_USER_DATA.
            // TP-VPF is LSB bits 3 and 4 from the first octect of TPDU
            tpVpf = ( aMsgData[KTpduIndexMessageParameters] >> 3 ) & 3;
            if ( tpVpf )
                {
                // Relative format (tpVpf == 2).
                // Subblock length SIZE_SMS_SB_VALIDITY_PERIOD by default
                if ( 2 == tpVpf)
                    {
                    tpVpLength = SMS_VPF_RELATIVE;
                    tpUserDataLengthIndex =
                        KTpduSubmitIndexUserDataLengthVpfRelative;
                    }
                // Absolute or enhanced format, subblock length is 12
                else
                    {
                    tpVpLength = SMS_VPF_ABSOLUTE_OR_ENHANCED;
                    tpUserDataLengthIndex =
                        KTpduSubmitIndexUserDataLengthVpfAbsoluteEnchanced;
                    }
                }
                // No else. If no TP-VP, User data length index was set to
                // 'KTpduSubmitIndexUserDataLengthIfNoTpVp' by default
            }
        else // Create SMS_SB_COMMAND subblock
            {
            msgOffset += BuildSmsSbCommand( aMsgData, isiMsg, msgOffset );
TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_COMMAND created. Message offset: %d", msgOffset );
OstTraceExt1( TRACE_NORMAL,  DUP3_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ_TD, "CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_COMMAND created.;msgOffset=%hhu", msgOffset );
            tpDaIndex = KTpduCommandIndexDestinationAddressLength;
            tpUserDataLengthIndex = KTpduCommandIndexUserDataLength;
            }

TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. Validity period format: %d", tpVpf);
TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. User data length index: %d", tpUserDataLengthIndex);
OstTraceExt2( TRACE_NORMAL,  CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ_TD, "CMmSmsMessHandler::CreateSmsMessageSendReq;tpVpf=%hhu;tpUserDataLengthIndex=%hhu", tpVpf, tpUserDataLengthIndex );

        // Create SMS_SB_ADDRESS subblock for destination address
        // TP-DA length = Length (1 byte) + TON/NPI (1 byte) + address data
        TPtrC8 addressData( aMsgData.Mid( tpDaIndex, ( addressLength + 2 ) ) );
        msgOffset += BuildSmsSbAddress(
            addressData,
            isiMsg,
            SMS_DESTINATION_ADDRESS,
            msgOffset );
TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_ADDRESS created for destination address. Message offset: %d", msgOffset );
OstTraceExt1( TRACE_NORMAL,  DUP4_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ_TD, "CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_ADDRESS created for destination address.;msgOffset=%hhu", msgOffset );

        // Create SMS_SB_ADDRESS subblock for service center address
        TBuf8<SMS_ADDRESS_MAX_LEN> scAddr;
        BuildScAddress( aMsgAttr->iGsmServiceCentre, scAddr );
        msgOffset +=
            BuildSmsSbAddress( scAddr, isiMsg, SMS_SMSC_ADDRESS, msgOffset );
TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_ADDRESS created for SC address. Message offset: %d", msgOffset );
OstTraceExt1( TRACE_NORMAL,  DUP5_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ_TD, "CMmSmsMessHandler::CreateSmsMessageSendReq.SMS_SB_ADDRESS created for SC address.;msgOffset=%hhu", msgOffset );

        // Create SMS_SB_VALIDITY_PERIOD subblock (optional, used only in
        // case of SMS_SB_SUBMIT)
        if ( SMS_SB_SUBMIT == aSubblockId && tpVpf )
            {
            TUint8 tpVpIndex(
                KTpduSubmitIndexValidityperiod + addressLength );
            msgOffset += BuildSmsSbValidityPeriod(
                aMsgData,
                isiMsg,
                tpVpIndex,
                tpVpLength,
                msgOffset );
            numOfSubblocks++;
TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_VALIDITY_PERIOD created. Message offset: %d", msgOffset );
OstTraceExt1( TRACE_NORMAL,  DUP6_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ_TD, "CMmSmsMessHandler::CreateSmsMessageSendReq.SMS_SB_VALIDITY_PERIOD created.;msgOffset=%hhu", msgOffset );
            }

        // Create SMS_SB_USER_DATA subblock if user data exists
        // Destination address length must be added to get user data
        // length index
        tpUserDataLengthIndex += addressLength;
        tpUdl = aMsgData[tpUserDataLengthIndex];
TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. User data length from TPDU: %d", tpUdl);
OstTrace1( TRACE_NORMAL,  DUP10_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ_TD, "CMmSmsMessHandler::CreateSmsMessageSendReq;tpUdl=%d", tpUdl );

        if ( tpUdl )
            {
            // Actual user data is next index from TP-UDL position
            tpUserDataIndex = tpUserDataLengthIndex + 1;
            if ( SMS_SB_SUBMIT == aSubblockId )
                {
                tpDcs = aMsgData[ KTpduSubmitIndexDataCodingScheme + addressLength ];
                defaultAlphabet = IsDataCodingScheme7Bit( tpDcs );
                }
            msgOffset += BuildSmsSbUserData(
                aMsgData,
                isiMsg,
                tpUdl,
                tpUserDataIndex,
                defaultAlphabet,
                msgOffset );
            numOfSubblocks++;
TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_USER_DATA created. Message offset: %d", msgOffset );
OstTraceExt1( TRACE_NORMAL,  DUP7_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ_TD, "CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_USER_DATA created.;msgOffset=%hhu", msgOffset );
            }

        // Create SMS_SB_CHECK_INFO subblock if user data exists
        // Destination address length must be added to get user data
        // length index
        if ( aSmsCheckDisableFdn )
            {
            msgOffset += BuildSmsCheckInfo(
                isiMsg,
                msgOffset );
            numOfSubblocks++;
TFLOGSTRING("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_CHECK_INFO created." );
OstTrace0( TRACE_NORMAL,  DUP11_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ_TD, "CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_CHECK_INFO created." );
            }


#if (NCP_COMMON_S60_VERSION_SUPPORT>S60_VERSION_32)
        iSMSSendingOngoing = ETrue;
#endif //NCP_COMMON_S60_VERSION_SUPPORT

        // Set number of subblocks and then send message via phonet
        isiMsg.Set8bit(
            ISI_HEADER_SIZE + SMS_MESSAGE_SEND_REQ_OFFSET_SUBBLOCKCOUNT,
            numOfSubblocks );
        ret = iPhoNetSender->Send( isiMsg.Complete() );

TFLOGSTRING3("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_MESSAGE_SEND_REQ was sent. Number of subblocks in message: %d, ret = %d", numOfSubblocks, ret  );
OstTraceExt2( TRACE_NORMAL,  DUP8_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ_TD, "CMmSmsMessHandler::CreateSmsMessageSendReq.SMS_MESSAGE_SEND_REQ was sent.;numOfSubblocks=%hhu;ret=%d", numOfSubblocks, ret );
        } // End of if destination address is OK

    return ret;
    }


// -----------------------------------------------------------------------------
// CMmSmsMessHandler::SmsReceiveMessageReq
// Construct a SMS_RECEIVE_MESSAGE_REQ ISI message for activating SMS receiving
// and send it to SMS server
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::SmsReceiveMessageReq( TUint8 aAction )
    {
TFLOGSTRING2("TSY: CMmSmsMessHandler::SmsReceiveMessageReq. Action = %d",aAction );
OstTraceExt1( TRACE_NORMAL,  CMMSMSMESSHANDLER_SMSRECEIVEMESSAGEREQ_TD, "CMmSmsMessHandler::SmsReceiveMessageReq;aAction=%hhu", aAction );

    TUint8 trId( 0 );
    if ( SMS_RECEPTION_STORAGE_STATUS_UPDATE == aAction )
        {
        trId = ESmsMessagingResumeSmsReception;
        }

    TIsiSend isiMsg( iPhoNetSender->SendBufferDes() );
    isiMsg.Set8bit( ISI_HEADER_OFFSET_RESOURCEID, PN_SMS );
    isiMsg.Set8bit(
        ISI_HEADER_SIZE + SMS_RECEIVE_MESSAGE_REQ_OFFSET_TRANSID, trId );
    isiMsg.Set8bit(
        ISI_HEADER_SIZE + SMS_RECEIVE_MESSAGE_REQ_OFFSET_MESSAGEID,
        SMS_RECEIVE_MESSAGE_REQ );
    isiMsg.Set8bit(
        ISI_HEADER_SIZE + SMS_RECEIVE_MESSAGE_REQ_OFFSET_ACTION, aAction );
    isiMsg.Set8bit(
        ISI_HEADER_SIZE + SMS_RECEIVE_MESSAGE_REQ_OFFSET_FILLERBYTE1,
        KSmsPadding );

    return iPhoNetSender->Send( isiMsg.Complete() );
    }

// --------------------------------------------------------------------------
// CMmSmsMessHandler::SmsReceivedMsgReportReq
// Construct a SMS_RECEIVED_MSG_REPORT_REQ ISI message sub block for received
// SMS report request to the SMS server
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::SmsReceivedMsgReportReq(
    TUint8 aTransactionId,      // Transaction identifier
    const TDesC8* aMsgData,     // A pointer to the message data
    TInt aRpCause )             // RP cause value
    {
    // Structure of the message:
    // SMS_RECEIVED_MSG_REPORT_REQ (8 bytes + sub blocks. Max. total 204 bytes)
    //  |
    //  |- SMS_SB_DELIVER_REPORT (optional, included in NACK case
    //  |                         8 bytes )
    //  |- SMS_SB_PARAM_INDICATOR (optional, included if PDU (aMsgData) is not
    //  |                          empty. Max. 20 bytes)
    //  |- SMS_SB_USER_DATA (optional, included if PDU contains user data.
    //                       Max. 8  + SMS_GSM_DELIVER_ACK_UD_MAX_LEN
    //                       + padding = 168 bytes)

TFLOGSTRING3("TSY: CMmSmsMessHandler::SmsReceivedMsgReportReq - traId: %d, RP cause value: %d", aTransactionId, aRpCause);
OstTraceExt2( TRACE_NORMAL,  CMMSMSMESSHANDLER_SMSRECEIVEDPPREPORTREQ_TD, "CMmSmsMessHandler::SmsReceivedMsgReportReq;aTransactionId=%hhu;aRpCause=%d", aTransactionId, aRpCause );

    TInt ret( KErrNone );
    TUint8 numOfSubblocks( 0 ); // All subblocks are optional
    TUint8 tpFailureCause( 0 );
    TUint8 causeType( 0 ); // SMS_CAUSE_TYPE_COMMON
    TUint8 smsCause( 0 ); // SMS_CAUSE_OK
    TUint8 messageParameters( 0 ); // Default message parameters
    TUint8 sbOffset( ISI_HEADER_SIZE + SIZE_SMS_RECEIVED_MSG_REPORT_REQ );
    TUint8 paramIndSbLength( SIZE_SMS_SB_PARAM_INDICATOR );
    TBool userDataIncluded( EFalse );

    // Create SMS_SB_DELIVER_REPORT. Buffer size must be 168
    // (subblock size + user data). This subblock is added to message only
    // in NACK case.
    TBuf8<SIZE_SMS_SB_DELIVER_REPORT> deliverReportBuf;
    TIsiSubBlock deliverReportSb(
        deliverReportBuf,
        SMS_SB_DELIVER_REPORT,
        EIsiSubBlockTypeId16Len16 );

    // Create SMS_SB_USER_DATA. This subblock is added to message only if
    // user data exists
    TBuf8<SIZE_SMS_SB_USER_DATA + SMS_DELIVER_ACK_UD_MAX_LEN>
        userDataBuf;
    TIsiSubBlock userDataSb(
        userDataBuf,
        SMS_SB_USER_DATA,
        EIsiSubBlockTypeId16Len16 );

    // Create SMS_SB_PARAM_INDICATOR. This subblock is added to message only
    // if user data exists
    TBuf8<20> paramIndicatorBuf;
    TIsiSubBlock paramIndicatorSb(
         paramIndicatorBuf,
         SMS_SB_PARAM_INDICATOR,
         EIsiSubBlockTypeId16Len16 );

    // If RP Cause value is other than KErrNone, values of the cause type and the
    // SMS cause must be defined. In this case we also include subblock
    // SMS_SB_DELIVER_REPORT.
    if ( KErrNone != aRpCause )
        {
        causeType = SMS_CAUSE_TYPE_EXT;
        smsCause = SmsMapCause( aRpCause );
        numOfSubblocks++;
        }

    // If message data is available
    if ( NULL != aMsgData && 0 < aMsgData->Length() )
        {
TFLOGSTRING2("TSY: CMmSmsMessHandler::SmsReceivedMsgReportReq. Message data availabe, length %d", aMsgData->Length());
OstTrace1( TRACE_NORMAL,  CMMSMSMESSHANDLER_SMSRECEIVEDMSGREPORTREQ_TD, "CMmSmsMessHandler::SmsReceivedMsgReportReq;aMsgData->Length()=%d", aMsgData->Length() );

        TUint8 ind( 0 );

        // Message parameters = 1st byte of deliver report
        messageParameters = ( *aMsgData )[ind++];

        // Message type indicator is 2 LSB in message parameters.
        TUint8 tpMti( messageParameters & 0x03 );

        // If both bits in the TP_MTI are 0, message type is
        // SMS DELIVER REPORT (3GPP 23.040 chapter 9.2.3.1)
        if ( 0 == tpMti )
            {
            TUint8 protocolInd( 0 );
            TUint8 dcs( 0 );
            TUint8 tpUdl( 0 );
            TPtrC8 userData( 0, 0 );

            if ( 0 != aRpCause )
                {
                tpFailureCause = ( *aMsgData )[ind++];
                }

            // Lets find out how many parameter indicators are there
            TBuf8<SMS_PARAM_INDICATOR_MAX_LEN> paramIndicator;
            TUint8 paramIndCount( 1 ); // There is at least one TP-PI
            TUint8 paramInd( 0 );
            TBool moreParamInd( ETrue );

            while ( moreParamInd )
                {
                paramInd = ( *aMsgData )[ind++];
                paramIndicator.Append( paramInd );
                paramInd = paramInd >> 7;

                // If true, another TP-PI octet follows immediately afterwards
                if ( KSmsDelRepParamIndExtensionBit == paramInd )
                    {
                    paramIndCount++;
                    }
                else
                    {
                    moreParamInd = EFalse;
                    }

                // Too many TP-PI octets -> this PDU is corrupted.
                if ( SMS_PARAM_INDICATOR_MAX_LEN < paramIndCount )
                    {
TFLOGSTRING2("TSY: CMmSmsMessHandler::SmsReceivedMsgReportReq. Error! Too mamy TP-PI parameters: %d", paramIndCount );
OstTraceExt1( TRACE_NORMAL,  DUP4_CMMSMSMESSHANDLER_SMSRECEIVEDMSGREPORTREQ_TD, "CMmSmsMessHandler::SmsReceivedMsgReportReq. Error!;paramIndCount=%hhu", paramIndCount );
                    ret = KErrArgument;
                    moreParamInd = EFalse;
                    }
                }

            // Calculate final length of SMS_SB_PARAM_INDICATOR, depends on
            // number of param indicators. Must be divisible by 4.
            if ( paramIndCount > 1)
                {
                // One param indicator has already counted
                paramIndSbLength += ( --paramIndCount );
                while( paramIndSbLength % 4 )
                    {
                    paramIndSbLength++;
                    }
                }

            // Lets take first TP-PI and check what fields this PDU includes
            paramInd = paramIndicator[0];
            TInt paramask( KSmsParametersIndMask & paramInd ); // Mask bits

            // Gather data from PDU using parameter indicator information
            if ( KSmsParametersIndProtocolId & paramask )
                {
                protocolInd = ( *aMsgData )[ind++];
                }
            if ( KSmsParametersIndDataCodingScheme & paramask )
                {
                dcs = ( *aMsgData )[ind++];
                }
            if ( KSmsParametersIndUserData & paramask )
                {
                tpUdl = ( *aMsgData )[ind++];
                }
TFLOGSTRING4("TSY: CMmSmsMessHandler::SmsReceivedMsgReportReq. protocolInd: %d, dcs: %d, tpUdl: %d", protocolInd, dcs, tpUdl );
OstTraceExt3( TRACE_NORMAL,  DUP2_CMMSMSMESSHANDLER_SMSRECEIVEDMSGREPORTREQ_TD, "CMmSmsMessHandler::SmsReceivedMsgReportReq;protocolInd=%hhu;dcs=%hhu;tpUdl=%hhu", protocolInd, dcs, tpUdl );

            // If user data exists, fill SMS_SB_USER_DATA and
            // SMS_SB_PARAM_INDICATOR subblocks
            if ( 0 < tpUdl )
                {
                TUint8 userDataLengthInBytes( 0 );
                userDataIncluded = ETrue;
                numOfSubblocks += 2;

                TBool defaultAlphabet( IsDataCodingScheme7Bit( dcs ) );
                // If data is 7bit, then TP-UDL is integer reprentation of
                // the number of septets within the TP-UD field.
                if ( defaultAlphabet )
                    {
                    // Data length in bytes
                    userDataLengthInBytes = ( ( tpUdl + 1 ) * 7 ) / 8 ;
                    }
                else
                    {
                    userDataLengthInBytes = tpUdl;
                    }

                // Append filler + user data length in bytes
                userDataBuf.Append( KSmsPadding );
                userDataBuf.Append( userDataLengthInBytes );
                // Append filler + amount of characters in user data
                userDataBuf.Append( KSmsPadding );
                userDataBuf.Append( tpUdl );
                // Append user data
                userData.Set( aMsgData->Mid( ind, userDataLengthInBytes ) );
                userDataBuf.Append( userData );

                paramIndicatorBuf.Append( protocolInd );
                paramIndicatorBuf.Append( dcs );
                paramIndicatorBuf.Append( paramIndicator.Length() );
                paramIndicatorBuf.Append( paramIndicator );
                } // End of if ( 0 < tpUdl )
            } // end of if ( 0 == tpMti )
        else
        // TP-MTI is other than SMS_GSM_DELIVER_REPORT, message is not sent
            {
TFLOGSTRING2("TSY: CMmSmsMessHandler::SmsReceivedMsgReportReq. Error! Invalid message type indicator: %d", tpMti);
OstTraceExt1( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_SMSRECEIVEDMSGREPORTREQ_TD, "CMmSmsMessHandler::SmsReceivedMsgReportReq;tpMti=%hhu", tpMti );
            ret = KErrArgument;
            }
        } // end of if ( NULL != aMsgData && 0 < aMsgData->Length() )
    else
        {
TFLOGSTRING("TSY: CMmSmsMessHandler::SmsReceivedMsgReportReq. No message data availabe!");
OstTrace0( TRACE_NORMAL,  DUP3_CMMSMSMESSHANDLER_SMSRECEIVEDMSGREPORTREQ_TD, "CMmSmsMessHandler::SmsReceivedMsgReportReq. No message data available" );
        // If memory capacity exceeded -> gsmTpfailureCause is 0
        if ( 0 != aRpCause && SMS_EXT_ERR_MEMORY_CAPACITY_EXC != smsCause  )
            {
            // 0xAF is unspecified TP-command error
            tpFailureCause = 0xAF;
            }
        }

    // Send SMS_RECEIVED_MSG_REPORT_REQ
    if ( KErrNone == ret )
        {
        // Create SMS_RECEIVED_MSG_REPORT_REQ message
        TIsiSend isiMsg( iPhoNetSender->SendBufferDes() );
        isiMsg.Set8bit( ISI_HEADER_OFFSET_RESOURCEID, PN_SMS );
        isiMsg.Set8bit(
            ISI_HEADER_SIZE + SMS_RECEIVED_MSG_REPORT_REQ_OFFSET_TRANSID,
            aTransactionId );
        isiMsg.Set8bit(
            ISI_HEADER_SIZE + SMS_RECEIVED_MSG_REPORT_REQ_OFFSET_MESSAGEID,
            SMS_RECEIVED_MSG_REPORT_REQ );
        isiMsg.Set8bit(
            ISI_HEADER_SIZE + SMS_RECEIVED_MSG_REPORT_REQ_OFFSET_CAUSETYPE,
            causeType );
        isiMsg.Set8bit(
            ISI_HEADER_SIZE + SMS_RECEIVED_MSG_REPORT_REQ_OFFSET_SMSCAUSE,
            smsCause );
        isiMsg.Set8bit( ISI_HEADER_SIZE +
            SMS_RECEIVED_MSG_REPORT_REQ_OFFSET_FILLERBYTE1,
            KSmsPadding );
        isiMsg.Set8bit( ISI_HEADER_SIZE +
            SMS_RECEIVED_MSG_REPORT_REQ_OFFSET_SUBBLOCKCOUNT,
            numOfSubblocks );

        // Add SMS_SB_DELIVER_REPORT if needed
        if ( 0 != aRpCause )
            {
            deliverReportBuf.Append( messageParameters );
            deliverReportBuf.Append( tpFailureCause);
            // Add SMS_SB_DELIVER_REPORT subblock
            isiMsg.CopyData( sbOffset, deliverReportSb.CompleteSubBlock() );
            sbOffset += SIZE_SMS_SB_DELIVER_REPORT;
            }

        // Add SMS_SB_PARAM_INDICATOR & SMS_SB_USER_DATA subblocks if needed
        if ( userDataIncluded )
            {
            // Add SMS_SB_PARAM_INDICATOR subblock
            isiMsg.CopyData( sbOffset, paramIndicatorSb.CompleteSubBlock() );
            // Add SMS_SB_USER_DATA subblock
            sbOffset += paramIndSbLength;
            isiMsg.CopyData( sbOffset, userDataSb.CompleteSubBlock() );
            }

        ret = iPhoNetSender->Send( isiMsg.Complete() );
        }

    return ret;
    }

// --------------------------------------------------------------------------
// Maps RP cause value to SMS cause value.
// --------------------------------------------------------------------------
TUint8 CMmSmsMessHandler::SmsMapCause ( TInt aRpCause )
    {
TFLOGSTRING2("TSY: CMmSmsMessHandler::SmsReceivedPpReportReq - aRpCause: %d", aRpCause);
OstTrace1( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_SMSMAPCAUSE_TD, "CMmSmsMessHandler::SmsMapCause;aRpCause=%d", aRpCause );

    //initialization of the Sms Cause value is 0x00 (SMS_CAUSE_OK)
    TUint8 retSmsCause( 0 );

    switch ( aRpCause )
        {
        case KErrGsmSMSMemoryCapacityExceeded:
            {
            retSmsCause = SMS_EXT_ERR_MEMORY_CAPACITY_EXC;
            break;
            }

        //Try to find matching RP cause value from GSM 04.11

        case KErrGsmSMSInvalidShortMessageTransferReferenceValue:
            {
            retSmsCause = SMS_EXT_ERR_INVALID_REFERENCE;
            break;
            }

        case KErrGsmSMSNonExistentMessageType:
            {
            retSmsCause = SMS_EXT_ERR_INCORRECT_MESSAGE;
            break;
            }

        case KErrGsmSMSInvalidMandatoryInformation:
            {
            retSmsCause = SMS_EXT_ERR_INVALID_MAND_INFO;
            break;
            }

        case KErrGsmSMSIncompatibleMessageWithSmsProtocolState:
            {
            retSmsCause = SMS_EXT_ERR_MSG_NOT_COMP_WITH_ST;
            break;
            }

        case KErrGsmSMSInformationElementNotImplemented:
            {
            retSmsCause = SMS_EXT_ERR_INVALID_INFO_ELEMENT;
            break;
            }

        case KErrGsmSMSUnspecifiedInvalidMessage:
            {
            retSmsCause = SMS_EXT_ERR_INVALID_MSG_TYPE;
            break;
            }

        case KErrGsmSMSUnspecifiedProtocolError:
            {
            retSmsCause = SMS_EXT_ERR_PROTOCOL_ERROR;
            break;
            }

        default:
            {
TFLOGSTRING2("TSY: CMmSmsMessHandler::SmsReceivedPpReportReq - unknown RpCause: %d", aRpCause);
OstTrace1( TRACE_NORMAL,  CMMSMSMESSHANDLER_SMSMAPCAUSE_TD, "CMmSmsMessHandler::SmsMapCause;unknown aRpCause=%d", aRpCause );
            retSmsCause = SMS_EXT_ERR_PROTOCOL_ERROR;
            break;
            }
        }

    return retSmsCause;
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::SmsMessageSendResp
// Breaks a ISI-message and get possible TP-Failure-Cause from
// ISI-message.
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::SmsMessageSendResp(
    const TIsiReceiveC& aIsiMsg,
    TInt aIpc )
    {
TFLOGSTRING2("TSY: CMmSmsMessHandler::SmsMessageSendResp - IPC: %d", aIpc);
OstTrace1( TRACE_NORMAL,  CMMSMSMESSHANDLER_SMSMESSAGESENDRESP_TD, "CMmSmsMessHandler::SmsMessageSendResp;aIpc=%d", aIpc );

    TInt epocCause( KErrNone );
    TUint16 msgRef( 0 );
    TUint8 tpFailureCause( 0 );

    // Cause type and cause value
    TUint8 smsServerCauseType( aIsiMsg.Get8bit(
        ISI_HEADER_SIZE + SMS_MESSAGE_SEND_RESP_OFFSET_CAUSETYPE ) );
    TUint8 smsServerCauseValue = aIsiMsg.Get8bit(
        ISI_HEADER_SIZE + SMS_MESSAGE_SEND_RESP_OFFSET_SMSCAUSE );

    if ( SMS_OK != smsServerCauseValue )
        {
        if ( SMS_CAUSE_TYPE_COMMON == smsServerCauseType )
            {
            if ( SMS_ERR_RC_REJECTED  == smsServerCauseValue )
                {
                if ( EMobileSmsMessagingSendMessage == aIpc )
                    {
TFLOGSTRING("TSY: CMmSmsMessHandler::SmsMessageSendResp - server cause: SMS_ERR_RC_REJECTED");
OstTrace0( TRACE_NORMAL,  DUP2_CMMSMSMESSHANDLER_SMSMESSAGESENDRESP_TD, "CMmSmsMessHandler::SmsMessageSendResp, server cause: SMS_ERR_RC_REJECTED" );
                    // This is an ETel MM-initiated SMS, barred by SAT.
                    epocCause = CMmStaticUtility::EpocErrorCode(
                        KErrAccessDenied,
                        KErrSatControl );
                    }
                else if (  EMmTsySmsSendSatMessage == aIpc )
                    {
TFLOGSTRING("TSY: CMmSmsMessHandler::SmsMessageSendResp - server cause: SMS_ERR_RC_REJECTED");
OstTrace0( TRACE_NORMAL,  DUP4_CMMSMSMESSHANDLER_SMSMESSAGESENDRESP_TD, "CMmSmsMessHandler::SmsMessageSendResp, server cause: SMS_ERR_RC_REJECTED" );
                    // This is a SAT-initiated SMS, barred by SAT.
                    epocCause = KErrSatMoSmControlBarred;
                    }
                }
             else
                {
                epocCause = CMmStaticUtility::CSCauseToEpocError(
                    PN_SMS,
                    SMS_CAUSE_TYPE_COMMON,
                    smsServerCauseValue );
                }
            }
        else if ( SMS_CAUSE_TYPE_EXT == smsServerCauseType )
            {
            epocCause = CMmStaticUtility::CSCauseToEpocError(
                PN_SMS,
                SMS_CAUSE_TYPE_EXT,
                smsServerCauseValue );
            }
        else // Invalid cause type
            {
TFLOGSTRING2("TSY: CMmSmsMessHandler::SmsMessageSendResp: Unknown cause type %d.", smsServerCauseType );
OstTraceExt1( TRACE_NORMAL,  DUP5_CMMSMSMESSHANDLER_SMSMESSAGESENDRESP_TD, "CMmSmsMessHandler::SmsMessageSendResp;smsServerCauseType=%hhu", smsServerCauseType );
TF_ASSERT_NOT_REACHED();
            }
        }
    else // Sending was OK
        {
        msgRef = aIsiMsg.Get8bit( ISI_HEADER_SIZE +
            SMS_MESSAGE_SEND_RESP_OFFSET_REFERENCEFORMESSAGE );
        }

    TUint smsSbSubmitReportOffset( 0 );
    if ( KErrNone == aIsiMsg.FindSubBlockOffsetById(
        ISI_HEADER_SIZE + SIZE_SMS_MESSAGE_SEND_RESP,
        SMS_SB_SUBMIT_REPORT,
        EIsiSubBlockTypeId16Len16,
        smsSbSubmitReportOffset ) )
        {
        // SMS_SB_SUBMIT_REPORT subblock exists.
        // SMS server sets TP-Failure-Cause to zero in OK case.
        tpFailureCause = aIsiMsg.Get8bit(
            smsSbSubmitReportOffset
            + SMS_SB_SUBMIT_REPORT_OFFSET_TPFAILURECAUSE );
        }

    // Response for send SMS request
    if ( EMobileSmsMessagingSendMessage == aIpc
        || EMobileSmsMessagingSendMessageNoFdnCheck == aIpc )
        {
        TBuf8<RMobileSmsMessaging::KGsmTpduSize> pdu;

        // Create default SMS SUBMIT REPORT. Some operators may send
        // some information inside of this pdu. SMS stack refuses
        // to handle submit report that doesn't follow GSM 24.040 & 23.038
        // specifications.
        pdu.Append( KSmsMTISubmitOrSubmitReport ); // TP-MSG-Parameters

        if ( KErrNone == epocCause )
            {
            tpFailureCause = 0;
            }
        else if ( 0 == tpFailureCause )
            {
            tpFailureCause = 0xFF; // Unspecified error
            }

        pdu.Append( tpFailureCause ); // TP Failure Cause
        pdu.Append( 0x00 ); // TP Parameter Indicator

        TBuf8<KSmsScTimeStampMaxLength> timeStamp;
        TUint8 tsBuffer[KSmsScTimeStampMaxLength] =
            { 0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
        timeStamp.Append( &tsBuffer[0], sizeof( tsBuffer ) );
        pdu.Append( timeStamp ); // TP Service Centre Time Stamp

        // Create package and pack data
        CMmDataPackage data;
        data.PackData( &msgRef, &pdu );

        //complete the request
        if ( EMobileSmsMessagingSendMessage == aIpc )
            {
            iMessageRouter->Complete(
                EMobileSmsMessagingSendMessage,
                &data,
                epocCause );
            }
        else
            {
            iMessageRouter->Complete(
                EMobileSmsMessagingSendMessageNoFdnCheck,
                &data,
                epocCause );
            }

#if (NCP_COMMON_S60_VERSION_SUPPORT>S60_VERSION_32)
        iSMSSendingOngoing = EFalse;
#endif // NCP_COMMON_S60_VERSION_SUPPORT
        }
    // Response for send SAT SMS request
    else if ( EMmTsySmsSendSatMessage == aIpc )
        {
        //complete the request
        #if (NCP_COMMON_S60_VERSION_SUPPORT==S60_VERSION_32)
        iMessageRouter->Complete( EMmTsySmsSendSatMessage, epocCause );
        #else
#ifdef __WINSCW__
         // for simatktsy testtool
         if ( iMessageRouter->iSatMessaging )
             {
             iMessageRouter->iSatMessaging->CompleteSendSmsMessage ( epocCause );
             }
            // for nokiatsy testtool
         iMessageRouter->Complete ( EMmTsySmsSendSatMessage, epocCause );
#else // __WINSCW__
         iMessageRouter->iSatMessaging->CompleteSendSmsMessage ( epocCause );
#endif // __WINSCW__
        iSMSSendingOngoing = EFalse;
#endif //NCP_COMMON_S60_VERSION_SUPPORT
        }
    else
        {
TFLOGSTRING2("TSY:CMmSmsMessHandler::SmsMessageSendResp:Unexpected IPC %d.",aIpc);
OstTrace1( TRACE_NORMAL,  DUP6_CMMSMSMESSHANDLER_SMSMESSAGESENDRESP_TD, "CMmSmsMessHandler::SmsMessageSendResp;aIpc=%d", aIpc );
        }
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::SmsReceiveMessageResp
// Breaks a SMS_RECEIVE_MESSAGE_RESP ISI-message and
// completes for SMS receiving request.
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::SmsReceiveMessageResp( const TIsiReceiveC& aIsiMsg )
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::SmsReceiveMessageResp");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_SMSPPROUTINGRESP_TD, "CMmSmsMessHandler::SmsReceiveMessageResp" );

    // Get transaction ID for completing with correct IPC
    TUint8 trId( aIsiMsg.Get8bit(
        ISI_HEADER_SIZE + SMS_RECEIVE_MESSAGE_RESP_OFFSET_TRANSID ) );
    // Get reception status
    TUint8 receptionStatus( aIsiMsg.Get8bit(
        ISI_HEADER_SIZE + SMS_RECEIVE_MESSAGE_RESP_OFFSET_STATUS ) );

    // Get cause type and cause value. SMS_SB_CAUSE is mandatory subblock
    TUint8 smsServerCauseType( aIsiMsg.Get8bit(
        ISI_HEADER_SIZE + SIZE_SMS_RECEIVE_MESSAGE_RESP
        + SMS_SB_CAUSE_OFFSET_CAUSETYPE ) );
    TUint8 smsServerCauseValue( aIsiMsg.Get8bit(
        ISI_HEADER_SIZE + SIZE_SMS_RECEIVE_MESSAGE_RESP
        + SMS_SB_CAUSE_OFFSET_SMSCAUSE ) );

    TInt epocError( CMmStaticUtility::CSCauseToEpocError(
        PN_SMS,
        smsServerCauseType,
        smsServerCauseValue ) );

    // Compete active reception status
    if ( SMS_RECEPTION_ACTIVE == receptionStatus )
        {
        if ( 0 == trId ) // SMS receiving activated
            {
            CMmDataPackage package;
            package.PackData( &receptionStatus );
            iMessageRouter->Complete(
                EMmTsyActivateSmsRouting,
                &package,
                epocError );
            }
        else if ( ESmsMessagingResumeSmsReception == trId ) // Receive resumed
            {
            iMessageRouter->Complete(
                EMobileSmsMessagingResumeSmsReception,
                epocError );
            }
        // No else
        }
    else // SMS_RECEPTION_INACTIVE
        {
        CMmDataPackage package;
        package.PackData( &receptionStatus );
        iMessageRouter->Complete(
            EMmTsyDeactivateSmsRouting,
            &package,
            epocError );
        }
    return;
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::IsSmsClass2
// Check if the class of the received sms is Class2 or not
// -----------------------------------------------------------------------------
//
TBool CMmSmsMessHandler::IsSmsClass2(
    const TIsiReceiveC& aIsiMsg, //Isi Msg
    TUint8& aSmsClass2ReplaceTpPid ) // TP-PID to replace (set by this function)
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::IsSmsClass2");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_ISSMSCLASS2_TD, "CMmSmsMessHandler::IsSmsClass2" );
    TBool smsClass2( EFalse );
    TBool cphsCase( EFalse );

    // If received Class 2 SMS is a "replace type" message, contains
    // the TP-PID value, else value is zero.
    // See 3GPP TS 23.040 "Technical realization of Short Message
    // Service (SMS)", version V6.2.0 (2003-09), chapter 9.2.3.9
    // "TP Protocol Identifier (TP PID)"
    aSmsClass2ReplaceTpPid = 0;

    TUint tpduOffset( 0 );
    if ( KErrNone == aIsiMsg.FindSubBlockOffsetById(
        ISI_HEADER_SIZE + SIZE_SMS_RECEIVED_MSG_IND,
        SMS_SB_TPDU,
        EIsiSubBlockTypeId16Len16,
        tpduOffset ) )
        {
        TUint8 userDataLength( aIsiMsg.Get8bit(
            tpduOffset + SMS_SB_TPDU_OFFSET_DATALENGTH ) );
        TPtrC8 sms( aIsiMsg.GetData(
            tpduOffset + SMS_SB_TPDU_OFFSET_DATABYTES,
            userDataLength ) );

        if ( 0 < sms.Length() )
            {
            // Begin CPHS special case handling
            // "CPHS Version 4.2, B.4.2.1 Voice Message Waiting Indicator":
            // An MT Class 2 ((U)SIM-specific) SMS with
            // - TP-Originating-Address coded as a Voice Message Waiting
            //   Indicator message
            // - User data a single space is not saved into EF_SMS.
            const TUint8 KCphsAddressLength( 4 );     // 00000100
            const TUint8 KCphsTypeOfAddress( 0xD0 );  // 11010000
            const TUint8 KCphsSpaceCharacter( 0x20 ); // 01000000
            // Skip message parameters (1 byte)
            TUint8 oaLen( sms[1] );
            if ( KCphsAddressLength == oaLen )
                {
                TUint8 typeOfAddress( sms[2] );
                TUint8 addressValueChar1( sms[3] );
                TUint8 addressValueChar2( sms[4] );
                if ( ( KCphsTypeOfAddress == typeOfAddress )
                     && ( 0x10 == ( 0x7E & addressValueChar1 ) )  //x001000x
                     && ( 0x00 == ( 0x7E & addressValueChar2 ) ) )//x000000x
                    {
                    // Skip PID(1 byte), skip DCS(1 byte), skip SCTS(7 bytes)
                    TUint8 udl( sms[14] );
                    if ( 1 == udl )
                        {
                        TUint8 ud( sms[15] );
                        if ( KCphsSpaceCharacter == ud )
                            {
                            // This is a CPHS message indicator. No further
                            // check of DCS and PID necessary.
                            cphsCase = ETrue;
                            smsClass2 = EFalse;
TFLOGSTRING("TSY: CMmSmsMessHandler::IsSmsClass2: CPHS message");
OstTrace0( TRACE_NORMAL,  DUP4_CMMSMSMESSHANDLER_ISSMSCLASS2_TD, "CMmSmsMessHandler::IsSmsClass2. CPHS message" );
                            }
                        }
                    }
                }
            // End CPHS special case handling

            // No CPHS case, continue checking
            if ( ! cphsCase )
                {
                // Check type of received SMS message
                TUint8 messageParams( sms[0] );
                messageParams &= 0x03;
                if ( KSmsMTIDeliverOrDeliverReport == messageParams )
                    {
                    TUint8 protocolId( 0 );
                    // To retrieve the TP-DCS, we have to find the right index
                    // See 3GPP TS 23.040 "Technical realization of Short
                    // Message Service (SMS)", version V6.2.0 (2003-09),
                    // chapter 9.2.2.1 "SMS Deliver Type"

                    TUint8 index( 1 ); // Skip the first byte (message params)
                    TUint8 addressLength( sms[index] );
                    // Address is coded in semi-octets in TPDU->divide by two.
                    // Add two mandatory bytes of TP-OA
                    addressLength = ( addressLength + 1 ) / 2 + 2;
                    index += addressLength;
                    protocolId = sms[index++];

                    // Check if this class 2 SMS is a "replace type" message
                    // See 3GPP TS 23.040 "Technical realization of Short
                    // Message Service (SMS)", version V6.2.0 (2003-09),
                    // chapter 9.2.3.9 "TP Protocol Identifier (TP PID)"
                    if ( ( 0x41 <= protocolId ) && ( 0x47 >= protocolId ) )
                        {
                        // Yes, this is a "replace type" message
TFLOGSTRING2("TSY: CMmSmsMessHandler::IsSmsClass2: Replace type message, protocol ID: %d", protocolId );
OstTraceExt1( TRACE_NORMAL,  DUP3_CMMSMSMESSHANDLER_ISSMSCLASS2_TD, "CMmSmsMessHandler::IsSmsClass2. Replace type message;protocolId=%hhu", protocolId );
                        aSmsClass2ReplaceTpPid = protocolId;
                        }

                    // TP-DCS tells us the class of the SMS
                    TUint8 dataCodingScheme( sms[index++] );
                    // Copy TP-DCS to get the stronger bits later
                    TUint8 strongerBitsDCS( dataCodingScheme );

                    // Received message is of Class2 if dataCodingScheme
                    // contains either bits 00x1xx10 or 1111xx10.
                    // Gets the lower bits.
                    // See 3GPP TS 23.038 "Technical Specification Group
                    // Terminals; Alphabets and language-specific information"
                    // version V6.0.0 (2003-09), chapter 4 "SMS Data Coding
                    // Scheme"
                    dataCodingScheme &= 0x03;

                    // Gets the stronger bits
                    strongerBitsDCS >>= 4;
                    if (  ( 2 == dataCodingScheme ) &&
                        ( ( 1 == strongerBitsDCS ) ||
                        ( 3 == strongerBitsDCS ) ||
                        ( 15 == strongerBitsDCS ) ) )
                        {
                        // SMS is from Class2
                        smsClass2 = ETrue;
                        }
                    } // End of if KSmsMTIDeliverOrDeliverReport==messageParams
                } // End of if ( ! cphsCase )
            } // End of if ( 0 < sms.Length() )
        } // End of if SMS_SB_USER_DATA found

    // We are only interested in TP-PID "replace", if message is Class 2
    // (TP-PID "replace" for class 1 messages is handled by upper layers)
    if ( 0 != aSmsClass2ReplaceTpPid )
        {
        if ( smsClass2 )
            {
TFLOGSTRING2("TSY: CMmSmsMessHandler::SmsClass: Received class 2 message has TP-PID 0x%x", aSmsClass2ReplaceTpPid);
OstTraceExt1( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_ISSMSCLASS2_TD, "CMmSmsMessHandler::IsSmsClass2;aSmsClass2ReplaceTpPid=%hhx", aSmsClass2ReplaceTpPid );
            }
        else
            {
            aSmsClass2ReplaceTpPid = 0;
            }
        }
    return smsClass2;
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::SmsReceivedMsgInd
// Breaks SMS_RECEIVED_MSG_IND ISI-message that contains incoming
// SMS message. SMS message is not acknowledged to the network
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::SmsReceivedMsgInd( const TIsiReceiveC& aIsiMsg )
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::SmsReceivedMsgInd");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_SMSPPROUTINGNTF_TD, "CMmSmsMessHandler::SmsReceivedMsgInd" );

    TInt ret( KErrNone );
    // Create a package
    CMmDataPackage package;

    TUint8 replaceTpPid( 0 ); // IsSmsClass2 also fills this
    TBool receivedSmsClass2( IsSmsClass2( aIsiMsg, replaceTpPid ) );

    // SIM SMS cache: incoming class 2 SMS
    if ( receivedSmsClass2 )
        {
        ret = SmsClass2ReceivedMsgInd( aIsiMsg, replaceTpPid );
        }
    // Received SMS is not a class 2 SMS (it is a normal SMS)
    else
        {
        ret = SmsClass1ReceivedMsgInd( aIsiMsg );
        }
    // There was an error, complete to upper level
    if ( KErrNone != ret )
        {
TFLOGSTRING2("TSY: CMmSmsMessHandler::SmsReceivedMsgInd;ret=%d", ret);
OstTrace1( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_SMSPPROUTINGNTF_TD, "CMmSmsMessHandler::SmsReceivedMsgInd;ret=%d", ret );
        TBool smsInd( ETrue );
        TSmsMsg* nullSms = NULL;

        package.PackData( &smsInd, &nullSms );

        // Complete request to client
        iMessageRouter->Complete(
            EMobileSmsMessagingReceiveMessage,
            &package,
            ret );
        }
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::SmsReceivedMsgReportResp
// Breaks a ISI-message, gets GSM specific sub blocks and
// response for Sms gsm received pp report request
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::SmsReceivedMsgReportResp( const TIsiReceiveC& aIsiMsg )
    {
    TUint8 traId( aIsiMsg.Get8bit( ISI_HEADER_SIZE
        + SMS_RECEIVED_MSG_REPORT_RESP_OFFSET_TRANSID ) );
    TUint8 cause( aIsiMsg.Get8bit( ISI_HEADER_SIZE
        + SMS_RECEIVED_MSG_REPORT_RESP_OFFSET_SMSCAUSE ) );

TFLOGSTRING3("TSY: CMmSmsMessHandler::SmsReceivedPpReportResp - traId: %d, cause: %d", traId, cause);
OstTraceExt2( TRACE_NORMAL,  CMMSMSMESSHANDLER_SMSRECEIVEDPPREPORTRESP_TD, "CMmSmsMessHandler::SmsReceivedPpReportResp;traId=%hhu;cause=%hhu", traId, cause );

    // Response for SmsReceivedPpReportReq (Ack)
    if ( ESmsMessagingAckSmsStored == traId )
        {
        iMessageRouter->Complete(
            EMobileSmsMessagingAckSmsStored,
            CMmStaticUtility::CSCauseToEpocError(
                PN_SMS,
                SMS_CAUSE_TYPE_COMMON,
                cause ) );
        }
    // Response for SmsReceivedPpReportReq (Nack)
    else if ( ESmsMessagingNackSmsStored == traId )
        {
        iMessageRouter->Complete(
            EMobileSmsMessagingNackSmsStored,
            CMmStaticUtility::CSCauseToEpocError(
                PN_SMS,
                SMS_CAUSE_TYPE_COMMON,
                cause ) );
        }
    else
        {
TFLOGSTRING2("TSY:CMmSmsMessHandler::SmsReceivedPpReportResp:Unexpected transaction ID %d.",traId);
OstTraceExt1( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_SMSRECEIVEDPPREPORTRESP_TD, "CMmSmsMessHandler::SmsReceivedPpReportResp;Unexpected  transaction ID=%hhu", traId );
        }

    if ( SMS_OK != cause )
        {
        //Acknowledging failed.
        iSmsSlotLocation = 0;
        }
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::BuildScAddress
// Build Service Centre Address
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::BuildScAddress(
    RMobilePhone::TMobileAddress const & scPtr, //Pointer to Service center
    TDes8 &aScAddress ) const                  //Service center address
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::BuildScAddress");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_BUILDSCADDRESS_TD, "CMmSmsMessHandler::BuildScAddress" );
    //get type of number from attributes
    RMobilePhone::TMobileTON ton( scPtr.iTypeOfNumber );
    //map type of number from TMobileTON to TUint8
    TUint8 typeOfNumber( CMmSmsGsmAddress::GsmMapTonToTUint8( ton ) );
    //get numbering plan identification from attributes
    RMobilePhone::TMobileNPI npi( scPtr.iNumberPlan );
    //map numbering plan identification from TMobileTON to TUint8
    TUint8 numberPlan( CMmSmsGsmAddress::GsmMapNpiToTUint8( npi ) );
    //return service center address
    TPtrC16 telNumber( scPtr.iTelNumber );

    //build Gsm 04.11 type of address structure
    CMmSmsGsmAddress::GsmConvUnicodeTo0411Addr(
        typeOfNumber,
        numberPlan,
        aScAddress,
        telNumber );
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::BuildDeAddress
// Build Destination Address
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::BuildDeAddress(
    RMobilePhone::TMobileAddress const & scPtr,  // Service centre pointer
    TDes8 &aDeAddress ) const                    // Destination address
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::BuildDeAddress");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_BUILDDEADDRESS_TD, "CMmSmsMessHandler::BuildDeAddress" );
    //get type of number from attributes
    RMobilePhone::TMobileTON ton( scPtr.iTypeOfNumber );

    //map type of number from TMobileTON to TUint8
    TUint8 typeOfNumber( CMmSmsGsmAddress::GsmMapTonToTUint8( ton ) );

    //get numbering plan identification from attributes
    RMobilePhone::TMobileNPI npi( scPtr.iNumberPlan );

    //map numbering plan identification from TMobileTON to TUint8
    TUint8 numberPlan( CMmSmsGsmAddress::GsmMapNpiToTUint8( npi ) );

    //return service center address
    TPtrC16 telNumber( scPtr.iTelNumber );

    //build Gsm 03.40 type of address structure
    CMmSmsGsmAddress::GsmConvUnicodeTo0340Addr(
        typeOfNumber,
        numberPlan,
        aDeAddress,
        telNumber );
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::DataCodingScheme
// Check if message data is coded using 7bit alphabet
// (other items were commented in header)
// -----------------------------------------------------------------------------
//
TBool CMmSmsMessHandler::IsDataCodingScheme7Bit( TUint8 aDcs ) const
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::IsDataCodingScheme7Bit");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_ISDATACODINGSCHEME7BIT_TD, "CMmSmsMessHandler::IsDataCodingScheme7Bit" );
    TUint8 codingGroup( static_cast<TUint8>( 0xf0 & aDcs ) );  // 11110000
    TUint8 lowerBits( static_cast<TUint8>( 0x0f & aDcs ) );    // 00001111

    // See 3GPP TS 23.038 "Technical Specification Group Terminals;
    //Alphabets and language-specific information"
    // version V6.0.0 (2003-09), chapter 4 "SMS Data Coding Scheme"
    // 00XX General data coding indication
    // 01XX Message Marked for Automation Deletion Group
    if ( codingGroup >> 6 == 0x00 || codingGroup >> 6 == 0x01 )
        {
        // 00XX Default alphabet, 11XX Reserved
        if ( ( lowerBits >> 2 == 0x00 ) || ( lowerBits >> 2 == 0x03 ) )
            {
            return ETrue;
            }
        else
            {
            return EFalse;
            }
        }
    // 1100 Message Waiting Indication Group: Discard Message
    // 1101 Message Waiting Indication Group: Store Message
    else if ( codingGroup >> 4 == 0x0C || codingGroup >> 4 == 0x0D )
        {
        return ETrue;
        }
    // 1110 Message Waiting Indication Group: Store Message (UCS2)
    else if ( codingGroup >> 4 == 0x0E )
        {
        return EFalse;
        }
    // 1111 Data coding/message class
    else if ( codingGroup >> 4 == 0x0F )
        {
        lowerBits&= 0x04;
        // X0XX Default alphabet
        if ( lowerBits == 0 )
            {
            return ETrue;
            }
        else
            {
            return EFalse;
            }
        }
    // 1000..1011 Reserved coding groups
    else
        {
        // Any reserved codings shall be assumed to be the GSM default alphabet
        return ETrue;
        }
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::CalculateNumberOfCharsInUserData
// Calculate number of characters in 7-bit user data
// -----------------------------------------------------------------------------
//
TUint8 CMmSmsMessHandler::CalculateNumberOfCharsInUserData(
    TUint8 aCharacterAmount,           //Character amount (from ISI message)
    TUint8 aDataLength,                //Data length in bytes (from ISI message)
    TPtrC8 const & aUserData ) const   //User data
    {
TFLOGSTRING3("TSY: CMmSmsMessHandler::CalculateNumberOfCharsInUserData - char amount (from ISI): %d, data length (from ISI): %d", aCharacterAmount, aDataLength);
OstTraceExt2( TRACE_NORMAL,  CMMSMSMESSHANDLER_CALCULATENUMBEROFCHARSINUSERDATA_TD, "CMmSmsMessHandler::CalculateNumberOfCharsInUserData;aCharacterAmount=%hhu;aDataLength=%hhu", aCharacterAmount, aDataLength );

    TUint16 characterAmount;

    // This calculation is only needed if the number of characters is
    // not provided in the aCharacterAmount parameter. Seems to be some
    // old backwards-compatibility issue or so ...
    if ( ( 0 != aCharacterAmount ) && ( 0xff != aCharacterAmount ) )
        {
        characterAmount = aCharacterAmount;
        }
    else
        {
        //we have to calculate number of characters in user data, when
        //7-bit chars are used.
        characterAmount = static_cast<TUint16>(  ( aDataLength * 8 ) / 7 );
        if ( ( 0 == ( ( aDataLength * 8 ) % 7 ) ) && characterAmount )
            {
            if ( 0 == ( aUserData[aDataLength-1] & 0xFE ) )
                {
                //LSB in user data's last byte is zero -> number of characters
                //is characterAmount-1
                characterAmount--;
                }
            }
        }
    return static_cast<TUint8>( characterAmount );
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::ExtFuncL
// Dispatches Etel requests to DOS level handlers
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::ExtFuncL(
    TInt aIpc,                           // IPC number
    const CMmDataPackage* aDataPackage ) // Data package
    {
TFLOGSTRING2("TSY: CMmSmsMessHandler::ExtFuncL: IPC: %d", aIpc);
OstTrace1( TRACE_NORMAL,  CMMSMSMESSHANDLER_EXTFUNCL_TD, "CMmSmsMessHandler::ExtFuncL;aIpc=%d", aIpc );

    TInt ret( KErrNone );

    switch ( aIpc )
        {
        case EMobileSmsMessagingGetMessageStoreInfo:
        case EMobilePhoneStoreGetInfo:
            {
            ret = GetSmsStoreInfo( aIpc );
            break;
            }
        case EMmTsyActivateSmsRouting:
            {
#if defined( INTERNAL_TESTING_SMS_WITH_EMULATOR )  && ( ! defined( __WINS__ ) )
TFLOGSTRING("TSY: CMmSmsMessHandler::ExtFuncL: SMS routing deactivated with flag INTERNAL_TESTING_SMS_WITH_EMULATOR");
OstTrace0( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_EXTFUNCL_TD, "CMmSmsMessHandler::ExtFuncL, SMS routing deactivated with flag INTERNAL_TESTING_SMS_WITH_EMULATOR" );
#else
            ret = SmsReceiveMessageReq( SMS_RECEPTION_ACTIVATE );
#endif // defined( INTERNAL_TESTING_SMS_WITH_EMULATOR ) && ( ! defined( __WINS__ ) )
            break;
            }
        case EMmTsyDeactivateSmsRouting:
            {
            //Release the SMS_PP_ROUTING
            ret = SmsReceiveMessageReq( SMS_RECEPTION_DEACTIVATE );
            break;
            }
        case EMobileSmsMessagingSendMessage:
            {
            ret = SmsMessageSendReq(
                ESmsMessagingSendMessage,
                aDataPackage,
                EFalse );
            break;
            }
        case EMobileSmsMessagingSendMessageNoFdnCheck:
            {
            ret = SmsMessageSendReq(
                ESmsMessagingSendNoFdnMessage,
                aDataPackage,
                ETrue );
            break;
            }
        case EMmTsySmsSendSatMessage:
            {
            ret = SmsMessageSendReq(
                ESmsMessagingSendSatMessage,
                aDataPackage,
                ETrue );
            break;
            }
        case EMobileSmsMessagingResumeSmsReception:
            {
            ret = SmsReceiveMessageReq( SMS_RECEPTION_STORAGE_STATUS_UPDATE );
            break;
            }
        case EMobileSmsMessagingGetSmspListPhase1:
            {
            // Reset internal temporary SMSP storage
            iSmspListArray->ResetAndDestroy();
            // Start reading SMSP entries
            ret = UiccGetSmspEntryReq();
            break;
            }
        case EMobileSmsMessagingStoreSmspList:
            {
            ret = UiccSmsUpdateParameterReq( aDataPackage );
            break;
            }
        case EMobileSmsMessagingAckSmsStored:
            {
            TDesC8* data;
            //unpack data
            aDataPackage->UnPackData( data );

            TBuf8<RMobileSmsMessaging::KGsmTpduSize>* msgData =
                reinterpret_cast<TBuf8<RMobileSmsMessaging::KGsmTpduSize> *> ( data );

            if ( NULL == msgData )
                {
TFLOGSTRING("TSY: CMmSmsMessHandler::ExtFuncL.Internal Ack handling started" );
OstTrace0( TRACE_NORMAL,  DUP2_CMMSMSMESSHANDLER_EXTFUNCL_TD, "CMmSmsMessHandler::ExtFuncL, Internal Ack handling started" );
                }
            ret = SmsReceivedMsgReportReq(
                ESmsMessagingAckSmsStored,
                msgData,
                KErrNone );
            break;
            }
        case EMobileSmsMessagingNackSmsStored:
            {
            TInt rpCause( 0 );
            TBuf8<RMobileSmsMessaging::KGsmTpduSize>* msgData;

            //unpack data
            aDataPackage->UnPackData( msgData, rpCause );

            if ( NULL == msgData )
                {
TFLOGSTRING("TSY: CMmSmsMessHandler::ExtFuncL.Internal Nack handling started" );
OstTrace0( TRACE_NORMAL,  DUP3_CMMSMSMESSHANDLER_EXTFUNCL_TD, "CMmSmsMessHandler::ExtFuncL, Internal Nack handling started" );
                }

            ret = SmsReceivedMsgReportReq(
                ESmsMessagingNackSmsStored,
                msgData,
                rpCause );
            break;
            }
        case EMobilePhoneStoreDelete:
            {
            ret = DeleteSms( aDataPackage );
            break;
            }
        case EMobilePhoneStoreDeleteAll:
            {
            iRecordId = 1; // Start fron 1st location
            ret = DeleteAllSms();
            break;
            }
        case EMobilePhoneStoreRead:
            {
            ret = ReadSms( aDataPackage );
            break;
            }
        case EMobilePhoneStoreReadAllPhase1:
            {
            ret = ReadAllSmsL();
            break;
            }
        case EMobilePhoneStoreWrite:
            {
            TInt index( 0 );
            TDesC8* data;

            // unpacked index is not used since the index to write to
            // can also be taken from smsData
            aDataPackage->UnPackData( data, index );

            //typecast for aEntry
            RMobileSmsStore::TMobileGsmSmsEntryV1Pckg* entryPckg =
                reinterpret_cast<RMobileSmsStore::TMobileGsmSmsEntryV1Pckg*>(
                const_cast<TDesC8*>( data ) );
            RMobileSmsStore::TMobileGsmSmsEntryV1& entry = ( *entryPckg )();
            iSMSClass2Write = EFalse;
            ret = WriteSms( entry, index );
           break;
            }
        case ECustomSetSimMessageStatusReadIPC:
            {
TFLOGSTRING("TSY: CMmSmsMessHandler::ExtFuncL - ECustomSetSimMessageStatusReadIPC starts.");
OstTrace0( TRACE_NORMAL,  DUP4_CMMSMSMESSHANDLER_EXTFUNCL_TD, "CMmSmsMessHandler::ExtFuncL, ECustomSetSimMessageStatusReadIPC starts" );
            TTime scTime;
            TInt timezoneDiff;
            aDataPackage->UnPackData( scTime, timezoneDiff );

            // start searching for a SIM message with this timestamp
            TUint8 totalSlots( static_cast<TUint8>(
                iSmsCache.TotalEntries() ) );
            TUint8 currentSlot( 1 );
            while ( currentSlot <= totalSlots )
                {
                RMobileSmsStore::TMobileGsmSmsEntryV1* smsFromCache =
                    iSmsCache.GetEntry( currentSlot );

                if ( smsFromCache )
                    {
                    if ( CheckSCTimestamp( *smsFromCache, scTime ) )
                        {
                        // Message with the same timestamp found,
                        // update SIM flag.
                        UiccUpdateSMSStatus( currentSlot );
                        currentSlot = totalSlots; // we're done, exit loop
                        }
                    }
                currentSlot++;
                }
TFLOGSTRING("TSY: CMmSmsMessHandler::ExtFuncL - ECustomSetSimMessageStatusReadIPC done.");
OstTrace0( TRACE_NORMAL,  DUP5_CMMSMSMESSHANDLER_EXTFUNCL_TD, "CMmSmsMessHandler::ExtFuncL, ECustomSetSimMessageStatusReadIPC done" );
            ret = KErrNone;
            break;
            }
        case EMobileSmsMessagingSetMoSmsBearer:
            {
            RMobileSmsMessaging::TMobileSmsBearer bearer;
            aDataPackage->UnPackData( bearer );
            ret = SmsSettingsUpdateReq( bearer );
            break;
            }
        default:
            {
TFLOGSTRING2("TSY: CMmSmsMessHandler::ExtFuncL - Unknown IPC: %d", aIpc);
OstTrace1( TRACE_NORMAL,  DUP6_CMMSMSMESSHANDLER_EXTFUNCL_TD, "CMmSmsMessHandler::ExtFuncL;Unknown aIpc=%d", aIpc );
            ret = KErrArgument;
            break;
            }
        }
    return ret;
    }


// -----------------------------------------------------------------------------
// CMmSmsMessHandler::CheckTpPidAndSenderAndServiceCenter
// Compares TP-PID, sender number and SC number of the received class 2
// SMS in aReceivedSmsIsiMsg, and the SMS read from SIM in aReadSmsIsiMsg.
// -----------------------------------------------------------------------------
//
TBool CMmSmsMessHandler::CheckTpPidAndSenderAndServiceCenter(
    TUint8 aReceivedTpPid,                             //received TP-PID
    const TIsiReceiveC&  aReceivedSmsIsiMsg,           //received isi msg
    RMobileSmsStore::TMobileGsmSmsEntryV1* aSMSOnSIM ) //SMS stored on SIM
    {
TFLOGSTRING2("TSY: CMmSmsMessHandler::CheckTpPidAndSenderAndServiceCenter, aReceivedTpPid = %d", aReceivedTpPid);
OstTraceExt1( TRACE_NORMAL,  CMMSMSMESSHANDLER_CHECKTPPIDANDSENDERANDSERVICECENTER_TD, "CMmSmsMessHandler::CheckTpPidAndSenderAndServiceCenter;aReceivedTpPid=%hhu", aReceivedTpPid );

    TBool matchFound( EFalse );

    // Get protocol id from stored SMS

    TInt offset( 1 ); // Set offset to message reference in TPDU
    TUint8 messageReference( aSMSOnSIM->iMsgData[offset] );

    // Destination address length is integer representation
    // of the number of useful semi-octets of address field
    // Add two mandatory bytes of TP-OA, too.

    messageReference = ( ( messageReference + 1 ) / 2 ) + 2;
    offset += messageReference;

    TUint8 protocolId( aSMSOnSIM->iMsgData[offset] );
    if ( protocolId == aReceivedTpPid )
        {
        // this message has the same TP-PID. Now check if it also has
        // same sender number and service center number
        TBuf<KMaxAddressBufferSize> receivedMsgServiceCentre;
        RMobilePhone::TMobileTON receivedMsgMobileScTON(
            RMobilePhone::EUnknownNumber );
        RMobilePhone::TMobileNPI receivedMsgMobileScNPI(
            RMobilePhone::EUnknownNumberingPlan );

        TBuf<KMaxAddressBufferSize> receivedMsgOriginatorAdress;
        RMobilePhone::TMobileTON receivedMsgMobileOaTON(
            RMobilePhone::EUnknownNumber );
        RMobilePhone::TMobileNPI receivedMsgMobileOaNPI(
            RMobilePhone::EUnknownNumberingPlan );

        TBuf<KMaxAddressBufferSize> readMsgOriginatorAdress;
        RMobilePhone::TMobileTON readMsgMobileOaTON(
            RMobilePhone::EUnknownNumber );
        RMobilePhone::TMobileNPI readMsgMobileOaNPI(
            RMobilePhone::EUnknownNumberingPlan );

        // 1. Get service center address from received message
        TUint smsAddressOffset( 0 );
        if ( KErrNone == aReceivedSmsIsiMsg.FindSubBlockOffsetById(
            ISI_HEADER_SIZE + SIZE_SMS_RECEIVED_MSG_IND,
            SMS_SB_ADDRESS,
            EIsiSubBlockTypeId16Len16,
            smsAddressOffset ) )
            {
            if ( SMS_SMSC_ADDRESS == aReceivedSmsIsiMsg.Get8bit(
                smsAddressOffset + SMS_SB_ADDRESS_OFFSET_ADDRESSTYPE ) )
                {
                // Convert service centre address (SC Address 04.11)
                TUint8 addressDataLength( aReceivedSmsIsiMsg.Get8bit(
                    smsAddressOffset +
                    SMS_SB_ADDRESS_OFFSET_ADDRESSDATALENGTH ) );
                TPtrC8 scA( aReceivedSmsIsiMsg.GetData(
                    smsAddressOffset + SMS_SB_ADDRESS_OFFSET_ADDRESSDATA,
                    addressDataLength ) );
                CMmSmsGsmAddress::GsmConv0411AddrToUnicode(
                    receivedMsgServiceCentre,
                    scA,
                    receivedMsgMobileScTON,
                    receivedMsgMobileScNPI );
                }
            }
        else // could not extract data from received message
            {
TFLOGSTRING("TSY: CMmSmsMessHandler::CheckTpPidAndSenderAndServiceCenter: Could not extract data from received message");
            OstTrace0( TRACE_NORMAL,  DUP2_CMMSMSMESSHANDLER_CHECKTPPIDANDSENDERANDSERVICECENTER_TD, "CMmSmsMessHandler::CheckTpPidAndSenderAndServiceCenter: Could not extract data from received message" );
            return EFalse;
            }

        // 2. Get sender address from received message
        TUint smsUserDataOffset( 0 );
        if ( KErrNone == aReceivedSmsIsiMsg.FindSubBlockOffsetById(
            ISI_HEADER_SIZE + SIZE_SMS_RECEIVED_MSG_IND,
            SMS_SB_TPDU,
            EIsiSubBlockTypeId16Len16,
            smsUserDataOffset ) )
            {
            TUint8 userDataLength( aReceivedSmsIsiMsg.Get8bit(
                smsUserDataOffset + SMS_SB_TPDU_OFFSET_DATALENGTH ) );
            TPtrC8 sms( aReceivedSmsIsiMsg.GetData(
                smsUserDataOffset + SMS_SB_TPDU_OFFSET_DATABYTES,
                userDataLength ) );

            if ( 0 < sms.Length() )
                {
                // Check type of received SMS message
                TUint8 messageParams( sms[0] );
                // Extract the least 2 bits to get SMS message type
                messageParams &= 0x03;
                if ( KSmsMTIDeliverOrDeliverReport == messageParams )
                    {
                    TPtrC8 tpOa( sms.Mid( 1 ) );
                    CMmSmsGsmAddress::GsmConv0340AddrToUnicode(
                        receivedMsgOriginatorAdress,
                        tpOa,
                        receivedMsgMobileOaTON,
                        receivedMsgMobileOaNPI );
                    }
                }
            }
        else // Could not extract data from received message
            {
TFLOGSTRING("TSY: CMmSmsMessHandler::CheckTpPidAndSenderAndServiceCenter: Could not extract data from received message");
OstTrace0( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_CHECKTPPIDANDSENDERANDSERVICECENTER_TD, "CMmSmsMessHandler::CheckTpPidAndSenderAndServiceCenter - Could not extract data from received message" );
            return EFalse;
            }

        // 3. Get sender number from stored message

        TPtrC8 tpOa( aSMSOnSIM->iMsgData.Mid ( 1 ) );
        CMmSmsGsmAddress::GsmConv0340AddrToUnicode(
            readMsgOriginatorAdress,
            tpOa,
            readMsgMobileOaTON,
            readMsgMobileOaNPI );

        // 4. Compare
        if ( ( receivedMsgMobileOaTON == readMsgMobileOaTON )
            && ( receivedMsgMobileOaNPI == readMsgMobileOaNPI )
            && ( 0 == receivedMsgOriginatorAdress.Compare(
            readMsgOriginatorAdress ) )

            && ( receivedMsgMobileScTON == aSMSOnSIM->iServiceCentre.iTypeOfNumber )
            && ( receivedMsgMobileScNPI == aSMSOnSIM->iServiceCentre.iNumberPlan )
            && ( 0 == receivedMsgServiceCentre.Compare(
                 aSMSOnSIM->iServiceCentre.iTelNumber ) ) )
            {
            matchFound = ETrue;
            }
        }
    return matchFound;
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::GetSmsStoreInfo
// ETel requests EMobileSmsMessagingGetMessageStoreInfo and
// EMobilePhoneStoreGetInfo
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::GetSmsStoreInfo( TInt aIpc )
    {
TFLOGSTRING2("TSY: CMmSmsMessHandler::GetSmsStoreInfo - IPC: %d", aIpc);
OstTrace1( TRACE_NORMAL,  CMMSMSMESSHANDLER_GETSMSSTOREINFO_TD, "CMmSmsMessHandler::GetSmsStoreInfo;aIpc=%d", aIpc );
    TInt ret( KErrNone );
    // SIM SMS cache:
    // -- EMobileSmsMessagingGetMessageStoreInfo/EMobilePhoneStoreGetInfo
    if ( KErrNone == iSmsCache.Status() )
        {
TFLOGSTRING("TSY: CMmSmsMessHandler::GetSmsStoreInfo -- completed immediatedly");
OstTrace0( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_GETSMSSTOREINFO_TD, "CMmSmsMessHandler::GetSmsStoreInfo, completed immediatedly" );
        TUint8 numOfLoc( TUint8( iSmsCache.TotalEntries() ) );
        TInt usedEntries( iSmsCache.UsedEntries() );
        CMmDataPackage data;
        data.PackData( &numOfLoc, &usedEntries );
        iMessageRouter->Complete( aIpc, &data, KErrNone );
        }
    // try to recover from out of memory condition
    else if ( KErrNoMemory == iSmsCache.Status() )
        {
TFLOGSTRING("TSY: CMmSmsMessHandler::GetSmsStoreInfo -- recovering from OOM");
OstTrace0( TRACE_NORMAL,  DUP2_CMMSMSMESSHANDLER_GETSMSSTOREINFO_TD, "CMmSmsMessHandler::GetSmsStoreInfo, recovering from OOM" );
        InitializeSmsCache();
        }
    // cache is not ready, start waiting
    else if ( KErrNotReady == iSmsCache.Status() )
        {
TFLOGSTRING("TSY: CMmSmsMessHandler::GetSmsStoreInfo -- waiting");
OstTrace0( TRACE_NORMAL,  DUP3_CMMSMSMESSHANDLER_GETSMSSTOREINFO_TD, "CMmSmsMessHandler::GetSmsStoreInfo, waiting" );
        }
    // some other, error return error value
    else
        {
TFLOGSTRING("TSY: CMmSmsMessHandler::GetSmsStoreInfo -- failed");
OstTrace0( TRACE_NORMAL,  DUP4_CMMSMSMESSHANDLER_GETSMSSTOREINFO_TD, "CMmSmsMessHandler::GetSmsStoreInfo, failed" );
        ret = iSmsCache.Status();
        }
    return ret;
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::DeleteSms
// Delete SMS from SIM
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::DeleteSms( const CMmDataPackage* aDataPackage )
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::DeleteSms");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_DELETESMS_TD, "CMmSmsMessHandler::DeleteSms" );
    // SIM SMS cache: -- EMobilePhoneStoreDelete
    TInt ret( KErrNone );

    // Symbian sms stack will try to delete received SMS2 from SIM if it can't
    // save it to filesystem, so deletion should be possible in out of memory
    // state..
    if ( KErrNone == iSmsCache.Status() || KErrNoMemory == iSmsCache.Status() )
        {
        TInt index( 0 );
        //unpack data
        aDataPackage->UnPackData( index );
        RMobileSmsStore::TMobileGsmSmsEntryV1* smsData(
            iSmsCache.GetEntry( index ) );

        if ( smsData )
            {
            iSmsCache.SetDeleteLocation( index );

            // Set parameters for UICC_APPL_CMD_REQ message
            TUiccWriteLinearFixed params;
            params.messHandlerPtr = static_cast<MUiccOperationBase*>( this );
            params.trId = ETrIdDeleteSMS;
            params.dataOffset = 0;
            params.dataAmount = 0;
            params.record = index;

            params.fileId = KElemFileShortMessages;
            params.fileIdSfi = UICC_SFI_NOT_PRESENT;
            params.serviceType = UICC_APPL_UPDATE_LINEAR_FIXED;

            // File id path
            params.filePath.Append( KMasterFileId >> 8 );
            params.filePath.Append( KMasterFileId );
            params.filePath.Append( iMmUiccMessHandler->GetApplicationFileId() );

            // Update file data with 0xFF
            TBuf8<KSmsElemetaryFileRecordLength> fileDataBuf;
            fileDataBuf.AppendFill( 0xFF, KSmsElemetaryFileRecordLength );

            params.fileData.Append( fileDataBuf );

            return iMmUiccMessHandler->CreateUiccApplCmdReq( params );
            }
        else
            {
            // Location empty or not in use.
            iMessageRouter->Complete( EMobilePhoneStoreDelete, KErrNone );
            }
        }
    else
        {
TFLOGSTRING("TSY: CMmSmsMessHandler::DeleteSms, cache not ready/failed");
OstTrace0( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_DELETESMS_TD, "CMmSmsMessHandler::DeleteSms, cache not ready/failed" );
        ret = iSmsCache.Status();
        }
    return ret;
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::DeleteAllSms
// Delete all SMS's from sim
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::DeleteAllSms()
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::DeleteAllSms");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_DELETEALLSMS_TD, "CMmSmsMessHandler::DeleteAllSms" );
    TInt ret( KErrNone );
    // SIM SMS cache: -- EMobilePhoneStoreDeleteAll
    if ( KErrNone == iSmsCache.Status() )
        {
        if ( 0 < iSmsCache.TotalEntries() )
            {
            RMobileSmsStore::TMobileGsmSmsEntryV1* smsData(
                iSmsCache.GetEntry( iRecordId ) );

            if ( smsData )
                {
                iSmsCache.SetDeleteLocation( iRecordId );

                // Set parameters for UICC_APPL_CMD_REQ message
                TUiccWriteLinearFixed params;
                params.messHandlerPtr = static_cast<MUiccOperationBase*>( this );
                params.trId = ETrIdDeleteAllSMSs;
                params.dataOffset = 0;
                params.dataAmount = 0;
                params.record = iRecordId;

                params.fileId = KElemFileShortMessages;
                params.fileIdSfi = UICC_SFI_NOT_PRESENT;
                params.serviceType = UICC_APPL_UPDATE_LINEAR_FIXED;

                // File id path
                params.filePath.Append( KMasterFileId >> 8 );
                params.filePath.Append( KMasterFileId );
                params.filePath.Append( iMmUiccMessHandler->GetApplicationFileId() );

                // Update file data with 0xFF
                TBuf8<KSmsElemetaryFileRecordLength> fileDataBuf;
                fileDataBuf.AppendFill( 0xFF, KSmsElemetaryFileRecordLength );

                params.fileData.Append( fileDataBuf );

                return iMmUiccMessHandler->CreateUiccApplCmdReq( params );
                }
            else
                {
                // Location is empty. Check next location
                UiccDeleteAllSMSResp( KErrNone );
                }
            }
        else
            {
            iMessageRouter->Complete( EMobilePhoneStoreDeleteAll, KErrNone );
            }
        }
    else
        {
TFLOGSTRING("TSY: CMmSmsMessHandler::DeleteAllSms, cache not ready/failed");
OstTrace0( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_DELETEALLSMS_TD, "CMmSmsMessHandler::DeleteAllSms, cache not ready/failed" );
        ret = iSmsCache.Status();
        }
    return ret;
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::ReadSms
// Read SMS's from SIM
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::ReadSms( const CMmDataPackage* aDataPackage )
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::ReadSms");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_READSMS_TD, "CMmSmsMessHandler::ReadSms" );

    TInt ret( KErrNone );

    TInt location( 0 );
    //unpack data
    aDataPackage->UnPackData( location );

    // SIM SMS cache: -- EMobilePhoneStoreRead
    if ( KErrNone == iSmsCache.Status() )
        {
         // Find sms from cache
        RMobileSmsStore::TMobileGsmSmsEntryV1* smsData(
            iSmsCache.GetEntry( location ) );

        if ( smsData )
            {
            TSmsMsg smsMsg;
            smsMsg.iLocation = location;
            smsMsg.iMessageStatus = smsData->iMsgStatus;
            smsMsg.iMobileScNPI = smsData->iServiceCentre.iNumberPlan;
            smsMsg.iMobileScTON = smsData->iServiceCentre.iTypeOfNumber;
            smsMsg.iServiceCentre = smsData->iServiceCentre.iTelNumber;
            smsMsg.iSmsClass2 = ETrue;
            smsMsg.iSmsMsg = smsData->iMsgData;

            CMmDataPackage data;
            data.PackData( &smsMsg );
            iMessageRouter->Complete(
                EMobilePhoneStoreRead,
                &data,
                KErrNone );

            ret = KErrNone;
            }
        else
            {
            ret = KErrNotFound;
            }
        }
    else
        {
TFLOGSTRING("TSY: CMmSmsMessHandler::ReadSms, cache not ready/failed");
OstTrace0( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_READSMS_TD, "CMmSmsMessHandler::ReadSms, cache not ready/failed" );
        ret = iSmsCache.Status();
        }
    return ret;
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::ReadAllSmsL
// Read SMS's from SIM
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::ReadAllSmsL()
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::ReadAllSms");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_READALLSMSL_TD, "CMmSmsMessHandler::ReadAllSmsL" );
    TInt ret( KErrNone );

    // SIM SMS cache: -- EMobilePhoneStoreReadAllPhase1
    if ( KErrNone == iSmsCache.Status() )
        {
        // reads all sms's from SIM to a list and returns
        // the list to commontsy.

        iSmsListArray->ResetAndDestroy();

        // process & copy SMS's to iSmsListArray..
        for ( TInt i( 1 ); i <= iSmsCache.TotalEntries(); i++ )
            {
            // Add read SMS to the TSY's internal storage
            // Find sms from cache
            RMobileSmsStore::TMobileGsmSmsEntryV1* smsData(
                iSmsCache.GetEntry( i ) );

            TSmsMsg* smsMsg = new ( ELeave )TSmsMsg();
            CleanupDeletePushL( smsMsg );

            if ( smsData )
                {
                smsMsg->iLocation = i;
                smsMsg->iMessageStatus = smsData->iMsgStatus;
                smsMsg->iMobileScNPI = smsData->iServiceCentre.iNumberPlan;
                smsMsg->iMobileScTON = smsData->iServiceCentre.iTypeOfNumber;
                smsMsg->iServiceCentre = smsData->iServiceCentre.iTelNumber;
                smsMsg->iSmsClass2 = ETrue;
                smsMsg->iSmsMsg = smsData->iMsgData;

                iSmsListArray->AppendL( smsMsg );
                CleanupStack::Pop( smsMsg );
                }
            else
                {
                CleanupStack::PopAndDestroy( smsMsg );
                }
            }

        // complete immediatedly...
        CMmDataPackage package;
        package.PackData( &iSmsListArray, &iReceivedClass2ToBeReSent );
        iMessageRouter->Complete(
            EMobilePhoneStoreReadAllPhase1,
            &package,
            KErrNone );

        //Delete array
        iSmsListArray->ResetAndDestroy();
        iReceivedClass2ToBeReSent = EFalse;
        }
    else
        {
TFLOGSTRING("TSY: CMmSmsMessHandler::ReadAllSms --- cache not ready/failed");
OstTrace0( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_READALLSMSL_TD, "CMmSmsMessHandler::ReadAllSmsL, cache not ready/failed" );
        iSmsListArray->ResetAndDestroy();
        CMmDataPackage package;
        package.PackData( &iSmsListArray, &iReceivedClass2ToBeReSent );
        iMessageRouter->Complete(
            EMobilePhoneStoreReadAllPhase1,
            &package,
            iSmsCache.Status() );
        iReceivedClass2ToBeReSent = EFalse;
        }
    return ret;
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::WriteSms
// Write SMS to SIM
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::WriteSms(
    const RMobileSmsStore::TMobileGsmSmsEntryV1& aEntry,
    TInt aIndex)
    {
    TInt ret( KErrNone );

TFLOGSTRING("TSY: CMmSmsMessHandler::WriteSms");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_WRITESMS_TD, "CMmSmsMessHandler::WriteSms" );

    // SIM SMS cache: -- EMobilePhoneStoreWrite
    //check if sms writing is ongoing or not
    if ( 0 != iSmsSlotLocation )
        {
        ret = KErrNotReady;
        }
    else if ( KErrNone == iSmsCache.Status() )
        {

        //iWriteSmsEntryPtr = aEntry;

        //find a free slot to write the Sms
        // -1 means "find the frst free slot"
        if ( -1 != aIndex )
            {
            iSmsSlotLocation = TUint8( aIndex );
            }
        else
            {
            iSmsSlotLocation = TUint8( iSmsCache.FirstFreeLocation() );
            aIndex = iSmsSlotLocation;
            }

        if ( 0 == iSmsSlotLocation )
            {
            // asked to write to a free slot, but no free slots found
            ret = CMmStaticUtility::EpocErrorCode(
                KErrOverflow,
                KErrMMEtelMaxReached );
            }
        else
            {
            ret = UiccWriteSMSReq( aEntry, iSmsSlotLocation );
            }
        }
    else
        {
        ret = iSmsCache.Status();
        }
    return ret;
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::InitializeSmsCache
// Start reading cache
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::InitializeSmsCache()
    {
    // SIM SMS cache: initialize cache
    if( KErrNotReady != iSmsCache.Status() )
        {
TFLOGSTRING("TSY: CMmSmsMessHandler::InitializeSmsCache -- SMS CACHEING START ---");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_INITIALIZESMSCACHE_TD, "CMmSmsMessHandler::InitializeSmsCache" );
        iSmsCache.Reset();
        GetNumOfEFSMSRecords (); // Read EF SMS count.
        }
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::HandleError
// Handles CMmSmsMessHandler's errors comes via PhoNetReceiver RunError method.
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::HandleError(
        const TIsiReceiveC& aIsiMsg, // Isi message
        TInt aError )                // Error code

    {
TFLOGSTRING2( "TSY: CMmSmsMessHandler::HandleError - Error: %d", aError );
OstTrace1( TRACE_NORMAL,  CMMSMSMESSHANDLER_HANDLEERROR_TD, "CMmSmsMessHandler::HandleError;aError=%d", aError );

    TUint8 resource( aIsiMsg.Get8bit( ISI_HEADER_OFFSET_RESOURCEID ) );
    TUint8 messageId( aIsiMsg.Get8bit( ISI_HEADER_OFFSET_MESSAGEID ) );
    TUint8 transId( aIsiMsg.Get8bit( ISI_HEADER_OFFSET_TRANSID ) );

TFLOGSTRING4( "TSY: CMmSmsMessHandler::HandleError - resource: %d, msgId: %d, traId: %d", resource, messageId, transId );
OstTraceExt3(TRACE_NORMAL,DUP1_CMMSMSMESSHANDLER_HANDLEERROR_TD,"CMmSmsMessHandler::HandleError;resource=%hhu;messageId=%hhu;transId=%hhu", resource, messageId, transId );

    switch ( resource )
        {
        default:
            {
TFLOGSTRING2( "TSY: CMmSmsMessHandler::HandleError - PN_SMS, unknown resource: %d", resource );
OstTraceExt1( TRACE_NORMAL,  DUP4_CMMSMSMESSHANDLER_HANDLEERROR_TD, "CMmSmsMessHandler::HandleError;resource=%hhu", resource );
            // Nothing to do here.
            break;
            }
        }
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::SmsSettingsUpdateReq
// Sets SMS bearer.
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::SmsSettingsUpdateReq(
    RMobileSmsMessaging::TMobileSmsBearer& aBearer )
    {
TFLOGSTRING2("TSY: CMmSmsMessHandler::SmsSettingsUpdateReq. aBearer: %d", aBearer);
OstTrace1( TRACE_NORMAL,  CMMSMSMESSHANDLER_SMSSETTINGSUPDATEREQ_TD, "CMmSmsMessHandler::SmsSettingsUpdateReq;aBearer=%d", aBearer );

    TUint8 csRoutePriority( SMS_ROUTE_NOT_AVAILABLE );
    TUint8 psRoutePriority( SMS_ROUTE_NOT_AVAILABLE );

    // The bearer information must be used in two ways:
    // 1. It must be saved here, and is used later for SMS sending.
    iMobileSmsBearer = aBearer;

    // 2. It must be immediadely set to ISI SMS Server (affects
    // RP-SHORT-MESSAGE-MEMORY-AVAILABLE).
    switch ( iMobileSmsBearer )
        {
        case RMobileSmsMessaging::ESmsBearerPacketOnly:
            { // PS with highest priority, CS not available
            psRoutePriority = SMS_ROUTE_PRIORITY_1;
            break;
            }
        case RMobileSmsMessaging::ESmsBearerPacketPreferred:
            { // PS with highest priority, CS with second highest priority
            psRoutePriority = SMS_ROUTE_PRIORITY_1;
            csRoutePriority = SMS_ROUTE_PRIORITY_2;
            break;
            }
        case RMobileSmsMessaging::ESmsBearerCircuitOnly:
            { // CS with highest priority, PS not available
            csRoutePriority = SMS_ROUTE_PRIORITY_1;
            break;
            }
        case RMobileSmsMessaging::ESmsBearerCircuitPreferred:
            { // CS with highest priority, PS with second highest priority
            csRoutePriority = SMS_ROUTE_PRIORITY_1;
            psRoutePriority = SMS_ROUTE_PRIORITY_2;
            break;
            }
        default:
            {
TFLOGSTRING2("TSY:CMmSmsMessHandler::SmsSettingsUpdateReq:Invalid bearer = %d",iMobileSmsBearer);
OstTrace1( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_SMSSETTINGSUPDATEREQ_TD, "CMmSmsMessHandler::SmsSettingsUpdateReq;iMobileSmsBearer=%d", iMobileSmsBearer );
            break;
            }
        }

TFLOGSTRING3("TSY:CMmSmsMessHandler::SmsSettingsUpdateReq:CS priority = %d, PS priority = %d",csRoutePriority,psRoutePriority);
OstTraceExt2( TRACE_NORMAL,  DUP2_CMMSMSMESSHANDLER_SMSSETTINGSUPDATEREQ_TD, "CMmSmsMessHandler::SmsSettingsUpdateReq;csRoutePriority=%hhd;psRoutePriority=%hhd", csRoutePriority, psRoutePriority );

    // SMS_SB_ROUTE_INFO sub block (8 bytes)
    TBuf8<SIZE_SMS_SB_ROUTE_INFO> smsRouteInfoBuf( 0 );
    TIsiSubBlock smsRouteInfoSb(
        smsRouteInfoBuf,
        SMS_SB_ROUTE_INFO,
        EIsiSubBlockTypeId16Len16 );
    smsRouteInfoBuf.Append( csRoutePriority );
    smsRouteInfoBuf.Append( psRoutePriority );

    // Create SMS_SETTINGS_UPDATE_REQ message
    TIsiSend isiMsg( iPhoNetSender->SendBufferDes() );
    isiMsg.Set8bit( ISI_HEADER_OFFSET_RESOURCEID, PN_SMS );
    isiMsg.Set8bit(
        ISI_HEADER_SIZE + SMS_SETTINGS_UPDATE_REQ_OFFSET_TRANSID,
        0 );
    isiMsg.Set8bit(
        ISI_HEADER_SIZE + SMS_SETTINGS_UPDATE_REQ_OFFSET_MESSAGEID,
        SMS_SETTINGS_UPDATE_REQ  );
    isiMsg.Set8bit(
        ISI_HEADER_SIZE + SMS_SETTINGS_UPDATE_REQ_OFFSET_SETTINGTYPE,
        SMS_SETTING_TYPE_ROUTE );
    isiMsg.Set8bit(
        ISI_HEADER_SIZE + SMS_SETTINGS_UPDATE_REQ_OFFSET_SUBBLOCKCOUNT,
        1 );

    isiMsg.CopyData(
        ISI_HEADER_SIZE + SIZE_SMS_SETTINGS_UPDATE_RESP,
        smsRouteInfoSb.CompleteSubBlock() );

    return ( iPhoNetSender->Send( isiMsg.Complete() ) );
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::SmsSettingsUpdateResp
// Completes SMS bearer setting.
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::SmsSettingsUpdateResp( const TIsiReceiveC& aIsiMsg )
    {
    TUint8 cause( aIsiMsg.Get8bit(
        ISI_HEADER_SIZE + SMS_SETTINGS_UPDATE_RESP_OFFSET_SMSCAUSE ) );

TFLOGSTRING2("TSY:CMmSmsMessHandler::SmsSettingsUpdateResp: response status=%d.",cause);
OstTraceExt1( TRACE_NORMAL,  CMMSMSMESSHANDLER_SMSGSMSETTINGSUPDATERESP_TD, "CMmSmsMessHandler::SmsSettingsUpdateResp;cause=%hhu", cause );

    TInt err( CMmStaticUtility::CSCauseToEpocError(
        PN_SMS,
        SMS_CAUSE_TYPE_COMMON,
        cause ) );

    iMessageRouter->Complete( EMobileSmsMessagingSetMoSmsBearer, err );
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::SmsClass2ReceivedMsgInd
// Processes class2 SMS. Called by CMmSmsMessHandler::SmsReceivedMsgInd.
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::SmsClass2ReceivedMsgInd(
    const TIsiReceiveC& aIsiMsg,
    TUint8 aIsReplace )
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::SmsClass2ReceivedMsgInd");
OstTrace0( TRACE_NORMAL,  DUP4_CMMSMSMESSHANDLER_SMSCLASS2PPROUTINGNTF_TD, "CMmSmsMessHandler::SmsClass2ReceivedMsgInd" );
    TInt ret( KErrNone );

    TUint smsTpduOffset( 0 );
    if ( KErrNone == aIsiMsg.FindSubBlockOffsetById(
        ISI_HEADER_SIZE + SIZE_SMS_RECEIVED_MSG_IND,
        SMS_SB_TPDU,
        EIsiSubBlockTypeId16Len16,
        smsTpduOffset ) )
        {
        // SMS_SB_TPDU sub block found
        // Checked if sms writing is ongoing or not and cache is ok
        if ( 0 == iSmsSlotLocation && KErrNone == iSmsCache.Status() )
            {
            TUint location( 0 );

            // If this is a replace message, try find a SMS to replace
            if ( aIsReplace )
                {
TFLOGSTRING("TSY: CMmSmsMessHandler::SmsClass2ReceivedMsgInd --- replace");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_SMSCLASS2PPROUTINGNTF_TD, "CMmSmsMessHandler::SmsClass2ReceivedMsgInd, replace" );
                for ( TInt i( 0 ); i <= iSmsCache.TotalEntries(); i++ )
                    {
                    RMobileSmsStore::TMobileGsmSmsEntryV1* simIsiMsg =
                        iSmsCache.GetEntry( i );
                    if ( simIsiMsg )
                        {
                        if ( CheckTpPidAndSenderAndServiceCenter(
                            aIsReplace,
                            aIsiMsg,
                            simIsiMsg ) )
                            {
                            location = i;
                            break;
                            }
                        }
                    }
                }

            // Not a replace message, or no message to replace found.
            // Try to find a free slot
            if ( 0 == location )
                {
                location = iSmsCache.FirstFreeLocation();
                }

            // Location found, start SMS writing
            if ( 0 != location )
                {
TFLOGSTRING2("TSY: CMmSmsMessHandler::SmsClass2ReceivedMsgInd -- incoming SMS2, writing to location %d", location);
OstTrace1( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_SMSCLASS2PPROUTINGNTF_TD, "CMmSmsMessHandler::SmsClass2ReceivedMsgInd;incoming SMS2, writing to location=%d", location );
                // iSmsSlotLocation = TUint8(location);
                // Write received class2 SMS to SIM Card
                // Get data from incoming message.
                RMobileSmsStore::TMobileGsmSmsEntryV1 incomingSMS;

                // 1. Get service center address from received message
                TUint smsAddressOffset( 0 );
                if ( KErrNone == aIsiMsg.FindSubBlockOffsetById(
                    ISI_HEADER_SIZE + SIZE_SMS_RECEIVED_MSG_IND,
                    SMS_SB_ADDRESS,
                    EIsiSubBlockTypeId16Len16,
                    smsAddressOffset ) )
                    {
                    if ( SMS_SMSC_ADDRESS == aIsiMsg.Get8bit(
                        smsAddressOffset + SMS_SB_ADDRESS_OFFSET_ADDRESSTYPE ) )
                        {
                        // Convert service centre address (SC Address 04.11)
                        TUint8 addressDataLength( aIsiMsg.Get8bit(
                            smsAddressOffset +
                            SMS_SB_ADDRESS_OFFSET_ADDRESSDATALENGTH ) );
                        TPtrC8 scA( aIsiMsg.GetData(
                            smsAddressOffset + SMS_SB_ADDRESS_OFFSET_ADDRESSDATA,
                            addressDataLength ) );
                        CMmSmsGsmAddress::GsmConv0411AddrToUnicode(
                            incomingSMS.iServiceCentre.iTelNumber,
                            scA,
                            incomingSMS.iServiceCentre.iTypeOfNumber,
                            incomingSMS.iServiceCentre.iNumberPlan );
                        }
                    }

                // 2. Get sender address from received message
                TUint smsUserDataOffset( 0 );
                if ( KErrNone == aIsiMsg.FindSubBlockOffsetById(
                    ISI_HEADER_SIZE + SIZE_SMS_RECEIVED_MSG_IND,
                    SMS_SB_TPDU,
                    EIsiSubBlockTypeId16Len16,
                    smsUserDataOffset ) )
                    {
                    TUint8 userDataLength( aIsiMsg.Get8bit(
                        smsUserDataOffset + SMS_SB_TPDU_OFFSET_DATALENGTH ) );
                    TPtrC8 sms( aIsiMsg.GetData(
                        smsUserDataOffset + SMS_SB_TPDU_OFFSET_DATABYTES,
                        userDataLength ) );

                    if ( 0 < sms.Length() )
                        {
                        // Check type of received SMS message
                        TUint8 position( 0 );
                        incomingSMS.iMsgStatus =
                            static_cast <RMobileSmsStore::TMobileSmsStoreStatus>( sms[position] );

                        // Start of the user data
                        incomingSMS.iMsgData =  sms.Mid( position );
                        }
                    }
                    iSMSClass2Write = ETrue;
                    ret = WriteSms( incomingSMS, location );
               }

            // No free slots! SIM full
            else
                {
                ret = KErrGsmSMSUnspecifiedProtocolError;
                }
            }

        // Cache not ready
        else
            {
TFLOGSTRING("TSY: CMmSmsMessHandler::SmsClass2ReceivedMsgInd -- incoming SMS2, cache not ready/failed");
OstTrace0( TRACE_NORMAL,  DUP2_CMMSMSMESSHANDLER_SMSCLASS2PPROUTINGNTF_TD, "CMmSmsMessHandler::SmsClass2ReceivedMsgInd, incoming SMS2, cache not ready/failed" );
            ret = KErrGsmSMSMemoryCapacityExceeded;
            // Setting this true will cause it to be resent?
            iReceivedClass2ToBeReSent = ETrue;

            // If this is out of memory error, try to refill cache..
            if ( KErrNoMemory == iSmsCache.Status() )
                {
                InitializeSmsCache();
                }
            }
        }

TFLOGSTRING2("TSY: CMmSmsMessHandler::SmsClass2ReceivedMsgInd ret=%d", ret);
OstTrace1( TRACE_NORMAL,  DUP3_CMMSMSMESSHANDLER_SMSCLASS2PPROUTINGNTF_TD, "CMmSmsMessHandler::SmsClass2ReceivedMsgInd;ret=%d", ret );
    return ret;
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::SmsClass1ReceivedMsgInd
// Processes class1 SMS. Called by CMmSmsMessHandler::SmsReceivedMsgInd.
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::SmsClass1ReceivedMsgInd(
        const TIsiReceiveC& aIsiMsg)
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::SmsClass1ReceivedMsgInd");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_SMSCLASS1PPROUTINGNTF_TD, "CMmSmsMessHandler::SmsClass1ReceivedMsgInd" );
    TInt ret( KErrNone );
    TBool validPduFormat( EFalse );
    TSmsMsg  smsMsgValue;
    TSmsMsg* smsMsg = &smsMsgValue;

    // Handle SMS_SB_ADDRESS subblock (service center address)
    TUint smsAddressOffset( 0 );
    if ( KErrNone == aIsiMsg.FindSubBlockOffsetById(
        ISI_HEADER_SIZE + SIZE_SMS_RECEIVED_MSG_IND,
        SMS_SB_ADDRESS,
        EIsiSubBlockTypeId16Len16,
        smsAddressOffset ) )
        {
         TUint8 addressDataLength( aIsiMsg.Get8bit(
             smsAddressOffset + SMS_SB_ADDRESS_OFFSET_ADDRESSDATALENGTH ) );

         TPtrC8 serviceCenterAddress( aIsiMsg.GetData(
             smsAddressOffset + SMS_SB_ADDRESS_OFFSET_ADDRESSDATA,
             addressDataLength ) );

         CMmSmsGsmAddress::GsmConv0411AddrToUnicode(
             smsMsg->iServiceCentre,
             serviceCenterAddress,
             smsMsg->iMobileScTON,
             smsMsg->iMobileScNPI );
         }
     else
         {
TFLOGSTRING("TSY:CMmSmsMessHandler::SmsClass1ReceivedMsgInd,SMS_SB_ADDRESS expected");
OstTrace0( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_SMSCLASS1PPROUTINGNTF_TD, "CMmSmsMessHandler::SmsClass1ReceivedMsgInd,SMS_SB_ADDRESS expected" );
         TF_ASSERT_NOT_REACHED();
         }

    // Handle SMS_SB_TPDU subblock
    TUint smsTpduOffset( 0 );
    if ( KErrNone == aIsiMsg.FindSubBlockOffsetById(
        ISI_HEADER_SIZE + SIZE_SMS_RECEIVED_MSG_IND,
        SMS_SB_TPDU,
        EIsiSubBlockTypeId16Len16,
        smsTpduOffset ) )
        {
        TUint8 userDataLength( aIsiMsg.Get8bit(
            smsTpduOffset + SMS_SB_TPDU_OFFSET_DATALENGTH ) );

        TPtrC8 smsUserData( aIsiMsg.GetData(
            smsTpduOffset + SMS_SB_TPDU_OFFSET_DATABYTES,
            userDataLength ) );

        if ( 0 < smsUserData.Length() )
            {
            // Check type of received SMS message
            TUint8 messageParams( smsUserData[0] );
            messageParams &= 0x03;

            // Copy SMS to iSmsMsg if message type was SMS-DELIVER or
            // SMS-STATUS-REPORT. Set also KSimSmsNotPresent in iMessageStatus
            // because message is routed directly to the SMS stack (not
            // stored in SIM).
            if ( KSmsMTIDeliverOrDeliverReport == messageParams ||
                KSmsMTIStatusReportOrCommand == messageParams )
                {
                validPduFormat = ETrue;
                smsMsg->iMessageStatus = KSimSmsNotPresent;
                smsMsg->iSmsMsg.Copy( smsUserData );
                }
            }
        else
            {
TFLOGSTRING("TSY:CMmSmsMessHandler::SmsClass1ReceivedMsgInd, SMS_SB_USER_DATA expected");
OstTrace0( TRACE_NORMAL,  DUP2_CMMSMSMESSHANDLER_SMSCLASS1PPROUTINGNTF_TD, "CMmSmsMessHandler::SmsClass1ReceivedMsgInd, SMS_SB_USER_DATA expected" );
            TF_ASSERT_NOT_REACHED();
            }

        if ( validPduFormat )
            {
            TBool smsInd( ETrue );
            smsMsg->iSmsClass2 = EFalse;

            // Pack data
            CMmDataPackage package;
            package.PackData( &smsInd, &smsMsg );

            // Complete request to client
            iMessageRouter->Complete(
                EMobileSmsMessagingReceiveMessage,
                &package,
                KErrNone );

            ret = KErrNone; // avoid doubled completion
            }
        else
            {
            // Message type is undefined. Send NACK to the SMS Server.
            SmsReceivedMsgReportReq(
                EInternalNack,
                NULL,
                KErrGsmSMSUnspecifiedInvalidMessage );
            // Caller is forced to complete
            ret = KErrGeneral;
            }
        }
TFLOGSTRING2("TSY:CMmSmsMessHandler::SmsClass1ReceivedMsgInd;ret=%d", ret);
OstTrace1( TRACE_NORMAL,  DUP3_CMMSMSMESSHANDLER_SMSCLASS1PPROUTINGNTF_TD, "CMmSmsMessHandler::SmsClass1ReceivedMsgInd;ret=%d", ret );
    return ret;
    }


// -----------------------------------------------------------------------------
// CMmSmsMessHandler::GetDestAddressLength
// Extracts the length of destination address from TPDU in octets
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::GetDestAddressLength(
    const TDesC8& aMsgData,
    TUint8 subBlockId,
    TUint8& aDestAddressLength ) const
    {
TFLOGSTRING("TSY:CMmSmsMessHandler::GetDestAddressLength");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_GETDESTADDRESSLENGTH_TD, "CMmSmsMessHandler::GetDestAddressLength" );

    TInt ret( KErrNone );

    if ( SMS_SB_SUBMIT == subBlockId )
        {
        aDestAddressLength =
            aMsgData[ KTpduSubmitIndexDestinationAddressLength ] ;
        }
    else
        {
        aDestAddressLength =
            aMsgData[ KTpduCommandIndexDestinationAddressLength ] ;
        }

    // According 3GPP 23.040 max length of destination address is 20
    if ( KMaxAmountOfDigits >= aDestAddressLength )
        {
        // Destination address length is integer representation
        // of the number of useful semi-octets of address field
        aDestAddressLength =  ( aDestAddressLength + 1 ) / 2 ;
        }
    else
        {
        ret = KErrArgument;
TFLOGSTRING2("TSY:CMmSmsMessHandler::GetDestinationAddressLength: Error! Destination address too long: %d.",aDestAddressLength);
OstTraceExt1( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_GETDESTADDRESSLENGTH_TD, "CMmSmsMessHandler::GetDestAddressLength;aDestAddressLength=%hhu", aDestAddressLength );
        }
TFLOGSTRING2("TSY:CMmSmsMessHandler::GetDestinationAddressLength:Destination address length %d.",aDestAddressLength);
OstTraceExt1( TRACE_NORMAL,  DUP2_CMMSMSMESSHANDLER_GETDESTADDRESSLENGTH_TD, "CMmSmsMessHandler::GetDestAddressLength;aDestAddressLength=%hhu", aDestAddressLength );
    return ret;
    }


// -----------------------------------------------------------------------------
// CMmSmsMessHandler::BuildSmsSbSubmit
// Creates SMS_SB_SUBMIT subblock and appends it to ISI message
// -----------------------------------------------------------------------------
//
TUint16 CMmSmsMessHandler::BuildSmsSbSubmit(
    const TDesC8& aMsgData,
    TIsiSend& aIsiMsg,
    TUint8 aDestAddressLength,
    TUint aMsgOffset ) const
    {
TFLOGSTRING("TSY:CMmSmsMessHandler::BuildSmsSbSubmit");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_BUILDSMSSBSUBMIT_TD, "CMmSmsMessHandler::BuildSmsSbSubmit" );

    // Extract needed parameters from TPDU for for SMS_SB_SUBMIT
    TUint8 messageParameters( aMsgData[ KTpduIndexMessageParameters ] );
    TUint8 messageReference( aMsgData[ KTpduIndexMessageReference ] );
    TUint8 protocolId( aMsgData[ KTpduSubmitIndexProtocolIdentifier +
        aDestAddressLength ] );
    TUint8 dataCodingScheme( aMsgData[ KTpduSubmitIndexDataCodingScheme +
        aDestAddressLength ] );

    // Create and fill SMS_SB_SUBMIT subblock
    TBuf8<SIZE_SMS_SB_SUBMIT> submitBuf;
    TIsiSubBlock submit( submitBuf, SMS_SB_SUBMIT, EIsiSubBlockTypeId16Len16 );
    submitBuf.Append( messageParameters );
    submitBuf.Append( messageReference );
    submitBuf.Append( protocolId );
    submitBuf.Append( dataCodingScheme );

    aIsiMsg.CopyData( aMsgOffset, submit.CompleteSubBlock() );

TFLOGSTRING2( "TSY:CMmSmsMessHandler::BuildSmsSbSubmit. Message parameters: %d", messageParameters );
TFLOGSTRING2( "TSY:CMmSmsMessHandler::BuildSmsSbSubmit. Message reference: %d", messageReference );
TFLOGSTRING2( "TSY:CMmSmsMessHandler::BuildSmsSbSubmit. Protocol ID: %d", protocolId );
TFLOGSTRING2( "TSY:CMmSmsMessHandler::BuildSmsSbSubmit. Data coding scheme: %d", dataCodingScheme );
OstTraceExt4( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_BUILDSMSSBSUBMIT_TD, "CMmSmsMessHandler::BuildSmsSbSubmit;messageParameters=%hhu;messageReference=%hhu;protocolId=%hhu;dataCodingScheme=%hhu", messageParameters, messageReference, protocolId, dataCodingScheme );

    return submitBuf.Length();
    }


// -----------------------------------------------------------------------------
// CMmSmsMessHandler::BuildSmsSbCommand
// Creates SMS_SB_COMMAND subblock and appends it to ISI message
// -----------------------------------------------------------------------------
TUint16 CMmSmsMessHandler::BuildSmsSbCommand(
    const TDesC8& aMsgData,
    TIsiSend& aIsiMsg,
    TUint aMsgOffset ) const
    {
TFLOGSTRING("TSY:CMmSmsMessHandler::BuildSmsSbCommand");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_BUILDSMSSBCOMMAND_TD, "CMmSmsMessHandler::BuildSmsSbCommand" );

    // Extract needed parameters from TPDU for SMS_SB_COMMAND
    TUint8 messageParameters( aMsgData[ KTpduIndexMessageParameters ] );
    TUint8 messageReference( aMsgData[ KTpduIndexMessageReference ] );
    TUint8 protocolId( aMsgData[ KTpduCommandIndexProtocolIdentifier ] );
    TUint8 commandType( aMsgData[ KTpduCommandIndexType ] );
    TUint8 messageNumber( aMsgData[ KTpduCommandIndexMessageNumber ] );

    // Create and fill SMS_SB_COMMAND subblock
    TBuf8<SIZE_SMS_SB_COMMAND> commandBuf;
    TIsiSubBlock command(
        commandBuf,
        SMS_SB_COMMAND,
        EIsiSubBlockTypeId16Len16 );

    commandBuf.Append( messageParameters );
    commandBuf.Append( messageReference );
    commandBuf.Append( protocolId );
    commandBuf.Append( commandType );
    commandBuf.Append( messageNumber );

    aIsiMsg.CopyData( aMsgOffset, command.CompleteSubBlock() );

TFLOGSTRING2( "TSY:CMmSmsMessHandler::BuildSmsSbCommand. Message parameters: %d", messageParameters );
TFLOGSTRING2( "TSY:CMmSmsMessHandler::BuildSmsSbCommand. Message reference: %d", messageReference );
TFLOGSTRING2( "TSY:CMmSmsMessHandler::BuildSmsSbCommand. Protocol ID: %d", protocolId );
TFLOGSTRING2( "TSY:CMmSmsMessHandler::BuildSmsSbCommand. Command type: %d", commandType );
TFLOGSTRING2( "TSY:CMmSmsMessHandler::BuildSmsSbCommand. Message Number: %d", messageNumber );
OstTraceExt5( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_BUILDSMSSBCOMMAND_TD, "CMmSmsMessHandler::BuildSmsSbCommand;messageParameters=%hhu;messageReference=%hhu;protocolId=%hhu;commandType=%hhu;messageNumber=%hhu", messageParameters, messageReference, protocolId, commandType, messageNumber );

    return commandBuf.Length();
    }


// -----------------------------------------------------------------------------
// CMmSmsMessHandler::BuildSmsSbAddress
// Creates SMS_SB_ADDRESS subblock and appends it to ISI message
// -----------------------------------------------------------------------------
TUint16 CMmSmsMessHandler::BuildSmsSbAddress(
    const TDesC8& aAddress,
    TIsiSend& aIsiMsg,
    TUint8 aAddressType,
    TUint aMsgOffset ) const
    {
TFLOGSTRING("TSY:CMmSmsMessHandler::BuildSmsSbAddress");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_BUILDSMSSBADDRESS_TD, "CMmSmsMessHandler::BuildSmsSbAddress" );

    TUint8 addressLength( aAddress.Length() );
    // Create and fill SMS_SB_ADDRESS subblock
    TBuf8<SIZE_SMS_SB_ADDRESS + SMS_ADDRESS_MAX_LEN> addressBuf( 0 );
    TIsiSubBlock address(
        addressBuf,
        SMS_SB_ADDRESS,
        EIsiSubBlockTypeId16Len16 );
    addressBuf.Append( aAddressType  );
    addressBuf.Append( addressLength );
    addressBuf.Append( aAddress );

    aIsiMsg.CopyData( aMsgOffset, address.CompleteSubBlock() );

TFLOGSTRING2( "TSY:CMmSmsMessHandler::BuildSmsSbAddress. Address type: %d", aAddressType );
TFLOGSTRING2( "TSY:CMmSmsMessHandler::BuildSmsSbAddress. Address length: %d", addressLength );
OstTraceExt2( TRACE_NORMAL,  DUP2_CMMSMSMESSHANDLER_BUILDSMSSBADDRESS_TD, "CMmSmsMessHandler::BuildSmsSbAddress;aAddressType=%hhu;addressLength=%hhu", aAddressType, addressLength );
#ifdef _DEBUG
for ( TInt i( 0 ); i < aAddress.Length(); i++ )
    {
TFLOGSTRING3( "TSY:CMmSmsMessHandler::BuildSmsSbAddress. Address data[%d]: 0x%x", i, aAddress[i] );
OstTraceExt2( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_BUILDSMSSBADDRESS_TD, "CMmSmsMessHandler::BuildSmsSbAddress;i=%hhu;aAddress[i]=%hhu", i, aAddress[i] );
    }
#endif // _DEBUG

    return addressBuf.Length();
    }


// -----------------------------------------------------------------------------
// CMmSmsMessHandler::BuildSmsSbUserData
// Creates SMS_SB_USER_DATA subblock and appends it to ISI message
// -----------------------------------------------------------------------------
TUint16 CMmSmsMessHandler::BuildSmsSbUserData(
    const TDesC8& aMsgData,
    TIsiSend& aIsiMsg,
    TUint8 aTpUdl,
    TUint8 aTpUserDataIndex,
    TBool aDefaultAlphabet,
    TUint aMsgOffset ) const
    {
TFLOGSTRING("TSY:CMmSmsMessHandler::BuildSmsSbUserData");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_BUILDSMSSBUSERDATA_TD, "CMmSmsMessHandler::BuildSmsSbUserData" );

    TUint8 dataLengthInOctets( 0 );

    // If data is 7-bit, then TP-UDL is integer representation of
    // the number of septets within the TP-UD field
    if ( aDefaultAlphabet )
        {
        dataLengthInOctets = ( ( aTpUdl + 1 ) * 7 ) / 8;
        }
    else
        {
        dataLengthInOctets = aTpUdl;
        }

    // Extract actual data bytes from TPDU
    TPtrC8 dataBytes( aMsgData.Mid( aTpUserDataIndex, dataLengthInOctets ) );

    // Create and fill SMS_SB_USER_DATA subblock
    TBuf8<SIZE_SMS_SB_USER_DATA + SMS_COMMAND_DATA_MAX_LEN> userDataBuf;
    TIsiSubBlock userData(
        userDataBuf,
        SMS_SB_USER_DATA,
        EIsiSubBlockTypeId16Len16 );
    userDataBuf.Append( KSmsPadding );
    userDataBuf.Append( dataLengthInOctets );
    userDataBuf.Append( KSmsPadding );
    userDataBuf.Append( aTpUdl );
    userDataBuf.Append( dataBytes );

    aIsiMsg.CopyData( aMsgOffset, userData.CompleteSubBlock() );

TFLOGSTRING2( "TSY:CMmSmsMessHandler::BuildSmsSbUserData. User data length in octets: %d", dataLengthInOctets );
TFLOGSTRING2( "TSY:CMmSmsMessHandler::BuildSmsSbUserData. User data character count: %d", aTpUdl );
OstTraceExt2( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_BUILDSMSSBUSERDATA_TD, "CMmSmsMessHandler::BuildSmsSbUserData;dataLengthInOctets=%hhu;aTpUdl=%hhu", dataLengthInOctets, aTpUdl );

    return userDataBuf.Length();
    }


// -----------------------------------------------------------------------------
// CMmSmsMessHandler::BuildSmsSbValidityPeriod
// Creates SMS_SB_VALIDITY_PERIOD subblock and appends it to ISI message
// -----------------------------------------------------------------------------
TUint16 CMmSmsMessHandler::BuildSmsSbValidityPeriod(
    const TDesC8& aMsgData,
    TIsiSend& aIsiMsg,
    TUint8 aTpVpIndex,
    TUint8 aTpVpLength,
    TUint aMsgOffset ) const
    {
TFLOGSTRING("TSY:CMmSmsMessHandler::BuildSmsSbValidityPeriod");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_BUILDSMSSBVALIDITYPERIOD_TD, "CMmSmsMessHandler::BuildSmsSbValidityPeriod" );

    // Extract validity period data bytes
    TPtrC8 tpVpData( aMsgData.Mid( aTpVpIndex, aTpVpLength ) );

    // Create and fill SMS_SB_VALIDITY_PERIOD subblock, max length is 12
    TBuf8<12> validityPeriodBuf;
    TIsiSubBlock validityPeriod(
        validityPeriodBuf,
        SMS_SB_VALIDITY_PERIOD,
        EIsiSubBlockTypeId16Len16 );
    validityPeriodBuf.Append( aTpVpLength );
    validityPeriodBuf.Append( tpVpData );

    aIsiMsg.CopyData( aMsgOffset, validityPeriod.CompleteSubBlock() );

TFLOGSTRING2( "TSY:CMmSmsMessHandler::BuildSmsSbValidityPeriod. Validity period length: %d", aTpVpLength );
OstTraceExt1( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_BUILDSMSSBVALIDITYPERIOD_TD, "CMmSmsMessHandler::BuildSmsSbValidityPeriod;aTpVpLength=%hhu", aTpVpLength );

#ifdef _DEBUG
for ( TInt i( 0 ); i < aTpVpLength; i++ )
    {
TFLOGSTRING3( "Validity period, byte[%d], 0x%x", i, tpVpData[i] );
OstTraceExt2( TRACE_NORMAL,  DUP3_CMMSMSMESSHANDLER_BUILDSMSSBVALIDITYPERIOD_TD, "CMmSmsMessHandler::BuildSmsSbValidityPeriod;i=%hhu;tpVpData[i]=%hhu", i, tpVpData[i] );
    }
#endif // _DEBUG

    return validityPeriodBuf.Length();
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::BuildSmsCheckInfo
// Creates SMS_SB_CHECK_INFO sub block with SMS_CHECK_DISABLE_FDN and appends it
// to ISI message.
// -----------------------------------------------------------------------------
TUint16 CMmSmsMessHandler::BuildSmsCheckInfo(
    TIsiSend& aIsiMsg,
    TUint aMsgOffset ) const
    {
TFLOGSTRING("TSY:CMmSmsMessHandler::BuildSmsCheckInfo");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_BUILDSMSCHECKINFO_TD, "CMmSmsMessHandler::BuildSmsCheckInfo" );

    // Create and fill SMS_SB_CHECK_INFO subblock.
    TBuf8<SIZE_SMS_SB_CHECK_INFO> checkInfoBuf;
    TIsiSubBlock checkInfo(
        checkInfoBuf,
        SMS_SB_CHECK_INFO,
        EIsiSubBlockTypeId16Len16 );
    checkInfoBuf.Append( SMS_CHECK_DISABLE_FDN );
    checkInfoBuf.Append( KSmsPadding );
    checkInfoBuf.Append( KSmsPadding );
    checkInfoBuf.Append( KSmsPadding );

    aIsiMsg.CopyData( aMsgOffset, checkInfo.CompleteSubBlock() );

    return checkInfoBuf.Length();
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::ProcessUiccMsg
// Handles data received from UICC server
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::ProcessUiccMsg(
    TInt aTraId,
    TInt aStatus,
    TUint8 /*aDetails*/,
    const TDesC8& aFileData )
    {
TFLOGSTRING3("TSY:CMmSmsMessHandler::ProcessUiccMsg, aTraId: %d, status: %d", aTraId, aStatus );
OstTrace1( TRACE_NORMAL,  CMMSMSMESSHANDLER_PROCESSUICCMSG_TD, "CMmSmsMessHandler::ProcessUiccMsg;aTraId=%d", aTraId );
OstTrace1( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_PROCESSUICCMSG_TD, "CMmSmsMessHandler::ProcessUiccMsg;aStatus=%d", aStatus );

    TInt ret( KErrNone );

    switch( aTraId )
        {
        case ETrIdReadSMS:
            {
            UiccReadSMSResp( aStatus, aFileData );
            break;
            }
        case ETrIdReadSMSForComplete:
            {
            UiccReadSMSRespForComplete( aStatus, aFileData );
            break;
            }
        case ETrIdWriteSMS:
            {
            UiccWriteSMSResp( aStatus );
            break;
            }
        case ETrIdReadSMSRecordCount:
            {
            GetNumOfEFSMSRecordsResp( aStatus, aFileData );
            break;
            }
        case ETrIdDeleteSMS:
            {
            UiccDeleteSMSResp( aStatus );
            break;
            }
        case ETrIdDeleteAllSMSs:
            {
            UiccDeleteAllSMSResp( aStatus );
            break;
            }
        case ETrIdUpdateSMSStatusReadSMS:
            {
            UiccUpdateSMSStatusReadSMSResp( aStatus, aFileData );
            break;
            }
        case ETrIdUpdateSMSStatusWriteSMS:
            {
            UiccUpdateSMSStatusWriteSMSResp( aStatus );
            break;
            }
        case ETrIdGetSmspEntries:
            {
            // If status is OK, save the entry and then try to read next record
            if ( UICC_STATUS_OK == aStatus )
                {
                // Store the entry to the list
                ret = UiccStoreSmspEntry( aFileData );
                }

            // If the first record was tried to read, but UICC server returned
            // error or data was invalid, error is completed to commontsy
            if ( 1 == iSmspRecordNumber &&
                ( UICC_STATUS_OK != aStatus || KErrNone != ret ) )
                {
                iMessageRouter->Complete(
                    EMobileSmsMessagingGetSmspListPhase1,
                    KErrNotFound );
                // Reset internal array
                iSmspListArray->ResetAndDestroy();
                }
            // At least one SMS entry was read and stored successfully
            else if( UICC_STATUS_OK != aStatus || KErrNone != ret )
                {
                CMmDataPackage package;
                package.PackData( iSmspListArray );
                iMessageRouter->Complete(
                    EMobileSmsMessagingGetSmspListPhase1,
                    &package,
                    KErrNone );
                // Reset internal array
                iSmspListArray->ResetAndDestroy();
                }
            break;
            }
        case ETrIdWriteSmspEntry:
            {
            TInt error( KErrNone );
            if ( UICC_STATUS_OK != aStatus )
                {
                error = KErrNotFound;
                }
            iMessageRouter->Complete( EMobileSmsMessagingStoreSmspList, error );
            break;
            }
        default:
            {
TFLOGSTRING("TSY:CMmSmsMessHandler::ProcessUiccMsg - unknown transaction ID" );
OstTrace0( TRACE_NORMAL,  DUP2_CMMSMSMESSHANDLER_PROCESSUICCMSG_TD, "CMmSmsMessHandler::ProcessUiccMsg - unknown transaction ID" );

            break;
            }
        }
    return ret;
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::UiccReadSMSOrSMSRecordCountReq
// Read SMS or SMS EF record count from SIM/USIM
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::UiccReadSMSOrSMSRecordCountReq(
    const TUint8 aRecordId,
    const TUiccTrId aTrId )
    {
TFLOGSTRING3("TSY: CMmSmsMessHandler::UiccReadSMSReq, aTraId: %d, aRecordId: %d", aTrId, aRecordId );
OstTraceExt2( TRACE_NORMAL,  CMMSMSMESSHANDLER_UICCREADSMSORSMSRECORDCOUNTREQ_TD, "CMmSmsMessHandler::UiccReadSMSOrSMSRecordCountReq;aTrId=%hhu;aRecordId=%hhu", aTrId, aRecordId );

    TUint8 serviceType( 0 );
    TInt ret( KErrNone );

    switch( aTrId )
        {
        case ETrIdReadSMS:
        case ETrIdReadSMSForComplete:
            {
            // Save record id for next request
            iRecordId = aRecordId;
            serviceType = UICC_APPL_READ_LINEAR_FIXED;
            break;
            }
        case ETrIdReadSMSRecordCount:
            {
            serviceType = UICC_APPL_FILE_INFO;
            break;
            }
        default:
            {
TFLOGSTRING("TSY: CMmSmsMessHandler::UiccReadSMSReq - unknown transaction ID" );
OstTrace0( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_UICCREADSMSORSMSRECORDCOUNTREQ_TD, "CMmSmsMessHandler::UiccReadSMSOrSMSRecordCountReq - unknown transaction ID" );
            ret = KErrUnknown;
            break;
            }
        }

    // Set parameters for UICC_APPL_CMD_REQ message
    TUiccReadLinearFixed params;
    params.messHandlerPtr = static_cast<MUiccOperationBase*>( this );
    params.trId = aTrId;
    params.dataOffset = 0;
    params.dataAmount = 0;
    params.record = aRecordId;

    params.fileId = KElemFileShortMessages;
    params.fileIdSfi = UICC_SFI_NOT_PRESENT;
    params.serviceType = serviceType;

    // File id path
    params.filePath.Append( KMasterFileId >> 8 );
    params.filePath.Append( KMasterFileId );
    params.filePath.Append( iMmUiccMessHandler->GetApplicationFileId() );

    if ( KErrNone == ret )
        {
        ret = iMmUiccMessHandler->CreateUiccApplCmdReq( params );
        }

    return ret;
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::UiccReadSMSResp
//
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::UiccReadSMSResp(
    TInt aStatus,
    const TDesC8& aFileData )
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::UiccReadSMSResp" );
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_UICCREADSMSRESP_TD, "CMmSmsMessHandler::UiccReadSMSResp" );

    if ( UICC_STATUS_OK == aStatus )
        {
TFLOGSTRING2("TSY: CMmSmsMessHandler::SimStSmsHandleReadCacheEntriesL -- cacheing iRecordId=%d", iRecordId );
OstTraceExt1( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_UICCREADSMSRESP_TD, "CMmSmsMessHandler::UiccReadSMSResp;iRecordId=%hhu", iRecordId );

        if ( 0 != aFileData.Length() )
            {
            // add to cache
            RMobileSmsStore::TMobileGsmSmsEntryV1 smsData;

            TUint8 position( 0 );
            smsData.iMsgStatus =
                static_cast <RMobileSmsStore::TMobileSmsStoreStatus>(
                    aFileData[position] );

            TBuf<KMaxAddressBufferSize> receivedMsgServiceCentre;
            RMobilePhone::TMobileTON receivedMsgMobileScTON(
                RMobilePhone::EUnknownNumber );
            RMobilePhone::TMobileNPI receivedMsgMobileScNPI(
                RMobilePhone::EUnknownNumberingPlan );

            position++;
            TUint8 addressDataLength( aFileData[position] );
            // Also length byte should be included to addressDataLength so it
            // is added by one
            addressDataLength++;
            TPtrC8 scA( aFileData.Mid( position, addressDataLength ) );
            CMmSmsGsmAddress::GsmConv0411AddrToUnicode(
                receivedMsgServiceCentre,
                scA,
                receivedMsgMobileScTON,
                receivedMsgMobileScNPI );

            smsData.iServiceCentre.iTypeOfNumber = receivedMsgMobileScTON;
            smsData.iServiceCentre.iNumberPlan = receivedMsgMobileScNPI;
            smsData.iServiceCentre.iTelNumber = receivedMsgServiceCentre;

            position += addressDataLength; // Start of the TPDU
            TUint8 totalLength( aFileData.Length() ); // Total aFileData length
            TUint8 tpduLength( totalLength - position );
            if ( RMobileSmsMessaging::KGsmTpduSize < tpduLength )
                {
                tpduLength = RMobileSmsMessaging::KGsmTpduSize;
                }
            smsData.iMsgData = aFileData.Mid( position, tpduLength  );
            iSmsCache.AddEntryL( &smsData, iRecordId );
            }

        // if the cache is not ready, try reading the next entry
        if ( iRecordId < iSmsCache.TotalEntries() )
            {
            iRecordId++; // Next record
            UiccReadSMSOrSMSRecordCountReq( iRecordId, ETrIdReadSMS );
            }
        // or else this is the last entry, mark cache as ready
        else
            {
            iSmsCache.SetStatus( KErrNone );
            }
        }
    else
        {
TFLOGSTRING("TSY: CMmSmsMessHandler::UiccReadSMSResp - abort caching");
OstTrace0( TRACE_NORMAL,  DUP2_CMMSMSMESSHANDLER_UICCREADSMSRESP_TD, "CMmSmsMessHandler::UiccReadSMSResp - abort caching" );
        // else SIM suddenly removed ==> abort caching
        // or example SIM rejected (EFSA-6ZQ9K3).

        // SMS is on SIM, but we couldn't read it. Cache must be
        // invalidated
        iSmsCache.Reset();
        // use KErrNoMemory as error condition, so that getinfo will try
        // to fill cache again
        iSmsCache.SetStatus( KErrNoMemory );
        }

    // either done or failed
    if ( KErrNotReady != iSmsCache.Status() )
        {
TFLOGSTRING2("TSY: CMmSmsMessHandler::UiccReadSMSResp - Success or Error value of SMS cache read = %d",iSmsCache.Status() );
OstTrace1( TRACE_NORMAL,  DUP3_CMMSMSMESSHANDLER_UICCREADSMSRESP_TD, "CMmSmsMessHandler::UiccReadSMSResp;iSmsCache.Status()=%d", iSmsCache.Status() );

TFLOGSTRING3("TSY: CMmSmsMessHandler::UiccReadSMSResp --- SMS CACHE READ DONE --- total=%d used=%d",iSmsCache.TotalEntries(), iSmsCache.UsedEntries() );
OstTrace1( TRACE_NORMAL,  DUP4_CMMSMSMESSHANDLER_UICCREADSMSRESP_TD, "CMmSmsMessHandler::UiccReadSMSResp;iSmsCache.TotalEntries()=%d", iSmsCache.TotalEntries() );

        // there is a chance that EMobileSmsMessagingGetMessageStoreInfo
        // request is already on if so, then complete it here... if there is
        // no request on, then this is harmless..
        TUint8 numOfLoc( TUint8( iSmsCache.TotalEntries() ) );
        TInt usedEntries( iSmsCache.UsedEntries() );

        //create package
        CMmDataPackage data;
        data.PackData( &numOfLoc, &usedEntries );
        iSmsSlotLocation = 0;

        iMessageRouter->Complete(
            EMobileSmsMessagingGetMessageStoreInfo,
            &data,
            iSmsCache.Status() );

        iMessageRouter->Complete(
            EMobilePhoneStoreGetInfo,
            &data,
            iSmsCache.Status() );

        // it is possible that re-caching was done due to sim refresh.
        iMessageRouter->GetPhoneMessHandler()->
            SmsCachingCompleted( iSmsCache.Status() );

        // if cache is up and a message was received while cacheing then resume
        if ( KErrNone == iSmsCache.Status() && iReceivedClass2ToBeReSent )
            {
TFLOGSTRING("TSY: CMmSmsMessHandler::UiccReadSMSResp -- resume SMS reception");
OstTrace0( TRACE_NORMAL,  DUP5_CMMSMSMESSHANDLER_UICCREADSMSRESP_TD, "CMmSmsMessHandler::UiccReadSMSResp -- resume SMS reception" );
            SmsReceiveMessageReq( SMS_RECEPTION_STORAGE_STATUS_UPDATE );
            iReceivedClass2ToBeReSent = EFalse;
            }
        }
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::UiccReadSMSRespForComplete
//
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::UiccReadSMSRespForComplete(
    TInt aStatus,
    const TDesC8& aFileData )
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::UiccReadSMSRespForComplete" );
//OstTraceExt2( TRACE_NORMAL,  CMMSMSMESSHANDLER_UICCREADSMSRESP_TD, "CMmSmsMessHandler::UiccReadSMSResp;aStatus=%d;aFileData=%s", aStatus,aFileData );


    if ( UICC_STATUS_OK == aStatus )
        {
TFLOGSTRING2("TSY: CMmSmsMessHandler::UiccReadSMSRespForComplete -- cacheing iRecordId=%d", iRecordId );
OstTraceExt1( TRACE_NORMAL,  CMMSMSMESSHANDLER_UICCREADSMSRESPFORCOMPLETE_TD, "CMmSmsMessHandler::UiccReadSMSRespForComplete;iRecordId=%hhu", iRecordId );

        if ( 0 != aFileData.Length() )
            {
            // add to cache
            RMobileSmsStore::TMobileGsmSmsEntryV1 smsData;

            TUint8 position( 0 );
            // Force status as message to be read
            smsData.iMsgStatus =
                static_cast <RMobileSmsStore::TMobileSmsStoreStatus>(
                    aFileData[position] );

            TBuf<KMaxAddressBufferSize> receivedMsgServiceCentre;
            RMobilePhone::TMobileTON receivedMsgMobileScTON(
                RMobilePhone::EUnknownNumber );
            RMobilePhone::TMobileNPI receivedMsgMobileScNPI(
                RMobilePhone::EUnknownNumberingPlan );

            position++;
            TUint8 addressDataLength( aFileData[position] );
            // Also length byte should be included to addressDataLength so it
            // is added by one
            addressDataLength++;

            TPtrC8 scA( aFileData.Mid( position, addressDataLength ) );
            CMmSmsGsmAddress::GsmConv0411AddrToUnicode(
                receivedMsgServiceCentre,
                scA,
                receivedMsgMobileScTON,
                receivedMsgMobileScNPI );

            smsData.iServiceCentre.iTypeOfNumber = receivedMsgMobileScTON;
            smsData.iServiceCentre.iNumberPlan = receivedMsgMobileScNPI;
            smsData.iServiceCentre.iTelNumber = receivedMsgServiceCentre;

            position += addressDataLength; // Start of the TPDU
            TUint8 totalLength( aFileData.Length() ); // Total aFileData length
            TUint8 tpduLength( totalLength - position );
            smsData.iMsgData = aFileData.Mid( position, tpduLength  );

            // This is done only when SMS written through ETel.
            if ( !iSMSClass2Write )
                {
                //create package
                CMmDataPackage data;
                data.PackData( &iSmsSlotLocation, &iReceivedClass2ToBeReSent );
                iSmsSlotLocation = 0;
                iMessageRouter->Complete(
                    EMobilePhoneStoreWrite,
                    &data,
                    KErrNone );

                iReceivedClass2ToBeReSent = EFalse;
                }
            else
                {
                // This is done only when received class 2 message has been handled.
                TSmsMsg smsMsg;
                smsMsg.iLocation = iSmsSlotLocation;
                smsMsg.iMessageStatus = smsData.iMsgStatus;
                smsMsg.iMobileScNPI = smsData.iServiceCentre.iNumberPlan;
                smsMsg.iMobileScTON = smsData.iServiceCentre.iTypeOfNumber;
                smsMsg.iServiceCentre = smsData.iServiceCentre.iTelNumber;
                smsMsg.iSmsClass2 = ETrue;
                smsMsg.iSmsMsg = smsData.iMsgData;

                iSmsSlotLocation = 0;

                //Complete request to client
                TBool smsInd( ETrue );
                TSmsMsg* smsMsgPtr = &smsMsg;

                //create package
                CMmDataPackage data;
                data.PackData( &smsInd, &smsMsgPtr );
                iMessageRouter->Complete(
                    EMobileSmsMessagingReceiveMessage,
                    &data,
                    KErrNone );
                }
            // At this point sms is safely in SIM and request is completed
            // Add to cache may fail, in which case we just invalidate
            // cache in out of memory handler

            iSmsCache.AddEntryL( &smsData, iRecordId );
            }

        }
    else
        {
        // This is done only when received class 2 message has been handled.
        if ( iSMSClass2Write )
            {
            TInt ret ( SmsReceivedMsgReportReq(
                ESmsMessagingAckSmsStored,
                NULL,
                KErrNone ) );

            if ( KErrNone != ret )
                {
                TBool smsInd( EFalse );
                TSmsMsg* nullSms = NULL;

                //create package
                CMmDataPackage data;
                //Complete request to client
                data.PackData( &smsInd, &nullSms );
                iSmsSlotLocation = 0;

                // ISI message construction failed or phonet sender
                // returned error
                iMessageRouter->Complete(
                    EMobileSmsMessagingReceiveMessage,
                    &data,
                    KErrGeneral );
                }
            }
        else
            {
            //create package
            CMmDataPackage data;
            data.PackData( &iSmsSlotLocation, &iReceivedClass2ToBeReSent );
            iSmsSlotLocation = 0;
            iMessageRouter->Complete(
                EMobilePhoneStoreWrite,
                &data,
                CMmStaticUtility::UICCCSCauseToEpocError( aStatus ) );
            }
        // SMS is on SIM, but we couldn't read it. Cache must be
        // invalidated
        iSmsCache.Reset();
        // use KErrNoMemory as error condition, so that getinfo will try
        // to fill cache again
        iSmsCache.SetStatus( KErrNoMemory );
        }

    iSMSClass2Write = EFalse;
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::UiccWriteSMSReq
// Write SMS to SIM
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::UiccWriteSMSReq(
    const RMobileSmsStore::TMobileGsmSmsEntryV1& aEntry,
    const TUint8 aRecordId
    )
    {
TFLOGSTRING2("TSY: CMmSmsMessHandler::UiccWriteSMSReq aRecordId: %d", aRecordId );
OstTraceExt1( TRACE_NORMAL,  CMMSMSMESSHANDLER_UICCWRITESMSREQ_TD, "CMmSmsMessHandler::UiccWriteSMSReq;aRecordId=%hhu", aRecordId );

    // Set parameters for UICC_APPL_CMD_REQ message
    TUiccWriteLinearFixed params;
    params.messHandlerPtr = static_cast<MUiccOperationBase*>( this );
    params.trId = ETrIdWriteSMS;
    params.dataOffset = 0;
    params.dataAmount = 0;
    params.record = aRecordId;

    params.fileId = KElemFileShortMessages;
    params.fileIdSfi = UICC_SFI_NOT_PRESENT;
    params.serviceType = UICC_APPL_UPDATE_LINEAR_FIXED;

    // File id path
    params.filePath.Append( KMasterFileId >> 8 );
    params.filePath.Append( KMasterFileId );
    params.filePath.Append( iMmUiccMessHandler->GetApplicationFileId() );

    // File data to be updated.
    TBuf8<KSmsElemetaryFileRecordLength> fileDataBuf;

    // Fill record. See ETSI TS 31 102 "4.2.25   EFSMS (Short messages)"

    TUint8 totalDataLength( 0 );
    fileDataBuf.Append( KSimSmsMtNotRead );
    totalDataLength++;

    //build Gsm 04.11 type of address structure
    TBuf8<KMaxAddressBufferSize>  scAddress;
    TPtrC16 telNumber( aEntry.iServiceCentre.iTelNumber );
    CMmSmsGsmAddress::GsmConvUnicodeTo0411Addr(
        aEntry.iServiceCentre.iTypeOfNumber,
        aEntry.iServiceCentre.iNumberPlan,
        scAddress,
        telNumber );

    fileDataBuf.Append( scAddress );

    // It is possible for a TS Service Centre Address of maximum permitted
    // length, e.g. containing more than 18 address digits, to be associated
    // with a maximum length TPDU such that their combined length is 176 bytes.
    // In this case the ME shall store in the USIM the TS Service Centre
    // Address and the TPDU in bytes 2 176 without modification, except for the
    // last byte of the TPDU, which shall not be stored.

    RMobileSmsMessaging::TMobileSmsGsmTpdu msgData( aEntry.iMsgData );

    totalDataLength += ( msgData.Length() + scAddress.Length() );

    TUint msgDataLen( msgData.Length() );
    TInt unfilledLength( fileDataBuf.MaxLength() - totalDataLength );

    if ( 0 >  unfilledLength )
        {
        msgDataLen--;
        }
    fileDataBuf.Append( msgData.Left( msgDataLen ) );

    // Fill unused fields with FF
    if ( 0 <  unfilledLength )
        {
        fileDataBuf.AppendFill( 0xFF, unfilledLength );
        }

    params.fileData.Append( fileDataBuf );

    return iMmUiccMessHandler->CreateUiccApplCmdReq( params );
    }


// -----------------------------------------------------------------------------
// CMmSmsMessHandler::UiccWriteSMSResp
//
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::UiccWriteSMSResp( TInt aStatus )
    {
TFLOGSTRING2("TSY: CMmSmsMessHandler::UiccWriteSMSResp aStatus: %d", aStatus );
OstTrace1( TRACE_NORMAL,  CMMSMSMESSHANDLER_UICCWRITESMSRESP_TD, "CMmSmsMessHandler::UiccWriteSMSResp;aStatus=%d", aStatus );

    // Create Package
    CMmDataPackage package;

    if ( iSMSClass2Write )
        {
        if ( UICC_STATUS_OK == aStatus )
            {
            // After writing class2 SMS to SIM card, it has
            // to be read in case SIM SW has changed the contents
            TInt ret( UiccReadSMSOrSMSRecordCountReq( iSmsSlotLocation, ETrIdReadSMSForComplete ) );
            if ( KErrNone != ret )
                {
                ret = SmsReceivedMsgReportReq( EInternalNack, NULL, KErrGsmSMSUnspecifiedProtocolError );
                if ( KErrNone != ret )
                    {
                    TBool smsInd( EFalse );
                    TSmsMsg* nullSms = NULL;
                    //Complete request to client
                    package.PackData( &smsInd, &nullSms );
                    iSmsSlotLocation = 0;

                    // ISI message construction failed or phonet sender
                    // returned error
                    iMessageRouter->Complete(
                        EMobileSmsMessagingReceiveMessage,
                        &package,
                        KErrGeneral );
                    }
                }
            }
        else
            {
            TInt ret( SmsReceivedMsgReportReq( EInternalNack, NULL, KErrGsmSMSUnspecifiedProtocolError ) );
            if ( KErrNone != ret )
                {
                // ISI message construction failed or phonet sender
                // returned error
                TBool smsInd( EFalse );
                TSmsMsg* nullSms = NULL;

                //Pack data
                package.PackData( &smsInd, &nullSms );
                iSmsSlotLocation = 0;

                // ISI message construction failed or phonet sender
                // returned error
                iMessageRouter->Complete(
                    EMobileSmsMessagingReceiveMessage,
                    &package,
                    KErrGeneral );
                }
            }
        }
    else
        {
        if ( UICC_STATUS_OK == aStatus )
            {
            // After writing class2 SMS to SIM card, it has
            // to be read in case SIM SW has changed the contents
            TInt ret( UiccReadSMSOrSMSRecordCountReq( iSmsSlotLocation, ETrIdReadSMSForComplete ) );
            if ( KErrNone != ret )
                {
                package.PackData(
                    &iSmsSlotLocation,
                    &iReceivedClass2ToBeReSent );
                iSmsSlotLocation = 0;
                iMessageRouter->Complete(
                    EMobilePhoneStoreWrite,
                    &package,
                    ret );
                iReceivedClass2ToBeReSent = EFalse;
                }
            }
        else
            {
            package.PackData( &iSmsSlotLocation, &iReceivedClass2ToBeReSent );
            iSmsSlotLocation = 0;
            iMessageRouter->Complete(
                EMobilePhoneStoreWrite,
                &package,
            KErrGeneral );
            iReceivedClass2ToBeReSent = EFalse;
            }
        }
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::GetNumOfEFSMSRecords
//
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::GetNumOfEFSMSRecords( void )
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::GetNumOfEFSMSRecords" );
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_GETNUMOFEFSMSRECORDS_TD, "CMmSmsMessHandler::GetNumOfEFSMSRecords" );

    TUint8 recordID( 0 );
    TUiccTrId trId( ETrIdReadSMSRecordCount );

    CMmSmsMessHandler::UiccReadSMSOrSMSRecordCountReq ( recordID,
                                                        trId  );
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::GetNumOfEFSMSRecordsResp
//
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::GetNumOfEFSMSRecordsResp(
    TInt aStatus,
    const TDesC8& aFileData )
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::GetNumOfEFSMSRecordsResp" );
OstTraceExt2( TRACE_NORMAL,  CMMSMSMESSHANDLER_GETNUMOFEFSMSRECORDSRESP_TD, "CMmSmsMessHandler::GetNumOfEFSMSRecordsResp;aStatus=%d;aFileData=%s", aStatus, aFileData );

    //Save number of SMS locations on SIM card
    TInt smsNumOfLoc( 0 );

    if ( UICC_STATUS_OK == aStatus )
        {
        TFci fci( aFileData );
        smsNumOfLoc = fci.GetNumberOfRecords();
        }

    // Continue with reading all sms entries from sim
    if ( smsNumOfLoc > 0 )
        {
        // got the total number or SIM SMS entries
        iSmsCache.SetTotalEntriesL( smsNumOfLoc );
TFLOGSTRING2("TSY: CMmSmsMessHandler::SimStSmsGetNumOfLocRespL -- total number of locations on sim %d", iSmsCache.TotalEntries() );
OstTrace1( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_GETNUMOFEFSMSRECORDSRESP_TD, "CMmSmsMessHandler::GetNumOfEFSMSRecordsResp;iSmsCache.TotalEntries()=%d", iSmsCache.TotalEntries() );

        // now start reading entries one by one starting from record 1
        UiccReadSMSOrSMSRecordCountReq( 1, ETrIdReadSMS );
        }
    else
        {
        // There is a chance that getinfo requests are already ongoing
        // if so, then complete them here.
        TUint8 numOfLoc( 0 );
        TInt usedEntries( -1 ); // unable to determine.
        CMmDataPackage data;
        data.PackData( &numOfLoc, &usedEntries );
        iMessageRouter->Complete(
            EMobileSmsMessagingGetMessageStoreInfo,
            &data,
            CMmStaticUtility::UICCCSCauseToEpocError( aStatus )  );

        iMessageRouter->Complete(
            EMobilePhoneStoreGetInfo,
            &data,
            KErrNoMemory );
        }
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::UiccDeleteSMSResp
//
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::UiccDeleteSMSResp( TInt aStatus )
    {
TFLOGSTRING2("TSY: CMmSmsMessHandler::UiccDeleteSMSResp aStatus: %d", aStatus );
OstTrace1( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_UICCDELETESMSRESP_TD, "CMmSmsMessHandler::UiccDeleteSMSResp;aStatus=%d", aStatus );

    // Create Package
    CMmDataPackage package;

    TInt error( CMmStaticUtility::UICCCSCauseToEpocError( aStatus ) );

    if ( KErrNone == error )
        {
        iSmsCache.Delete();
        }
    iMessageRouter->Complete( EMobilePhoneStoreDelete, error );

    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::UiccDeleteAllSMSResp
//
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::UiccDeleteAllSMSResp( TInt aStatus )
    {
TFLOGSTRING2("TSY: CMmSmsMessHandler::UiccDeleteSMSResp aStatus: %d", aStatus );
OstTrace1( TRACE_NORMAL,  CMMSMSMESSHANDLER_UICCDELETEALLSMSRESP_TD, "CMmSmsMessHandler::UiccDeleteAllSMSResp;aStatus=%d", aStatus );

    // Create Package
    CMmDataPackage package;

    TInt error( CMmStaticUtility::UICCCSCauseToEpocError( aStatus ) );

    // Delete SMS from SIM one by one and then all from cache.
    if ( ( iRecordId < iSmsCache.TotalEntries() ) &&
         ( KErrNone == error ) )
        {
        iRecordId++; // Next record
        error = DeleteAllSms();

        if ( KErrNone != error )
            {
            iMessageRouter->Complete( EMobilePhoneStoreDeleteAll, error );
            }
        }
    else
        {
        iSmsCache.DeleteAll();
        iMessageRouter->Complete( EMobilePhoneStoreDeleteAll, error );
        }

    }
// -----------------------------------------------------------------------------
// CMmSmsMessHandler::CheckSCTimestamp
// Returns ETrue if the SC timestamp in this message is equal to
// the client's timestamp in aScTime.
// -----------------------------------------------------------------------------
//
TBool CMmSmsMessHandler::CheckSCTimestamp(
    const RMobileSmsStore::TMobileGsmSmsEntryV1& aEntry,
    const TTime& aScTime )
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::CheckSCTimestamp");
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_CHECKSCTIMESTAMP_TD, "CMmSmsMessHandler::CheckSCTimestamp" );
    TBool matchFound( EFalse );

    TInt offset( 1 ); // Message Reference position
    TInt messageReference( aEntry.iMsgData[offset] );
    // Destination address length is integer representation
    // of the number of useful semi-octets of address field
    messageReference = ( messageReference + 1 ) / 2;
    offset += messageReference;
    offset += 4; // Service Centre Time Stamp

    TBuf8<KSmsScTimeStampMaxLength> scTimeStamp;
    scTimeStamp = aEntry.iMsgData.Mid( offset, KSmsScTimeStampMaxLength );

    // Convert from the semi-octet representation to decimals.
    for ( TUint8 i ( 0 ); i < KSmsScTimeStampMaxLength; i++ )
        {
        TUint8 lowDigit( static_cast<TUint8>( (
            scTimeStamp[i] & 0xf0 ) >> 4 ) );
        TUint8 highDigit( static_cast<TUint8>( scTimeStamp[i] & 0xf ) );
        scTimeStamp[i] = static_cast<TUint8>( (10 * highDigit) + lowDigit );
        }

    // Ignore this messsage if month or day are zero (should not happen)
    if ( ( 0 == scTimeStamp[1] ) || ( 0 == scTimeStamp[2] ) )
        {
TFLOGSTRING("TSY:CMmSmsMessHandler::CheckSCTimestamp:Invalid timestamp found, ignored.");
OstTrace0( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_CHECKSCTIMESTAMP_TD, "CMmSmsMessHandler::CheckSCTimestamp, Invalid timestamp found, ignored" );
        matchFound = ETrue;
        }

    if ( !matchFound )
        {
        // Construct a string of the form YYYYMMDD:HHMMSS
        TBuf<15> timeString;
        // This is the same way Symbian GSMU does it,
        // see GSMU's method TSmsServiceCenterTimeStamp::DecodeL.
        if ( scTimeStamp[0]>95 )
            {
            timeString.Append( _L( "19" ) );
            }
        else
            {
            timeString.Append( _L( "20" ) );
            }
        //two digits for year, month, day, hour, minute, second
        _LIT( KDateFormat, "%02d" );
        //year
        timeString.AppendFormat( KDateFormat,scTimeStamp[0] );
        //month, starting at 0
        timeString.AppendFormat( KDateFormat,scTimeStamp[1]-1 );
        //day, starting at 0
        timeString.AppendFormat( KDateFormat,scTimeStamp[2]-1 );
        timeString.Append( _L(":" ) );
        //hour
        timeString.AppendFormat( KDateFormat,scTimeStamp[3] );
        //minute
        timeString.AppendFormat( KDateFormat,scTimeStamp[4] );
        //second
        timeString.AppendFormat( KDateFormat,scTimeStamp[5] );

        TTime simStoredTime( 0 );
        TInt err( simStoredTime.Set( timeString ) );

        if ( KErrNone == err )
            {
            // Handle the timezone difference. The timezone is found in the
            // last byte of the SC timestamp buffer.
            TUint8 simTimezoneDiffRaw( scTimeStamp[6] );
            // Highest bit is the algebraic sign (0=positive, 1=negative).
            // Timezone is defined in 'quarters of an hour', but we allow
            // only whole numbers.
            TInt8 simTimezoneSign( ( simTimezoneDiffRaw & 0x80 ) ? -1 : 1 );
            TInt8 simTimezoneDiff( static_cast<TInt8>(
                simTimezoneSign * ( simTimezoneDiffRaw & 0x7F) / 4 ) );
            // Substract timezone difference
            TTimeIntervalHours simTimezoneInterval( simTimezoneDiff );
            simStoredTime -= simTimezoneInterval;

#ifdef _DEBUG
            // debug print
            TDateTime dt = simStoredTime.DateTime();
TFLOGSTRING("TSY:CMmSmsMessHandler::CheckSCTimestamp:Message stored on SIM:");
OstTrace0( TRACE_NORMAL,  DUP2_CMMSMSMESSHANDLER_CHECKSCTIMESTAMP_TD, "CMmSmsMessHandler::CheckSCTimestamp, Message stored on SIM:" );
TFLOGSTRING2("    year=%d",dt.Year());
OstTrace1( TRACE_NORMAL,  DUP3_CMMSMSMESSHANDLER_CHECKSCTIMESTAMP_TD, "CMmSmsMessHandler::CheckSCTimestamp;Year=%d", dt.Year() );
TFLOGSTRING2("    month=%d",dt.Month()+1);
OstTrace1( TRACE_NORMAL,  DUP4_CMMSMSMESSHANDLER_CHECKSCTIMESTAMP_TD, "CMmSmsMessHandler::CheckSCTimestamp;Month=%d", ( dt.Month() + 1 ) );
TFLOGSTRING2("    day=%d",dt.Day()+1);
OstTrace1( TRACE_NORMAL,  DUP5_CMMSMSMESSHANDLER_CHECKSCTIMESTAMP_TD, "CMmSmsMessHandler::CheckSCTimestamp;Day=%d", ( dt.Day() + 1 ) );
TFLOGSTRING2("    hour=%d",dt.Hour());
OstTrace1( TRACE_NORMAL,  DUP6_CMMSMSMESSHANDLER_CHECKSCTIMESTAMP_TD, "CMmSmsMessHandler::CheckSCTimestamp;Hour=%d", dt.Hour() );
TFLOGSTRING2("    minute=%d",dt.Minute());
OstTrace1( TRACE_NORMAL,  DUP7_CMMSMSMESSHANDLER_CHECKSCTIMESTAMP_TD, "CMmSmsMessHandler::CheckSCTimestamp;Minute=%d", dt.Minute() );
TFLOGSTRING2("    second=%d",dt.Second());
OstTrace1( TRACE_NORMAL,  DUP8_CMMSMSMESSHANDLER_CHECKSCTIMESTAMP_TD, "CMmSmsMessHandler::CheckSCTimestamp;Second=%d", dt.Second() );
TFLOGSTRING2("    timezone difference=%d",simTimezoneDiff);
OstTraceExt1( TRACE_NORMAL,  DUP9_CMMSMSMESSHANDLER_CHECKSCTIMESTAMP_TD, "CMmSmsMessHandler::CheckSCTimestamp;simTimezoneDiff=%hhd", simTimezoneDiff );
            dt = aScTime.DateTime();
TFLOGSTRING("TSY:CMmSmsMessHandler::CheckSCTimestamp:Message opened on client side:");
OstTrace0( TRACE_NORMAL,  DUP10_CMMSMSMESSHANDLER_CHECKSCTIMESTAMP_TD, "CMmSmsMessHandler::CheckSCTimestamp, Message opened on client side:" );
TFLOGSTRING2("    year=%d",dt.Year());
OstTrace1( TRACE_NORMAL,  DUP11_CMMSMSMESSHANDLER_CHECKSCTIMESTAMP_TD, "CMmSmsMessHandler::CheckSCTimestamp;Year=%d", ( dt.Year() + 1 ) );
TFLOGSTRING2("    month=%d",dt.Month()+1);
OstTrace1( TRACE_NORMAL,  DUP12_CMMSMSMESSHANDLER_CHECKSCTIMESTAMP_TD, "CMmSmsMessHandler::CheckSCTimestamp;Month=%d", ( dt.Month() + 1 ) );
TFLOGSTRING2("    day=%d",dt.Day()+1);
OstTrace1( TRACE_NORMAL,  DUP13_CMMSMSMESSHANDLER_CHECKSCTIMESTAMP_TD, "CMmSmsMessHandler::CheckSCTimestamp;Day=%d", ( dt.Day() + 1 ) );
TFLOGSTRING2("    hour=%d",dt.Hour());
OstTrace1( TRACE_NORMAL,  DUP14_CMMSMSMESSHANDLER_CHECKSCTIMESTAMP_TD, "CMmSmsMessHandler::CheckSCTimestamp;Hour=%d", dt.Hour() );
TFLOGSTRING2("    minute=%d",dt.Minute());
OstTrace1( TRACE_NORMAL,  DUP15_CMMSMSMESSHANDLER_CHECKSCTIMESTAMP_TD, "CMmSmsMessHandler::CheckSCTimestamp;Minute=%d", dt.Minute() );
TFLOGSTRING2("    second=%d",dt.Second());
OstTrace1( TRACE_NORMAL,  DUP16_CMMSMSMESSHANDLER_CHECKSCTIMESTAMP_TD, "CMmSmsMessHandler::CheckSCTimestamp;Second=%d", dt.Second() );
            // debug print
#endif // _DEBUG

            if ( simStoredTime == aScTime )
                {
                matchFound = ETrue;
                }
            }
        }

    return matchFound;

    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::UiccUpdateSMSStatus
// Write SMS to SIM
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::UiccUpdateSMSStatus(
    const TUint8 aRecordId
    )
    {
TFLOGSTRING2("TSY: CMmSmsMessHandler::UiccUpdateSMSStatusReq aRecordId: %d", aRecordId );
OstTraceExt1( TRACE_NORMAL,  CMMSMSMESSHANDLER_UICCUPDATESMSSTATUS_TD, "CMmSmsMessHandler::UiccUpdateSMSStatus;aRecordId=%hhu", aRecordId );

    // Read parameters from SIM
    // Set parameters for UICC_APPL_CMD_REQ message
    iRecordId = aRecordId;
    TUiccReadLinearFixed params;
    params.messHandlerPtr = static_cast<MUiccOperationBase*>( this );
    params.trId = ETrIdUpdateSMSStatusReadSMS;
    params.dataOffset = 0;
    params.dataAmount = 0;
    params.record = aRecordId;

    params.fileId = KElemFileShortMessages;
    params.fileIdSfi = UICC_SFI_NOT_PRESENT;
    params.serviceType = UICC_APPL_READ_LINEAR_FIXED;

    // File id path
    params.filePath.Append( KMasterFileId >> 8 );
    params.filePath.Append( KMasterFileId );
    params.filePath.Append( iMmUiccMessHandler->GetApplicationFileId() );

    return iMmUiccMessHandler->CreateUiccApplCmdReq( params );

    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::UiccUpdateSMSStatusReadSMSResp
//
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::UiccUpdateSMSStatusReadSMSResp(
    TInt aStatus,
    const TDesC8& aFileData )
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::UiccReadSMSResp" );
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_UICCUPDATESMSSTATUSREADSMSRESP_TD, "CMmSmsMessHandler::UiccUpdateSMSStatusReadSMSResp" );

    if ( UICC_STATUS_OK == aStatus )
        {
        if ( 0 != aFileData.Length() )
            {
           // Set parameters for UICC_APPL_CMD_REQ message
            TUiccWriteLinearFixed params;
            params.messHandlerPtr = static_cast<MUiccOperationBase*>( this );
            params.trId = ETrIdUpdateSMSStatusWriteSMS;
            params.dataOffset = 0;
            params.dataAmount = 0;
            params.record = iRecordId;

            params.fileId = KElemFileShortMessages;
            params.fileIdSfi = UICC_SFI_NOT_PRESENT;
            params.serviceType = UICC_APPL_UPDATE_LINEAR_FIXED;

            // File id path
            params.filePath.Append( KMasterFileId >> 8 );
            params.filePath.Append( KMasterFileId );
            params.filePath.Append( iMmUiccMessHandler->GetApplicationFileId() );

            // Update status as read
            // File data to be updated.
            TBuf8<KSmsElemetaryFileRecordLength> fileDataBuf;
            fileDataBuf = aFileData.Left( aFileData.Length() );
            fileDataBuf[0] = KSimSmsMtRead;

            TInt unfilledLength( fileDataBuf.MaxLength() - aFileData.Length() );
            // Fill unused fields with FF
            if ( 0 <  unfilledLength )
                {
                fileDataBuf.AppendFill( 0xFF, unfilledLength );
                }

            params.fileData.Append( fileDataBuf );

            TInt ret( iMmUiccMessHandler->CreateUiccApplCmdReq( params ) );

            if ( KErrNone != ret )
                {
                iMessageRouter->Complete(
                    ECustomSetSimMessageStatusReadIPC,
                    ret );
                }
            }
        }
    else
        {
        iMessageRouter->Complete(
            ECustomSetSimMessageStatusReadIPC,
            CMmStaticUtility::UICCCSCauseToEpocError( aStatus )  );
        }
    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::UiccUpdateSMSStatusWriteSMSResp
//
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::UiccUpdateSMSStatusWriteSMSResp( TInt aStatus )
    {
TFLOGSTRING2("TSY: CMmSmsMessHandler::UiccUpdateSMSStatusReadSMSResp aStatus: %d", aStatus );
OstTrace1( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_UICCUPDATESMSSTATUSREADSMSRESP_TD, "CMmSmsMessHandler::UiccUpdateSMSStatusReadSMSResp;aStatus=%d", aStatus );

    iMessageRouter->Complete(
        ECustomSetSimMessageStatusReadIPC,
        CMmStaticUtility::UICCCSCauseToEpocError( aStatus )  );

    // Update the same flag also in TSY's cache.
    if ( UICC_STATUS_OK == aStatus )
        {
        iSmsCache.SetStorageStatus( iRecordId, RMobileSmsStore::EStoredMessageRead );
        }

    }

// -----------------------------------------------------------------------------
// CMmSmsMessHandler::UiccGetSmspEntryReq
//
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::UiccGetSmspEntryReq()
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::UiccGetSmspEntryReq" );
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_UICCREADNUMOFSMSPENTRIES_TD, "CMmSmsMessHandler::UiccGetSmspEntryReq" );

    // Set parameters for UICC_APPL_CMD_REQ message
    TUiccReadLinearFixed params;
    params.messHandlerPtr = static_cast<MUiccOperationBase*>( this );
    params.trId = ETrIdGetSmspEntries;
    params.dataOffset = 0;
    params.dataAmount = 0;
    params.record = iSmspRecordNumber;
    params.fileId = KElemFileSmsParams;
    params.fileIdSfi = UICC_SFI_NOT_PRESENT;
    params.serviceType = UICC_APPL_READ_LINEAR_FIXED;

    // File id path
    params.filePath.Append( KMasterFileId >> 8 );
    params.filePath.Append( KMasterFileId );
    params.filePath.Append( iMmUiccMessHandler->GetApplicationFileId() );

    return iMmUiccMessHandler->CreateUiccApplCmdReq( params );
    }


// -----------------------------------------------------------------------------
// CMmSmsMessHandler::UiccStoreSmspEntry
//
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::UiccStoreSmspEntry( const TDesC8& aFileData )
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::UiccStoreSmspEntry" );
OstTrace0( TRACE_NORMAL,  CMMSMSMESSHANDLER_UICCSTORESMSPENTRY_TD, "CMmSmsMessHandler::UiccStoreSmspEntry" );

    TInt ret( KErrNone );
    TInt dataLength( aFileData.Length() );
    TPtrC8 data( KNullDesC8 );
    TSmsParameters* smsParam = new ( ELeave ) TSmsParameters();
    CleanupStack::PushL( smsParam );

    // SMS parameters are located in EF smsp, see 3GPP TS 31.102
    // V8.3.0 chapter 4.2.27 EFSMSP (Short message service parameters)

    // Alpha identifier is optional. Check if it exists.
    if ( KSmsMandatoryParamsLength < dataLength )
        {
        // Copy mandatory fields to different buffer for later use
        data.Set( aFileData.Right( KSmsMandatoryParamsLength ) );
        smsParam->iAlphaTagPresent = ETrue;

        // Alpha identifier length
        TInt alphaLength( dataLength - KSmsMandatoryParamsLength );
        if ( RMobileSmsMessaging::KMaxSmspTextSize < alphaLength )
            {
            alphaLength = RMobileSmsMessaging::KMaxSmspTextSize;
            }

        // Copy alpha identifier data as it is in SIM elementary file
        TBuf8<RMobileSmsMessaging::KMaxSmspTextSize> alphaIdentifier;
        alphaIdentifier.Copy( aFileData.Left( alphaLength ) );

        // Coding of alpha identifier may be 7-bit default of one of UCS2 code
        // options. At first convert data to 16-bit format
        TBuf8<RMobileSmsMessaging::KMaxSmspTextSize> alphaIdentifierOutput;
        CMmStaticUtility::ConvertGsmDataToUcs2(
            alphaIdentifier,
            alphaIdentifier.Length(),
            alphaIdentifierOutput );

        // Convert to 16-bit UNICODE string and copy to SMS parameters buffer
        TBuf16<RMobileSmsMessaging::KMaxSmspTextSize> alphaBuf;
        TIsiUtility::CopyFromBigEndian( alphaIdentifierOutput, alphaBuf );
        smsParam->iAlphaTagData.Copy( alphaBuf );
        }
    // Only mandatory 28 bytes are included, no alpha identifier
    else if ( KSmsMandatoryParamsLength == dataLength )
        {
        smsParam->iAlphaTagPresent = EFalse;
        // Copy all the data
        data.Set( aFileData );
        }
    else
        {
        ret = KErrNotFound;
        }

    if ( KErrNone == ret )
        {
        // Parameters indicator.
        // In SIM card bit value "0" means that parameter is present,
        // in S60 vice versa
        TUint8 paramIndicators( data[0] );
        paramIndicators = ~paramIndicators;
        paramIndicators &= KSmsGsmParametersIndMask; // Mask 5 LSB
        smsParam->iParameterIndicator = paramIndicators;

        // Location where SMS parameters in EFsms were fetched
        smsParam->iLocationNumber = iSmspRecordNumber;

        // Service center address
        if ( paramIndicators & KServiceCentreAddress )
            {
            TBuf8<KSmsMaxAddressLength>scAddress( data. Mid(
                KSmsParamsScAddressOffset, KSmsMaxAddressLength ) );
            CMmSmsGsmAddress::GsmConv0411AddrToUnicode(
                smsParam->iServiceCenterAddress,
                scAddress,
                smsParam->iMobileScTON,
                smsParam->iMobileScNPI );
            }

        // Destination address
        if ( paramIndicators & KDestinationAddress )
            {
            TBuf8<KSmsMaxAddressLength>destAddress( data.Mid(
                KSmsParamsDestAddressOffset, KSmsMaxAddressLength ) );
            CMmSmsGsmAddress::GsmConv0340AddrToUnicode(
                 smsParam->iDestinationAddress,
                 destAddress,
                 smsParam->iMobileDeTON,
                 smsParam->iMobileDeNPI );
            }

        // Protocol ID
        if ( paramIndicators & KProtocolID )
            {
            smsParam->iProtocolId = data[KSmsParamsProtocolIdOffset];
            }

        // Data coding scheme
        if ( paramIndicators & KDataCodingScheme )
            {
            smsParam->iDataCodingScheme = data[KSmsParamsDcsOffset];
            }

        // Validity period
        if ( paramIndicators & KValidityPeriod )
            {
            smsParam->iValidityPeriod = data[KSmsParamsValidityPeriodOffset];
            }

        // Add this parameter set to array
        iSmspListArray->AppendL( smsParam );
        // Read the next entry
        iSmspRecordNumber++;
        ret = UiccGetSmspEntryReq();
        }
    // Don't reset struct because it may be stored to CArrayPtrFlat.
    // All structs will be reseted when request is completed.
    CleanupStack::Pop( smsParam );
    return ret;
    }


// -----------------------------------------------------------------------------
// CMmSmsMessHandler::UiccSmsUpdateParameterReq
// -----------------------------------------------------------------------------
//
TInt CMmSmsMessHandler::UiccSmsUpdateParameterReq(
    const CMmDataPackage* aDataPackage )
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::UiccSmsUpdateParameterReq");
OstTrace0( TRACE_NORMAL,  DUP1_CMMSMSMESSHANDLER_UICCSTORESMSPENTRY_TD, "CMmSmsMessHandler::UiccStoreSmspEntry" );

    RMobileSmsMessaging::TMobileSmspEntryV1* smsParameters;
    // Unpack data
    aDataPackage->UnPackData( &smsParameters );

    // Buffer for all the file data to be written to UICC
    // (possible alpha tag + params )
    TBuf8<KSmsMandatoryParamsLength + KSizeOfAlphaTag> smspBuffer;

    // Check if there is alpha tag
    TInt alphaTagLength( smsParameters->iText.Length() );
    // Buffer for alpha tag
    if ( 0 < alphaTagLength )
        {
        // Temporary buffer for alpha tag
        TBuf8<KSizeOfAlphaTag> alphaTagData;
        TIsiUtility::CopyToBigEndian( smsParameters->iText, alphaTagData );
        smspBuffer.Append( 0x80 ); // First byte 0x80 means 16-bit UCS coding
        smspBuffer.Append( alphaTagData );
        }

    // Temporary buffer for mandatory data, filled by FF (unused bytes)
    TBuf8<KSmsMandatoryParamsLength> paramsData;
    paramsData.Fill( 0xFF, KSmsMandatoryParamsLength );

    // Fill SMS parameters to data buffer ( see 3GPP TS 31.102 V8.3.0
    // 4.2.27  EFSMSP (Short message service parameters). Unused parameters
    // are filled by 0xFF

    // Parameter indicator
    TUint8 paramInd( static_cast<TUint8>( smsParameters->iValidParams ) );
    paramsData[KSmsParamsParamIndicatorOffset] = paramInd;

    // Destination address
    if ( KDestinationAddress & paramInd )
        {
        TBuf8<KSmsMaxAddressLength> deAddr;
        // Fill address by 0x00 at first
        BuildDeAddress( smsParameters->iDestination, deAddr );
        // Add address data to buffer
        paramsData.Replace(
            KSmsParamsDestAddressOffset,
            deAddr.Length(),
            deAddr );
        }

    // Service center address
    if ( KServiceCentreAddress & paramInd )
        {
        TBuf8<KSmsMaxAddressLength> scAddr;
        // Fill address by 0x00 at first
        BuildScAddress( smsParameters->iServiceCentre, scAddr );
        // Add address data to buffer
        paramsData.Replace(
            KSmsParamsScAddressOffset,
            scAddr.Length(),
            scAddr );
        }

    // Protocol ID
    if ( KProtocolID & paramInd )
        {
        paramsData[KSmsParamsProtocolIdOffset] = smsParameters->iProtocolId;
        }

    // Data coding scheme
    if ( KDataCodingScheme & paramInd )
        {
        paramsData[KSmsParamsDcsOffset] = smsParameters->iDcs;
        }

    // If validity period is valid, set value
    if ( KValidityPeriod & paramInd )
        {
        paramsData[KSmsParamsValidityPeriodOffset] =
            smsParameters->iValidityPeriod;
        }

    smspBuffer.Append( paramsData );

    // Set parameters for UICC_APPL_CMD_REQ message
    TUiccWriteLinearFixed params;
    params.messHandlerPtr = static_cast<MUiccOperationBase*>( this );
    params.trId = ETrIdWriteSmspEntry;
    params.dataOffset = 0;
    params.dataAmount = 0;
    params.record = smsParameters->iIndex;

    params.fileId = KElemFileSmsParams;
    params.fileIdSfi = UICC_SFI_NOT_PRESENT;
    params.serviceType = UICC_APPL_UPDATE_LINEAR_FIXED;

    // File id path
    params.filePath.Append( KMasterFileId >> 8 );
    params.filePath.Append( KMasterFileId );
    params.filePath.Append( iMmUiccMessHandler->GetApplicationFileId() );

    // File data
    params.fileData.Append( smspBuffer );

    return iMmUiccMessHandler->CreateUiccApplCmdReq( params );
    }


// -----------------------------------------------------------------------------
// CMmSmsMessHandler::SmsResourceConfInd
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::SmsResourceConfInd( const TIsiReceiveC& aIsiMsg )
    {
TFLOGSTRING( "TSY: CMmSmsMessHandler::SmsResourceConfInd" );
OstTrace0( TRACE_NORMAL, CMMSMSMESSHANDLER_SMSRESOURCECONFIND_TD, "CMmSmsMessHandler::SmsResourceConfInd" );

    // To check The receive indication is for startup or reconfiguration
    if ( SMS_RES_CONF_STARTUP == aIsiMsg.Get8bit(
        ISI_HEADER_SIZE + SMS_RESOURCE_CONF_IND_OFFSET_CONFSTATUS ) )
        {
        TUint sbStartOffset( 0 );
        // Check if resource control is requested for MO SM.
        if ( KErrNone == aIsiMsg.FindSubBlockOffsetById(
            ISI_HEADER_SIZE + SIZE_SMS_RESOURCE_CONF_IND,
            SMS_SB_RESOURCE_CONF_REQUIRED,
            EIsiSubBlockTypeId16Len16,
            sbStartOffset ) )
            {
            TUint16 resource( aIsiMsg.Get16bit( 
                sbStartOffset + SMS_SB_RESOURCE_CONF_REQUIRED_OFFSET_RESPP ) );
            // Check MO SMS control is supported by SIM service table
            if ( SMS_RES_ID_CONF_MO_SM_INIT == resource &&
                 NULL == iPhonetReceiver->SatMessHandler() )
                {
                SmsResourceConfReq();
                }
            }
        }
    }


// -----------------------------------------------------------------------------
// CMmSmsMessHandler::SmsResourceConfReq
// -----------------------------------------------------------------------------
//
void CMmSmsMessHandler::SmsResourceConfReq()
    {
TFLOGSTRING("TSY: CMmSmsMessHandler::SmsResourceConfReq");
OstTrace0( TRACE_NORMAL, CMMSMSMESSHANDLER_SMSRESOURCECONFREQ_TD, "CMmSmsMessHandler::SmsResourceConfReq" );

    TBuf8<SIZE_SMS_SB_RESOURCE_CONF> data;
    TIsiSubBlock ResourceConfReqSb(
        data,
        SMS_SB_RESOURCE_CONF,
        EIsiSubBlockTypeId16Len16 );

    // set SMS_RESOURCE_IDS to SMS_RES_ID_MO_SM_INIT_DISABLE
    data.Append( KSmsResIdMoSmInitDisable >> KShift8 );
    data.Append( KSmsResIdMoSmInitDisable );

    // set SMS_RESOURCE_IDS_MASK to SMS_RES_ID_MASK_MO_SM_INIT
    data.Append( SMS_RES_ID_MASK_MO_SM_INIT >> KShift8 );
    data.Append( SMS_RES_ID_MASK_MO_SM_INIT );

    // Create SMS_RESOURCE_CONF_REQ message
    TIsiSend isiMsg( iPhoNetSender->SendBufferDes() );
    isiMsg.Set8bit( ISI_HEADER_OFFSET_RESOURCEID, PN_SMS );
    isiMsg.Set8bit(
        ISI_HEADER_SIZE + SMS_RESOURCE_CONF_REQ_OFFSET_TRANSID,
        0 );
    isiMsg.Set8bit(
        ISI_HEADER_SIZE + SMS_RESOURCE_CONF_REQ_OFFSET_MESSAGEID,
        SMS_RESOURCE_CONF_REQ );
    isiMsg.Set8bit(
        ISI_HEADER_SIZE + SMS_RESOURCE_CONF_REQ_OFFSET_CONFOPERATION,
        SMS_RES_CONF_SET );
    isiMsg.Set8bit(
        ISI_HEADER_SIZE + SMS_RESOURCE_CONF_REQ_OFFSET_SUBBLOCKCOUNT,
        1 );

    isiMsg.CopyData(
        ISI_HEADER_SIZE + SIZE_SMS_RESOURCE_CONF_REQ,
        ResourceConfReqSb.CompleteSubBlock() );

    iPhoNetSender->Send( isiMsg.Complete() );
    }

//  End of File
