networkprotocolmodules/common/suplrrlpasn1/src/rrlpmeasureposresponse.cpp
changeset 45 15a2125aa2f3
parent 40 18280709ae43
child 49 5f20f71a57a3
child 51 95c570bf4a05
equal deleted inserted replaced
40:18280709ae43 45:15a2125aa2f3
     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 "RRLP-Messages.h"
       
    23 #include "rrlpmeasureposresponse.h"
       
    24 #include "supldevloggermacros.h" 
       
    25 #include "suplrrlpasn1common.h"
       
    26 
       
    27 #include <lbssatellite.h>
       
    28 #include <lbs/lbsgpsmeasurement.h>
       
    29 #include <lbs/lbsextendedsatellite.h>
       
    30 
       
    31 /*
       
    32 Modulus used in conversion of GPS TOW in GPS Measurement Information Element.
       
    33 */
       
    34 const TInt KLbsTowMod = 14400000;
       
    35 
       
    36 
       
    37 /**
       
    38 CRrlpMeasurePositionResponse
       
    39 
       
    40 Class for building an outgoing RRLP Measure Position Response Message
       
    41 Translates content of passed LBS defined data structures to data encoded as per
       
    42 the RRLP specification 3GPP 44.031 v5.12 and related documents. 
       
    43 Provides a mechanism to encode the data to a target buffer as an ASN1 PER encoded 
       
    44 data stream
       
    45 
       
    46 
       
    47 The RRLP Measure Position Repsonse message consists of the following components:
       
    48 
       
    49 Multiple Sets (optional):
       
    50   allows the mobile terminal to specify the number of sets of location or
       
    51   measurement datum included in this message. This is not used by Symbian LBS
       
    52   and is left absent, indicating a single measurement set is included.
       
    53 
       
    54 Reference BTS Identity Element (optional):
       
    55   Identifies the Base Transceiver Stations used in the calculation of position.
       
    56   This element is conditional to the number of reference BTSs. It is mandatory, 
       
    57   if there is more than one reference BTS, and optional otherwise. If this 
       
    58   element is not included, the Reference BTS, used in other elements, is the 
       
    59   current serving BTS of MS. If this element is included, the BTSs defined here
       
    60   are used as Reference BTSs in all other elements.
       
    61   Currently not included in this implementation.
       
    62   
       
    63 E-OTD Measurement Information (optional):
       
    64   Provides OTD measurements of signals sent from the reference and neighbor base
       
    65   stations. Mandatory if E-OTD is the agreed positioning method, omitted otherwise.
       
    66   Symbian LBS currently does not support E-OTD positioning, so this component is
       
    67   omitted.
       
    68 
       
    69 Location Information (optional):
       
    70   The purpose of Location Information element is to provide the location 
       
    71   estimate from the MS to the network, if the MS is capable of determining its 
       
    72   own position. Optionally, the element may contain the velocity parameters 
       
    73   computed by the MS.
       
    74   
       
    75   This element is populated via calls to the SetLocationInformation() API
       
    76 
       
    77 GPS Measurement Information (optional):
       
    78   The purpose of the GPS Measurement Information element is to provide GPS 
       
    79   measurement information from the MS to the SMLC. This information includes 
       
    80   the measurements of code phase and Doppler, which enables the network-based
       
    81   GPS method where position is computed in the SMLC.
       
    82   
       
    83   This element is populated via a call to the SetMeasurementInformation() API
       
    84 
       
    85 Location Information Error (optional):
       
    86   The purpose of Location Information Error element is to provide the indication
       
    87   of error and the reason for it, when the MS can not perform the required 
       
    88   location or the network can not determine the position estimate. The element 
       
    89   may also indicate what further assistance data may be needed by the target MS 
       
    90   to produce a successful location estimate or location measurements.
       
    91   
       
    92   This element is populated via a call to the SetLocationError() APIs
       
    93 
       
    94 GPS Time Assistance Measurements (optional):
       
    95   This IE contains measurements that are used to define an accurate relation 
       
    96   between GSM and GPS time or to provide additional GPS TOW information for MS
       
    97   Assisted A-GPS.
       
    98 
       
    99 Extended Reference (optional):
       
   100   This IE shall be included in any Measure Position Response if and only if an 
       
   101   Extended Reference IE was received in the corresponding previous Measure 
       
   102   Position Request message.
       
   103   
       
   104   This element is populated via a call to the SetReference() API.
       
   105   
       
   106 
       
   107 Uplink RRLP Pseudo Segmentation Indication (optional):
       
   108   This element is included by the MS when up-link RRLP pseudo-segmentation is used. 
       
   109   In the first segment, 'first of many' is indicated and in the second 'second of 
       
   110   many' is indicated. 
       
   111   This implementation does not use up-link pseudo-segmentation hence this component
       
   112   is not included.
       
   113 
       
   114 */
       
   115 
       
   116 /**
       
   117 Static factory constructor
       
   118 */
       
   119 EXPORT_C CRrlpMeasurePositionResponse* CRrlpMeasurePositionResponse::NewL()
       
   120 	{
       
   121 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::NewL() Begin\n");
       
   122 	CRrlpMeasurePositionResponse* self = CRrlpMeasurePositionResponse::NewLC();
       
   123 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::NewL() End\n");
       
   124 	CleanupStack::Pop(self);
       
   125 	return self;
       
   126 	}
       
   127 
       
   128 /**
       
   129 Static factory constructor
       
   130 */
       
   131 EXPORT_C CRrlpMeasurePositionResponse* CRrlpMeasurePositionResponse::NewLC()
       
   132 	{
       
   133 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::NewLC() Begin\n");
       
   134 	CRrlpMeasurePositionResponse* self = new (ELeave) CRrlpMeasurePositionResponse();
       
   135 	CleanupStack::PushL(self);
       
   136 	self->ConstructL();
       
   137 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::NewLC() End\n");
       
   138 	return self;
       
   139 	}
       
   140 
       
   141 /** 
       
   142 Default constructor 
       
   143 */
       
   144 CRrlpMeasurePositionResponse::CRrlpMeasurePositionResponse()
       
   145  : CRrlpMessageBase(ERrlpMeasurePositionResp, ETrue)
       
   146 	{
       
   147 	}
       
   148 
       
   149 /** 
       
   150 Second stage constructor 
       
   151 */
       
   152 void CRrlpMeasurePositionResponse::ConstructL()
       
   153 	{
       
   154 	// outgoing message - call base class ConstructL to create data structures.
       
   155 	CRrlpMessageBase::ConstructL();
       
   156 		
       
   157 	// local reference to context object
       
   158 	OSCTXT* pctxt = iControl->getCtxtPtr();
       
   159 
       
   160 	iData->component.t = T_RRLP_Component_msrPositionRsp;
       
   161 	iData->component.u.msrPositionRsp = (ASN1T_MsrPosition_Rsp*)rtxMemAllocZ(pctxt, sizeof(ASN1T_MsrPosition_Rsp));
       
   162    	LeaveIfAllocErrorL();
       
   163 	}
       
   164 
       
   165 /** 
       
   166 Destructor 
       
   167 */
       
   168 CRrlpMeasurePositionResponse::~CRrlpMeasurePositionResponse()
       
   169 	{
       
   170 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::~CRrlpMeasurePositionResponse() Begin\n");
       
   171 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::~CRrlpMeasurePositionResponse() End\n");
       
   172 	}
       
   173 	
       
   174 
       
   175 /**	
       
   176 SetLocationInformation()
       
   177 
       
   178 Sets the content of the location information component of the RRLP Measure 
       
   179 Position Response Message.
       
   180 
       
   181 RRLP Location Information component consists of the following:
       
   182 
       
   183 Reference Frame (mandatory):
       
   184   This field specifies the reference BTS Reference Frame number during which
       
   185   the location estimate was measured. This information is not available at the
       
   186   Protocol Module, hence this is set to a value which is ignored by the SMLC.
       
   187 
       
   188 GPS TOW (optional):
       
   189   This field specifies the GPS TOW for which the location estimate is valid, 
       
   190   rounded down to the nearest millisecond unit. This field is optional but 
       
   191   shall be included if GPS Time Assistance Measurements are included. 
       
   192   Currently omitted in this implementation.
       
   193  
       
   194 Fix Type (mandatory)
       
   195   This field contains an indication as to the type of measurements performed 
       
   196   by the MS: 2D or 3D. 
       
   197   Set to 3D if altitude information is available, 2D otherwise.
       
   198 
       
   199 Position Estimate (mandatory)
       
   200   This field contains the calculated position estimate in the format defined 
       
   201   in 3GPP TS 23.032. The allowed shapes are ellipsoid Point, ellipsoid point 
       
   202   with uncertainty circle, ellipsoid point with uncertainty ellipse, ellipsoid 
       
   203   point with altitude and uncertainty ellipsoid.
       
   204 
       
   205 
       
   206 @param  aPosInfo reference to the reported position data from LBS
       
   207 @return error indication, KErrNone otherwise
       
   208 */
       
   209 EXPORT_C TInt CRrlpMeasurePositionResponse::SetLocationInformation(TPositionInfoBase& aPosInfo)
       
   210 	{
       
   211 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::SetLocationInformation() Begin\n");
       
   212 	__ASSERT_DEBUG(iData->component.u.msrPositionRsp != NULL, User::Invariant());
       
   213 	
       
   214 	ASN1T_MsrPosition_Rsp* msgBody = iData->component.u.msrPositionRsp;
       
   215 	
       
   216 	// handle Position Info class type
       
   217 	if (aPosInfo.PositionClassType() & EPositionInfoClass)
       
   218 		{
       
   219 		TPositionInfo& posInfo = reinterpret_cast <TPositionInfo&>(aPosInfo);
       
   220 
       
   221 		// the position
       
   222 		TPosition position;
       
   223 		posInfo.GetPosition(position);
       
   224 		
       
   225 		// indicate that location information is present
       
   226 		msgBody->m.locationInfoPresent = 1;
       
   227 
       
   228 		// BTS Reference Frame (mandatory) 0-65535 - however is ignored if 
       
   229 		// is in the range 42432..65535
       
   230 		// In this case GPS TOW should be provided if available. Which it is not.
       
   231 		msgBody->locationInfo.refFrame = 65535;
       
   232 		
       
   233 		// GPS Time Of Week (optional) should be included if GPS Time Assistance 
       
   234 		// Measurements  are included in the Measure Position Response, or if the
       
   235 		// BTS Reference Frame is in the "ignore" range. Not available.
       
   236 		msgBody->locationInfo.m.gpsTOWPresent = 0;
       
   237 		
       
   238 		// Position Estimate 
       
   239 		// ASN1T_Ext_GeographicalInformation is a 20 byte array, populated as 
       
   240 		// described in 3GPP 23.032. 
       
   241 
       
   242 		// Latitude/Longitude description is common to all supported position types
       
   243 		// Latitude is 23 bits of value and 1 bit describing direction (0 = north, 1 = south)
       
   244 		TReal64 latitudeDegrees = position.Latitude();
       
   245 		TInt latitudeEncoded;
       
   246 		TBool isSouth = EFalse;
       
   247 		if (latitudeDegrees < 0)
       
   248 			{
       
   249 			latitudeDegrees *= -1;
       
   250 			isSouth = ETrue;
       
   251 			}
       
   252 		 
       
   253 		latitudeEncoded = latitudeDegrees * KLbsLatitudeConst;	// * 2^23 / 90
       
   254 		if (isSouth)
       
   255 			{
       
   256 			// set the 24th bit
       
   257 			latitudeEncoded |= KBit23;
       
   258 			}
       
   259 
       
   260 		// Longitude is 24 bit 2's complimentary binary
       
   261 		TReal64 longitudeDegrees = position.Longitude();
       
   262 		TInt longitudeEncoded;
       
   263 		TBool isNegative = EFalse;
       
   264 		if (longitudeDegrees < 0)
       
   265 			{
       
   266 			longitudeDegrees *= -1;
       
   267 			isNegative = ETrue;
       
   268 			}
       
   269 		
       
   270 		longitudeEncoded = longitudeDegrees *  16777216 / 360; // * 2^24 / 360
       
   271 		if (isNegative)
       
   272 			{
       
   273 			// invert and add 1 for 2's complimentary binary
       
   274 			longitudeEncoded = ~longitudeEncoded;
       
   275 			longitudeEncoded += 1;
       
   276 			}
       
   277 
       
   278 		// insert into the octet array
       
   279 		const TInt bottom8bits = 255;
       
   280 		msgBody->locationInfo.posEstimate.data[1] = (latitudeEncoded >> 16) & bottom8bits;
       
   281 		msgBody->locationInfo.posEstimate.data[2] = (latitudeEncoded >> 8) & bottom8bits;
       
   282 		msgBody->locationInfo.posEstimate.data[3] = (latitudeEncoded) & bottom8bits;
       
   283 
       
   284 		msgBody->locationInfo.posEstimate.data[4] = (longitudeEncoded >> 16) & bottom8bits;
       
   285 		msgBody->locationInfo.posEstimate.data[5] = (longitudeEncoded >> 8) & bottom8bits;
       
   286 		msgBody->locationInfo.posEstimate.data[6] = (longitudeEncoded) & bottom8bits;
       
   287 		
       
   288 		// encode the horizontal uncertainty, if present;
       
   289 		TInt horizontalUncertaintyEncoded = 0;
       
   290 		if (position.HorizontalAccuracy() > 0)
       
   291 			{
       
   292 			horizontalUncertaintyEncoded = MetersToHorizontalUncertainty(position.HorizontalAccuracy());
       
   293 			}
       
   294 				
       
   295 		// encode altitude if present in the position estimate:
       
   296 		TInt altitudeEncoded = 0;
       
   297 		TInt altitudeUncertaintyEncoded = 0;
       
   298 		if(!Math::IsNaN(position.Altitude()))
       
   299 			{
       
   300 			TBool isUp = ETrue;
       
   301 			TReal32 altitude = position.Altitude();
       
   302 			if (altitude < 0)
       
   303 				{
       
   304 				isUp = EFalse;
       
   305 				altitude *= -1;
       
   306 				}
       
   307 			if (altitude > 32767) // = (2^15)-1  maximum size is 15 bits.
       
   308 				{
       
   309 				altitude = 32767;
       
   310 				}
       
   311 			
       
   312 			altitudeEncoded = altitude;
       
   313 			// 16th bit indicates direction of altitude, 1 indicates below surface
       
   314 			if (!isUp)
       
   315 				{
       
   316 				altitudeEncoded |= KBit15;
       
   317 				}
       
   318 			
       
   319 			// is vertical accuracy defined?
       
   320 			if (position.VerticalAccuracy() != 0)
       
   321 				{
       
   322 				altitudeUncertaintyEncoded = MetersToVerticalUncertainty(position.VerticalAccuracy());
       
   323 				}
       
   324 			} // end of altitude conversion
       
   325 		
       
   326 		
       
   327 		// clear the first byte and set remaining content according to data available
       
   328 		if (altitudeEncoded)
       
   329 			{
       
   330 			// EEllipsoidPointWithAltitudeAndUncertaintyEllipsoid
       
   331 			msgBody->locationInfo.posEstimate.data[0]  = EGeoInfoEllipsoidPointWithAltitudeAndUncertaintyEllipsoid<<4;
       
   332 			msgBody->locationInfo.posEstimate.data[7]  = altitudeEncoded>>8;
       
   333 			msgBody->locationInfo.posEstimate.data[8]  = altitudeEncoded;
       
   334 			msgBody->locationInfo.posEstimate.data[9]  = horizontalUncertaintyEncoded; // semi-major axis
       
   335 			msgBody->locationInfo.posEstimate.data[10] = horizontalUncertaintyEncoded; // semi-major axis
       
   336 			msgBody->locationInfo.posEstimate.data[11] = 0; // orientation
       
   337 			msgBody->locationInfo.posEstimate.data[12] = altitudeUncertaintyEncoded;
       
   338 			msgBody->locationInfo.posEstimate.data[13] = 0; // confidence, 0 == "no information"
       
   339 			msgBody->locationInfo.posEstimate.numocts = 14;
       
   340 			
       
   341 			msgBody->locationInfo.fixType = FixType::threeDFix;
       
   342 			}
       
   343 		else if (horizontalUncertaintyEncoded)
       
   344 			{
       
   345 			// EEllipsoidPointWithUncertaintyCircle
       
   346 			msgBody->locationInfo.posEstimate.data[0] = EGeoInfoEllipsoidPointWithUncertaintyCircle<<4;
       
   347 			msgBody->locationInfo.posEstimate.data[7] = horizontalUncertaintyEncoded;
       
   348 			msgBody->locationInfo.posEstimate.numocts = 8;
       
   349 
       
   350 			msgBody->locationInfo.fixType = FixType::twoDFix;
       
   351 			}
       
   352 		else
       
   353 			{
       
   354 			// EEllipsoidPoint
       
   355 			msgBody->locationInfo.posEstimate.data[0] = EGeoInfoEllipsoidPoint<<4;
       
   356 			msgBody->locationInfo.posEstimate.numocts = 7;
       
   357 
       
   358 			msgBody->locationInfo.fixType = FixType::twoDFix;
       
   359 			}
       
   360 		}
       
   361 	else
       
   362 		{
       
   363 		SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::SetLocationInformation() End (not a EPositionInfoClass)\n");
       
   364 		return KErrNotSupported;
       
   365 		}
       
   366 	
       
   367 	// additional handling for extended satellite info 
       
   368 	if (aPosInfo.PositionClassType() & EPositionExtendedSatelliteInfoClass)
       
   369 	    {
       
   370 	    TPositionExtendedSatelliteInfo& extSatInfo = reinterpret_cast <TPositionExtendedSatelliteInfo&>(aPosInfo);
       
   371 
       
   372 	    // GPS Timing Measurements
       
   373         TGpsTimingMeasurementData timingData;
       
   374         if  (KErrNone == extSatInfo.GetGpsTimingData(timingData))
       
   375             {
       
   376             SetGpsTimingData(timingData);
       
   377             }
       
   378 	    }
       
   379 
       
   380 
       
   381 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::SetLocationInformation() End\n");
       
   382 	return KErrNone;
       
   383 	}
       
   384 
       
   385 /**	
       
   386 MetersToHorizontalUncertainty()
       
   387 
       
   388 Converts from meters to uncertainty code, as defined in 3GPP TS 23.032:
       
   389 uncertainty r = C( (1+x)^k - 1 )
       
   390 
       
   391 r = uncertainty in meters
       
   392 C = 10;
       
   393 x = 0.1
       
   394 k = uncertainty code
       
   395 
       
   396 hence k = ln(h/C + 1) / ln(1+x), limited to 7 bits
       
   397 */
       
   398 TInt CRrlpMeasurePositionResponse::MetersToHorizontalUncertainty(const TReal32& aDistance)
       
   399 	{
       
   400 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::MetersToHorizontalUncertainty() Begin\n");
       
   401 	TReal uncert;
       
   402 	Math::Ln(uncert,  (aDistance/10) + 1 );
       
   403 	uncert /= KLbsLogOnePointOne;
       
   404 	if (uncert>KLbsMaxUncert)
       
   405 		{
       
   406 		uncert = KLbsMaxUncert;
       
   407 		}
       
   408 
       
   409 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::MetersToHorizontalUncertainty() End\n");
       
   410 	return (TInt)uncert;	
       
   411 	}
       
   412 
       
   413 /**	
       
   414 MetersToVerticalUncertainty()
       
   415 
       
   416 Converts from meters to uncertainty code, as defined in 3GPP TS 23.032:
       
   417 uncertainty h = C( (1+x)^k - 1 )
       
   418 
       
   419 h = uncertainty in meters
       
   420 C = 45;
       
   421 x = 0.025
       
   422 k = uncertainty code
       
   423 
       
   424 hence k = ln(h/C + 1) / ln(1+x), limited to 7 bits
       
   425 */
       
   426 TInt CRrlpMeasurePositionResponse::MetersToVerticalUncertainty(const TReal32& aDistance)
       
   427 	{
       
   428 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::MetersToVerticalUncertainty() Begin\n");
       
   429 	TReal uncert;
       
   430 	Math::Ln(uncert,  (aDistance/45) + 1 );
       
   431 	uncert /= KLbsLogOnePointZeroTwoFive;
       
   432 	if (uncert>KLbsMaxUncert)
       
   433 		{
       
   434 		uncert = KLbsMaxUncert;
       
   435 		}
       
   436 
       
   437 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::MetersToVerticalUncertainty() End\n");
       
   438 	return (TInt)uncert;
       
   439 	}
       
   440 
       
   441 /** 
       
   442 Sets measurement information
       
   443 
       
   444 @param  aPosInfo reference to the reported position data from LBS
       
   445 @return error indication, KErrNone otherwise
       
   446 */
       
   447 EXPORT_C TInt CRrlpMeasurePositionResponse::SetMeasurementInformation(const TPositionInfoBase& aPosInfo)
       
   448 	{
       
   449 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::SetMeasurementInformation() Begin\n");
       
   450 	__ASSERT_DEBUG(iData->component.u.msrPositionRsp != NULL, User::Invariant());
       
   451 	
       
   452 	ASN1T_MsrPosition_Rsp* msgBody = iData->component.u.msrPositionRsp;
       
   453 	
       
   454 	// handle Position Info class type
       
   455 	if ((aPosInfo.PositionClassType() & EPositionGpsMeasurementInfoClass) != 0)
       
   456 		{
       
   457 		const TPositionGpsMeasurementInfo& measurementInfo = reinterpret_cast <const TPositionGpsMeasurementInfo&>(aPosInfo);
       
   458 		msgBody->m.gps_MeasureInfoPresent = 1;
       
   459 		
       
   460 		// only support the sending of a single set of GPS measurements.
       
   461 		ASN1C_SeqOfGPS_MsrSetElement msrSetArray(*iControl, msgBody->gps_MeasureInfo.gpsMsrSetList);
       
   462 		msrSetArray.init();
       
   463 		ASN1T_GPS_MsrSetElement* gpsMsrSetElement = msrSetArray.NewElement();
       
   464 		if (gpsMsrSetElement == NULL)
       
   465 			{
       
   466 			return KErrNoMemory;
       
   467 			}
       
   468 		
       
   469 		// LBS API does not provide optional Reference Frame information.
       
   470 		gpsMsrSetElement->m.refFramePresent = 0;
       
   471 		
       
   472 		// GPS Time Of Week - RRLP parameter is described as the least significant 
       
   473 		// 24 bits of the GPS TOW. Further study indicates it is in fact the result
       
   474 		// of the TOW within a 4 hour window period (144000000ms). Therefore the
       
   475 		// value is calculated as GPS_TOW_MS mod 144000000.
       
   476 		TReal tow = 0;
       
   477 		Math::Mod(tow, measurementInfo.GpsTimeOfWeek(), KLbsTowMod);
       
   478 		gpsMsrSetElement->gpsTOW = tow;
       
   479 		
       
   480 		// build the array of measurements
       
   481 		ASN1C_SeqOfGPS_MsrElement msrElementArray(*iControl, gpsMsrSetElement->gps_msrList);
       
   482 		msrElementArray.init();
       
   483 
       
   484 		for (TInt i = 0; i < measurementInfo.NumMeasurements(); ++i)
       
   485 			{
       
   486 			TPositionGpsMeasurementData data;
       
   487 			if (measurementInfo.GetMeasurementData(i, data) == KErrNone)
       
   488 				{
       
   489 				ASN1T_GPS_MsrElement* gpsMsrElement = msrElementArray.NewElement();
       
   490 				if (gpsMsrElement == NULL)
       
   491 					{
       
   492 					return KErrNoMemory;
       
   493 					}
       
   494 
       
   495 				gpsMsrElement->satelliteID     = data.SatelliteId();
       
   496 				gpsMsrElement->cNo             = data.CarrierNoiseRatio();
       
   497 				gpsMsrElement->doppler         = data.Doppler();
       
   498 				gpsMsrElement->wholeChips      = data.WholeGpsChips();
       
   499 				gpsMsrElement->fracChips       = data.FractionalGpsChips();
       
   500 				gpsMsrElement->mpathIndic      = data.MultiPathIndicator();
       
   501 				gpsMsrElement->pseuRangeRMSErr = data.PseudoRangeRmsError();
       
   502 				
       
   503 				msrElementArray.Append(gpsMsrElement);
       
   504 				}
       
   505 			}
       
   506 		msrSetArray.Append(gpsMsrSetElement);
       
   507 		
       
   508 		// append any GPS Timing Measurement Data
       
   509 		TGpsTimingMeasurementData timingData;
       
   510 		if  (KErrNone == measurementInfo.GetGpsTimingData(timingData))
       
   511 		    {
       
   512 		    SetGpsTimingData(timingData);
       
   513 		    }
       
   514 		}
       
   515 	
       
   516 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::SetMeasurementInformation() End\n");
       
   517 	return KErrNone;
       
   518 	}
       
   519 
       
   520 
       
   521 /** 
       
   522 SetLocationError()
       
   523 
       
   524 Sets Location Error element
       
   525 
       
   526 @param  aLocError - location error
       
   527 @return error indication, KErrNone otherwise
       
   528 */
       
   529 EXPORT_C TInt CRrlpMeasurePositionResponse::SetLocationError(TRrlpLocError aLocError)
       
   530 	{
       
   531 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::SetLocationError() Begin\n");
       
   532 	SUPLLOG2(ELogP1, "    - TRrlpLocError aLocError = %d", aLocError);
       
   533 	
       
   534 	__ASSERT_DEBUG(iData->component.u.msrPositionRsp != NULL, User::Invariant());
       
   535 	ASN1T_MsrPosition_Rsp* msgBody = iData->component.u.msrPositionRsp;
       
   536 	msgBody->m.locationErrorPresent = 1;
       
   537 	msgBody->locationError.locErrorReason = aLocError;
       
   538 	
       
   539 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::SetLocationError() End\n");
       
   540 	return KErrNone;
       
   541 	}
       
   542 
       
   543 	
       
   544 /** 
       
   545 SetLocationError()
       
   546 
       
   547 Sets Location Error element with request for additional assistance data 
       
   548 
       
   549 @see TRrlpLocError
       
   550 @param  aLocError - location error
       
   551 @return error indication, KErrNone otherwise
       
   552 */
       
   553 EXPORT_C TInt CRrlpMeasurePositionResponse::SetLocationError(TRrlpLocError aLocError, const TLbsAsistanceDataGroup& aDataReqMask)
       
   554 	{
       
   555 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::SetLocationError() Begin\n");
       
   556 	SUPLLOG2(ELogP1, "    - TRrlpLocError aLocError = %d", aLocError);
       
   557 	SUPLLOG2(ELogP1, "    - TLbsAsistanceDataGroup aDataReqMask  = 0x%08X\n", aDataReqMask);
       
   558 	
       
   559 	__ASSERT_DEBUG(iData->component.u.msrPositionRsp != NULL, User::Invariant());
       
   560 	ASN1T_MsrPosition_Rsp* msgBody = iData->component.u.msrPositionRsp;
       
   561 	msgBody->m.locationErrorPresent = 1;
       
   562 	msgBody->locationError.locErrorReason = aLocError;
       
   563 
       
   564 	// Additional Assistance Data is encoded according to 3GPP TS 49.031, excluding
       
   565 	// the IEI and length octets.
       
   566 	if (aDataReqMask != EAssistanceDataNone)
       
   567 		{
       
   568 		msgBody->locationError.m.additionalAssistanceDataPresent = 1;
       
   569 		//ASN1T_AdditionalAssistanceData
       
   570 		msgBody->locationError.additionalAssistanceData.m.extensionContainerPresent = 0;
       
   571 		msgBody->locationError.additionalAssistanceData.m.gpsAssistanceDataPresent = 1;
       
   572 
       
   573 		// short name reference
       
   574 		ASN1T_GPSAssistanceData& requestedData = msgBody->locationError.additionalAssistanceData.gpsAssistanceData;
       
   575 
       
   576 		// ensure the data masks are clear and set number of octets to be sent
       
   577 		requestedData.data[0] = 0;
       
   578 		requestedData.data[1] = 0;
       
   579 		requestedData.numocts = 2;
       
   580 				
       
   581 		// set requested assistance types
       
   582 		// we do not request Ephemeris Extension or Ephemeris Extension Check or inform
       
   583 		// the SMLC of satellite specific information we already have.
       
   584 		// data is described by bit location, as per the following:
       
   585 
       
   586 		//         | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
       
   587 		// octet 1 | H | G | F | E | D | C | B | A | 
       
   588 		// octet 2 | P | O | N | M | L | K | J | I |
       
   589 		if (EAssistanceDataAquisitionAssistance & aDataReqMask)
       
   590 			{
       
   591 			// bit H
       
   592 			requestedData.data[0] |= 1<<7;
       
   593 			}
       
   594 		if (EAssistanceDataBadSatList & aDataReqMask)
       
   595 			{
       
   596 			// bit I
       
   597 			requestedData.data[1] |= 1;
       
   598 			}
       
   599 		if (EAssistanceDataNavigationModel & aDataReqMask)
       
   600 			{
       
   601 			// bit D
       
   602 			requestedData.data[0] |= 1<<3;
       
   603 			}
       
   604 		if (EAssistanceDataReferenceTime & aDataReqMask)
       
   605 			{
       
   606 			// bit G
       
   607 			requestedData.data[0] |= 1<<6;
       
   608 			}
       
   609 		if (EAssistanceDataIonosphericModel & aDataReqMask)
       
   610 			{
       
   611 			// bit C
       
   612 			requestedData.data[0] |= 1<<2;
       
   613 			}
       
   614 		if (EAssistanceDataDgpsCorrections & aDataReqMask)
       
   615 			{
       
   616 			// bit E
       
   617 			requestedData.data[0] |= 1<<4;
       
   618 			}
       
   619 		if (EAssistanceDataReferenceLocation & aDataReqMask)
       
   620 			{
       
   621 		 	// bit F
       
   622 		 	requestedData.data[0] |= 1<<5;
       
   623 			}
       
   624 		if (EAssistanceDataAlmanac & aDataReqMask)
       
   625 			{
       
   626 			// bit A
       
   627 			requestedData.data[0] |= 1;
       
   628 			}
       
   629 		if (EAssistanceDataPositioningGpsUtcModel & aDataReqMask)
       
   630 			{
       
   631 			// bit B
       
   632 			requestedData.data[0] |= 1<<1;
       
   633 			}
       
   634 		}
       
   635 	
       
   636 	SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::SetLocationError() End\n");
       
   637 	return KErrNone;
       
   638 	}
       
   639 
       
   640 /** 
       
   641 SetGpsTimingData()
       
   642 
       
   643 Sets GPS Fine Timing Data
       
   644 
       
   645 @see TGpsTimingMeasurementData
       
   646 @param  aTimingData - timing data
       
   647 @return error indication, KErrNone otherwise
       
   648 */
       
   649 void CRrlpMeasurePositionResponse::SetGpsTimingData(const TGpsTimingMeasurementData& aTimingData)
       
   650     {
       
   651     SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::SetGpsTimingData() Begin\n");
       
   652     
       
   653     // check that the timing structure contains GPS data
       
   654     if (TGpsTimingMeasurementData::EGpsTimingDataTypeGsm != aTimingData.DataType())
       
   655         {
       
   656         SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::SetGpsTimingData() End Unsupported Data Type\n");
       
   657         return;
       
   658         }
       
   659         
       
   660     __ASSERT_DEBUG(iData->component.u.msrPositionRsp != NULL, User::Invariant());
       
   661     ASN1T_MsrPosition_Rsp* msgBody = iData->component.u.msrPositionRsp;
       
   662 
       
   663     // mark r98 extension and timing measurements parameter present
       
   664     msgBody->m.rel_98_MsrPosition_Rsp_ExtensionPresent = 1;
       
   665     msgBody->rel_98_MsrPosition_Rsp_Extension.m.timeAssistanceMeasurementsPresent = 1;
       
   666     
       
   667     // reference to the data member to be populated
       
   668     ASN1T_GPSTimeAssistanceMeasurements& measurements = msgBody->rel_98_MsrPosition_Rsp_Extension.timeAssistanceMeasurements;
       
   669 
       
   670     // populate the data structure. 
       
   671     measurements.referenceFrameMSB = aTimingData.ReferenceFrameMsb();
       
   672     if (aTimingData.GpsTowSubms() >= 0)
       
   673         {
       
   674         measurements.m.gpsTowSubmsPresent = 1;
       
   675         measurements.gpsTowSubms = aTimingData.GpsTowSubms();
       
   676         }
       
   677     if (aTimingData.DeltaTow() >= 0)
       
   678         {
       
   679         measurements.m.deltaTowPresent = 1;
       
   680         measurements.deltaTow = aTimingData.DeltaTow();
       
   681         }
       
   682     if (aTimingData.GpsReferenceTimeUncertainty() >= 0)
       
   683         {
       
   684         measurements.m.gpsReferenceTimeUncertaintyPresent = 1;
       
   685         measurements.gpsReferenceTimeUncertainty = aTimingData.GpsReferenceTimeUncertainty();
       
   686         }
       
   687 
       
   688     SUPLLOG(ELogP1, "CRrlpMeasurePositionResponse::SetGpsTimingData() End\n");
       
   689     return;
       
   690     }
       
   691 
       
   692 
       
   693 /**
       
   694 SetExtendedReference()
       
   695 
       
   696 Sets the extended reference parameters in the outgoing message, if they are set
       
   697 in the passed container.
       
   698 
       
   699 @param aRrlpRef on return, populated with the session reference details
       
   700 @return KErrNotFound if no extended reference data is present, 
       
   701 		KErrNone otherwise
       
   702 */	
       
   703 TInt CRrlpMeasurePositionResponse::SetExtendedReference(const TRrlpReference& aRrlpRef)
       
   704 	{
       
   705 	__ASSERT_DEBUG(iData->component.u.msrPositionRsp != NULL, User::Invariant());
       
   706 	
       
   707 	// if present, populate the optional Rel-5 extended reference
       
   708 	if (aRrlpRef.aRel5EntendedRefPresent)
       
   709 		{
       
   710 		// mark the optional component present
       
   711 		iData->component.u.msrPositionRsp->m.rel_5_MsrPosition_Rsp_ExtensionPresent = 1;
       
   712 		iData->component.u.msrPositionRsp->rel_5_MsrPosition_Rsp_Extension.m.extended_referencePresent = 1;
       
   713 		ASN1T_Extended_reference* extendedRef = &iData->component.u.msrPositionRsp->rel_5_MsrPosition_Rsp_Extension.extended_reference;
       
   714 		extendedRef->smlc_code = aRrlpRef.aRel5SmlcCode;
       
   715 		extendedRef->transaction_ID = aRrlpRef.aRel5TransactionId;
       
   716 		}
       
   717 	else
       
   718 		{
       
   719 		return KErrNotFound;
       
   720 		}
       
   721 	
       
   722 	return KErrNone;
       
   723 	}
       
   724