1 /* Copyright (c) 2017, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation, nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29 #define LOG_TAG "LocSvc_GnssAdapter"
30
31 #include <sys/stat.h>
32 #include <errno.h>
33 #include <ctype.h>
34 #include <cutils/properties.h>
35 #include <math.h>
36 #include <arpa/inet.h>
37 #include <netinet/in.h>
38 #include <netdb.h>
39 #include <GnssAdapter.h>
40 #include <string>
41 #include <loc_log.h>
42 #include <Agps.h>
43
44 using namespace loc_core;
45
GnssAdapter()46 GnssAdapter::GnssAdapter() :
47 LocAdapterBase(0,
48 LocDualContext::getLocFgContext(NULL,
49 NULL,
50 LocDualContext::mLocationHalName,
51 false)),
52 mUlpProxy(new UlpProxyBase()),
53 mSuplMode(GNSS_SUPL_MODE_STANDALONE),
54 mUlpPositionMode(),
55 mGnssSvIdUsedInPosition(),
56 mGnssSvIdUsedInPosAvail(false),
57 mControlCallbacks(),
58 mPowerVoteId(0),
59 mNiData(),
60 mAgpsManager()
61 {
62 LOC_LOGD("%s]: Constructor %p", __func__, this);
63 mUlpPositionMode.mode = LOC_POSITION_MODE_INVALID;
64 readConfigCommand();
65 setConfigCommand();
66
67 }
68
69 inline
~GnssAdapter()70 GnssAdapter::~GnssAdapter()
71 {
72 LOC_LOGD("%s]: Destructor", __func__);
73 delete mUlpProxy;
74 }
75
76 void
setControlCallbacksCommand(LocationControlCallbacks & controlCallbacks)77 GnssAdapter::setControlCallbacksCommand(LocationControlCallbacks& controlCallbacks)
78 {
79 struct MsgSetControlCallbacks : public LocMsg {
80 GnssAdapter& mAdapter;
81 const LocationControlCallbacks mControlCallbacks;
82 inline MsgSetControlCallbacks(GnssAdapter& adapter,
83 LocationControlCallbacks& controlCallbacks) :
84 LocMsg(),
85 mAdapter(adapter),
86 mControlCallbacks(controlCallbacks) {}
87 inline virtual void proc() const {
88 mAdapter.setControlCallbacks(mControlCallbacks);
89 }
90 };
91
92 sendMsg(new MsgSetControlCallbacks(*this, controlCallbacks));
93 }
94
95 void
convertOptions(LocPosMode & out,const LocationOptions & options)96 GnssAdapter::convertOptions(LocPosMode& out, const LocationOptions& options)
97 {
98 LocPosMode locPosMode = {};
99 switch (options.mode) {
100 case GNSS_SUPL_MODE_MSB:
101 out.mode = LOC_POSITION_MODE_MS_BASED;
102 break;
103 case GNSS_SUPL_MODE_MSA:
104 out.mode = LOC_POSITION_MODE_MS_ASSISTED;
105 break;
106 default:
107 out.mode = LOC_POSITION_MODE_STANDALONE;
108 break;
109 }
110 out.share_position = true;
111 out.min_interval = options.minInterval;
112 }
113
114 void
convertLocation(Location & out,const LocGpsLocation & locGpsLocation,const LocPosTechMask techMask)115 GnssAdapter::convertLocation(Location& out, const LocGpsLocation& locGpsLocation,
116 const LocPosTechMask techMask)
117 {
118 out.size = sizeof(Location);
119 if (LOC_GPS_LOCATION_HAS_LAT_LONG & locGpsLocation.flags) {
120 out.flags |= LOCATION_HAS_LAT_LONG_BIT;
121 out.latitude = locGpsLocation.latitude;
122 out.longitude = locGpsLocation.longitude;
123 }
124 if (LOC_GPS_LOCATION_HAS_ALTITUDE & locGpsLocation.flags) {
125 out.flags |= LOCATION_HAS_ALTITUDE_BIT;
126 out.altitude = locGpsLocation.altitude;
127 }
128 if (LOC_GPS_LOCATION_HAS_SPEED & locGpsLocation.flags) {
129 out.flags |= LOCATION_HAS_SPEED_BIT;
130 out.speed = locGpsLocation.speed;
131 }
132 if (LOC_GPS_LOCATION_HAS_BEARING & locGpsLocation.flags) {
133 out.flags |= LOCATION_HAS_BEARING_BIT;
134 out.bearing = locGpsLocation.bearing;
135 }
136 if (LOC_GPS_LOCATION_HAS_ACCURACY & locGpsLocation.flags) {
137 out.flags |= LOCATION_HAS_ACCURACY_BIT;
138 out.accuracy = locGpsLocation.accuracy;
139 }
140 out.timestamp = locGpsLocation.timestamp;
141 if (LOC_POS_TECH_MASK_SATELLITE & techMask) {
142 out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT;
143 }
144 if (LOC_POS_TECH_MASK_CELLID & techMask) {
145 out.techMask |= LOCATION_TECHNOLOGY_CELL_BIT;
146 }
147 if (LOC_POS_TECH_MASK_WIFI & techMask) {
148 out.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT;
149 }
150 if (LOC_POS_TECH_MASK_SENSORS & techMask) {
151 out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT;
152 }
153 }
154
155 void
convertLocationInfo(GnssLocationInfoNotification & out,const GpsLocationExtended & locationExtended)156 GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out,
157 const GpsLocationExtended& locationExtended)
158 {
159 out.size = sizeof(GnssLocationInfoNotification);
160 if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL & locationExtended.flags) {
161 out.flags |= GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT;
162 out.altitudeMeanSeaLevel = locationExtended.altitudeMeanSeaLevel;
163 }
164 if (GPS_LOCATION_EXTENDED_HAS_DOP & locationExtended.flags) {
165 out.flags |= GNSS_LOCATION_INFO_DOP_BIT;
166 out.pdop = locationExtended.pdop;
167 out.hdop = locationExtended.hdop;
168 out.vdop = locationExtended.vdop;
169 }
170 if (GPS_LOCATION_EXTENDED_HAS_MAG_DEV & locationExtended.flags) {
171 out.flags |= GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT;
172 out.magneticDeviation = locationExtended.magneticDeviation;
173 }
174 if (GPS_LOCATION_EXTENDED_HAS_VERT_UNC & locationExtended.flags) {
175 out.flags |= GNSS_LOCATION_INFO_VER_ACCURACY_BIT;
176 out.verAccuracy = locationExtended.vert_unc;
177 }
178 if (GPS_LOCATION_EXTENDED_HAS_SPEED_UNC & locationExtended.flags) {
179 out.flags |= GNSS_LOCATION_INFO_SPEED_ACCURACY_BIT;
180 out.speedAccuracy = locationExtended.speed_unc;
181 }
182 if (GPS_LOCATION_EXTENDED_HAS_BEARING_UNC & locationExtended.flags) {
183 out.flags |= GNSS_LOCATION_INFO_BEARING_ACCURACY_BIT;
184 out.bearingAccuracy = locationExtended.bearing_unc;
185 }
186 if (GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY & locationExtended.flags) {
187 out.flags |= GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT;
188 switch (locationExtended.horizontal_reliability) {
189 case LOC_RELIABILITY_VERY_LOW:
190 out.horReliability = LOCATION_RELIABILITY_VERY_LOW;
191 break;
192 case LOC_RELIABILITY_LOW:
193 out.horReliability = LOCATION_RELIABILITY_LOW;
194 break;
195 case LOC_RELIABILITY_MEDIUM:
196 out.horReliability = LOCATION_RELIABILITY_MEDIUM;
197 break;
198 case LOC_RELIABILITY_HIGH:
199 out.horReliability = LOCATION_RELIABILITY_HIGH;
200 break;
201 default:
202 out.horReliability = LOCATION_RELIABILITY_NOT_SET;
203 break;
204 }
205 }
206 if (GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY & locationExtended.flags) {
207 out.flags |= GNSS_LOCATION_INFO_VER_RELIABILITY_BIT;
208 switch (locationExtended.vertical_reliability) {
209 case LOC_RELIABILITY_VERY_LOW:
210 out.verReliability = LOCATION_RELIABILITY_VERY_LOW;
211 break;
212 case LOC_RELIABILITY_LOW:
213 out.verReliability = LOCATION_RELIABILITY_LOW;
214 break;
215 case LOC_RELIABILITY_MEDIUM:
216 out.verReliability = LOCATION_RELIABILITY_MEDIUM;
217 break;
218 case LOC_RELIABILITY_HIGH:
219 out.verReliability = LOCATION_RELIABILITY_HIGH;
220 break;
221 default:
222 out.verReliability = LOCATION_RELIABILITY_NOT_SET;
223 break;
224 }
225 }
226 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MAJOR & locationExtended.flags) {
227 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT;
228 out.horUncEllipseSemiMajor = locationExtended.horUncEllipseSemiMajor;
229 }
230 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MINOR & locationExtended.flags) {
231 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT;
232 out.horUncEllipseSemiMinor = locationExtended.horUncEllipseSemiMinor;
233 }
234 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_AZIMUTH & locationExtended.flags) {
235 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT;
236 out.horUncEllipseOrientAzimuth = locationExtended.horUncEllipseOrientAzimuth;
237 }
238 }
239
240 inline uint32_t
convertGpsLock(const GnssConfigGpsLock gpsLock)241 GnssAdapter::convertGpsLock(const GnssConfigGpsLock gpsLock)
242 {
243 switch (gpsLock) {
244 case GNSS_CONFIG_GPS_LOCK_MO:
245 return 1;
246 case GNSS_CONFIG_GPS_LOCK_NI:
247 return 2;
248 case GNSS_CONFIG_GPS_LOCK_MO_AND_NI:
249 return 3;
250 case GNSS_CONFIG_GPS_LOCK_NONE:
251 default:
252 return 0;
253 }
254 }
255
256 inline GnssConfigGpsLock
convertGpsLock(const uint32_t gpsLock)257 GnssAdapter::convertGpsLock(const uint32_t gpsLock)
258 {
259 switch (gpsLock) {
260 case 1:
261 return GNSS_CONFIG_GPS_LOCK_MO;
262 case 2:
263 return GNSS_CONFIG_GPS_LOCK_NI;
264 case 3:
265 return GNSS_CONFIG_GPS_LOCK_MO_AND_NI;
266 case 0:
267 default:
268 return GNSS_CONFIG_GPS_LOCK_NONE;
269 }
270 }
271
272 inline uint32_t
convertSuplVersion(const GnssConfigSuplVersion suplVersion)273 GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion)
274 {
275 switch (suplVersion) {
276 case GNSS_CONFIG_SUPL_VERSION_2_0_0:
277 return 0x00020000;
278 case GNSS_CONFIG_SUPL_VERSION_2_0_2:
279 return 0x00020002;
280 case GNSS_CONFIG_SUPL_VERSION_1_0_0:
281 default:
282 return 0x00010000;
283 }
284 }
285
286 inline GnssConfigSuplVersion
convertSuplVersion(const uint32_t suplVersion)287 GnssAdapter::convertSuplVersion(const uint32_t suplVersion)
288 {
289 switch (suplVersion) {
290 case 0x00020000:
291 return GNSS_CONFIG_SUPL_VERSION_2_0_0;
292 case 0x00020002:
293 return GNSS_CONFIG_SUPL_VERSION_2_0_2;
294 case 0x00010000:
295 default:
296 return GNSS_CONFIG_SUPL_VERSION_1_0_0;
297 }
298 }
299
300 inline uint32_t
convertLppProfile(const GnssConfigLppProfile lppProfile)301 GnssAdapter::convertLppProfile(const GnssConfigLppProfile lppProfile)
302 {
303 switch (lppProfile) {
304 case GNSS_CONFIG_LPP_PROFILE_USER_PLANE:
305 return 1;
306 case GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE:
307 return 2;
308 case GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE:
309 return 3;
310 case GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE:
311 default:
312 return 0;
313 }
314 }
315
316 inline GnssConfigLppProfile
convertLppProfile(const uint32_t lppProfile)317 GnssAdapter::convertLppProfile(const uint32_t lppProfile)
318 {
319 switch (lppProfile) {
320 case 1:
321 return GNSS_CONFIG_LPP_PROFILE_USER_PLANE;
322 case 2:
323 return GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE;
324 case 3:
325 return GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE;
326 case 0:
327 default:
328 return GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE;
329 }
330 }
331
332 uint32_t
convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)333 GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask)
334 {
335 uint32_t mask = 0;
336 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT & lppeControlPlaneMask) {
337 mask |= (1<<0);
338 }
339 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) {
340 mask |= (1<<1);
341 }
342 return mask;
343 }
344
345 GnssConfigLppeControlPlaneMask
convertLppeCp(const uint32_t lppeControlPlaneMask)346 GnssAdapter::convertLppeCp(const uint32_t lppeControlPlaneMask)
347 {
348 GnssConfigLppeControlPlaneMask mask = 0;
349 if ((1<<0) & lppeControlPlaneMask) {
350 mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT;
351 }
352 if ((1<<1) & lppeControlPlaneMask) {
353 mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT;
354 }
355 return mask;
356 }
357
358
359 uint32_t
convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)360 GnssAdapter::convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask)
361 {
362 uint32_t mask = 0;
363 if (GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT & lppeUserPlaneMask) {
364 mask |= (1<<0);
365 }
366 if (GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) {
367 mask |= (1<<1);
368 }
369 return mask;
370 }
371
372 GnssConfigLppeUserPlaneMask
convertLppeUp(const uint32_t lppeUserPlaneMask)373 GnssAdapter::convertLppeUp(const uint32_t lppeUserPlaneMask)
374 {
375 GnssConfigLppeUserPlaneMask mask = 0;
376 if ((1<<0) & lppeUserPlaneMask) {
377 mask |= GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT;
378 }
379 if ((1<<1) & lppeUserPlaneMask) {
380 mask |= GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT;
381 }
382 return mask;
383 }
384
385 uint32_t
convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)386 GnssAdapter::convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask)
387 {
388 uint32_t mask = 0;
389 if (GNSS_CONFIG_RRC_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
390 mask |= (1<<0);
391 }
392 if (GNSS_CONFIG_RRLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
393 mask |= (1<<1);
394 }
395 if (GNSS_CONFIG_LLP_USER_PLANE_BIT & aGloPositionProtocolMask) {
396 mask |= (1<<2);
397 }
398 if (GNSS_CONFIG_LLP_CONTROL_PLANE_BIT & aGloPositionProtocolMask) {
399 mask |= (1<<3);
400 }
401 return mask;
402 }
403
404 uint32_t
convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)405 GnssAdapter::convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl)
406 {
407 switch (emergencyPdnForEmergencySupl) {
408 case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES:
409 return 1;
410 case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO:
411 default:
412 return 0;
413 }
414 }
415
416 uint32_t
convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)417 GnssAdapter::convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices)
418 {
419 switch (suplEmergencyServices) {
420 case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES:
421 return 1;
422 case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO:
423 default:
424 return 0;
425 }
426 }
427
428 uint32_t
convertSuplMode(const GnssConfigSuplModeMask suplModeMask)429 GnssAdapter::convertSuplMode(const GnssConfigSuplModeMask suplModeMask)
430 {
431 uint32_t mask = 0;
432 if (GNSS_CONFIG_SUPL_MODE_MSB & suplModeMask) {
433 mask |= (1<<0);
434 }
435 if (GNSS_CONFIG_SUPL_MODE_MSA & suplModeMask) {
436 mask |= (1<<1);
437 }
438 return mask;
439 }
440
441 bool
resolveInAddress(const char * hostAddress,struct in_addr * inAddress)442 GnssAdapter::resolveInAddress(const char* hostAddress, struct in_addr* inAddress)
443 {
444 bool ret = true;
445
446 struct hostent* hp;
447 hp = gethostbyname(hostAddress);
448 if (hp != NULL) { /* DNS OK */
449 memcpy(inAddress, hp->h_addr_list[0], hp->h_length);
450 } else {
451 /* Try IP representation */
452 if (inet_aton(hostAddress, inAddress) == 0) {
453 /* IP not valid */
454 LOC_LOGE("%s]: DNS query on '%s' failed", __func__, hostAddress);
455 ret = false;
456 }
457 }
458
459 return ret;
460 }
461
462 void
readConfigCommand()463 GnssAdapter::readConfigCommand()
464 {
465 LOC_LOGD("%s]: ", __func__);
466
467 struct MsgReadConfig : public LocMsg {
468 GnssAdapter* mAdapter;
469 ContextBase& mContext;
470 inline MsgReadConfig(GnssAdapter* adapter,
471 ContextBase& context) :
472 LocMsg(),
473 mAdapter(adapter),
474 mContext(context) {}
475 inline virtual void proc() const {
476 // reads config into mContext->mGps_conf
477 mContext.readConfig();
478 mContext.requestUlp((LocAdapterBase*)mAdapter, mContext.getCarrierCapabilities());
479 }
480 };
481
482 if (mContext != NULL) {
483 sendMsg(new MsgReadConfig(this, *mContext));
484 }
485 }
486
487 void
setConfigCommand()488 GnssAdapter::setConfigCommand()
489 {
490 LOC_LOGD("%s]: ", __func__);
491
492 struct MsgSetConfig : public LocMsg {
493 GnssAdapter& mAdapter;
494 LocApiBase& mApi;
495 inline MsgSetConfig(GnssAdapter& adapter,
496 LocApiBase& api) :
497 LocMsg(),
498 mAdapter(adapter),
499 mApi(api) {}
500 inline virtual void proc() const {
501 mApi.setSUPLVersion(mAdapter.convertSuplVersion(ContextBase::mGps_conf.SUPL_VER));
502 mApi.setLPPConfig(mAdapter.convertLppProfile(ContextBase::mGps_conf.LPP_PROFILE));
503 mApi.setSensorControlConfig(ContextBase::mSap_conf.SENSOR_USAGE,
504 ContextBase::mSap_conf.SENSOR_PROVIDER);
505 mApi.setAGLONASSProtocol(ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT);
506 mApi.setLPPeProtocolCp(
507 mAdapter.convertLppeCp(ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY));
508 mApi.setLPPeProtocolUp(
509 mAdapter.convertLppeUp(ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY));
510 if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) {
511 mApi.setNMEATypes(LOC_NMEA_ALL_SUPPORTED_MASK);
512 }
513 mApi.setXtraVersionCheck(ContextBase::mGps_conf.XTRA_VERSION_CHECK);
514 if (ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID ||
515 ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
516 ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
517 ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID ||
518 ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID ) {
519 mApi.setSensorProperties(
520 ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID,
521 ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK,
522 ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
523 ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY,
524 ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
525 ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY,
526 ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
527 ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY,
528 ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID,
529 ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY);
530 }
531 mApi.setSensorPerfControlConfig(
532 ContextBase::mSap_conf.SENSOR_CONTROL_MODE,
533 ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH,
534 ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC,
535 ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH,
536 ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC,
537 ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH,
538 ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH,
539 ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH,
540 ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH,
541 ContextBase::mSap_conf.SENSOR_ALGORITHM_CONFIG_MASK);
542 }
543 };
544
545 sendMsg(new MsgSetConfig(*this, *mLocApi));
546 }
547
548 uint32_t*
gnssUpdateConfigCommand(GnssConfig config)549 GnssAdapter::gnssUpdateConfigCommand(GnssConfig config)
550 {
551 // count the number of bits set
552 GnssConfigFlagsMask flagsCopy = config.flags;
553 size_t count = 0;
554 while (flagsCopy > 0) {
555 if (flagsCopy & 1) {
556 count++;
557 }
558 flagsCopy >>= 1;
559 }
560 std::string idsString = "[";
561 uint32_t* ids = NULL;
562 if (count > 0) {
563 ids = new uint32_t[count];
564 for (size_t i=0; i < count; ++i) {
565 ids[i] = generateSessionId();
566 IF_LOC_LOGD {
567 idsString += std::to_string(ids[i]) + " ";
568 }
569 }
570 }
571 idsString += "]";
572
573 LOC_LOGD("%s]: ids %s flags 0x%X", __func__, idsString.c_str(), config.flags);
574
575 struct MsgGnssUpdateConfig : public LocMsg {
576 GnssAdapter& mAdapter;
577 LocApiBase& mApi;
578 GnssConfig mConfig;
579 uint32_t* mIds;
580 size_t mCount;
581 inline MsgGnssUpdateConfig(GnssAdapter& adapter,
582 LocApiBase& api,
583 GnssConfig config,
584 uint32_t* ids,
585 size_t count) :
586 LocMsg(),
587 mAdapter(adapter),
588 mApi(api),
589 mConfig(config),
590 mIds(ids),
591 mCount(count) {}
592 inline virtual ~MsgGnssUpdateConfig()
593 {
594 delete[] mIds;
595 }
596 inline virtual void proc() const {
597 //const size_t MAX_BITS_COUNT = 10;
598 //LocationError errs[MAX_BITS_COUNT] = {};
599 LocationError* errs = new LocationError[mCount];
600 LocationError err = LOCATION_ERROR_SUCCESS;
601 uint32_t index = 0;
602
603 if (mConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) {
604 uint32_t newGpsLock = mAdapter.convertGpsLock(mConfig.gpsLock);
605 ContextBase::mGps_conf.GPS_LOCK = newGpsLock;
606 if (0 == mAdapter.getPowerVoteId()) {
607 err = mApi.setGpsLock(mConfig.gpsLock);
608 }
609 if (index < mCount) {
610 errs[index++] = err;
611 }
612 }
613 if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) {
614 uint32_t newSuplVersion = mAdapter.convertSuplVersion(mConfig.suplVersion);
615 if (newSuplVersion != ContextBase::mGps_conf.SUPL_VER) {
616 ContextBase::mGps_conf.SUPL_VER = newSuplVersion;
617 err = mApi.setSUPLVersion(mConfig.suplVersion);
618 } else {
619 err = LOCATION_ERROR_SUCCESS;
620 }
621 if (index < mCount) {
622 errs[index++] = err;
623 }
624 }
625 if (mConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) {
626 if (GNSS_ASSISTANCE_TYPE_SUPL == mConfig.assistanceServer.type) {
627 char serverUrl[MAX_URL_LEN] = {};
628 uint32_t length = 0;
629 const char noHost[] = "NONE";
630 if (NULL == mConfig.assistanceServer.hostName ||
631 strncasecmp(noHost,
632 mConfig.assistanceServer.hostName,
633 sizeof(noHost)) == 0) {
634 } else {
635 length = snprintf(serverUrl, sizeof(serverUrl), "%s:%u",
636 mConfig.assistanceServer.hostName,
637 mConfig.assistanceServer.port);
638 }
639
640 if (sizeof(serverUrl) > length) {
641 err = mApi.setServer(serverUrl, length);
642 } else {
643 err = LOCATION_ERROR_INVALID_PARAMETER;
644 }
645 } else if (GNSS_ASSISTANCE_TYPE_C2K == mConfig.assistanceServer.type) {
646 struct in_addr addr;
647 if (!mAdapter.resolveInAddress(mConfig.assistanceServer.hostName, &addr)) {
648 LOC_LOGE("%s]: hostName %s cannot be resolved",
649 __func__, mConfig.assistanceServer.hostName);
650 err = LOCATION_ERROR_INVALID_PARAMETER;
651 } else {
652 unsigned int ip = htonl(addr.s_addr);
653 err = mApi.setServer(ip, mConfig.assistanceServer.port,
654 LOC_AGPS_CDMA_PDE_SERVER);
655 }
656 } else {
657 LOC_LOGE("%s]: Not a valid gnss assistance type %u",
658 __func__, mConfig.assistanceServer.type);
659 err = LOCATION_ERROR_INVALID_PARAMETER;
660 }
661 if (index < mCount) {
662 errs[index++] = err;
663 }
664 }
665 if (mConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) {
666 uint32_t newLppProfile = mAdapter.convertLppProfile(mConfig.lppProfile);
667 if (newLppProfile != ContextBase::mGps_conf.LPP_PROFILE) {
668 ContextBase::mGps_conf.LPP_PROFILE = newLppProfile;
669 err = mApi.setLPPConfig(mConfig.lppProfile);
670 } else {
671 err = LOCATION_ERROR_SUCCESS;
672 }
673 if (index < mCount) {
674 errs[index++] = err;
675 }
676 }
677 if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) {
678 uint32_t newLppeControlPlaneMask =
679 mAdapter.convertLppeCp(mConfig.lppeControlPlaneMask);
680 if (newLppeControlPlaneMask != ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY) {
681 ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY = newLppeControlPlaneMask;
682 err = mApi.setLPPeProtocolCp(mConfig.lppeControlPlaneMask);
683 } else {
684 err = LOCATION_ERROR_SUCCESS;
685 }
686 if (index < mCount) {
687 errs[index++] = err;
688 }
689 }
690 if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) {
691 uint32_t newLppeUserPlaneMask =
692 mAdapter.convertLppeUp(mConfig.lppeUserPlaneMask);
693 if (newLppeUserPlaneMask != ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY) {
694 ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY = newLppeUserPlaneMask;
695 err = mApi.setLPPeProtocolUp(mConfig.lppeUserPlaneMask);
696 } else {
697 err = LOCATION_ERROR_SUCCESS;
698 }
699 if (index < mCount) {
700 errs[index++] = err;
701 }
702 }
703 if (mConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) {
704 uint32_t newAGloProtMask =
705 mAdapter.convertAGloProt(mConfig.aGlonassPositionProtocolMask);
706 if (newAGloProtMask != ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT) {
707 ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = newAGloProtMask;
708 err = mApi.setAGLONASSProtocol(mConfig.aGlonassPositionProtocolMask);
709 } else {
710 err = LOCATION_ERROR_SUCCESS;
711 }
712 if (index < mCount) {
713 errs[index++] = err;
714 }
715 }
716 if (mConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) {
717 uint32_t newEP4ES = mAdapter.convertEP4ES(mConfig.emergencyPdnForEmergencySupl);
718 if (newEP4ES != ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
719 ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = newEP4ES;
720 }
721 err = LOCATION_ERROR_SUCCESS;
722 if (index < mCount) {
723 errs[index++] = err;
724 }
725 }
726 if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) {
727 uint32_t newSuplEs = mAdapter.convertSuplEs(mConfig.suplEmergencyServices);
728 if (newSuplEs != ContextBase::mGps_conf.SUPL_ES) {
729 ContextBase::mGps_conf.SUPL_ES = newSuplEs;
730 }
731 err = LOCATION_ERROR_SUCCESS;
732 if (index < mCount) {
733 errs[index++] = err;
734 }
735 }
736 if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) {
737 uint32_t newSuplMode = mAdapter.convertSuplMode(mConfig.suplModeMask);
738 if (newSuplMode != ContextBase::mGps_conf.SUPL_MODE) {
739 ContextBase::mGps_conf.SUPL_MODE = newSuplMode;
740 mAdapter.getUlpProxy()->setCapabilities(
741 ContextBase::getCarrierCapabilities());
742 }
743 err = LOCATION_ERROR_SUCCESS;
744 if (index < mCount) {
745 errs[index++] = err;
746 }
747 }
748
749 mAdapter.reportResponse(index, errs, mIds);
750 delete[] errs;
751 }
752 };
753
754 if (NULL != ids) {
755 sendMsg(new MsgGnssUpdateConfig(*this, *mLocApi, config, ids, count));
756 } else {
757 LOC_LOGE("%s]: No GNSS config items to update", __func__);
758 }
759
760 return ids;
761 }
762
763 uint32_t
gnssDeleteAidingDataCommand(GnssAidingData & data)764 GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data)
765 {
766 uint32_t sessionId = generateSessionId();
767 LOC_LOGD("%s]: client %p id %u", __func__, sessionId);
768
769 struct MsgDeleteAidingData : public LocMsg {
770 GnssAdapter& mAdapter;
771 LocApiBase& mApi;
772 uint32_t mSessionId;
773 GnssAidingData mData;
774 inline MsgDeleteAidingData(GnssAdapter& adapter,
775 LocApiBase& api,
776 uint32_t sessionId,
777 GnssAidingData& data) :
778 LocMsg(),
779 mAdapter(adapter),
780 mApi(api),
781 mSessionId(sessionId),
782 mData(data) {}
783 inline virtual void proc() const {
784 LocationError err = LOCATION_ERROR_SUCCESS;
785 #ifdef TARGET_BUILD_VARIANT_USER
786 err = LOCATION_ERROR_NOT_SUPPORTED;
787 #endif
788 if (LOCATION_ERROR_SUCCESS == err) {
789 err = mApi.deleteAidingData(mData);
790 }
791 mAdapter.reportResponse(err, mSessionId);
792 }
793 };
794
795 sendMsg(new MsgDeleteAidingData(*this, *mLocApi, sessionId, data));
796 return sessionId;
797 }
798
799 void
injectLocationCommand(double latitude,double longitude,float accuracy)800 GnssAdapter::injectLocationCommand(double latitude, double longitude, float accuracy)
801 {
802 LOC_LOGD("%s]: latitude %8.4f longitude %8.4f accuracy %8.4f",
803 __func__, latitude, longitude, accuracy);
804
805 struct MsgInjectLocation : public LocMsg {
806 LocApiBase& mApi;
807 ContextBase& mContext;
808 double mLatitude;
809 double mLongitude;
810 float mAccuracy;
811 inline MsgInjectLocation(LocApiBase& api,
812 ContextBase& context,
813 double latitude,
814 double longitude,
815 float accuracy) :
816 LocMsg(),
817 mApi(api),
818 mContext(context),
819 mLatitude(latitude),
820 mLongitude(longitude),
821 mAccuracy(accuracy) {}
822 inline virtual void proc() const {
823 if (!mContext.hasCPIExtendedCapabilities()) {
824 mApi.injectPosition(mLatitude, mLongitude, mAccuracy);
825 }
826 }
827 };
828
829 sendMsg(new MsgInjectLocation(*mLocApi, *mContext, latitude, longitude, accuracy));
830 }
831
832 void
injectTimeCommand(int64_t time,int64_t timeReference,int32_t uncertainty)833 GnssAdapter::injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty)
834 {
835 LOC_LOGD("%s]: time %lld timeReference %lld uncertainty %d",
836 __func__, time, timeReference, uncertainty);
837
838 struct MsgInjectTime : public LocMsg {
839 LocApiBase& mApi;
840 ContextBase& mContext;
841 int64_t mTime;
842 int64_t mTimeReference;
843 int32_t mUncertainty;
844 inline MsgInjectTime(LocApiBase& api,
845 ContextBase& context,
846 int64_t time,
847 int64_t timeReference,
848 int32_t uncertainty) :
849 LocMsg(),
850 mApi(api),
851 mContext(context),
852 mTime(time),
853 mTimeReference(timeReference),
854 mUncertainty(uncertainty) {}
855 inline virtual void proc() const {
856 mApi.setTime(mTime, mTimeReference, mUncertainty);
857 }
858 };
859
860 sendMsg(new MsgInjectTime(*mLocApi, *mContext, time, timeReference, uncertainty));
861 }
862
863 void
setUlpProxyCommand(UlpProxyBase * ulp)864 GnssAdapter::setUlpProxyCommand(UlpProxyBase* ulp)
865 {
866 LOC_LOGD("%s]: ", __func__);
867
868 struct MsgSetUlpProxy : public LocMsg {
869 GnssAdapter& mAdapter;
870 UlpProxyBase* mUlp;
871 inline MsgSetUlpProxy(GnssAdapter& adapter,
872 UlpProxyBase* ulp) :
873 LocMsg(),
874 mAdapter(adapter),
875 mUlp(ulp) {}
876 inline virtual void proc() const {
877 mAdapter.setUlpProxy(mUlp);
878 }
879 };
880
881 sendMsg(new MsgSetUlpProxy(*this, ulp));
882 }
883
884 void
setUlpProxy(UlpProxyBase * ulp)885 GnssAdapter::setUlpProxy(UlpProxyBase* ulp)
886 {
887 if (ulp == mUlpProxy) {
888 //This takes care of the case when double initalization happens
889 //and we get the same object back for UlpProxyBase . Do nothing
890 return;
891 }
892
893 LOC_LOGV("%s]: %p", __func__, ulp);
894 if (NULL == ulp) {
895 LOC_LOGE("%s]: ulp pointer is NULL", __func__);
896 ulp = new UlpProxyBase();
897 }
898
899 if (LOC_POSITION_MODE_INVALID != mUlpProxy->mPosMode.mode) {
900 // need to send this mode and start msg to ULP
901 ulp->sendFixMode(mUlpProxy->mPosMode);
902 }
903
904 if (mUlpProxy->mFixSet) {
905 ulp->sendStartFix();
906 }
907
908 delete mUlpProxy;
909 mUlpProxy = ulp;
910 }
911
912 void
addClientCommand(LocationAPI * client,const LocationCallbacks & callbacks)913 GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks)
914 {
915 LOC_LOGD("%s]: client %p", __func__, client);
916
917 struct MsgAddClient : public LocMsg {
918 GnssAdapter& mAdapter;
919 LocationAPI* mClient;
920 const LocationCallbacks mCallbacks;
921 inline MsgAddClient(GnssAdapter& adapter,
922 LocationAPI* client,
923 const LocationCallbacks& callbacks) :
924 LocMsg(),
925 mAdapter(adapter),
926 mClient(client),
927 mCallbacks(callbacks) {}
928 inline virtual void proc() const {
929 mAdapter.saveClient(mClient, mCallbacks);
930 }
931 };
932
933 sendMsg(new MsgAddClient(*this, client, callbacks));
934 }
935
936 void
removeClientCommand(LocationAPI * client)937 GnssAdapter::removeClientCommand(LocationAPI* client)
938 {
939 LOC_LOGD("%s]: client %p", __func__, client);
940
941 struct MsgRemoveClient : public LocMsg {
942 GnssAdapter& mAdapter;
943 LocationAPI* mClient;
944 inline MsgRemoveClient(GnssAdapter& adapter,
945 LocationAPI* client) :
946 LocMsg(),
947 mAdapter(adapter),
948 mClient(client) {}
949 inline virtual void proc() const {
950 mAdapter.stopClientSessions(mClient);
951 mAdapter.eraseClient(mClient);
952 }
953 };
954
955 sendMsg(new MsgRemoveClient(*this, client));
956 }
957
958 void
stopClientSessions(LocationAPI * client)959 GnssAdapter::stopClientSessions(LocationAPI* client)
960 {
961 LOC_LOGD("%s]: client %p", __func__, client);
962 for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end();) {
963 if (client == it->first.client) {
964 LocationError err = stopTrackingMultiplex(it->first.client, it->first.id);
965 if (LOCATION_ERROR_SUCCESS == err) {
966 it = mTrackingSessions.erase(it);
967 continue;
968 }
969 }
970 ++it; // increment only when not erasing an iterator
971 }
972
973 }
974
975 void
updateClientsEventMask()976 GnssAdapter::updateClientsEventMask()
977 {
978 LOC_API_ADAPTER_EVENT_MASK_T mask = 0;
979 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
980 if (it->second.trackingCb != nullptr) {
981 mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT;
982 }
983 if (it->second.gnssNiCb != nullptr) {
984 mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST;
985 }
986 if (it->second.gnssSvCb != nullptr) {
987 mask |= LOC_API_ADAPTER_BIT_SATELLITE_REPORT;
988 }
989 if (it->second.gnssNmeaCb != nullptr &&
990 NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) {
991 mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT;
992 }
993 if (it->second.gnssMeasurementsCb != nullptr) {
994 mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT;
995 }
996 }
997 updateEvtMask(mask, LOC_REGISTRATION_MASK_SET);
998 }
999
1000 void
handleEngineUpEvent()1001 GnssAdapter::handleEngineUpEvent()
1002 {
1003 struct MsgRestartSessions : public LocMsg {
1004 GnssAdapter& mAdapter;
1005 inline MsgRestartSessions(GnssAdapter& adapter) :
1006 LocMsg(),
1007 mAdapter(adapter) {}
1008 virtual void proc() const {
1009 mAdapter.restartSessions();
1010 }
1011 };
1012
1013 setConfigCommand();
1014 sendMsg(new MsgRestartSessions(*this));
1015 }
1016
1017 void
restartSessions()1018 GnssAdapter::restartSessions()
1019 {
1020 LOC_LOGD("%s]: ", __func__);
1021
1022 if (mTrackingSessions.empty()) {
1023 return;
1024 }
1025
1026 // get the LocationOptions that has the smallest interval, which should be the active one
1027 LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time
1028 for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) {
1029 if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet
1030 it->second.minInterval < smallestIntervalOptions.minInterval) {
1031 smallestIntervalOptions = it->second;
1032 }
1033 }
1034
1035 startTracking(smallestIntervalOptions);
1036 }
1037
1038 void
requestCapabilitiesCommand(LocationAPI * client)1039 GnssAdapter::requestCapabilitiesCommand(LocationAPI* client)
1040 {
1041 LOC_LOGD("%s]: ", __func__);
1042
1043 struct MsgRequestCapabilities : public LocMsg {
1044 GnssAdapter& mAdapter;
1045 LocApiBase& mApi;
1046 LocationAPI* mClient;
1047 inline MsgRequestCapabilities(GnssAdapter& adapter,
1048 LocApiBase& api,
1049 LocationAPI* client) :
1050 LocMsg(),
1051 mAdapter(adapter),
1052 mApi(api),
1053 mClient(client) {}
1054 inline virtual void proc() const {
1055 LocationCallbacks callbacks = mAdapter.getClientCallbacks(mClient);
1056 if (callbacks.capabilitiesCb == nullptr) {
1057 LOC_LOGE("%s]: capabilitiesCb is NULL", __func__);
1058 return;
1059 }
1060
1061 LocationCapabilitiesMask mask = {};
1062 // time based tracking always supported
1063 mask |= LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT;
1064 if (mApi.isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)){
1065 mask |= LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT |
1066 LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT;
1067 }
1068 if (mApi.isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) {
1069 mask |= LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT;
1070 }
1071 // geofence always supported
1072 mask |= LOCATION_CAPABILITIES_GEOFENCE_BIT;
1073 if (mApi.gnssConstellationConfig()) {
1074 mask |= LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT;
1075 }
1076 uint32_t carrierCapabilities = ContextBase::getCarrierCapabilities();
1077 if (carrierCapabilities & LOC_GPS_CAPABILITY_MSB) {
1078 mask |= LOCATION_CAPABILITIES_GNSS_MSB_BIT;
1079 }
1080 if (LOC_GPS_CAPABILITY_MSA & carrierCapabilities) {
1081 mask |= LOCATION_CAPABILITIES_GNSS_MSA_BIT;
1082 }
1083
1084 callbacks.capabilitiesCb(mask);
1085 }
1086 };
1087
1088 sendMsg(new MsgRequestCapabilities(*this, *mLocApi, client));
1089 }
1090
1091 LocationCallbacks
getClientCallbacks(LocationAPI * client)1092 GnssAdapter::getClientCallbacks(LocationAPI* client)
1093 {
1094 LocationCallbacks callbacks = {};
1095 auto it = mClientData.find(client);
1096 if (it != mClientData.end()) {
1097 callbacks = it->second;
1098 }
1099 return callbacks;
1100 }
1101
1102 void
saveClient(LocationAPI * client,const LocationCallbacks & callbacks)1103 GnssAdapter::saveClient(LocationAPI* client, const LocationCallbacks& callbacks)
1104 {
1105 mClientData[client] = callbacks;
1106 updateClientsEventMask();
1107 }
1108
1109 void
eraseClient(LocationAPI * client)1110 GnssAdapter::eraseClient(LocationAPI* client)
1111 {
1112 auto it = mClientData.find(client);
1113 if (it != mClientData.end()) {
1114 mClientData.erase(it);
1115 }
1116 updateClientsEventMask();
1117 }
1118
1119 bool
hasTrackingCallback(LocationAPI * client)1120 GnssAdapter::hasTrackingCallback(LocationAPI* client)
1121 {
1122 auto it = mClientData.find(client);
1123 return (it != mClientData.end() && it->second.trackingCb);
1124 }
1125
1126 bool
hasMeasurementsCallback(LocationAPI * client)1127 GnssAdapter::hasMeasurementsCallback(LocationAPI* client)
1128 {
1129 auto it = mClientData.find(client);
1130 return (it != mClientData.end() && it->second.gnssMeasurementsCb);
1131 }
1132
1133 bool
isTrackingSession(LocationAPI * client,uint32_t sessionId)1134 GnssAdapter::isTrackingSession(LocationAPI* client, uint32_t sessionId)
1135 {
1136 LocationSessionKey key(client, sessionId);
1137 return (mTrackingSessions.find(key) != mTrackingSessions.end());
1138 }
1139
1140 void
saveTrackingSession(LocationAPI * client,uint32_t sessionId,const LocationOptions & options)1141 GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId,
1142 const LocationOptions& options)
1143 {
1144 LocationSessionKey key(client, sessionId);
1145 mTrackingSessions[key] = options;
1146 }
1147
1148 void
eraseTrackingSession(LocationAPI * client,uint32_t sessionId)1149 GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId)
1150 {
1151 LocationSessionKey key(client, sessionId);
1152 auto it = mTrackingSessions.find(key);
1153 if (it != mTrackingSessions.end()) {
1154 mTrackingSessions.erase(it);
1155 }
1156
1157 }
1158
1159 void
reportResponse(LocationAPI * client,LocationError err,uint32_t sessionId)1160 GnssAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId)
1161 {
1162 LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err);
1163
1164 auto it = mClientData.find(client);
1165 if (it != mClientData.end() &&
1166 it->second.responseCb != nullptr) {
1167 it->second.responseCb(err, sessionId);
1168 } else {
1169 LOC_LOGW("%s]: client %p id %u not found in data", __func__, client, sessionId);
1170 }
1171 }
1172
1173 void
reportResponse(LocationError err,uint32_t sessionId)1174 GnssAdapter::reportResponse(LocationError err, uint32_t sessionId)
1175 {
1176 LOC_LOGD("%s]: id %u err %u", __func__, sessionId, err);
1177
1178 if (mControlCallbacks.size > 0 && mControlCallbacks.responseCb != nullptr) {
1179 mControlCallbacks.responseCb(err, sessionId);
1180 } else {
1181 LOC_LOGW("%s]: control client response callback not found", __func__);
1182 }
1183 }
1184
1185 void
reportResponse(size_t count,LocationError * errs,uint32_t * ids)1186 GnssAdapter::reportResponse(size_t count, LocationError* errs, uint32_t* ids)
1187 {
1188 IF_LOC_LOGD {
1189 std::string idsString = "[";
1190 std::string errsString = "[";
1191 if (NULL != ids && NULL != errs) {
1192 for (size_t i=0; i < count; ++i) {
1193 idsString += std::to_string(ids[i]) + " ";
1194 errsString += std::to_string(errs[i]) + " ";
1195 }
1196 }
1197 idsString += "]";
1198 errsString += "]";
1199
1200 LOC_LOGD("%s]: ids %s errs %s",
1201 __func__, idsString.c_str(), errsString.c_str());
1202 }
1203
1204 if (mControlCallbacks.size > 0 && mControlCallbacks.collectiveResponseCb != nullptr) {
1205 mControlCallbacks.collectiveResponseCb(count, errs, ids);
1206 } else {
1207 LOC_LOGW("%s]: control client callback not found", __func__);
1208 }
1209 }
1210
1211 uint32_t
startTrackingCommand(LocationAPI * client,LocationOptions & options)1212 GnssAdapter::startTrackingCommand(LocationAPI* client, LocationOptions& options)
1213 {
1214 uint32_t sessionId = generateSessionId();
1215 LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
1216 __func__, client, sessionId, options.minInterval, options.mode);
1217
1218 struct MsgStartTracking : public LocMsg {
1219 GnssAdapter& mAdapter;
1220 LocApiBase& mApi;
1221 LocationAPI* mClient;
1222 uint32_t mSessionId;
1223 LocationOptions mOptions;
1224 inline MsgStartTracking(GnssAdapter& adapter,
1225 LocApiBase& api,
1226 LocationAPI* client,
1227 uint32_t sessionId,
1228 LocationOptions options) :
1229 LocMsg(),
1230 mAdapter(adapter),
1231 mApi(api),
1232 mClient(client),
1233 mSessionId(sessionId),
1234 mOptions(options) {}
1235 inline virtual void proc() const {
1236 LocationError err = LOCATION_ERROR_SUCCESS;
1237 if (!mAdapter.hasTrackingCallback(mClient) &&
1238 !mAdapter.hasMeasurementsCallback(mClient)) {
1239 err = LOCATION_ERROR_CALLBACK_MISSING;
1240 } else if (0 == mOptions.size) {
1241 err = LOCATION_ERROR_INVALID_PARAMETER;
1242 } else {
1243 // Api doesn't support multiple clients for time based tracking, so mutiplex
1244 err = mAdapter.startTrackingMultiplex(mOptions);
1245 if (LOCATION_ERROR_SUCCESS == err) {
1246 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
1247 }
1248 }
1249 mAdapter.reportResponse(mClient, err, mSessionId);
1250 }
1251 };
1252
1253 sendMsg(new MsgStartTracking(*this, *mLocApi, client, sessionId, options));
1254 return sessionId;
1255
1256 }
1257
1258 LocationError
startTrackingMultiplex(const LocationOptions & options)1259 GnssAdapter::startTrackingMultiplex(const LocationOptions& options)
1260 {
1261 LocationError err = LOCATION_ERROR_SUCCESS;
1262 bool updateTrackingSession = false;
1263
1264 if (mTrackingSessions.empty()) {
1265 err = startTracking(options);
1266 } else {
1267 // get the LocationOptions that has the smallest interval, which should be the active one
1268 LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time
1269 for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) {
1270 if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet
1271 it->second.minInterval < smallestIntervalOptions.minInterval) {
1272 smallestIntervalOptions = it->second;
1273 }
1274 }
1275 // if new session's minInterval is smaller than any in other sessions
1276 if (options.minInterval < smallestIntervalOptions.minInterval) {
1277 // restart time based tracking with new options
1278 err = startTracking(options);
1279 }
1280 }
1281
1282 return err;
1283 }
1284
1285 LocationError
startTracking(const LocationOptions & options)1286 GnssAdapter::startTracking(const LocationOptions& options)
1287 {
1288 LocationError err = LOCATION_ERROR_SUCCESS;
1289 LocPosMode locPosMode = {};
1290 convertOptions(locPosMode, options);
1291 if (!mUlpProxy->sendFixMode(locPosMode)) {
1292 // do nothing
1293 }
1294 if (!mUlpProxy->sendStartFix()) {
1295 loc_api_adapter_err apiErr = mLocApi->startFix(locPosMode);
1296 if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) {
1297 err = LOCATION_ERROR_SUCCESS;
1298 // save supl mode, which is used for NMEA generation
1299 setSuplMode(options.mode);
1300 } else {
1301 err = LOCATION_ERROR_GENERAL_FAILURE;
1302 }
1303 }
1304
1305 return err;
1306 }
1307
1308 void
setPositionModeCommand(LocPosMode & locPosMode)1309 GnssAdapter::setPositionModeCommand(LocPosMode& locPosMode)
1310 {
1311 LOC_LOGD("%s]: min_interval %u mode %u",
1312 __func__, locPosMode.min_interval, locPosMode.mode);
1313
1314 struct MsgSetPositionMode : public LocMsg {
1315 GnssAdapter& mAdapter;
1316 LocApiBase& mApi;
1317 LocPosMode mLocPosMode;
1318 inline MsgSetPositionMode(GnssAdapter& adapter,
1319 LocApiBase& api,
1320 LocPosMode& locPosMode) :
1321 LocMsg(),
1322 mAdapter(adapter),
1323 mApi(api),
1324 mLocPosMode(locPosMode) {}
1325 inline virtual void proc() const {
1326 // saves the mode in adapter to be used when startTrackingCommand is called from ULP
1327 mAdapter.setUlpPositionMode(mLocPosMode);
1328 mApi.setPositionMode(mLocPosMode);
1329 }
1330 };
1331
1332 sendMsg(new MsgSetPositionMode(*this, *mLocApi, locPosMode));
1333 }
1334
1335 void
startTrackingCommand()1336 GnssAdapter::startTrackingCommand()
1337 {
1338 LOC_LOGD("%s]: ", __func__);
1339
1340 struct MsgStartTracking : public LocMsg {
1341 GnssAdapter& mAdapter;
1342 LocApiBase& mApi;
1343 inline MsgStartTracking(GnssAdapter& adapter,
1344 LocApiBase& api) :
1345 LocMsg(),
1346 mAdapter(adapter),
1347 mApi(api) {}
1348 inline virtual void proc() const {
1349 // we get this call from ULP, so just call LocApi without multiplexing because
1350 // ulp would be doing the multiplexing for us if it is present
1351 LocPosMode& ulpPositionMode = mAdapter.getUlpPositionMode();
1352 mApi.startFix(ulpPositionMode);
1353 // save supl mode, which is used for NMEA generation
1354 mAdapter.setSuplMode((GnssSuplMode)ulpPositionMode.mode);
1355 }
1356 };
1357
1358 sendMsg(new MsgStartTracking(*this, *mLocApi));
1359 }
1360
1361 void
updateTrackingOptionsCommand(LocationAPI * client,uint32_t id,LocationOptions & options)1362 GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id,
1363 LocationOptions& options)
1364 {
1365 LOC_LOGD("%s]: client %p id %u minInterval %u mode %u",
1366 __func__, client, id, options.minInterval, options.mode);
1367
1368 struct MsgUpdateTracking : public LocMsg {
1369 GnssAdapter& mAdapter;
1370 LocApiBase& mApi;
1371 LocationAPI* mClient;
1372 uint32_t mSessionId;
1373 LocationOptions mOptions;
1374 inline MsgUpdateTracking(GnssAdapter& adapter,
1375 LocApiBase& api,
1376 LocationAPI* client,
1377 uint32_t sessionId,
1378 LocationOptions options) :
1379 LocMsg(),
1380 mAdapter(adapter),
1381 mApi(api),
1382 mClient(client),
1383 mSessionId(sessionId),
1384 mOptions(options) {}
1385 inline virtual void proc() const {
1386 if (mAdapter.isTrackingSession(mClient, mSessionId)) {
1387 LocationError err = LOCATION_ERROR_SUCCESS;
1388 if (0 == mOptions.size) {
1389 err = LOCATION_ERROR_INVALID_PARAMETER;
1390 } else {
1391 // Api doesn't support multiple clients for time based tracking, so mutiplex
1392 err = mAdapter.startTrackingMultiplex(mOptions);
1393 if (LOCATION_ERROR_SUCCESS == err) {
1394 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions);
1395 }
1396 }
1397 mAdapter.reportResponse(mClient, err, mSessionId);
1398 }
1399 // we do not reportResponse for the case where there is no existing tracking session
1400 // for the client and id being used, since updateTrackingCommand can be sent to both
1401 // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response
1402 }
1403 };
1404
1405 sendMsg(new MsgUpdateTracking(*this, *mLocApi, client, id, options));
1406 }
1407
1408 void
stopTrackingCommand(LocationAPI * client,uint32_t id)1409 GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id)
1410 {
1411 LOC_LOGD("%s]: client %p id %u", __func__, client, id);
1412
1413 struct MsgStopTracking : public LocMsg {
1414 GnssAdapter& mAdapter;
1415 LocApiBase& mApi;
1416 LocationAPI* mClient;
1417 uint32_t mSessionId;
1418 inline MsgStopTracking(GnssAdapter& adapter,
1419 LocApiBase& api,
1420 LocationAPI* client,
1421 uint32_t sessionId) :
1422 LocMsg(),
1423 mAdapter(adapter),
1424 mApi(api),
1425 mClient(client),
1426 mSessionId(sessionId) {}
1427 inline virtual void proc() const {
1428 if (mAdapter.isTrackingSession(mClient, mSessionId)) {
1429 LocationError err = LOCATION_ERROR_SUCCESS;
1430 // Api doesn't support multiple clients for time based tracking, so mutiplex
1431 err = mAdapter.stopTrackingMultiplex(mClient, mSessionId);
1432 if (LOCATION_ERROR_SUCCESS == err) {
1433 mAdapter.eraseTrackingSession(mClient, mSessionId);
1434 }
1435 mAdapter.reportResponse(mClient, err, mSessionId);
1436 }
1437 // we do not reportResponse for the case where there is no existing tracking session
1438 // for the client and id being used, since stopTrackingCommand can be sent to both
1439 // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response
1440
1441 }
1442 };
1443
1444 sendMsg(new MsgStopTracking(*this, *mLocApi, client, id));
1445 }
1446
1447 LocationError
stopTrackingMultiplex(LocationAPI * client,uint32_t id)1448 GnssAdapter::stopTrackingMultiplex(LocationAPI* client, uint32_t id)
1449 {
1450 LocationError err = LOCATION_ERROR_SUCCESS;
1451
1452 if (1 == mTrackingSessions.size()) {
1453 err = stopTracking();
1454 } else {
1455 LocationSessionKey key(client, id);
1456
1457 // get the session we are stopping
1458 auto it = mTrackingSessions.find(key);
1459 if (it != mTrackingSessions.end()) {
1460 // find the next smallest interval, other than the session we are stopping
1461 LocationOptions smallestIntervalOptions; // size will be zero until set for the first time
1462 for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) {
1463 // if session is not the one we are stopping and either smallest interval is not set
1464 // or there is a new smallest interval, then set the new smallest interval
1465 if (it2->first != key && (0 == smallestIntervalOptions.size ||
1466 it2->second.minInterval < smallestIntervalOptions.minInterval)) {
1467 smallestIntervalOptions = it2->second;
1468 }
1469 }
1470 // if session we are stopping has smaller interval then next smallest
1471 if (it->second.minInterval < smallestIntervalOptions.minInterval) {
1472 // restart time based tracking with next smallest interval
1473 err = startTracking(smallestIntervalOptions);
1474 }
1475 }
1476 }
1477
1478 return err;
1479 }
1480
1481 LocationError
stopTracking()1482 GnssAdapter::stopTracking()
1483 {
1484 LocationError err = LOCATION_ERROR_SUCCESS;
1485 if (!mUlpProxy->sendStopFix()) {
1486 loc_api_adapter_err apiErr = mLocApi->stopFix();
1487 if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) {
1488 err = LOCATION_ERROR_SUCCESS;
1489 } else {
1490 err = LOCATION_ERROR_GENERAL_FAILURE;
1491 }
1492 }
1493
1494 return err;
1495 }
1496
1497 void
stopTrackingCommand()1498 GnssAdapter::stopTrackingCommand()
1499 {
1500 LOC_LOGD("%s]: ", __func__);
1501
1502 struct MsgStopTracking : public LocMsg {
1503 GnssAdapter& mAdapter;
1504 LocApiBase& mApi;
1505 inline MsgStopTracking(GnssAdapter& adapter,
1506 LocApiBase& api) :
1507 LocMsg(),
1508 mAdapter(adapter),
1509 mApi(api) {}
1510 inline virtual void proc() const {
1511 // clear the position mode
1512 LocPosMode mLocPosMode = {};
1513 mLocPosMode.mode = LOC_POSITION_MODE_INVALID;
1514 mAdapter.setUlpPositionMode(mLocPosMode);
1515 // don't need to multiplex because ULP will do that for us if it is present
1516 mApi.stopFix();
1517 }
1518 };
1519
1520 sendMsg(new MsgStopTracking(*this, *mLocApi));
1521 }
1522
1523 void
getZppCommand()1524 GnssAdapter::getZppCommand()
1525 {
1526 LOC_LOGD("%s]: ", __func__);
1527
1528 struct MsgGetZpp : public LocMsg {
1529 GnssAdapter& mAdapter;
1530 LocApiBase& mApi;
1531 inline MsgGetZpp(GnssAdapter& adapter,
1532 LocApiBase& api) :
1533 LocMsg(),
1534 mAdapter(adapter),
1535 mApi(api) {}
1536 inline virtual void proc() const {
1537 UlpLocation location = {};
1538 LocPosTechMask techMask = LOC_POS_TECH_MASK_DEFAULT;
1539 GpsLocationExtended locationExtended = {};
1540 locationExtended.size = sizeof(locationExtended);
1541
1542 mApi.getBestAvailableZppFix(location.gpsLocation, techMask);
1543 //Mark the location source as from ZPP
1544 location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO;
1545 location.position_source = ULP_LOCATION_IS_FROM_ZPP;
1546
1547 mAdapter.getUlpProxy()->reportPosition(location,
1548 locationExtended,
1549 LOC_SESS_SUCCESS,
1550 techMask);
1551 }
1552 };
1553
1554 sendMsg(new MsgGetZpp(*this, *mLocApi));
1555 }
1556
1557 bool
hasNiNotifyCallback(LocationAPI * client)1558 GnssAdapter::hasNiNotifyCallback(LocationAPI* client)
1559 {
1560 auto it = mClientData.find(client);
1561 return (it != mClientData.end() && it->second.gnssNiCb);
1562 }
1563
1564 void
gnssNiResponseCommand(LocationAPI * client,uint32_t id,GnssNiResponse response)1565 GnssAdapter::gnssNiResponseCommand(LocationAPI* client,
1566 uint32_t id,
1567 GnssNiResponse response)
1568 {
1569 LOC_LOGD("%s]: client %p id %u response %u", __func__, client, id, response);
1570
1571 struct MsgGnssNiResponse : public LocMsg {
1572 GnssAdapter& mAdapter;
1573 LocationAPI* mClient;
1574 uint32_t mSessionId;
1575 GnssNiResponse mResponse;
1576 inline MsgGnssNiResponse(GnssAdapter& adapter,
1577 LocationAPI* client,
1578 uint32_t sessionId,
1579 GnssNiResponse response) :
1580 LocMsg(),
1581 mAdapter(adapter),
1582 mClient(client),
1583 mSessionId(sessionId),
1584 mResponse(response) {}
1585 inline virtual void proc() const {
1586 NiData& niData = mAdapter.getNiData();
1587 LocationError err = LOCATION_ERROR_SUCCESS;
1588 if (!mAdapter.hasNiNotifyCallback(mClient)) {
1589 err = LOCATION_ERROR_ID_UNKNOWN;
1590 } else {
1591 NiSession* pSession = NULL;
1592 if (mSessionId == niData.sessionEs.reqID &&
1593 NULL != niData.sessionEs.rawRequest) {
1594 pSession = &niData.sessionEs;
1595 // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted
1596 if (mResponse == GNSS_NI_RESPONSE_ACCEPT &&
1597 NULL != niData.session.rawRequest) {
1598 pthread_mutex_lock(&niData.session.tLock);
1599 niData.session.resp = GNSS_NI_RESPONSE_IGNORE;
1600 niData.session.respRecvd = true;
1601 pthread_cond_signal(&niData.session.tCond);
1602 pthread_mutex_unlock(&niData.session.tLock);
1603 }
1604 } else if (mSessionId == niData.session.reqID &&
1605 NULL != niData.session.rawRequest) {
1606 pSession = &niData.session;
1607 }
1608
1609 if (pSession) {
1610 LOC_LOGI("%s]: gnssNiResponseCommand: send user mResponse %u for id %u",
1611 __func__, mResponse, mSessionId);
1612 pthread_mutex_lock(&pSession->tLock);
1613 pSession->resp = mResponse;
1614 pSession->respRecvd = true;
1615 pthread_cond_signal(&pSession->tCond);
1616 pthread_mutex_unlock(&pSession->tLock);
1617 } else {
1618 err = LOCATION_ERROR_ID_UNKNOWN;
1619 LOC_LOGE("%s]: gnssNiResponseCommand: id %u not an active session",
1620 __func__, mSessionId);
1621 }
1622 }
1623 mAdapter.reportResponse(mClient, err, mSessionId);
1624 }
1625 };
1626
1627 sendMsg(new MsgGnssNiResponse(*this, client, id, response));
1628
1629 }
1630
1631 void
gnssNiResponseCommand(GnssNiResponse response,void * rawRequest)1632 GnssAdapter::gnssNiResponseCommand(GnssNiResponse response, void* rawRequest)
1633 {
1634 LOC_LOGD("%s]: response %u", __func__, response);
1635
1636 struct MsgGnssNiResponse : public LocMsg {
1637 LocApiBase& mApi;
1638 const GnssNiResponse mResponse;
1639 const void* mPayload;
1640 inline MsgGnssNiResponse(LocApiBase& api,
1641 const GnssNiResponse response,
1642 const void* rawRequest) :
1643 LocMsg(),
1644 mApi(api),
1645 mResponse(response),
1646 mPayload(rawRequest) {}
1647 inline virtual ~MsgGnssNiResponse() {
1648 // this is a bit weird since mPayload is not
1649 // allocated by this class. But there is no better way.
1650 // mPayload actually won't be NULL here.
1651 free((void*)mPayload);
1652 }
1653 inline virtual void proc() const {
1654 mApi.informNiResponse(mResponse, mPayload);
1655 }
1656 };
1657
1658 sendMsg(new MsgGnssNiResponse(*mLocApi, response, rawRequest));
1659
1660 }
1661
1662 uint32_t
enableCommand(LocationTechnologyType techType)1663 GnssAdapter::enableCommand(LocationTechnologyType techType)
1664 {
1665 uint32_t sessionId = generateSessionId();
1666 LOC_LOGD("%s]: id %u techType %u", __func__, sessionId, techType);
1667
1668 struct MsgEnableGnss : public LocMsg {
1669 GnssAdapter& mAdapter;
1670 LocApiBase& mApi;
1671 ContextBase& mContext;
1672 uint32_t mSessionId;
1673 LocationTechnologyType mTechType;
1674 inline MsgEnableGnss(GnssAdapter& adapter,
1675 LocApiBase& api,
1676 ContextBase& context,
1677 uint32_t sessionId,
1678 LocationTechnologyType techType) :
1679 LocMsg(),
1680 mAdapter(adapter),
1681 mApi(api),
1682 mContext(context),
1683 mSessionId(sessionId),
1684 mTechType(techType) {}
1685 inline virtual void proc() const {
1686 LocationError err = LOCATION_ERROR_SUCCESS;
1687 uint32_t powerVoteId = mAdapter.getPowerVoteId();
1688 if (mTechType != LOCATION_TECHNOLOGY_TYPE_GNSS) {
1689 err = LOCATION_ERROR_INVALID_PARAMETER;
1690 } else if (powerVoteId > 0) {
1691 err = LOCATION_ERROR_ALREADY_STARTED;
1692 } else {
1693 mContext.modemPowerVote(true);
1694 mAdapter.setPowerVoteId(mSessionId);
1695 mApi.setGpsLock(GNSS_CONFIG_GPS_LOCK_NONE);
1696 }
1697 mAdapter.reportResponse(err, mSessionId);
1698 }
1699 };
1700
1701 if (mContext != NULL) {
1702 sendMsg(new MsgEnableGnss(*this, *mLocApi, *mContext, sessionId, techType));
1703 } else {
1704 LOC_LOGE("%s]: Context is NULL", __func__);
1705 }
1706
1707 return sessionId;
1708 }
1709
1710 void
disableCommand(uint32_t id)1711 GnssAdapter::disableCommand(uint32_t id)
1712 {
1713 LOC_LOGD("%s]: id %u", __func__, id);
1714
1715 struct MsgDisableGnss : public LocMsg {
1716 GnssAdapter& mAdapter;
1717 LocApiBase& mApi;
1718 ContextBase& mContext;
1719 uint32_t mSessionId;
1720 inline MsgDisableGnss(GnssAdapter& adapter,
1721 LocApiBase& api,
1722 ContextBase& context,
1723 uint32_t sessionId) :
1724 LocMsg(),
1725 mAdapter(adapter),
1726 mApi(api),
1727 mContext(context),
1728 mSessionId(sessionId) {}
1729 inline virtual void proc() const {
1730 LocationError err = LOCATION_ERROR_SUCCESS;
1731 uint32_t powerVoteId = mAdapter.getPowerVoteId();
1732 if (powerVoteId != mSessionId) {
1733 err = LOCATION_ERROR_ID_UNKNOWN;
1734 } else {
1735 mContext.modemPowerVote(false);
1736 mAdapter.setPowerVoteId(0);
1737 mApi.setGpsLock(mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK));
1738 }
1739 mAdapter.reportResponse(err, mSessionId);
1740 }
1741 };
1742
1743 if (mContext != NULL) {
1744 sendMsg(new MsgDisableGnss(*this, *mLocApi, *mContext, id));
1745 }
1746
1747 }
1748
1749 void
reportPositionEvent(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask,bool fromUlp)1750 GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation,
1751 const GpsLocationExtended& locationExtended,
1752 enum loc_sess_status status,
1753 LocPosTechMask techMask,
1754 bool fromUlp)
1755 {
1756 LOC_LOGD("%s]: fromUlp %u status %u", __func__, fromUlp, status);
1757
1758 // if this event is not called from ULP, then try to call into ULP and return if successfull
1759 if (!fromUlp) {
1760 if (mUlpProxy->reportPosition(ulpLocation, locationExtended,
1761 status, techMask)) {
1762 return;
1763 }
1764 }
1765
1766 struct MsgReportPosition : public LocMsg {
1767 GnssAdapter& mAdapter;
1768 const UlpLocation mUlpLocation;
1769 const GpsLocationExtended mLocationExtended;
1770 loc_sess_status mStatus;
1771 LocPosTechMask mTechMask;
1772 inline MsgReportPosition(GnssAdapter& adapter,
1773 const UlpLocation& ulpLocation,
1774 const GpsLocationExtended& locationExtended,
1775 loc_sess_status status,
1776 LocPosTechMask techMask) :
1777 LocMsg(),
1778 mAdapter(adapter),
1779 mUlpLocation(ulpLocation),
1780 mLocationExtended(locationExtended),
1781 mStatus(status),
1782 mTechMask(techMask) {}
1783 inline virtual void proc() const {
1784 mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask);
1785 }
1786 };
1787
1788 sendMsg(new MsgReportPosition(*this, ulpLocation, locationExtended, status, techMask));
1789 }
1790
1791 void
reportPosition(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,enum loc_sess_status status,LocPosTechMask techMask)1792 GnssAdapter::reportPosition(const UlpLocation& ulpLocation,
1793 const GpsLocationExtended& locationExtended,
1794 enum loc_sess_status status,
1795 LocPosTechMask techMask)
1796 {
1797 bool reported = false;
1798 if (LOC_SESS_FAILURE == status) {
1799 Location invalidLocation = {};
1800 invalidLocation.size = sizeof(Location);
1801 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
1802 if (nullptr != it->second.trackingCb) {
1803 it->second.trackingCb(invalidLocation);
1804 }
1805 }
1806 reported = true;
1807 }
1808 // what's in the else if is... (line by line)
1809 // 1. this is a final fix; and
1810 // 1.1 it is a Satellite fix; or
1811 // 1.2 it is a sensor fix
1812 // 2. (must be intermediate fix... implicit)
1813 // 2.1 we accepte intermediate; and
1814 // 2.2 it is NOT the case that
1815 // 2.2.1 there is inaccuracy; and
1816 // 2.2.2 we care about inaccuracy; and
1817 // 2.2.3 the inaccuracy exceeds our tolerance
1818 else if ((LOC_SESS_SUCCESS == status &&
1819 ((LOC_POS_TECH_MASK_SATELLITE |
1820 LOC_POS_TECH_MASK_SENSORS |
1821 LOC_POS_TECH_MASK_HYBRID) &
1822 techMask)) ||
1823 (LOC_SESS_INTERMEDIATE == ContextBase::mGps_conf.INTERMEDIATE_POS &&
1824 !((ulpLocation.gpsLocation.flags &
1825 LOC_GPS_LOCATION_HAS_ACCURACY) &&
1826 (ContextBase::mGps_conf.ACCURACY_THRES != 0) &&
1827 (ulpLocation.gpsLocation.accuracy >
1828 ContextBase::mGps_conf.ACCURACY_THRES)))) {
1829 if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) {
1830 mGnssSvIdUsedInPosAvail = true;
1831 mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids;
1832 }
1833 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
1834 if (nullptr != it->second.trackingCb) {
1835 Location location = {};
1836 convertLocation(location, ulpLocation.gpsLocation, techMask);
1837 it->second.trackingCb(location);
1838 }
1839 if (nullptr != it->second.gnssLocationInfoCb) {
1840 GnssLocationInfoNotification locationInfo = {};
1841 convertLocationInfo(locationInfo, locationExtended);
1842 it->second.gnssLocationInfoCb(locationInfo);
1843 }
1844 }
1845 reported = true;
1846 }
1847
1848 if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) {
1849 if (reported && status != LOC_SESS_FAILURE) {
1850 generateNmea(ulpLocation, locationExtended);
1851 } else {
1852 generateNmeaBlank();
1853 }
1854 }
1855
1856 // Free the allocated memory for rawData
1857 UlpLocation* gp = (UlpLocation*)&(ulpLocation);
1858 if (gp != NULL && gp->rawData != NULL)
1859 {
1860 delete (char*)gp->rawData;
1861 gp->rawData = NULL;
1862 gp->rawDataSize = 0;
1863 }
1864 }
1865
1866 void
reportSvEvent(const GnssSvNotification & svNotify,bool fromUlp)1867 GnssAdapter::reportSvEvent(const GnssSvNotification& svNotify,
1868 bool fromUlp)
1869 {
1870 LOC_LOGD("%s]: fromUlp %u", __func__, fromUlp);
1871
1872 // if this event is not called from ULP, then try to call into ULP and return if successfull
1873 if (!fromUlp) {
1874 if (mUlpProxy->reportSv(svNotify)) {
1875 return;
1876 }
1877 }
1878
1879 struct MsgReportSv : public LocMsg {
1880 GnssAdapter& mAdapter;
1881 const GnssSvNotification mSvNotify;
1882 inline MsgReportSv(GnssAdapter& adapter,
1883 const GnssSvNotification& svNotify) :
1884 LocMsg(),
1885 mAdapter(adapter),
1886 mSvNotify(svNotify) {}
1887 inline virtual void proc() const {
1888 mAdapter.reportSv((GnssSvNotification&)mSvNotify);
1889 }
1890 };
1891
1892 sendMsg(new MsgReportSv(*this, svNotify));
1893 }
1894
1895 void
reportSv(GnssSvNotification & svNotify)1896 GnssAdapter::reportSv(GnssSvNotification& svNotify)
1897 {
1898 if (mGnssSvIdUsedInPosAvail) {
1899 int numSv = svNotify.count;
1900 int16_t gnssSvId = 0;
1901 int prnMin = 0;
1902 uint64_t svUsedIdMask = 0;
1903 for (int i=0; i < numSv; i++) {
1904 gnssSvId = svNotify.gnssSvs[i].svId;
1905 if (gnssSvId <= GPS_SV_PRN_MAX) {
1906 svUsedIdMask = mGnssSvIdUsedInPosition.gps_sv_used_ids_mask;
1907 prnMin = GPS_SV_PRN_MIN;
1908 } else if ((gnssSvId >= GLO_SV_PRN_MIN) && (gnssSvId <= GLO_SV_PRN_MAX)) {
1909 svUsedIdMask = mGnssSvIdUsedInPosition.glo_sv_used_ids_mask;
1910 prnMin = GLO_SV_PRN_MIN;
1911 } else if ((gnssSvId >= BDS_SV_PRN_MIN) && (gnssSvId <= BDS_SV_PRN_MAX)) {
1912 svUsedIdMask = mGnssSvIdUsedInPosition.bds_sv_used_ids_mask;
1913 prnMin = BDS_SV_PRN_MIN;
1914 } else if ((gnssSvId >= GAL_SV_PRN_MIN) && (gnssSvId <= GAL_SV_PRN_MAX)) {
1915 svUsedIdMask = mGnssSvIdUsedInPosition.gal_sv_used_ids_mask;
1916 prnMin = GAL_SV_PRN_MIN;
1917 }
1918
1919 // If SV ID was used in previous position fix, then set USED_IN_FIX
1920 // flag, else clear the USED_IN_FIX flag.
1921 if (svUsedIdMask & (1 << (gnssSvId - prnMin))) {
1922 svNotify.gnssSvs[i].gnssSvOptionsMask |= GNSS_SV_OPTIONS_USED_IN_FIX_BIT;
1923 } else {
1924 svNotify.gnssSvs[i].gnssSvOptionsMask &= ~GNSS_SV_OPTIONS_USED_IN_FIX_BIT;
1925 }
1926 }
1927 }
1928
1929 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
1930 if (nullptr != it->second.gnssSvCb) {
1931 it->second.gnssSvCb(svNotify);
1932 }
1933 }
1934
1935 if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) {
1936 generateNmea(svNotify);
1937 }
1938
1939 mGnssSvIdUsedInPosAvail = false;
1940 }
1941
1942 void
reportNmeaEvent(const char * nmea,size_t length,bool fromUlp)1943 GnssAdapter::reportNmeaEvent(const char* nmea, size_t length, bool fromUlp)
1944 {
1945 //LOC_LOGD("%s]: fromUlp %u", __func__, fromUlp);
1946
1947 // if this event is not called from ULP, then try to call into ULP and return if successfull
1948 if (!fromUlp) {
1949 if (mUlpProxy->reportNmea(nmea, length)) {
1950 return;
1951 }
1952 }
1953
1954 struct MsgReportNmea : public LocMsg {
1955 GnssAdapter& mAdapter;
1956 const char* mNmea;
1957 size_t mLength;
1958 inline MsgReportNmea(GnssAdapter& adapter,
1959 const char* nmea,
1960 size_t length) :
1961 LocMsg(),
1962 mAdapter(adapter),
1963 mNmea(new char[length]),
1964 mLength(length) {
1965 memcpy((void*)mNmea, (void*)nmea, length);
1966 }
1967 inline virtual ~MsgReportNmea()
1968 {
1969 delete[] mNmea;
1970 }
1971 inline virtual void proc() const {
1972 mAdapter.reportNmea(mNmea, mLength);
1973 }
1974 };
1975
1976 sendMsg(new MsgReportNmea(*this, nmea, length));
1977 }
1978
1979 void
reportNmea(const char * nmea,size_t length)1980 GnssAdapter::reportNmea(const char* nmea, size_t length)
1981 {
1982 GnssNmeaNotification nmeaNotification = {};
1983 nmeaNotification.size = sizeof(GnssNmeaNotification);
1984
1985 struct timeval tv;
1986 gettimeofday(&tv, (struct timezone *) NULL);
1987 int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
1988 nmeaNotification.timestamp = now;
1989 nmeaNotification.nmea = nmea;
1990 nmeaNotification.length = length;
1991
1992 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
1993 if (nullptr != it->second.gnssNmeaCb) {
1994 it->second.gnssNmeaCb(nmeaNotification);
1995 }
1996 }
1997
1998 }
1999
2000 bool
requestNiNotifyEvent(const GnssNiNotification & notify,const void * data)2001 GnssAdapter::requestNiNotifyEvent(const GnssNiNotification ¬ify, const void* data)
2002 {
2003 LOC_LOGI("%s]: notif_type: %d, timeout: %d, default_resp: %d"
2004 "requestor_id: %s (encoding: %d) text: %s text (encoding: %d) extras: %s",
2005 __func__, notify.type, notify.timeout, notify.timeoutResponse,
2006 notify.requestor, notify.requestorEncoding,
2007 notify.message, notify.messageEncoding, notify.extras);
2008
2009 struct MsgReportNiNotify : public LocMsg {
2010 GnssAdapter& mAdapter;
2011 const GnssNiNotification mNotify;
2012 const void* mData;
2013 inline MsgReportNiNotify(GnssAdapter& adapter,
2014 const GnssNiNotification& notify,
2015 const void* data) :
2016 LocMsg(),
2017 mAdapter(adapter),
2018 mNotify(notify),
2019 mData(data) {}
2020 inline virtual void proc() const {
2021 mAdapter.requestNiNotify(mNotify, mData);
2022 }
2023 };
2024
2025 sendMsg(new MsgReportNiNotify(*this, notify, data));
2026
2027 return true;
2028 }
2029
niThreadProc(void * args)2030 static void* niThreadProc(void *args)
2031 {
2032 NiSession* pSession = (NiSession*)args;
2033 int rc = 0; /* return code from pthread calls */
2034
2035 struct timeval present_time;
2036 struct timespec expire_time;
2037
2038 pthread_mutex_lock(&pSession->tLock);
2039 /* Calculate absolute expire time */
2040 gettimeofday(&present_time, NULL);
2041 expire_time.tv_sec = present_time.tv_sec + pSession->respTimeLeft;
2042 expire_time.tv_nsec = present_time.tv_usec * 1000;
2043 LOC_LOGD("%s]: time out set for abs time %ld with delay %d sec",
2044 __func__, (long)expire_time.tv_sec, pSession->respTimeLeft);
2045
2046 while (!pSession->respRecvd) {
2047 rc = pthread_cond_timedwait(&pSession->tCond,
2048 &pSession->tLock,
2049 &expire_time);
2050 if (rc == ETIMEDOUT) {
2051 pSession->resp = GNSS_NI_RESPONSE_NO_RESPONSE;
2052 LOC_LOGD("%s]: time out after valting for specified time. Ret Val %d",
2053 __func__, rc);
2054 break;
2055 }
2056 }
2057 LOC_LOGD("%s]: Java layer has sent us a user response and return value from "
2058 "pthread_cond_timedwait = %d pSession->resp is %u", __func__, rc, pSession->resp);
2059 pSession->respRecvd = false; /* Reset the user response flag for the next session*/
2060
2061 // adding this check to support modem restart, in which case, we need the thread
2062 // to exit without calling sending data. We made sure that rawRequest is NULL in
2063 // loc_eng_ni_reset_on_engine_restart()
2064 GnssAdapter* adapter = pSession->adapter;
2065 GnssNiResponse resp;
2066 void* rawRequest = NULL;
2067 bool sendResponse = false;
2068
2069 if (NULL != pSession->rawRequest) {
2070 if (pSession->resp != GNSS_NI_RESPONSE_IGNORE) {
2071 resp = pSession->resp;
2072 rawRequest = pSession->rawRequest;
2073 sendResponse = true;
2074 } else {
2075 free(pSession->rawRequest);
2076 }
2077 pSession->rawRequest = NULL;
2078 }
2079 pthread_mutex_unlock(&pSession->tLock);
2080
2081 pSession->respTimeLeft = 0;
2082 pSession->reqID = 0;
2083
2084 if (sendResponse) {
2085 adapter->gnssNiResponseCommand(resp, rawRequest);
2086 }
2087
2088 return NULL;
2089 }
2090
2091 bool
requestNiNotify(const GnssNiNotification & notify,const void * data)2092 GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data)
2093 {
2094 NiSession* pSession = NULL;
2095 gnssNiCallback gnssNiCb = nullptr;
2096
2097 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2098 if (nullptr != it->second.gnssNiCb) {
2099 gnssNiCb = it->second.gnssNiCb;
2100 break;
2101 }
2102 }
2103 if (nullptr == gnssNiCb) {
2104 EXIT_LOG(%s, "no clients with gnssNiCb.");
2105 return false;
2106 }
2107
2108 if (notify.type == GNSS_NI_TYPE_EMERGENCY_SUPL) {
2109 if (NULL != mNiData.sessionEs.rawRequest) {
2110 LOC_LOGI("%s]: supl es NI in progress, new supl es NI ignored, type: %d",
2111 __func__, notify.type);
2112 if (NULL != data) {
2113 free((void*)data);
2114 }
2115 } else {
2116 pSession = &mNiData.sessionEs;
2117 }
2118 } else {
2119 if (NULL != mNiData.session.rawRequest ||
2120 NULL != mNiData.sessionEs.rawRequest) {
2121 LOC_LOGI("%s]: supl NI in progress, new supl NI ignored, type: %d",
2122 __func__, notify.type);
2123 if (NULL != data) {
2124 free((void*)data);
2125 }
2126 } else {
2127 pSession = &mNiData.session;
2128 }
2129 }
2130
2131 if (pSession) {
2132 /* Save request */
2133 pSession->rawRequest = (void*)data;
2134 pSession->reqID = ++mNiData.reqIDCounter;
2135 pSession->adapter = this;
2136
2137 int sessionId = pSession->reqID;
2138
2139 /* For robustness, spawn a thread at this point to timeout to clear up the notification
2140 * status, even though the OEM layer in java does not do so.
2141 **/
2142 pSession->respTimeLeft =
2143 5 + (notify.timeout != 0 ? notify.timeout : LOC_NI_NO_RESPONSE_TIME);
2144
2145 int rc = 0;
2146 rc = pthread_create(&pSession->thread, NULL, niThreadProc, pSession);
2147 if (rc) {
2148 LOC_LOGE("%s]: Loc NI thread is not created.", __func__);
2149 }
2150 rc = pthread_detach(pSession->thread);
2151 if (rc) {
2152 LOC_LOGE("%s]: Loc NI thread is not detached.", __func__);
2153 }
2154
2155 if (nullptr != gnssNiCb) {
2156 gnssNiCb(sessionId, notify);
2157 }
2158 }
2159
2160 return true;
2161 }
2162
2163 void
reportGnssMeasurementDataEvent(const GnssMeasurementsNotification & measurementsNotify)2164 GnssAdapter::reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurementsNotify)
2165 {
2166 LOC_LOGD("%s]: ", __func__);
2167
2168 struct MsgReportGnssMeasurementData : public LocMsg {
2169 GnssAdapter& mAdapter;
2170 const GnssMeasurementsNotification mMeasurementsNotify;
2171 inline MsgReportGnssMeasurementData(GnssAdapter& adapter,
2172 const GnssMeasurementsNotification& measurementsNotify) :
2173 LocMsg(),
2174 mAdapter(adapter),
2175 mMeasurementsNotify(measurementsNotify) {}
2176 inline virtual void proc() const {
2177 mAdapter.reportGnssMeasurementData(mMeasurementsNotify);
2178 }
2179 };
2180
2181 sendMsg(new MsgReportGnssMeasurementData(*this, measurementsNotify));
2182 }
2183
2184 void
reportGnssMeasurementData(const GnssMeasurementsNotification & measurementsNotify)2185 GnssAdapter::reportGnssMeasurementData(const GnssMeasurementsNotification& measurementsNotify)
2186 {
2187 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) {
2188 if (nullptr != it->second.gnssMeasurementsCb) {
2189 it->second.gnssMeasurementsCb(measurementsNotify);
2190 }
2191 }
2192 }
2193
2194 void
reportSvMeasurementEvent(GnssSvMeasurementSet & svMeasurementSet)2195 GnssAdapter::reportSvMeasurementEvent(GnssSvMeasurementSet &svMeasurementSet)
2196 {
2197 LOC_LOGD("%s]: ", __func__);
2198
2199 // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary.
2200 mUlpProxy->reportSvMeasurement(svMeasurementSet);
2201 }
2202
2203 void
reportSvPolynomialEvent(GnssSvPolynomial & svPolynomial)2204 GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial)
2205 {
2206 LOC_LOGD("%s]: ", __func__);
2207
2208 // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary.
2209 mUlpProxy->reportSvPolynomial(svPolynomial);
2210 }
2211
2212 int
nmeaPutChecksum(char * nmea,size_t maxSize)2213 GnssAdapter::nmeaPutChecksum(char *nmea, size_t maxSize)
2214 {
2215 uint8_t checksum = 0;
2216 int length = 0;
2217
2218 nmea++; //skip the $
2219 while (*nmea != '\0') {
2220 checksum ^= *nmea++;
2221 length++;
2222 }
2223
2224 // length now contains nmea sentence string length not including $ sign.
2225 int checksumLength = snprintf(nmea,(maxSize-length-1),"*%02X\r\n", checksum);
2226
2227 // total length of nmea sentence is length of nmea sentence inc $ sign plus
2228 // length of checksum (+1 is to cover the $ character in the length).
2229 return (length + checksumLength + 1);
2230 }
2231
2232 void
generateNmea(const GnssSvNotification & svNotify)2233 GnssAdapter::generateNmea(const GnssSvNotification& svNotify)
2234 {
2235 char sentence[NMEA_SENTENCE_MAX_LENGTH] = {0};
2236
2237 // ------$GPGSV------
2238 NmeaSvMeta gpsSvMeta =
2239 {GNSS_SV_TYPE_GPS, "GP", 0, 0};
2240 generateNmeaGSV(svNotify, gpsSvMeta, sentence, sizeof(sentence));
2241
2242 // ------$GLGSV------
2243 NmeaSvMeta gloSvMeta =
2244 {GNSS_SV_TYPE_GLONASS, "GL", 0, GLONASS_SV_ID_OFFSET};
2245 generateNmeaGSV(svNotify, gloSvMeta, sentence, sizeof(sentence));
2246
2247 // ------$GAGSV------
2248 NmeaSvMeta galSvMeta =
2249 {GNSS_SV_TYPE_GALILEO, "GA", 0, 0};
2250 generateNmeaGSV(svNotify, galSvMeta, sentence, sizeof(sentence));
2251 }
2252
2253 void
generateNmea(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended)2254 GnssAdapter::generateNmea(const UlpLocation& ulpLocation,
2255 const GpsLocationExtended& locationExtended)
2256 {
2257
2258 char sentence[NMEA_SENTENCE_MAX_LENGTH] = {0};
2259
2260 time_t utcTime(ulpLocation.gpsLocation.timestamp/1000);
2261 tm * pTm = gmtime(&utcTime);
2262 if (NULL == pTm) {
2263 LOC_LOGE("%s]: gmtime failed", __func__);
2264 return;
2265 }
2266
2267 uint32_t svUsedCount = 0;
2268 uint32_t count = 0;
2269 bool isCombinedFix = (mGnssSvIdUsedInPosition.gps_sv_used_ids_mask ? 1 : 0) +
2270 (mGnssSvIdUsedInPosition.glo_sv_used_ids_mask ? 1 : 0) +
2271 (mGnssSvIdUsedInPosition.gal_sv_used_ids_mask ? 1 : 0) > 1;
2272 NmeaSvMeta gnssSvMeta =
2273 {GNSS_SV_TYPE_GPS, isCombinedFix ? "GN" : "GP",
2274 mGnssSvIdUsedInPosition.gps_sv_used_ids_mask, 0};
2275
2276 // ---$GPGSA/$GNGSA---
2277 NmeaSvMeta gpsSvMeta =
2278 {GNSS_SV_TYPE_GPS, isCombinedFix ? "GN" : "GP",
2279 mGnssSvIdUsedInPosition.gps_sv_used_ids_mask, 0};
2280 count = generateNmeaGSA(locationExtended, gpsSvMeta, sentence, sizeof(sentence));
2281 if (count > 0) {
2282 svUsedCount += count;
2283 gnssSvMeta = gpsSvMeta;
2284 }
2285
2286 // ---$GLGSA/$GNGSA---
2287 NmeaSvMeta gloSvMeta =
2288 {GNSS_SV_TYPE_GLONASS, isCombinedFix ? "GN" : "GL",
2289 mGnssSvIdUsedInPosition.glo_sv_used_ids_mask, GLONASS_SV_ID_OFFSET};
2290 count = generateNmeaGSA(locationExtended, gloSvMeta, sentence, sizeof(sentence));
2291 if (count > 0) {
2292 svUsedCount += count;
2293 gnssSvMeta = gloSvMeta;
2294 }
2295
2296 // ---$GAGSA/$GNGSA---
2297 NmeaSvMeta galSvMeta =
2298 {GNSS_SV_TYPE_GALILEO, isCombinedFix ? "GN" : "GA",
2299 mGnssSvIdUsedInPosition.gal_sv_used_ids_mask, 0};
2300 count = generateNmeaGSA(locationExtended, galSvMeta, sentence, sizeof(sentence));
2301 if (count > 0) {
2302 svUsedCount += count;
2303 gnssSvMeta = galSvMeta;
2304 }
2305
2306 // ---$GPVTG/$GLVTG/$GAVTG/$GNVTG---
2307 generateNmeaVTG(ulpLocation, locationExtended, gnssSvMeta,
2308 sentence, sizeof(sentence));
2309
2310 // ---$GPRMC/$GLRMC/$GARMC/$GNRMC---
2311 generateNmeaRMC(ulpLocation, locationExtended, gnssSvMeta,
2312 *pTm, sentence, sizeof(sentence));
2313
2314 // ---$GPGGA/$GLGGA/$GAGGA/$GNGGA---
2315 generateNmeaGGA(ulpLocation, locationExtended, gnssSvMeta,
2316 *pTm, svUsedCount, sentence, sizeof(sentence));
2317
2318 }
2319
2320 void
generateNmeaBlank()2321 GnssAdapter::generateNmeaBlank()
2322 {
2323 char sentence[NMEA_SENTENCE_MAX_LENGTH] = {0};
2324 int length = 0;
2325
2326 strlcpy(sentence, "$GPGSA,A,1,,,,,,,,,,,,,,,", sizeof(sentence));
2327 length = nmeaPutChecksum(sentence, sizeof(sentence));
2328 reportNmeaEvent(sentence, length);
2329
2330 strlcpy(sentence, "$GNGSA,A,1,,,,,,,,,,,,,,,", sizeof(sentence));
2331 length = nmeaPutChecksum(sentence, sizeof(sentence));
2332 reportNmeaEvent(sentence, length);
2333
2334 strlcpy(sentence, "$GPVTG,,T,,M,,N,,K,N", sizeof(sentence));
2335 length = nmeaPutChecksum(sentence, sizeof(sentence));
2336 reportNmeaEvent(sentence, length);
2337
2338 strlcpy(sentence, "$GPRMC,,V,,,,,,,,,,N", sizeof(sentence));
2339 length = nmeaPutChecksum(sentence, sizeof(sentence));
2340 reportNmeaEvent(sentence, length);
2341
2342 strlcpy(sentence, "$GPGGA,,,,,,0,,,,,,,,", sizeof(sentence));
2343 length = nmeaPutChecksum(sentence, sizeof(sentence));
2344 reportNmeaEvent(sentence, length);
2345 }
2346
2347 void
generateNmeaGSV(const GnssSvNotification & svNotify,NmeaSvMeta & svMeta,char * sentence,size_t size)2348 GnssAdapter::generateNmeaGSV(const GnssSvNotification& svNotify, NmeaSvMeta& svMeta,
2349 char* sentence, size_t size)
2350 {
2351 if (!sentence || size == 0) {
2352 LOC_LOGE("%s]: NMEA Error invalid argument.", __func__);
2353 return;
2354 }
2355
2356 char* pMarker = sentence;
2357 int lengthRemaining = size;
2358 int length = 0;
2359 int sentenceCount = 0;
2360 int sentenceNumber = 1;
2361 int svCount = 0;
2362 int sv = 1;
2363
2364 for (sv=1; sv <= svNotify.count; sv++) {
2365 if (svMeta.svType == svNotify.gnssSvs[sv - 1].type) {
2366 // cache the used in fix mask, as it will be needed to send $GPGSA
2367 // during the position report
2368 if (LOC_GNSS_SV_FLAGS_USED_IN_FIX ==
2369 (svNotify.gnssSvs[sv - 1].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT)) {
2370 svCount++;
2371 }
2372 }
2373 }
2374
2375 if (svCount == 0) {
2376 // no svs in view, so just send a blank $--GSV sentence
2377 snprintf(sentence, lengthRemaining, "$%sGSV,1,1,0,", svMeta.talker);
2378 length = nmeaPutChecksum(sentence, size);
2379 reportNmeaEvent(sentence, length);
2380 return;
2381 }
2382
2383 sv = 1;
2384 sentenceNumber = 1;
2385 sentenceCount = svCount / 4 + (svCount % 4 != 0);
2386
2387 while (sentenceNumber <= sentenceCount) {
2388 pMarker = sentence;
2389 lengthRemaining = size;
2390
2391 length = snprintf(pMarker, lengthRemaining, "$%sGSV,%d,%d,%02d",
2392 svMeta.talker, sentenceCount, sentenceNumber, svCount);
2393
2394 if (length < 0 || length >= lengthRemaining) {
2395 LOC_LOGE("%s:%d]: NMEA Error in string formatting", __func__, __LINE__);
2396 return;
2397 }
2398 pMarker += length;
2399 lengthRemaining -= length;
2400
2401 for (int i=0; (sv <= svNotify.count) && (i < 4); sv++) {
2402 if (svMeta.svType == svNotify.gnssSvs[sv - 1].type) {
2403 length = snprintf(pMarker, lengthRemaining,",%02d,%02d,%03d,",
2404 svNotify.gnssSvs[sv - 1].svId,
2405 (int)(0.5 + svNotify.gnssSvs[sv - 1].elevation), //float to int
2406 (int)(0.5 + svNotify.gnssSvs[sv - 1].azimuth)); //float to int
2407
2408 if (length < 0 || length >= lengthRemaining) {
2409 LOC_LOGE("%s:%d]: NMEA Error in string formatting", __func__, __LINE__);
2410 return;
2411 }
2412 pMarker += length;
2413 lengthRemaining -= length;
2414
2415 if (svNotify.gnssSvs[sv - 1].cN0Dbhz > 0) {
2416 length = snprintf(pMarker, lengthRemaining,"%02d",
2417 (int)(0.5 + svNotify.gnssSvs[sv - 1].cN0Dbhz)); //float to int
2418
2419 if (length < 0 || length >= lengthRemaining) {
2420 LOC_LOGE("%s:%d]: NMEA Error in string formatting", __func__, __LINE__);
2421 return;
2422 }
2423 pMarker += length;
2424 lengthRemaining -= length;
2425 }
2426 i++;
2427 }
2428 }
2429
2430 length = nmeaPutChecksum(sentence, size);
2431 reportNmeaEvent(sentence, length);
2432 sentenceNumber++;
2433 } //while
2434 }
2435
2436 uint8_t
generateNmeaGSA(const GpsLocationExtended & locationExtended,NmeaSvMeta & svMeta,char * sentence,size_t size)2437 GnssAdapter::generateNmeaGSA(const GpsLocationExtended& locationExtended,
2438 NmeaSvMeta& svMeta, char* sentence, size_t size)
2439 {
2440 if (!sentence || size == 0) {
2441 LOC_LOGE("%s]: NMEA Error invalid arguments.", __func__);
2442 return 0;
2443 }
2444
2445 char* pMarker = sentence;
2446 int lengthRemaining = size;
2447 int length = 0;
2448
2449 uint8_t svUsedCount = 0;
2450 uint32_t svUsedList[32] = {0};
2451
2452 char fixType = '\0';
2453
2454 uint32_t svIdOffset = svMeta.svIdOffset;
2455 uint32_t mask = svMeta.mask;
2456
2457 for (uint8_t i = 1; mask > 0 && svUsedCount < 32; i++) {
2458 if (mask & 1) {
2459 svUsedList[svUsedCount++] = i + svIdOffset;
2460 }
2461 mask = mask >> 1;
2462 }
2463
2464 if (svUsedCount == 0 && LOC_GNSS_CONSTELLATION_GPS != svMeta.svType) {
2465 return 0;
2466 }
2467
2468 if (svUsedCount == 0) {
2469 fixType = '1'; // no fix
2470 } else if (svUsedCount <= 3) {
2471 fixType = '2'; // 2D fix
2472 } else {
2473 fixType = '3'; // 3D fix
2474 }
2475
2476 // Start printing the sentence
2477 // Format: $--GSA,a,x,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,xx,p.p,h.h,v.v*cc
2478 // a : Mode : A : Automatic, allowed to automatically switch 2D/3D
2479 // x : Fixtype : 1 (no fix), 2 (2D fix), 3 (3D fix)
2480 // xx : 12 SV ID
2481 // p.p : Position DOP (Dilution of Precision)
2482 // h.h : Horizontal DOP
2483 // v.v : Vertical DOP
2484 // cc : Checksum value
2485 length = snprintf(pMarker, lengthRemaining, "$%sGSA,A,%c,", svMeta.talker, fixType);
2486
2487 if (length < 0 || length >= lengthRemaining) {
2488 LOC_LOGE("%s:%d]: NMEA Error in string formatting", __func__, __LINE__);;
2489 return 0;
2490 }
2491 pMarker += length;
2492 lengthRemaining -= length;
2493
2494 // Add first 12 satellite IDs
2495 for (uint8_t i = 0; i < 12; i++) {
2496 if (i < svUsedCount) {
2497 length = snprintf(pMarker, lengthRemaining, "%02d,", svUsedList[i]);
2498 } else {
2499 length = snprintf(pMarker, lengthRemaining, ",");
2500 }
2501 if (length < 0 || length >= lengthRemaining) {
2502 LOC_LOGE("%s:%d]: NMEA Error in string formatting", __func__, __LINE__);
2503 return 0;
2504 }
2505 pMarker += length;
2506 lengthRemaining -= length;
2507 }
2508
2509 // Add the position/horizontal/vertical DOP values
2510 if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP) {
2511 length = snprintf(pMarker, lengthRemaining, "%.1f,%.1f,%.1f",
2512 locationExtended.pdop,
2513 locationExtended.hdop,
2514 locationExtended.vdop);
2515 } else {
2516 length = snprintf(pMarker, lengthRemaining, ",,");
2517 }
2518
2519 /* Sentence is ready, add checksum and broadcast */
2520 length = nmeaPutChecksum(sentence, size);
2521 reportNmeaEvent(sentence, length);
2522
2523 return svUsedCount;
2524 }
2525
2526 void
generateNmeaVTG(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,NmeaSvMeta & svMeta,char * sentence,size_t size)2527 GnssAdapter::generateNmeaVTG(const UlpLocation& ulpLocation,
2528 const GpsLocationExtended& locationExtended,
2529 NmeaSvMeta& svMeta, char* sentence, size_t size)
2530 {
2531 if (!sentence || size == 0) {
2532 LOC_LOGE("%s]: NMEA Error invalid arguments.", __func__);
2533 return;
2534 }
2535
2536 char* pMarker = sentence;
2537 int lengthRemaining = size;
2538 int length = 0;
2539
2540 if (ulpLocation.gpsLocation.flags & LOC_GPS_LOCATION_HAS_BEARING)
2541 {
2542 float magTrack = ulpLocation.gpsLocation.bearing;
2543 if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_MAG_DEV)
2544 {
2545 float magTrack = ulpLocation.gpsLocation.bearing - locationExtended.magneticDeviation;
2546 if (magTrack < 0.0)
2547 magTrack += 360.0;
2548 else if (magTrack > 360.0)
2549 magTrack -= 360.0;
2550 }
2551
2552 length = snprintf(pMarker, lengthRemaining, "$%sVTG,%.1lf,T,%.1lf,M,",
2553 svMeta.talker, ulpLocation.gpsLocation.bearing, magTrack);
2554 }
2555 else
2556 {
2557 length = snprintf(pMarker, lengthRemaining, "$%sVTG,,T,,M,", svMeta.talker);
2558 }
2559
2560 if (length < 0 || length >= lengthRemaining)
2561 {
2562 LOC_LOGE("%s:%d]: NMEA Error in string formatting", __func__, __LINE__);
2563 return;
2564 }
2565 pMarker += length;
2566 lengthRemaining -= length;
2567
2568 if (ulpLocation.gpsLocation.flags & LOC_GPS_LOCATION_HAS_SPEED)
2569 {
2570 float speedKnots = ulpLocation.gpsLocation.speed * (3600.0/1852.0);
2571 float speedKmPerHour = ulpLocation.gpsLocation.speed * 3.6;
2572
2573 length = snprintf(pMarker, lengthRemaining, "%.1lf,N,%.1lf,K,", speedKnots, speedKmPerHour);
2574 }
2575 else
2576 {
2577 length = snprintf(pMarker, lengthRemaining, ",N,,K,");
2578 }
2579
2580 if (length < 0 || length >= lengthRemaining)
2581 {
2582 LOC_LOGE("%s:%d]: NMEA Error in string formatting", __func__, __LINE__);
2583 return;
2584 }
2585 pMarker += length;
2586 lengthRemaining -= length;
2587
2588 if (!(ulpLocation.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG))
2589 length = snprintf(pMarker, lengthRemaining, "%c", 'N'); // N means no fix
2590 else if (GNSS_SUPL_MODE_STANDALONE == mSuplMode)
2591 length = snprintf(pMarker, lengthRemaining, "%c", 'A'); // A means autonomous
2592 else
2593 length = snprintf(pMarker, lengthRemaining, "%c", 'D'); // D means differential
2594
2595 length = nmeaPutChecksum(sentence, size);
2596 reportNmeaEvent(sentence, length);
2597 }
2598
2599 void
generateNmeaRMC(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,NmeaSvMeta & svMeta,tm & utcTime,char * sentence,size_t size)2600 GnssAdapter::generateNmeaRMC(const UlpLocation& ulpLocation,
2601 const GpsLocationExtended& locationExtended,
2602 NmeaSvMeta& svMeta, tm& utcTime,
2603 char* sentence, size_t size)
2604 {
2605 if (!sentence || size == 0) {
2606 LOC_LOGE("NMEA Error invalid arguments.");
2607 return;
2608 }
2609
2610 int utcYear = utcTime.tm_year % 100; // 2 digit year
2611 int utcMonth = utcTime.tm_mon + 1; // tm_mon starts at zero
2612 int utcDay = utcTime.tm_mday;
2613 int utcHours = utcTime.tm_hour;
2614 int utcMinutes = utcTime.tm_min;
2615 int utcSeconds = utcTime.tm_sec;
2616 int utcMSeconds = (ulpLocation.gpsLocation.timestamp)%1000;
2617
2618 char* pMarker = sentence;
2619 int lengthRemaining = size;
2620 int length = 0;
2621
2622 length = snprintf(pMarker, lengthRemaining, "$%sRMC,%02d%02d%02d.%02d,A," ,
2623 svMeta.talker, utcHours, utcMinutes, utcSeconds,utcMSeconds/10);
2624
2625 if (length < 0 || length >= lengthRemaining) {
2626 LOC_LOGE("%s:%d]: NMEA Error in string formatting", __func__, __LINE__);
2627 return;
2628 }
2629 pMarker += length;
2630 lengthRemaining -= length;
2631
2632 if (ulpLocation.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG) {
2633 double latitude = ulpLocation.gpsLocation.latitude;
2634 double longitude = ulpLocation.gpsLocation.longitude;
2635 char latHemisphere;
2636 char lonHemisphere;
2637 double latMinutes;
2638 double lonMinutes;
2639
2640 if (latitude > 0) {
2641 latHemisphere = 'N';
2642 } else {
2643 latHemisphere = 'S';
2644 latitude *= -1.0;
2645 }
2646
2647 if (longitude < 0) {
2648 lonHemisphere = 'W';
2649 longitude *= -1.0;
2650 } else {
2651 lonHemisphere = 'E';
2652 }
2653
2654 latMinutes = fmod(latitude * 60.0 , 60.0);
2655 lonMinutes = fmod(longitude * 60.0 , 60.0);
2656
2657 length = snprintf(pMarker, lengthRemaining, "%02d%09.6lf,%c,%03d%09.6lf,%c,",
2658 (uint8_t)floor(latitude), latMinutes, latHemisphere,
2659 (uint8_t)floor(longitude),lonMinutes, lonHemisphere);
2660 } else {
2661 length = snprintf(pMarker, lengthRemaining,",,,,");
2662 }
2663
2664 if (length < 0 || length >= lengthRemaining) {
2665 LOC_LOGE("%s:%d]: NMEA Error in string formatting", __func__, __LINE__);
2666 return;
2667 }
2668 pMarker += length;
2669 lengthRemaining -= length;
2670
2671 if (ulpLocation.gpsLocation.flags & LOC_GPS_LOCATION_HAS_SPEED) {
2672 float speedKnots = ulpLocation.gpsLocation.speed * (3600.0/1852.0);
2673 length = snprintf(pMarker, lengthRemaining, "%.1lf,", speedKnots);
2674 } else {
2675 length = snprintf(pMarker, lengthRemaining, ",");
2676 }
2677
2678 if (length < 0 || length >= lengthRemaining) {
2679 LOC_LOGE("%s:%d]: NMEA Error in string formatting", __func__, __LINE__);
2680 return;
2681 }
2682 pMarker += length;
2683 lengthRemaining -= length;
2684
2685 if (ulpLocation.gpsLocation.flags & LOC_GPS_LOCATION_HAS_BEARING) {
2686 length = snprintf(pMarker, lengthRemaining, "%.1lf,", ulpLocation.gpsLocation.bearing);
2687 } else {
2688 length = snprintf(pMarker, lengthRemaining, ",");
2689 }
2690
2691 if (length < 0 || length >= lengthRemaining) {
2692 LOC_LOGE("%s:%d]: NMEA Error in string formatting", __func__, __LINE__);
2693 return;
2694 }
2695 pMarker += length;
2696 lengthRemaining -= length;
2697
2698 length = snprintf(pMarker, lengthRemaining, "%2.2d%2.2d%2.2d,",
2699 utcDay, utcMonth, utcYear);
2700
2701 if (length < 0 || length >= lengthRemaining) {
2702 LOC_LOGE("%s:%d]: NMEA Error in string formatting", __func__, __LINE__);
2703 return;
2704 }
2705 pMarker += length;
2706 lengthRemaining -= length;
2707
2708 if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_MAG_DEV) {
2709 float magneticVariation = locationExtended.magneticDeviation;
2710 char direction;
2711 if (magneticVariation < 0.0) {
2712 direction = 'W';
2713 magneticVariation *= -1.0;
2714 } else {
2715 direction = 'E';
2716 }
2717
2718 length = snprintf(pMarker, lengthRemaining, "%.1lf,%c,",
2719 magneticVariation, direction);
2720 } else {
2721 length = snprintf(pMarker, lengthRemaining, ",,");
2722 }
2723
2724 if (length < 0 || length >= lengthRemaining) {
2725 LOC_LOGE("%s:%d]: NMEA Error in string formatting", __func__, __LINE__);
2726 return;
2727 }
2728 pMarker += length;
2729 lengthRemaining -= length;
2730
2731 if (!(ulpLocation.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG)) {
2732 length = snprintf(pMarker, lengthRemaining, "%c", 'N'); // N means no fix
2733 } else if (GNSS_SUPL_MODE_STANDALONE == mSuplMode) {
2734 length = snprintf(pMarker, lengthRemaining, "%c", 'A'); // A means autonomous
2735 } else {
2736 length = snprintf(pMarker, lengthRemaining, "%c", 'D'); // D means differential
2737 }
2738
2739 length = nmeaPutChecksum(sentence, size);
2740 reportNmeaEvent(sentence, length);
2741 }
2742
2743 void
generateNmeaGGA(const UlpLocation & ulpLocation,const GpsLocationExtended & locationExtended,NmeaSvMeta & svMeta,tm & utcTime,uint32_t svUsedCount,char * sentence,size_t size)2744 GnssAdapter::generateNmeaGGA(const UlpLocation& ulpLocation,
2745 const GpsLocationExtended& locationExtended,
2746 NmeaSvMeta& svMeta, tm& utcTime, uint32_t svUsedCount,
2747 char* sentence, size_t size)
2748 {
2749 if (!sentence || size == 0) {
2750 LOC_LOGE("NMEA Error invalid arguments.");
2751 return;
2752 }
2753
2754 int utcYear = utcTime.tm_year % 100; // 2 digit year
2755 int utcMonth = utcTime.tm_mon + 1; // tm_mon starts at zero
2756 int utcDay = utcTime.tm_mday;
2757 int utcHours = utcTime.tm_hour;
2758 int utcMinutes = utcTime.tm_min;
2759 int utcSeconds = utcTime.tm_sec;
2760 int utcMSeconds = (ulpLocation.gpsLocation.timestamp)%1000;
2761
2762 char* pMarker = sentence;
2763 int lengthRemaining = size;
2764 int length = 0;
2765
2766 length = snprintf(pMarker, lengthRemaining, "$%sGGA,%02d%02d%02d.%02d," ,
2767 svMeta.talker, utcHours, utcMinutes, utcSeconds, utcMSeconds/10);
2768
2769 if (length < 0 || length >= lengthRemaining) {
2770 LOC_LOGE("%s:%d]: NMEA Error in string formatting", __func__, __LINE__);
2771 return;
2772 }
2773 pMarker += length;
2774 lengthRemaining -= length;
2775
2776 if (ulpLocation.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG) {
2777 double latitude = ulpLocation.gpsLocation.latitude;
2778 double longitude = ulpLocation.gpsLocation.longitude;
2779 char latHemisphere;
2780 char lonHemisphere;
2781 double latMinutes;
2782 double lonMinutes;
2783
2784 if (latitude > 0) {
2785 latHemisphere = 'N';
2786 } else {
2787 latHemisphere = 'S';
2788 latitude *= -1.0;
2789 }
2790
2791 if (longitude < 0) {
2792 lonHemisphere = 'W';
2793 longitude *= -1.0;
2794 } else {
2795 lonHemisphere = 'E';
2796 }
2797
2798 latMinutes = fmod(latitude * 60.0 , 60.0);
2799 lonMinutes = fmod(longitude * 60.0 , 60.0);
2800
2801 length = snprintf(pMarker, lengthRemaining, "%02d%09.6lf,%c,%03d%09.6lf,%c,",
2802 (uint8_t)floor(latitude), latMinutes, latHemisphere,
2803 (uint8_t)floor(longitude),lonMinutes, lonHemisphere);
2804 } else {
2805 length = snprintf(pMarker, lengthRemaining,",,,,");
2806 }
2807
2808 if (length < 0 || length >= lengthRemaining) {
2809 LOC_LOGE("%s:%d]: NMEA Error in string formatting", __func__, __LINE__);
2810 return;
2811 }
2812 pMarker += length;
2813 lengthRemaining -= length;
2814
2815 char gpsQuality;
2816 if (!(ulpLocation.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG)) {
2817 gpsQuality = '0'; // 0 means no fix
2818 } else if (GNSS_SUPL_MODE_STANDALONE == mSuplMode) {
2819 gpsQuality = '1'; // 1 means GPS fix
2820 } else {
2821 gpsQuality = '2'; // 2 means DGPS fix
2822 }
2823
2824 // Number of satellites in use, 00-12
2825 if (svUsedCount > MAX_SATELLITES_IN_USE) {
2826 svUsedCount = MAX_SATELLITES_IN_USE;
2827 }
2828
2829 // Add the position/horizontal/vertical DOP values
2830 if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP) {
2831 length = snprintf(pMarker, lengthRemaining, "%c,%02d,%.1f,",
2832 gpsQuality, svUsedCount, locationExtended.hdop);
2833 } else {
2834 length = snprintf(pMarker, lengthRemaining, "%c,%02d,,",
2835 gpsQuality, svUsedCount);
2836 }
2837
2838 if (length < 0 || length >= lengthRemaining) {
2839 LOC_LOGE("%s:%d]: NMEA Error in string formatting", __func__, __LINE__);
2840 return;
2841 }
2842 pMarker += length;
2843 lengthRemaining -= length;
2844
2845 if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL) {
2846 length = snprintf(pMarker, lengthRemaining, "%.1lf,M,",
2847 locationExtended.altitudeMeanSeaLevel);
2848 } else {
2849 length = snprintf(pMarker, lengthRemaining,",,");
2850 }
2851
2852 if (length < 0 || length >= lengthRemaining) {
2853 LOC_LOGE("%s:%d]: NMEA Error in string formatting", __func__, __LINE__);
2854 return;
2855 }
2856 pMarker += length;
2857 lengthRemaining -= length;
2858
2859 if ((ulpLocation.gpsLocation.flags & LOC_GPS_LOCATION_HAS_ALTITUDE) &&
2860 (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL)) {
2861 length = snprintf(pMarker, lengthRemaining, "%.1lf,M,,",
2862 ulpLocation.gpsLocation.altitude - locationExtended.altitudeMeanSeaLevel);
2863 } else {
2864 length = snprintf(pMarker, lengthRemaining,",,,");
2865 }
2866
2867 length = nmeaPutChecksum(sentence, size);
2868 reportNmeaEvent(sentence, length);
2869 }
2870
2871 /* INIT LOC AGPS MANAGER */
initAgpsCommand(void * statusV4Cb)2872 void GnssAdapter::initAgpsCommand(void* statusV4Cb){
2873
2874 LOC_LOGI("GnssAdapter::initAgpsCommand");
2875
2876 /* Set ATL open/close callbacks */
2877 AgpsAtlOpenStatusCb atlOpenStatusCb =
2878 [this](int handle, int isSuccess, char* apn,
2879 AGpsBearerType bearerType, AGpsExtType agpsType) {
2880
2881 mLocApi->atlOpenStatus(
2882 handle, isSuccess, apn, bearerType, agpsType);
2883 };
2884 AgpsAtlCloseStatusCb atlCloseStatusCb =
2885 [this](int handle, int isSuccess) {
2886
2887 mLocApi->atlCloseStatus(handle, isSuccess);
2888 };
2889
2890 /* Register DS Client APIs */
2891 AgpsDSClientInitFn dsClientInitFn =
2892 [this](bool isDueToSSR) {
2893
2894 return mLocApi->initDataServiceClient(isDueToSSR);
2895 };
2896
2897 AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn =
2898 [this] {
2899
2900 return mLocApi->openAndStartDataCall();
2901 };
2902
2903 AgpsDSClientStopDataCallFn dsClientStopDataCallFn =
2904 [this] {
2905
2906 mLocApi->stopDataCall();
2907 };
2908
2909 AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn =
2910 [this] {
2911
2912 mLocApi->closeDataCall();
2913 };
2914
2915 AgpsDSClientReleaseFn dsClientReleaseFn =
2916 [this] {
2917
2918 mLocApi->releaseDataServiceClient();
2919 };
2920
2921 /* Send Msg function */
2922 SendMsgToAdapterMsgQueueFn sendMsgFn =
2923 [this](LocMsg* msg) {
2924
2925 sendMsg(msg);
2926 };
2927
2928 /* Message to initialize AGPS module */
2929 struct AgpsMsgInit: public LocMsg {
2930
2931 AgpsManager* mAgpsManager;
2932
2933 AgpsFrameworkInterface::AgnssStatusIpV4Cb mFrameworkStatusV4Cb;
2934
2935 AgpsAtlOpenStatusCb mAtlOpenStatusCb;
2936 AgpsAtlCloseStatusCb mAtlCloseStatusCb;
2937
2938 AgpsDSClientInitFn mDSClientInitFn;
2939 AgpsDSClientOpenAndStartDataCallFn mDSClientOpenAndStartDataCallFn;
2940 AgpsDSClientStopDataCallFn mDSClientStopDataCallFn;
2941 AgpsDSClientCloseDataCallFn mDSClientCloseDataCallFn;
2942 AgpsDSClientReleaseFn mDSClientReleaseFn;
2943
2944 SendMsgToAdapterMsgQueueFn mSendMsgFn;
2945
2946 inline AgpsMsgInit(AgpsManager* agpsManager,
2947 AgpsFrameworkInterface::AgnssStatusIpV4Cb frameworkStatusV4Cb,
2948 AgpsAtlOpenStatusCb atlOpenStatusCb,
2949 AgpsAtlCloseStatusCb atlCloseStatusCb,
2950 AgpsDSClientInitFn dsClientInitFn,
2951 AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn,
2952 AgpsDSClientStopDataCallFn dsClientStopDataCallFn,
2953 AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn,
2954 AgpsDSClientReleaseFn dsClientReleaseFn,
2955 SendMsgToAdapterMsgQueueFn sendMsgFn) :
2956 LocMsg(), mAgpsManager(agpsManager), mFrameworkStatusV4Cb(
2957 frameworkStatusV4Cb), mAtlOpenStatusCb(atlOpenStatusCb), mAtlCloseStatusCb(
2958 atlCloseStatusCb), mDSClientInitFn(dsClientInitFn), mDSClientOpenAndStartDataCallFn(
2959 dsClientOpenAndStartDataCallFn), mDSClientStopDataCallFn(
2960 dsClientStopDataCallFn), mDSClientCloseDataCallFn(
2961 dsClientCloseDataCallFn), mDSClientReleaseFn(
2962 dsClientReleaseFn), mSendMsgFn(sendMsgFn) {
2963
2964 LOC_LOGV("AgpsMsgInit");
2965 }
2966
2967 inline virtual void proc() const {
2968
2969 LOC_LOGV("AgpsMsgInit::proc()");
2970
2971 mAgpsManager->registerCallbacks(mFrameworkStatusV4Cb, mAtlOpenStatusCb,
2972 mAtlCloseStatusCb, mDSClientInitFn,
2973 mDSClientOpenAndStartDataCallFn, mDSClientStopDataCallFn,
2974 mDSClientCloseDataCallFn, mDSClientReleaseFn, mSendMsgFn);
2975
2976 mAgpsManager->createAgpsStateMachines();
2977 }
2978 };
2979
2980 /* Send message to initialize AGPS Manager */
2981 sendMsg(new AgpsMsgInit(
2982 &mAgpsManager,
2983 (AgpsFrameworkInterface::AgnssStatusIpV4Cb)statusV4Cb,
2984 atlOpenStatusCb, atlCloseStatusCb,
2985 dsClientInitFn, dsClientOpenAndStartDataCallFn,
2986 dsClientStopDataCallFn, dsClientCloseDataCallFn,
2987 dsClientReleaseFn,
2988 sendMsgFn));
2989 }
2990
2991 /* GnssAdapter::requestATL
2992 * Method triggered in QMI thread as part of handling below message:
2993 * eQMI_LOC_SERVER_REQUEST_OPEN_V02
2994 * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
2995 * eQMI_LOC_WWAN_TYPE_INTERNET_V02
2996 * eQMI_LOC_WWAN_TYPE_AGNSS_V02 */
requestATL(int connHandle,LocAGpsType agpsType)2997 bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType){
2998
2999 LOC_LOGI("GnssAdapter::requestATL");
3000
3001 sendMsg( new AgpsMsgRequestATL(
3002 &mAgpsManager, connHandle, (AGpsExtType)agpsType));
3003
3004 return true;
3005 }
3006
3007 /* GnssAdapter::requestSuplES
3008 * Method triggered in QMI thread as part of handling below message:
3009 * eQMI_LOC_SERVER_REQUEST_OPEN_V02
3010 * Triggers the AGPS state machine to setup AGPS call for below WWAN types:
3011 * eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02 */
requestSuplES(int connHandle)3012 bool GnssAdapter::requestSuplES(int connHandle){
3013
3014 LOC_LOGI("GnssAdapter::requestSuplES");
3015
3016 sendMsg( new AgpsMsgRequestATL(
3017 &mAgpsManager, connHandle, LOC_AGPS_TYPE_SUPL_ES));
3018
3019 return true;
3020 }
3021
3022 /* GnssAdapter::releaseATL
3023 * Method triggered in QMI thread as part of handling below message:
3024 * eQMI_LOC_SERVER_REQUEST_CLOSE_V02
3025 * Triggers teardown of an existing AGPS call */
releaseATL(int connHandle)3026 bool GnssAdapter::releaseATL(int connHandle){
3027
3028 LOC_LOGI("GnssAdapter::releaseATL");
3029
3030 /* Release SUPL/INTERNET/SUPL_ES ATL */
3031 struct AgpsMsgReleaseATL: public LocMsg {
3032
3033 AgpsManager* mAgpsManager;
3034 int mConnHandle;
3035
3036 inline AgpsMsgReleaseATL(AgpsManager* agpsManager, int connHandle) :
3037 LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle) {
3038
3039 LOC_LOGV("AgpsMsgReleaseATL");
3040 }
3041
3042 inline virtual void proc() const {
3043
3044 LOC_LOGV("AgpsMsgReleaseATL::proc()");
3045 mAgpsManager->releaseATL(mConnHandle);
3046 }
3047 };
3048
3049 sendMsg( new AgpsMsgReleaseATL(&mAgpsManager, connHandle));
3050
3051 return true;
3052 }
3053
3054 /* GnssAdapter::reportDataCallOpened
3055 * DS Client data call opened successfully.
3056 * Send message to AGPS Manager to handle. */
reportDataCallOpened()3057 bool GnssAdapter::reportDataCallOpened(){
3058
3059 LOC_LOGI("GnssAdapter::reportDataCallOpened");
3060
3061 struct AgpsMsgSuplEsOpened: public LocMsg {
3062
3063 AgpsManager* mAgpsManager;
3064
3065 inline AgpsMsgSuplEsOpened(AgpsManager* agpsManager) :
3066 LocMsg(), mAgpsManager(agpsManager) {
3067
3068 LOC_LOGV("AgpsMsgSuplEsOpened");
3069 }
3070
3071 inline virtual void proc() const {
3072
3073 LOC_LOGV("AgpsMsgSuplEsOpened::proc()");
3074 mAgpsManager->reportDataCallOpened();
3075 }
3076 };
3077
3078 sendMsg( new AgpsMsgSuplEsOpened(&mAgpsManager));
3079
3080 return true;
3081 }
3082
3083 /* GnssAdapter::reportDataCallClosed
3084 * DS Client data call closed.
3085 * Send message to AGPS Manager to handle. */
reportDataCallClosed()3086 bool GnssAdapter::reportDataCallClosed(){
3087
3088 LOC_LOGI("GnssAdapter::reportDataCallClosed");
3089
3090 struct AgpsMsgSuplEsClosed: public LocMsg {
3091
3092 AgpsManager* mAgpsManager;
3093
3094 inline AgpsMsgSuplEsClosed(AgpsManager* agpsManager) :
3095 LocMsg(), mAgpsManager(agpsManager) {
3096
3097 LOC_LOGV("AgpsMsgSuplEsClosed");
3098 }
3099
3100 inline virtual void proc() const {
3101
3102 LOC_LOGV("AgpsMsgSuplEsClosed::proc()");
3103 mAgpsManager->reportDataCallClosed();
3104 }
3105 };
3106
3107 sendMsg( new AgpsMsgSuplEsClosed(&mAgpsManager));
3108
3109 return true;
3110 }
3111
dataConnOpenCommand(AGpsExtType agpsType,const char * apnName,int apnLen,LocApnIpType ipType)3112 void GnssAdapter::dataConnOpenCommand(
3113 AGpsExtType agpsType,
3114 const char* apnName, int apnLen, LocApnIpType ipType){
3115
3116 LOC_LOGI("GnssAdapter::frameworkDataConnOpen");
3117
3118 struct AgpsMsgAtlOpenSuccess: public LocMsg {
3119
3120 AgpsManager* mAgpsManager;
3121 AGpsExtType mAgpsType;
3122 char* mApnName;
3123 int mApnLen;
3124 LocApnIpType mIpType;
3125
3126 inline AgpsMsgAtlOpenSuccess(AgpsManager* agpsManager, AGpsExtType agpsType,
3127 const char* apnName, int apnLen, LocApnIpType ipType) :
3128 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType), mApnName(
3129 new char[apnLen + 1]), mApnLen(apnLen), mIpType(ipType) {
3130
3131 LOC_LOGV("AgpsMsgAtlOpenSuccess");
3132 memcpy(mApnName, apnName, apnLen);
3133 mApnName[apnLen] = 0;
3134 }
3135
3136 inline ~AgpsMsgAtlOpenSuccess() {
3137 delete[] mApnName;
3138 }
3139
3140 inline virtual void proc() const {
3141
3142 LOC_LOGV("AgpsMsgAtlOpenSuccess::proc()");
3143 mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen,
3144 mIpType);
3145 }
3146 };
3147
3148 sendMsg( new AgpsMsgAtlOpenSuccess(
3149 &mAgpsManager, (AGpsExtType)agpsType, apnName, apnLen, ipType));
3150 }
3151
dataConnClosedCommand(AGpsExtType agpsType)3152 void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){
3153
3154 LOC_LOGI("GnssAdapter::frameworkDataConnClosed");
3155
3156 struct AgpsMsgAtlClosed: public LocMsg {
3157
3158 AgpsManager* mAgpsManager;
3159 AGpsExtType mAgpsType;
3160
3161 inline AgpsMsgAtlClosed(AgpsManager* agpsManager, AGpsExtType agpsType) :
3162 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
3163
3164 LOC_LOGV("AgpsMsgAtlClosed");
3165 }
3166
3167 inline virtual void proc() const {
3168
3169 LOC_LOGV("AgpsMsgAtlClosed::proc()");
3170 mAgpsManager->reportAtlClosed(mAgpsType);
3171 }
3172 };
3173
3174 sendMsg( new AgpsMsgAtlClosed(&mAgpsManager, (AGpsExtType)agpsType));
3175 }
3176
dataConnFailedCommand(AGpsExtType agpsType)3177 void GnssAdapter::dataConnFailedCommand(AGpsExtType agpsType){
3178
3179 LOC_LOGI("GnssAdapter::frameworkDataConnFailed");
3180
3181 struct AgpsMsgAtlOpenFailed: public LocMsg {
3182
3183 AgpsManager* mAgpsManager;
3184 AGpsExtType mAgpsType;
3185
3186 inline AgpsMsgAtlOpenFailed(AgpsManager* agpsManager, AGpsExtType agpsType) :
3187 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) {
3188
3189 LOC_LOGV("AgpsMsgAtlOpenFailed");
3190 }
3191
3192 inline virtual void proc() const {
3193
3194 LOC_LOGV("AgpsMsgAtlOpenFailed::proc()");
3195 mAgpsManager->reportAtlOpenFailed(mAgpsType);
3196 }
3197 };
3198
3199 sendMsg( new AgpsMsgAtlOpenFailed(&mAgpsManager, (AGpsExtType)agpsType));
3200 }
3201