telephonyserverplugins/simtsy/test/Te_SimSms/Te_SimSmsUtil.cpp
branchopencode
changeset 24 6638e7f4bd8f
parent 0 3553901f7fa8
--- a/telephonyserverplugins/simtsy/test/Te_SimSms/Te_SimSmsUtil.cpp	Mon May 03 13:37:20 2010 +0300
+++ b/telephonyserverplugins/simtsy/test/Te_SimSms/Te_SimSmsUtil.cpp	Thu May 06 15:10:38 2010 +0100
@@ -1,569 +1,569 @@
-// Copyright (c) 1997-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:
-//
-
-#include <etelmm.h> // for RMobilePhone::TMobileAddress
-#include "Te_SimSmsUtil.h"
-#include "Te_SimSmsPanic.h"
-
-//
-// Currently this file can not include the matstd file due to a dependency that
-// the test code t_sms has on this. So the constants needed are duplicated below.
-_LIT8(KMEStorage,"ME");
-_LIT8(KMTStorage,"MT");
-_LIT8(KSMStorage,"SM");
-
-//
-// Panic Function
-//
-GLDEF_C void Panic(TTSYPanic aPanicNumber)
-	{
-	_LIT(panicText,"MM TSY");
-	User::Panic(panicText,aPanicNumber);
-	}
-
-RMobilePhone::TMobileTON CATSmsUtils::ConvertTypeOfNumber(TInt aValue) 
-/**
- * @param aValue should be an ETSI Type-Of-Number field
- * @return The equivalent RMobilePhone::TMobileTON value for aValue
- */
-	{
-	switch(aValue)
-		{
-		// The below 'magic numbers' come from the ETSI 03.40
-		// specification for Address Fields (section 9.1.2.5)
-	case 0:		
-		return RMobilePhone::EUnknownNumber;
-	case 1:		
-		return RMobilePhone::EInternationalNumber;
-	case 2:
-		return RMobilePhone::ENationalNumber;
-	case 3:
-		return RMobilePhone::ENetworkSpecificNumber;
-	case 4:
-		return RMobilePhone::ESubscriberNumber;
-	default:
-		return RMobilePhone::EUnknownNumber;
-		}
-	
-	}
-
-TInt CATSmsUtils::ConvertTypeOfNumber(RMobilePhone::TMobileTON aEnum) 
-/**
- * @param aEnum must be a n RMobile::TMobileTON value 
- * @return The equivalent ETSI Type-Of-Number value for aEnum
- */
-	{
-	switch(aEnum)
-		{
-		// The below 'magic numbers' come from the ETSI 03.40
-		// specification for Address Fields (section 9.1.2.5)
-	case RMobilePhone::EInternationalNumber:
-		return 1;
-	case RMobilePhone::ENationalNumber:
-		return 2;
-	case RMobilePhone::ENetworkSpecificNumber:
-		return 3;
-	case RMobilePhone::ESubscriberNumber:
-		return 4;
-	case RMobilePhone::EUnknownNumber:
-	case RMobilePhone::EAbbreviatedNumber:
-	default:
-		return 0;
-		}
-	}
-
-RMobilePhone::TMobileNPI CATSmsUtils::ConvertNumberingPlan(TInt aValue)
-/**
- * @param aValue should be an ETSI Numbering-Plan-Identification field
- * @return The equivalent RMobilePhone::TMobileNPI value for aValue
- */
-	{
-	switch(aValue)
-		{
-		// The below 'magic numbers' come from the ETSI 03.40
-		// specification for Address Fields (section 9.1.2.5)
-	case 1:
-		return RMobilePhone::EIsdnNumberPlan;
-	case 3:
-		return RMobilePhone::EDataNumberPlan;
-	case 4:
-		return RMobilePhone::ETelexNumberPlan;
-	case 8:
-		return RMobilePhone::ENationalNumberPlan;
-	case 9:
-		return RMobilePhone::EPrivateNumberPlan;
-	default:
-		return RMobilePhone::EUnknownNumberingPlan;
-		}
-	}
-
-
-TInt CATSmsUtils::ConvertNumberingPlan(RMobilePhone::TMobileNPI aEnum)  
-/**
- * @param aEnum must be a n RMobile::TMobileNPI value 
- * @return The equivalent ETSI Numbering-Plan-Identification value for aEnum
- */
-	{
-	switch(aEnum)
-		{
-		// The below 'magic numbers' come from the ETSI 03.40
-		// specification for Address Fields (section 9.1.2.5)
-	case RMobilePhone::EIsdnNumberPlan:
-		return 1;
-	case RMobilePhone::EDataNumberPlan:
-		return 3;
-	case RMobilePhone::ETelexNumberPlan:
-		return 4;
-	case RMobilePhone::ENationalNumberPlan:
-		return 8;
-	case RMobilePhone::EPrivateNumberPlan:
-		return 9;
-	case RMobilePhone::EUnknownNumberingPlan:
-	default:
-		return 0;
-		}
-	}
-
-
-
-TInt CATSmsUtils::AppendAddressToAscii(TDes8& aAscii,const RMobilePhone::TMobileAddress& aAddress,TBool aUse0340Format)
-/**
- * Default operation is to code Address-Length according to=
- * 04.11 spec (ie. Address-Length=number of digits in Address-Value).
- *
- * If aUse0340Format argument is ETrue then Address Length will be coded using 
- * 03.40 format (ie. Address-Length=number of octets used for Address-Type
- * and Address-Value). 03.40 is typically only used when prefixing an SCA to a PDU.
- *
- * @return Standard KErr... values
- */
-	{
-	// Duplicate tel number, removing all the weird chars
-	TBuf<RMobilePhone::KMaxMobileTelNumberSize> telNumber;
-	const TInt count(aAddress.iTelNumber.Length());
-	TInt i;
-	for(i=0;i<count;++i)
-		{
-		if(IsAddressChar(TChar(aAddress.iTelNumber[i])))
-			telNumber.Append(aAddress.iTelNumber[i]);
-		}
-
-	const TInt telNumberLength(telNumber.Length());
-
-	// Validate the size of the supplied SCA
-
-	// Calculate the number of ascii chars we'll need
-	// We need 4 chars to code the Address-Length and Address-Type fields.
-	// We need to add on an extra 'padding' char if the total number of chars is odd.
-	const TInt neededAsciiChars=(4+telNumberLength)+(telNumberLength%2);
-	if((aAscii.MaxLength()-aAscii.Length())<neededAsciiChars)	
-		return KErrOverflow;
-
-	// Code Address-Length
-	if(aUse0340Format)
-		AppendOctet(1+(telNumberLength/2)+(telNumberLength%2),aAscii);
-	else
-		AppendOctet(telNumberLength,aAscii);
-
-	// Code Type-Of-Address
-	TInt typeOfNumber=ConvertTypeOfNumber(aAddress.iTypeOfNumber);
-	TInt numberingPlan=ConvertNumberingPlan(aAddress.iNumberPlan);
-	AppendOctet(0x80+(typeOfNumber<<4)+(numberingPlan),aAscii);
-
-	// Code Address-Value
-	TInt highSemiOctet;
-	TInt lowSemiOctet;
-	const TInt octets(telNumberLength/2);	// This division will be rounded down
-	for(i=0;i<octets;++i)
-		{
-		// See ETSI 03.40 section 9.1.2.3
-		// Address digits are coded into octets as pairs.
-		lowSemiOctet=ConvertAddressChar(TChar(telNumber[i*2]));
-		highSemiOctet=ConvertAddressChar(TChar(telNumber[(i*2)+1]));
-		AppendOctet((highSemiOctet<<4)+lowSemiOctet,aAscii);
-		}
-				
-	// If number of semi octects is odd then process the final octet
-	if(telNumberLength%2==1)		
-		{
-		lowSemiOctet=ConvertAddressChar(TChar(telNumber[telNumberLength-1]));
-		AppendOctet(0xf0+lowSemiOctet,aAscii);
-		}
-				
-	__ASSERT_DEBUG(aAscii.Length()%2==0,Panic(EATSmsUtilsOddNumberOfSemiOctets));
-	return KErrNone;
-	}
-
-
-void CATSmsUtils::AppendOctet(TInt aOctet,TDes8& aAscii)
-/**
- * Converts a TInt octet value into ASCII representation and then appends that
- * ASCII representation to the end of the given ASCII string.
- *
- * @param aOctet the octet value to append
- * @param aAscii the ASCII string to which aOctet value should be appended
- */
-	{
-	// Ensure client has only passed us a octet (ie. low 8 bits only)
-	aOctet=aOctet&0xff;
-
-	// Append octet 
-	// (prefix '0' if the octets value only uses one digit as final octet coding must use two digits)
-	if(aOctet<=0x0f)
-		aAscii.Append(TChar('0'));
-	aAscii.AppendNum(aOctet,EHex);
-	}
-
-
-TInt CATSmsUtils::ConvertAddressChar(TChar aChar)
-/**
- * Returns the equivalent numeric value for a given ASCII address character.
- *
- * @param aChar the address character to be converted
- * @return The numeric value equivalent of the given address character.
- */
- 	{
-	aChar.LowerCase();
-	if(aChar-TChar('0')<=9)  
-		return aChar-TChar('0');		// Assumes digit characters are one after each other
-	else if(aChar==TChar('*'))
-		return 10;
-	else if(aChar==TChar('#'))
-		return 11;
-	else if(aChar==TChar('a'))
-		return 12;
-	else if(aChar==TChar('b'))
-		return 13;
-	else if(aChar==TChar('c'))
-		return 14;
-	return 15;
-	}
-			
-TChar CATSmsUtils::ConvertAddressChar(TInt aBinary)
-/**
- * Returns the equivalent ASCII address character for a given address value.
- *
- * @param aBinary the numerix value of the address character to be returned
- * @return The ASCII charcater which represents the given address numeric value.
- */
-	{
-	if(aBinary>=0 && aBinary<=9)
-		return TChar(aBinary)+TChar('0');  	// Assumes digit characters are one after each other
-	else if(aBinary==10)
-		return TChar('*');
-	else if(aBinary==11)
-		return TChar('#');
-	else if(aBinary==12)
-		return TChar('a');
-	else if(aBinary==13)
-		return TChar('b');
-	else if(aBinary==14)
-		return TChar('c');
-	return TChar(0);		// This is the cloest I can find to a NULL char 
-	}
-
-
-
-TBool CATSmsUtils::IsAddressChar(TChar aChar)
-/**
- * Returns ETrue if, and only if, the given ASCII charcater is valid as an ASCII address character.
- */
- 	{
-	if(aChar.IsDigit())
-		return ETrue;
-	if(aChar==TChar('*') ||
-	   aChar==TChar('#') ||
-	   aChar==TChar('a') ||
-	   aChar==TChar('b') ||
-	   aChar==TChar('c'))
-		return ETrue;
-	return EFalse;
-	}
-
-
-void CATSmsUtils::AppendDataToAscii(TDes8& aAscii,const TDesC8& aData)
-/**
- * Appends the binary data (aData) onto the end of an ASCII string (aAscii) in ASCII format.
- */
- 	{
-	const TInt count(aData.Length());
-	__ASSERT_DEBUG((aAscii.MaxLength()-aAscii.MaxLength())<=(count*2),Panic(EATSmsUtilsDescriptorOverflow));
-
-	for(TInt i=0;i<count;++i)
-		AppendOctet(aData[i],aAscii);
-
-	__ASSERT_DEBUG(aAscii.Length()%2==0,Panic(EATSmsUtilsOddNumberOfSemiOctets));
-	}
-
-
-
-TInt CATSmsUtils::ConvertAsciiToBinary(const TDesC8& aAscii,TDes8& aData)
-/**
- * Converts aAscii ASCII chars to Semi Octets in aData.
- * One ASCII char (8bits in aAscii) is translated to one Semi-Octet (4bits in aData).
- * @return Standard KErr... values 
- */
-	{
-	__ASSERT_DEBUG(aAscii.Length()%2==0,Panic(EATSmsUtilsOddNumberOfSemiOctets));
-	__ASSERT_DEBUG(aData.MaxLength()>=(aAscii.Length()/2),Panic(EATSmsUtilsDescriptorOverflow));
-
-	aData.Zero();
-	TLex8 lex;
-	TUint8 val;
-	TInt ret;
-	const TInt count(aAscii.Length());
-	for(TInt i=0;i<count;i=i+2)
-		{
-		lex=aAscii.Mid(i,2);
-		ret=lex.Val(val,EHex);
-		if(ret!=KErrNone)
-			return ret;
-
-		aData.Append(val);
-		}
-		
-	return KErrNone;
-	}
-
-
-TInt CATSmsUtils::ReadAddressFromAscii(const TDesC8& aAscii,RMobilePhone::TMobileAddress& aAddress,TBool aPduUses0340Format)
-/**
- * Default operation assumes has prefixed SCA which uses 04.11 format
- * (ie. Address-Length=number of digits in Address-Value).
- *
- * If aUse0340Format argument is ETrue then Address Length will be coded using 
- * 03.40 format (ie. Address-Length=number of octets used for Address-Type
- * and Address-Value). 03.40 is typically only used when prefixing an SCA to a PDU.
- *
- * @return Standard KErr... values
- */
-	{
-	TLex8 lex;
-	TInt ret;
-	TUint8 val;
-
-	// Address-length
-	lex=aAscii.Mid(0,2);
-	ret=lex.Val(val,EHex);
-	if(ret!=KErrNone)
-		return ret;
-	
-	TInt addrLen;	// Will hold number of octets used to code Address-Value
-	if(aPduUses0340Format)
-		addrLen=val-1;
-	else
-		addrLen=(val/2)+(val%2);
-
-	// Type-Of-Number
-	lex=aAscii.Mid(2,1);
-	ret=lex.Val(val,EHex);
-	if(ret!=KErrNone)
-		return ret;
-	aAddress.iTypeOfNumber=ConvertTypeOfNumber(val&0x07);	// Highest bit is not part of Type-Of-Number
-
-	// Number-Plan
-	lex=aAscii.Mid(3,1);
-	ret=lex.Val(val,EHex);
-	if(ret!=KErrNone)
-		return ret;
-	aAddress.iNumberPlan=ConvertNumberingPlan(val);
-	
-	// Address (loop for each octet ie. two hex chars from aAscii)
-	aAddress.iTelNumber.Zero();
-	for(TInt i=0;i<addrLen;++i)		
-		{
-		// Process semi-octet
-		lex=aAscii.Mid((i*2)+5,1);
-		ret=lex.Val(val,EHex);
-		if(ret!=KErrNone)
-			return ret;
-		if(val<=14)
-			aAddress.iTelNumber.Append(ConvertAddressChar(val));
-
-		// Process semi-octet
-		lex=aAscii.Mid((i*2)+4,1);
-		ret=lex.Val(val,EHex);
-		if(ret!=KErrNone)
-			return ret;
-		if(val<=14)
-			aAddress.iTelNumber.Append(ConvertAddressChar(val));
-		}
-
-	return KErrNone;
-	}
-	
-
-TInt CATSmsUtils::ReadAndRemoveAddressFromAscii(TDes8& aAscii,RMobilePhone::TMobileAddress& aAddress,TBool aPduUses0340Format)
-/**
- * Reads an address from the front of the ASCII string (aAscii) and fills up Address structure (aAddress).
- * The address read from the ASCII string is removed from the ASCII string.
- */
-	{
-	__ASSERT_DEBUG(aAscii.Length()%2==0,Panic(EATSmsUtilsOddNumberOfSemiOctets));
-	TInt ret(KErrNone);
-
-	ret=ReadAddressFromAscii(aAscii,aAddress,aPduUses0340Format);
-	if(ret==KErrNone)
-		{
-		// Delete address from aAscii (using Address-length at start of string)
-		TLex8 lex(aAscii.Mid(0,2));
-		TUint val;
-		ret=lex.Val(val,EHex);
-		if(ret==KErrNone)
-			{
-			if(aPduUses0340Format)
-				{
-				// +1 to include Address-Length octect
-				val=val+1;		
-				
-				// double value to change from 'octets used' to 'ASCII chars used'
-				val=val*2;
-				}
-			else	
-				{
-				// Allow for the case where the last digit is actually a dummy digit
-				if(val%2!=0)
-					++val;
-				// +4 to include the Address-Length and Address-Type octets
-				val=val+4; 
-				}
-
-			aAscii.Delete(0,val);		
-			__ASSERT_DEBUG(aAscii.Length()%2==0,Panic(EATSmsUtilsOddNumberOfSemiOctets));
-			}
-		}
-			
-	return ret;
-	}
-
-
-TInt CATSmsUtils::CopyAddressStringToAddressStruct(const TDesC8& aAddressValueString,const TDesC8& aAddressTypeString,RMobilePhone::TMobileAddress& aAddress)
-/**
- * Analyse rx results for a CSCA response and attempt to parse into provided tel
- * number object
- * An example CSCA response would be '+CSCA: "00447785016005",129'.
- */
-	{
-	// Process Address-Type
-	TLex8 lex(aAddressTypeString);
-	TUint8 val;
-	TInt ret=lex.Val(val,EDecimal);
-	if(ret!=KErrNone)
-		return ret;
-	
-	aAddress.iTypeOfNumber=ConvertTypeOfNumber((TInt)((val&0x70)>>4));
-	aAddress.iNumberPlan=ConvertNumberingPlan((TInt)(val&0x0f));
-	
-	// Process Address-Value, filtering out non telephone chars
-	aAddress.iTelNumber.Zero();
-	const TInt len=aAddressValueString.Length();
-	TChar c;
-	for(TInt i=0;i<len;++i)
-		{
-		c=aAddressValueString[i];
-		if(IsAddressChar(c))
-			aAddress.iTelNumber.Append(c);
-		}
-			
-	return KErrNone;
-	}
-
-
-void CATSmsUtils::GetTypeOfAddressInDecimal(const RMobilePhone::TMobileAddress& aAddress, TUint& aVal)
-/**
- * Reads the type-of-number and numbering-plan contents of the address structure (aAddress) and
- * saves the equivalent decimal value in aVal.
- *
- * For example...
- *  if type-of-number is 'international' and numbering-plan is 'telephone' then aVal will be 145.
- *  if type-of-number is 'unknown' and numbering-plan is 'telephone' then aVal will be 129.
- */
- 	{
-	const TInt typeOfNumber=ConvertTypeOfNumber(aAddress.iTypeOfNumber);
-	const TInt numberingPlan=ConvertNumberingPlan(aAddress.iNumberPlan);
-	aVal=0x80+(typeOfNumber<<4)+numberingPlan;
-	}
-
-
-void CATSmsUtils::SetTypeOfAddressFromDecimal(RMobilePhone::TMobileAddress& aAddress,const TUint& aVal)
-/**
- * Uses the aVal decimal value and set the type-of-number and numbering-plan fields
- * of aAddress accordingly.
- * This is the opposite functionality to ::GetTypeOfAddressInDecimal
- */
-	{
-	aAddress.iTypeOfNumber=ConvertTypeOfNumber((aVal&0x70)>>4);
-	aAddress.iNumberPlan=ConvertNumberingPlan(aVal&0x0f);
-	}
-
-
-
-void CATSmsUtils::ConvertStoreNameToPhoneVersion(const TDesC& aEtelMMVersion,TDes8& aPhoneVersion)
-/**
- * Convert from Etel MultiMode API SMS store names to ETSI GSM store names
- */
- 	{
-	if(aEtelMMVersion.Compare(KETelMeSmsStore)==0)
-		{
-		aPhoneVersion.Copy(KMEStorage);
-		return;
-		}
-	if(aEtelMMVersion.Compare(KETelIccSmsStore)==0)
-		{
-		aPhoneVersion.Copy(KSMStorage);
-		return;
-		}
-	if(aEtelMMVersion.Compare(KETelCombinedSmsStore)==0)
-		{
-		aPhoneVersion.Copy(KMTStorage);
-		return;
-		}
-
-	// Panic if we are in debug build
-	__ASSERT_DEBUG(EFalse,Panic(EATSmsUtilsUnknownStoreName));
-
-	// Return the combined store if we are in release build
-	aPhoneVersion.Copy(KMTStorage);
-	}
-
-
-void CATSmsUtils::ConvertStoreNameToEtelMMVersion(TDes& aEtelMMVersion,const TDesC8& aPhoneVersion)
-/**
- * Convert from ETSI GSM store names to Etel MultiMode API SMS store names
- */
-	{
-	if(aPhoneVersion.Compare(KMEStorage)==0)
-		{
-		aEtelMMVersion.Copy(KETelMeSmsStore);
-		return;
-		}
-	if(aPhoneVersion.Compare(KSMStorage)==0)
-		{
-		aEtelMMVersion.Copy(KETelIccSmsStore);
-		return;
-		}
-	if(aPhoneVersion.Compare(KMTStorage)==0)
-		{
-		aEtelMMVersion.Copy(KETelCombinedSmsStore);
-		return;
-		}
-
-	// Panic if we are in debug build
-	__ASSERT_DEBUG(EFalse,Panic(EATSmsUtilsUnknownStoreName));
-
-	// Return the combined store if we are in release build
-	aEtelMMVersion.Copy(KETelCombinedSmsStore);
-	}
-
+// Copyright (c) 1997-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:
+//
+
+#include <etelmm.h> // for RMobilePhone::TMobileAddress
+#include "Te_SimSmsUtil.h"
+#include "Te_SimSmsPanic.h"
+
+//
+// Currently this file can not include the matstd file due to a dependency that
+// the test code t_sms has on this. So the constants needed are duplicated below.
+_LIT8(KMEStorage,"ME");
+_LIT8(KMTStorage,"MT");
+_LIT8(KSMStorage,"SM");
+
+//
+// Panic Function
+//
+GLDEF_C void Panic(TTSYPanic aPanicNumber)
+	{
+	_LIT(panicText,"MM TSY");
+	User::Panic(panicText,aPanicNumber);
+	}
+
+RMobilePhone::TMobileTON CATSmsUtils::ConvertTypeOfNumber(TInt aValue) 
+/**
+ * @param aValue should be an ETSI Type-Of-Number field
+ * @return The equivalent RMobilePhone::TMobileTON value for aValue
+ */
+	{
+	switch(aValue)
+		{
+		// The below 'magic numbers' come from the ETSI 03.40
+		// specification for Address Fields (section 9.1.2.5)
+	case 0:		
+		return RMobilePhone::EUnknownNumber;
+	case 1:		
+		return RMobilePhone::EInternationalNumber;
+	case 2:
+		return RMobilePhone::ENationalNumber;
+	case 3:
+		return RMobilePhone::ENetworkSpecificNumber;
+	case 4:
+		return RMobilePhone::ESubscriberNumber;
+	default:
+		return RMobilePhone::EUnknownNumber;
+		}
+	
+	}
+
+TInt CATSmsUtils::ConvertTypeOfNumber(RMobilePhone::TMobileTON aEnum) 
+/**
+ * @param aEnum must be a n RMobile::TMobileTON value 
+ * @return The equivalent ETSI Type-Of-Number value for aEnum
+ */
+	{
+	switch(aEnum)
+		{
+		// The below 'magic numbers' come from the ETSI 03.40
+		// specification for Address Fields (section 9.1.2.5)
+	case RMobilePhone::EInternationalNumber:
+		return 1;
+	case RMobilePhone::ENationalNumber:
+		return 2;
+	case RMobilePhone::ENetworkSpecificNumber:
+		return 3;
+	case RMobilePhone::ESubscriberNumber:
+		return 4;
+	case RMobilePhone::EUnknownNumber:
+	case RMobilePhone::EAbbreviatedNumber:
+	default:
+		return 0;
+		}
+	}
+
+RMobilePhone::TMobileNPI CATSmsUtils::ConvertNumberingPlan(TInt aValue)
+/**
+ * @param aValue should be an ETSI Numbering-Plan-Identification field
+ * @return The equivalent RMobilePhone::TMobileNPI value for aValue
+ */
+	{
+	switch(aValue)
+		{
+		// The below 'magic numbers' come from the ETSI 03.40
+		// specification for Address Fields (section 9.1.2.5)
+	case 1:
+		return RMobilePhone::EIsdnNumberPlan;
+	case 3:
+		return RMobilePhone::EDataNumberPlan;
+	case 4:
+		return RMobilePhone::ETelexNumberPlan;
+	case 8:
+		return RMobilePhone::ENationalNumberPlan;
+	case 9:
+		return RMobilePhone::EPrivateNumberPlan;
+	default:
+		return RMobilePhone::EUnknownNumberingPlan;
+		}
+	}
+
+
+TInt CATSmsUtils::ConvertNumberingPlan(RMobilePhone::TMobileNPI aEnum)  
+/**
+ * @param aEnum must be a n RMobile::TMobileNPI value 
+ * @return The equivalent ETSI Numbering-Plan-Identification value for aEnum
+ */
+	{
+	switch(aEnum)
+		{
+		// The below 'magic numbers' come from the ETSI 03.40
+		// specification for Address Fields (section 9.1.2.5)
+	case RMobilePhone::EIsdnNumberPlan:
+		return 1;
+	case RMobilePhone::EDataNumberPlan:
+		return 3;
+	case RMobilePhone::ETelexNumberPlan:
+		return 4;
+	case RMobilePhone::ENationalNumberPlan:
+		return 8;
+	case RMobilePhone::EPrivateNumberPlan:
+		return 9;
+	case RMobilePhone::EUnknownNumberingPlan:
+	default:
+		return 0;
+		}
+	}
+
+
+
+TInt CATSmsUtils::AppendAddressToAscii(TDes8& aAscii,const RMobilePhone::TMobileAddress& aAddress,TBool aUse0340Format)
+/**
+ * Default operation is to code Address-Length according to=
+ * 04.11 spec (ie. Address-Length=number of digits in Address-Value).
+ *
+ * If aUse0340Format argument is ETrue then Address Length will be coded using 
+ * 03.40 format (ie. Address-Length=number of octets used for Address-Type
+ * and Address-Value). 03.40 is typically only used when prefixing an SCA to a PDU.
+ *
+ * @return Standard KErr... values
+ */
+	{
+	// Duplicate tel number, removing all the weird chars
+	TBuf<RMobilePhone::KMaxMobileTelNumberSize> telNumber;
+	const TInt count(aAddress.iTelNumber.Length());
+	TInt i;
+	for(i=0;i<count;++i)
+		{
+		if(IsAddressChar(TChar(aAddress.iTelNumber[i])))
+			telNumber.Append(aAddress.iTelNumber[i]);
+		}
+
+	const TInt telNumberLength(telNumber.Length());
+
+	// Validate the size of the supplied SCA
+
+	// Calculate the number of ascii chars we'll need
+	// We need 4 chars to code the Address-Length and Address-Type fields.
+	// We need to add on an extra 'padding' char if the total number of chars is odd.
+	const TInt neededAsciiChars=(4+telNumberLength)+(telNumberLength%2);
+	if((aAscii.MaxLength()-aAscii.Length())<neededAsciiChars)	
+		return KErrOverflow;
+
+	// Code Address-Length
+	if(aUse0340Format)
+		AppendOctet(1+(telNumberLength/2)+(telNumberLength%2),aAscii);
+	else
+		AppendOctet(telNumberLength,aAscii);
+
+	// Code Type-Of-Address
+	TInt typeOfNumber=ConvertTypeOfNumber(aAddress.iTypeOfNumber);
+	TInt numberingPlan=ConvertNumberingPlan(aAddress.iNumberPlan);
+	AppendOctet(0x80+(typeOfNumber<<4)+(numberingPlan),aAscii);
+
+	// Code Address-Value
+	TInt highSemiOctet;
+	TInt lowSemiOctet;
+	const TInt octets(telNumberLength/2);	// This division will be rounded down
+	for(i=0;i<octets;++i)
+		{
+		// See ETSI 03.40 section 9.1.2.3
+		// Address digits are coded into octets as pairs.
+		lowSemiOctet=ConvertAddressChar(TChar(telNumber[i*2]));
+		highSemiOctet=ConvertAddressChar(TChar(telNumber[(i*2)+1]));
+		AppendOctet((highSemiOctet<<4)+lowSemiOctet,aAscii);
+		}
+				
+	// If number of semi octects is odd then process the final octet
+	if(telNumberLength%2==1)		
+		{
+		lowSemiOctet=ConvertAddressChar(TChar(telNumber[telNumberLength-1]));
+		AppendOctet(0xf0+lowSemiOctet,aAscii);
+		}
+				
+	__ASSERT_DEBUG(aAscii.Length()%2==0,Panic(EATSmsUtilsOddNumberOfSemiOctets));
+	return KErrNone;
+	}
+
+
+void CATSmsUtils::AppendOctet(TInt aOctet,TDes8& aAscii)
+/**
+ * Converts a TInt octet value into ASCII representation and then appends that
+ * ASCII representation to the end of the given ASCII string.
+ *
+ * @param aOctet the octet value to append
+ * @param aAscii the ASCII string to which aOctet value should be appended
+ */
+	{
+	// Ensure client has only passed us a octet (ie. low 8 bits only)
+	aOctet=aOctet&0xff;
+
+	// Append octet 
+	// (prefix '0' if the octets value only uses one digit as final octet coding must use two digits)
+	if(aOctet<=0x0f)
+		aAscii.Append(TChar('0'));
+	aAscii.AppendNum(aOctet,EHex);
+	}
+
+
+TInt CATSmsUtils::ConvertAddressChar(TChar aChar)
+/**
+ * Returns the equivalent numeric value for a given ASCII address character.
+ *
+ * @param aChar the address character to be converted
+ * @return The numeric value equivalent of the given address character.
+ */
+ 	{
+	aChar.LowerCase();
+	if(aChar-TChar('0')<=9)  
+		return aChar-TChar('0');		// Assumes digit characters are one after each other
+	else if(aChar==TChar('*'))
+		return 10;
+	else if(aChar==TChar('#'))
+		return 11;
+	else if(aChar==TChar('a'))
+		return 12;
+	else if(aChar==TChar('b'))
+		return 13;
+	else if(aChar==TChar('c'))
+		return 14;
+	return 15;
+	}
+			
+TChar CATSmsUtils::ConvertAddressChar(TInt aBinary)
+/**
+ * Returns the equivalent ASCII address character for a given address value.
+ *
+ * @param aBinary the numerix value of the address character to be returned
+ * @return The ASCII charcater which represents the given address numeric value.
+ */
+	{
+	if(aBinary>=0 && aBinary<=9)
+		return TChar(aBinary)+TChar('0');  	// Assumes digit characters are one after each other
+	else if(aBinary==10)
+		return TChar('*');
+	else if(aBinary==11)
+		return TChar('#');
+	else if(aBinary==12)
+		return TChar('a');
+	else if(aBinary==13)
+		return TChar('b');
+	else if(aBinary==14)
+		return TChar('c');
+	return TChar(0);		// This is the cloest I can find to a NULL char 
+	}
+
+
+
+TBool CATSmsUtils::IsAddressChar(TChar aChar)
+/**
+ * Returns ETrue if, and only if, the given ASCII charcater is valid as an ASCII address character.
+ */
+ 	{
+	if(aChar.IsDigit())
+		return ETrue;
+	if(aChar==TChar('*') ||
+	   aChar==TChar('#') ||
+	   aChar==TChar('a') ||
+	   aChar==TChar('b') ||
+	   aChar==TChar('c'))
+		return ETrue;
+	return EFalse;
+	}
+
+
+void CATSmsUtils::AppendDataToAscii(TDes8& aAscii,const TDesC8& aData)
+/**
+ * Appends the binary data (aData) onto the end of an ASCII string (aAscii) in ASCII format.
+ */
+ 	{
+	const TInt count(aData.Length());
+	__ASSERT_DEBUG((aAscii.MaxLength()-aAscii.MaxLength())<=(count*2),Panic(EATSmsUtilsDescriptorOverflow));
+
+	for(TInt i=0;i<count;++i)
+		AppendOctet(aData[i],aAscii);
+
+	__ASSERT_DEBUG(aAscii.Length()%2==0,Panic(EATSmsUtilsOddNumberOfSemiOctets));
+	}
+
+
+
+TInt CATSmsUtils::ConvertAsciiToBinary(const TDesC8& aAscii,TDes8& aData)
+/**
+ * Converts aAscii ASCII chars to Semi Octets in aData.
+ * One ASCII char (8bits in aAscii) is translated to one Semi-Octet (4bits in aData).
+ * @return Standard KErr... values 
+ */
+	{
+	__ASSERT_DEBUG(aAscii.Length()%2==0,Panic(EATSmsUtilsOddNumberOfSemiOctets));
+	__ASSERT_DEBUG(aData.MaxLength()>=(aAscii.Length()/2),Panic(EATSmsUtilsDescriptorOverflow));
+
+	aData.Zero();
+	TLex8 lex;
+	TUint8 val;
+	TInt ret;
+	const TInt count(aAscii.Length());
+	for(TInt i=0;i<count;i=i+2)
+		{
+		lex=aAscii.Mid(i,2);
+		ret=lex.Val(val,EHex);
+		if(ret!=KErrNone)
+			return ret;
+
+		aData.Append(val);
+		}
+		
+	return KErrNone;
+	}
+
+
+TInt CATSmsUtils::ReadAddressFromAscii(const TDesC8& aAscii,RMobilePhone::TMobileAddress& aAddress,TBool aPduUses0340Format)
+/**
+ * Default operation assumes has prefixed SCA which uses 04.11 format
+ * (ie. Address-Length=number of digits in Address-Value).
+ *
+ * If aUse0340Format argument is ETrue then Address Length will be coded using 
+ * 03.40 format (ie. Address-Length=number of octets used for Address-Type
+ * and Address-Value). 03.40 is typically only used when prefixing an SCA to a PDU.
+ *
+ * @return Standard KErr... values
+ */
+	{
+	TLex8 lex;
+	TInt ret;
+	TUint8 val;
+
+	// Address-length
+	lex=aAscii.Mid(0,2);
+	ret=lex.Val(val,EHex);
+	if(ret!=KErrNone)
+		return ret;
+	
+	TInt addrLen;	// Will hold number of octets used to code Address-Value
+	if(aPduUses0340Format)
+		addrLen=val-1;
+	else
+		addrLen=(val/2)+(val%2);
+
+	// Type-Of-Number
+	lex=aAscii.Mid(2,1);
+	ret=lex.Val(val,EHex);
+	if(ret!=KErrNone)
+		return ret;
+	aAddress.iTypeOfNumber=ConvertTypeOfNumber(val&0x07);	// Highest bit is not part of Type-Of-Number
+
+	// Number-Plan
+	lex=aAscii.Mid(3,1);
+	ret=lex.Val(val,EHex);
+	if(ret!=KErrNone)
+		return ret;
+	aAddress.iNumberPlan=ConvertNumberingPlan(val);
+	
+	// Address (loop for each octet ie. two hex chars from aAscii)
+	aAddress.iTelNumber.Zero();
+	for(TInt i=0;i<addrLen;++i)		
+		{
+		// Process semi-octet
+		lex=aAscii.Mid((i*2)+5,1);
+		ret=lex.Val(val,EHex);
+		if(ret!=KErrNone)
+			return ret;
+		if(val<=14)
+			aAddress.iTelNumber.Append(ConvertAddressChar(val));
+
+		// Process semi-octet
+		lex=aAscii.Mid((i*2)+4,1);
+		ret=lex.Val(val,EHex);
+		if(ret!=KErrNone)
+			return ret;
+		if(val<=14)
+			aAddress.iTelNumber.Append(ConvertAddressChar(val));
+		}
+
+	return KErrNone;
+	}
+	
+
+TInt CATSmsUtils::ReadAndRemoveAddressFromAscii(TDes8& aAscii,RMobilePhone::TMobileAddress& aAddress,TBool aPduUses0340Format)
+/**
+ * Reads an address from the front of the ASCII string (aAscii) and fills up Address structure (aAddress).
+ * The address read from the ASCII string is removed from the ASCII string.
+ */
+	{
+	__ASSERT_DEBUG(aAscii.Length()%2==0,Panic(EATSmsUtilsOddNumberOfSemiOctets));
+	TInt ret(KErrNone);
+
+	ret=ReadAddressFromAscii(aAscii,aAddress,aPduUses0340Format);
+	if(ret==KErrNone)
+		{
+		// Delete address from aAscii (using Address-length at start of string)
+		TLex8 lex(aAscii.Mid(0,2));
+		TUint val;
+		ret=lex.Val(val,EHex);
+		if(ret==KErrNone)
+			{
+			if(aPduUses0340Format)
+				{
+				// +1 to include Address-Length octect
+				val=val+1;		
+				
+				// double value to change from 'octets used' to 'ASCII chars used'
+				val=val*2;
+				}
+			else	
+				{
+				// Allow for the case where the last digit is actually a dummy digit
+				if(val%2!=0)
+					++val;
+				// +4 to include the Address-Length and Address-Type octets
+				val=val+4; 
+				}
+
+			aAscii.Delete(0,val);		
+			__ASSERT_DEBUG(aAscii.Length()%2==0,Panic(EATSmsUtilsOddNumberOfSemiOctets));
+			}
+		}
+			
+	return ret;
+	}
+
+
+TInt CATSmsUtils::CopyAddressStringToAddressStruct(const TDesC8& aAddressValueString,const TDesC8& aAddressTypeString,RMobilePhone::TMobileAddress& aAddress)
+/**
+ * Analyse rx results for a CSCA response and attempt to parse into provided tel
+ * number object
+ * An example CSCA response would be '+CSCA: "00447785016005",129'.
+ */
+	{
+	// Process Address-Type
+	TLex8 lex(aAddressTypeString);
+	TUint8 val;
+	TInt ret=lex.Val(val,EDecimal);
+	if(ret!=KErrNone)
+		return ret;
+	
+	aAddress.iTypeOfNumber=ConvertTypeOfNumber((TInt)((val&0x70)>>4));
+	aAddress.iNumberPlan=ConvertNumberingPlan((TInt)(val&0x0f));
+	
+	// Process Address-Value, filtering out non telephone chars
+	aAddress.iTelNumber.Zero();
+	const TInt len=aAddressValueString.Length();
+	TChar c;
+	for(TInt i=0;i<len;++i)
+		{
+		c=aAddressValueString[i];
+		if(IsAddressChar(c))
+			aAddress.iTelNumber.Append(c);
+		}
+			
+	return KErrNone;
+	}
+
+
+void CATSmsUtils::GetTypeOfAddressInDecimal(const RMobilePhone::TMobileAddress& aAddress, TUint& aVal)
+/**
+ * Reads the type-of-number and numbering-plan contents of the address structure (aAddress) and
+ * saves the equivalent decimal value in aVal.
+ *
+ * For example...
+ *  if type-of-number is 'international' and numbering-plan is 'telephone' then aVal will be 145.
+ *  if type-of-number is 'unknown' and numbering-plan is 'telephone' then aVal will be 129.
+ */
+ 	{
+	const TInt typeOfNumber=ConvertTypeOfNumber(aAddress.iTypeOfNumber);
+	const TInt numberingPlan=ConvertNumberingPlan(aAddress.iNumberPlan);
+	aVal=0x80+(typeOfNumber<<4)+numberingPlan;
+	}
+
+
+void CATSmsUtils::SetTypeOfAddressFromDecimal(RMobilePhone::TMobileAddress& aAddress,const TUint& aVal)
+/**
+ * Uses the aVal decimal value and set the type-of-number and numbering-plan fields
+ * of aAddress accordingly.
+ * This is the opposite functionality to ::GetTypeOfAddressInDecimal
+ */
+	{
+	aAddress.iTypeOfNumber=ConvertTypeOfNumber((aVal&0x70)>>4);
+	aAddress.iNumberPlan=ConvertNumberingPlan(aVal&0x0f);
+	}
+
+
+
+void CATSmsUtils::ConvertStoreNameToPhoneVersion(const TDesC& aEtelMMVersion,TDes8& aPhoneVersion)
+/**
+ * Convert from Etel MultiMode API SMS store names to ETSI GSM store names
+ */
+ 	{
+	if(aEtelMMVersion.Compare(KETelMeSmsStore)==0)
+		{
+		aPhoneVersion.Copy(KMEStorage);
+		return;
+		}
+	if(aEtelMMVersion.Compare(KETelIccSmsStore)==0)
+		{
+		aPhoneVersion.Copy(KSMStorage);
+		return;
+		}
+	if(aEtelMMVersion.Compare(KETelCombinedSmsStore)==0)
+		{
+		aPhoneVersion.Copy(KMTStorage);
+		return;
+		}
+
+	// Panic if we are in debug build
+	__ASSERT_DEBUG(EFalse,Panic(EATSmsUtilsUnknownStoreName));
+
+	// Return the combined store if we are in release build
+	aPhoneVersion.Copy(KMTStorage);
+	}
+
+
+void CATSmsUtils::ConvertStoreNameToEtelMMVersion(TDes& aEtelMMVersion,const TDesC8& aPhoneVersion)
+/**
+ * Convert from ETSI GSM store names to Etel MultiMode API SMS store names
+ */
+	{
+	if(aPhoneVersion.Compare(KMEStorage)==0)
+		{
+		aEtelMMVersion.Copy(KETelMeSmsStore);
+		return;
+		}
+	if(aPhoneVersion.Compare(KSMStorage)==0)
+		{
+		aEtelMMVersion.Copy(KETelIccSmsStore);
+		return;
+		}
+	if(aPhoneVersion.Compare(KMTStorage)==0)
+		{
+		aEtelMMVersion.Copy(KETelCombinedSmsStore);
+		return;
+		}
+
+	// Panic if we are in debug build
+	__ASSERT_DEBUG(EFalse,Panic(EATSmsUtilsUnknownStoreName));
+
+	// Return the combined store if we are in release build
+	aEtelMMVersion.Copy(KETelCombinedSmsStore);
+	}
+