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 |
|