diff -r 000000000000 -r 63b37f68c1ce adaptationlayer/tsy/nokiatsy_dll/src/cmmsmsmesshandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/adaptationlayer/tsy/nokiatsy_dll/src/cmmsmsmesshandler.cpp Fri Nov 06 17:28:23 2009 +0000 @@ -0,0 +1,3715 @@ +/* +* Copyright (c) 2007-2009 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 +#include +// Temporarily removed for Bridge camp! +//#include +#include // for sat mo sm control error values +#include // for sat mo sm control error values +#include +#include +#include +#include // for tsmsfirstoctet +#include +#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 ); + +// 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, "CMmSmsMessHandler::CMmSmsMessHandler" ); + } + +// ----------------------------------------------------------------------------- +// CMmSmsMessHandler::CMmSmsMessHandler +// C++ default destructor +// ----------------------------------------------------------------------------- +// +CMmSmsMessHandler::~CMmSmsMessHandler() + { +TFLOGSTRING("TSY: CMmSmsMessHandler::CMmSmsMessHandler: destructor."); +OstTrace0( TRACE_NORMAL, DUP1_CMMSMSMESSHANDLER_CMMSMSMESSHANDLER, "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, "CMmSmsMessHandler::NewL" ); + CMmSmsMessHandler* smsMessHandler = new ( ELeave ) CMmSmsMessHandler(); + + CleanupStack::PushL( smsMessHandler ); + smsMessHandler->iPhoNetSender = aPhoNetSender; + 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, "CMmSmsMessHandler::ConstructL" ); + iSmsListArray = new ( ELeave ) CArrayPtrFlat( 1 ); + iSmspListArray = new ( ELeave ) CArrayPtrFlat( 1 ); + + iReceivedClass2ToBeReSent = EFalse; + // default bearer setting is "CS preferred" + iMobileSmsBearer = RMobileSmsMessaging::ESmsBearerCircuitPreferred; + } + +// ----------------------------------------------------------------------------- +// 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,"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, "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; + } + default: + { +TFLOGSTRING2("TSY: CMmSmsMessHandler::ReceiveMessageL - PN_SMS - unknown msgId: %d", messageId); +OstTraceExt1( TRACE_NORMAL, DUP2_CMMSMSMESSHANDLER_RECEIVEMESSAGEL, "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, "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,"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 msgData; + + aDataPackage->UnPackData( sendData ); + msgAttr = sendData.iAttributes; + + // Check TPDU length + if ( RMobileSmsMessaging::KGsmTpduSize >= sendData.iMsgData->Length() ) + { + msgData.Append( *sendData.iMsgData ); + } + 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, "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, "CMmSmsMessHandler::SmsMessageSendReq.Error!;msgAttr->iFlags=%d;msgAttr->iDataFormat=%hhu", msgAttr->iFlags, msgAttr->iDataFormat ); + } + + // 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, "CMmSmsMessHandler::SmsMessageSendReq.Error! SMS type not supported;tpMti=%hhu", tpMti ); + } + +#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, "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, "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 tpVpSubblockLength( SIZE_SMS_SB_VALIDITY_PERIOD ); + 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 + TUint8 lengthOfAddressSb( 0 ); + TUint8 lengthOfSMSUserDataSb( 0 ); + 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( 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, "CMmSmsMessHandler::CreateSmsMessageSendReq;msgOffset=%hhu;moreMsgToSend=%hhu;smsRoute=%hhu", msgOffset, moreMsgToSend, smsRoute ); + + // Create SMS_SB_SUBMIT subblock + if ( SMS_SB_SUBMIT == aSubblockId ) + { + BuildSmsSbSubmit( aMsgData, isiMsg, msgOffset, addressLength ); + msgOffset += SIZE_SMS_SB_SUBMIT; +TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_SUBMIT created. Message offset: %d", msgOffset ); +OstTraceExt1( TRACE_NORMAL, DUP2_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ, "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; + tpVpSubblockLength = 12; + tpUserDataLengthIndex = + KTpduSubmitIndexUserDataLengthVpfAbsoluteEnchanced; + } + } + // No else. If no TP-VP, User data length index was set to + // 'KTpduSubmitIndexUserDataLengthIfNoTpVp' by default + } + else // Create SMS_SB_COMMAND subblock + { + BuildSmsSbCommand( aMsgData, isiMsg, msgOffset ); + msgOffset += SIZE_SMS_SB_COMMAND; +TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_COMMAND created. Message offset: %d", msgOffset ); +OstTraceExt1( TRACE_NORMAL, DUP3_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ, "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, "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 ) ) ); + lengthOfAddressSb = BuildSmsSbAddress( + addressData, + isiMsg, + SMS_DESTINATION_ADDRESS, + msgOffset ); + msgOffset += lengthOfAddressSb; +TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_ADDRESS created for destination address. Message offset: %d", msgOffset ); +OstTraceExt1( TRACE_NORMAL, DUP4_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ, "CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_ADDRESS created for destination address.;msgOffset=%hhu", msgOffset ); + + // Create SMS_SB_ADDRESS subblock for service center address + TBuf8 scAddr; + BuildScAddress( aMsgAttr->iGsmServiceCentre, scAddr ); + lengthOfAddressSb = + BuildSmsSbAddress( scAddr, isiMsg, SMS_SMSC_ADDRESS, msgOffset ); + msgOffset += lengthOfAddressSb; +TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_ADDRESS created for SC address. Message offset: %d", msgOffset ); +OstTraceExt1( TRACE_NORMAL, DUP5_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ, "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 ); + BuildSmsSbValidityPeriod( + aMsgData, + isiMsg, + tpVpIndex, + tpVpLength, + msgOffset ); + // Udate message offset according to validity period length + msgOffset += tpVpSubblockLength; + numOfSubblocks++; +TFLOGSTRING2("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_VALIDITY_PERIOD created. Message offset: %d", msgOffset ); +OstTraceExt1( TRACE_NORMAL, DUP6_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ, "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, "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 ); + } + lengthOfSMSUserDataSb = BuildSmsSbUserData( + aMsgData, + isiMsg, + tpUdl, + tpUserDataIndex, + defaultAlphabet, + msgOffset + ); + numOfSubblocks++; + msgOffset += lengthOfSMSUserDataSb + 1; // Add one byte to put offset into + // next free position. +TFLOGSTRING("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_USER_DATA created." ); +OstTrace0( TRACE_NORMAL, DUP7_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ, "CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_USER_DATA created." ); + } + + // Create SMS_SB_CHECK_INFO subblock if user data exists + // Destination address length must be added to get user data + // length index + if ( aSmsCheckDisableFdn ) + { + BuildSmsCheckInfo( + isiMsg, + msgOffset ); + numOfSubblocks++; +TFLOGSTRING("TSY: CMmSmsMessHandler::CreateSmsMessageSendReq. SMS_SB_CHECK_INFO created." ); +OstTrace0( TRACE_NORMAL, DUP11_CMMSMSMESSHANDLER_CREATESMSMESSAGESENDREQ, "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, "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, "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, "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 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 + 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, "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 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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "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 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 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 + // Temporarily removed for Bridge camp! + /*if ( iMessageRouter->iSatMessaging ) + { + iMessageRouter->iSatMessaging->CompleteSendSmsMessage ( epocCause ); + } + // for nokiatsy testtool + */ + iMessageRouter->Complete ( EMmTsySmsSendSatMessage, epocCause ); +#else // __WINSCW__ + // Temporarily removed for Bridge camp! + //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, "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, "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, "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, "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, "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, "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, "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, "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, "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, "CMmSmsMessHandler::SmsReceivedPpReportResp;Unexpected transaction ID=%hhu", traId ); + } + + if ( KErrNone != cause ) + { + //Acknowledging failed. + //Complete possible receive message request with KErrGeneral and + //set routing activity to false. SMS Stack makes new ReceiveMessage + //request. + TBool smsInd( EFalse ); + TSmsMsg* nullSms = NULL; + + //Complete request to client + CMmDataPackage package; + package.PackData( &smsInd, &nullSms ); + iSmsSlotLocation = 0; + + // ISI message construction failed or phonet sender + // returned error + iMessageRouter->Complete( + EMobileSmsMessagingReceiveMessage, + &package, + KErrGeneral ); + } + } + +// ----------------------------------------------------------------------------- +// 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, "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, "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, "CMmSmsMessHandler::IsDataCodingScheme7Bit" ); + TUint8 codingGroup( static_cast( 0xf0 & aDcs ) ); // 11110000 + TUint8 lowerBits( static_cast( 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, "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( ( 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( 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, "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, "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: + { + // Lets delete TSY's internal temporary SMSP storage + iSmspListArray->ResetAndDestroy(); + break; + } + case EMobileSmsMessagingStoreSmspList: + { + break; + } + case EMobileSmsMessagingAckSmsStored: + { + TDesC8* data; + //unpack data + aDataPackage->UnPackData( data ); + + TBuf8* msgData = + reinterpret_cast *> ( data ); + + if ( NULL == msgData ) + { +TFLOGSTRING("TSY: CMmSmsMessHandler::ExtFuncL.Internal Ack handling started" ); +OstTrace0( TRACE_NORMAL, DUP2_CMMSMSMESSHANDLER_EXTFUNCL, "CMmSmsMessHandler::ExtFuncL, Internal Ack handling started" ); + } + ret = SmsReceivedMsgReportReq( + ESmsMessagingAckSmsStored, + msgData, + KErrNone ); + break; + } + case EMobileSmsMessagingNackSmsStored: + { + TInt rpCause( 0 ); + TBuf8* msgData; + + //unpack data + aDataPackage->UnPackData( msgData, rpCause ); + + if ( NULL == msgData ) + { +TFLOGSTRING("TSY: CMmSmsMessHandler::ExtFuncL.Internal Nack handling started" ); +OstTrace0( TRACE_NORMAL, DUP3_CMMSMSMESSHANDLER_EXTFUNCL, "CMmSmsMessHandler::ExtFuncL, Internal Nack handling started" ); + } + + ret = SmsReceivedMsgReportReq( + ESmsMessagingNackSmsStored, + msgData, + rpCause ); + break; + } + case EMobilePhoneStoreDelete: + { + ret = DeleteSms( aDataPackage ); + break; + } + case EMobilePhoneStoreDeleteAll: + { + 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( + const_cast( 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, "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( + iSmsCache.TotalEntries() ) ); + TUint8 currentSlot( 1 ); + while ( currentSlot <= totalSlots ) + { + RMobileSmsStore::TMobileGsmSmsEntryV1* smsFromCache = + iSmsCache.GetEntry( currentSlot ); + + if ( smsFromCache ) + { + delete smsFromCache; + } + currentSlot++; + } +TFLOGSTRING("TSY: CMmSmsMessHandler::ExtFuncL - ECustomSetSimMessageStatusReadIPC done."); +OstTrace0( TRACE_NORMAL, DUP5_CMMSMSMESSHANDLER_EXTFUNCL, "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, "CMmSmsMessHandler::ExtFuncL;Unknown aIpc=%d", aIpc ); + ret = KErrArgument; + break; + } + } + return ret; + } + +// ----------------------------------------------------------------------------- +// CMmSmsMessHandler::InternalRetrieveSmspListL +// Complete SmsParametersReadREQuest and call GetSmspList +// or CompleteReadSmsp method +// (other items were commented in header) +// ----------------------------------------------------------------------------- +// +void CMmSmsMessHandler::InternalRetrieveSmspListL( TSmsParameters* aParameters ) + { +TFLOGSTRING("TSY: CMmSmsMessHandler::InternalRetrieveSmspListL"); +OstTrace0( TRACE_NORMAL, CMMSMSMESSHANDLER_INTERNALRETRIEVESMSPLISTL, "CMmSmsMessHandler::InternalRetrieveSmspListL" ); + // Add parameter sets information to the TSY's internal storage + iSmspListArray->AppendL( aParameters ); + + // Lets read next SMSP set + if ( iLocationOfSmspSet <= iAmountOfSmspSets ) + { + iLocationOfSmspSet++; + } + else // All SMSP sets read + { + //Pack data + CMmDataPackage package; + package.PackData( iSmspListArray ); + + //complete the request, + iMessageRouter->Complete( + EMobileSmsMessagingGetSmspListPhase1, + &package, + KErrNone ); + + //Delete array + iSmspListArray->ResetAndDestroy(); + } + } + +// ----------------------------------------------------------------------------- +// 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, "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 + messageReference = ( messageReference + 1 ) / 2; + offset += messageReference; + offset += 2; // Set offset to Protocol Id + 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 receivedMsgServiceCentre; + RMobilePhone::TMobileTON receivedMsgMobileScTON( + RMobilePhone::EUnknownNumber ); + RMobilePhone::TMobileNPI receivedMsgMobileScNPI( + RMobilePhone::EUnknownNumberingPlan ); + + TBuf receivedMsgOriginatorAdress; + RMobilePhone::TMobileTON receivedMsgMobileOaTON( + RMobilePhone::EUnknownNumber ); + RMobilePhone::TMobileNPI receivedMsgMobileOaNPI( + RMobilePhone::EUnknownNumberingPlan ); + + TBuf 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, "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, "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, "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, "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, "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, "CMmSmsMessHandler::GetSmsStoreInfo, waiting" ); + } + // some other, error return error value + else + { +TFLOGSTRING("TSY: CMmSmsMessHandler::GetSmsStoreInfo -- failed"); +OstTrace0( TRACE_NORMAL, DUP4_CMMSMSMESSHANDLER_GETSMSSTOREINFO, "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, "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 ); + iSmsCache.SetDeleteLocation( index ); + } + else + { +TFLOGSTRING("TSY: CMmSmsMessHandler::DeleteSms, cache not ready/failed"); +OstTrace0( TRACE_NORMAL, DUP1_CMMSMSMESSHANDLER_DELETESMS, "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, "CMmSmsMessHandler::DeleteAllSms" ); + TInt ret( KErrNone ); + // SIM SMS cache: -- EMobilePhoneStoreDeleteAll + if ( KErrNone == iSmsCache.Status() ) + { + } + else + { +TFLOGSTRING("TSY: CMmSmsMessHandler::DeleteAllSms, cache not ready/failed"); +OstTrace0( TRACE_NORMAL, DUP1_CMMSMSMESSHANDLER_DELETEALLSMS, "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, "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, "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, "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, "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, "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 +TFLOGSTRING("TSY: CMmSmsMessHandler::InitializeSmsCache -- SMS CACHEING START ---"); +OstTrace0( TRACE_NORMAL, CMMSMSMESSHANDLER_INITIALIZESMSCACHE, "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, "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,"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, "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, "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, "CMmSmsMessHandler::SmsSettingsUpdateReq;iMobileSmsBearer=%d", iMobileSmsBearer ); + break; + } + } + +TFLOGSTRING3("TSY:CMmSmsMessHandler::SmsSettingsUpdateReq:CS priority = %d, PS priority = %d",csRoutePriority,psRoutePriority); +OstTraceExt2( TRACE_NORMAL, DUP2_CMMSMSMESSHANDLER_SMSSETTINGSUPDATEREQ, "CMmSmsMessHandler::SmsSettingsUpdateReq;csRoutePriority=%hhd;psRoutePriority=%hhd", csRoutePriority, psRoutePriority ); + + // SMS_SB_ROUTE_INFO sub block (8 bytes) + TBuf8 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, "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, "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, "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, "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 ( 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, "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, "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, "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, "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, "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, "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, "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, "CMmSmsMessHandler::GetDestAddressLength;aDestAddressLength=%hhu", aDestAddressLength ); + } +TFLOGSTRING2("TSY:CMmSmsMessHandler::GetDestinationAddressLength:Destination address length %d.",aDestAddressLength); +OstTraceExt1( TRACE_NORMAL, DUP2_CMMSMSMESSHANDLER_GETDESTADDRESSLENGTH, "CMmSmsMessHandler::GetDestAddressLength;aDestAddressLength=%hhu", aDestAddressLength ); + return ret; + } + + +// ----------------------------------------------------------------------------- +// Creates SMS_SB_SUBMIT subblock and appends it to ISI message +// ----------------------------------------------------------------------------- +// +void CMmSmsMessHandler::BuildSmsSbSubmit( + const TDesC8& aMsgData, + TIsiSend& aIsiMsg, + TUint8 aMsgOffset, + TUint8 aDestAddressLength ) const + { +TFLOGSTRING("TSY:CMmSmsMessHandler::BuildSmsSbSubmit"); +OstTrace0( TRACE_NORMAL, CMMSMSMESSHANDLER_BUILDSMSSBSUBMIT, "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 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, "CMmSmsMessHandler::BuildSmsSbSubmit;messageParameters=%hhu;messageReference=%hhu;protocolId=%hhu;dataCodingScheme=%hhu", messageParameters, messageReference, protocolId, dataCodingScheme ); + } + + +// ----------------------------------------------------------------------------- +// Creates SMS_SB_COMMAND subblock and appends it to ISI message +// ----------------------------------------------------------------------------- +void CMmSmsMessHandler::BuildSmsSbCommand( + const TDesC8& aMsgData, + TIsiSend& aIsiMsg, + TUint8 aMsgOffset ) const + { +TFLOGSTRING("TSY:CMmSmsMessHandler::BuildSmsSbCommand"); +OstTrace0( TRACE_NORMAL, CMMSMSMESSHANDLER_BUILDSMSSBCOMMAND, "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 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, "CMmSmsMessHandler::BuildSmsSbCommand;messageParameters=%hhu;messageReference=%hhu;protocolId=%hhu;commandType=%hhu;messageNumber=%hhu", messageParameters, messageReference, protocolId, commandType, messageNumber ); + } + + +// ----------------------------------------------------------------------------- +// Creates SMS_SB_ADDRESS subblock and appends it to ISI message +// ----------------------------------------------------------------------------- +TUint8 CMmSmsMessHandler::BuildSmsSbAddress( + const TDesC8& aAddress, + TIsiSend& aIsiMsg, + TUint8 aAddressType, + TUint8 aMsgOffset ) const + { +TFLOGSTRING("TSY:CMmSmsMessHandler::BuildSmsSbAddress"); +OstTrace0( TRACE_NORMAL, CMMSMSMESSHANDLER_BUILDSMSSBADDRESS, "CMmSmsMessHandler::BuildSmsSbAddress" ); + + TUint8 addressLength( aAddress.Length() ); + TUint8 subblockLength( 0 ); + // Create and fill SMS_SB_ADDRESS subblock + TBuf8 addressBuf( 0 ); + TIsiSubBlock address( + addressBuf, + SMS_SB_ADDRESS, + EIsiSubBlockTypeId16Len16 ); + addressBuf.Append( aAddressType ); + addressBuf.Append( addressLength ); + addressBuf.Append( aAddress ); + + aIsiMsg.CopyData( aMsgOffset, address.CompleteSubBlock() ); + + // Subblock length is needed for return value + subblockLength = addressBuf.Length(); + +TFLOGSTRING2( "TSY:CMmSmsMessHandler::BuildSmsSbAddress. Address type: %d", aAddressType ); +TFLOGSTRING2( "TSY:CMmSmsMessHandler::BuildSmsSbAddress. Address length: %d", addressLength ); +OstTraceExt2( TRACE_NORMAL, DUP2_CMMSMSMESSHANDLER_BUILDSMSSBADDRESS, "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, "CMmSmsMessHandler::BuildSmsSbAddress;i=%hhu;aAddress[i]=%hhu", i, aAddress[i] ); + } +#endif // _DEBUG +TFLOGSTRING2( "TSY:CMmSmsMessHandler::BuildSmsSbAddress. Length of subblock: %d", subblockLength ); +OstTraceExt1( TRACE_NORMAL, DUP3_CMMSMSMESSHANDLER_BUILDSMSSBADDRESS, "CMmSmsMessHandler::BuildSmsSbAddress;subblockLength=%hhu", subblockLength ); + + return subblockLength; + } + + +// ----------------------------------------------------------------------------- +// Creates SMS_SB_USER_DATA subblock and appends it to ISI message +// ----------------------------------------------------------------------------- +TUint8 CMmSmsMessHandler::BuildSmsSbUserData( + const TDesC8& aMsgData, + TIsiSend& aIsiMsg, + TUint8 aTpUdl, + TUint8 aTpUserDataIndex, + TBool aDefaultAlphabet, + TUint8 aMsgOffset ) const + { +TFLOGSTRING("TSY:CMmSmsMessHandler::BuildSmsSbUserData"); +OstTrace0( TRACE_NORMAL, CMMSMSMESSHANDLER_BUILDSMSSBUSERDATA, "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 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, "CMmSmsMessHandler::BuildSmsSbUserData;dataLengthInOctets=%hhu;aTpUdl=%hhu", dataLengthInOctets, aTpUdl ); + + return dataLengthInOctets + 8; // 8 bytes sub block header data before data bytes + } + + +// ----------------------------------------------------------------------------- +// Creates SMS_SB_VALIDITY_PERIOD subblock and appends it to ISI message +// ----------------------------------------------------------------------------- +void CMmSmsMessHandler::BuildSmsSbValidityPeriod( + const TDesC8& aMsgData, + TIsiSend& aIsiMsg, + TUint8 aTpVpIndex, + TUint8 aTpVpLength, + TUint8 aMsgOffset ) const + { +TFLOGSTRING("TSY:CMmSmsMessHandler::BuildSmsSbValidityPeriod"); +OstTrace0( TRACE_NORMAL, CMMSMSMESSHANDLER_BUILDSMSSBVALIDITYPERIOD, "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, "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, "CMmSmsMessHandler::BuildSmsSbValidityPeriod;i=%hhu;tpVpData[i]=%hhu", i, tpVpData[i] ); + } +#endif // _DEBUG + } + +// ----------------------------------------------------------------------------- +// Creates SMS_SB_CHECK_INFO sub block with SMS_CHECK_DISABLE_FDN and appends it +// to ISI message. +// ----------------------------------------------------------------------------- +void CMmSmsMessHandler::BuildSmsCheckInfo( + TIsiSend& aIsiMsg, + TUint8 aMsgOffset ) const + { +TFLOGSTRING("TSY:CMmSmsMessHandler::BuildSmsCheckInfo"); +OstTrace0( TRACE_NORMAL, CMMSMSMESSHANDLER_BUILDSMSCHECKINFO, "CMmSmsMessHandler::BuildSmsCheckInfo" ); + + // Create and fill SMS_SB_CHECK_INFO subblock. + TBuf8 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() ); + + } + +// ----------------------------------------------------------------------------- +// CMmSmsMessHandler::ProcessUiccMsg +// Handles data received from UICC server +// ----------------------------------------------------------------------------- +// +TInt CMmSmsMessHandler::ProcessUiccMsg( + TInt aTraId, + TInt aStatus, + const TDesC8& aFileData ) + { +TFLOGSTRING3("TSY:CMmSmsMessHandler::ProcessUiccMsg, aTraId: %d, status: %d", aTraId, aStatus ); +OstTrace1( TRACE_NORMAL, CMMSMSMESSHANDLER_PROCESSUICCMSG, "CMmSmsMessHandler::ProcessUiccMsg;aTraId=%d", aTraId ); +OstTrace1( TRACE_NORMAL, DUP1_CMMSMSMESSHANDLER_PROCESSUICCMSG, "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; + } + default: + { +TFLOGSTRING("TSY:CMmSmsMessHandler::ProcessUiccMsg - unknown transaction ID" ); +OstTrace0( TRACE_NORMAL, DUP2_CMMSMSMESSHANDLER_PROCESSUICCMSG, "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, "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, "CMmSmsMessHandler::UiccReadSMSOrSMSRecordCountReq - unknown transaction ID" ); + ret = KErrUnknown; + break; + } + } + + // Set parameters for UICC_APPL_CMD_REQ message + TUiccReadLinearFixed params; + params.messHandlerPtr = static_cast( 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, "CMmSmsMessHandler::UiccReadSMSResp" ); + + if ( KErrNone == aStatus ) + { +TFLOGSTRING2("TSY: CMmSmsMessHandler::SimStSmsHandleReadCacheEntriesL -- cacheing iRecordId=%d", iRecordId ); +OstTraceExt1( TRACE_NORMAL, DUP1_CMMSMSMESSHANDLER_UICCREADSMSRESP, "CMmSmsMessHandler::UiccReadSMSResp;iRecordId=%hhu", iRecordId ); + + if ( 0 != aFileData.Length() ) + { + // add to cache + RMobileSmsStore::TMobileGsmSmsEntryV1 smsData; + + TUint8 position( 0 ); + smsData.iMsgStatus = + static_cast ( + aFileData[position] ); + + TBuf receivedMsgServiceCentre; + RMobilePhone::TMobileTON receivedMsgMobileScTON( + RMobilePhone::EUnknownNumber ); + RMobilePhone::TMobileNPI receivedMsgMobileScNPI( + RMobilePhone::EUnknownNumberingPlan ); + + position++; + TUint8 addressDataLength( aFileData[position] ); + position++; + 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 ); + + 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, "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, "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, "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, "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, "CMmSmsMessHandler::UiccReadSMSResp;aStatus=%d;aFileData=%s", aStatus,aFileData ); + + + if ( KErrNone == aStatus ) + { +TFLOGSTRING2("TSY: CMmSmsMessHandler::UiccReadSMSRespForComplete -- cacheing iRecordId=%d", iRecordId ); +OstTraceExt1( TRACE_NORMAL, CMMSMSMESSHANDLER_UICCREADSMSRESPFORCOMPLETE, "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 ( + aFileData[position] ); + + TBuf receivedMsgServiceCentre; + RMobilePhone::TMobileTON receivedMsgMobileScTON( + RMobilePhone::EUnknownNumber ); + RMobilePhone::TMobileNPI receivedMsgMobileScNPI( + RMobilePhone::EUnknownNumberingPlan ); + + position++; + TUint8 addressDataLength( aFileData[position] ); + position++; + 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, "CMmSmsMessHandler::UiccWriteSMSReq;aRecordId=%hhu", aRecordId ); + + // Set parameters for UICC_APPL_CMD_REQ message + TUiccWriteLinearFixed params; + params.messHandlerPtr = static_cast( 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 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 scAddress; + TPtrC16 telNumber( aEntry.iServiceCentre.iTelNumber ); + CMmSmsGsmAddress::GsmConvUnicodeTo0411Addr( + aEntry.iServiceCentre.iTypeOfNumber, + aEntry.iServiceCentre.iNumberPlan, + scAddress, + telNumber ); + + // addressDataLength + fileDataBuf.Append( scAddress.Length() ); + totalDataLength++; + + 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, "CMmSmsMessHandler::UiccWriteSMSResp;aStatus=%d", aStatus ); + + // Create Package + CMmDataPackage package; + + if ( iSMSClass2Write ) + { + if ( KErrNone == 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 ( KErrNone == 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::SimStSmsGetNumOfLocReq +// Construct a SIM_ST_SMS_GET_NUM_OF_LOC_REQ ISI message +// to the SIM Server +// ----------------------------------------------------------------------------- +// +void CMmSmsMessHandler::GetNumOfEFSMSRecords( void ) + { +TFLOGSTRING("TSY: CMmSmsMessHandler::GetNumOfEFSMSRecords" ); +OstTrace0( TRACE_NORMAL, CMMSMSMESSHANDLER_GETNUMOFEFSMSRECORDS, "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, "CMmSmsMessHandler::GetNumOfEFSMSRecordsResp;aStatus=%d;aFileData=%s", aStatus, aFileData ); + + TInt offSet( 0 ); + + //Save number of SMS locations on SIM card + TInt smsNumOfLoc( 0 ); + + if ( KErrNone == aStatus ) + { + offSet = aFileData.Find( &KTagFCIFileDescriptor, 1 ); + if( offSet != KErrNotFound ) + { + smsNumOfLoc = + aFileData[offSet + UICC_FCI_EF_FDESC_OFFSET_NUM_ENTR]; + } + } + + // 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, "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 ); + } + } + +// End of File