networkprotocolmodules/common/suplrrlpasn1/src/suplmessagebase.cpp
changeset 57 3267d9ea3e98
parent 48 81c9bee26a45
child 61 a2244af7b395
equal deleted inserted replaced
48:81c9bee26a45 57:3267d9ea3e98
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @internalTechnology
       
    19  
       
    20 */
       
    21 
       
    22 #include "ULP.h"
       
    23 #include "suplmessagebase.h"
       
    24 #include "suplpos.h"
       
    25 #include "supldevloggermacros.h" 
       
    26 #include "suplrrlpasn1common.h"
       
    27 #include <lbssatellite.h>
       
    28 #include <lbs/lbsgpsmeasurement.h>
       
    29 #include <lbs/lbsnetcommon.h>
       
    30 #include <lbspositioninfo.h>
       
    31 #include <lbsposition.h>
       
    32 #include <reent.h>
       
    33 
       
    34 /** 
       
    35 Default constructor
       
    36 */
       
    37 CSuplMessageBase::CSuplMessageBase(TSuplMessageType aType, TBool aIsOutgoingMessage)
       
    38  : iSuplMessageType(aType), iIsOutgoingMessage(aIsOutgoingMessage)
       
    39 	{
       
    40 	}
       
    41 	
       
    42 /** 
       
    43 Destructor
       
    44 */
       
    45 CSuplMessageBase::~CSuplMessageBase()
       
    46 	{
       
    47 	SUPLLOG(ELogP1, "CSuplMessageBase::~CSuplMessageBase() Begin\n");
       
    48 	delete iControl;
       
    49 	delete iData;
       
    50 	delete iEncodeBuffer;
       
    51 	// release the STDLIB resources associated with this thread
       
    52 	CloseSTDLIB();
       
    53 	SUPLLOG(ELogP1, "CSuplMessageBase::~CSuplMessageBase() End\n");
       
    54 	}
       
    55 	
       
    56 /** 
       
    57 Second stage constructor 
       
    58 
       
    59 Outgoing messages: constructs the data encapsulation and control objects.
       
    60 Incoming message: no action
       
    61 */
       
    62 void CSuplMessageBase::ConstructL()
       
    63 	{
       
    64 	if (iIsOutgoingMessage)
       
    65 		{
       
    66 		iData    = new (ELeave) ASN1T_ULP_PDU();
       
    67 		ASN1Context* context = new (ELeave) ASN1Context;
       
    68 		CleanupDeletePushL(context);
       
    69 		iControl = new (ELeave) ASN1C_ULP_PDU(*context, *iData);
       
    70 		// construction of iControl successful, pop context off the cleanup stack
       
    71 		CleanupStack::Pop(context);
       
    72 
       
    73 		// set the version parameter of the outgoing message
       
    74 		iData->version.maj = 1;
       
    75 		iData->version.min = 0;
       
    76 		iData->version.servind = 0;
       
    77 		}
       
    78 	}
       
    79 	
       
    80 
       
    81 /** 
       
    82 EncodeToL()
       
    83 
       
    84 Encode a populated outgoing message to the specified buffer.
       
    85 
       
    86 @param  aBuf buffer pointer 
       
    87 @return error indication, KErrNone otherwise
       
    88 */
       
    89 EXPORT_C TInt CSuplMessageBase::EncodeToL(TPtr8& aBuf)
       
    90 	{
       
    91 	SUPLLOG(ELogP1, "CSuplMessageBase::EncodeToL() Begin\n");
       
    92 	__ASSERT_DEBUG(iIsOutgoingMessage, User::Invariant());
       
    93 
       
    94 	TInt retval = KErrNone;
       
    95 	
       
    96 	// buffer pointer, fixed max length
       
    97 	TUint8* msgBuf = (TUint8*)aBuf.Ptr();
       
    98 	TInt maxLength = aBuf.MaxLength();
       
    99 	
       
   100 	// Log the un-encoded SUPL values
       
   101 	SUPLLOG(ELogP9, "-> ENCODING SUPL MESSAGE FOR SENDING\n");
       
   102 	//LogMessageContent();
       
   103 	
       
   104 	// if the message is a SUPL POS, encode the payload
       
   105 	if (iData->message.t == T_UlpMessage_msSUPLPOS)
       
   106 		{
       
   107 		CSuplPos* suplPos = reinterpret_cast <CSuplPos*>(this);
       
   108 		retval = suplPos->EncodePosPayloadL();
       
   109 		if (retval != KErrNone)
       
   110 			{
       
   111 			SUPLLOG(ELogP1, "CSuplMessageBase::EncodeToL() Error encoding Positioning Payload\n");
       
   112 			return retval;
       
   113 			}
       
   114 		}
       
   115 		
       
   116 	// construct the encode buffer control object
       
   117 	iEncodeBuffer = new (ELeave) ASN1PEREncodeBuffer (msgBuf, (unsigned int)maxLength, FALSE, (OSRTContext*)iControl->getContext());
       
   118 	
       
   119 	// Encode the message to the buffer
       
   120 	TInt stat = iControl->EncodeTo(*iEncodeBuffer);
       
   121 
       
   122 	if (stat == 0)
       
   123 		{
       
   124 		// Set the length according to reported buffer length
       
   125 		TInt len = iEncodeBuffer->getMsgLen ();
       
   126 		iData->length = len;
       
   127 		aBuf.SetLength(len);
       
   128 		
       
   129 		// clear the encoded length field
       
   130 		msgBuf[0] = 0;
       
   131 		msgBuf[1] = 0;
       
   132 
       
   133 		// set the encoded length field
       
   134       	msgBuf[0] |= (TUint8)( len >> 8 );
       
   135 		msgBuf[1] |= (TUint8)( len );
       
   136 		}
       
   137 	else
       
   138 		{
       
   139 		retval = ProcessAsn1Error(stat);
       
   140 		}
       
   141 	
       
   142 	// finished with encode buffer object
       
   143 	delete iEncodeBuffer;
       
   144 	iEncodeBuffer = NULL;
       
   145 
       
   146 	// Log the encoded ASN1	
       
   147 	SUPLLOG(ELogP8, "-> ENCODED SUPL MESSAGE FOR SENDING (HEX)\n");
       
   148 	SUPLLOGHEX(ELogP8, aBuf.Ptr(), aBuf.Length());
       
   149 
       
   150 	SUPLLOG2(ELogP1, "CSuplMessageBase::EncodeToL() End (retval = %d)\n", retval);
       
   151 	return retval;
       
   152 	}
       
   153 
       
   154 /** 
       
   155 SetDecodedData()
       
   156 
       
   157 Assign decoded ASN1 data, for received messages.
       
   158 Takes ownership of passed objects.
       
   159 
       
   160 @param aData    data structure containing decoded message parameters
       
   161 @param aControl control structure associated with decoded data structure.
       
   162 */
       
   163 void CSuplMessageBase::SetDecodedData(ASN1T_ULP_PDU* aData, ASN1C_ULP_PDU* aControl)
       
   164 	{
       
   165 	SUPLLOG(ELogP1, "CSuplMessageBase::SetDecodedData() Begin\n");
       
   166 	__ASSERT_DEBUG(!iIsOutgoingMessage, User::Invariant());
       
   167 	iData = aData;
       
   168 	iControl = aControl;
       
   169 	SUPLLOG(ELogP1, "CSuplMessageBase::SetDecodedData() End\n");
       
   170 	}
       
   171 
       
   172 
       
   173 /** 
       
   174 SetVersion()
       
   175 
       
   176 Set the SUPL version used 
       
   177 @param aVersion SUPL version in use
       
   178 */
       
   179 EXPORT_C void CSuplMessageBase::SetVersion(CSuplVersion& aVersion)
       
   180 	{
       
   181 	SUPLLOG(ELogP1, "CSuplMessageBase::SetVersion() Begin\n");
       
   182 	__ASSERT_DEBUG(iIsOutgoingMessage, User::Invariant());
       
   183 	
       
   184 	SUPLLOG2(ELogP1, "    - TInt iMaj = %d\n", aVersion.iMaj);
       
   185 	SUPLLOG2(ELogP1, "    - TInt iMin = %d\n", aVersion.iMin);
       
   186 	SUPLLOG2(ELogP1, "    - TInt iServind = %d\n", aVersion.iServind);
       
   187 	
       
   188 	iData->version.maj = aVersion.iMaj;
       
   189 	iData->version.min = aVersion.iMin;
       
   190 	iData->version.servind =  aVersion.iServind;
       
   191 	SUPLLOG(ELogP1, "CSuplMessageBase::SetVersion() End\n");
       
   192 	}
       
   193 	
       
   194 
       
   195 /** 
       
   196 SetSessionId()
       
   197 
       
   198 Set the SUPL Session ID
       
   199 @param aSessionId session identifier
       
   200 */
       
   201 EXPORT_C TInt CSuplMessageBase::SetSessionId(CSuplSessionId& aSessionId)
       
   202 	{
       
   203 	SUPLLOG(ELogP1, "CSuplMessageBase::SetSessionId() Begin\n");
       
   204 	__ASSERT_DEBUG(iIsOutgoingMessage, User::Invariant());
       
   205 	
       
   206 	// local reference to context object
       
   207 	OSCTXT* pctxt = iControl->getCtxtPtr();
       
   208 	
       
   209 	// populate SET Session ID, if present
       
   210 	// note this should always be present as this method is for building 
       
   211 	// outgoing messages.
       
   212 	if (aSessionId.iSetSessionIdPresent)
       
   213 		{
       
   214 		iData->sessionID.m.setSessionIDPresent = 1;
       
   215 		
       
   216 		// SET Session ID / Session ID
       
   217 		iData->sessionID.setSessionID.sessionId = aSessionId.iSetSessionId->iSessionId;
       
   218 
       
   219 		// SET Session ID / SET ID
       
   220 		ASN1T_SETId& setId = iData->sessionID.setSessionID.setId;
       
   221 		switch (aSessionId.iSetSessionId->iSetId->iSetIdType)
       
   222 			{	
       
   223 		  	case ESuplSetIdTypeIPAddress:
       
   224 		  		{
       
   225 		  		// ID is based on IP Address
       
   226 	  			setId.t =  T_SETId_iPAddress;
       
   227 				setId.u.iPAddress = (ASN1T_IPAddress*)rtxMemAllocZ(pctxt, sizeof(ASN1T_IPAddress));
       
   228 				if (iControl->getStatus() != 0)
       
   229 					{
       
   230 					SUPLLOG(ELogP1, "CSuplMessageBase::SetSessionId() Error, out of memory\n");
       
   231 					return KErrNoMemory;
       
   232 					}				
       
   233 
       
   234 				if (aSessionId.iSetSessionId->iSetId->iIpAddress->iIpAddressType == ESuplIpAddressTypeV6)
       
   235 					{
       
   236 					setId.u.iPAddress->t =  T_IPAddress_ipv6Address;
       
   237 					setId.u.iPAddress->u.ipv6Address = (ASN1T_IPAddress_ipv6Address*)rtxMemAllocZ(pctxt, sizeof(ASN1T_IPAddress_ipv6Address));
       
   238 					if (iControl->getStatus() != 0)
       
   239 						{
       
   240 						SUPLLOG(ELogP1, "CSuplMessageBase::SetSessionId() Error, out of memory\n");
       
   241 						return KErrNoMemory;
       
   242 						}					
       
   243 
       
   244 					TInt len = aSessionId.iSetSessionId->iSetId->iIpAddress->iIpAddress.Length();
       
   245 					void* data = (void*)aSessionId.iSetSessionId->iSetId->iIpAddress->iIpAddress.Ptr();
       
   246 					memcpy ((void*)setId.u.iPAddress->u.ipv6Address->data, data, len);
       
   247 					setId.u.iPAddress->u.ipv6Address->numocts = len;
       
   248 					}
       
   249 				else
       
   250 					{
       
   251 					setId.u.iPAddress->t =  T_IPAddress_ipv4Address;
       
   252 					setId.u.iPAddress->u.ipv4Address = (ASN1T_IPAddress_ipv4Address*)rtxMemAllocZ(pctxt, sizeof(ASN1T_IPAddress_ipv4Address));
       
   253 					if (iControl->getStatus() != 0)
       
   254 						{
       
   255 						SUPLLOG(ELogP1, "CSuplMessageBase::SetSessionId() Error, out of memory\n");
       
   256 						return KErrNoMemory;
       
   257 						}					
       
   258 
       
   259 					TInt len = aSessionId.iSetSessionId->iSetId->iIpAddress->iIpAddress.Length();
       
   260 					void* data = (void*)aSessionId.iSetSessionId->iSetId->iIpAddress->iIpAddress.Ptr();
       
   261 					memcpy ((void*)setId.u.iPAddress->u.ipv4Address->data, data, len);
       
   262 					setId.u.iPAddress->u.ipv4Address->numocts = len;
       
   263 					}
       
   264 				break;
       
   265 		  		}
       
   266 
       
   267 			case ESuplSetIdTypeMsisdn:
       
   268 				{
       
   269 				setId.t = T_SETId_msisdn;
       
   270 				setId.u.msisdn = (ASN1T_SETId_msisdn*)rtxMemAllocZ(pctxt, sizeof(ASN1T_SETId_msisdn));
       
   271 				if (iControl->getStatus() != 0)
       
   272 					{
       
   273 					SUPLLOG(ELogP1, "CSuplMessageBase::SetSessionId() Error, out of memory\n");
       
   274 					return KErrNoMemory;
       
   275 					}				
       
   276 				TInt len = aSessionId.iSetSessionId->iSetId->iSetId.Length();
       
   277 				void* data = (void*)aSessionId.iSetSessionId->iSetId->iSetId.Ptr();
       
   278 				memcpy ((void*)setId.u.msisdn->data, data, len);
       
   279 				setId.u.msisdn->numocts = len;
       
   280 				break;
       
   281 				}
       
   282 
       
   283 		  	case ESuplSetIdTypeMdn:
       
   284 		  		{
       
   285 				setId.t = T_SETId_mdn;
       
   286 				setId.u.mdn = (ASN1T_SETId_mdn*)rtxMemAllocZ(pctxt, sizeof(ASN1T_SETId_mdn));
       
   287 				if (iControl->getStatus() != 0)
       
   288 					{
       
   289 					SUPLLOG(ELogP1, "CSuplMessageBase::SetSessionId() Error, out of memory\n");
       
   290 					return KErrNoMemory;
       
   291 					}				
       
   292 				TInt len = aSessionId.iSetSessionId->iSetId->iSetId.Length();
       
   293 				void* data = (void*)aSessionId.iSetSessionId->iSetId->iSetId.Ptr();
       
   294 				memcpy ((void*)setId.u.mdn->data, data, len);
       
   295 				setId.u.mdn->numocts = len;
       
   296 				break;
       
   297 				}
       
   298 
       
   299 		  	case ESuplSetIdTypeMin:
       
   300 		  		{
       
   301 				setId.t = T_SETId_min;
       
   302 				setId.u.min = (ASN1T_SETId_min*)rtxMemAllocZ(pctxt, sizeof(ASN1T_SETId_min));
       
   303 				if (iControl->getStatus() != 0)
       
   304 					{
       
   305 					SUPLLOG(ELogP1, "CSuplMessageBase::SetSessionId() Error, out of memory\n");
       
   306 					return KErrNoMemory;
       
   307 					}				
       
   308 				TInt len = aSessionId.iSetSessionId->iSetId->iSetId.Length();
       
   309 				void* data = (void*)aSessionId.iSetSessionId->iSetId->iSetId.Ptr();
       
   310 				memcpy ((void*)setId.u.min->data, data, len);
       
   311 				setId.u.min->numbits = len*8;
       
   312 				break;
       
   313 				}
       
   314 
       
   315 		  	case ESuplSetIdTypeImsi:
       
   316 		  		{
       
   317 				setId.t = T_SETId_imsi;
       
   318 				setId.u.imsi = (ASN1T_SETId_imsi*)rtxMemAllocZ(pctxt, sizeof(ASN1T_SETId_imsi));
       
   319 				if (iControl->getStatus() != 0)
       
   320 					{
       
   321 					SUPLLOG(ELogP1, "CSuplMessageBase::SetSessionId() Error, out of memory\n");
       
   322 					return KErrNoMemory;
       
   323 					}				
       
   324 				TInt len = aSessionId.iSetSessionId->iSetId->iSetId.Length();
       
   325 				void* data = (void*)aSessionId.iSetSessionId->iSetId->iSetId.Ptr();
       
   326 				memcpy ((void*)setId.u.imsi->data, data, len);
       
   327 				setId.u.imsi->numocts = len;
       
   328 				break;
       
   329 				}
       
   330 
       
   331 		  	case ESuplSetIdTypeNai:
       
   332 		  	default:
       
   333 		  		{
       
   334 		  		__ASSERT_DEBUG(0, User::Invariant());
       
   335 		  		return KErrNotSupported;
       
   336 		  		}
       
   337 			}
       
   338 		}
       
   339 	
       
   340 	// populate SLP Session ID, if present
       
   341 	// note this may not be present if building an outgoing SUPL START message,
       
   342 	// as it is specified by the first incoming message from the SLP.
       
   343 	if (aSessionId.iSlpSessionIdPresent)
       
   344 		{
       
   345 		iData->sessionID.m.slpSessionIDPresent = 1;
       
   346 
       
   347 		// SLP Session ID / Session ID
       
   348 		TInt len = aSessionId.iSlpSessionId->iSessionId.Length();
       
   349 		void* data = (void*)aSessionId.iSlpSessionId->iSessionId.Ptr();
       
   350 		memcpy ((void*)iData->sessionID.slpSessionID.sessionID.data, data, len);
       
   351 		iData->sessionID.slpSessionID.sessionID.numocts = len;
       
   352 		
       
   353 		// SLP Session ID / SLP ID
       
   354 		if (aSessionId.iSlpSessionId->iSlpAddress->iSlpAddressType == ESuplSlpAddressTypeFqdn)
       
   355 			{
       
   356 			iData->sessionID.slpSessionID.slpId.t = T_SLPAddress_fQDN;
       
   357 			TInt len = aSessionId.iSlpSessionId->iSlpAddress->iFqdn->iFqdn.Length();
       
   358 			
       
   359 			// allocate memory for the FQDN string			
       
   360 			char* tmpstr = (char*) rtxMemAlloc (pctxt, len+1);
       
   361 			if (tmpstr == NULL)
       
   362 				{
       
   363 				SUPLLOG(ELogP1, "CSuplMessageBase::SetSessionId() Error, out of memory\n");
       
   364 				return KErrNoMemory;
       
   365 				}
       
   366 				
       
   367 			void* source = (void*)aSessionId.iSlpSessionId->iSlpAddress->iFqdn->iFqdn.Ptr();
       
   368 			memcpy ((void*)tmpstr, source, len);
       
   369 			tmpstr[len] = '\0';  // add null-terminator
       
   370 			iData->sessionID.slpSessionID.slpId.u.fQDN = tmpstr;
       
   371 			}
       
   372 		else
       
   373 			{
       
   374 			// SLP ID is an IP address
       
   375 			iData->sessionID.slpSessionID.slpId.t = T_SLPAddress_iPAddress;
       
   376 			iData->sessionID.slpSessionID.slpId.u.iPAddress = (ASN1T_IPAddress*)rtxMemAllocZ(pctxt, sizeof(ASN1T_IPAddress));
       
   377 			if (iControl->getStatus() != 0)
       
   378 				{
       
   379 				SUPLLOG(ELogP1, "CSuplMessageBase::SetSessionId() Error, out of memory\n");
       
   380 				return KErrNoMemory;
       
   381 				}
       
   382 						
       
   383 			if (aSessionId.iSlpSessionId->iSlpAddress->iIpAddress->iIpAddressType == ESuplIpAddressTypeV6)
       
   384 				{ // IPv6
       
   385 				iData->sessionID.slpSessionID.slpId.u.iPAddress->t =  T_IPAddress_ipv6Address;
       
   386 				iData->sessionID.slpSessionID.slpId.u.iPAddress->u.ipv6Address = (ASN1T_IPAddress_ipv6Address*)rtxMemAllocZ(pctxt, sizeof(ASN1T_IPAddress_ipv6Address));
       
   387 				if (iControl->getStatus() != 0)
       
   388 					{
       
   389 					SUPLLOG(ELogP1, "CSuplMessageBase::SetSessionId() Error, out of memory\n");
       
   390 					return KErrNoMemory;
       
   391 					}
       
   392 							
       
   393 				TInt len = aSessionId.iSlpSessionId->iSlpAddress->iIpAddress->iIpAddress.Length();
       
   394 				void* data = (void*)aSessionId.iSlpSessionId->iSlpAddress->iIpAddress->iIpAddress.Ptr();
       
   395 				memcpy ((void*)iData->sessionID.slpSessionID.slpId.u.iPAddress->u.ipv6Address->data, data, len);
       
   396 				iData->sessionID.slpSessionID.slpId.u.iPAddress->u.ipv6Address->numocts = len;
       
   397 				}
       
   398 			else
       
   399 				{ // IPv4
       
   400 				iData->sessionID.slpSessionID.slpId.u.iPAddress->t =  T_IPAddress_ipv4Address;
       
   401 				iData->sessionID.slpSessionID.slpId.u.iPAddress->u.ipv4Address = (ASN1T_IPAddress_ipv4Address*)rtxMemAllocZ(pctxt, sizeof(ASN1T_IPAddress_ipv4Address));
       
   402 				if (iControl->getStatus() != 0)
       
   403 					{
       
   404 					SUPLLOG(ELogP1, "CSuplMessageBase::SetSessionId() Error, out of memory\n");
       
   405 					return KErrNoMemory;
       
   406 					}				
       
   407 
       
   408 				TInt len = aSessionId.iSlpSessionId->iSlpAddress->iIpAddress->iIpAddress.Length();
       
   409 				void* data = (void*)aSessionId.iSlpSessionId->iSlpAddress->iIpAddress->iIpAddress.Ptr();
       
   410 				memcpy ((void*)iData->sessionID.slpSessionID.slpId.u.iPAddress->u.ipv4Address->data, data, len);
       
   411 				iData->sessionID.slpSessionID.slpId.u.iPAddress->u.ipv4Address->numocts = len;
       
   412 				}
       
   413 			}
       
   414 		}
       
   415 	SUPLLOG(ELogP1, "CSuplMessageBase::SetSessionId() End\n");
       
   416 	return KErrNone;
       
   417 	}
       
   418 
       
   419 /** 
       
   420 MessageType()
       
   421 
       
   422 Returns the message type 
       
   423 @return message type (set at construction)
       
   424 */
       
   425 EXPORT_C CSuplMessageBase::TSuplMessageType CSuplMessageBase::MessageType()
       
   426 	{
       
   427 	SUPLLOG(ELogP1, "CSuplMessageBase::MessageType() Begin\n");
       
   428 	SUPLLOG2(ELogP1, "CSuplMessageBase::MessageType() End (message type = %d)\n", iSuplMessageType);
       
   429 	return iSuplMessageType;
       
   430 	}
       
   431 
       
   432 /** 
       
   433 GetVersion()
       
   434 
       
   435 Populates aVersion with the SUPL version
       
   436 @param aVersion on return, populated with version of received SUPL message
       
   437 */
       
   438 EXPORT_C TInt CSuplMessageBase::GetVersion(CSuplVersion& aVersion)
       
   439 	{
       
   440 	SUPLLOG(ELogP1, "CSuplMessageBase::Version() Begin\n");
       
   441 	__ASSERT_DEBUG(!iIsOutgoingMessage, User::Invariant());
       
   442 	aVersion.iMaj = iData->version.maj;
       
   443 	aVersion.iMin = iData->version.min;
       
   444 	aVersion.iServind = iData->version.servind;
       
   445 	
       
   446 	SUPLLOG(ELogP1, "CSuplMessageBase::Version() End\n");
       
   447 	return KErrNone;
       
   448 	}
       
   449 
       
   450 /** 
       
   451 GetSessionId()
       
   452 
       
   453 Populates aSessionId with the SUPL Session ID
       
   454 
       
   455 @param aSessionId on return, populated with session ID of received SUPL message
       
   456 */
       
   457 EXPORT_C TInt CSuplMessageBase::GetSessionId(CSuplSessionId& aSessionId)
       
   458 	{
       
   459 	SUPLLOG(ELogP1, "CSuplMessageBase::SessionId() Begin\n");
       
   460 	__ASSERT_DEBUG(!iIsOutgoingMessage, User::Invariant());
       
   461 	
       
   462 	// populate SET Session ID, if present
       
   463 	// note in the case of a received SUPL INIT message, the 
       
   464 	// SET Session ID is not present.
       
   465 	if (iData->sessionID.m.setSessionIDPresent != 0)
       
   466 		{
       
   467 		aSessionId.iSetSessionIdPresent = ETrue;
       
   468 		aSessionId.iSetSessionId->iSessionId = iData->sessionID.setSessionID.sessionId;
       
   469 		ASN1T_SETId& setId = iData->sessionID.setSessionID.setId;
       
   470 		
       
   471 		switch (setId.t)
       
   472 			{
       
   473 			case T_SETId_iPAddress:
       
   474 				{
       
   475 				aSessionId.iSetSessionId->iSetId->iSetIdType = ESuplSetIdTypeIPAddress;
       
   476 				// Pointer to the address data buffer
       
   477 				TBuf8<16>& ipAddress = aSessionId.iSetSessionId->iSetId->iIpAddress->iIpAddress;
       
   478 				
       
   479 				// IPv4 or IPv6 address?
       
   480 				if (setId.u.iPAddress->t == T_IPAddress_ipv6Address)
       
   481 					{
       
   482 					aSessionId.iSetSessionId->iSetId->iIpAddress->iIpAddressType = ESuplIpAddressTypeV6;
       
   483 					TInt len = setId.u.iPAddress->u.ipv6Address->numocts;
       
   484 					TUint8* data = setId.u.iPAddress->u.ipv6Address->data;
       
   485 					ipAddress.Copy(data, len);
       
   486 					}
       
   487 				else
       
   488 					{
       
   489 					aSessionId.iSetSessionId->iSetId->iIpAddress->iIpAddressType = ESuplIpAddressTypeV4;
       
   490 					TInt len = setId.u.iPAddress->u.ipv4Address->numocts;
       
   491 					TUint8* data = setId.u.iPAddress->u.ipv4Address->data;
       
   492 					ipAddress.Copy(data, len);
       
   493 					}
       
   494 				break;
       
   495 				}
       
   496 			case T_SETId_msisdn:
       
   497 				{
       
   498 				aSessionId.iSetSessionId->iSetId->iSetIdType = ESuplSetIdTypeMsisdn;
       
   499 				TBuf8<16>& targetSetId = aSessionId.iSetSessionId->iSetId->iSetId;
       
   500 				TInt len = setId.u.msisdn->numocts;
       
   501 				TUint8* data = setId.u.msisdn->data;
       
   502 				targetSetId.Copy(data, len);
       
   503 				break;
       
   504 				}
       
   505 			case T_SETId_mdn:
       
   506 				{
       
   507 				aSessionId.iSetSessionId->iSetId->iSetIdType = ESuplSetIdTypeMdn;
       
   508 				TBuf8<16>& targetSetId = aSessionId.iSetSessionId->iSetId->iSetId;
       
   509 				TInt len = setId.u.mdn->numocts;
       
   510 				TUint8* data = setId.u.mdn->data;
       
   511 				targetSetId.Copy(data, len);
       
   512 				break;
       
   513 				}
       
   514 			case T_SETId_min:
       
   515 				{
       
   516 				aSessionId.iSetSessionId->iSetId->iSetIdType = ESuplSetIdTypeMin;
       
   517 				TBuf8<16>& targetSetId = aSessionId.iSetSessionId->iSetId->iSetId;
       
   518 				TInt len = 5; // min is limited to 5 bytes (34 bits). Copy it all.
       
   519 				TUint8* data = setId.u.min->data;
       
   520 				targetSetId.Copy(data, len);
       
   521 				break;
       
   522 				}
       
   523 			case T_SETId_imsi:
       
   524 				{
       
   525 				aSessionId.iSetSessionId->iSetId->iSetIdType = ESuplSetIdTypeImsi;
       
   526 				TBuf8<16>& targetSetId = aSessionId.iSetSessionId->iSetId->iSetId;
       
   527 				TInt len = setId.u.imsi->numocts;
       
   528 				TUint8* data = setId.u.imsi->data;
       
   529 				targetSetId.Copy(data, len);
       
   530 				break;
       
   531 				}
       
   532 			case T_SETId_nai:
       
   533 				{
       
   534 				// we should not receive SET IDs of these types, as we will never 
       
   535 				// have set them in the first outgoing message.
       
   536 				__ASSERT_DEBUG(0, User::Invariant());
       
   537 				return KErrNotSupported;
       
   538 				}
       
   539 			case T_SETId_extElem1:
       
   540 			default:
       
   541 				{
       
   542 				__ASSERT_DEBUG(0, User::Invariant());
       
   543 				return KErrCorrupt;
       
   544 				}
       
   545 			}
       
   546 		} // end of SET Session ID handling
       
   547 
       
   548 	// populate SLP Session ID, if present
       
   549 	// note this should always be present as this method is intended for the 
       
   550 	// decoding of received messages.
       
   551 	if (iData->sessionID.m.slpSessionIDPresent != 0)
       
   552 		{
       
   553 		aSessionId.iSlpSessionIdPresent = ETrue;
       
   554 		TUint8* dataSource = iData->sessionID.slpSessionID.sessionID.data;
       
   555 		TInt len = iData->sessionID.slpSessionID.sessionID.numocts;
       
   556 		aSessionId.iSlpSessionId->iSessionId.Copy(dataSource, len);
       
   557 		
       
   558 		if (iData->sessionID.slpSessionID.slpId.t == T_SLPAddress_fQDN)
       
   559 			{
       
   560 			// FQDN is a NULL terminated string, length 1..255
       
   561 			aSessionId.iSlpSessionId->iSlpAddress->iSlpAddressType = ESuplSlpAddressTypeFqdn;
       
   562 						
       
   563 			// find the length of the FQDN (NULL terminated)
       
   564 			const TUint8* tmp = (const TUint8*)iData->sessionID.slpSessionID.slpId.u.fQDN;
       
   565 			TPtrC8 source = TPtrC8(tmp, 256);
       
   566 			_LIT8(KNull,"\0");
       
   567 			TInt fqdnLength = source.Find(KNull);
       
   568 			
       
   569 			if (fqdnLength > 0 && fqdnLength <256)
       
   570 				{
       
   571 				// copy to the container
       
   572 				source.Set(tmp, fqdnLength);
       
   573 				TBuf8<256>& fqdn = aSessionId.iSlpSessionId->iSlpAddress->iFqdn->iFqdn;
       
   574 				fqdn.Copy(source);
       
   575 				fqdn.SetLength(fqdnLength);
       
   576 				}
       
   577 			else
       
   578 				{
       
   579 				// fqdn length is corrupt
       
   580 				__ASSERT_DEBUG(0, User::Invariant());
       
   581 				return KErrCorrupt;
       
   582 				}
       
   583 			}
       
   584 		else if (iData->sessionID.slpSessionID.slpId.t == T_SLPAddress_iPAddress)
       
   585 			{
       
   586 			// SLP ID is an IP Address
       
   587 			aSessionId.iSlpSessionId->iSlpAddress->iSlpAddressType = ESuplSlpAddressTypeIp;
       
   588 
       
   589 			// Pointer to the address data buffer
       
   590 			TBuf8<16>& ipAddress = aSessionId.iSlpSessionId->iSlpAddress->iIpAddress->iIpAddress;
       
   591 							
       
   592 			// IPv4 or IPv6 address?
       
   593 			if (iData->sessionID.slpSessionID.slpId.u.iPAddress->t == T_IPAddress_ipv6Address)
       
   594 				{
       
   595 				aSessionId.iSlpSessionId->iSlpAddress->iIpAddress->iIpAddressType = ESuplIpAddressTypeV6;
       
   596 				TInt len = iData->sessionID.slpSessionID.slpId.u.iPAddress->u.ipv6Address->numocts;
       
   597 				TUint8* data = iData->sessionID.slpSessionID.slpId.u.iPAddress->u.ipv6Address->data;
       
   598 				ipAddress.Copy(data, len);
       
   599 				}
       
   600 			else
       
   601 				{
       
   602 				aSessionId.iSlpSessionId->iSlpAddress->iIpAddress->iIpAddressType = ESuplIpAddressTypeV4;
       
   603 				TInt len = iData->sessionID.slpSessionID.slpId.u.iPAddress->u.ipv4Address->numocts;
       
   604 				TUint8* data = iData->sessionID.slpSessionID.slpId.u.iPAddress->u.ipv4Address->data;
       
   605 				ipAddress.Copy(data, len);
       
   606 				}
       
   607 			}
       
   608 		else
       
   609 			{
       
   610 			// SLP ID Type is corrupt
       
   611 			__ASSERT_DEBUG(0, User::Invariant());
       
   612 			SUPLLOG(ELogP1, "CSuplMessageBase::SessionId() End (unexpected SLP ID type)\n");
       
   613 			return KErrCorrupt;
       
   614 			}
       
   615 		} // end of SLP Session ID handling
       
   616 		
       
   617 	SUPLLOG(ELogP1, "CSuplMessageBase::SessionId() End\n");
       
   618 	return KErrNone;
       
   619 	}
       
   620 
       
   621 /**
       
   622 PopulateSetCapabilities()
       
   623 
       
   624 Populates the data container specifying the content of the SET CAPABILITIES 
       
   625 componenet according to the passed LBS capabilities.
       
   626 
       
   627 Note that the Preferred Method parameter is set to the method identified
       
   628 LAST in the array of capable methods. It is acceptable if this method is 
       
   629 repeated elsewhere in the passed array.
       
   630 
       
   631 @param  aCapsSource Capabilities Source
       
   632 @param  aCapsTarget outgoing capabilities data object
       
   633 @return error indication, KErrNone otherwise
       
   634 */
       
   635 TInt CSuplMessageBase::PopulateSetCapabilities(const TLbsNetPosCapabilities& aCapsSource, ASN1T_SETCapabilities& aCapsTarget)
       
   636 	{
       
   637 	SUPLLOG(ELogP1, "CSuplMessageBase::PopulateSetCapabilities() Begin\n");
       
   638 	
       
   639 	// Specify supported positioning protocols. This implementation supports only RRLP
       
   640 	aCapsTarget.posProtocol.rrlp = ETrue;
       
   641 	
       
   642 	// the preferred method is the last identified in the array.
       
   643 	TInt prefMethod = PrefMethod::noPreference;
       
   644 	
       
   645 	// specify supported positioning methods
       
   646 	TLbsNetPosMethod posMethod;
       
   647 	for (TInt i=0 ; i<aCapsSource.NumPosMethods() ; ++i)
       
   648 		{
       
   649 		if (aCapsSource.GetPosMethod(i, posMethod) == KErrNone)
       
   650 			{
       
   651 			TUid means = posMethod.PosMeans();
       
   652 			if (means == KLbsPositioningMeansGps)
       
   653 				{
       
   654 				// GPS positioning means
       
   655 				if (posMethod.PosMode() == TPositionModuleInfo::ETechnologyTerminal ||
       
   656 					posMethod.PosMode() == TPositionModuleInfo::ETechnologyUnknown)
       
   657 					{
       
   658 					aCapsTarget.posTechnology.autonomousGPS = ETrue;
       
   659 					}
       
   660 				else if (posMethod.PosMode() == (TPositionModuleInfo::ETechnologyTerminal | TPositionModuleInfo::ETechnologyAssisted))
       
   661 					{
       
   662 					aCapsTarget.posTechnology.agpsSETBased = ETrue;
       
   663 					prefMethod = PrefMethod::agpsSETBasedPreferred;
       
   664 					}
       
   665 				else if (posMethod.PosMode() == (TPositionModuleInfo::ETechnologyNetwork | TPositionModuleInfo::ETechnologyAssisted))
       
   666 					{
       
   667 					aCapsTarget.posTechnology.agpsSETassisted = ETrue;
       
   668 					prefMethod = PrefMethod::agpsSETassistedPreferred;
       
   669 					}
       
   670 				}
       
   671 			else if (means == KLbsPositioningMeansCell)
       
   672 				{
       
   673 				// Cell positioning means
       
   674 				aCapsTarget.posTechnology.eCID = ETrue;
       
   675 				}
       
   676 			else if (means == KLbsPositioningMeansEotd)
       
   677 				{
       
   678 				// EOTD positioning means
       
   679 				aCapsTarget.posTechnology.eOTD = ETrue;
       
   680 				}
       
   681 			else if (means == KLbsPositioningMeansOtdoa)
       
   682 				{
       
   683 				// OTDOA positioning means
       
   684 				aCapsTarget.posTechnology.oTDOA = ETrue;
       
   685 				}
       
   686 			else if (means == KLbsPositioningMeansAflt)
       
   687 				{
       
   688 				// AFLT positioning means
       
   689 				aCapsTarget.posTechnology.aFLT = ETrue;
       
   690 				}
       
   691 			else 
       
   692 				{
       
   693 				// unknown/corrupt positioning means
       
   694 				__ASSERT_DEBUG(0, User::Invariant());
       
   695 				return KErrCorrupt;
       
   696 				}
       
   697 			}
       
   698 		}
       
   699 	
       
   700 	// specify the preferred GPS mode
       
   701 	aCapsTarget.prefMethod = prefMethod;
       
   702 	
       
   703 	SUPLLOG(ELogP1, "CSuplMessageBase::PopulateSetCapabilities() End\n");
       
   704 	return KErrNone;
       
   705 	}
       
   706 
       
   707 
       
   708 /**
       
   709 PopulateLocationId()
       
   710 
       
   711 Populates the data container specifying the content of the LOCATION ID
       
   712 componenet according to the passed LBS location details.
       
   713 
       
   714 
       
   715 @param  aLocSource LocationID Source
       
   716 @param  aLocTarget outgoing LocationID data object
       
   717 @return error indication, KErrNone otherwise
       
   718 */
       
   719 TInt CSuplMessageBase::PopulateLocationId(const CSuplLocationId& aLocSource, ASN1T_LocationId& aLocTarget)
       
   720 	{
       
   721 	SUPLLOG(ELogP1, "CSuplMessageBase::PopulateLocationId() Begin\n");
       
   722 	__ASSERT_DEBUG(aLocSource.iType<ESuplLocationTypeLimit, User::Invariant());
       
   723 	
       
   724 	// pointer to context object
       
   725 	OSCTXT* pctxt = iControl->getCtxtPtr();
       
   726 
       
   727 	// Cell information status
       
   728 	aLocTarget.status = aLocSource.iStatus;
       
   729 
       
   730 	// Cell information is carrier type dependant
       
   731 	if (aLocSource.iType == ESuplLocationTypeGsm)
       
   732 		{
       
   733 		aLocTarget.cellInfo.t = T_CellInfo_gsmCell;
       
   734 		aLocTarget.cellInfo.u.gsmCell = (ASN1T_GsmCellInformation*)rtxMemAllocZ(pctxt, sizeof(ASN1T_GsmCellInformation));
       
   735 		if (iControl->getStatus() != 0)
       
   736 			{
       
   737 			SUPLLOG(ELogP1, "CSuplMessageBase::PopulateLocationId() Error, out of memory\n");
       
   738 			return KErrNoMemory;
       
   739 			}
       
   740 		
       
   741 		// populate the cell information
       
   742 		CSuplGsmCellInfo* gsmInfo = aLocSource.iGsmCellInfo;
       
   743 		aLocTarget.cellInfo.u.gsmCell->refMCC = gsmInfo->iRefMCC;
       
   744 		aLocTarget.cellInfo.u.gsmCell->refMNC = gsmInfo->iRefMNC;
       
   745 		aLocTarget.cellInfo.u.gsmCell->refLAC = gsmInfo->iRefLAC;
       
   746 		aLocTarget.cellInfo.u.gsmCell->refCI  = gsmInfo->iRefCI;
       
   747 		
       
   748 		// NMR is optional
       
   749 		if (gsmInfo->iNMR > 0)
       
   750 			{
       
   751 			
       
   752 			aLocTarget.cellInfo.u.gsmCell->m.nMRPresent = 1;
       
   753 
       
   754 			// initialise the NMR list
       
   755 			ASN1C_NMR list (*iControl, aLocTarget.cellInfo.u.gsmCell->nMR);
       
   756 			list.init();
       
   757 	
       
   758 			// populate the array
       
   759 			for (TInt i = 0; i < gsmInfo->iNMR; ++i)
       
   760 				{
       
   761 				ASN1T_NMRelement* nmrElement;
       
   762 				nmrElement = list.NewElement();
       
   763 				if (nmrElement == NULL)
       
   764 					{
       
   765 					SUPLLOG(ELogP1, "CSuplMessageBase::PopulateLocationId() Error, out of memory\n");
       
   766 					return KErrNoMemory;
       
   767 					}
       
   768 				nmrElement->aRFCN = gsmInfo->iNmrElements[i].iARFCN;
       
   769 				nmrElement->bSIC  = gsmInfo->iNmrElements[i].iBSIC;
       
   770 				nmrElement->rxLev = gsmInfo->iNmrElements[i].iRxLev;
       
   771 				
       
   772 				list.Append(nmrElement);
       
   773 				}			
       
   774 			} // NMR
       
   775 
       
   776 		// TA is optional
       
   777 		if (gsmInfo->iTA >= 0)
       
   778 			{
       
   779 			aLocTarget.cellInfo.u.gsmCell->m.tAPresent = 1;
       
   780 			aLocTarget.cellInfo.u.gsmCell->tA = gsmInfo->iTA;
       
   781 			}
       
   782 		}
       
   783 	else if (aLocSource.iType == ESuplLocationTypeCdma)
       
   784 		{
       
   785 		iData->message.u.msSUPLSTART->locationId.cellInfo.t = T_CellInfo_cdmaCell;
       
   786 		aLocTarget.cellInfo.u.cdmaCell = (ASN1T_CdmaCellInformation*)rtxMemAllocZ(pctxt, sizeof(ASN1T_CdmaCellInformation));
       
   787 		if (iControl->getStatus() != 0)
       
   788 			{
       
   789 			SUPLLOG(ELogP1, "CSuplMessageBase::PopulateLocationId() Error, out of memory\n");
       
   790 			return KErrNoMemory;
       
   791 			}
       
   792 		
       
   793 		// populate the cell information
       
   794 		CSuplCdmaCellInfo* cdmaInfo = aLocSource.iCdmaCellInfo;
       
   795 	   	aLocTarget.cellInfo.u.cdmaCell->refNID        = cdmaInfo->iRefNID;
       
   796 		aLocTarget.cellInfo.u.cdmaCell->refSID        = cdmaInfo->iRefSID;
       
   797    		aLocTarget.cellInfo.u.cdmaCell->refBASEID     = cdmaInfo->iRefBASEID;
       
   798    		aLocTarget.cellInfo.u.cdmaCell->refBASELAT    = cdmaInfo->iRefBASELAT;
       
   799    		aLocTarget.cellInfo.u.cdmaCell->reBASELONG    = cdmaInfo->iReBASELONG;
       
   800    		aLocTarget.cellInfo.u.cdmaCell->refREFPN      = cdmaInfo->iRefREFPN;
       
   801    		aLocTarget.cellInfo.u.cdmaCell->refWeekNumber = cdmaInfo->iRefWeekNumber;
       
   802    		aLocTarget.cellInfo.u.cdmaCell->refSeconds    = cdmaInfo->iRefSeconds;
       
   803 		}
       
   804 	else if (aLocSource.iType == ESuplLocationTypeWcdma)
       
   805 		{
       
   806 		aLocTarget.cellInfo.t = T_CellInfo_wcdmaCell;
       
   807 		aLocTarget.cellInfo.u.wcdmaCell = (ASN1T_WcdmaCellInformation*)rtxMemAllocZ(pctxt, sizeof(ASN1T_WcdmaCellInformation));
       
   808 		if (iControl->getStatus() != 0)
       
   809 			{
       
   810 			SUPLLOG(ELogP1, "CSuplMessageBase::PopulateLocationId() Error, out of memory\n");
       
   811 			return KErrNoMemory;
       
   812 			}
       
   813 		
       
   814 		// populate the cell information
       
   815 		CSuplWcdmaCellInfo* wcdmaInfo = aLocSource.iWcdmaCellInfo;
       
   816 		aLocTarget.cellInfo.u.wcdmaCell->refMCC = wcdmaInfo->iRefMCC;
       
   817 		aLocTarget.cellInfo.u.wcdmaCell->refMNC = wcdmaInfo->iRefMNC;
       
   818 		aLocTarget.cellInfo.u.wcdmaCell->refUC  = wcdmaInfo->iRefUC;
       
   819 		}
       
   820 	else
       
   821 		{
       
   822 		SUPLLOG(ELogP1, "CSuplMessageBase::PopulateLocationId() Error, unexpected location source type\n");
       
   823 		return KErrArgument;
       
   824 		}
       
   825 	
       
   826 	SUPLLOG(ELogP1, "CSuplMessageBase::PopulateLocationId() End\n");
       
   827 	return KErrNone;
       
   828 	}
       
   829 
       
   830 
       
   831 /**
       
   832 PopulatePosition()
       
   833 
       
   834 Populates the outgoing position element, used in POS INIT and END messages.
       
   835 
       
   836 Timestamp is encoded in UTC format YYMMDDhhmmssZ
       
   837 
       
   838 Latitude is encoded as an integer N (0..2^23-1) from the actual latitude X 
       
   839 in degrees, where   N <= 2^23 * X/90 < N+1
       
   840 	
       
   841 Longitude is encoded as an integer N (-2^23..2^23-1) from the actual 
       
   842 longitude X in degrees, where   N <= 2^24 * X/360 < N+1
       
   843 	
       
   844 Horizontal Uncertainty is encoded as per 3GPP GAD, ie describing an 
       
   845 ellipse with semi-major and semi-minor axis measurements and orientation.
       
   846 With only one value for horizontal accuracy available, the circle 
       
   847 described is encoded as an ellipse with semi-major = semi-minor axis and
       
   848 0 degree orientation. The uncertainty is encoded to 7 bits, thus:
       
   849 	r = C( (1+x)^k - 1 )
       
   850 where r = distance in meters, C = 10, x = 0.1 and K is the encoded constant.
       
   851 
       
   852 Confidence information is not available in this implementation and is omitted
       
   853 
       
   854 Altitude, if data is available, is encoded as a 15 bit binary encoded number.
       
   855 
       
   856 Altitude uncertainty is encoded as a distance above or below the WGS84
       
   857 ellipsoid, using the same formula as for horizontal uncertainty, but where
       
   858 C = 45, x = 0.025. Encoded value K is limited to 7 bits.
       
   859 
       
   860 If the passed TPositionInfoBase object is a TPositionCourseInfo, then the
       
   861 optional velocity element is populated with data from the course info object.
       
   862 Velocity information is encoded as per 3GPP TS 23.032, and the "horizontal
       
   863 velocity with uncertainty" format is used.
       
   864 
       
   865 @param  aPosSource Position source data from LBS
       
   866 @param  aPosTarget outgoing Position message data object
       
   867 @return error indication, KErrNone otherwise
       
   868 */
       
   869 TInt CSuplMessageBase::PopulatePosition(const TPositionInfoBase& aPosSource, ASN1T_Position& aPosTarget)
       
   870 	{
       
   871 	SUPLLOG(ELogP1, "CSuplMessageBase::PopulatePosition() Begin\n");
       
   872 	
       
   873 	// access to source position data
       
   874 	TPosition position;
       
   875 	if ((aPosSource.PositionClassType() & EPositionInfoClass) != 0)
       
   876 		{
       
   877 		TPositionInfo posSource = reinterpret_cast <const TPositionInfo&> (aPosSource);
       
   878 		posSource.GetPosition(position);
       
   879 
       
   880 		// TIMESTAMP (mandatory)
       
   881 		// Convert timestamp to UTC format: YYMMDDhhmmssZ
       
   882 		TDateTime dateTime = position.Time().DateTime();
       
   883 		iUtcTime.SetLength(iUtcTime.MaxLength());
       
   884 
       
   885 		iUtcTime[0]=(((dateTime.Year() % 1000) % 100) / 10) + 48; // second last number in the year
       
   886 		iUtcTime[1]=(((dateTime.Year() % 1000) % 100) % 10) + 48; // last number in the year
       
   887 		iUtcTime[2]=((dateTime.Month() + 1) / 10) + 48;
       
   888 		iUtcTime[3]=((dateTime.Month() + 1) % 10) + 48;
       
   889 		iUtcTime[4]=((dateTime.Day()) / 10) + 48;
       
   890 		iUtcTime[5]=((dateTime.Day()) % 10) + 48;
       
   891 		iUtcTime[6]=(dateTime.Hour() / 10) + 48;
       
   892 		iUtcTime[7]=(dateTime.Hour() % 10) + 48;
       
   893 		iUtcTime[8]=(dateTime.Minute() / 10) + 48;
       
   894 		iUtcTime[9]=(dateTime.Minute() % 10) + 48;
       
   895 		iUtcTime[10]=(dateTime.Second() / 10) + 48;
       
   896 		iUtcTime[11]=(dateTime.Second() % 10) + 48;
       
   897 		iUtcTime[12]= 0x5A; // ASCII for "Z"
       
   898 		
       
   899 		aPosTarget.timestamp = (const char*) &iUtcTime[0];
       
   900 		
       
   901 		// POSITION ESTIMATE (mandatory)
       
   902 		// -- latitude/longitude (mandatory)
       
   903 		aPosTarget.positionEstimate.latitudeSign = PositionEstimate_latitudeSign::north;
       
   904 		TReal64 latitude  = position.Latitude();
       
   905 		TReal64 longitude = position.Longitude();
       
   906 		if (latitude < 0)
       
   907 			{
       
   908 			aPosTarget.positionEstimate.latitudeSign = PositionEstimate_latitudeSign::south;
       
   909 			latitude *= -1;
       
   910 			}
       
   911 		aPosTarget.positionEstimate.latitude  = latitude  * KLbsLatitudeConst; 
       
   912 		aPosTarget.positionEstimate.longitude = longitude * KLbsLongitudeConst;
       
   913 
       
   914 		// -- uncertainty (optional)
       
   915 		if (position.HorizontalAccuracy() != 0)
       
   916 			{
       
   917 			TInt uncert = Uncertainty(position.HorizontalAccuracy());
       
   918 			aPosTarget.positionEstimate.m.uncertaintyPresent = 1;
       
   919 			aPosTarget.positionEstimate.uncertainty.uncertaintySemiMajor = uncert;
       
   920 			aPosTarget.positionEstimate.uncertainty.uncertaintySemiMinor = uncert;
       
   921 			aPosTarget.positionEstimate.uncertainty.orientationMajorAxis = 0;
       
   922 			}
       
   923 
       
   924 		// -- confidence (optional)
       
   925 		// this information is not available, omitted.
       
   926 		aPosTarget.positionEstimate.m.confidencePresent = 0;
       
   927 		aPosTarget.positionEstimate.confidence = 0;
       
   928 		
       
   929 		// -- altitude information (optional)
       
   930 		if (position.Altitude() != 0)
       
   931 			{
       
   932 			aPosTarget.positionEstimate.m.altitudeInfoPresent = 1;
       
   933 			TReal32 altitude = position.Altitude();
       
   934 			aPosTarget.positionEstimate.altitudeInfo.altitudeDirection = AltitudeInfo_altitudeDirection::height;
       
   935 			if (altitude < 0)
       
   936 				{
       
   937 				aPosTarget.positionEstimate.altitudeInfo.altitudeDirection = AltitudeInfo_altitudeDirection::depth;
       
   938 				altitude *= -1;
       
   939 				}
       
   940 			aPosTarget.positionEstimate.altitudeInfo.altitude = EncodeAltitude(altitude);
       
   941 			aPosTarget.positionEstimate.altitudeInfo.altUncertainty = UncertaintyAltitude(position.VerticalAccuracy());
       
   942 			}
       
   943 		}
       
   944 	else
       
   945 		{
       
   946 		SUPLLOG(ELogP1, "CSuplMessageBase::PopulatePosition() Error, position class is not EPositionInfoClass type\n");
       
   947 		return KErrNotSupported;
       
   948 		}
       
   949 	
       
   950 	// handle velocity (TCourse) information
       
   951 	if ((aPosSource.PositionClassType() & EPositionCourseInfoClass) != 0)
       
   952 		{
       
   953 		TPositionCourseInfo posSource = reinterpret_cast <const TPositionCourseInfo&> (aPosSource);
       
   954 		TCourse course;
       
   955 		posSource.GetCourse(course);
       
   956 		
       
   957 		// -- velocity
       
   958 		aPosTarget.m.velocityPresent = 1;
       
   959 		TInt velErr = PopulateVelocity(course, aPosTarget.velocity);
       
   960 		
       
   961 		if (velErr != KErrNone)
       
   962 			{
       
   963 			return velErr;
       
   964 			}
       
   965 		}
       
   966 
       
   967 	SUPLLOG(ELogP1, "CSuplMessageBase::PopulatePosition() End\n");
       
   968 	return KErrNone;
       
   969 	}
       
   970 
       
   971 /*
       
   972 PopulateVelocity()
       
   973 
       
   974 Populates the outgoing velocity sub-element with velocity information from 
       
   975 an LBS TCourse object.
       
   976 
       
   977 @param  aVelSource course/velocity source data from LBS
       
   978 @param  aVelTarget outgoing velocity message data object
       
   979 @return error indication, KErrNone otherwise
       
   980 */
       
   981 TInt CSuplMessageBase::PopulateVelocity(const TCourse& aCourse, ASN1T_Velocity& aVelTarget)
       
   982 	{
       
   983 	SUPLLOG(ELogP1, "CSuplMessageBase::PopulateVelocity() Begin\n");
       
   984 	aVelTarget.t = T_Velocity_horveluncert;
       
   985 	aVelTarget.u.horveluncert = (ASN1T_Horveluncert*)rtxMemAllocZ(iControl->getCtxtPtr(), sizeof(ASN1T_Horveluncert));
       
   986 	if (iControl->getStatus() != 0)
       
   987 		{
       
   988 		SUPLLOG(ELogP1, "CSuplMessageBase::PopulateVelocity() Error, out of memory\n");
       
   989 		return KErrNoMemory;
       
   990 		}
       
   991 
       
   992 	// ---- bearing
       
   993 	TUint bearing  = (TUint)aCourse.Heading();
       
   994 	aVelTarget.u.horveluncert->bearing.numbits = 9;
       
   995 	aVelTarget.u.horveluncert->bearing.data[0] = bearing >> 1; // the first 8 of 9 bits
       
   996 	aVelTarget.u.horveluncert->bearing.data[1] = bearing << 7; // just the 9th bit, in msb
       
   997 
       
   998 	// ---- horizontal speed. Convert meters per second -> kilomteres per hour
       
   999 	TReal32 horSpeed = aCourse.Speed() * KLbsMpsKmphConstant;
       
  1000 	//      adjust for GAD encoding and lose decimal precision
       
  1001 	horSpeed += 0.5;
       
  1002 	TUint horSpeedInt = (TUint)horSpeed;
       
  1003 	//      limit to 2^16-1
       
  1004 	if (horSpeedInt > 65535)
       
  1005 		{
       
  1006 		horSpeedInt = 65535;
       
  1007 		}
       
  1008 	aVelTarget.u.horveluncert->horspeed.numbits = 16;
       
  1009 	aVelTarget.u.horveluncert->horspeed.data[0] = horSpeedInt >> 8;
       
  1010 	aVelTarget.u.horveluncert->horspeed.data[1] = horSpeedInt;
       
  1011 
       
  1012 	// ---- horizontal speed. Convert meters per second -> kilomteres per hour
       
  1013 	TUint uncertSpeed  = (TUint)(aCourse.SpeedAccuracy() * KLbsMpsKmphConstant);
       
  1014 	if (uncertSpeed > 255)
       
  1015 		{
       
  1016 		uncertSpeed = 255;
       
  1017 		}
       
  1018 	aVelTarget.u.horveluncert->uncertspeed.numbits = 8;
       
  1019 	aVelTarget.u.horveluncert->uncertspeed.data[0] = uncertSpeed;
       
  1020 	
       
  1021 	SUPLLOG(ELogP1, "CSuplMessageBase::PopulateVelocity() End\n");
       
  1022 	return KErrNone;
       
  1023 	}
       
  1024 	
       
  1025 		
       
  1026 
       
  1027 
       
  1028 /**
       
  1029 LeaveIfAllocErrorL()
       
  1030 
       
  1031 Calls User::Leave(<error code>) if a memory allocation has failed.
       
  1032 */
       
  1033 void CSuplMessageBase::LeaveIfAllocErrorL()
       
  1034 	{
       
  1035 	SUPLLOG(ELogP1, "CSuplMessageBase::LeaveIfAllocErrorL() Begin\n");
       
  1036 	if (iControl->getStatus() == RTERR_NOMEM)
       
  1037 		{
       
  1038 		SUPLLOG(ELogP1, "CSuplMessageBase::LeaveIfAllocErrorL() End (out of memory error)\n");
       
  1039 		User::Leave(KErrNoMemory);
       
  1040 		}
       
  1041 	else if (iControl->getStatus() != RT_OK)
       
  1042 		{
       
  1043 		SUPLLOG2(ELogP1, "CSuplMessageBase::LeaveIfAllocErrorL() End (ASN1 runtime error, %d)\n", iControl->getStatus());
       
  1044 		User::Leave(KErrGeneral);
       
  1045 		}
       
  1046 	SUPLLOG(ELogP1, "CSuplMessageBase::LeaveIfAllocErrorL() End\n");
       
  1047 	}
       
  1048 
       
  1049 /**
       
  1050 Uncertainty()
       
  1051 
       
  1052 Converts a minumum accuracy value in meters to an uncertainty value K as 
       
  1053 described in 3GPP 23.032 (Universal Geographical Area Description) section 6.2.
       
  1054 
       
  1055 r = C((1+x)^K - 1)
       
  1056 
       
  1057 where r = distance in meters
       
  1058       C = 10
       
  1059       x = 0.1
       
  1060       K = uncertainty value
       
  1061       
       
  1062 hence K = ln(r/C + 1) / ln(1.1)
       
  1063 
       
  1064 @param aDistance - distance measurement in meters
       
  1065 @return uncertainty value K
       
  1066 */
       
  1067 TInt CSuplMessageBase::Uncertainty(const TReal32& aDistance)
       
  1068 	{
       
  1069 	SUPLLOG(ELogP1, "CSuplMessageBase::Uncertainty() Begin\n");
       
  1070 	TReal uncert;
       
  1071 	Math::Ln(uncert,  (aDistance/10) + 1 );
       
  1072 	uncert /= KLbsLogOnePointOne;
       
  1073 	if (uncert>KLbsMaxUncert)
       
  1074 		{
       
  1075 		uncert = KLbsMaxUncert;
       
  1076 		}
       
  1077 
       
  1078 	// round to nearest whole number
       
  1079 	TReal uncertRounded;
       
  1080 	Math::Round(uncertRounded, uncert, 0);
       
  1081 	
       
  1082 	SUPLLOG(ELogP1, "CSuplMessageBase::Uncertainty() End\n");
       
  1083 	return (TInt)uncertRounded;
       
  1084 	}
       
  1085 	
       
  1086 /**
       
  1087 UncertaintyAltitude()
       
  1088 
       
  1089 Converts a minumum accuracy value in meters to an uncertainty altitude value K as 
       
  1090 described in 3GPP 23.032 (Universal Geographical Area Description) section 6.4.
       
  1091 
       
  1092 r = C((1+x)^K - 1)
       
  1093 
       
  1094 where r = distance in meters
       
  1095       C = 45
       
  1096       x = 0.1
       
  1097       K = uncertainty value
       
  1098       
       
  1099 hence K = ln(r/C + 1) / ln(1.1)
       
  1100 
       
  1101 @param aDistance - altitude accuracy in meters
       
  1102 @return uncertainty altitude value K
       
  1103 */
       
  1104 TInt CSuplMessageBase::UncertaintyAltitude(const TReal32& aDistance)
       
  1105 	{
       
  1106 	SUPLLOG(ELogP1, "CSuplMessageBase::UncertaintyAltitude() Begin\n");
       
  1107 	TReal uncert;
       
  1108 	Math::Ln(uncert,  (aDistance/45) + 1 );
       
  1109 	uncert /= KLbsLogOnePointZeroTwoFive;
       
  1110 	if (uncert>KLbsMaxUncert)
       
  1111 		{
       
  1112 		uncert = KLbsMaxUncert;
       
  1113 		}
       
  1114 
       
  1115 	// round to nearest whole number
       
  1116 	TReal uncertRounded;
       
  1117 	Math::Round(uncertRounded, uncert, 0);
       
  1118 	
       
  1119 	SUPLLOG(ELogP1, "CSuplMessageBase::UncertaintyAltitude() End\n");
       
  1120 	return (TInt)uncertRounded;
       
  1121 	}
       
  1122 
       
  1123 
       
  1124 /**
       
  1125 EncodeAltitude()
       
  1126 
       
  1127 Converts an value for altiutude to an 15 bit binary coded number N
       
  1128 
       
  1129 @param aAltitude - altitude in meters
       
  1130 @return uncertainty altitude value K
       
  1131 */
       
  1132 TInt CSuplMessageBase::EncodeAltitude(const TReal32& aAltitude)
       
  1133 	{
       
  1134 	SUPLLOG(ELogP1, "CSuplMessageBase::EncodeAltitude() Begin\n");
       
  1135 	TInt altEncoded = (TInt)aAltitude;
       
  1136 	if (altEncoded>KLbsMaxAltitude)
       
  1137 		{
       
  1138 		altEncoded = KLbsMaxAltitude;
       
  1139 		}
       
  1140 
       
  1141 	SUPLLOG(ELogP1, "CSuplMessageBase::EncodeAltitude() End\n");
       
  1142 	return altEncoded;
       
  1143 	}
       
  1144 
       
  1145 /**
       
  1146 Translates error codes returned by the ASN1 runtime library to distinguish
       
  1147 from Symbian global error codes.
       
  1148 
       
  1149 Errors are simply translated to positive error codes. They maintain their
       
  1150 meaning as described in rtxErrCodes.h and asn1ErrCodes.h.
       
  1151 
       
  1152 Exceptions:
       
  1153   RTERR_NOMEM is translated to global error code KErrNoMemory
       
  1154 
       
  1155 @see rtxErrCodes.h
       
  1156 @see asn1ErrCodes.h
       
  1157 */
       
  1158 TInt CSuplMessageBase::ProcessAsn1Error(TInt aError)
       
  1159 	{
       
  1160 	SUPLLOG(ELogP1, "CSuplMessageBase::ProcessAsn1Error() Begin\n");
       
  1161 	if (aError == RTERR_NOMEM)
       
  1162 		{
       
  1163 		SUPLLOG(ELogP1, "CSuplMessageBase::ProcessAsn1Error() End (Out Of Memory)\n");
       
  1164 		return KErrNoMemory;
       
  1165 		}
       
  1166 	else
       
  1167 		{
       
  1168 		SUPLLOG2(ELogP1, "CSuplMessageBase::ProcessAsn1Error() End (ASN1 Runtime Error %d)\n", aError);
       
  1169 		return aError * -1;
       
  1170 		}
       
  1171 	}
       
  1172 
       
  1173 /** 
       
  1174 Prints the content of the data structure to the logger 
       
  1175 */
       
  1176 EXPORT_C void CSuplMessageBase::LogMessageContent()
       
  1177 	{
       
  1178 	//SUPLLOG_PDU(iControl);
       
  1179 	if (MessageType() == ESuplPos)
       
  1180 		{
       
  1181 		CSuplPos* suplPos = reinterpret_cast <CSuplPos*>(this);
       
  1182 		suplPos->LogPayload();
       
  1183 		}
       
  1184 	}
       
  1185 	
       
  1186