smsprotocols/smsstack/gsmu/src/gsmupdu.cpp
changeset 0 3553901f7fa8
child 14 7ef16719d8cb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/smsprotocols/smsstack/gsmu/src/gsmupdu.cpp	Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,3767 @@
+// Copyright (c) 2003-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:
+// Contains implementations for the classes defined in gsmpdu.h
+// 
+//
+
+/**
+ @file
+*/
+
+#include <etelmm.h>
+#include "gsmuNmspaceMobMsg.h"
+#include "gsmuetel.h"
+#include <exterror.h>
+#include <e32uid.h>
+
+#include "gsmupdu.h"
+#include "Gsmumain.h"
+#include "Gsmumsg.h"
+
+/**
+ *  Restores a CSmsPDU from a stream where the object has bean previously persisted.
+ *  
+ *  The type is determined from the first byte in the stream.
+ *  
+ *  @param aStream Stream from which to restore this CSmsPDU
+ *  @param aCharacterSetConverter Character converter utility, required for encoding
+ *  and decoding this PDU
+ *  @param aFs File system handle, required for encoding and decoding this PDU
+ *  @return Newly constructed CSmsPDU-derived object restored from aStream
+ *  @capability None
+ */
+EXPORT_C CSmsPDU* CSmsPDU::NewL(RReadStream& aStream,CCnvCharacterSetConverter& aCharacterSetConverter,RFs& aFs)
+	{
+	LOGGSMU1("CSmsPDU::NewL()");
+
+	TInt type=aStream.ReadUint8L();
+	CSmsPDU* smspdu=NULL;
+	switch (type)
+		{
+		case ESmsDeliver:
+			{
+			smspdu=new(ELeave) CSmsDeliver();
+			break;
+			}
+		case ESmsSubmit:
+			{
+			smspdu=new(ELeave) CSmsSubmit();
+			break;
+			}
+		case ESmsDeliverReport:
+			{
+			smspdu=new(ELeave) CSmsDeliverReport();
+			break;
+			}
+		case ESmsSubmitReport:
+			{
+			smspdu=new(ELeave) CSmsSubmitReport();
+			break;
+			}
+		case ESmsStatusReport:
+			{
+			smspdu=new(ELeave) CSmsStatusReport();
+			break;
+			}
+		case ESmsCommand:
+			{
+			smspdu=new(ELeave) CSmsCommand();
+			break;
+			}
+		default:
+			User::Leave(KErrNotSupported);
+		};
+	CleanupStack::PushL(smspdu);
+	smspdu->ConstructL(aCharacterSetConverter,aFs);
+	smspdu->InternalizeMessagePDUL(aStream);
+	CleanupStack::Pop();
+	return smspdu;
+	} // CSmsPDU::NewL
+
+
+/**
+ *  Allocates and constructs a CSmsPDU from a TGsmSms.
+ *  
+ *  The type of SMS to construct is determined from the first octet in aGsmSms
+ *  and whether the SMS is mobile terminated.
+ *  
+ *  @param aGsmSms Encoded (raw) GSM SMS PDU
+ *  @param aCharacterSetConverter Character converter utility, required for encoding
+ *  and decoding this PDU
+ *  @param aFs File system handle, required for encoding and decoding this PDU
+ *  @param aIsRPError True if the PDU is part of an RP Error. This is used only
+ *  for SUBMIT REPORT (CSmsSubmitReport) and DELIVER REPORT (CSmsDeliverReport),
+ *  as the format of these PDUs differs depending on whether the PDU is part of
+ *  an RP Ack or RP Error.
+ *  @param aIsMobileTerminated Used to determine (with the first octet in aGsmSms)
+ *  the TSmsPDUType
+ *  @return Newly constructed CSmsPDU-derived object restored from aGsmSms
+ *  @capability None
+ */
+EXPORT_C CSmsPDU* CSmsPDU::NewL(const TGsmSms& aGsmSms,CCnvCharacterSetConverter& aCharacterSetConverter,RFs& aFs, TBool aIsRPError,TBool aIsMobileTerminated)
+	{
+	LOGGSMU3("CSmsPDU::NewL(): aIsRPError=%d, aIsMobileTerminated=%d",
+			 aIsRPError, aIsMobileTerminated);
+
+    const TUint8* ptr1=aGsmSms.Pdu().Ptr();
+
+    TInt mti=*ptr1 & TSmsFirstOctet::ESmsMTIMask; // mask first two bits
+	CSmsPDU* smspdu=NULL;
+	switch (mti)
+		{
+		case TSmsFirstOctet::ESmsMTIDeliverOrDeliverReport:
+			{
+			if (aIsMobileTerminated)
+				smspdu=new(ELeave) CSmsDeliver();
+			else
+				smspdu=new(ELeave) CSmsDeliverReport(aIsRPError);
+			break;
+			}
+		case TSmsFirstOctet::ESmsMTISubmitOrSubmitReport:
+			{
+			if (aIsMobileTerminated)
+				smspdu=new(ELeave) CSmsSubmitReport(aIsRPError);
+			else
+				smspdu=new(ELeave) CSmsSubmit();
+			break;
+			}
+		case TSmsFirstOctet::ESmsMTIStatusReportOrCommand:
+			{
+			if (aIsMobileTerminated)
+				smspdu=new(ELeave) CSmsStatusReport();
+			else
+				smspdu=new(ELeave) CSmsCommand();
+			break;
+			}
+		default:
+			User::Leave(KErrNotSupported);
+		};
+	CleanupStack::PushL(smspdu);
+	smspdu->ConstructL(aCharacterSetConverter,aFs);
+
+	TGsmuLex8 lex(aGsmSms.Pdu());
+	smspdu->DecodeL(lex);
+
+	// TODO Service centre address should be in rigth format when it comes from TSY
+	smspdu->SetParsedServiceCenterAddressL(aGsmSms.Sca());
+
+	CleanupStack::Pop(smspdu);
+	return smspdu;
+	} // CSmsPDU::NewL
+
+
+/**
+ *  Allocates and constructs a CSmsPDU, with the type specified by a TSmsPDUType.
+ *  
+ *  @param aType The PDU type to construct
+ *  @param aCharacterSetConverter Character converter utility, required for encoding
+ *  and decoding this PDU
+ *  @param aFs File system handle, required for encoding and decoding this PDU
+ *  @param aIsRPError True if the PDU is part of an RP Error. This is used only
+ *  for SUBMIT REPORT (CSmsSubmitReport) and DELIVER REPORT (CSmsDeliverReport),
+ *  as the format of these PDUs differs depending on whether the PDU is part of
+ *  an RP Ack or RP Error.
+ *  @return Newly constructed CSmsPDU-derived object
+ *  @capability None
+ */
+EXPORT_C CSmsPDU* CSmsPDU::NewL(TSmsPDUType aType,CCnvCharacterSetConverter& aCharacterSetConverter,RFs& aFs,TBool aIsRPError)
+	{
+	LOGGSMU2("CSmsPDU::NewL(): aIsRPError=%d", aIsRPError);
+
+	CSmsPDU* smspdu=NULL;
+	switch (aType)
+		{
+		case ESmsDeliver:
+			{
+			smspdu=new(ELeave) CSmsDeliver();
+			break;
+			}
+		case ESmsSubmit:
+			{
+			smspdu=new(ELeave) CSmsSubmit();
+			break;
+			}
+		case ESmsDeliverReport:
+			{
+			smspdu=new(ELeave) CSmsDeliverReport(aIsRPError);
+			break;
+			}
+		case ESmsSubmitReport:
+			{
+			smspdu=new(ELeave) CSmsSubmitReport(aIsRPError);
+			break;
+			}
+		case ESmsStatusReport:
+			{
+			smspdu=new(ELeave) CSmsStatusReport();
+			break;
+			}
+		case ESmsCommand:
+			{
+			smspdu=new(ELeave) CSmsCommand();
+			break;
+			}
+		default:
+			User::Leave(KErrNotSupported);
+		};
+	CleanupStack::PushL(smspdu);
+	smspdu->ConstructL(aCharacterSetConverter,aFs);
+	CleanupStack::Pop();
+	return smspdu;
+	} // CSmsPDU::NewL
+
+
+/**
+ *  Allocates and constructs a CSmsPDU as a copy of another CSmsPDU.
+ *  
+ *  @return Newly constructed CSmsPDU-derived object
+ *  @capability None
+ */
+EXPORT_C CSmsPDU* CSmsPDU::DuplicateL() const
+	{
+	LOGGSMU1("CSmsPDU::DuplicateL()");
+
+	CSmsPDU*  smsPDU = NULL;
+
+	switch (Type())
+		{
+		case ESmsDeliver:
+			{
+			smsPDU = ((CSmsDeliver*) this)->DuplicateL();
+			}
+			break;
+
+		case ESmsDeliverReport:
+			{
+			smsPDU = ((CSmsDeliverReport*) this)->DuplicateL();
+			}
+			break;
+
+		case ESmsSubmit:
+			{
+			smsPDU = ((CSmsSubmit*) this)->DuplicateL();
+			}
+			break;
+
+		case ESmsSubmitReport:
+			{
+			smsPDU = ((CSmsSubmitReport*) this)->DuplicateL();
+			}
+			break;
+
+		case ESmsStatusReport:
+			{
+			smsPDU = ((CSmsStatusReport*) this)->DuplicateL();
+			}
+			break;
+
+		case ESmsCommand:
+			{
+			smsPDU = ((CSmsCommand*) this)->DuplicateL();
+			}
+			break;
+
+		default:
+			{
+			User::Leave(KErrNotSupported);
+			}
+			break;
+		};
+
+	return smsPDU;
+	} // CSmsPDU::DuplicateL
+
+
+/**
+ *  Externalises the object.
+ *  
+ *  @param aStream Stream to write to
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::ExternalizeL(RWriteStream& aStream) const
+	{
+	aStream.WriteUint8L(iSmsPDUType);
+	ExternalizeMessagePDUL(aStream);
+	} // CSmsPDU::ExternalizeL
+
+
+/**
+ *  Encodes a TGsmSms for the given type of CSmsPDU.
+ *  
+ *  @param aGsmSms On return, encoded GSM SMS PDU
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::EncodeMessagePDUL(TGsmSms& aGsmSms) const
+	{
+	LOGGSMU1("CSmsPDU::EncodeMessagePDUL()");
+
+	NMobileSmsMessaging::TMobileSmsGsmTpdu pdu;
+	pdu.SetLength(NMobileSmsMessaging::KGsmTpduSize);
+	TUint8 *ptr1=(TUint8*) pdu.Ptr();
+	TUint8 *ptr2=ptr1;
+
+	TGsmSmsTelNumber parsedAddress;
+	iServiceCenterAddress->ParsedAddress(parsedAddress);
+	aGsmSms.SetSca(parsedAddress);
+
+	ptr2=EncodeL(ptr1);
+	pdu.SetLength(ptr2-ptr1);
+	aGsmSms.SetPdu(pdu);
+	} // CSmsPDU::EncodeMessagePDUL
+
+void CSmsPDU::EncodeMessagePDUL(TGsmSms& aGsmSms, const TEncodeParams* aEncodeParams) const
+	{
+	LOGGSMU1("CSmsPDU::EncodeMessagePDUL()");
+
+	NMobileSmsMessaging::TMobileSmsGsmTpdu pdu;
+	pdu.SetLength(NMobileSmsMessaging::KGsmTpduSize);
+	TUint8 *ptr1=(TUint8*) pdu.Ptr();
+	TUint8 *ptr2=ptr1;
+
+	TGsmSmsTelNumber parsedAddress;
+	iServiceCenterAddress->ParsedAddress(parsedAddress);
+	aGsmSms.SetSca(parsedAddress);
+
+	ptr2=EncodeL(ptr1, aEncodeParams);
+	pdu.SetLength(ptr2-ptr1);
+	aGsmSms.SetPdu(pdu);
+	} // CSmsPDU::EncodeMessagePDUL	
+
+/**
+ *  Gets the service center address.
+ *  
+ *  It is assumed that the address is Unicode, and can contain spaces and alphabetic
+ *  characters.
+ *  
+ *  @return Service center address
+ *  @capability None
+ */
+EXPORT_C TPtrC CSmsPDU::ServiceCenterAddress() const
+	{
+	LOGGSMU1("CSmsPDU::ServiceCenterAddress()");
+
+	return iServiceCenterAddress->Address();
+	} // CSmsPDU::ServiceCenterAddress
+
+
+/**
+ *  Sets the service center address.
+ *  
+ *  A prepended '+' is used to indicate an international number.
+ *  
+ *  @param aAddress Service center address
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetServiceCenterAddressL(const TDesC& aAddress)
+	{
+	LOGGSMU1("CSmsPDU::SetServiceCenterAddressL()");
+
+	iServiceCenterAddress->SetAddressL(aAddress);
+	} // CSmsPDU::SetServiceCenterAddressL
+
+
+/**
+ *  Gets the service center address in a TGsmSmsTelNumber object.
+ *  
+ *  A prepended '+', spaces and aphabetic characters are removed.
+ *  
+ *  @param aParsedAddress Service center address
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::ParsedServiceCenterAddress(TGsmSmsTelNumber& aParsedAddress) const
+	{
+	LOGGSMU1("CSmsPDU::ParsedServiceCenterAddress()");
+
+	iServiceCenterAddress->ParsedAddress(aParsedAddress);
+	} // CSmsPDU::ParsedServiceCenterAddress
+
+
+/**
+ *  Sets the service center address through a TGsmSmsTelNumber object.
+ *  
+ *  These functions panic for a DELIVER REPORT (CSmsDeliverReport) or a SUBMIT REPORT (CSmsSubmitReport).
+ *  
+ *  @param aParsedAddress Service center address
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetParsedServiceCenterAddressL(const TGsmSmsTelNumber& aParsedAddress)
+	{
+	LOGGSMU1("CSmsPDU::SetParsedServiceCenterAddressL()");
+
+	iServiceCenterAddress->SetParsedAddressL(aParsedAddress);
+	} // CSmsPDU::SetParsedServiceCenterAddressL
+
+
+/**
+ *  Gets the "to from" address.
+ *  
+ *  This address is the original (sender's) address for a DELIVER (CSmsDeliver),
+ *  the destination address for a SUBMIT (CSmsSubmit), the recipient (sender's)
+ *  address for a STATUS REPORT (CSmsStatusReport) and the destination address
+ *  for a COMMAND (CSmsCommand).
+ *  
+ *  The function panics for a DELIVER REPORT (CSmsDeliverReport) or a SUBMIT REPORT
+ *  (CSmsSubmitReport).
+ *  
+ *  It is assumed that the address is Unicode, and can contain spaces and alphabetic
+ *  characters.
+ *  
+ *  @return The destination or sender address
+ *  @capability None
+ */
+EXPORT_C TPtrC CSmsPDU::ToFromAddress() const
+	{
+	LOGGSMU1("CSmsPDU::SetParsedServiceCenterAddressL()");
+
+	if (ToFromAddressPtr() == NULL)
+		{
+		return TPtrC(KNullDesC16);
+		}
+
+	return ToFromAddressPtr()->Address();
+	} // CSmsPDU::ToFromAddress
+
+
+/**
+ *  Sets the "to from" address.
+ *  
+ *  The function panics for a DELIVER REPORT (CSmsDeliverReport) or a SUBMIT REPORT
+ *  (CSmsSubmitReport).
+ *  
+ *  A prepended '+' is used to indicate an international number.
+ *  
+ *  @param aAddress The destination or sender address
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetToFromAddressL(const TDesC& aAddress)
+	{
+	LOGGSMU1("CSmsPDU::SetToFromAddressL()");
+
+	__ASSERT_DEBUG(ToFromAddressPtr()!=NULL,Panic(KGsmuPanicToFromAddressNotPresent));
+	CSmsAddress* tofromaddress=(CSmsAddress*) ToFromAddressPtr();
+	tofromaddress->SetAddressL(aAddress);
+	} // CSmsPDU::SetToFromAddressL
+
+
+/**
+ *  Gets the "to from" in a TGsmSmsTelNumber object.
+ *  
+ *  A prepended '+', spaces and aphabetic characters are removed.
+ *  
+ *  @param aParsedAddress The destination or sender address
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::ParsedToFromAddress(TGsmSmsTelNumber& aParsedAddress) const
+	{
+	LOGGSMU1("CSmsPDU::ParsedToFromAddress()");
+
+	__ASSERT_DEBUG(ToFromAddressPtr()!=NULL,Panic(KGsmuPanicToFromAddressNotPresent));
+	ToFromAddressPtr()->ParsedAddress(aParsedAddress);
+	} // CSmsPDU::ParsedToFromAddress
+
+
+/**
+ *  Sets the "to from" with a TGsmSmsTelNumber object.
+ *  
+ *  @param aParsedAddress The destination or sender address
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetParsedToFromAddressL(const TGsmSmsTelNumber& aParsedAddress)
+	{
+	LOGGSMU1("CSmsPDU::SetParsedToFromAddressL()");
+
+	__ASSERT_DEBUG(ToFromAddressPtr()!=NULL,Panic(KGsmuPanicToFromAddressNotPresent));
+	CSmsAddress* tofromaddress=(CSmsAddress*) ToFromAddressPtr();
+	tofromaddress->SetParsedAddressL(aParsedAddress);
+	} // CSmsPDU::SetParsedToFromAddressL
+
+
+//
+//  TODO move this to the DCS descriptions
+//  Also, the functions available are dependant on bits 7 to 4 in the data coding scheme.
+//  Functions panic when they are not available.
+//  This requires the caller to have some knowledge of ETSI GSM 03.38 in order to keep the data coding scheme in a consistent state.
+//
+/**
+ *  Updates the three pieces of concatenation data (reference number,
+ *  pdu index and max pdu number) in this PDU.
+ * 
+ *  @param aRef       Reference number.
+ *  @param aPduIndex  Current PDU number.
+ *  @param aMaxPdu    Total PDU number.
+ */
+void CSmsPDU::UpdateConcatenationDataL(TInt aRef, TInt aPduIndex, TInt aMaxPdu)
+	{
+	LOGGSMU1("CSmsPDU::UpdateConcatenationDataL()");
+
+	SetConcatenatedMessageReference(aRef);
+	SetConcatenatedMessagePDUIndex(aPduIndex);
+	SetNumConcatenatedMessagePDUs(aMaxPdu);
+	} // CSmsPDU::UpdateConcatenationDataL
+
+
+/**
+ *  Updates the email header data in this PDU.
+ * 
+ *  @param aEmailOverallHeaderLength  Length of the email header.
+ */
+void CSmsPDU::UpdateEmailHeaderDataL(TInt& aEmailOverallHeaderLength)
+	{
+	LOGGSMU1("CSmsPDU::UpdateEmailHeaderDataL()");
+
+	TInt emailIndex(0);
+	TInt udLength=0;
+	TInt headerPortionLength=0;
+	if(UserData().InformationElementIndex(CSmsInformationElement::ESmsIEIRFC822EmailHeader,emailIndex))
+		{
+		if(aEmailOverallHeaderLength<=0)
+			headerPortionLength=0;
+		else
+			{
+			udLength=UserData().Body().Length();
+			if(Alphabet() == TSmsDataCodingScheme::ESmsAlphabetUCS2)
+				udLength/=2;
+			if(aEmailOverallHeaderLength>=udLength)
+				headerPortionLength=udLength;
+			else
+				headerPortionLength=aEmailOverallHeaderLength;
+			aEmailOverallHeaderLength-=udLength;
+			}
+		UserData().InformationElement(emailIndex).Data()[0]=static_cast<TUint8>(headerPortionLength);
+		}
+	else
+		User::Leave(KErrCorrupt);
+	} // CSmsPDU::UpdateEmailHeaderDataL
+
+	
+/**
+ *  Updates the SMSC control parameter in this PDU.
+ * 
+ *  @param aOctet  Value to store in the SMSC control parameter.
+ */
+TBool CSmsPDU::UpdateSMSCCtrlParameterL(const TUint8 aOctet)
+	{
+	TInt smscIndex(0);
+	if(UserData().InformationElementIndex(CSmsInformationElement::ESmsIEISMSCControlParameters,smscIndex))
+		{
+		UserData().InformationElement(smscIndex).Data()[0] = aOctet;
+		if (Type() == ESmsSubmit)
+			{
+			CSmsSubmit* smsSubmit = (CSmsSubmit*)this;
+			smsSubmit->SetStatusReportRequest(ETrue);	
+			}
+		else if (Type() == ESmsDeliver)
+			{
+			CSmsDeliver* smsDeliver = (CSmsDeliver*)this;
+			smsDeliver->SetStatusReportIndication(ETrue);
+			}
+		}
+	else
+		{
+		User::Leave(KErrCorrupt);	
+		} 
+
+	return ETrue;
+	} // CSmsPDU::UpdateSMSCCtrlParameterL
+
+	
+/**
+ *  Updates the TPSRRL control parameter in this PDU.
+ * 
+ *  @param aSmsReportRequest  Status Report Request setting.
+ * 
+ *  @return  Always returns ETrue.
+ */
+TBool CSmsPDU::UpdateTPSRRL(TSmsFirstOctet aSmsReportRequest)
+	{
+	if (Type() == ESmsSubmit)
+		{
+		CSmsSubmit* smsSubmit = (CSmsSubmit*)this;
+		if (aSmsReportRequest)
+			{
+			smsSubmit->SetStatusReportRequest(ETrue);
+			}
+		else
+			{
+			smsSubmit->SetStatusReportRequest(EFalse);	
+			}
+		}
+	else if (Type() == ESmsDeliver)
+			{
+			CSmsDeliver* smsDeliver = (CSmsDeliver*)this;
+			if (aSmsReportRequest)
+				{
+				smsDeliver->SetStatusReportIndication(ETrue);
+				}
+			else
+				{
+				smsDeliver->SetStatusReportIndication(EFalse);	
+				}
+			}
+	
+	return ETrue;
+	} // CSmsPDU::UpdateTPSRRL
+
+
+EXPORT_C TSmsEncoding CSmsPDU::NationalLanguageEncoding() const
+	{
+	LOGGSMU1("CSmsPDU::NationalLanguageEncoding()");
+	
+	TSmsEncoding  encodingUsed = ESmsEncodingNone;
+	
+	//
+	// Only valid in 7bit...
+	//
+	if (Alphabet() != TSmsDataCodingScheme::ESmsAlphabet7Bit)
+		{
+		return ESmsEncodingNone;
+		}
+	
+	//
+	// Get the locking shift setting...
+	//
+	TInt  lockingIndex = 0;
+	TSmsNationalLanguageIdentifier  lockingShiftValue  = (TSmsNationalLanguageIdentifier) 0;
+	
+	if (UserData().InformationElementLastIndex(CSmsInformationElement::ESmsNationalLanguageLockingShift, lockingIndex))
+		{
+		lockingShiftValue = (TSmsNationalLanguageIdentifier) UserData().InformationElement(lockingIndex).Data()[0];
+		
+		//
+		// Store the locking shift value. We will combine this with the single
+		// shift value later.
+		//
+		switch (lockingShiftValue)
+			{
+			case ESmsNationalLanguageIdentifierTurkish:
+				{
+				encodingUsed = ESmsEncodingTurkishLockingShift;
+				}
+				break;
+
+			case ESmsNationalLanguageIdentifierPortuguese:
+				{
+				encodingUsed = ESmsEncodingPortugueseLockingShift;
+				}
+				break;
+
+			default:
+				{
+				//
+				// Invalid or not understood, so ignore it!
+				//
+				}
+			};
+		}
+	
+	//
+	// Get the single shift setting...
+	//
+	TInt  singleIndex = 0;
+	TSmsNationalLanguageIdentifier  singleShiftValue  = (TSmsNationalLanguageIdentifier) 0;
+	
+	if (UserData().InformationElementLastIndex(CSmsInformationElement::ESmsNationalLanguageSingleShift, singleIndex))
+		{
+		singleShiftValue = (TSmsNationalLanguageIdentifier) UserData().InformationElement(singleIndex).Data()[0];
+		
+		//
+		// Combine the single shift value into the encoding setting. If any
+		// single shift does not match an accepted locking shift, then it is
+		// ignored as the locking table has more value.
+		//
+		switch (singleShiftValue)
+			{
+			case ESmsNationalLanguageIdentifierTurkish:
+				{
+				if (encodingUsed == ESmsEncodingNone)
+					{
+					encodingUsed = ESmsEncodingTurkishSingleShift;
+					}
+				else if (encodingUsed == ESmsEncodingTurkishLockingShift)
+					{
+					encodingUsed = ESmsEncodingTurkishLockingAndSingleShift;
+					}
+				}
+				break;
+
+			case ESmsNationalLanguageIdentifierSpanish:
+				{
+				if (encodingUsed == ESmsEncodingNone)
+					{
+					encodingUsed = ESmsEncodingSpanishSingleShift;
+					}
+				}
+				break;
+
+			case ESmsNationalLanguageIdentifierPortuguese:
+				{
+				if (encodingUsed == ESmsEncodingNone)
+					{
+					encodingUsed = ESmsEncodingPortugueseSingleShift;
+					}
+				else if (encodingUsed == ESmsEncodingPortugueseLockingShift)
+					{
+					encodingUsed = ESmsEncodingPortugueseLockingAndSingleShift;
+					}
+				}
+				break;
+
+			default:
+				{
+				//
+				// Invalid or not understood, so ignore it!
+				//
+				}
+			};
+		}
+	
+	LOGGSMU2("CSmsPDU::NationalLanguageEncoding(): lockingShift=%d", lockingShiftValue);
+	LOGGSMU2("CSmsPDU::NationalLanguageEncoding(): singleShift=%d", singleShiftValue);
+	LOGGSMU2("CSmsPDU::NationalLanguageEncoding(): encodingUsed=%d", encodingUsed);
+	
+	return encodingUsed;
+	} // CSmsPDU::NationalLanguageEncoding
+
+
+EXPORT_C void CSmsPDU::SetNationalLanguageEncodingL(TSmsEncoding aEncoding)
+	{
+	LOGGSMU2("CSmsPDU::SetNationalLanguageEncodingL(): aEncoding=%d", aEncoding);
+	
+	//
+	// Convert the encoding enum into two parts: Single Shift and Locking Shift
+	//
+	TSmsNationalLanguageIdentifier  lockingShiftValue = (TSmsNationalLanguageIdentifier) 0;
+	TSmsNationalLanguageIdentifier  singleShiftValue  = (TSmsNationalLanguageIdentifier) 0;
+	TBool  lockingIERequired = EFalse;
+	TBool  singleIERequired = EFalse;
+
+	switch (aEncoding)
+		{
+		case ESmsEncodingNone:
+			{
+			// Nothing to set.
+			}
+			break;
+		
+		case ESmsEncodingTurkishSingleShift:
+			{
+			singleShiftValue = ESmsNationalLanguageIdentifierTurkish;
+			singleIERequired = ETrue;
+			}
+			break;
+		
+		case ESmsEncodingTurkishLockingShift:
+			{
+			lockingShiftValue = ESmsNationalLanguageIdentifierTurkish;
+			lockingIERequired = ETrue;
+			}
+			break;
+		
+		case ESmsEncodingTurkishLockingAndSingleShift:
+			{
+			lockingShiftValue = ESmsNationalLanguageIdentifierTurkish;
+			singleShiftValue  = ESmsNationalLanguageIdentifierTurkish;
+			lockingIERequired = ETrue;
+			singleIERequired  = ETrue;
+			}
+			break;
+		
+		case ESmsEncodingSpanishSingleShift:
+			{
+			singleShiftValue = ESmsNationalLanguageIdentifierSpanish;
+			singleIERequired = ETrue;
+			}
+			break;
+		
+		case ESmsEncodingPortugueseSingleShift:
+			{
+			singleShiftValue = ESmsNationalLanguageIdentifierPortuguese;
+			singleIERequired = ETrue;
+			}
+			break;
+		
+		case ESmsEncodingPortugueseLockingShift:
+			{
+			lockingShiftValue = ESmsNationalLanguageIdentifierPortuguese;
+			lockingIERequired = ETrue;
+			}
+			break;
+		
+		case ESmsEncodingPortugueseLockingAndSingleShift:
+			{
+			lockingShiftValue = ESmsNationalLanguageIdentifierPortuguese;
+			singleShiftValue  = ESmsNationalLanguageIdentifierPortuguese;
+			lockingIERequired = ETrue;
+			singleIERequired  = ETrue;
+			}
+			break;
+
+		default:
+			{
+			//
+			// Invalid encoder method!
+			//
+			User::Leave(KErrArgument);
+			}
+		};
+	
+	LOGGSMU2("CSmsPDU::SetNationalLanguageEncodingL(): lockingShift=%d", lockingShiftValue);
+	LOGGSMU2("CSmsPDU::SetNationalLanguageEncodingL(): singleShift=%d", singleShiftValue);
+	
+	//
+	// Update the locking shift setting...
+	//
+	TInt  lockingIndex = 0;
+	TBool  lockingExists = UserData().InformationElementIndex(
+							CSmsInformationElement::ESmsNationalLanguageLockingShift, lockingIndex);
+	
+	if (lockingExists)
+		{
+		if (lockingIERequired)
+			{
+			// Update the IE...
+			UserData().InformationElement(lockingIndex).Data()[0] = (TUint8) lockingShiftValue;
+			}
+		else
+			{
+			// Remove the element as it is not needed...
+			UserData().RemoveInformationElement(lockingIndex);
+			}
+		}
+	else
+		{
+		if (lockingIERequired)
+			{
+			// Add the IE...
+			TBuf8<1> data;
+			data.SetLength(1);
+			data[0] = lockingShiftValue;
+			UserData().AddInformationElementL(CSmsInformationElement::ESmsNationalLanguageLockingShift, data);
+			}
+		else
+			{
+			// Nothing to do!
+			}
+		}
+
+	//
+	// Update the single shift setting...
+	//
+	TInt  singleIndex = 0;
+	TBool  singleExists = UserData().InformationElementIndex(
+							CSmsInformationElement::ESmsNationalLanguageSingleShift, singleIndex);
+	
+	if (singleExists)
+		{
+		if (singleIERequired)
+			{
+			// Update the IE...
+			UserData().InformationElement(singleIndex).Data()[0] = (TUint8) singleShiftValue;
+			}
+		else
+			{
+			// Remove the element as it is not needed...
+			UserData().RemoveInformationElement(singleIndex);
+			}
+		}
+	else
+		{
+		if (singleIERequired)
+			{
+			// Add the IE...
+			TBuf8<1> data;
+			data.SetLength(1);
+			data[0] = singleShiftValue;
+			UserData().AddInformationElementL(CSmsInformationElement::ESmsNationalLanguageSingleShift, data);
+			}
+		else
+			{
+			// Nothing to do!
+			}
+		}
+	} // CSmsPDU::SetNationalLanguageEncodingL
+
+
+/**
+ *  Gets bits 7 to 4 on the data coding scheme.
+ *  
+ *  The value of bits 7 to 4 effects the meaning of the lower order bits.
+ *  
+ *  The function panics if the data coding scheme is not present.
+ *  
+ *  @return Bits 7 to 4
+ *  @capability None
+ */
+EXPORT_C TSmsDataCodingScheme::TSmsDCSBits7To4 CSmsPDU::Bits7To4() const
+	{
+	LOGGSMU1("CSmsPDU::Bits7To4()");
+
+	__ASSERT_DEBUG(DataCodingScheme()!=NULL,Panic(KGsmuPanicDataCodingSchemeNotPresent));
+
+	return DataCodingScheme()->Bits7To4();
+	} // TSmsDataCodingScheme::TSmsDCSBits7To4
+
+
+/**
+ *  Sets key bits 7 to 4 of the data coding scheme.
+ *  
+ *  This is designed to be used for message waiting indication, as it is not needed
+ *  for the normal type of data coding scheme where the alphabet and class are
+ *  defined in the lower order bits.
+ *  
+ *  The function panics if the data coding scheme is not present.
+ *  
+ *  @param aBits7To4 Bits 7 to 4
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetBits7To4(TSmsDataCodingScheme::TSmsDCSBits7To4 aBits7To4)
+	{
+	LOGGSMU1("CSmsPDU::SetBits7To4()");
+
+	__ASSERT_DEBUG(DataCodingScheme()!=NULL,Panic(KGsmuPanicDataCodingSchemeNotPresent));
+	TSmsDataCodingScheme* datacodingscheme=(TSmsDataCodingScheme*) DataCodingScheme();
+	datacodingscheme->SetBits7To4(aBits7To4);
+	} // CSmsPDU::SetBits7To4
+
+
+/**
+ *  Gets the alphabet encoded in the data coding scheme.
+ *  
+ *  The function panics if the data coding scheme is not present.
+ *  
+ *  @return Alphabet
+ *  @capability None
+ */
+EXPORT_C TSmsDataCodingScheme::TSmsAlphabet CSmsPDU::Alphabet() const
+	{
+	LOGGSMU1("CSmsPDU::Alphabet()");
+
+	__ASSERT_DEBUG(DataCodingScheme()!=NULL,Panic(KGsmuPanicDataCodingSchemeNotPresent));
+	return DataCodingScheme()->Alphabet();
+	} // TSmsDataCodingScheme::TSmsAlphabet
+
+
+/**
+ *  Sets the alphabet encoded in the data coding scheme.
+ *  
+ *  The function panics if the data coding scheme is not present.
+ *  
+ *  @param aAlphabet Alphabet
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetAlphabet(TSmsDataCodingScheme::TSmsAlphabet aAlphabet)
+	{
+	LOGGSMU1("CSmsPDU::SetAlphabet()");
+
+	__ASSERT_DEBUG(DataCodingScheme()!=NULL,Panic(KGsmuPanicDataCodingSchemeNotPresent));
+	TSmsDataCodingScheme* datacodingscheme=(TSmsDataCodingScheme*) DataCodingScheme();
+	datacodingscheme->SetAlphabet(aAlphabet);
+	} // CSmsPDU::SetAlphabet
+
+
+/**
+ *  Gets the GSM SMS PDU class in the data coding scheme.
+ *  
+ *  The function panics if the data coding scheme is not present.
+ *  
+ *  @param aClass Sms class 0 - 3 encoded in the data coding scheme
+ *  @return True if SMS class is defined, else false
+ *  @capability None
+ */
+EXPORT_C TBool CSmsPDU::Class(TSmsDataCodingScheme::TSmsClass& aClass) const
+	{
+	LOGGSMU1("CSmsPDU::Class()");
+
+	__ASSERT_DEBUG(DataCodingScheme()!=NULL,Panic(KGsmuPanicDataCodingSchemeNotPresent));
+	return DataCodingScheme()->Class(aClass);
+	} // CSmsPDU::Class
+
+
+/**
+ *  Sets the GSM SMS PDU class in the data coding scheme.
+ *  
+ *  The function panics if the data coding scheme is not present.
+ *  
+ *  @param aClassDefined True if SMS class is defined, else false
+ *  @param aClass Sms class 0 - 3 encoded in the data coding scheme
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetClass(TBool aClassDefined,TSmsDataCodingScheme::TSmsClass aClass)
+	{
+	LOGGSMU1("CSmsPDU::SetClass()");
+
+	__ASSERT_DEBUG(DataCodingScheme()!=NULL,Panic(KGsmuPanicDataCodingSchemeNotPresent));
+	TSmsDataCodingScheme* datacodingscheme=(TSmsDataCodingScheme*) DataCodingScheme();
+	datacodingscheme->SetClass(aClassDefined,aClass);
+	} // CSmsPDU::SetClass
+
+
+/**
+ *  True if Text Compressed is encoded in the data coding scheme.
+ *  
+ *  The function panics if the data coding scheme is not present.
+ *  
+ *  @return True if Text Compressed is encoded
+ *  @capability None
+ */
+EXPORT_C TBool CSmsPDU::TextCompressed() const
+	{
+	LOGGSMU1("CSmsPDU::TextCompressed()");
+
+	__ASSERT_DEBUG(DataCodingScheme()!=NULL,Panic(KGsmuPanicDataCodingSchemeNotPresent));
+	return DataCodingScheme()->TextCompressed();
+	} // CSmsPDU::TextCompressed
+
+
+/**
+ *  Set to encode Text Compressed in the data coding scheme.
+ *  
+ *  The function panics if the data coding scheme is not present.
+ *  
+ *  @param aCompressed True to encode Text Compressed
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetTextCompressed(TBool aCompressed)
+	{
+	LOGGSMU1("CSmsPDU::SetTextCompressed()");
+
+	__ASSERT_DEBUG(DataCodingScheme()!=NULL,Panic(KGsmuPanicDataCodingSchemeNotPresent));
+	TSmsDataCodingScheme* datacodingscheme=(TSmsDataCodingScheme*) DataCodingScheme();
+	datacodingscheme->SetTextCompressed(aCompressed);
+	} // CSmsPDU::SetTextCompressed
+
+
+/**
+ *  Gets the Indication State encoded in the data coding scheme.
+ *  
+ *  The function panics if the data coding scheme is not present.
+ *  
+ *  @return Indication State
+ *  @capability None
+ */
+EXPORT_C TSmsDataCodingScheme::TSmsIndicationState CSmsPDU::IndicationState() const
+	{
+	LOGGSMU1("CSmsPDU::IndicationState()");
+
+	__ASSERT_DEBUG(DataCodingScheme()!=NULL,Panic(KGsmuPanicDataCodingSchemeNotPresent));
+	return DataCodingScheme()->IndicationState();
+	} // TSmsDataCodingScheme::TSmsIndicationState
+
+
+/**
+ *  Sets the Indication State encoded in the data coding scheme.
+ *  
+ *  The function panics if the data coding scheme is not present.
+ *  
+ *  @param aState Indication State
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetIndicationState(TSmsDataCodingScheme::TSmsIndicationState aState)
+	{
+	LOGGSMU1("CSmsPDU::SetIndicationState()");
+
+	__ASSERT_DEBUG(DataCodingScheme()!=NULL,Panic(KGsmuPanicDataCodingSchemeNotPresent));
+	TSmsDataCodingScheme* datacodingscheme=(TSmsDataCodingScheme*) DataCodingScheme();
+	datacodingscheme->SetIndicationState(aState);
+	} // CSmsPDU::SetIndicationState
+
+
+/**
+ *  Gets the Indication Type encoded in the data coding scheme.
+ *  
+ *  The function panics if the data coding scheme is not present.
+ *  
+ *  @return Indication Type
+ *  @capability None
+ */
+EXPORT_C TSmsDataCodingScheme::TSmsIndicationType CSmsPDU::IndicationType() const
+	{
+	LOGGSMU1("CSmsPDU::IndicationType()");
+
+	__ASSERT_DEBUG(DataCodingScheme()!=NULL,Panic(KGsmuPanicDataCodingSchemeNotPresent));
+	return DataCodingScheme()->IndicationType();
+	} // TSmsDataCodingScheme::TSmsIndicationType
+
+
+/**
+ *  Sets the Indication Type encoded in the data coding scheme.
+ *  
+ *  The function panics if the data coding scheme is not present.
+ *  
+ *  @param aType Indication Type
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetIndicationType(TSmsDataCodingScheme::TSmsIndicationType aType)
+	{
+	LOGGSMU1("CSmsPDU::SetIndicationType()");
+
+	__ASSERT_DEBUG(DataCodingScheme()!=NULL,Panic(KGsmuPanicDataCodingSchemeNotPresent));
+	TSmsDataCodingScheme* datacodingscheme=(TSmsDataCodingScheme*) DataCodingScheme();
+	datacodingscheme->SetIndicationType(aType);
+	} // CSmsPDU::SetIndicationType
+
+
+/**
+ *  Tests if the PDU is part of a concatenated message.
+ *  
+ *  @param aIs16Bit Content is set true if Concatenation Information Element is
+ *  16-bit. Default is null.
+ *  @return True if the PDU is part of a concatenated message.
+ *  @capability None
+ */
+EXPORT_C TBool CSmsPDU::TextConcatenated(TBool* aIs16Bit) const
+	{
+	LOGGSMU1("CSmsPDU::TextConcatenated()");
+
+	TInt index;
+	return DoTextConcatenated(index,aIs16Bit);
+	} // CSmsPDU::TextConcatenated
+
+
+/**
+ *  Sets whether the PDU is part of a concatenated message or not.
+ *  
+ *  It is a leaving function as it is inserting an information element into the
+ *  user data.
+ *  
+ *  @param aConcatenated True if message is concatenated
+ *  @param aIs16Bit True if type of Concatenation Information Element is 16 bit
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetTextConcatenatedL(TBool aConcatenated,TBool aIs16Bit)
+	{
+	LOGGSMU1("CSmsPDU::SetTextConcatenatedL()");
+
+	TInt index=0;
+	TInt is16bit;
+	TBool textconcatenated=DoTextConcatenated(index,&is16bit);
+	if (aConcatenated)
+		{
+		if (!textconcatenated)
+			{
+			DoSetTextConcatenatedL(aIs16Bit);
+			}
+		else
+			{
+			if (((!aIs16Bit) && (is16bit)) || (aIs16Bit && (!is16bit)))
+				{
+				UserData().RemoveInformationElement(index);
+				DoSetTextConcatenatedL(aIs16Bit);
+				}
+			}
+		}
+	else
+		{
+		if (textconcatenated)
+			{
+			UserData().RemoveInformationElement(index);
+			}
+		}
+	} // CSmsPDU::SetTextConcatenatedL
+
+
+/**
+ *  Gets the reference contained in the Concatenation Information Element.
+ *  
+ *  @return Reference contained in the Concatenation Information Element
+ *  @capability None
+ */
+EXPORT_C TInt CSmsPDU::ConcatenatedMessageReference() const
+	{
+	LOGGSMU1("CSmsPDU::ConcatenatedMessageReference()");
+
+	TInt index=0;
+	TBool is16bit;
+	TInt reference=0;
+	TBool textconcatenated=DoTextConcatenated(index,&is16bit);
+	__ASSERT_ALWAYS(textconcatenated,Panic(KGsmuPanicMessageNotConcatenated));
+	if (is16bit)
+		{
+		reference=UserData().InformationElement(index).Data()[0]<<8;
+		reference+=UserData().InformationElement(index).Data()[1];
+		}
+	else
+		reference=UserData().InformationElement(index).Data()[0];
+	return reference;
+	} // CSmsPDU::ConcatenatedMessageReference
+
+
+/**
+ *  Sets the reference contained in the Concatenation Information Element.
+ *  
+ *  The function panics if aReference is out of range for the message type.
+ *  
+ *  @param aReference Value to set the Concatenated Message Reference.
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetConcatenatedMessageReference(TInt aReference)
+	{
+	LOGGSMU1("CSmsPDU::SetConcatenatedMessageReference()");
+
+	TInt index=0;
+	TBool is16bit;
+	TBool textconcatenated=DoTextConcatenated(index,&is16bit);
+	__ASSERT_ALWAYS(textconcatenated,Panic(KGsmuPanicMessageNotConcatenated));
+	if (is16bit)
+		{
+		__ASSERT_DEBUG((aReference>=0x00) && (aReference<=0xFFFF),Panic(KGsmuPanicConcatenatedMessageReferenceOutOfRange));
+		UserData().InformationElement(index).Data()[0]=(TUint8) (aReference >> 8);
+		UserData().InformationElement(index).Data()[1]=(TUint8) aReference;
+		}
+	else
+		{
+		__ASSERT_DEBUG((aReference>=0x00) && (aReference<=0xFF),Panic(KGsmuPanicConcatenatedMessageReferenceOutOfRange));
+		UserData().InformationElement(index).Data()[0]=(TUint8) aReference;
+		}
+	} // CSmsPDU::SetConcatenatedMessageReference
+
+
+/**
+ *  Gets the number of PDU's in a Concatenated Message.
+ *  
+ *  The function panics if the PDU is not concatenated.
+ *  
+ *  @return Number of PDU's in a Concatenated Message
+ *  @capability None
+ */
+EXPORT_C TInt CSmsPDU::NumConcatenatedMessagePDUs() const
+	{
+	LOGGSMU1("CSmsPDU::NumConcatenatedMessagePDUs()");
+
+	TInt index=0;
+	TBool is16bit;
+	TBool textconcatenated=DoTextConcatenated(index,&is16bit);
+	__ASSERT_ALWAYS(textconcatenated,Panic(KGsmuPanicMessageNotConcatenated));
+	TInt offset=is16bit? 2: 1;
+	return UserData().InformationElement(index).Data()[offset];
+	} // CSmsPDU::NumConcatenatedMessagePDUs
+
+
+/**
+ *  Sets the number of PDU's in a Concatenated Message.
+ *  
+ *  The function panics if the PDU is not concatenated or if aNum is out of range.
+ *  
+ *  @param aNum Number of PDU's in a Concatenated Message
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetNumConcatenatedMessagePDUs(TInt aNum)
+	{
+	LOGGSMU1("CSmsPDU::SetNumConcatenatedMessagePDUs()");
+
+	TInt index=0;
+	TBool is16bit;
+	TBool textconcatenated=DoTextConcatenated(index,&is16bit);
+	__ASSERT_ALWAYS(textconcatenated,Panic(KGsmuPanicMessageNotConcatenated));
+	__ASSERT_DEBUG(((aNum>=0x01) && (aNum<=0xFF)),Panic(KGsmuPanicNumConcatenatedMessagePDUsOutOfRange));
+	TInt offset=is16bit? 2: 1;
+	UserData().InformationElement(index).Data()[offset]=(TUint8) aNum;
+	} // CSmsPDU::SetNumConcatenatedMessagePDUs
+
+
+/**
+ *  Gets the index of the PDU within the Concatenated Message.
+ *  
+ *  The function panics if the PDU is not concatenated.
+ *  
+ *  @return Index of the PDU within the Concatenated Message
+ *  @capability None
+ */
+EXPORT_C TInt CSmsPDU::ConcatenatedMessagePDUIndex() const
+	{
+	LOGGSMU1("CSmsPDU::ConcatenatedMessagePDUIndex()");
+
+	TInt index=0;
+	TBool is16bit;
+	TBool textconcatenated=DoTextConcatenated(index,&is16bit);
+	__ASSERT_ALWAYS(textconcatenated,Panic(KGsmuPanicMessageNotConcatenated));
+	TInt offset=is16bit? 3: 2;
+	return UserData().InformationElement(index).Data()[offset];
+	} // CSmsPDU::ConcatenatedMessagePDUIndex
+
+
+/**
+ *  Sets the index of the PDU within the Concatenated Message.
+ *  
+ *  The function panics if the PDU is not concatenated or aIndex is out of range.
+ *  
+ *  @param aIndex Index of the PDU within the Concatenated Message
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetConcatenatedMessagePDUIndex(TInt aIndex)
+	{
+	LOGGSMU1("CSmsPDU::SetConcatenatedMessagePDUIndex()");
+
+	TInt index=0;
+	TBool is16bit;
+	TBool textconcatenated=DoTextConcatenated(index,&is16bit);
+	__ASSERT_ALWAYS(textconcatenated,Panic(KGsmuPanicMessageNotConcatenated));
+	__ASSERT_DEBUG(((aIndex>=0x01) && (aIndex<=0xFF)),Panic(KGsmuPanicConcatenatedMessagePDUIndexOutOfRange));
+	TInt offset=is16bit? 3: 2;
+	UserData().InformationElement(index).Data()[offset]=(TUint8) aIndex;
+	} // CSmsPDU::SetConcatenatedMessagePDUIndex
+
+
+/**
+ *  Gets application port addressing information in the user data.
+ *  
+ *  @param aDestination The destination port address
+ *  @param aOriginator The originating port address
+ *  @param aIs16Bit Set to true if the addressing is 16 bit. Default is null.
+ *  @return True if there is an application port addressing information element
+ *  in the user data
+ *  @capability None
+ */
+EXPORT_C TBool CSmsPDU::ApplicationPortAddressing(TInt& aDestination,TInt& aOriginator,TBool* aIs16Bit) const
+	{
+	LOGGSMU1("CSmsPDU::ApplicationPortAddressing()");
+
+	TInt index;
+	return DoApplicationPortAddressing(index,aDestination,aOriginator,aIs16Bit);
+	} // CSmsPDU::ApplicationPortAddressing
+
+
+/**
+ *  Sets application port addressing information in the user data.
+ *  
+ *  @param aAddressing If true, set application port addressing in the PDU. If
+ *  false, removes addressing if it's already set
+ *  @param aDestination The destination port address to set in the PDU
+ *  @param aOriginator The originating port address to set in the PDU
+ *  @param aIs16Bit True if the addresses are 16 bit, false if 8 bit
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetApplicationPortAddressingL(TBool aAddressing,TInt aDestination,TInt aOriginator,TBool aIs16Bit)
+	{
+	LOGGSMU1("CSmsPDU::SetApplicationPortAddressingL()");
+
+	TInt index=0;
+	TInt is16bit;
+	TBool addressing=DoApplicationPortAddressing(index,aDestination,aOriginator,&is16bit);
+	if (aAddressing)
+		{
+		if (!addressing)
+			{
+			DoSetApplicationPortAddressingL(aDestination,aOriginator,aIs16Bit);
+			}
+		else
+			{
+			if (((!aIs16Bit) && (is16bit)) || (aIs16Bit && (!is16bit)))
+				{
+				UserData().RemoveInformationElement(index);
+				DoSetApplicationPortAddressingL(aDestination,aOriginator,aIs16Bit);
+				}
+			}
+		}
+	else
+		{
+		if (addressing)
+			{
+			UserData().RemoveInformationElement(index);
+			}
+		}
+	} // CSmsPDU::SetApplicationPortAddressingL
+
+
+/**
+ *  Gets key bits 7 and 6 of the PID field.
+ *  
+ *  @return Bits 7 and 6 of the PID field
+ *  @capability None
+ */
+EXPORT_C TSmsProtocolIdentifier::TSmsPIDType CSmsPDU::PIDType() const
+	{
+	LOGGSMU1("CSmsPDU::PIDType()");
+
+	__ASSERT_DEBUG(ProtocolIdentifier()!=NULL,Panic(KGsmuPanicProtocolIdentifierNotPresent));
+	return ProtocolIdentifier()->PIDType();
+	} // TSmsProtocolIdentifier::TSmsPIDType
+
+
+/**
+ *  Sets key bits 7 and 6 of the PID field.
+ *  
+ *  @param aSmsPIDType Bits 7 and 6 of the PID field
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetPIDType(TSmsProtocolIdentifier::TSmsPIDType aSmsPIDType)
+	{
+	LOGGSMU1("CSmsPDU::SetPIDType()");
+
+	__ASSERT_DEBUG(ProtocolIdentifier()!=NULL,Panic(KGsmuPanicProtocolIdentifierNotPresent));
+	TSmsProtocolIdentifier* protocolidentifier=(TSmsProtocolIdentifier*) ProtocolIdentifier();
+	protocolidentifier->SetPIDType(aSmsPIDType);
+	} // CSmsPDU::SetPIDType
+
+
+/**
+ *  Gets the Telematic device indicator from the PID field.
+ *  
+ *  @return Telematic device indicator
+ *  @capability None
+ */
+EXPORT_C TSmsProtocolIdentifier::TSmsTelematicDeviceIndicator CSmsPDU::TelematicDeviceIndicator() const
+	{
+	LOGGSMU1("CSmsPDU::TelematicDeviceIndicator()");
+
+	__ASSERT_DEBUG(ProtocolIdentifier()!=NULL,Panic(KGsmuPanicProtocolIdentifierNotPresent));
+	return ProtocolIdentifier()->TelematicDeviceIndicator();
+	} // TSmsProtocolIdentifier::TSmsTelematicDeviceIndicator
+
+
+/**
+ *  Sets the Telematic device indicator from the PID field.
+ *  
+ *  @param aIndicator Telematic device indicator
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetTelematicDeviceIndicator(TSmsProtocolIdentifier::TSmsTelematicDeviceIndicator aIndicator)
+	{
+	LOGGSMU1("CSmsPDU::SetTelematicDeviceIndicator()");
+
+	__ASSERT_DEBUG(ProtocolIdentifier()!=NULL,Panic(KGsmuPanicProtocolIdentifierNotPresent));
+	TSmsProtocolIdentifier* protocolidentifier=(TSmsProtocolIdentifier*) ProtocolIdentifier();
+	protocolidentifier->SetTelematicDeviceIndicator(aIndicator);
+	} // CSmsPDU::SetTelematicDeviceIndicator
+
+
+/**
+ *  Gets the Short Message Type in the PID field.
+ *  
+ *  @return Short Message Type
+ *  @capability None
+ */
+EXPORT_C TSmsProtocolIdentifier::TSmsShortMessageType CSmsPDU::ShortMessageType() const
+	{
+	LOGGSMU1("CSmsPDU::ShortMessageType()");
+
+	__ASSERT_DEBUG(ProtocolIdentifier()!=NULL,Panic(KGsmuPanicProtocolIdentifierNotPresent));
+	return (TSmsProtocolIdentifier::TSmsShortMessageType) ProtocolIdentifier()->ShortMessageType();
+	} // TSmsProtocolIdentifier::TSmsShortMessageType
+
+
+/**
+ *  Sets the Short Message Type in the PID field.
+ *  
+ *  @param aShortMessageType Short Message Type
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetShortMessageType(TSmsProtocolIdentifier::TSmsShortMessageType aShortMessageType)
+	{
+	LOGGSMU1("CSmsPDU::SetShortMessageType()");
+
+	__ASSERT_DEBUG(ProtocolIdentifier()!=NULL,Panic(KGsmuPanicProtocolIdentifierNotPresent));
+	TSmsProtocolIdentifier* protocolidentifier=(TSmsProtocolIdentifier*) ProtocolIdentifier();
+	protocolidentifier->SetShortMessageType(aShortMessageType);
+	} // CSmsPDU::SetShortMessageType
+
+
+/**
+ *  Gets the Telematic device type in the PID field.
+ *  
+ *  @return Telematic device type
+ *  @capability None
+ */
+EXPORT_C TSmsProtocolIdentifier::TSmsTelematicDeviceType CSmsPDU::TelematicDeviceType() const
+	{
+	LOGGSMU1("CSmsPDU::TelematicDeviceType()");
+
+	__ASSERT_DEBUG(ProtocolIdentifier()!=NULL,Panic(KGsmuPanicProtocolIdentifierNotPresent));
+	return ProtocolIdentifier()->TelematicDeviceType();
+	} // TSmsProtocolIdentifier::TSmsTelematicDeviceType
+
+
+/**
+ *  Sets the Telematic device type in the PID field.
+ *  
+ *  @param aDeviceType Telematic device type
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetTelematicDeviceType(TSmsProtocolIdentifier::TSmsTelematicDeviceType aDeviceType)
+	{
+	LOGGSMU1("CSmsPDU::SetTelematicDeviceType()");
+
+	__ASSERT_DEBUG(ProtocolIdentifier()!=NULL,Panic(KGsmuPanicProtocolIdentifierNotPresent));
+	TSmsProtocolIdentifier* protocolidentifier=(TSmsProtocolIdentifier*) ProtocolIdentifier();
+	protocolidentifier->SetTelematicDeviceType(aDeviceType);
+	} // CSmsPDU::SetTelematicDeviceType
+
+
+/**
+ *  Tests if the User Data Header Indicator is set.
+ *  
+ *  It panics if PDU type is unsupported.
+ *  
+ *  @return True if the User Data Header Indicator is set
+ *  @capability None
+ */
+EXPORT_C TBool CSmsPDU::UserDataPresent() const
+	{
+	LOGGSMU1("CSmsPDU::UserDataPresent()");
+
+	TBool udPresent=ETrue;
+	switch (iSmsPDUType)
+		{
+		case ESmsDeliver:
+		case ESmsSubmit:
+			break;
+		case ESmsDeliverReport:
+		case ESmsSubmitReport:
+			udPresent=ParameterIndicator()->UserDataPresent();
+			break;
+		case ESmsStatusReport:
+			udPresent=((CSmsStatusReport*)this)->ParameterIndicatorPresent()
+				&& ParameterIndicator()->UserDataPresent();
+			break;
+		default:
+			Panic(KGsmuPanicUnsupportedPduType);
+		}
+	return udPresent;
+	} // CSmsPDU::UserDataPresent
+
+
+/**
+ *  Sets or unsets the User Data Header Indicator.
+ *  
+ *  It panics if PDU type is unsupported.
+ *  
+ *  @param aPresent True to set the User Data Header Indicator
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetUserDataPresent(TBool aPresent)
+	{
+	LOGGSMU2("CSmsPDU::SetUserDataPresent(): aPresent=%d", aPresent);
+
+	__ASSERT_DEBUG(ParameterIndicator()!=NULL,Panic(KGsmuPanicParameterIndicatorNotPresent));
+	TSmsParameterIndicator* parameterindicator=(TSmsParameterIndicator*) ParameterIndicator();
+	parameterindicator->SetUserDataPresent(aPresent);
+	} // CSmsPDU::SetUserDataPresent
+
+
+/**
+ *  Tests if data coding scheme is present.
+ *  
+ *  Panics if PDU type is unsupported.
+ *  
+ *  @return True if data coding scheme is present
+ *  @capability None
+ */
+EXPORT_C TBool CSmsPDU::DataCodingSchemePresent() const
+	{
+	LOGGSMU1("CSmsPDU::DataCodingSchemePresent()");
+
+	TBool dcsPresent=ETrue;
+	switch (iSmsPDUType)
+		{
+		case ESmsDeliver:
+		case ESmsSubmit:
+			break;
+		case ESmsDeliverReport:
+		case ESmsSubmitReport:
+			dcsPresent=ParameterIndicator()->DataCodingSchemePresent();
+			break;
+		case ESmsStatusReport:
+			dcsPresent=((CSmsStatusReport*)this)->ParameterIndicatorPresent()
+				&& ParameterIndicator()->DataCodingSchemePresent();
+			break;
+		case ESmsCommand:
+			dcsPresent=EFalse;
+			break;
+		default:
+			Panic(KGsmuPanicUnsupportedPduType);
+		}
+	return dcsPresent;
+	} // CSmsPDU::DataCodingSchemePresent
+
+
+/**
+ *  Sets if data coding scheme is present.
+ *  
+ *  @param aPresent True if data coding scheme is present
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetDataCodingSchemePresent(TBool aPresent)
+	{
+	LOGGSMU2("CSmsPDU::SetDataCodingSchemePresent(): aPresent=%d", aPresent);
+
+	__ASSERT_DEBUG(ParameterIndicator()!=NULL,Panic(KGsmuPanicParameterIndicatorNotPresent));
+	TSmsParameterIndicator* parameterindicator=(TSmsParameterIndicator*) ParameterIndicator();
+	parameterindicator->SetDataCodingSchemePresent(aPresent);
+	} // CSmsPDU::SetDataCodingSchemePresent
+
+
+/**
+ *  Tests if Protocol Identifier is present.
+ *  
+ *  It panics if the PDU type is unsupported.
+ *  
+ *  @return True if Protocol Identifier is present
+ *  @capability None
+ */
+EXPORT_C TBool CSmsPDU::ProtocolIdentifierPresent() const
+	{
+	LOGGSMU1("CSmsPDU::ProtocolIdentifierPresent()");
+
+	TBool pidPresent=ETrue;
+	switch (iSmsPDUType)
+		{
+		case ESmsDeliver:
+		case ESmsSubmit:
+		case ESmsCommand:
+			break;
+		case ESmsDeliverReport:
+		case ESmsSubmitReport:
+			pidPresent=ParameterIndicator()->ProtocolIdentifierPresent();
+			break;
+		case ESmsStatusReport:
+			pidPresent=((CSmsStatusReport*)this)->ParameterIndicatorPresent()
+				&& ParameterIndicator()->ProtocolIdentifierPresent();
+			break;
+		default:
+			Panic(KGsmuPanicUnsupportedPduType);
+		}
+	return pidPresent;
+	} // CSmsPDU::ProtocolIdentifierPresent
+
+
+/**
+ *  Sets if Protocol Identifier is present.
+ *  
+ *  It panics if the PDU type is unsupported.
+ *  
+ *  @param aPresent True if Protocol Identifier is present
+ *  @capability None
+ */
+EXPORT_C void CSmsPDU::SetProtocolIdentifierPresent(TBool aPresent)
+	{
+	LOGGSMU2("CSmsPDU::SetProtocolIdentifierPresent(): aPresent=%d", aPresent);
+
+	__ASSERT_DEBUG(ParameterIndicator()!=NULL,Panic(KGsmuPanicParameterIndicatorNotPresent));
+	TSmsParameterIndicator* parameterindicator=(TSmsParameterIndicator*) ParameterIndicator();
+	parameterindicator->SetProtocolIdentifierPresent(aPresent);
+	} // CSmsPDU::SetProtocolIdentifierPresent
+
+
+/**
+ *  
+ *  Gets User Data (non-const).
+ *  
+ *  @return User Data
+ *  @capability None
+ */
+EXPORT_C CSmsUserData& CSmsPDU::UserData()
+	{
+	LOGGSMU1("CSmsPDU::UserData()");
+
+	__ASSERT_DEBUG(UserDataPtr()!=NULL,Panic(KGsmuPanicUserDataNotPresent));
+	CSmsUserData* userdata=(CSmsUserData*) UserDataPtr();
+	return *userdata;
+	} // CSmsPDU::UserData
+
+
+/**
+ *  Gets User Data (const).
+ *  
+ *  @return User Data
+ *  @capability None
+ */
+EXPORT_C const CSmsUserData& CSmsPDU::UserData() const
+	{
+	LOGGSMU1("CSmsPDU::UserData()");
+
+	__ASSERT_DEBUG(UserDataPtr()!=NULL,Panic(KGsmuPanicUserDataNotPresent));
+	return *UserDataPtr();
+	} // CSmsPDU::UserData
+
+
+CSmsPDU::CSmsPDU(TSmsPDUType aSmsPDUType):
+	iSmsPDUType(aSmsPDUType)
+	{
+	// NOP
+	} // CSmsPDU::CSmsPDU
+
+
+const TSmsDataCodingScheme* CSmsPDU::DataCodingScheme() const
+    {
+    // Ignore in code coverage - for PDUs that are meant to have a DCS
+    // this method is overridden; the base class implementation is not
+    // intended to be used.
+    BULLSEYE_OFF
+    return NULL;
+    BULLSEYE_RESTORE
+    }
+
+const TSmsProtocolIdentifier* CSmsPDU::ProtocolIdentifier() const
+    {
+    // Ignore in code coverage - for PDUs that are meant to have a PID
+    // this method is overridden; the base class implementation is not
+    // intended to be used.
+    BULLSEYE_OFF
+    return NULL;
+    BULLSEYE_RESTORE
+    }
+
+const TSmsParameterIndicator* CSmsPDU::ParameterIndicator() const
+    {
+    // Ignore in code coverage - for PDUs that are meant to have a PI
+    // this method is overridden; the base class implementation is not
+    // intended to be used.
+    BULLSEYE_OFF
+    return NULL;
+    BULLSEYE_RESTORE
+    }
+
+const CSmsUserData* CSmsPDU::UserDataPtr() const
+    {
+    // Ignore in code coverage - for PDUs that are meant to have a UD
+    // this method is overridden; the base class implementation is not
+    // intended to be used.
+    BULLSEYE_OFF
+    return NULL;
+    BULLSEYE_RESTORE
+    }
+
+const CSmsAddress* CSmsPDU::ToFromAddressPtr() const
+    {
+    return NULL;
+    }
+
+TBool CSmsPDU::DoTextConcatenated(TInt& aIndex,TBool* aIs16Bit) const
+	{
+	LOGGSMU1("CSmsPDU::DoTextConcatenated()");
+
+	TBool is8bit=UserData().InformationElementIndex(CSmsInformationElement::ESmsIEIConcatenatedShortMessages8BitReference,aIndex);
+	TBool is16bit=EFalse;
+	if (!is8bit)
+		is16bit=UserData().InformationElementIndex(CSmsInformationElement::ESmsIEIConcatenatedShortMessages16BitReference,aIndex);
+	if (aIs16Bit!=NULL)
+		*aIs16Bit=is16bit;
+	return is8bit || is16bit;
+	} // CSmsPDU::DoTextConcatenated
+
+
+void CSmsPDU::DoSetTextConcatenatedL(TBool aIs16Bit)
+	{
+	LOGGSMU2("CSmsPDU::DoSetTextConcatenatedL(): aIs16Bit=%d", aIs16Bit);
+
+	if (!aIs16Bit)
+		{
+		TBuf8<3> data;
+		data.SetLength(3);
+		data[0]=1;
+		data[1]=1;
+		data[2]=1;
+		UserData().AddInformationElementL(CSmsInformationElement::ESmsIEIConcatenatedShortMessages8BitReference,data);
+		}
+	else
+		{
+		TBuf8<4> data;
+		data.SetLength(4);
+		data[0]=0;
+		data[1]=1;
+		data[2]=1;
+		data[3]=1;
+		UserData().AddInformationElementL(CSmsInformationElement::ESmsIEIConcatenatedShortMessages16BitReference,data);
+		}
+	} // CSmsPDU::DoSetTextConcatenatedL
+
+
+TBool CSmsPDU::DoApplicationPortAddressing(TInt& aIndex,TInt& aDestination,TInt& aOriginator,TBool* aIs16Bit) const
+	{
+	LOGGSMU1("CSmsPDU::DoApplicationPortAddressing()");
+
+	TBool is8bit=UserData().InformationElementIndex(CSmsInformationElement::ESmsIEIApplicationPortAddressing8Bit,aIndex);
+	TBool is16bit=EFalse;
+	if (is8bit)
+		{
+		TPtr8 data=UserData().InformationElement(aIndex).Data();
+		aDestination=data[0];
+		aOriginator=data[1];
+		}
+	else
+		{
+		is16bit=UserData().InformationElementIndex(CSmsInformationElement::ESmsIEIApplicationPortAddressing16Bit,aIndex);
+		if (is16bit)
+			{
+			TPtr8 data=UserData().InformationElement(aIndex).Data();
+			aDestination=data[0]<<8;
+			aDestination+=data[1];
+			aOriginator=data[2]<<8;
+			aOriginator+=data[3];
+			}
+		}
+	if (aIs16Bit!=NULL)
+		*aIs16Bit=is16bit;
+	return is8bit || is16bit;
+	} // CSmsPDU::DoApplicationPortAddressing
+
+
+void CSmsPDU::DoSetApplicationPortAddressingL(TInt aDestination,TInt aOriginator,TBool aIs16Bit)
+	{
+	LOGGSMU4("CSmsPDU::DoSetApplicationPortAddressingL(): aDestination=%d, aOriginator=%d, aIs16Bit=%d",
+			 aDestination, aOriginator, aIs16Bit);
+
+	if (!aIs16Bit)
+		{
+		__ASSERT_ALWAYS((aDestination>=0x00) && (aDestination<=0xFF) && (aOriginator>=0x00) && (aOriginator<=0xFF),Panic(KGsmuPanicPortOutOfRange));
+		TBuf8<2> data;
+		data.SetLength(2);
+		data[0]=(TUint8) aDestination;
+		data[1]=(TUint8) aOriginator;
+		UserData().AddInformationElementL(CSmsInformationElement::ESmsIEIApplicationPortAddressing8Bit,data);
+		}
+	else
+		{
+		__ASSERT_ALWAYS((aDestination>=0x00) && (aDestination<=0xFFFF) && (aOriginator>=0x00) && (aOriginator<=0xFFFF),Panic(KGsmuPanicPortOutOfRange));
+		TBuf8<4> data;
+		data.SetLength(4);
+		data[0]=(TUint8) (aDestination>>8);
+		data[1]=(TUint8) aDestination;
+		data[2]=(TUint8) (aOriginator>>8);
+		data[3]=(TUint8) aOriginator;
+		UserData().AddInformationElementL(CSmsInformationElement::ESmsIEIApplicationPortAddressing16Bit,data);
+		}
+	} // CSmsPDU::DoSetApplicationPortAddressingL
+
+
+CSmsDeliver::CSmsDeliver():
+	CSmsPDU(ESmsDeliver),
+	iFirstOctet(TSmsFirstOctet::ESmsMTIDeliverOrDeliverReport)
+	{
+	//NOP
+	} // TSmsFirstOctet::ESmsMTIDeliverOrDeliverReport
+
+
+/**
+ *  Gets More Messages to Send flag.
+ *  
+ *  @return True if More Messages to Send flag set
+ *  @capability None
+ */
+EXPORT_C TBool CSmsDeliver::MoreMessagesToSend() const
+	{
+	LOGGSMU1("CSmsDeliver::MoreMessagesToSend");
+
+	return (iFirstOctet&TSmsFirstOctet::ESmsMoreMessagesToSendMask)==TSmsFirstOctet::ESmsMoreMessagesToSend;
+	} // CSmsDeliver::MoreMessagesToSend
+
+
+/**
+ *  Sets More Messages to Send flag.
+ *  
+ *  @param aMore True if More Messages to Send
+ *  @capability None
+ */
+EXPORT_C void CSmsDeliver::SetMoreMessagesToSend(TBool aMore)
+	{
+	LOGGSMU2("CSmsDeliver::SetMoreMessagesToSend(): aMore=%d", aMore);
+
+	iFirstOctet=aMore? (iFirstOctet&(~TSmsFirstOctet::ESmsMoreMessagesToSendMask)|TSmsFirstOctet::ESmsMoreMessagesToSend):
+	                   (iFirstOctet&(~TSmsFirstOctet::ESmsMoreMessagesToSendMask)|TSmsFirstOctet::ESmsNoMoreMessagesToSend);
+	} // CSmsDeliver::SetMoreMessagesToSend
+
+
+/**
+ *  Gets Reply Path flag.
+ *  
+ *  If a reply path exists, the service center encoded in the DELIVER can be used
+ *  to construct a SUBMIT reply.
+ *  
+ *  @return True if Reply Path exists
+ *  @capability None
+ */
+EXPORT_C TBool CSmsDeliver::ReplyPath() const
+	{
+	LOGGSMU1("CSmsDeliver::ReplyPath");
+
+	return (iFirstOctet&TSmsFirstOctet::ESmsReplyPathMask)==TSmsFirstOctet::ESmsReplyPathExists;
+	} // CSmsDeliver::ReplyPath
+
+
+/**
+ *  Sets Reply Path flag.
+ *  
+ *  @param aReplyPath True to set Reply Path
+ *  @capability None
+ */
+EXPORT_C void CSmsDeliver::SetReplyPath(TBool aReplyPath)
+	{
+	LOGGSMU2("CSmsDeliver::SetReplyPath(): aReplyPath=%d", aReplyPath);
+
+	iFirstOctet=aReplyPath? (iFirstOctet&(~TSmsFirstOctet::ESmsReplyPathMask)|TSmsFirstOctet::ESmsReplyPathExists):
+	                        (iFirstOctet&(~TSmsFirstOctet::ESmsReplyPathMask)|TSmsFirstOctet::ESmsReplyPathNone);
+	} // CSmsDeliver::SetReplyPath
+
+
+/**
+ *  Gets Status Report flag.
+ *  
+ *  @return True if Status Report to be returned.
+ *  @capability None
+ */
+EXPORT_C TBool CSmsDeliver::StatusReportIndication() const
+	{
+	LOGGSMU1("CSmsDeliver::StatusReportIndication");
+
+	return (iFirstOctet&TSmsFirstOctet::ESmsStatusReportIndicatorMask)==TSmsFirstOctet::ESmsStatusReportReturned;
+	} // CSmsDeliver::StatusReportIndication
+
+
+/**
+ *  Sets Status Report flag.
+ *  
+ *  @param aIndication Set True to request Status Report
+ *  @capability None
+ */
+EXPORT_C void CSmsDeliver::SetStatusReportIndication(TBool aIndication)
+	{
+	LOGGSMU2("CSmsDeliver::SetStatusReportIndication(): aIndication=%d", aIndication);
+
+	iFirstOctet=aIndication? (iFirstOctet&(~TSmsFirstOctet::ESmsStatusReportIndicatorMask)|TSmsFirstOctet::ESmsStatusReportReturned):
+	                         (iFirstOctet&(~TSmsFirstOctet::ESmsStatusReportIndicatorMask)|TSmsFirstOctet::ESmsStatusReportNotReturned);
+	} // CSmsDeliver::SetStatusReportIndication
+
+
+/**
+ *  Destructor.
+ */
+CSmsDeliver::~CSmsDeliver()
+	{
+	delete iServiceCenterAddress;
+	delete iOriginalAddress;
+	delete iUserData;
+	} // CSmsDeliver::SetStatusReportIndication
+
+
+/**
+ *  Gets Service Center Time Stamp.
+ *  
+ *  @param aTime Service Center Time Stamp represented in Universal Time
+ *  @param aNumQuarterHours +/- Time Zone difference to GMT in quarter hours
+ *  @capability None
+ */
+EXPORT_C void CSmsDeliver::ServiceCenterTimeStamp(TTime& aTime,TInt& aNumQuarterHours)
+	{
+	LOGGSMU1("CSmsDeliver::ServiceCenterTimeStamp()");
+
+	aTime=iServiceCenterTimeStamp.Time();
+	aNumQuarterHours=iServiceCenterTimeStamp.TimeOffset();
+	} // CSmsDeliver::ServiceCenterTimeStamp
+
+
+/**
+ *  Sets Service Center Time Stamp.
+ *  
+ *  @param aTime Service Center Time Stamp represented in Universal Time
+ *  @param aNumQuarterHours +/- Time Zone difference to GMT in quarter hours
+ *  @capability None
+ */
+EXPORT_C void CSmsDeliver::SetServiceCenterTimeStamp(const TTime& aTime,TInt aNumQuarterHours)
+	{
+	LOGGSMU2("CSmsDeliver::ServiceCenterTimeStamp(): aNumQuarterHours=%d", aNumQuarterHours);
+
+	iServiceCenterTimeStamp.SetTime(aTime);
+	iServiceCenterTimeStamp.SetTimeOffset(aNumQuarterHours);
+	} // CSmsDeliver::SetServiceCenterTimeStamp
+
+
+void CSmsDeliver::ConstructL(CCnvCharacterSetConverter& aCharacterSetConverter,RFs& aFs)
+	{
+	LOGGSMU1("CSmsDeliver::ConstructL()");
+
+	iServiceCenterAddress=CSmsAddress::NewL(aCharacterSetConverter,aFs);
+	iOriginalAddress=CSmsAddress::NewL(aCharacterSetConverter,aFs);
+	iUserData=CSmsUserData::NewL(aCharacterSetConverter,aFs,iFirstOctet,iDataCodingScheme);
+	} // CSmsDeliver::ConstructL
+
+
+/**
+ *  Duplicates this CSmsDeliver object.
+ * 
+ *  @return  Pointer to the newly created CSmsDeliver object.
+ */
+EXPORT_C CSmsDeliver* CSmsDeliver::DuplicateL() const
+	{
+	LOGGSMU1("CSmsDeliver::DuplicateL()");
+
+	CSmsDeliver*  smsDeliver = new (ELeave) CSmsDeliver();
+	CleanupStack::PushL(smsDeliver);
+
+	smsDeliver->iServiceCenterAddress   = iServiceCenterAddress->DuplicateL();
+	smsDeliver->iFirstOctet             = iFirstOctet;
+	smsDeliver->iOriginalAddress        = iOriginalAddress->DuplicateL();
+	smsDeliver->iProtocolIdentifier     = iProtocolIdentifier;
+	smsDeliver->iDataCodingScheme       = iDataCodingScheme;
+	smsDeliver->iServiceCenterTimeStamp = iServiceCenterTimeStamp;
+	smsDeliver->iUserData               = iUserData->DuplicateL(smsDeliver->iFirstOctet,
+																smsDeliver->iDataCodingScheme);
+
+	CleanupStack::Pop(smsDeliver);
+
+	return smsDeliver;
+	} // CSmsDeliver::DuplicateL
+
+
+TUint8* CSmsDeliver::EncodeL(TUint8* aPtr) const
+	{
+	LOGGSMU1("CSmsDeliver::EncodeL()");
+
+	aPtr=iFirstOctet.EncodeL(aPtr);
+	aPtr=iOriginalAddress->EncodeL(aPtr);
+	aPtr=iProtocolIdentifier.EncodeL(aPtr);
+	aPtr=iDataCodingScheme.EncodeL(aPtr);
+	aPtr=iServiceCenterTimeStamp.EncodeL(aPtr);
+	return iUserData->EncodeL(aPtr);
+	} // CSmsDeliver::EncodeL
+
+TUint8* CSmsDeliver::EncodeL(TUint8* aPtr, const TEncodeParams* ) const
+	{
+	return EncodeL(aPtr);		
+	}	
+
+void CSmsDeliver::DecodeL(TGsmuLex8& aPdu)
+	{
+	LOGGSMU1("CSmsDeliver::DecodeL()");
+
+	iFirstOctet.DecodeL(aPdu);
+	iOriginalAddress->DecodeL(aPdu);
+	iProtocolIdentifier.DecodeL(aPdu);
+	iDataCodingScheme.DecodeL(aPdu);
+	TInt bit7to4=iDataCodingScheme.Bits7To4();
+	TInt lowerLimit = TSmsDataCodingScheme::ESmsDCSReserved5;
+	TInt upperLimit = TSmsDataCodingScheme::ESmsDCSReserved8;
+	if ((bit7to4>=lowerLimit) &&
+	    (bit7to4<=upperLimit))
+		User::Leave(KErrGsmSMSUnspecifiedDCSError);
+
+	TInt timeError = KErrNone;
+	iServiceCenterTimeStamp.DecodeL(aPdu, timeError);  //  Review, fix for bug
+	if (timeError != KErrNone)
+		{
+		TTime time;
+		time.UniversalTime();
+		iServiceCenterTimeStamp.SetTime(time);
+		iServiceCenterTimeStamp.SetTimeOffset((User::UTCOffset().Int()) / CSmsMessage::E15MinutesRepresentedInSeconds);
+		}
+
+	iUserData->DecodeL(aPdu);
+	} // CSmsDeliver::DecodeL
+
+
+void CSmsDeliver::InternalizeMessagePDUL(RReadStream& aStream)
+	{
+	LOGGSMU1("CSmsDeliver::InternalizeMessagePDUL()");
+
+	iServiceCenterAddress->InternalizeL(aStream);
+
+	aStream >> iFirstOctet;
+	iOriginalAddress->InternalizeL(aStream);
+/*	TUint8 tmp;
+	aStream >> tmp;
+	SetMessageConversion((TSmsProtocolIdentifier::TSmsPIDConversion)tmp);
+*/	aStream >> iProtocolIdentifier;
+	aStream >> iDataCodingScheme;
+	aStream >> iServiceCenterTimeStamp;
+
+	aStream >> *iUserData;
+	} // CSmsDeliver::InternalizeMessagePDUL
+
+
+void CSmsDeliver::ExternalizeMessagePDUL(RWriteStream& aStream) const
+	{
+	LOGGSMU1("CSmsDeliver::ExternalizeMessagePDUL()");
+
+	iServiceCenterAddress->ExternalizeL(aStream);
+
+	aStream << iFirstOctet;
+	iOriginalAddress->ExternalizeL(aStream);
+/*	TSmsProtocolIdentifier::TSmsPIDConversion tmp;
+	tmp=MessageConversion();
+	aStream << (TUint8)tmp;
+*/	aStream << iProtocolIdentifier;
+	aStream << iDataCodingScheme;
+	aStream << iServiceCenterTimeStamp;
+
+	aStream << *iUserData;
+	} // CSmsDeliver::ExternalizeMessagePDUL
+
+
+const TSmsDataCodingScheme* CSmsDeliver::DataCodingScheme() const
+	{
+	LOGGSMU1("CSmsDeliver::DataCodingScheme()");
+
+	return &iDataCodingScheme;
+	} // CSmsDeliver::DataCodingScheme
+
+
+/**
+ *  Gets the Deliver PID field.
+ *  
+ *  @return The Deliver PID field
+ *  @capability None
+ */
+EXPORT_C const TSmsProtocolIdentifier* CSmsDeliver::ProtocolIdentifier() const
+	{
+	LOGGSMU1("CSmsDeliver::ProtocolIdentifier()");
+
+	return &iProtocolIdentifier;
+	} // CSmsDeliver::ProtocolIdentifier
+
+
+const CSmsUserData* CSmsDeliver::UserDataPtr() const
+	{
+	LOGGSMU1("CSmsDeliver::UserDataPtr()");
+
+	return iUserData;
+	} // CSmsDeliver::UserDataPtr
+
+
+const CSmsAddress* CSmsDeliver::ToFromAddressPtr() const
+	{
+	LOGGSMU1("CSmsDeliver::ToFromAddressPtr()");
+
+	return iOriginalAddress;
+	} // CSmsDeliver::ToFromAddressPtr
+
+
+CSmsSubmit::CSmsSubmit():
+	CSmsPDU(ESmsSubmit),
+	iFirstOctet(TSmsFirstOctet::ESmsMTISubmitOrSubmitReport|TSmsFirstOctet::ESmsNoMoreMessagesToSend|TSmsFirstOctet::ESmsVPFInteger),
+	iValidityPeriod(iFirstOctet)
+	{
+	// NOP
+	} // TSmsFirstOctet::ESmsMTISubmitOrSubmitReport
+
+
+/**
+ *  Destructor.
+ */
+CSmsSubmit::~CSmsSubmit()
+	{
+	delete iServiceCenterAddress;
+	delete iDestinationAddress;
+	delete iUserData;
+	} // TSmsFirstOctet::ESmsMTISubmitOrSubmitReport
+
+
+/**
+ *  Gets Reject Duplicates flag.
+ *  
+ *  SUBMITs with duplicate message reference and destination address can be rejected.
+ *  
+ *  @return True if the SC is being instructed to reject duplicates
+ *  @capability None
+ */
+EXPORT_C TBool CSmsSubmit::RejectDuplicates() const
+	{
+	LOGGSMU1("CSmsSubmit::RejectDuplicates()");
+
+	return (iFirstOctet&TSmsFirstOctet::ESmsRejectDuplicatesMask)==TSmsFirstOctet::ESmsRejectDuplicates;
+	} // CSmsSubmit::RejectDuplicates
+
+
+/**
+ *  Sets Reject Duplicates flag.
+ *  
+ *  @param aRejectDuplicates True to instruct the SC to reject duplicates
+ *  @capability None
+ */
+EXPORT_C void CSmsSubmit::SetRejectDuplicates(TBool aRejectDuplicates)
+	{
+	LOGGSMU2("CSmsSubmit::SetRejectDuplicates(): aRejectDuplicates=%d", aRejectDuplicates);
+
+	iFirstOctet=aRejectDuplicates? (iFirstOctet&(~TSmsFirstOctet::ESmsRejectDuplicatesMask)|TSmsFirstOctet::ESmsRejectDuplicates):
+	                        (iFirstOctet&(~TSmsFirstOctet::ESmsRejectDuplicatesMask)|TSmsFirstOctet::ESmsAcceptDuplicates);
+	} // CSmsSubmit::SetRejectDuplicates
+
+
+/**
+ *  Gets the Validity Period Format.
+ *  
+ *  @return Validity Period Format
+ *  @capability None
+ */
+EXPORT_C TSmsFirstOctet::TSmsValidityPeriodFormat CSmsSubmit::ValidityPeriodFormat() const
+	{
+	LOGGSMU1("CSmsSubmit::ValidityPeriodFormat()");
+
+	return iValidityPeriod.ValidityPeriodFormat();
+	} // TSmsFirstOctet::TSmsValidityPeriodFormat
+
+
+/**
+ *  Sets the Validity Period Format.
+ *  
+ *  @param aValidityPeriodFormat Validity Period Format
+ *  @capability None
+ */
+EXPORT_C void CSmsSubmit::SetValidityPeriodFormat(TSmsFirstOctet::TSmsValidityPeriodFormat aValidityPeriodFormat)
+	{
+	LOGGSMU1("CSmsSubmit::SetValidityPeriodFormat()");
+
+	iValidityPeriod.SetValidityPeriodFormat(aValidityPeriodFormat);
+	} // CSmsSubmit::SetValidityPeriodFormat
+
+
+/**
+ *  Gets Reply Path flag.
+ *  
+ *  If a Reply Path exists, the recipient of the SMS can reply using the same
+ *  service center address.
+ *  
+ *  @return True if Reply Path exists
+ *  @capability None
+ */
+EXPORT_C TBool CSmsSubmit::ReplyPath() const
+	{
+	LOGGSMU1("CSmsSubmit::ReplyPath()");
+
+	return (iFirstOctet&TSmsFirstOctet::ESmsReplyPathMask)==TSmsFirstOctet::ESmsReplyPathExists;
+	} // CSmsSubmit::ReplyPath
+
+
+/**
+ *  Sets Reply Path flag.
+ *  
+ *  @param aReplyPath Set to True to set Reply Path
+ *  @capability None
+ */
+EXPORT_C void CSmsSubmit::SetReplyPath(TBool aReplyPath)
+	{
+	LOGGSMU2("CSmsSubmit::SetReplyPath(): aReplyPath=%d", aReplyPath);
+
+	iFirstOctet=aReplyPath? (iFirstOctet&(~TSmsFirstOctet::ESmsReplyPathMask)|TSmsFirstOctet::ESmsReplyPathExists):
+	                        (iFirstOctet&(~TSmsFirstOctet::ESmsReplyPathMask)|TSmsFirstOctet::ESmsReplyPathNone);
+	} // CSmsSubmit::SetReplyPath
+
+
+/**
+ *  Gets Status Report Request flag.
+ *  
+ *  A sender can request STATUS REPORTs for the SUBMIT being sent.
+ *  
+ *  @return True if the sender is requesting Status Reports
+ *  @capability None
+ */
+EXPORT_C TBool CSmsSubmit::StatusReportRequest() const
+	{
+	LOGGSMU1("CSmsSubmit::StatusReportRequest()");
+
+	return (iFirstOctet&TSmsFirstOctet::ESmsStatusReportRequestMask)==TSmsFirstOctet::ESmsStatusReportRequested;
+	} // CSmsSubmit::StatusReportRequest
+
+
+/**
+ *  Sets Status Report Request flag.
+ *  
+ *  @param aRequest Status Report Request flag
+ *  @capability None
+ */
+EXPORT_C void CSmsSubmit::SetStatusReportRequest(TBool aRequest)
+	{
+	LOGGSMU2("CSmsSubmit::SetStatusReportRequest(): aRequest=%d", aRequest);
+
+	iFirstOctet=aRequest? (iFirstOctet&(~TSmsFirstOctet::ESmsStatusReportRequestMask)|TSmsFirstOctet::ESmsStatusReportRequested):
+	                      (iFirstOctet&(~TSmsFirstOctet::ESmsStatusReportRequestMask)|TSmsFirstOctet::ESmsStatusReportNotRequested);
+	} // CSmsSubmit::SetStatusReportRequest
+
+
+/**
+ *  Gets the Message Reference.
+ *  
+ *  @return Message Reference
+ *  @capability None
+ */
+EXPORT_C TInt CSmsSubmit::MessageReference() const
+	{
+	LOGGSMU1("CSmsSubmit::MessageReference()");
+
+	return iMessageReference;
+	} // CSmsSubmit::MessageReference
+
+
+/**
+ *  Sets the Message Reference.
+ *  
+ *  @param aMessageReference Message Reference
+ *  @capability None
+ */
+EXPORT_C void CSmsSubmit::SetMessageReference(TInt aMessageReference)
+	{
+	LOGGSMU2("CSmsSubmit::SetMessageReference(): aMessageReference=%d",
+			 aMessageReference);
+	iMessageReference=aMessageReference;
+	} // CSmsSubmit::SetMessageReference
+
+
+/**
+ *  Gets the Validity Period for the SUBMIT.
+ *  
+ *  @return Validity Period
+ *  @capability None
+ */
+EXPORT_C const TTimeIntervalMinutes&  CSmsSubmit::ValidityPeriod() const
+	{
+	LOGGSMU1("CSmsSubmit::ValidityPeriod()");
+
+	return iValidityPeriod.TimeIntervalMinutes();
+	} // CSmsSubmit::ValidityPeriod
+
+
+/**
+ *  Sets the Validity Period for the SUBMIT.
+ *  
+ *  @param aTimeIntervalMinutes Validity Period
+ *  @capability None
+ */
+EXPORT_C void CSmsSubmit::SetValidityPeriod(const TTimeIntervalMinutes& aTimeIntervalMinutes)
+	{
+	LOGGSMU2("CSmsSubmit::SetValidityPeriod(): aTimeIntervalMinutes",
+			 aTimeIntervalMinutes.Int());
+
+	iValidityPeriod.SetTimeIntervalMinutes(aTimeIntervalMinutes);
+	} // CSmsSubmit::SetValidityPeriod
+
+
+const TSmsDataCodingScheme* CSmsSubmit::DataCodingScheme() const
+	{
+	LOGGSMU1("CSmsSubmit::DataCodingScheme()");
+
+	return &iDataCodingScheme;
+	} // CSmsSubmit::DataCodingScheme
+
+
+const TSmsProtocolIdentifier* CSmsSubmit::ProtocolIdentifier() const
+	{
+	LOGGSMU1("CSmsSubmit::ProtocolIdentifier()");
+
+	return &iProtocolIdentifier;
+	} // CSmsSubmit::ProtocolIdentifier
+
+
+const CSmsUserData* CSmsSubmit::UserDataPtr() const
+	{
+	LOGGSMU1("CSmsSubmit::UserDataPtr()");
+
+	return iUserData;
+	} // CSmsSubmit::UserDataPtr
+
+
+const CSmsAddress* CSmsSubmit::ToFromAddressPtr() const
+	{
+	LOGGSMU1("CSmsSubmit::ToFromAddressPtr()");
+
+	return iDestinationAddress;
+	} // CSmsSubmit::ToFromAddressPtr
+
+
+void CSmsSubmit::ConstructL(CCnvCharacterSetConverter& aCharacterSetConverter,RFs& aFs)
+	{
+	LOGGSMU1("CSmsSubmit::ConstructL()");
+
+	iServiceCenterAddress=CSmsAddress::NewL(aCharacterSetConverter,aFs);
+	iDestinationAddress=CSmsAddress::NewL(aCharacterSetConverter,aFs);
+	iUserData=CSmsUserData::NewL(aCharacterSetConverter,aFs,iFirstOctet,iDataCodingScheme);
+	} // CSmsSubmit::ConstructL
+
+
+/**
+ *  Duplicates this CSmsSubmit object.
+ * 
+ *  @return  Pointer to the newly created CSmsSubmit object.
+ */
+EXPORT_C CSmsSubmit* CSmsSubmit::DuplicateL() const
+	{
+	LOGGSMU1("CSmsSubmit::DuplicateL()");
+
+	CSmsSubmit*  smsSubmit = new (ELeave) CSmsSubmit();
+	CleanupStack::PushL(smsSubmit);
+	
+	smsSubmit->iServiceCenterAddress = iServiceCenterAddress->DuplicateL();
+	smsSubmit->iDestinationAddress   = iDestinationAddress->DuplicateL();
+	smsSubmit->iUserData             = iUserData->DuplicateL(smsSubmit->iFirstOctet,
+															 smsSubmit->iDataCodingScheme);
+	smsSubmit->iFirstOctet           = iFirstOctet;
+	smsSubmit->iMessageReference     = iMessageReference;
+	smsSubmit->iProtocolIdentifier   = iProtocolIdentifier;
+	smsSubmit->iDataCodingScheme     = iDataCodingScheme;
+	smsSubmit->iValidityPeriod.SetValidityPeriodFormat(iValidityPeriod.ValidityPeriodFormat());
+	smsSubmit->iValidityPeriod.SetTimeIntervalMinutes(iValidityPeriod.TimeIntervalMinutes());
+	
+	CleanupStack::Pop(smsSubmit);
+
+	return smsSubmit;
+	} // CSmsSubmit::DuplicateL
+
+
+TUint8* CSmsSubmit::EncodeL(TUint8* aPtr) const
+	{
+	LOGGSMU1("CSmsSubmit::EncodeL()");
+
+	aPtr=iFirstOctet.EncodeL(aPtr);
+	aPtr=iMessageReference.EncodeL(aPtr);
+	aPtr=iDestinationAddress->EncodeL(aPtr);
+	aPtr=iProtocolIdentifier.EncodeL(aPtr);
+	aPtr=iDataCodingScheme.EncodeL(aPtr);
+	aPtr=iValidityPeriod.EncodeL(aPtr);
+	return iUserData->EncodeL(aPtr);
+	} // CSmsSubmit::EncodeL
+
+TUint8* CSmsSubmit::EncodeL(TUint8* aPtr, const TEncodeParams* aEncodeParams) const		
+	{
+	LOGGSMU1("CSmsSubmit::EncodeL()");
+
+	aPtr=iFirstOctet.EncodeL(aPtr);
+	aPtr=iMessageReference.EncodeL(aPtr);
+	aPtr=iDestinationAddress->EncodeL(aPtr);
+	aPtr=iProtocolIdentifier.EncodeL(aPtr);
+	aPtr=iDataCodingScheme.EncodeL(aPtr);
+	aPtr=iValidityPeriod.EncodeL(aPtr, aEncodeParams);
+	return iUserData->EncodeL(aPtr);
+	} // CSmsSubmit::EncodeL
+
+void CSmsSubmit::DecodeL(TGsmuLex8& aPdu)
+	{
+	LOGGSMU1("CSmsSubmit::DecodeL()");
+
+	iFirstOctet.DecodeL(aPdu);
+	iMessageReference.DecodeL(aPdu);
+	iDestinationAddress->DecodeL(aPdu);
+	iProtocolIdentifier.DecodeL(aPdu);
+	iDataCodingScheme.DecodeL(aPdu);
+	TInt bit7to4=iDataCodingScheme.Bits7To4();
+	TInt lowerLimit = TSmsDataCodingScheme::ESmsDCSReserved5;
+	TInt upperLimit = TSmsDataCodingScheme::ESmsDCSReserved8;
+	if ((bit7to4>=lowerLimit) &&
+	    (bit7to4<=upperLimit))
+		User::Leave(KErrGsmSMSUnspecifiedDCSError);
+	iValidityPeriod.DecodeL(aPdu);
+	iUserData->DecodeL(aPdu);
+	} // CSmsSubmit::DecodeL
+
+
+void CSmsSubmit::InternalizeMessagePDUL(RReadStream& aStream)
+	{
+	LOGGSMU1("CSmsSubmit::InternalizeMessagePDUL()");
+
+	iServiceCenterAddress->InternalizeL(aStream);
+
+	aStream >> iFirstOctet;
+	aStream >> iMessageReference;
+	iDestinationAddress->InternalizeL(aStream);
+	aStream >> iProtocolIdentifier;
+	aStream >> iDataCodingScheme;
+	aStream >> iValidityPeriod;
+
+	aStream >> *iUserData;
+	} // CSmsSubmit::InternalizeMessagePDUL
+
+
+void CSmsSubmit::ExternalizeMessagePDUL(RWriteStream& aStream) const
+	{
+	iServiceCenterAddress->ExternalizeL(aStream);
+
+	aStream << iFirstOctet;
+	aStream << iMessageReference;
+	iDestinationAddress->ExternalizeL(aStream);
+	aStream << iProtocolIdentifier;
+	aStream << iDataCodingScheme;
+	aStream << iValidityPeriod;
+
+	aStream << *iUserData;
+	} // CSmsSubmit::ExternalizeMessagePDUL
+
+
+CSmsDeliverReport::CSmsDeliverReport(TBool aIsRPError):
+	CSmsPDU(ESmsDeliverReport),
+	iIsRPError((TUint8) aIsRPError),
+	iFirstOctet(TSmsFirstOctet::ESmsMTIDeliverOrDeliverReport)
+	{
+	} // TSmsFirstOctet::ESmsMTIDeliverOrDeliverReport
+
+
+/**
+ *  Destructor.
+ */
+CSmsDeliverReport::~CSmsDeliverReport()
+	{
+	delete iServiceCenterAddress;
+	delete iUserData;
+	} // TSmsFirstOctet::ESmsMTIDeliverOrDeliverReport
+
+
+/**
+ *  Gets the Failure Cause.
+ *  
+ *  @return The Failure Cause
+ *  @capability None
+ */
+EXPORT_C TInt CSmsDeliverReport::FailureCause() const
+	{
+	LOGGSMU1("CSmsDeliverReport::FailureCause()");
+
+	__ASSERT_DEBUG(iIsRPError,Panic(KGsmuPanicNotRPError));
+	return iFailureCause.Error();
+	} // CSmsDeliverReport::FailureCause
+
+
+/**
+ *  Sets the Failure Cause.
+ *  
+ *  @param aFailureCause The Failure Cause
+ *  @capability None
+ */
+EXPORT_C void CSmsDeliverReport::SetFailureCause(TSmsFailureCause::TSmsFailureCauseError aFailureCause)
+	{
+	LOGGSMU1("CSmsDeliverReport::SetFailureCause()");
+
+	__ASSERT_DEBUG(iIsRPError,Panic(KGsmuPanicNotRPError));
+	iFailureCause.SetError(aFailureCause);
+	} // CSmsDeliverReport::SetFailureCause
+
+
+const TSmsDataCodingScheme* CSmsDeliverReport::DataCodingScheme() const
+	{
+	LOGGSMU1("CSmsDeliverReport::DataCodingScheme()");
+
+	__ASSERT_DEBUG(DataCodingSchemePresent(),Panic(KGsmuPanicDataCodingSchemeNotPresent));
+	return &iDataCodingScheme;
+	} // CSmsDeliverReport::DataCodingScheme
+
+
+const TSmsProtocolIdentifier* CSmsDeliverReport::ProtocolIdentifier() const
+	{
+	LOGGSMU1("CSmsDeliverReport::ProtocolIdentifier()");
+
+	__ASSERT_DEBUG(ProtocolIdentifierPresent(),Panic(KGsmuPanicProtocolIdentifierNotPresent));
+	return &iProtocolIdentifier;
+	} // CSmsDeliverReport::ProtocolIdentifier
+
+
+const TSmsParameterIndicator* CSmsDeliverReport::ParameterIndicator() const
+	{
+	LOGGSMU1("CSmsDeliverReport::ParameterIndicator()");
+
+	return &iParameterIndicator;
+	} // CSmsDeliverReport::ParameterIndicator
+
+
+const CSmsUserData* CSmsDeliverReport::UserDataPtr() const
+	{
+	LOGGSMU1("CSmsDeliverReport::UserDataPtr()");
+
+	__ASSERT_DEBUG(UserDataPresent(),Panic(KGsmuPanicUserDataNotPresent));
+	return iUserData;
+	} // CSmsDeliverReport::UserDataPtr
+
+
+void CSmsDeliverReport::ConstructL(CCnvCharacterSetConverter& aCharacterSetConverter,RFs& aFs)
+	{
+	LOGGSMU1("CSmsDeliverReport::ConstructL()");
+
+	iServiceCenterAddress=CSmsAddress::NewL(aCharacterSetConverter,aFs);
+	iUserData=CSmsUserData::NewL(aCharacterSetConverter,aFs,iFirstOctet,iDataCodingScheme);
+	} // CSmsDeliverReport::ConstructL
+
+
+/**
+ *  Duplicates this CSmsDeliverReport object.
+ * 
+ *  @return  Pointer to the newly created CSmsDeliverReport object.
+ */
+EXPORT_C CSmsDeliverReport* CSmsDeliverReport::DuplicateL() const
+	{
+	LOGGSMU1("CSmsDeliverReport::DuplicateL()");
+
+	CSmsDeliverReport*  smsDeliverReport = new (ELeave) CSmsDeliverReport(iIsRPError);
+	CleanupStack::PushL(smsDeliverReport);
+
+	smsDeliverReport->iServiceCenterAddress = iServiceCenterAddress->DuplicateL();
+	smsDeliverReport->iFirstOctet           = iFirstOctet;
+	smsDeliverReport->iFailureCause         = iFailureCause;
+	smsDeliverReport->iParameterIndicator   = iParameterIndicator;
+	smsDeliverReport->iProtocolIdentifier   = iProtocolIdentifier;
+	smsDeliverReport->iDataCodingScheme     = iDataCodingScheme;
+	smsDeliverReport->iUserData             = iUserData->DuplicateL(smsDeliverReport->iFirstOctet,
+																	smsDeliverReport->iDataCodingScheme);
+
+	CleanupStack::Pop(smsDeliverReport);
+
+	return smsDeliverReport;
+	} // CSmsDeliverReport::DuplicateL
+
+
+TUint8* CSmsDeliverReport::EncodeL(TUint8* aPtr) const
+	{
+	LOGGSMU1("CSmsDeliverReport::EncodeL()");
+
+	aPtr=iFirstOctet.EncodeL(aPtr);
+	if (iIsRPError)
+		aPtr=iFailureCause.EncodeL(aPtr);
+	aPtr=iParameterIndicator.EncodeL(aPtr);
+	if (iParameterIndicator.ProtocolIdentifierPresent())
+		aPtr=iProtocolIdentifier.EncodeL(aPtr);
+	if (iParameterIndicator.DataCodingSchemePresent())
+		aPtr=iDataCodingScheme.EncodeL(aPtr);
+	if (iParameterIndicator.UserDataPresent())
+		aPtr=iUserData->EncodeL(aPtr);
+	return aPtr;
+	} // CSmsDeliverReport::EncodeL
+
+TUint8* CSmsDeliverReport::EncodeL(TUint8* aPtr, const TEncodeParams* ) const
+	{
+	return EncodeL(aPtr);		
+	}	
+
+void CSmsDeliverReport::DecodeL(TGsmuLex8& aPdu)
+	{
+	LOGGSMU1("CSmsDeliverReport::DecodeL()");
+
+	iFirstOctet.DecodeL(aPdu);
+	if (iIsRPError)
+		iFailureCause.DecodeL(aPdu);
+	iParameterIndicator.DecodeL(aPdu);
+	if (iParameterIndicator.Extension())
+		{
+		//
+		//  Throw away rest of the pdu - some pdus received with this bit set don't appear to conform to 03.40 v7.4.0 spec.
+		//  TODO Will need to review later, though this appears safest option now.
+		//
+		((TSmsOctet&)iParameterIndicator)=TSmsParameterIndicator::ESmsPIDExtension;
+		return;
+		}
+	if (iParameterIndicator.ProtocolIdentifierPresent())
+		iProtocolIdentifier.DecodeL(aPdu);
+	if (iParameterIndicator.DataCodingSchemePresent())
+		{
+		iDataCodingScheme.DecodeL(aPdu);
+		TInt bit7to4=iDataCodingScheme.Bits7To4();
+		TInt lowerLimit = TSmsDataCodingScheme::ESmsDCSReserved5;
+	    TInt upperLimit = TSmsDataCodingScheme::ESmsDCSReserved8;
+       	if ((bit7to4>=lowerLimit) &&
+	        (bit7to4<=upperLimit))
+		    User::Leave(KErrGsmSMSUnspecifiedDCSError);
+		}
+	if (iParameterIndicator.UserDataPresent())
+		{
+		if (!iParameterIndicator.DataCodingSchemePresent())
+		    {
+		    iParameterIndicator.SetDataCodingSchemePresent(TBool (ETrue));
+		    iDataCodingScheme = TSmsDataCodingScheme();
+		    }
+
+		iUserData->DecodeL(aPdu);
+		}
+	} // CSmsDeliverReport::DecodeL
+
+
+void CSmsDeliverReport::InternalizeMessagePDUL(RReadStream& aStream)
+	{
+	iServiceCenterAddress->InternalizeL(aStream);
+
+	aStream >> iIsRPError;
+
+	aStream >> iFirstOctet;
+	aStream >> iFailureCause;
+	aStream >> iParameterIndicator;
+	aStream >> iProtocolIdentifier;
+	aStream >> iDataCodingScheme;
+	aStream >> *iUserData;
+	} // CSmsDeliverReport::InternalizeMessagePDUL
+
+
+void CSmsDeliverReport::ExternalizeMessagePDUL(RWriteStream& aStream) const
+	{
+	iServiceCenterAddress->ExternalizeL(aStream);
+
+	aStream << iIsRPError;
+
+	aStream << iFirstOctet;
+	aStream << iFailureCause;
+	aStream << iParameterIndicator;
+	aStream << iProtocolIdentifier;
+	aStream << iDataCodingScheme;
+	aStream << *iUserData;
+	} // CSmsDeliverReport::ExternalizeMessagePDUL
+
+
+CSmsSubmitReport::CSmsSubmitReport(TBool aIsRPError):
+	CSmsPDU(ESmsSubmitReport),
+	iIsRPError((TUint8) aIsRPError),
+	iFirstOctet(TSmsFirstOctet::ESmsMTISubmitOrSubmitReport)
+	{
+	} // TSmsFirstOctet::ESmsMTISubmitOrSubmitReport
+
+
+/**
+ *  Destructor.
+ */
+CSmsSubmitReport::~CSmsSubmitReport()
+	{
+	delete iServiceCenterAddress;
+	delete iUserData;
+	} // TSmsFirstOctet::ESmsMTISubmitOrSubmitReport
+
+
+/**
+ *  Gets the Failure Cause.
+ *  
+ *  @return The Failure Cause
+ *  @capability None
+ */
+EXPORT_C TInt CSmsSubmitReport::FailureCause() const
+	{
+	LOGGSMU1("CSmsSubmitReport::FailureCause()");
+
+	__ASSERT_DEBUG(iIsRPError,Panic(KGsmuPanicNotRPError));
+	return iFailureCause.Error();
+	} // CSmsSubmitReport::FailureCause
+
+
+/**
+ *  Sets the Failure Cause.
+ *  
+ *  @param aFailureCause The Failure Cause
+ *  @capability None
+ */
+EXPORT_C void CSmsSubmitReport::SetFailureCause(TSmsFailureCause::TSmsFailureCauseError aFailureCause)
+	{
+	LOGGSMU1("CSmsSubmitReport::SetFailureCause()");
+
+	__ASSERT_DEBUG(iIsRPError,Panic(KGsmuPanicNotRPError));
+	iFailureCause.SetError(aFailureCause);
+	} // CSmsSubmitReport::SetFailureCause
+
+
+const TSmsDataCodingScheme* CSmsSubmitReport::DataCodingScheme() const
+	{
+	LOGGSMU1("CSmsSubmitReport::DataCodingScheme()");
+
+	__ASSERT_DEBUG(DataCodingSchemePresent(),Panic(KGsmuPanicDataCodingSchemeNotPresent));
+	return &iDataCodingScheme;
+	} // CSmsSubmitReport::DataCodingScheme
+
+
+const TSmsProtocolIdentifier* CSmsSubmitReport::ProtocolIdentifier() const
+	{
+	LOGGSMU1("CSmsSubmitReport::ProtocolIdentifier()");
+
+	__ASSERT_DEBUG(ProtocolIdentifierPresent(),Panic(KGsmuPanicProtocolIdentifierNotPresent));
+	return &iProtocolIdentifier;
+	} // CSmsSubmitReport::ProtocolIdentifier
+
+
+const TSmsParameterIndicator* CSmsSubmitReport::ParameterIndicator() const
+	{
+	LOGGSMU1("CSmsSubmitReport::ParameterIndicator()");
+
+	return &iParameterIndicator;
+	} // CSmsSubmitReport::ParameterIndicator
+
+
+const CSmsUserData* CSmsSubmitReport::UserDataPtr() const
+	{
+	LOGGSMU1("CSmsSubmitReport::UserDataPtr()");
+
+	__ASSERT_DEBUG(UserDataPresent(),Panic(KGsmuPanicUserDataNotPresent));
+	return iUserData;
+	} // CSmsSubmitReport::UserDataPtr
+
+
+void CSmsSubmitReport::ConstructL(CCnvCharacterSetConverter& aCharacterSetConverter,RFs& aFs)
+	{
+	LOGGSMU1("CSmsSubmitReport::ConstructL()");
+
+	iServiceCenterAddress=CSmsAddress::NewL(aCharacterSetConverter,aFs);
+	iUserData=CSmsUserData::NewL(aCharacterSetConverter,aFs,iFirstOctet,iDataCodingScheme);
+	} // CSmsSubmitReport::ConstructL
+
+
+/**
+ *  Duplicates this CSmsSubmitReport object.
+ * 
+ *  @return  Pointer to the newly created CSmsSubmitReport object.
+ */
+EXPORT_C CSmsSubmitReport* CSmsSubmitReport::DuplicateL() const
+	{
+	LOGGSMU1("CSmsSubmitReport::DuplicateL()");
+
+	CSmsSubmitReport*  smsSubmitReport = new (ELeave) CSmsSubmitReport(iIsRPError);
+	CleanupStack::PushL(smsSubmitReport);
+
+	smsSubmitReport->iServiceCenterAddress   = iServiceCenterAddress->DuplicateL();
+	smsSubmitReport->iFirstOctet             = iFirstOctet;
+	smsSubmitReport->iFailureCause           = iFailureCause;
+	smsSubmitReport->iParameterIndicator     = iParameterIndicator;
+	smsSubmitReport->iServiceCenterTimeStamp = iServiceCenterTimeStamp;
+	smsSubmitReport->iProtocolIdentifier     = iProtocolIdentifier;
+	smsSubmitReport->iDataCodingScheme       = iDataCodingScheme;
+	smsSubmitReport->iUserData               = iUserData->DuplicateL(smsSubmitReport->iFirstOctet,
+																	 smsSubmitReport->iDataCodingScheme);
+
+	CleanupStack::Pop(smsSubmitReport);
+
+	return smsSubmitReport;
+	} // CSmsSubmitReport::DuplicateL
+
+
+TUint8* CSmsSubmitReport::EncodeL(TUint8* aPtr) const
+	{
+	LOGGSMU1("CSmsSubmitReport::EncodeL()");
+
+	aPtr=iFirstOctet.EncodeL(aPtr);
+	if (iIsRPError)
+		aPtr=iFailureCause.EncodeL(aPtr);
+	aPtr=iParameterIndicator.EncodeL(aPtr);
+	aPtr=iServiceCenterTimeStamp.EncodeL(aPtr);
+	if (iParameterIndicator.ProtocolIdentifierPresent())
+		aPtr=iProtocolIdentifier.EncodeL(aPtr);
+	if (iParameterIndicator.DataCodingSchemePresent())
+		aPtr=iDataCodingScheme.EncodeL(aPtr);
+	if (iParameterIndicator.UserDataPresent())
+		aPtr=iUserData->EncodeL(aPtr);
+	return aPtr;
+	} // CSmsSubmitReport::EncodeL
+
+TUint8* CSmsSubmitReport::EncodeL(TUint8* aPtr, const TEncodeParams* ) const
+	{
+	return EncodeL(aPtr);		
+	}	
+
+void CSmsSubmitReport::DecodeL(TGsmuLex8& aPdu)
+	{
+	LOGGSMU1("CSmsSubmitReport::DecodeL()");
+
+	iFirstOctet.DecodeL(aPdu);
+	if (iIsRPError)
+		iFailureCause.DecodeL(aPdu);
+	iParameterIndicator.DecodeL(aPdu);
+
+	if (iParameterIndicator.Extension())
+		{
+		//
+		//  Throw away rest of the pdu - some pdus received with this bit set don't appear to conform to 03.40 v7.4.0 spec.
+		//  TODO Will need to review later, though this appears safest option now.
+		//
+		((TSmsOctet&)iParameterIndicator)=TSmsParameterIndicator::ESmsPIDExtension;
+		return;
+		}
+
+	TInt timeError;
+	iServiceCenterTimeStamp.DecodeL(aPdu, timeError);
+	if (timeError != KErrNone)
+		{
+		TTime time;
+		time.UniversalTime();
+		iServiceCenterTimeStamp.SetTime(time);
+		iServiceCenterTimeStamp.SetTimeOffset((User::UTCOffset().Int())/CSmsMessage::E15MinutesRepresentedInSeconds);
+		}
+
+	if (iParameterIndicator.ProtocolIdentifierPresent())
+		iProtocolIdentifier.DecodeL(aPdu);
+
+	if (iParameterIndicator.DataCodingSchemePresent())
+		{
+		iDataCodingScheme.DecodeL(aPdu);
+    	TInt bit7to4=iDataCodingScheme.Bits7To4();
+	    TInt lowerLimit = TSmsDataCodingScheme::ESmsDCSReserved5;
+	    TInt upperLimit = TSmsDataCodingScheme::ESmsDCSReserved8;
+	    if ((bit7to4>=lowerLimit) &&
+	        (bit7to4<=upperLimit))
+
+			User::Leave(KErrGsmSMSUnspecifiedDCSError);
+		}
+	if (iParameterIndicator.UserDataPresent())
+		{
+		if (!iParameterIndicator.DataCodingSchemePresent())
+		    {
+		    iParameterIndicator.SetDataCodingSchemePresent(TBool (ETrue));
+		    iDataCodingScheme = TSmsDataCodingScheme();
+		    }
+
+		iUserData->DecodeL(aPdu);
+		}
+	} // CSmsSubmitReport::DecodeL
+
+
+void CSmsSubmitReport::InternalizeMessagePDUL(RReadStream& aStream)
+	{
+	iServiceCenterAddress->InternalizeL(aStream);
+
+	aStream >> iIsRPError;
+
+	aStream >> iFirstOctet;
+	aStream >> iFailureCause;
+	aStream >> iParameterIndicator;
+	aStream >> iServiceCenterTimeStamp;
+	aStream >> iProtocolIdentifier;
+	aStream >> iDataCodingScheme;
+	aStream >> *iUserData;
+	} // CSmsSubmitReport::InternalizeMessagePDUL
+
+
+void CSmsSubmitReport::ExternalizeMessagePDUL(RWriteStream& aStream) const
+	{
+	iServiceCenterAddress->ExternalizeL(aStream);
+
+	aStream << iIsRPError;
+
+	aStream << iFirstOctet;
+	aStream << iFailureCause;
+	aStream << iParameterIndicator;
+	aStream << iServiceCenterTimeStamp;
+	aStream << iProtocolIdentifier;
+	aStream << iDataCodingScheme;
+	aStream << *iUserData;
+	} // CSmsSubmitReport::ExternalizeMessagePDUL
+
+
+/**
+ *  Gets More Messages to Send flag.
+ *  
+ *  @return True if More Messages to Send flag set
+ *  @capability None
+ */
+EXPORT_C TBool CSmsStatusReport::MoreMessagesToSend() const
+	{
+	LOGGSMU1("CSmsStatusReport::MoreMessagesToSend()");
+
+	return (iFirstOctet&TSmsFirstOctet::ESmsMoreMessagesToSendMask)==TSmsFirstOctet::ESmsMoreMessagesToSend;
+	} // CSmsStatusReport::MoreMessagesToSend
+
+
+/**
+ *  Sets More Messages to Send flag.
+ *  
+ *  @param aMore True if More Messages to Send
+ *  @capability None
+ */
+EXPORT_C void CSmsStatusReport::SetMoreMessagesToSend(TBool aMore)
+	{
+	LOGGSMU1("CSmsStatusReport::SetMoreMessagesToSend()");
+
+	iFirstOctet=aMore? (iFirstOctet&(~TSmsFirstOctet::ESmsMoreMessagesToSendMask)|TSmsFirstOctet::ESmsMoreMessagesToSend):
+	                   (iFirstOctet&(~TSmsFirstOctet::ESmsMoreMessagesToSendMask)|TSmsFirstOctet::ESmsNoMoreMessagesToSend);
+	} // CSmsStatusReport::SetMoreMessagesToSend
+
+
+/**
+ *  Gets Status Report Qualifier: the field in the Status Report which determines whether it's
+ *  the result of a SUBMIT or COMMAND.
+ *  
+ *  @return Status Report Qualifier
+ *  @capability None
+ */
+EXPORT_C TSmsFirstOctet::TSmsStatusReportQualifier CSmsStatusReport::StatusReportQualifier() const
+	{
+	LOGGSMU1("TSmsFirstOctet::TSmsStatusReportQualifier()");
+
+	return (TSmsFirstOctet::TSmsStatusReportQualifier) (iFirstOctet&TSmsFirstOctet::ESmsStatusReportQualifierMask);
+	} // TSmsFirstOctet::TSmsStatusReportQualifier
+
+
+/**
+ *  Sets Status Report Qualifier to SUBMIT or COMMAND.
+ *  
+ *  @param aQualifier Status Report Qualifier
+ *  @capability None
+ */
+EXPORT_C void CSmsStatusReport::SetStatusReportQualifier(TSmsFirstOctet::TSmsStatusReportQualifier aQualifier)
+	{
+	LOGGSMU1("CSmsStatusReport::SetStatusReportQualifier()");
+
+	iFirstOctet=iFirstOctet&(~TSmsFirstOctet::ESmsStatusReportQualifierMask)|aQualifier;
+	} // CSmsStatusReport::SetStatusReportQualifier
+
+
+CSmsStatusReport::CSmsStatusReport():
+	CSmsPDU(ESmsStatusReport),
+	iFirstOctet(TSmsFirstOctet::ESmsMTIStatusReportOrCommand|TSmsFirstOctet::ESmsNoMoreMessagesToSend|TSmsFirstOctet::ESmsStatusReportResultOfSubmit)
+	{
+	} // TSmsFirstOctet::ESmsMTIStatusReportOrCommand
+
+
+/**
+ *  Destructor.
+ */
+CSmsStatusReport::~CSmsStatusReport()
+	{
+	delete iServiceCenterAddress;
+	delete iRecipientAddress;
+	delete iUserData;
+	} // TSmsFirstOctet::ESmsMTIStatusReportOrCommand
+
+
+/**
+ *  Gets the Message Reference.
+ *  
+ *  @return Message Reference
+ *  @capability None
+ */
+EXPORT_C TInt CSmsStatusReport::MessageReference() const
+	{
+	LOGGSMU2("CSmsStatusReport::MessageReference %d", (TInt)iMessageReference );
+	return iMessageReference;
+	} // CSmsStatusReport::MessageReference
+
+
+/**
+ *  Sets the Message Reference.
+ *  
+ *  @param aMessageReference Message Reference
+ *  @capability None
+ */
+EXPORT_C void CSmsStatusReport::SetMessageReference(TInt aMessageReference)
+	{
+	iMessageReference=aMessageReference;
+	LOGGSMU2("CSmsStatusReport::SetMessageReference %d", (TInt)iMessageReference );
+	} // CSmsStatusReport::SetMessageReference
+
+
+/**
+ *  Gets Service Center Time Stamp.
+ *  
+ *  @param aTime Service Center Time Stamp represented in Universal Time.
+ *  @param aNumQuarterHours +/- Time Zone difference to GMT in quarter hours.
+ *  @capability None
+ */
+EXPORT_C void CSmsStatusReport::ServiceCenterTimeStamp(TTime& aTime,TInt& aNumQuarterHours)
+	{
+	LOGGSMU1("CSmsStatusReport::ServiceCenterTimeStamp()");
+
+	aTime=iServiceCenterTimeStamp.Time();
+	aNumQuarterHours=iServiceCenterTimeStamp.TimeOffset();
+	} // CSmsStatusReport::ServiceCenterTimeStamp
+
+
+/**
+ *  Sets the Service Center Time Stamp.
+ *  
+ *  @param aTime Service Center Time Stamp represented in Universal Time.
+ *  @param aNumQuarterHours +/- Time Zone difference to GMT in quarter hours.
+ *  @capability None
+ */
+EXPORT_C void CSmsStatusReport::SetServiceCenterTimeStamp(const TTime& aTime,TInt& aNumQuarterHours)
+	{
+	LOGGSMU1("CSmsStatusReport::SetServiceCenterTimeStamp()");
+
+	iServiceCenterTimeStamp.SetTime(aTime);
+	iServiceCenterTimeStamp.SetTimeOffset(aNumQuarterHours);
+	} // CSmsStatusReport::SetServiceCenterTimeStamp
+
+
+/**
+ *  Gets the Discharge Time.
+ *  
+ *  @param aTime The Discharge Time represented in Universal Time.
+ *  @param aNumQuarterHours +/- Time Zone difference to GMT in quarter hours
+ *  @capability None
+ */
+EXPORT_C void CSmsStatusReport::DischargeTime(TTime& aTime,TInt& aNumQuarterHours)
+	{
+	LOGGSMU1("CSmsStatusReport::DischargeTime()");
+
+	aTime=iDischargeTime.Time();
+	aNumQuarterHours=iDischargeTime.TimeOffset();
+	} // CSmsStatusReport::DischargeTime
+
+
+/**
+ *  Sets the Discharge Time.
+ *  
+ *  @param aTime The Discharge Time represented in Universal Time.
+ *  @param aNumQuarterHours +/- Time Zone difference to GMT in quarter hours
+ *  @capability None
+ */
+EXPORT_C void CSmsStatusReport::SetDischargeTime(const TTime& aTime,TInt& aNumQuarterHours)
+	{
+	LOGGSMU1("CSmsStatusReport::SetDischargeTime()");
+
+	iDischargeTime.SetTime(aTime);
+	iDischargeTime.SetTimeOffset(aNumQuarterHours);
+	} // CSmsStatusReport::SetDischargeTime
+
+
+/**
+ *  Gets the Status of the Message.
+ *  
+ *  @return Status
+ *  @capability None
+ */
+EXPORT_C TSmsStatus::TSmsStatusValue CSmsStatusReport::Status() const
+	{
+	LOGGSMU2("CSmsStatusReport::Status %d", iStatus.Status());
+	return iStatus.Status();
+	} // TSmsStatus::TSmsStatusValue
+
+
+/**
+ *  Sets the Status of the Message.
+ *  
+ *  @param aValue Status
+ *  @capability None
+ */
+EXPORT_C void CSmsStatusReport::SetStatus(TSmsStatus::TSmsStatusValue aValue)
+	{
+	LOGGSMU1("CSmsStatusReport::SetStatus()");
+
+	iStatus.SetStatus(aValue);
+	} // CSmsStatusReport::SetStatus
+
+
+const TSmsDataCodingScheme* CSmsStatusReport::DataCodingScheme() const
+	{
+	LOGGSMU1("CSmsStatusReport::DataCodingScheme()");
+
+	__ASSERT_DEBUG(DataCodingSchemePresent(),Panic(KGsmuPanicDataCodingSchemeNotPresent));
+	return &iDataCodingScheme;
+	} // CSmsStatusReport::DataCodingScheme
+
+
+const TSmsProtocolIdentifier* CSmsStatusReport::ProtocolIdentifier() const
+	{
+	LOGGSMU1("CSmsStatusReport::ProtocolIdentifier()");
+
+	__ASSERT_DEBUG(ProtocolIdentifierPresent(),Panic(KGsmuPanicProtocolIdentifierNotPresent));
+	return &iProtocolIdentifier;
+	} // CSmsStatusReport::ProtocolIdentifier
+
+
+const TSmsParameterIndicator* CSmsStatusReport::ParameterIndicator() const
+	{
+	LOGGSMU1("CSmsStatusReport::ParameterIndicator()");
+
+	__ASSERT_DEBUG(iParameterIndicatorPresent,Panic(KGsmuPanicParameterIndicatorNotPresent));
+	return &iParameterIndicator;
+	} // CSmsStatusReport::ParameterIndicator
+
+
+const CSmsUserData* CSmsStatusReport::UserDataPtr() const
+	{
+	LOGGSMU1("CSmsStatusReport::UserDataPtr()");
+
+	__ASSERT_DEBUG(UserDataPresent(),Panic(KGsmuPanicUserDataNotPresent));
+	return iUserData;
+	} // CSmsStatusReport::UserDataPtr
+
+
+const CSmsAddress* CSmsStatusReport::ToFromAddressPtr() const
+	{
+	LOGGSMU1("CSmsStatusReport::ToFromAddressPtr()");
+
+	return iRecipientAddress;
+	} // CSmsStatusReport::ToFromAddressPtr
+
+
+void CSmsStatusReport::ConstructL(CCnvCharacterSetConverter& aCharacterSetConverter,RFs& aFs)
+	{
+	LOGGSMU1("CSmsStatusReport::ConstructL()");
+
+	iServiceCenterAddress=CSmsAddress::NewL(aCharacterSetConverter,aFs);
+	iRecipientAddress=CSmsAddress::NewL(aCharacterSetConverter,aFs);
+	iUserData=CSmsUserData::NewL(aCharacterSetConverter,aFs,iFirstOctet,iDataCodingScheme);
+	} // CSmsStatusReport::ConstructL
+
+
+/**
+ *  Duplicates this CSmsStatusReport object.
+ * 
+ *  @return  Pointer to the newly created CSmsStatusReport object.
+ */
+EXPORT_C CSmsStatusReport* CSmsStatusReport::DuplicateL() const
+	{
+	LOGGSMU1("CSmsStatusReport::DuplicateL()");
+
+	CSmsStatusReport*  smsStatusReport = new (ELeave) CSmsStatusReport();
+	CleanupStack::PushL(smsStatusReport);
+
+	smsStatusReport->iServiceCenterAddress      = iServiceCenterAddress->DuplicateL();
+	smsStatusReport->iParameterIndicatorPresent = iParameterIndicatorPresent;
+	smsStatusReport->iFirstOctet                = iFirstOctet;
+	smsStatusReport->iMessageReference          = iMessageReference;
+	smsStatusReport->iRecipientAddress          = iRecipientAddress->DuplicateL();
+	smsStatusReport->iServiceCenterTimeStamp    = iServiceCenterTimeStamp;
+	smsStatusReport->iDischargeTime             = iDischargeTime;
+	smsStatusReport->iStatus                    = iStatus;
+	smsStatusReport->iParameterIndicator        = iParameterIndicator;
+	smsStatusReport->iProtocolIdentifier        = iProtocolIdentifier;
+	smsStatusReport->iDataCodingScheme          = iDataCodingScheme;
+	smsStatusReport->iUserData                  = iUserData->DuplicateL(smsStatusReport->iFirstOctet,
+																		smsStatusReport->iDataCodingScheme);
+
+	CleanupStack::Pop(smsStatusReport);
+
+	return smsStatusReport;
+	} // CSmsStatusReport::DuplicateL
+
+
+TUint8* CSmsStatusReport::EncodeL(TUint8* aPtr) const
+	{
+	LOGGSMU1("CSmsStatusReport::EncodeL()");
+
+	aPtr=iFirstOctet.EncodeL(aPtr);
+	aPtr=iMessageReference.EncodeL(aPtr);
+	aPtr=iRecipientAddress->EncodeL(aPtr);
+	aPtr=iServiceCenterTimeStamp.EncodeL(aPtr);
+	aPtr=iDischargeTime.EncodeL(aPtr);
+	aPtr=iStatus.EncodeL(aPtr);
+	if (iParameterIndicatorPresent)
+		{
+		aPtr=iParameterIndicator.EncodeL(aPtr);
+		if (iParameterIndicator.ProtocolIdentifierPresent())
+			aPtr=iProtocolIdentifier.EncodeL(aPtr);
+		if (iParameterIndicator.DataCodingSchemePresent())
+			aPtr=iDataCodingScheme.EncodeL(aPtr);
+		if (iParameterIndicator.UserDataPresent())
+			aPtr=iUserData->EncodeL(aPtr);
+		}
+	return aPtr;
+	} // CSmsStatusReport::EncodeL
+
+TUint8* CSmsStatusReport::EncodeL(TUint8* aPtr, const TEncodeParams* ) const
+	{
+	return EncodeL(aPtr);	
+	}
+
+void CSmsStatusReport::DecodeL(TGsmuLex8& aPdu)
+	{
+	LOGGSMU1("CSmsStatusReport::DecodeL()");
+
+	iFirstOctet.DecodeL(aPdu);
+	iMessageReference.DecodeL(aPdu);
+	iRecipientAddress->DecodeL(aPdu);
+
+	TInt timeError;
+	iServiceCenterTimeStamp.DecodeL(aPdu, timeError);
+	if (timeError != KErrNone)
+		{
+		TTime time;
+		time.UniversalTime();
+		iServiceCenterTimeStamp.SetTime(time);
+		iServiceCenterTimeStamp.SetTimeOffset((User::UTCOffset().Int()) / CSmsMessage::E15MinutesRepresentedInSeconds);
+		}
+
+	iDischargeTime.DecodeL(aPdu, timeError);
+	if (timeError != KErrNone)
+		{
+		TTime time;
+		time.UniversalTime();
+		iDischargeTime.SetTime(time);
+		iDischargeTime.SetTimeOffset((User::UTCOffset().Int()) / CSmsMessage::E15MinutesRepresentedInSeconds);
+		}
+
+	iStatus.DecodeL(aPdu);
+
+	iParameterIndicatorPresent = (aPdu.Remainder().Length() > 0);
+
+	if (iParameterIndicatorPresent)
+		{
+		iParameterIndicator.DecodeL(aPdu);
+		if (!iParameterIndicator.Extension())
+			{
+			if (iParameterIndicator.ProtocolIdentifierPresent())
+				iProtocolIdentifier.DecodeL(aPdu);
+			if (iParameterIndicator.DataCodingSchemePresent())
+				{
+				iDataCodingScheme.DecodeL(aPdu);
+	            TInt bit7to4=iDataCodingScheme.Bits7To4();
+	            TInt lowerLimit = TSmsDataCodingScheme::ESmsDCSReserved5;
+	            TInt upperLimit = TSmsDataCodingScheme::ESmsDCSReserved8;
+	            if ((bit7to4>=lowerLimit) &&
+	                (bit7to4<=upperLimit))
+                    {
+                    //
+                    // defect fix for:  HOE-56GLND
+                    // Enumerating of status reports with 6210 leaves with
+                    // (-4688) KErrGsmSMSTpduNotSupported
+                    // && problems with
+                    // (-4671) KErrGsmSMSUnspecifiedDCSError
+					//User::Leave(KErrGsmSMSUnspecifiedDCSError);
+                    iParameterIndicator.SetExtension(EFalse);
+                    iParameterIndicator.SetUserDataPresent(EFalse);
+                    iParameterIndicator.SetDataCodingSchemePresent(EFalse);
+                    iParameterIndicator.SetProtocolIdentifierPresent(EFalse);
+					aPdu.UnGet();
+                    }
+				}
+			if (iParameterIndicator.UserDataPresent())
+				{
+				if (!iParameterIndicator.DataCodingSchemePresent())
+                    {
+		            iParameterIndicator.SetDataCodingSchemePresent(TBool (ETrue));
+		            iDataCodingScheme = TSmsDataCodingScheme();
+                    }
+				// PDEF137451: ETrue parameter indicates that a mismatch between length indicator and actual length is acceptable 
+				// (Service Centre may occasionally truncate the user data of a status report PDU) 
+				iUserData->DecodeL(aPdu,ETrue);
+				}
+			}
+		else
+			{
+			// Throw away rest of the pdu - some pdus received with this bit set don't
+			// appear to conform to 03.40 v7.4.0 spec.  Will need to review later, though
+			// this appears safest option now.
+			((TSmsOctet&)iParameterIndicator)=TSmsParameterIndicator::ESmsPIDExtension;
+			return;
+			}
+		}
+	} // CSmsStatusReport::DecodeL
+
+
+void CSmsStatusReport::InternalizeMessagePDUL(RReadStream& aStream)
+	{
+	iServiceCenterAddress->InternalizeL(aStream);
+
+	iParameterIndicatorPresent=aStream.ReadUint8L();
+
+	aStream >> iFirstOctet;
+	aStream >> iMessageReference;
+	iRecipientAddress->InternalizeL(aStream);
+	aStream >> iServiceCenterTimeStamp;
+	aStream >> iDischargeTime;
+	aStream >> iStatus;
+	aStream >> iParameterIndicator;
+	aStream >> iProtocolIdentifier;
+	aStream >> iDataCodingScheme;
+	aStream >> *iUserData;
+	} // CSmsStatusReport::InternalizeMessagePDUL
+
+
+void CSmsStatusReport::ExternalizeMessagePDUL(RWriteStream& aStream) const
+	{
+	iServiceCenterAddress->ExternalizeL(aStream);
+
+	aStream.WriteUint8L(iParameterIndicatorPresent);
+
+	aStream << iFirstOctet;
+	aStream << iMessageReference;
+	iRecipientAddress->ExternalizeL(aStream);
+	aStream << iServiceCenterTimeStamp;
+	aStream << iDischargeTime;
+	aStream << iStatus;
+	aStream << iParameterIndicator;
+	aStream << iProtocolIdentifier;
+	aStream << iDataCodingScheme;
+	aStream << *iUserData;
+	} // CSmsStatusReport::ExternalizeMessagePDUL
+
+
+CSmsCommand::CSmsCommand():
+	CSmsPDU(ESmsCommand),
+	iFirstOctet(TSmsFirstOctet::ESmsMTIStatusReportOrCommand | TSmsFirstOctet::ESmsStatusReportNotRequested)
+	{
+	} // TSmsFirstOctet::ESmsMTIStatusReportOrCommand
+
+
+/**
+ *  Destructor.
+ */
+CSmsCommand::~CSmsCommand()
+	{
+	delete iServiceCenterAddress;
+	delete iDestinationAddress;
+	delete iCommandData;
+	} // TSmsFirstOctet::ESmsMTIStatusReportOrCommand
+
+
+/**
+ *  Gets Status Report Request flag.
+ *  
+ *  @return True if the sender is requesting Status Reports
+ *  @capability None
+ */
+EXPORT_C TBool CSmsCommand::StatusReportRequest() const
+	{
+	LOGGSMU1("CSmsCommand::StatusReportRequest()");
+
+	return (iFirstOctet&TSmsFirstOctet::ESmsStatusReportRequestMask)==TSmsFirstOctet::ESmsStatusReportRequested;
+	} // CSmsCommand::StatusReportRequest
+
+
+/**
+ *  Sets Status Report Request flag.
+ *  
+ *  @param aRequest  Set to True to Request Status Report
+ *  @capability None
+ */
+EXPORT_C void CSmsCommand::SetStatusReportRequest(TBool aRequest)
+	{
+	LOGGSMU1("CSmsCommand::SetStatusReportRequest()");
+
+	__ASSERT_DEBUG(CommandType()==TSmsCommandType::ESmsCommandTypeEnableStatusReportRequest,Panic(KGsmuPanicSetStatusReportRequestNotSupportedForCommandType));
+	DoSetStatusReportRequest(aRequest);
+	} // CSmsCommand::SetStatusReportRequest
+
+
+/**
+ *  Gets the Message Reference.
+ *  
+ *  @return Message Reference
+ *  @capability None
+ */
+EXPORT_C TInt CSmsCommand::MessageReference() const
+	{
+	LOGGSMU1("CSmsCommand::MessageReference()");
+
+	return iMessageReference;
+	} // CSmsCommand::MessageReference
+
+
+/**
+ *  Sets the Message Reference.
+ *  
+ *  @param aMessageReference Message Reference
+ *  @capability None
+ */
+EXPORT_C void CSmsCommand::SetMessageReference(TInt aMessageReference)
+	{
+	LOGGSMU1("CSmsCommand::SetMessageReference()");
+
+	iMessageReference=aMessageReference;
+	} // CSmsCommand::SetMessageReference
+
+
+/**
+ *  Gets the Command Type.
+ *  
+ *  @return Command Type
+ *  @capability None
+ */
+EXPORT_C TInt CSmsCommand::CommandType() const
+	{
+	LOGGSMU1("CSmsCommand::CommandType()");
+
+	return iCommandType.CommandType();
+	} // CSmsCommand::CommandType
+
+
+/**
+ *  Sets the Command Type.
+ *  
+ *  @param aCommandType Command Type
+ *  @capability None
+ */
+EXPORT_C void CSmsCommand::SetCommandType(TSmsCommandType::TSmsCommandTypeValue aCommandType)
+	{
+	LOGGSMU1("CSmsCommand::SetCommandType()");
+
+	//  Some command types have default status report request
+	switch (aCommandType)
+		{
+		case TSmsCommandType::ESmsCommandTypeEnquiry:
+			{
+			DoSetStatusReportRequest(ETrue);
+			break;
+			}
+		case TSmsCommandType::ESmsCommandTypeCancel:
+		case TSmsCommandType::ESmsCommandTypeDelete:
+		case TSmsCommandType::ESmsCommandTypeEnableStatusReportRequest:
+			{
+			DoSetStatusReportRequest(EFalse);
+			break;
+			}
+		default:
+			{
+			}
+		}
+	iCommandType.SetCommandType(aCommandType);
+	} // CSmsCommand::SetCommandType
+
+
+/**
+ *  Gets the Message Number.
+ *  
+ *  @return Message Number
+ *  @capability None
+ */
+EXPORT_C TInt CSmsCommand::MessageNumber() const
+	{
+	LOGGSMU1("CSmsCommand::MessageNumber()");
+
+	return iMessageNumber;
+	} // CSmsCommand::MessageNumber
+
+
+/**
+ *  Sets the Message Number.
+ *  
+ *  @param aMessageNumber Message Number
+ *  @capability None
+ */
+EXPORT_C void CSmsCommand::SetMessageNumber(TInt aMessageNumber)
+	{
+	LOGGSMU1("CSmsCommand::SetMessageNumber()");
+
+	iMessageNumber=aMessageNumber;
+	} // CSmsCommand::SetMessageNumber
+
+
+/**
+ *  Gets the number of Information Elements in the User Data.
+ *  
+ *  @return Number of Information Elements in the User Data
+ *  @capability None
+ */
+EXPORT_C TInt CSmsCommand::NumInformationElements() const
+	{
+	LOGGSMU1("CSmsCommand::NumInformationElements()");
+
+	return iCommandData->NumInformationElements();
+	} // CSmsCommand::NumInformationElements
+
+
+/**
+ *  Gets an Information Element.
+ *  
+ *  @param aIndex The Information Element Index within the PDU
+ *  @return Information Element
+ *  @capability None
+ */
+EXPORT_C CSmsInformationElement& CSmsCommand::InformationElement(TInt aIndex) const
+	{
+	LOGGSMU1("CSmsCommand::InformationElement()");
+
+	return iCommandData->InformationElement(aIndex);
+	} // CSmsCommand::InformationElement
+
+
+/**
+ *  Gets a pointer to the Information Element located at aIndex.
+ *  
+ *  @param aIndex The Information Element Index within the PDU
+ *  @return Pointer to Information Element
+ *  @capability None
+ */
+CSmsInformationElement*& CSmsCommand::InformationElementPtr(TInt aIndex) const
+    {
+    // Ignore in code coverage - not used in SMS stack and not exported
+    // but cannot be removed as impacts public header.
+    BULLSEYE_OFF    
+    LOGGSMU1("CSmsCommand::InformationElementPtr()");
+    return iCommandData->InformationElementPtr(aIndex);
+    BULLSEYE_RESTORE
+    }
+
+/**
+ *  Gets index of a specified Information Element.
+ *  
+ *  @param aIdentifier Information Element Identifier to match
+ *  @param aIndex On return, index of the Information Element matching aIdentifier
+ *  @return True if Information Element present matching aIdentifier
+ *  @capability None
+ */
+EXPORT_C TBool CSmsCommand::InformationElementIndex(CSmsInformationElement::TSmsInformationElementIdentifier aIdentifier,
+		TInt& aIndex) const
+	{
+	LOGGSMU1("CSmsCommand::InformationElementIndex()");
+
+	return iCommandData->InformationElementIndex(aIdentifier,aIndex);
+	} // CSmsCommand::InformationElementIndex
+
+
+/**
+ *  Adds an Information Element.
+ *  
+ *  @param aIdentifier Information Element Identifier to add
+ *  @param aData The Information Element data
+ *  @capability None
+ */
+EXPORT_C void CSmsCommand::AddInformationElementL(CSmsInformationElement::TSmsInformationElementIdentifier aIdentifier, TDesC8& aData)
+	{
+	LOGGSMU1("CSmsCommand::AddInformationElementL()");
+
+	iCommandData->AddInformationElementL(aIdentifier,aData);
+	} // CSmsCommand::AddInformationElementL
+
+
+/**
+ *  Removes an Information Element.
+ *  
+ *  @param aIndex Index of the Information Element to be removed
+ *  @capability None
+ */
+EXPORT_C void CSmsCommand::RemoveInformationElement(TInt aIndex)
+	{
+	LOGGSMU1("CSmsCommand::RemoveInformationElement()");
+
+	iCommandData->RemoveInformationElement(aIndex);
+	} // CSmsCommand::RemoveInformationElement
+
+
+/**
+ *  Gets the Maximum Data Length of the Command.
+ *  
+ *  @return Maximum Data Length of the Command
+ *  @capability None
+ */
+EXPORT_C TInt CSmsCommand::MaxCommandDataLength() const
+	{
+	LOGGSMU1("CSmsCommand::MaxCommandDataLength()");
+
+	return iCommandData->MaxDataLength();
+	} // CSmsCommand::MaxCommandDataLength
+
+
+/**
+ *  Gets the Command Data.
+ *  
+ *  @return The Command Data
+ *  @capability None
+ */
+EXPORT_C TPtrC8 CSmsCommand::CommandData() const
+	{
+	LOGGSMU1("CSmsCommand::CommandData()");
+
+	return iCommandData->Data();
+	} // CSmsCommand::CommandData
+
+
+/**
+ *  Sets the Command Data.
+ *  
+ *  @param aData The Command Data
+ *  @capability None
+ */
+EXPORT_C void CSmsCommand::SetCommandDataL(const TDesC8& aData)
+	{
+	LOGGSMU1("CSmsCommand::SetCommandDataL()");
+
+	iCommandData->SetDataL(aData);
+	} // CSmsCommand::SetCommandDataL
+
+
+const TSmsProtocolIdentifier* CSmsCommand::ProtocolIdentifier() const
+	{
+	LOGGSMU1("CSmsCommand::ProtocolIdentifier()");
+
+	return &iProtocolIdentifier;
+	} // CSmsCommand::ProtocolIdentifier
+
+
+const CSmsAddress* CSmsCommand::ToFromAddressPtr() const
+	{
+	LOGGSMU1("CSmsCommand::ToFromAddressPtr()");
+
+	return iDestinationAddress;
+	} // CSmsCommand::ToFromAddressPtr
+
+
+void CSmsCommand::ConstructL(CCnvCharacterSetConverter& aCharacterSetConverter,RFs& aFs)
+	{
+	LOGGSMU1("CSmsCommand::ConstructL()");
+
+	iServiceCenterAddress=CSmsAddress::NewL(aCharacterSetConverter,aFs);
+	iDestinationAddress=CSmsAddress::NewL(aCharacterSetConverter,aFs);
+	iCommandData=CSmsCommandData::NewL(iFirstOctet);
+	} // CSmsCommand::ConstructL
+
+
+/**
+ *  Duplicates this CSmsCommand object.
+ * 
+ *  @return  Pointer to the newly created CSmsCommand object.
+ */
+EXPORT_C CSmsCommand* CSmsCommand::DuplicateL() const
+	{
+	LOGGSMU1("CSmsCommand::DuplicateL()");
+
+	CSmsCommand*  smsCommand = new (ELeave) CSmsCommand();
+	CleanupStack::PushL(smsCommand);
+
+	smsCommand->iServiceCenterAddress      = iServiceCenterAddress->DuplicateL();
+	smsCommand->iFirstOctet                = iFirstOctet;
+	smsCommand->iMessageReference          = iMessageReference;
+	smsCommand->iProtocolIdentifier        = iProtocolIdentifier;
+	smsCommand->iCommandType               = iCommandType;
+	smsCommand->iMessageNumber             = iMessageNumber;
+	smsCommand->iDestinationAddress        = iDestinationAddress->DuplicateL();
+	smsCommand->iCommandData               = iCommandData->DuplicateL();
+
+	CleanupStack::Pop(smsCommand);
+
+	return smsCommand;
+	} // CSmsCommand::DuplicateL
+
+
+TUint8* CSmsCommand::EncodeL(TUint8* aPtr) const
+	{
+	LOGGSMU1("CSmsCommand::EncodeL()");
+
+	aPtr=iFirstOctet.EncodeL(aPtr);
+	aPtr=iMessageReference.EncodeL(aPtr);
+	aPtr=iProtocolIdentifier.EncodeL(aPtr);
+	aPtr=iCommandType.EncodeL(aPtr);
+	aPtr=iMessageNumber.EncodeL(aPtr);
+	aPtr=iDestinationAddress->EncodeL(aPtr);
+	return iCommandData->EncodeL(aPtr);
+	} // CSmsCommand::EncodeL
+
+TUint8* CSmsCommand::EncodeL(TUint8* aPtr, const TEncodeParams* ) const
+    {
+    // Ignore in code coverage - not used in SMS stack and not exported
+    // but cannot be removed as impacts public header.
+    BULLSEYE_OFF
+    return EncodeL(aPtr);
+    BULLSEYE_RESTORE
+    }	
+
+void CSmsCommand::DecodeL(TGsmuLex8& aPdu)
+	{
+	LOGGSMU1("CSmsCommand::DecodeL()");
+
+	iFirstOctet.DecodeL(aPdu);
+	iMessageReference.DecodeL(aPdu);
+	iProtocolIdentifier.DecodeL(aPdu);
+	iCommandType.DecodeL(aPdu);
+	iMessageNumber.DecodeL(aPdu);
+	iDestinationAddress->DecodeL(aPdu);
+	iCommandData->DecodeL(aPdu);
+	} // CSmsCommand::DecodeL
+
+
+void CSmsCommand::InternalizeMessagePDUL(RReadStream& aStream)
+	{
+	iServiceCenterAddress->InternalizeL(aStream);
+
+	aStream >> iFirstOctet;
+	aStream >> iMessageReference;
+	aStream >> iProtocolIdentifier;
+	aStream >> iCommandType;
+	aStream >> iMessageNumber;
+	iDestinationAddress->InternalizeL(aStream);
+	iCommandData->InternalizeL(aStream);
+	} // CSmsCommand::InternalizeMessagePDUL
+
+
+void CSmsCommand::ExternalizeMessagePDUL(RWriteStream& aStream) const
+	{
+	iServiceCenterAddress->ExternalizeL(aStream);
+
+	aStream << iFirstOctet;
+	aStream << iMessageReference;
+	aStream << iProtocolIdentifier;
+	aStream << iCommandType;
+	aStream << iMessageNumber;
+	iDestinationAddress->ExternalizeL(aStream);
+	iCommandData->ExternalizeL(aStream);
+	} // CSmsCommand::ExternalizeMessagePDUL
+
+
+void CSmsCommand::DoSetStatusReportRequest(TBool aRequest)
+	{
+	LOGGSMU1("CSmsCommand::DoSetStatusReportRequest()");
+
+	iFirstOctet=aRequest? (iFirstOctet&(~TSmsFirstOctet::ESmsStatusReportRequestMask)|TSmsFirstOctet::ESmsStatusReportRequested):
+	                      (iFirstOctet&(~TSmsFirstOctet::ESmsStatusReportRequestMask)|TSmsFirstOctet::ESmsAcceptDuplicates);
+	} // CSmsCommand::DoSetStatusReportRequest