cbsref/telephonyrefplugins/atltsy/atcommand/sms/src/smsatutil.cpp
branchRCL_3
changeset 65 630d2f34d719
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cbsref/telephonyrefplugins/atltsy/atcommand/sms/src/smsatutil.cpp	Tue Aug 31 16:23:08 2010 +0300
@@ -0,0 +1,447 @@
+// Copyright (c) 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:
+// @file smsatutil.cpp
+// This contains SmsAtUtil which is util for Sms At command
+// 
+
+// user include
+#include "smsatutil.h"
+#include "ltsycommondefine.h"
+#include "panic.h"
+
+/**
+ * Receive PDU example 
+ * 0891683108200805F0040D91683188902848F4000850208151754500108FD9662F4E0067616D4B8BD577ED4FE1
+ * 08 ocet length including 91
+ * 91 Identify Address Type
+ * 683108200805F0 SCA address
+ * 04
+ * 0D91683188902848F4
+ * 00
+ * 08
+ * 50208151754500
+ * 10   
+ * 8FD9662F4E0067616D4B8BD577ED4FE1
+ */
+// ---------------------------------------------------------------------------
+// SmsAtUtil::ConvertAsciiToBinary
+// other items were commented in a header
+// ---------------------------------------------------------------------------
+TInt SmsAtUtil::ConvertAsciiToBinary(const TDesC8& aAscii,TDes8& aData)
+	{
+	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;
+	}
+
+// -------------------------------------------------------------------------------
+// SmsAtUtil::AppendAddressToAscii
+// other items were commented in a header
+// -------------------------------------------------------------------------------
+TInt SmsAtUtil::AppendAddressToAscii(TDes8& aAscii,
+		                             const RMobilePhone::TMobileAddress& aAddress)
+	{
+	// Duplicate tel number, removing all the weird chars
+	TBuf<RMobilePhone::KMaxMobileTelNumberSize> telNumber;
+	const TInt count(aAddress.iTelNumber.Length());
+	// Validate the size of the supplied SCA
+    if(count >= RMobilePhone::KMaxMobileTelNumberSize)
+    	{
+    	return KErrOverflow;
+    	}
+	TInt i;
+	for(i = 0;i < count;++i)
+		{
+		if(IsAddressChar(TChar(aAddress.iTelNumber[i])))
+			telNumber.Append(aAddress.iTelNumber[i]);
+		}
+
+	const TInt telNumberLength(telNumber.Length());
+	
+	// Code Address-Length
+	AppendOctet(1 + (telNumberLength/2) + (telNumberLength%2),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;
+	}
+
+
+// ---------------------------------------------------------------------------
+// SmsAtUtil::AppendDataToAscii
+// other items were commented in a header
+// ---------------------------------------------------------------------------
+void SmsAtUtil::AppendDataToAscii(TDes8& aAscii,const TDesC8& aData)
+ 	{
+	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));
+	}
+
+// ----------------------------------------------------------------------------------
+// SmsAtUtil::ReadAndRemoveAddressFromAscii
+// other items were commented in a header
+// ----------------------------------------------------------------------------------
+TInt SmsAtUtil::ReadAndRemoveAddressFromAscii(TDes8& aAscii,
+		                                      RMobilePhone::TMobileAddress& aAddress)
+	{
+	__ASSERT_DEBUG(aAscii.Length()%2==0,Panic(EATSmsUtilsOddNumberOfSemiOctets));
+	TInt ret(KErrNone);
+
+	ret = ReadAddressFromAscii(aAscii,aAddress);
+	
+	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)
+			{
+			// +1 to include 1 octect of Address-Length 
+			val = val+1;		
+			
+			// double value to change from 'octets used' to 'ASCII chars used'
+			val = val*2;
+			
+			aAscii.Delete(0,val);		
+			__ASSERT_DEBUG(aAscii.Length()%2==0,Panic(EATSmsUtilsOddNumberOfSemiOctets));
+			}
+		}
+	return ret;
+	}
+
+// ---------------------------------------------------------------------------
+// SmsAtUtil::ReadAddressFromAscii
+// other items were commented in a header
+// ---------------------------------------------------------------------------
+TInt SmsAtUtil::ReadAddressFromAscii(const TDesC8& aAscii,
+		                             RMobilePhone::TMobileAddress& aAddress)
+	{
+	TLex8 lex;
+	TInt ret;
+	TUint8 val;
+	
+	// get address length + 1 octet Address Type(91)
+	lex = aAscii.Mid(0,2);
+	ret = lex.Val(val,EHex);
+	if(ret != KErrNone)
+		{
+		return ret;
+		}
+		
+	// we exclude the Address Type as address should not include this 
+	TInt addrLen = val-1;
+
+	// Type-Of-Number (see example above as 9)
+	lex = aAscii.Mid(2,1);
+	ret = lex.Val(val,EHex);
+	if(ret != KErrNone)
+		{
+		return ret;
+		}
+	
+	// Highest bit is not part of Type-Of-Number
+	aAddress.iTypeOfNumber = ConvertTypeOfNumber(val&0x07);	
+
+	// Number-Plan
+	lex = aAscii.Mid(3,1);
+	ret = lex.Val(val,EHex);
+	if(ret != KErrNone)
+		{
+		return ret;
+		}
+	
+	// we got Number-Plan which should be compatiable with Symbian defination
+	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;
+			}
+		// 0xF is consider a pedding when the address length is odd number, so we do not need to append it to address field
+		if(val < 0xF)
+			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;
+			}
+		
+		// 0xF is consider a pedding when the address length is odd number, so we do not need to append it to address field
+		if(val < 0xF)
+			aAddress.iTelNumber.Append(ConvertAddressChar(val));
+		}
+	return KErrNone;
+	}
+
+// ----------------------------------------------------------------------------------------
+// SmsAtUtil::ReadAndRemoveAddressFromPdu
+// other items were commented in a header
+// ----------------------------------------------------------------------------------------
+void SmsAtUtil::ReadAndRemoveAddressFromPdu(TPtrC8& aPdu, 
+		                                    RMobilePhone::TMobileAddress& aGsmServiceCentre)
+	{
+	const TUint8 KTONBitMask = 0x70;
+	const TUint8 KNPIBitMask = 0x0f;
+	const TUint8 KTONBitShift = 4;
+	const TUint8 KNPIBitShift = 0;
+	_LIT(KInternationalPrefix,"+");
+
+	aGsmServiceCentre.iTypeOfNumber = (RMobilePhone::TMobileTON)0;
+	aGsmServiceCentre.iNumberPlan = (RMobilePhone::TMobileNPI)0;
+	aGsmServiceCentre.iTelNumber.Zero();
+	
+	TUint8 len = aPdu[0];
+	
+	if(len == 0)
+		{
+		// A zero length SCA has been prepended - just strip this first byte off
+		aPdu.Set(aPdu.Mid(len+1));
+		return;
+		}
+
+	TUint8 numDes = aPdu[1];
+	aGsmServiceCentre.iTypeOfNumber = (RMobilePhone::TMobileTON)((numDes&KTONBitMask)>>KTONBitShift);
+	aGsmServiceCentre.iNumberPlan = (RMobilePhone::TMobileNPI)((numDes&KNPIBitMask)>>KNPIBitShift);
+
+	if(aGsmServiceCentre.iTypeOfNumber == RMobilePhone::EInternationalNumber)
+		aGsmServiceCentre.iTelNumber.Append(KInternationalPrefix);
+
+	TInt i;
+	TUint16 digit;
+	for(i = 2;i<(len+1);i++)
+		{
+		digit = (TUint16)((aPdu[i]&0x0f) + 0x30);
+		aGsmServiceCentre.iTelNumber.Append(digit);
+		digit = (TUint16)(((aPdu[i]&0xf0)>>4) + 0x30);
+		if(digit == 0x003f)		// 'F' is the padding digit at the end of a number
+			break;
+		aGsmServiceCentre.iTelNumber.Append(digit);
+		}
+	aPdu.Set(aPdu.Mid(len + 1));
+	}
+
+// ---------------------------------------------------------------------------
+// SmsAtUtil::IsAddressChar
+// other items were commented in a header
+// ---------------------------------------------------------------------------
+TBool SmsAtUtil::IsAddressChar(TChar aChar)
+ 	{
+	if(aChar.IsDigit())
+		{
+		return ETrue;
+		}
+	if(aChar == TChar('*') ||
+	   aChar == TChar('#') ||
+	   aChar == TChar('a') ||
+	   aChar == TChar('b') ||
+	   aChar == TChar('c'))
+		{
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+// ---------------------------------------------------------------------------
+// SmsAtUtil::ConvertNumberingPlan
+// other items were commented in a header
+// ---------------------------------------------------------------------------
+RMobilePhone::TMobileNPI SmsAtUtil::ConvertNumberingPlan(TInt 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;
+		}
+	}
+
+// ---------------------------------------------------------------------------
+// SmsAtUtil::ConvertTypeOfNumber
+// other items were commented in a header
+// ---------------------------------------------------------------------------
+RMobilePhone::TMobileTON SmsAtUtil::ConvertTypeOfNumber(TInt 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;
+		}
+	}
+
+// ---------------------------------------------------------------------------
+// SmsAtUtil::AppendOctet
+// other items were commented in a header
+// ---------------------------------------------------------------------------
+void SmsAtUtil::AppendOctet(TInt aOctet,TDes8& aAscii)
+	{
+	// 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);
+	}
+
+// ---------------------------------------------------------------------------
+// SmsAtUtil::ConvertAddressChar
+// other items were commented in a header
+// ---------------------------------------------------------------------------
+TInt SmsAtUtil::ConvertAddressChar(TChar aChar)
+ 	{
+	aChar.LowerCase();
+	if(aChar-TChar('0') <= 9)
+		{
+		// it should be digital number from 0~9
+		return aChar-TChar('0');
+		}
+	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;
+	}	
+
+// ---------------------------------------------------------------------------
+// SmsAtUtil::ConvertAddressChar
+// other items were commented in a header
+// ---------------------------------------------------------------------------
+TChar SmsAtUtil::ConvertAddressChar(TInt aBinary)
+	{
+	if(aBinary >= 0 && aBinary <= 9)
+		{
+		return 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 
+	}
+
+// End of file