diff -r 6b1d113cdff3 -r 6638e7f4bd8f telephonyserverplugins/simatktsy/src/CSatNotifySendSm.cpp --- a/telephonyserverplugins/simatktsy/src/CSatNotifySendSm.cpp Mon May 03 13:37:20 2010 +0300 +++ b/telephonyserverplugins/simatktsy/src/CSatNotifySendSm.cpp Thu May 06 15:10:38 2010 +0100 @@ -1,899 +1,899 @@ -// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). -// All rights reserved. -// This component and the accompanying materials are made available -// under the terms of "Eclipse Public License v1.0" -// which accompanies this distribution, and is available -// at the URL "http://www.eclipse.org/legal/epl-v10.html". -// -// Initial Contributors: -// Nokia Corporation - initial contribution. -// -// Contributors: -// -// Description: -// Name : CSatNotifySendSm.cpp -// Part of : Common SIM ATK TSY / commonsimatktsy -// SendSm notification functionality of Sat Tsy -// Version : 1.0 -// - - - -//INCLUDES -#include // Etel SAT IPC definitions -#include "CSatTsy.h" // Tsy class header -#include "CSatNotifySendSm.h" // Tsy class header -#include "CSatNotificationsTsy.h" // Class header -#include "CBerTlv.h" // Ber Tlv data handling -#include "TTlv.h" // TTlv class -#include "CSatDataPackage.h" // Parameter packing -#include "TfLogger.h" // For TFLOGSTRING -#include "TSatUtility.h" // Utilities -#include "CSatTsyReqHandleStore.h" // Request handle class -#include "cmmmessagemanagerbase.h" // Message manager class for forwarding req. - -// ----------------------------------------------------------------------------- -// CSatNotifySendSm::NewL -// Two-phased constructor. -// ----------------------------------------------------------------------------- -// -CSatNotifySendSm* CSatNotifySendSm::NewL - ( - CSatNotificationsTsy* aNotificationsTsy - ) - { - TFLOGSTRING("CSAT: CSatNotifySendSm::NewL"); - CSatNotifySendSm* const satNotifySendSm = - new ( ELeave ) CSatNotifySendSm( aNotificationsTsy ); - CleanupStack::PushL( satNotifySendSm ); - satNotifySendSm->ConstructL(); - CleanupStack::Pop( satNotifySendSm ); - TFLOGSTRING("CSAT: CSatNotifySendSm::NewL, end of method"); - return satNotifySendSm; - } - -// ----------------------------------------------------------------------------- -// CSatNotifySendSm::~CSatNotifySendSm -// Destructor -// ----------------------------------------------------------------------------- -// -CSatNotifySendSm::~CSatNotifySendSm - ( - // None - ) - { - TFLOGSTRING("CSAT: CSatNotifySendSm::~CSatNotifySendSm"); - } - -// ----------------------------------------------------------------------------- -// CSatNotifySendSm::CSatNotifySendSm -// Default C++ constructor -// ----------------------------------------------------------------------------- -// -CSatNotifySendSm::CSatNotifySendSm - ( - CSatNotificationsTsy* aNotificationsTsy - ) : iNotificationsTsy ( aNotificationsTsy ) - { - // None - } - -// ----------------------------------------------------------------------------- -// CSatNotifySendSm::ConstructL -// Symbian 2nd phase constructor -// ----------------------------------------------------------------------------- -// -void CSatNotifySendSm::ConstructL - ( - // None - ) - { - TFLOGSTRING("CSAT: CSatNotifySendSm::ConstructL, does nothing"); - } - -// ----------------------------------------------------------------------------- -// CSatNotifySendSm::Notify -// This request allows a client to be notified of a Send Sm proactive command. -// ----------------------------------------------------------------------------- -// -TInt CSatNotifySendSm::Notify - ( - const TTsyReqHandle aTsyReqHandle, - const TDataPackage& aPackage - ) - { - TFLOGSTRING("CSAT: CSatNotifySendSm::Notify"); - // Save data pointer to client side for completion - iSendSmV1Pckg = reinterpret_cast( - aPackage.Des1n() ); - // Save the request handle - iNotificationsTsy->iSatTsy->SaveReqHandle( aTsyReqHandle, - CSatTsy::ESatNotifySendSmPCmdReqType ); - // Check if requested notification is already pending - iNotificationsTsy->NotifySatReadyForNotification( KSendShortMessage ); - return KErrNone; - } - -// ----------------------------------------------------------------------------- -// CSatNotifySendSm::CancelNotification -// This method cancels an outstanding asynchronous NotifySendSm request. -// ----------------------------------------------------------------------------- -// -TInt CSatNotifySendSm::CancelNotification - ( - const TTsyReqHandle aTsyReqHandle - ) - { - TFLOGSTRING("CSAT: CSatNotifySendSm::CancelNotification"); - // Reset the request handle - TTsyReqHandle reqHandle = iNotificationsTsy->iSatReqHandleStore-> - ResetTsyReqHandle( CSatTsy::ESatNotifySendSmPCmdReqType ); - // Reset the data pointer - iSendSmV1Pckg = NULL; - // Complete the request with KErrCancel - iNotificationsTsy->iSatTsy->ReqCompleted( aTsyReqHandle, KErrCancel ); - - return KErrNone; - } - -// ----------------------------------------------------------------------------- -// CSatNotifySendSm::CompleteNotifyL -// This method completes an outstanding asynchronous NotifySendSm request. -// ----------------------------------------------------------------------------- -// -TInt CSatNotifySendSm::CompleteNotifyL - ( - CSatDataPackage* aDataPackage, - TInt aErrorCode - ) - { - TFLOGSTRING("CSAT: CSatNotifySendSm::CompleteNotifyL"); - TInt ret( KErrNone ); - TBuf<1> additionalInfo; - // Unpack parameters - TPtrC8* data; - aDataPackage->UnPackData( &data ); - // Reset req handle. Returns the deleted req handle - TTsyReqHandle reqHandle = iNotificationsTsy->iSatReqHandleStore-> - ResetTsyReqHandle( CSatTsy::ESatNotifySendSmPCmdReqType ); - - // Get ber tlv - CBerTlv berTlv; - berTlv.SetData( *data ); - // Get command details tlv - CTlv commandDetails; - berTlv.TlvByTagValue( &commandDetails, KTlvCommandDetailsTag ); - // Store command details tlv - iNotificationsTsy->iTerminalRespData.iCommandDetails.Copy( - commandDetails.Data() ); - - TUint8 pCmdNumber( commandDetails.GetShortInfo( ETLV_CommandNumber ) ); - // In case the request was ongoing, continue.. - if ( CSatTsy::ESatReqHandleUnknown != reqHandle ) - { - // Complete right away if error has occured, otherwise continue.. - if ( KErrNone == aErrorCode ) - { - // Fill the send sm structure - RSat::TSendSmV1& sendSmV1 = ( *iSendSmV1Pckg )(); - // Command number - sendSmV1.SetPCmdNumber( pCmdNumber ); - sendSmV1.iSmsTpdu.Zero(); - CTlv smsTpduTlv; - // Get TPdu tlv - TInt returnValue( berTlv.TlvByTagValue( &smsTpduTlv, - KTlvSmsTpduTag ) ); - - if ( KErrNone == returnValue ) - { - // Tpdu TLV length - TUint16 smsTpduLength( smsTpduTlv.GetLength() ); - // Set pointer to Tpdu - TPtrC8 smsTpdu = smsTpduTlv.GetData( ETLV_SmsTPdu ); - // Check that TP-UDL is valid - ret = CheckTpdu( smsTpdu ); - - if ( KErrCorrupt == ret ) - { - TFLOGSTRING("CSAT: CSatNotifySendSm::CompleteNotifyL,\ - Invalid data"); - additionalInfo.Zero(); - additionalInfo.Append( KNoCause ); - CreateTerminalRespL( pCmdNumber, - RSat::KCmdDataNotUnderstood, additionalInfo ); - } - else if ( KErrNone == ret && smsTpduLength ) - { - // Copying the TTpdu - sendSmV1.iSmsTpdu.Append( smsTpdu ); - } - - // Checking if packing is required for the SMS message or not - // Packing: see ETSI 3.38 and 3.40 - if ( ( KSmsPackingRequiredMask & iNotificationsTsy-> - iTerminalRespData.iCommandDetails[KCommandQualifier] ) - && ( KErrNone == ret ) ) - { - // Packing required - if ( smsTpduLength ) - { - // Call method to pack sms - ret = PackSms( smsTpdu, sendSmV1.iSmsTpdu ); - if ( KErrNone != ret ) - { - TFLOGSTRING("CSAT: CSatNotifySendSm::\ - CompleteNotifyL, Invalid TPDU"); - // TPDU is invalid or packing cannot be requested - // if tpdu is something else than SMS-SUBMIT - additionalInfo.Zero(); - additionalInfo.Append( KNoCause ); - CreateTerminalRespL( pCmdNumber, - RSat::KCmdDataNotUnderstood, additionalInfo ); - ret = KErrCorrupt; - } - else - { - // Do nothing - } - } - else - { - TFLOGSTRING("CSAT: CSatNotifySendSm::CompleteNotifyL,\ - Packing not required"); - } - } - else - { - // Do nothing - } - } - else - { - TFLOGSTRING("CSAT: CSatNotifySendSm::CompleteNotifyL,\ - Missing TPDU"); - // TPdu is missing, returning response immediately - additionalInfo.Zero(); - additionalInfo.Append( KNoCause ); - CreateTerminalRespL( pCmdNumber, - RSat::KErrorRequiredValuesMissing, additionalInfo ); - ret = KErrCorrupt; - } - - if ( KErrNone == ret ) - { - SetAlphaIdAndAddressData( &berTlv, sendSmV1 ); - // Iconid - TSatUtility::FillIconStructure( berTlv, sendSmV1.iIconId ); - } - - } // End of if ( KErrNone == aErrorCode ) - else - { - ret = aErrorCode; - } - - iNotificationsTsy->iSatTsy->ReqCompleted( reqHandle, ret ); - - } // End of if ( CSatTsy::ESatReqHandleUnknown != reqHandle ) - else - { - TFLOGSTRING("CSAT: CSatNotifySendSm::CompleteNotifyL,\ - Request not ongoing"); - // Request not on, returning response immediately - additionalInfo.Zero(); - additionalInfo.Append( KNoCause ); - CreateTerminalRespL( pCmdNumber, RSat::KMeUnableToProcessCmd, - additionalInfo ); - } - return ret; - } - -// ----------------------------------------------------------------------------- -// CSatNotifySendSm::TerminalResponseL -// Called by ETel server, passes terminal response to NAA -// ----------------------------------------------------------------------------- -// -TInt CSatNotifySendSm::TerminalResponseL - ( - TDes8* aRsp - ) - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::TerminalResponseL" ); - - TInt ret( KErrNone ); - TBuf<1> additionalInfo; - RSat::TSendSmRspV1Pckg* aRspPckg = - reinterpret_cast( aRsp ); - RSat::TSendSmRspV1& rspV1 = ( *aRspPckg ) (); - // Get Proactive command number - TUint8 pCmdNumber( rspV1.PCmdNumber() ); - TFLOGSTRING2( "CSAT::CSatNotifySendSm::TerminalResponseL: GeneralResult: \ - %d", static_cast( rspV1.iGeneralResult ) ); - - // Check that general result value is valid - if ( ( RSat::KSuccess != rspV1.iGeneralResult ) && - ( RSat::KMeUnableToProcessCmd != rspV1.iGeneralResult ) && - ( RSat::KCmdBeyondMeCapabilities != rspV1.iGeneralResult )&& - ( RSat::KSmsRpError != rspV1.iGeneralResult ) && - ( RSat::KInteractionWithCCPermanentError != rspV1.iGeneralResult ) && - ( RSat::KModifiedByCallControl != rspV1.iGeneralResult ) && - ( RSat::KSuccessRequestedIconNotDisplayed != rspV1.iGeneralResult ) ) - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::TerminalResponseL,\ - Invalid General result" ); - // Invalid general result - ret = KErrCorrupt; - } - - // If there is ME (Mobile Entity) error or network error, additional info - // is needed - if ( ( RSat::KMeProblem == rspV1.iInfoType ) || - ( RSat::KSatNetworkErrorInfo == rspV1.iInfoType ) || - ( RSat::KControlInteraction == rspV1.iInfoType ) ) - { - // Check the length of additional info - if ( 0 == rspV1.iAdditionalInfo.Length() ) - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::TerminalResponseL,\ - Invalid Additional Info" ); - // No info - ret = KErrCorrupt; - } - else - { - additionalInfo.Append( rspV1.iAdditionalInfo[0] ); - } - } - else - { - // Do nothing - } - - // Creating the info message - TInt response = CreateTerminalRespL( pCmdNumber, static_cast( - rspV1.iGeneralResult ), additionalInfo ); - - if(KErrNone == ret) - ret = response; - return ret; - } - -// ----------------------------------------------------------------------------- -// CSatNotifySendSm::CreateTerminalRespL -// Constructs SendSm specific part of terminal response and calls -// DOS to send the actual message. -// ----------------------------------------------------------------------------- -// -TInt CSatNotifySendSm::CreateTerminalRespL - ( - TUint8 aPCmdNumber, - TUint8 aGeneralResult, - TDesC16& aAdditionalInfo - ) - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::CreateTerminalRespL" ); - // Create and append response data - TTlv tlvSpecificData; - // Create General Result TLV here - tlvSpecificData.AddTag( KTlvResultTag ); - // General result - tlvSpecificData.AddByte( aGeneralResult ); - - if ( ( RSat::KMeUnableToProcessCmd == aGeneralResult ) || - ( RSat::KNetworkUnableToProcessCmd == aGeneralResult ) || - ( RSat::KSmsRpError == aGeneralResult ) || - ( RSat::KInteractionWithCCPermanentError == aGeneralResult ) ) - { - if( aAdditionalInfo.Length() > 0 ) - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::CreateTerminalRespL,\ - Unsuccessful result" ); - // If there is ME, Network or SMS error, append additional info - tlvSpecificData.AddByte( static_cast( aAdditionalInfo[0] ) ); - } - } - else - { - // Do nothing - } - - // Prepare data - iNotificationsTsy->iTerminalRespData.iPCmdNumber = aPCmdNumber; - TPtrC8 data = tlvSpecificData.GetDataWithoutTopLevelTag(); - // Pack data - CSatDataPackage dataPackage; - dataPackage.PackData( &iNotificationsTsy->iTerminalRespData, &data ); - // Forward request to the DOS - return iNotificationsTsy->iSatTsy->MessageManager()->HandleRequestL( - ESatTerminalRsp, &dataPackage ); - } - -// ----------------------------------------------------------------------------- -// CSatNotifySendSm::SetAlphaIdAndAddressData -// Set Alpha id and Address into send sm structure -// ----------------------------------------------------------------------------- -// -void CSatNotifySendSm::SetAlphaIdAndAddressData - ( - CBerTlv* aBerTlv, - RSat::TSendSmV1& aSendSmV1 - ) - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::SetAlphaIdAndAddressData" ); - TInt returnValue; - TPtrC8 sourceString; // Used in unicode conversions - // Alpha id string (optional) - aSendSmV1.iAlphaId.iAlphaId.Zero(); - CTlv alphaIdTlv; - returnValue = aBerTlv->TlvByTagValue( &alphaIdTlv, - KTlvAlphaIdentifierTag ) ; - - if ( KErrNone == returnValue ) - { - // Alpha id tlv found - if ( alphaIdTlv.GetLength() ) - { - // Get alpha id text - sourceString.Set( alphaIdTlv.GetData( ETLV_AlphaIdentifier ) ); - // Convert and set alpha id - TSatUtility::SetAlphaId( sourceString, - aSendSmV1.iAlphaId.iAlphaId ); - } - - // Alpha Tag present - if ( aSendSmV1.iAlphaId.iAlphaId.Length() ) - { - aSendSmV1.iAlphaId.iStatus = RSat::EAlphaIdProvided; - } - else - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::SetAlphaIdAndAddressData,\ - Alpha ID is NULL" ); - aSendSmV1.iAlphaId.iStatus = RSat::EAlphaIdNull; - } - } - else - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::SetAlphaIdAndAddressData,\ - Alpha ID not present" ); - aSendSmV1.iAlphaId.iStatus = RSat::EAlphaIdNotPresent; - } - // The address data object holds the RP_Destination_Address of the Service - // Centre. If no RP_Destination_Address is transferred, then the ME shall - // insert the default Service Centre address (below). - aSendSmV1.iAddress.iTelNumber.Zero(); - CTlv addressTlv; - // Get address tlv. Includes SCA number. (optional) - returnValue = aBerTlv->TlvByTagValue( &addressTlv, KTlvAddressTag ); - - if ( KErrNone == returnValue ) - { - if ( 0 < addressTlv.GetLength() ) - { - // Initialize ton and npi - RSat::TTypeOfNumber ton; - RSat::TNumberingPlan npi; - // Call utility function that maps received TON and NPI to - // RSat values - TSatUtility::TonAndNpi( - addressTlv.GetShortInfo( ETLV_TonAndNpi ), &ton, &npi ); - // Set TON and NPI - aSendSmV1.iAddress.iTypeOfNumber = ton; - aSendSmV1.iAddress.iNumberPlan = npi; - TBuf8 tempScaNumber; - // set pointer to address tlv - sourceString.Set( addressTlv.GetData( - ETLV_DiallingNumberString ) ); - - if ( sourceString.Length() ) - { - // Semi-octet presentation used - // Converting back to ASCII format - TSatUtility::BCDToAscii( sourceString, tempScaNumber ); - aSendSmV1.iAddress.iTelNumber.Copy( tempScaNumber ); - TFLOGSTRING2("CSAT: SendSm, SCA number: %S", - &aSendSmV1.iAddress.iTelNumber ); - } - else - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::SetAlphaIdAndAddressData\ - Address TLV found, TON/NPI present, but number epmpty" ); - // Address TLV found, TON/NPI present, but number epmpty. - aSendSmV1.iAddress.iTypeOfNumber = RSat::EUnknownNumber; - aSendSmV1.iAddress.iNumberPlan = RSat::EUnknownNumberingPlan; - } - } - else - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::SetAlphaIdAndAddressData\ - Address TLV found, but the Value part doesn't exist"); - // Address TLV found, but the Value part doesn't exist - aSendSmV1.iAddress.iTypeOfNumber = RSat::EUnknownNumber; - aSendSmV1.iAddress.iNumberPlan = RSat::EUnknownNumberingPlan; - } - } - else - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::SetAlphaIdAndAddressData\ - Address TLV not found"); - // Address TLV not found - aSendSmV1.iAddress.iTypeOfNumber = RSat::ETypeOfNumberNotSet; - aSendSmV1.iAddress.iNumberPlan = RSat::ENumberingPlanNotSet; - } - } - -// ----------------------------------------------------------------------------- -// CSatNotifySendSm::CheckTpdu -// This method Checks TPDU validity -// ----------------------------------------------------------------------------- -// -TInt CSatNotifySendSm::CheckTpdu - ( - TPtrC8 aTpdu - ) - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::CheckTpdu"); - TInt ret( KErrNone ); - - if ( KSATSmsMTISubmitOrSubmitReport == ( aTpdu[0] & KMask3 ) ) - { - // SMS-SUBMIT - TUint8 tpUdl( GetTpUdl( aTpdu ) ); // TP-User-Data-Length - // Get data coding scheme, leave only Alphabet bits - TUint8 dcs( GetTpDcs( aTpdu ) ); - dcs &= KDCSAlphabetMask; - - if ( !dcs && KSmsMaxSize < tpUdl ) - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::CheckTpdu,\ - False DCS Length"); - // DCS is 7-bit and message is over 160 bytes, set ret to corrupt - ret = KErrCorrupt; - } - else if ( ( !( KSmsPackingRequiredMask & iNotificationsTsy-> - iTerminalRespData.iCommandDetails[KCommandQualifier] ) ) - && ( KSmsMaxSizeWithoutPacking < tpUdl && dcs ) ) - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::CheckTpdu,\ - TP-UD Too long without packing"); - // TP-UD is too long without packing - ret = KErrCorrupt; - } - else if ( ( KSmsMaxSize < tpUdl ) && dcs ) - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::CheckTpdu,\ - TP-UD is too long even with packing"); - // TP-UD is too long even with packing - ret = KErrCorrupt; - } - else - { - // Do nothing - } - } - else - { - // SMS-COMMAND - if ( KSMSCommandMaxSize < GetTpUdl( aTpdu ) ) - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::CheckTpdu,\ - False SMS Command length"); - ret = KErrCorrupt; - } - else - { - // Do nothing - } - } - - return ret; - } - -// ----------------------------------------------------------------------------- -// CSatNotifySendSm::GetTpUdl -// This method Returns TP-UDL or TP-CDL depending on is sms type SMS-SUBMIT or -// SMS-COMMAND. -// ----------------------------------------------------------------------------- -// -TUint8 CSatNotifySendSm::GetTpUdl - ( - TPtrC8 aTpdu - ) - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::GetTpUdl"); - TUint8 ret( 0 ); - if ( KSATSmsMTISubmitOrSubmitReport == ( aTpdu[0] & KMask3 ) ) - { - // SMS-SUBMIT - // Calculate the startpos of TP-UD field, - // 5 = number of mandatory fields - TUint8 startPos( KTPDUFieldStart ); - - // Checking the TP-VP field existence - // bit4 bit3 - // 0 0 TP-VP field not present - // 1 0 TP-VP field present - relative format - // KSmsVPFRelative:0x10:000 10 000 - // 0 1 TP-VP field present - enhanced format - // KSmsVPFEnhanced:0x08:000 01 000 - // 1 1 TP-VP field present - absolute format - // KSmsVPFAbsolute:0x18:000 11 000 - // - if ( KSmsVPFRelative == ( aTpdu[0] & KSmsVPFAbsolute ) ) - { - startPos++; - } - if ( ( KSmsVPFEnhanced == ( aTpdu[0] & KSmsVPFAbsolute ) ) - || ( KSmsVPFAbsolute == ( aTpdu[0] & KSmsVPFAbsolute ) ) ) - { - startPos += 7; - } - - // Then the address field length. - // Address field length is number of BCD charachters - // Two BCD string chars are coded in one byte. - // Divide by two to get number of bytes and plus two is - // length tag + TON&NPI byte. - startPos = TUint8( startPos + aTpdu[2] / 2 + 2 ); - if ( aTpdu[2] % 2 ) - { - // If odd number of BCD characters - // increase position by one - startPos++; - } - - else - { - // Do nothing - } - - ret = aTpdu[startPos]; // Return TP-UDL - } - else // SMS-COMMAND - { - TUint8 startPos( 0x05 ); - startPos = static_cast( startPos + aTpdu[5] / 2 + 2 ); - if ( aTpdu[5] % 2 ) - { - // If odd number of characters - // increase position by one - startPos++; - } - ret = aTpdu[startPos]; // Return TP-CDL - } - return ret; - } - -// ----------------------------------------------------------------------------- -// CSatNotifySendSm::GetTpDcs -// This method Returns data coding scheme of the SMS. In the case SMS is -// SMS-COMMAND then return null. -// ----------------------------------------------------------------------------- -// -TUint8 CSatNotifySendSm::GetTpDcs - ( - TPtrC8 aTpdu - ) - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::GetTpDcs"); - TUint8 retValue( NULL ); - if ( KSATSmsMTISubmitOrSubmitReport == ( aTpdu[0] & KMask3 ) ) - { - // SMS-SUBMIT - TUint8 posDCS( 0 ); - posDCS = static_cast( aTpdu[2] / 2 + 2 ); - - if ( aTpdu[2] % 2 ) - { - // If odd number of characters - // increase position by one - posDCS++; - } - - // Add 3 for first octet, message reference and protocol identifier - // mandatory fields - posDCS += 3; - - retValue = aTpdu[posDCS]; - } - // SMS-COMMAND - return retValue; - } - -// ----------------------------------------------------------------------------- -// CSatNotifySendSm::PackSms -// This method Pack SMS if it is required by the NAA -// ----------------------------------------------------------------------------- -// -TInt CSatNotifySendSm::PackSms - ( - TPtrC8 aTpdu, - TTpdu& aSendSm - ) - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::PackSms"); - // See 3GPP TS 23.040 and TS 23.038: - // Packing of Basic elements of the SMS SUBMIT type - TInt ret( KErrNone ); - - // Message is a SMS-SUBMIT message - if ( KSATSmsMTISubmitOrSubmitReport == ( aTpdu[0] & KMask3 ) ) - { - TUint8 startPos( KTPDUFieldStart ); - - if ( KSmsVPFRelative == ( aTpdu[0] & KSmsVPFAbsolute ) ) - { - startPos++; - } - - if ( ( KSmsVPFEnhanced == ( aTpdu[0] & KSmsVPFAbsolute ) ) || - ( KSmsVPFAbsolute == ( aTpdu[0] & KSmsVPFAbsolute ) ) ) - { - startPos += 7; - } - - // Then the address field length, Address field length in semi-octets - startPos = static_cast( startPos + aTpdu[2] / 2 + 2 ); - - if ( aTpdu[2] % 2 ) - { - // if odd number of characters, increase position by one - startPos++; - } - else - { - // Do nothing - } - - TInt i( 0 ); - TInt x = startPos + 1; - - // Checking of there is a header field(s) in the message - if ( KSmsHeaderIndicatorMask & aTpdu[0] ) - { - // Has headers, Pack all the characters in SMS message - TUint8 move( 0 ); - TBool endOfTPDU( EFalse ); - x++; - - for ( i = startPos; i < ( aTpdu[startPos] - aTpdu [startPos + 1] ) - + startPos; i++ ) - { - TUint8 char1( static_cast ( - aTpdu[aTpdu[startPos + 1] + 2 + i] >> move ) ); - TUint8 char2( 0 ); - - if ( ( i + 2 ) <= ( ( aTpdu[startPos] - aTpdu [startPos + 1] ) - + startPos ) ) - { - char2 = static_cast( - aTpdu[aTpdu[startPos + 1] + 2 + i + 1] << ( 7 - move ) ); - } - else - { - char2 = 0; - endOfTPDU = ETrue; - } - - aSendSm[aTpdu[startPos + 1] + x] = static_cast( - char1 | char2 ); - x++; - - if ( ( 6 == move ) && !endOfTPDU ) - { - i++; - move = 0; - } - else - { - move++; - } - } - // Calculate the new length (in septets) - // Old length was in octects - aSendSm[startPos] = - static_cast( ( aTpdu[startPos + 1] * 8 / 7 ) - + ( aTpdu[startPos] - aTpdu[startPos + 1] ) ); - } - else - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::PackSms, No headers"); - // No headers, lets pack all the characters in SMS message - TBool endOfTPDU( EFalse ); - TUint8 move( 0 ); - - for ( i = startPos; i < aTpdu[startPos] + startPos; i++ ) - { - if ( ( i + 1 ) < aTpdu.Length() ) - { - TUint8 char1( static_cast ( aTpdu[i + 1] >> move ) ); - TUint8 char2; - - if ( ( i + 2 ) <= ( aTpdu[startPos] + startPos ) ) - { - if ( ( i + 2 ) < aTpdu.Length() ) - { - char2 = static_cast( aTpdu[i + 2] << - ( 7 - move ) ); - } - else - { - ret = KErrCorrupt; - break; - } - } - else - { - endOfTPDU = ETrue; - char2 = 0; - } - - // Append packed character - aSendSm[x++] = static_cast( char1 | char2 ); - - if ( ( 6 == move ) && !endOfTPDU ) - { - i++; - move = 0; - } - else - { - move++; - } - } - else - { - TFLOGSTRING( "CSAT::CSatNotifySendSm::PackSms, Corrupted"); - ret = KErrCorrupt; - break; - } - } - } - - if ( KErrCorrupt != ret ) - { - // New string length (number of characters) - if ( i - ( x - 1 ) ) - { - aSendSm.SetLength( aSendSm.Length() - ( i - ( x - 1 ) ) ); - } - - // Address field length - // Address field length in semi-octets (BCD) - TUint8 posDCS( 0 ); - posDCS = static_cast( aTpdu[2] / 2 + 2 ); - - if ( aTpdu[2] % 2 ) - { - // If odd number of characters, increase position by one - posDCS++; - } - - // Add 3 for first octet, message reference and protocol identifier - // mandatory fields - posDCS += 3; - - // Change the DCS to default alphabet, Coding: see ETSI 3.38 - if ( ( aTpdu[posDCS] & KMaskC0 ) == 0 ) - { - aSendSm[posDCS] = static_cast( aSendSm[posDCS] & KMaskF3 ); - } - if ( ( KMaskF0 & aTpdu[posDCS] ) == KMaskF0 ) - { - aSendSm[posDCS] = static_cast( aSendSm[posDCS] & KMaskFB ); - } - else - { - // Do nothing - } - } - } - else - { - // Packing cannot be requested if tpdu is something else than SMS submit - ret = KErrCorrupt; - } - return ret; - } - -// End of file +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Name : CSatNotifySendSm.cpp +// Part of : Common SIM ATK TSY / commonsimatktsy +// SendSm notification functionality of Sat Tsy +// Version : 1.0 +// + + + +//INCLUDES +#include // Etel SAT IPC definitions +#include "CSatTsy.h" // Tsy class header +#include "CSatNotifySendSm.h" // Tsy class header +#include "CSatNotificationsTsy.h" // Class header +#include "CBerTlv.h" // Ber Tlv data handling +#include "TTlv.h" // TTlv class +#include "CSatDataPackage.h" // Parameter packing +#include "TfLogger.h" // For TFLOGSTRING +#include "TSatUtility.h" // Utilities +#include "CSatTsyReqHandleStore.h" // Request handle class +#include "cmmmessagemanagerbase.h" // Message manager class for forwarding req. + +// ----------------------------------------------------------------------------- +// CSatNotifySendSm::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CSatNotifySendSm* CSatNotifySendSm::NewL + ( + CSatNotificationsTsy* aNotificationsTsy + ) + { + TFLOGSTRING("CSAT: CSatNotifySendSm::NewL"); + CSatNotifySendSm* const satNotifySendSm = + new ( ELeave ) CSatNotifySendSm( aNotificationsTsy ); + CleanupStack::PushL( satNotifySendSm ); + satNotifySendSm->ConstructL(); + CleanupStack::Pop( satNotifySendSm ); + TFLOGSTRING("CSAT: CSatNotifySendSm::NewL, end of method"); + return satNotifySendSm; + } + +// ----------------------------------------------------------------------------- +// CSatNotifySendSm::~CSatNotifySendSm +// Destructor +// ----------------------------------------------------------------------------- +// +CSatNotifySendSm::~CSatNotifySendSm + ( + // None + ) + { + TFLOGSTRING("CSAT: CSatNotifySendSm::~CSatNotifySendSm"); + } + +// ----------------------------------------------------------------------------- +// CSatNotifySendSm::CSatNotifySendSm +// Default C++ constructor +// ----------------------------------------------------------------------------- +// +CSatNotifySendSm::CSatNotifySendSm + ( + CSatNotificationsTsy* aNotificationsTsy + ) : iNotificationsTsy ( aNotificationsTsy ) + { + // None + } + +// ----------------------------------------------------------------------------- +// CSatNotifySendSm::ConstructL +// Symbian 2nd phase constructor +// ----------------------------------------------------------------------------- +// +void CSatNotifySendSm::ConstructL + ( + // None + ) + { + TFLOGSTRING("CSAT: CSatNotifySendSm::ConstructL, does nothing"); + } + +// ----------------------------------------------------------------------------- +// CSatNotifySendSm::Notify +// This request allows a client to be notified of a Send Sm proactive command. +// ----------------------------------------------------------------------------- +// +TInt CSatNotifySendSm::Notify + ( + const TTsyReqHandle aTsyReqHandle, + const TDataPackage& aPackage + ) + { + TFLOGSTRING("CSAT: CSatNotifySendSm::Notify"); + // Save data pointer to client side for completion + iSendSmV1Pckg = reinterpret_cast( + aPackage.Des1n() ); + // Save the request handle + iNotificationsTsy->iSatTsy->SaveReqHandle( aTsyReqHandle, + CSatTsy::ESatNotifySendSmPCmdReqType ); + // Check if requested notification is already pending + iNotificationsTsy->NotifySatReadyForNotification( KSendShortMessage ); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CSatNotifySendSm::CancelNotification +// This method cancels an outstanding asynchronous NotifySendSm request. +// ----------------------------------------------------------------------------- +// +TInt CSatNotifySendSm::CancelNotification + ( + const TTsyReqHandle aTsyReqHandle + ) + { + TFLOGSTRING("CSAT: CSatNotifySendSm::CancelNotification"); + // Reset the request handle + TTsyReqHandle reqHandle = iNotificationsTsy->iSatReqHandleStore-> + ResetTsyReqHandle( CSatTsy::ESatNotifySendSmPCmdReqType ); + // Reset the data pointer + iSendSmV1Pckg = NULL; + // Complete the request with KErrCancel + iNotificationsTsy->iSatTsy->ReqCompleted( aTsyReqHandle, KErrCancel ); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CSatNotifySendSm::CompleteNotifyL +// This method completes an outstanding asynchronous NotifySendSm request. +// ----------------------------------------------------------------------------- +// +TInt CSatNotifySendSm::CompleteNotifyL + ( + CSatDataPackage* aDataPackage, + TInt aErrorCode + ) + { + TFLOGSTRING("CSAT: CSatNotifySendSm::CompleteNotifyL"); + TInt ret( KErrNone ); + TBuf<1> additionalInfo; + // Unpack parameters + TPtrC8* data; + aDataPackage->UnPackData( &data ); + // Reset req handle. Returns the deleted req handle + TTsyReqHandle reqHandle = iNotificationsTsy->iSatReqHandleStore-> + ResetTsyReqHandle( CSatTsy::ESatNotifySendSmPCmdReqType ); + + // Get ber tlv + CBerTlv berTlv; + berTlv.SetData( *data ); + // Get command details tlv + CTlv commandDetails; + berTlv.TlvByTagValue( &commandDetails, KTlvCommandDetailsTag ); + // Store command details tlv + iNotificationsTsy->iTerminalRespData.iCommandDetails.Copy( + commandDetails.Data() ); + + TUint8 pCmdNumber( commandDetails.GetShortInfo( ETLV_CommandNumber ) ); + // In case the request was ongoing, continue.. + if ( CSatTsy::ESatReqHandleUnknown != reqHandle ) + { + // Complete right away if error has occured, otherwise continue.. + if ( KErrNone == aErrorCode ) + { + // Fill the send sm structure + RSat::TSendSmV1& sendSmV1 = ( *iSendSmV1Pckg )(); + // Command number + sendSmV1.SetPCmdNumber( pCmdNumber ); + sendSmV1.iSmsTpdu.Zero(); + CTlv smsTpduTlv; + // Get TPdu tlv + TInt returnValue( berTlv.TlvByTagValue( &smsTpduTlv, + KTlvSmsTpduTag ) ); + + if ( KErrNone == returnValue ) + { + // Tpdu TLV length + TUint16 smsTpduLength( smsTpduTlv.GetLength() ); + // Set pointer to Tpdu + TPtrC8 smsTpdu = smsTpduTlv.GetData( ETLV_SmsTPdu ); + // Check that TP-UDL is valid + ret = CheckTpdu( smsTpdu ); + + if ( KErrCorrupt == ret ) + { + TFLOGSTRING("CSAT: CSatNotifySendSm::CompleteNotifyL,\ + Invalid data"); + additionalInfo.Zero(); + additionalInfo.Append( KNoCause ); + CreateTerminalRespL( pCmdNumber, + RSat::KCmdDataNotUnderstood, additionalInfo ); + } + else if ( KErrNone == ret && smsTpduLength ) + { + // Copying the TTpdu + sendSmV1.iSmsTpdu.Append( smsTpdu ); + } + + // Checking if packing is required for the SMS message or not + // Packing: see ETSI 3.38 and 3.40 + if ( ( KSmsPackingRequiredMask & iNotificationsTsy-> + iTerminalRespData.iCommandDetails[KCommandQualifier] ) + && ( KErrNone == ret ) ) + { + // Packing required + if ( smsTpduLength ) + { + // Call method to pack sms + ret = PackSms( smsTpdu, sendSmV1.iSmsTpdu ); + if ( KErrNone != ret ) + { + TFLOGSTRING("CSAT: CSatNotifySendSm::\ + CompleteNotifyL, Invalid TPDU"); + // TPDU is invalid or packing cannot be requested + // if tpdu is something else than SMS-SUBMIT + additionalInfo.Zero(); + additionalInfo.Append( KNoCause ); + CreateTerminalRespL( pCmdNumber, + RSat::KCmdDataNotUnderstood, additionalInfo ); + ret = KErrCorrupt; + } + else + { + // Do nothing + } + } + else + { + TFLOGSTRING("CSAT: CSatNotifySendSm::CompleteNotifyL,\ + Packing not required"); + } + } + else + { + // Do nothing + } + } + else + { + TFLOGSTRING("CSAT: CSatNotifySendSm::CompleteNotifyL,\ + Missing TPDU"); + // TPdu is missing, returning response immediately + additionalInfo.Zero(); + additionalInfo.Append( KNoCause ); + CreateTerminalRespL( pCmdNumber, + RSat::KErrorRequiredValuesMissing, additionalInfo ); + ret = KErrCorrupt; + } + + if ( KErrNone == ret ) + { + SetAlphaIdAndAddressData( &berTlv, sendSmV1 ); + // Iconid + TSatUtility::FillIconStructure( berTlv, sendSmV1.iIconId ); + } + + } // End of if ( KErrNone == aErrorCode ) + else + { + ret = aErrorCode; + } + + iNotificationsTsy->iSatTsy->ReqCompleted( reqHandle, ret ); + + } // End of if ( CSatTsy::ESatReqHandleUnknown != reqHandle ) + else + { + TFLOGSTRING("CSAT: CSatNotifySendSm::CompleteNotifyL,\ + Request not ongoing"); + // Request not on, returning response immediately + additionalInfo.Zero(); + additionalInfo.Append( KNoCause ); + CreateTerminalRespL( pCmdNumber, RSat::KMeUnableToProcessCmd, + additionalInfo ); + } + return ret; + } + +// ----------------------------------------------------------------------------- +// CSatNotifySendSm::TerminalResponseL +// Called by ETel server, passes terminal response to NAA +// ----------------------------------------------------------------------------- +// +TInt CSatNotifySendSm::TerminalResponseL + ( + TDes8* aRsp + ) + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::TerminalResponseL" ); + + TInt ret( KErrNone ); + TBuf<1> additionalInfo; + RSat::TSendSmRspV1Pckg* aRspPckg = + reinterpret_cast( aRsp ); + RSat::TSendSmRspV1& rspV1 = ( *aRspPckg ) (); + // Get Proactive command number + TUint8 pCmdNumber( rspV1.PCmdNumber() ); + TFLOGSTRING2( "CSAT::CSatNotifySendSm::TerminalResponseL: GeneralResult: \ + %d", static_cast( rspV1.iGeneralResult ) ); + + // Check that general result value is valid + if ( ( RSat::KSuccess != rspV1.iGeneralResult ) && + ( RSat::KMeUnableToProcessCmd != rspV1.iGeneralResult ) && + ( RSat::KCmdBeyondMeCapabilities != rspV1.iGeneralResult )&& + ( RSat::KSmsRpError != rspV1.iGeneralResult ) && + ( RSat::KInteractionWithCCPermanentError != rspV1.iGeneralResult ) && + ( RSat::KModifiedByCallControl != rspV1.iGeneralResult ) && + ( RSat::KSuccessRequestedIconNotDisplayed != rspV1.iGeneralResult ) ) + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::TerminalResponseL,\ + Invalid General result" ); + // Invalid general result + ret = KErrCorrupt; + } + + // If there is ME (Mobile Entity) error or network error, additional info + // is needed + if ( ( RSat::KMeProblem == rspV1.iInfoType ) || + ( RSat::KSatNetworkErrorInfo == rspV1.iInfoType ) || + ( RSat::KControlInteraction == rspV1.iInfoType ) ) + { + // Check the length of additional info + if ( 0 == rspV1.iAdditionalInfo.Length() ) + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::TerminalResponseL,\ + Invalid Additional Info" ); + // No info + ret = KErrCorrupt; + } + else + { + additionalInfo.Append( rspV1.iAdditionalInfo[0] ); + } + } + else + { + // Do nothing + } + + // Creating the info message + TInt response = CreateTerminalRespL( pCmdNumber, static_cast( + rspV1.iGeneralResult ), additionalInfo ); + + if(KErrNone == ret) + ret = response; + return ret; + } + +// ----------------------------------------------------------------------------- +// CSatNotifySendSm::CreateTerminalRespL +// Constructs SendSm specific part of terminal response and calls +// DOS to send the actual message. +// ----------------------------------------------------------------------------- +// +TInt CSatNotifySendSm::CreateTerminalRespL + ( + TUint8 aPCmdNumber, + TUint8 aGeneralResult, + TDesC16& aAdditionalInfo + ) + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::CreateTerminalRespL" ); + // Create and append response data + TTlv tlvSpecificData; + // Create General Result TLV here + tlvSpecificData.AddTag( KTlvResultTag ); + // General result + tlvSpecificData.AddByte( aGeneralResult ); + + if ( ( RSat::KMeUnableToProcessCmd == aGeneralResult ) || + ( RSat::KNetworkUnableToProcessCmd == aGeneralResult ) || + ( RSat::KSmsRpError == aGeneralResult ) || + ( RSat::KInteractionWithCCPermanentError == aGeneralResult ) ) + { + if( aAdditionalInfo.Length() > 0 ) + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::CreateTerminalRespL,\ + Unsuccessful result" ); + // If there is ME, Network or SMS error, append additional info + tlvSpecificData.AddByte( static_cast( aAdditionalInfo[0] ) ); + } + } + else + { + // Do nothing + } + + // Prepare data + iNotificationsTsy->iTerminalRespData.iPCmdNumber = aPCmdNumber; + TPtrC8 data = tlvSpecificData.GetDataWithoutTopLevelTag(); + // Pack data + CSatDataPackage dataPackage; + dataPackage.PackData( &iNotificationsTsy->iTerminalRespData, &data ); + // Forward request to the DOS + return iNotificationsTsy->iSatTsy->MessageManager()->HandleRequestL( + ESatTerminalRsp, &dataPackage ); + } + +// ----------------------------------------------------------------------------- +// CSatNotifySendSm::SetAlphaIdAndAddressData +// Set Alpha id and Address into send sm structure +// ----------------------------------------------------------------------------- +// +void CSatNotifySendSm::SetAlphaIdAndAddressData + ( + CBerTlv* aBerTlv, + RSat::TSendSmV1& aSendSmV1 + ) + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::SetAlphaIdAndAddressData" ); + TInt returnValue; + TPtrC8 sourceString; // Used in unicode conversions + // Alpha id string (optional) + aSendSmV1.iAlphaId.iAlphaId.Zero(); + CTlv alphaIdTlv; + returnValue = aBerTlv->TlvByTagValue( &alphaIdTlv, + KTlvAlphaIdentifierTag ) ; + + if ( KErrNone == returnValue ) + { + // Alpha id tlv found + if ( alphaIdTlv.GetLength() ) + { + // Get alpha id text + sourceString.Set( alphaIdTlv.GetData( ETLV_AlphaIdentifier ) ); + // Convert and set alpha id + TSatUtility::SetAlphaId( sourceString, + aSendSmV1.iAlphaId.iAlphaId ); + } + + // Alpha Tag present + if ( aSendSmV1.iAlphaId.iAlphaId.Length() ) + { + aSendSmV1.iAlphaId.iStatus = RSat::EAlphaIdProvided; + } + else + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::SetAlphaIdAndAddressData,\ + Alpha ID is NULL" ); + aSendSmV1.iAlphaId.iStatus = RSat::EAlphaIdNull; + } + } + else + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::SetAlphaIdAndAddressData,\ + Alpha ID not present" ); + aSendSmV1.iAlphaId.iStatus = RSat::EAlphaIdNotPresent; + } + // The address data object holds the RP_Destination_Address of the Service + // Centre. If no RP_Destination_Address is transferred, then the ME shall + // insert the default Service Centre address (below). + aSendSmV1.iAddress.iTelNumber.Zero(); + CTlv addressTlv; + // Get address tlv. Includes SCA number. (optional) + returnValue = aBerTlv->TlvByTagValue( &addressTlv, KTlvAddressTag ); + + if ( KErrNone == returnValue ) + { + if ( 0 < addressTlv.GetLength() ) + { + // Initialize ton and npi + RSat::TTypeOfNumber ton; + RSat::TNumberingPlan npi; + // Call utility function that maps received TON and NPI to + // RSat values + TSatUtility::TonAndNpi( + addressTlv.GetShortInfo( ETLV_TonAndNpi ), &ton, &npi ); + // Set TON and NPI + aSendSmV1.iAddress.iTypeOfNumber = ton; + aSendSmV1.iAddress.iNumberPlan = npi; + TBuf8 tempScaNumber; + // set pointer to address tlv + sourceString.Set( addressTlv.GetData( + ETLV_DiallingNumberString ) ); + + if ( sourceString.Length() ) + { + // Semi-octet presentation used + // Converting back to ASCII format + TSatUtility::BCDToAscii( sourceString, tempScaNumber ); + aSendSmV1.iAddress.iTelNumber.Copy( tempScaNumber ); + TFLOGSTRING2("CSAT: SendSm, SCA number: %S", + &aSendSmV1.iAddress.iTelNumber ); + } + else + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::SetAlphaIdAndAddressData\ + Address TLV found, TON/NPI present, but number epmpty" ); + // Address TLV found, TON/NPI present, but number epmpty. + aSendSmV1.iAddress.iTypeOfNumber = RSat::EUnknownNumber; + aSendSmV1.iAddress.iNumberPlan = RSat::EUnknownNumberingPlan; + } + } + else + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::SetAlphaIdAndAddressData\ + Address TLV found, but the Value part doesn't exist"); + // Address TLV found, but the Value part doesn't exist + aSendSmV1.iAddress.iTypeOfNumber = RSat::EUnknownNumber; + aSendSmV1.iAddress.iNumberPlan = RSat::EUnknownNumberingPlan; + } + } + else + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::SetAlphaIdAndAddressData\ + Address TLV not found"); + // Address TLV not found + aSendSmV1.iAddress.iTypeOfNumber = RSat::ETypeOfNumberNotSet; + aSendSmV1.iAddress.iNumberPlan = RSat::ENumberingPlanNotSet; + } + } + +// ----------------------------------------------------------------------------- +// CSatNotifySendSm::CheckTpdu +// This method Checks TPDU validity +// ----------------------------------------------------------------------------- +// +TInt CSatNotifySendSm::CheckTpdu + ( + TPtrC8 aTpdu + ) + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::CheckTpdu"); + TInt ret( KErrNone ); + + if ( KSATSmsMTISubmitOrSubmitReport == ( aTpdu[0] & KMask3 ) ) + { + // SMS-SUBMIT + TUint8 tpUdl( GetTpUdl( aTpdu ) ); // TP-User-Data-Length + // Get data coding scheme, leave only Alphabet bits + TUint8 dcs( GetTpDcs( aTpdu ) ); + dcs &= KDCSAlphabetMask; + + if ( !dcs && KSmsMaxSize < tpUdl ) + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::CheckTpdu,\ + False DCS Length"); + // DCS is 7-bit and message is over 160 bytes, set ret to corrupt + ret = KErrCorrupt; + } + else if ( ( !( KSmsPackingRequiredMask & iNotificationsTsy-> + iTerminalRespData.iCommandDetails[KCommandQualifier] ) ) + && ( KSmsMaxSizeWithoutPacking < tpUdl && dcs ) ) + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::CheckTpdu,\ + TP-UD Too long without packing"); + // TP-UD is too long without packing + ret = KErrCorrupt; + } + else if ( ( KSmsMaxSize < tpUdl ) && dcs ) + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::CheckTpdu,\ + TP-UD is too long even with packing"); + // TP-UD is too long even with packing + ret = KErrCorrupt; + } + else + { + // Do nothing + } + } + else + { + // SMS-COMMAND + if ( KSMSCommandMaxSize < GetTpUdl( aTpdu ) ) + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::CheckTpdu,\ + False SMS Command length"); + ret = KErrCorrupt; + } + else + { + // Do nothing + } + } + + return ret; + } + +// ----------------------------------------------------------------------------- +// CSatNotifySendSm::GetTpUdl +// This method Returns TP-UDL or TP-CDL depending on is sms type SMS-SUBMIT or +// SMS-COMMAND. +// ----------------------------------------------------------------------------- +// +TUint8 CSatNotifySendSm::GetTpUdl + ( + TPtrC8 aTpdu + ) + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::GetTpUdl"); + TUint8 ret( 0 ); + if ( KSATSmsMTISubmitOrSubmitReport == ( aTpdu[0] & KMask3 ) ) + { + // SMS-SUBMIT + // Calculate the startpos of TP-UD field, + // 5 = number of mandatory fields + TUint8 startPos( KTPDUFieldStart ); + + // Checking the TP-VP field existence + // bit4 bit3 + // 0 0 TP-VP field not present + // 1 0 TP-VP field present - relative format + // KSmsVPFRelative:0x10:000 10 000 + // 0 1 TP-VP field present - enhanced format + // KSmsVPFEnhanced:0x08:000 01 000 + // 1 1 TP-VP field present - absolute format + // KSmsVPFAbsolute:0x18:000 11 000 + // + if ( KSmsVPFRelative == ( aTpdu[0] & KSmsVPFAbsolute ) ) + { + startPos++; + } + if ( ( KSmsVPFEnhanced == ( aTpdu[0] & KSmsVPFAbsolute ) ) + || ( KSmsVPFAbsolute == ( aTpdu[0] & KSmsVPFAbsolute ) ) ) + { + startPos += 7; + } + + // Then the address field length. + // Address field length is number of BCD charachters + // Two BCD string chars are coded in one byte. + // Divide by two to get number of bytes and plus two is + // length tag + TON&NPI byte. + startPos = TUint8( startPos + aTpdu[2] / 2 + 2 ); + if ( aTpdu[2] % 2 ) + { + // If odd number of BCD characters + // increase position by one + startPos++; + } + + else + { + // Do nothing + } + + ret = aTpdu[startPos]; // Return TP-UDL + } + else // SMS-COMMAND + { + TUint8 startPos( 0x05 ); + startPos = static_cast( startPos + aTpdu[5] / 2 + 2 ); + if ( aTpdu[5] % 2 ) + { + // If odd number of characters + // increase position by one + startPos++; + } + ret = aTpdu[startPos]; // Return TP-CDL + } + return ret; + } + +// ----------------------------------------------------------------------------- +// CSatNotifySendSm::GetTpDcs +// This method Returns data coding scheme of the SMS. In the case SMS is +// SMS-COMMAND then return null. +// ----------------------------------------------------------------------------- +// +TUint8 CSatNotifySendSm::GetTpDcs + ( + TPtrC8 aTpdu + ) + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::GetTpDcs"); + TUint8 retValue( NULL ); + if ( KSATSmsMTISubmitOrSubmitReport == ( aTpdu[0] & KMask3 ) ) + { + // SMS-SUBMIT + TUint8 posDCS( 0 ); + posDCS = static_cast( aTpdu[2] / 2 + 2 ); + + if ( aTpdu[2] % 2 ) + { + // If odd number of characters + // increase position by one + posDCS++; + } + + // Add 3 for first octet, message reference and protocol identifier + // mandatory fields + posDCS += 3; + + retValue = aTpdu[posDCS]; + } + // SMS-COMMAND + return retValue; + } + +// ----------------------------------------------------------------------------- +// CSatNotifySendSm::PackSms +// This method Pack SMS if it is required by the NAA +// ----------------------------------------------------------------------------- +// +TInt CSatNotifySendSm::PackSms + ( + TPtrC8 aTpdu, + TTpdu& aSendSm + ) + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::PackSms"); + // See 3GPP TS 23.040 and TS 23.038: + // Packing of Basic elements of the SMS SUBMIT type + TInt ret( KErrNone ); + + // Message is a SMS-SUBMIT message + if ( KSATSmsMTISubmitOrSubmitReport == ( aTpdu[0] & KMask3 ) ) + { + TUint8 startPos( KTPDUFieldStart ); + + if ( KSmsVPFRelative == ( aTpdu[0] & KSmsVPFAbsolute ) ) + { + startPos++; + } + + if ( ( KSmsVPFEnhanced == ( aTpdu[0] & KSmsVPFAbsolute ) ) || + ( KSmsVPFAbsolute == ( aTpdu[0] & KSmsVPFAbsolute ) ) ) + { + startPos += 7; + } + + // Then the address field length, Address field length in semi-octets + startPos = static_cast( startPos + aTpdu[2] / 2 + 2 ); + + if ( aTpdu[2] % 2 ) + { + // if odd number of characters, increase position by one + startPos++; + } + else + { + // Do nothing + } + + TInt i( 0 ); + TInt x = startPos + 1; + + // Checking of there is a header field(s) in the message + if ( KSmsHeaderIndicatorMask & aTpdu[0] ) + { + // Has headers, Pack all the characters in SMS message + TUint8 move( 0 ); + TBool endOfTPDU( EFalse ); + x++; + + for ( i = startPos; i < ( aTpdu[startPos] - aTpdu [startPos + 1] ) + + startPos; i++ ) + { + TUint8 char1( static_cast ( + aTpdu[aTpdu[startPos + 1] + 2 + i] >> move ) ); + TUint8 char2( 0 ); + + if ( ( i + 2 ) <= ( ( aTpdu[startPos] - aTpdu [startPos + 1] ) + + startPos ) ) + { + char2 = static_cast( + aTpdu[aTpdu[startPos + 1] + 2 + i + 1] << ( 7 - move ) ); + } + else + { + char2 = 0; + endOfTPDU = ETrue; + } + + aSendSm[aTpdu[startPos + 1] + x] = static_cast( + char1 | char2 ); + x++; + + if ( ( 6 == move ) && !endOfTPDU ) + { + i++; + move = 0; + } + else + { + move++; + } + } + // Calculate the new length (in septets) + // Old length was in octects + aSendSm[startPos] = + static_cast( ( aTpdu[startPos + 1] * 8 / 7 ) + + ( aTpdu[startPos] - aTpdu[startPos + 1] ) ); + } + else + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::PackSms, No headers"); + // No headers, lets pack all the characters in SMS message + TBool endOfTPDU( EFalse ); + TUint8 move( 0 ); + + for ( i = startPos; i < aTpdu[startPos] + startPos; i++ ) + { + if ( ( i + 1 ) < aTpdu.Length() ) + { + TUint8 char1( static_cast ( aTpdu[i + 1] >> move ) ); + TUint8 char2; + + if ( ( i + 2 ) <= ( aTpdu[startPos] + startPos ) ) + { + if ( ( i + 2 ) < aTpdu.Length() ) + { + char2 = static_cast( aTpdu[i + 2] << + ( 7 - move ) ); + } + else + { + ret = KErrCorrupt; + break; + } + } + else + { + endOfTPDU = ETrue; + char2 = 0; + } + + // Append packed character + aSendSm[x++] = static_cast( char1 | char2 ); + + if ( ( 6 == move ) && !endOfTPDU ) + { + i++; + move = 0; + } + else + { + move++; + } + } + else + { + TFLOGSTRING( "CSAT::CSatNotifySendSm::PackSms, Corrupted"); + ret = KErrCorrupt; + break; + } + } + } + + if ( KErrCorrupt != ret ) + { + // New string length (number of characters) + if ( i - ( x - 1 ) ) + { + aSendSm.SetLength( aSendSm.Length() - ( i - ( x - 1 ) ) ); + } + + // Address field length + // Address field length in semi-octets (BCD) + TUint8 posDCS( 0 ); + posDCS = static_cast( aTpdu[2] / 2 + 2 ); + + if ( aTpdu[2] % 2 ) + { + // If odd number of characters, increase position by one + posDCS++; + } + + // Add 3 for first octet, message reference and protocol identifier + // mandatory fields + posDCS += 3; + + // Change the DCS to default alphabet, Coding: see ETSI 3.38 + if ( ( aTpdu[posDCS] & KMaskC0 ) == 0 ) + { + aSendSm[posDCS] = static_cast( aSendSm[posDCS] & KMaskF3 ); + } + if ( ( KMaskF0 & aTpdu[posDCS] ) == KMaskF0 ) + { + aSendSm[posDCS] = static_cast( aSendSm[posDCS] & KMaskFB ); + } + else + { + // Do nothing + } + } + } + else + { + // Packing cannot be requested if tpdu is something else than SMS submit + ret = KErrCorrupt; + } + return ret; + } + +// End of file