1 /* Copyright (c) 2011-2016, 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 Foundatoin, 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_NDEBUG 0 30 #define LOG_TAG "LocSvc_ApiV02" 31 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <math.h> 36 #include <dlfcn.h> 37 38 #include <hardware/gps.h> 39 40 #ifndef USE_GLIB 41 #include <utils/SystemClock.h> 42 #endif /* USE_GLIB */ 43 #include <LocApiV02.h> 44 #include <loc_api_v02_log.h> 45 #include <loc_api_sync_req.h> 46 #include <loc_api_v02_client.h> 47 #include <loc_util_log.h> 48 #include <gps_extended.h> 49 #include "platform_lib_includes.h" 50 51 using namespace loc_core; 52 53 /* Doppler Conversion from M/S to NS/S */ 54 #define MPS_TO_NSPS (1.0/0.299792458) 55 56 /* Default session id ; TBD needs incrementing for each */ 57 #define LOC_API_V02_DEF_SESSION_ID (1) 58 59 /* UMTS CP Address key*/ 60 #define LOC_NI_NOTIF_KEY_ADDRESS "Address" 61 62 /* GPS SV Id offset */ 63 #define GPS_SV_ID_OFFSET (1) 64 65 /* GLONASS SV Id offset */ 66 #define GLONASS_SV_ID_OFFSET (65) 67 68 /* SV ID range */ 69 #define SV_ID_RANGE (32) 70 71 #define BDS_SV_ID_OFFSET (201) 72 73 /* BeiDou SV ID RANGE*/ 74 #define BDS_SV_ID_RANGE QMI_LOC_DELETE_MAX_BDS_SV_INFO_LENGTH_V02 75 76 /* GPS week unknown*/ 77 #define C_GPS_WEEK_UNKNOWN (65535) 78 79 /* seconds per week*/ 80 #define WEEK_MSECS (60*60*24*7*1000) 81 82 /* number of QMI_LOC messages that need to be checked*/ 83 #define NUMBER_OF_MSG_TO_BE_CHECKED (3) 84 85 /* static event callbacks that call the LocApiV02 callbacks*/ 86 87 /* global event callback, call the eventCb function in loc api adapter v02 88 instance */ 89 static void globalEventCb(locClientHandleType clientHandle, 90 uint32_t eventId, 91 const locClientEventIndUnionType eventPayload, 92 void* pClientCookie) 93 { 94 MODEM_LOG_CALLFLOW(%s, loc_get_v02_event_name(eventId)); 95 LocApiV02 *locApiV02Instance = 96 (LocApiV02 *)pClientCookie; 97 98 LOC_LOGV ("%s:%d] client = %p, event id = %d, client cookie ptr = %p\n", 99 __func__, __LINE__, clientHandle, eventId, pClientCookie); 100 101 // return if null is passed 102 if( NULL == locApiV02Instance) 103 { 104 LOC_LOGE ("%s:%d] NULL object passed : client = %p, event id = %d\n", 105 __func__, __LINE__, clientHandle, eventId); 106 return; 107 } 108 locApiV02Instance->eventCb(clientHandle, eventId, eventPayload); 109 } 110 111 /* global response callback, it calls the sync request process 112 indication function to unblock the request that is waiting on this 113 response indication*/ 114 static void globalRespCb(locClientHandleType clientHandle, 115 uint32_t respId, 116 const locClientRespIndUnionType respPayload, 117 uint32_t respPayloadSize, 118 void* pClientCookie) 119 { 120 MODEM_LOG_CALLFLOW(%s, loc_get_v02_event_name(respId)); 121 LocApiV02 *locApiV02Instance = 122 (LocApiV02 *)pClientCookie; 123 124 LOC_LOGV ("%s:%d] client = %p, resp id = %d, client cookie ptr = %p\n", 125 __func__, __LINE__, clientHandle, respId, pClientCookie); 126 127 if( NULL == locApiV02Instance) 128 { 129 LOC_LOGE ("%s:%d] NULL object passed : client = %p, resp id = %d\n", 130 __func__, __LINE__, clientHandle, respId); 131 return; 132 } 133 134 // process the sync call 135 // use pDeleteAssistDataInd as a dummy pointer 136 loc_sync_process_ind(clientHandle, respId, 137 (void *)respPayload.pDeleteAssistDataInd, respPayloadSize); 138 } 139 140 /* global error callback, it will call the handle service down 141 function in the loc api adapter instance. */ 142 static void globalErrorCb (locClientHandleType clientHandle, 143 locClientErrorEnumType errorId, 144 void *pClientCookie) 145 { 146 LocApiV02 *locApiV02Instance = 147 (LocApiV02 *)pClientCookie; 148 149 LOC_LOGV ("%s:%d] client = %p, error id = %d\n, client cookie ptr = %p\n", 150 __func__, __LINE__, clientHandle, errorId, pClientCookie); 151 if( NULL == locApiV02Instance) 152 { 153 LOC_LOGE ("%s:%d] NULL object passed : client = %p, error id = %d\n", 154 __func__, __LINE__, clientHandle, errorId); 155 return; 156 } 157 locApiV02Instance->errorCb(clientHandle, errorId); 158 } 159 160 /* global structure containing the callbacks */ 161 locClientCallbacksType globalCallbacks = 162 { 163 sizeof(locClientCallbacksType), 164 globalEventCb, 165 globalRespCb, 166 globalErrorCb 167 }; 168 169 /* Constructor for LocApiV02 */ 170 LocApiV02 :: LocApiV02(const MsgTask* msgTask, 171 LOC_API_ADAPTER_EVENT_MASK_T exMask, 172 ContextBase* context): 173 LocApiBase(msgTask, exMask, context), 174 clientHandle(LOC_CLIENT_INVALID_HANDLE_VALUE), 175 dsClientIface(NULL), 176 dsClientHandle(NULL), 177 mGnssMeasurementSupported(sup_unknown), 178 mQmiMask(0), mInSession(false), 179 mEngineOn(false), mMeasurementsStarted(false) 180 { 181 // initialize loc_sync_req interface 182 loc_sync_req_init(); 183 } 184 185 /* Destructor for LocApiV02 */ 186 LocApiV02 :: ~LocApiV02() 187 { 188 close(); 189 } 190 191 LocApiBase* getLocApi(const MsgTask *msgTask, 192 LOC_API_ADAPTER_EVENT_MASK_T exMask, 193 ContextBase* context) 194 { 195 LOC_LOGD("%s:%d]: Creating new LocApiV02", __func__, __LINE__); 196 return new LocApiV02(msgTask, exMask, context); 197 } 198 199 /* Initialize a loc api v02 client AND 200 check which loc message are supported by modem */ 201 enum loc_api_adapter_err 202 LocApiV02 :: open(LOC_API_ADAPTER_EVENT_MASK_T mask) 203 { 204 enum loc_api_adapter_err rtv = LOC_API_ADAPTER_ERR_SUCCESS; 205 LOC_API_ADAPTER_EVENT_MASK_T newMask = mMask | (mask & ~mExcludedMask); 206 locClientEventMaskType qmiMask = convertMask(newMask); 207 LOC_LOGD("%s:%d]: Enter mMask: %x; mask: %x; newMask: %x mQmiMask: %lld qmiMask: %lld", 208 __func__, __LINE__, mMask, mask, newMask, mQmiMask, qmiMask); 209 /* If the client is already open close it first */ 210 if(LOC_CLIENT_INVALID_HANDLE_VALUE == clientHandle) 211 { 212 locClientStatusEnumType status = eLOC_CLIENT_SUCCESS; 213 214 LOC_LOGV ("%s:%d]: reference to this = %p passed in \n", 215 __func__, __LINE__, this); 216 /* initialize the loc api v02 interface, note that 217 the locClientOpen() function will block if the 218 service is unavailable for a fixed time out */ 219 220 // it is important to cap the mask here, because not all LocApi's 221 // can enable the same bits, e.g. foreground and bckground. 222 status = locClientOpen(adjustMaskForNoSession(qmiMask), &globalCallbacks, 223 &clientHandle, (void *)this); 224 mMask = newMask; 225 mQmiMask = qmiMask; 226 if (eLOC_CLIENT_SUCCESS != status || 227 clientHandle == LOC_CLIENT_INVALID_HANDLE_VALUE ) 228 { 229 mMask = 0; 230 mQmiMask = 0; 231 LOC_LOGE ("%s:%d]: locClientOpen failed, status = %s\n", __func__, 232 __LINE__, loc_get_v02_client_status_name(status)); 233 rtv = LOC_API_ADAPTER_ERR_FAILURE; 234 } else { 235 uint64_t supportedMsgList = 0; 236 const uint32_t msgArray[NUMBER_OF_MSG_TO_BE_CHECKED] = 237 { 238 // For - LOC_API_ADAPTER_MESSAGE_LOCATION_BATCHING 239 QMI_LOC_GET_BATCH_SIZE_REQ_V02, 240 241 // For - LOC_API_ADAPTER_MESSAGE_BATCHED_GENFENCE_BREACH 242 QMI_LOC_EVENT_GEOFENCE_BATCHED_BREACH_NOTIFICATION_IND_V02, 243 244 // For - LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING 245 QMI_LOC_START_DBT_REQ_V02 246 }; 247 248 // check the modem 249 status = locClientSupportMsgCheck(clientHandle, 250 msgArray, 251 NUMBER_OF_MSG_TO_BE_CHECKED, 252 &supportedMsgList); 253 if (eLOC_CLIENT_SUCCESS != status) { 254 LOC_LOGE("%s:%d]: Failed to checking QMI_LOC message supported. \n", 255 __func__, __LINE__); 256 } 257 258 /** if batching is supported , check if the adaptive batching or 259 distance-based batching is supported. */ 260 uint32_t messageChecker = 1 << LOC_API_ADAPTER_MESSAGE_LOCATION_BATCHING; 261 if ((messageChecker & supportedMsgList) == messageChecker) { 262 locClientReqUnionType req_union; 263 locClientStatusEnumType status = eLOC_CLIENT_SUCCESS; 264 qmiLocQueryAonConfigReqMsgT_v02 queryAonConfigReq; 265 qmiLocQueryAonConfigIndMsgT_v02 queryAonConfigInd; 266 267 memset(&queryAonConfigReq, 0, sizeof(queryAonConfigReq)); 268 memset(&queryAonConfigInd, 0, sizeof(queryAonConfigInd)); 269 queryAonConfigReq.transactionId = LOC_API_V02_DEF_SESSION_ID; 270 271 req_union.pQueryAonConfigReq = &queryAonConfigReq; 272 status = loc_sync_send_req(clientHandle, 273 QMI_LOC_QUERY_AON_CONFIG_REQ_V02, 274 req_union, 275 LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 276 QMI_LOC_QUERY_AON_CONFIG_IND_V02, 277 &queryAonConfigInd); 278 279 if (status == eLOC_CLIENT_FAILURE_UNSUPPORTED) { 280 LOC_LOGE("%s:%d]: Query AON config is not supported.\n", __func__, __LINE__); 281 } else { 282 if (status != eLOC_CLIENT_SUCCESS || 283 queryAonConfigInd.status != eQMI_LOC_SUCCESS_V02) { 284 LOC_LOGE("%s:%d]: Query AON config failed." 285 " status: %s, ind status:%s\n", 286 __func__, __LINE__, 287 loc_get_v02_client_status_name(status), 288 loc_get_v02_qmi_status_name(queryAonConfigInd.status)); 289 } else { 290 LOC_LOGD("%s:%d]: Query AON config succeeded. aonCapability is %d.\n", 291 __func__, __LINE__, queryAonConfigInd.aonCapability); 292 if (queryAonConfigInd.aonCapability_valid) { 293 if (queryAonConfigInd.aonCapability | 294 QMI_LOC_MASK_AON_TIME_BASED_BATCHING_SUPPORTED_V02) { 295 LOC_LOGD("%s:%d]: LB 1.0 is supported.\n", __func__, __LINE__); 296 } 297 if (queryAonConfigInd.aonCapability | 298 QMI_LOC_MASK_AON_AUTO_BATCHING_SUPPORTED_V02) { 299 LOC_LOGD("%s:%d]: LB 1.5 is supported.\n", __func__, __LINE__); 300 supportedMsgList |= 301 (1 << LOC_API_ADAPTER_MESSAGE_ADAPTIVE_LOCATION_BATCHING); 302 } 303 if (queryAonConfigInd.aonCapability | 304 QMI_LOC_MASK_AON_DISTANCE_BASED_BATCHING_SUPPORTED_V02) { 305 LOC_LOGD("%s:%d]: LB 2.0 is supported.\n", __func__, __LINE__); 306 supportedMsgList |= 307 (1 << LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING); 308 } 309 if (queryAonConfigInd.aonCapability | 310 QMI_LOC_MASK_AON_DISTANCE_BASED_TRACKING_SUPPORTED_V02) { 311 LOC_LOGD("%s:%d]: DBT 2.0 is supported.\n", __func__, __LINE__); 312 } 313 if (queryAonConfigInd.aonCapability | 314 QMI_LOC_MASK_AON_UPDATE_TBF_SUPPORTED_V02) { 315 LOC_LOGD("%s:%d]: Updating tracking TBF on the fly is supported.\n", 316 __func__, __LINE__); 317 supportedMsgList |= 318 (1 << LOC_API_ADAPTER_MESSAGE_UPDATE_TBF_ON_THE_FLY); 319 } 320 } else { 321 LOC_LOGE("%s:%d]: AON capability is invalid.\n", __func__, __LINE__); 322 } 323 } 324 } 325 } 326 LOC_LOGV("%s:%d]: supportedMsgList is %lld. \n", 327 __func__, __LINE__, supportedMsgList); 328 // save the supported message list 329 saveSupportedMsgList(supportedMsgList); 330 } 331 } else if (newMask != mMask) { 332 // it is important to cap the mask here, because not all LocApi's 333 // can enable the same bits, e.g. foreground and background. 334 if (!registerEventMask(qmiMask)) { 335 // we do not update mMask here, because it did not change 336 // as the mask update has failed. 337 rtv = LOC_API_ADAPTER_ERR_FAILURE; 338 } 339 else { 340 mMask = newMask; 341 mQmiMask = qmiMask; 342 } 343 } 344 LOC_LOGD("%s:%d]: Exit mMask: %x; mask: %x mQmiMask: %llx qmiMask: %llx", 345 __func__, __LINE__, mMask, mask, mQmiMask, qmiMask); 346 347 if (LOC_API_ADAPTER_ERR_SUCCESS == rtv) { 348 cacheGnssMeasurementSupport(); 349 } 350 351 return rtv; 352 } 353 354 bool LocApiV02 :: registerEventMask(locClientEventMaskType qmiMask) 355 { 356 if (!mInSession) { 357 qmiMask = adjustMaskForNoSession(qmiMask); 358 } 359 LOC_LOGD("%s:%d]: mQmiMask=%lld qmiMask=%lld", 360 __func__, __LINE__, mQmiMask, qmiMask); 361 return locClientRegisterEventMask(clientHandle, qmiMask); 362 } 363 364 locClientEventMaskType LocApiV02 :: adjustMaskForNoSession(locClientEventMaskType qmiMask) 365 { 366 LOC_LOGD("%s:%d]: before qmiMask=%lld", 367 __func__, __LINE__, qmiMask); 368 locClientEventMaskType clearMask = QMI_LOC_EVENT_MASK_POSITION_REPORT_V02 | 369 QMI_LOC_EVENT_MASK_GNSS_SV_INFO_V02 | 370 QMI_LOC_EVENT_MASK_NMEA_V02 | 371 QMI_LOC_EVENT_MASK_ENGINE_STATE_V02 | 372 QMI_LOC_EVENT_MASK_GNSS_MEASUREMENT_REPORT_V02; 373 374 qmiMask = qmiMask & ~clearMask; 375 LOC_LOGD("%s:%d]: after qmiMask=%lld", 376 __func__, __LINE__, qmiMask); 377 return qmiMask; 378 } 379 380 enum loc_api_adapter_err LocApiV02 :: close() 381 { 382 enum loc_api_adapter_err rtv = 383 // success if either client is already invalid, or 384 // we successfully close the handle 385 (LOC_CLIENT_INVALID_HANDLE_VALUE == clientHandle || 386 eLOC_CLIENT_SUCCESS == locClientClose(&clientHandle)) ? 387 LOC_API_ADAPTER_ERR_SUCCESS : LOC_API_ADAPTER_ERR_FAILURE; 388 389 mMask = 0; 390 clientHandle = LOC_CLIENT_INVALID_HANDLE_VALUE; 391 392 return rtv; 393 } 394 395 /* start positioning session */ 396 enum loc_api_adapter_err LocApiV02 :: startFix(const LocPosMode& fixCriteria) 397 { 398 locClientStatusEnumType status; 399 locClientReqUnionType req_union; 400 401 qmiLocStartReqMsgT_v02 start_msg; 402 403 qmiLocSetOperationModeReqMsgT_v02 set_mode_msg; 404 qmiLocSetOperationModeIndMsgT_v02 set_mode_ind; 405 406 // clear all fields, validity masks 407 memset (&start_msg, 0, sizeof(start_msg)); 408 memset (&set_mode_msg, 0, sizeof(set_mode_msg)); 409 memset (&set_mode_ind, 0, sizeof(set_mode_ind)); 410 411 LOC_LOGV("%s:%d]: start \n", __func__, __LINE__); 412 fixCriteria.logv(); 413 414 mInSession = true; 415 mMeasurementsStarted = true; 416 registerEventMask(mQmiMask); 417 418 // fill in the start request 419 switch(fixCriteria.mode) 420 { 421 case LOC_POSITION_MODE_MS_BASED: 422 set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_MSB_V02; 423 break; 424 425 case LOC_POSITION_MODE_MS_ASSISTED: 426 set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_MSA_V02; 427 break; 428 429 case LOC_POSITION_MODE_RESERVED_4: 430 set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_CELL_ID_V02; 431 break; 432 433 case LOC_POSITION_MODE_RESERVED_5: 434 set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_WWAN_V02; 435 break; 436 437 default: 438 set_mode_msg.operationMode = eQMI_LOC_OPER_MODE_STANDALONE_V02; 439 break; 440 } 441 442 req_union.pSetOperationModeReq = &set_mode_msg; 443 444 // send the mode first, before the start message. 445 status = loc_sync_send_req(clientHandle, 446 QMI_LOC_SET_OPERATION_MODE_REQ_V02, 447 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 448 QMI_LOC_SET_OPERATION_MODE_IND_V02, 449 &set_mode_ind); // NULL? 450 //When loc_sync_send_req status is time out, more likely the response was lost. 451 //startFix will continue as though it is succeeded. 452 if ((status != eLOC_CLIENT_SUCCESS && status != eLOC_CLIENT_FAILURE_TIMEOUT) || 453 eQMI_LOC_SUCCESS_V02 != set_mode_ind.status) 454 { 455 LOC_LOGE ("%s:%d]: set opertion mode failed status = %s, " 456 "ind..status = %s\n", __func__, __LINE__, 457 loc_get_v02_client_status_name(status), 458 loc_get_v02_qmi_status_name(set_mode_ind.status)); 459 } else { 460 if (status == eLOC_CLIENT_FAILURE_TIMEOUT) 461 { 462 LOC_LOGE ("%s:%d]: set operation mode timed out\n", __func__, __LINE__); 463 } 464 start_msg.minInterval_valid = 1; 465 start_msg.minInterval = fixCriteria.min_interval; 466 467 if (fixCriteria.preferred_accuracy >= 0) { 468 start_msg.horizontalAccuracyLevel_valid = 1; 469 470 if (fixCriteria.preferred_accuracy <= 100) 471 { 472 // fix needs high accuracy 473 start_msg.horizontalAccuracyLevel = eQMI_LOC_ACCURACY_HIGH_V02; 474 } 475 else if (fixCriteria.preferred_accuracy <= 1000) 476 { 477 //fix needs med accuracy 478 start_msg.horizontalAccuracyLevel = eQMI_LOC_ACCURACY_MED_V02; 479 } 480 else 481 { 482 //fix needs low accuracy 483 start_msg.horizontalAccuracyLevel = eQMI_LOC_ACCURACY_LOW_V02; 484 } 485 } 486 487 start_msg.fixRecurrence_valid = 1; 488 if(GPS_POSITION_RECURRENCE_SINGLE == fixCriteria.recurrence) 489 { 490 start_msg.fixRecurrence = eQMI_LOC_RECURRENCE_SINGLE_V02; 491 } 492 else 493 { 494 start_msg.fixRecurrence = eQMI_LOC_RECURRENCE_PERIODIC_V02; 495 } 496 497 //dummy session id 498 // TBD: store session ID, check for session id in pos reports. 499 start_msg.sessionId = LOC_API_V02_DEF_SESSION_ID; 500 501 if (fixCriteria.credentials[0] != 0) { 502 int size1 = sizeof(start_msg.applicationId.applicationName); 503 int size2 = sizeof(fixCriteria.credentials); 504 int len = ((size1 < size2) ? size1 : size2) - 1; 505 memcpy(start_msg.applicationId.applicationName, 506 fixCriteria.credentials, 507 len); 508 509 size1 = sizeof(start_msg.applicationId.applicationProvider); 510 size2 = sizeof(fixCriteria.provider); 511 len = ((size1 < size2) ? size1 : size2) - 1; 512 memcpy(start_msg.applicationId.applicationProvider, 513 fixCriteria.provider, 514 len); 515 516 start_msg.applicationId_valid = 1; 517 } 518 519 // config Altitude Assumed 520 start_msg.configAltitudeAssumed_valid = 1; 521 start_msg.configAltitudeAssumed = eQMI_LOC_ALTITUDE_ASSUMED_IN_GNSS_SV_INFO_DISABLED_V02; 522 523 req_union.pStartReq = &start_msg; 524 525 status = locClientSendReq (clientHandle, QMI_LOC_START_REQ_V02, 526 req_union ); 527 } 528 529 return convertErr(status); 530 } 531 532 /* stop a positioning session */ 533 enum loc_api_adapter_err LocApiV02 :: stopFix() 534 { 535 locClientStatusEnumType status; 536 locClientReqUnionType req_union; 537 538 qmiLocStopReqMsgT_v02 stop_msg; 539 540 LOC_LOGD(" %s:%d]: stop called \n", __func__, __LINE__); 541 542 memset(&stop_msg, 0, sizeof(stop_msg)); 543 544 // dummy session id 545 stop_msg.sessionId = LOC_API_V02_DEF_SESSION_ID; 546 547 req_union.pStopReq = &stop_msg; 548 549 status = locClientSendReq(clientHandle, 550 QMI_LOC_STOP_REQ_V02, 551 req_union); 552 553 mInSession = false; 554 // if engine on never happend, deregister events 555 // without waiting for Engine Off 556 if (!mEngineOn) { 557 registerEventMask(mQmiMask); 558 } 559 560 if( eLOC_CLIENT_SUCCESS != status) 561 { 562 LOC_LOGE("%s:%d]: error = %s\n",__func__, __LINE__, 563 loc_get_v02_client_status_name(status)); 564 } 565 566 return convertErr(status); 567 } 568 569 /* set the positioning fix criteria */ 570 enum loc_api_adapter_err LocApiV02 :: setPositionMode( 571 const LocPosMode& posMode) 572 { 573 if(isInSession()) 574 { 575 //fix is in progress, send a restart 576 LOC_LOGD ("%s:%d]: fix is in progress restarting the fix with new " 577 "criteria\n", __func__, __LINE__); 578 579 return( startFix(posMode)); 580 } 581 582 return LOC_API_ADAPTER_ERR_SUCCESS; 583 } 584 585 /* inject time into the position engine */ 586 enum loc_api_adapter_err LocApiV02 :: 587 setTime(GpsUtcTime time, int64_t timeReference, int uncertainty) 588 { 589 locClientReqUnionType req_union; 590 locClientStatusEnumType status; 591 qmiLocInjectUtcTimeReqMsgT_v02 inject_time_msg; 592 qmiLocInjectUtcTimeIndMsgT_v02 inject_time_ind; 593 594 memset(&inject_time_msg, 0, sizeof(inject_time_msg)); 595 596 inject_time_ind.status = eQMI_LOC_GENERAL_FAILURE_V02; 597 598 inject_time_msg.timeUtc = time; 599 600 inject_time_msg.timeUtc += (int64_t)(ELAPSED_MILLIS_SINCE_BOOT_PLATFORM_LIB_ABSTRACTION - timeReference); 601 602 inject_time_msg.timeUnc = uncertainty; 603 604 req_union.pInjectUtcTimeReq = &inject_time_msg; 605 606 LOC_LOGV ("%s:%d]: uncertainty = %d\n", __func__, __LINE__, 607 uncertainty); 608 609 status = loc_sync_send_req(clientHandle, 610 QMI_LOC_INJECT_UTC_TIME_REQ_V02, 611 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 612 QMI_LOC_INJECT_UTC_TIME_IND_V02, 613 &inject_time_ind); 614 615 if (status != eLOC_CLIENT_SUCCESS || 616 eQMI_LOC_SUCCESS_V02 != inject_time_ind.status) 617 { 618 LOC_LOGE ("%s:%d] status = %s, ind..status = %s\n", __func__, __LINE__, 619 loc_get_v02_client_status_name(status), 620 loc_get_v02_qmi_status_name(inject_time_ind.status)); 621 } 622 623 return convertErr(status); 624 } 625 626 /* inject position into the position engine */ 627 enum loc_api_adapter_err LocApiV02 :: 628 injectPosition(double latitude, double longitude, float accuracy) 629 { 630 locClientReqUnionType req_union; 631 locClientStatusEnumType status; 632 qmiLocInjectPositionReqMsgT_v02 inject_pos_msg; 633 qmiLocInjectPositionIndMsgT_v02 inject_pos_ind; 634 635 memset(&inject_pos_msg, 0, sizeof(inject_pos_msg)); 636 637 inject_pos_msg.latitude_valid = 1; 638 inject_pos_msg.latitude = latitude; 639 640 inject_pos_msg.longitude_valid = 1; 641 inject_pos_msg.longitude = longitude; 642 643 inject_pos_msg.horUncCircular_valid = 1; 644 645 inject_pos_msg.horUncCircular = accuracy; //meters assumed 646 if (inject_pos_msg.horUncCircular < 1000) { 647 inject_pos_msg.horUncCircular = 1000; 648 } 649 650 inject_pos_msg.horConfidence_valid = 1; 651 652 inject_pos_msg.horConfidence = 68; //1 std dev assumed as specified by API 653 654 inject_pos_msg.rawHorUncCircular_valid = 1; 655 656 inject_pos_msg.rawHorUncCircular = accuracy; //meters assumed 657 658 inject_pos_msg.rawHorConfidence_valid = 1; 659 660 inject_pos_msg.rawHorConfidence = 68; //1 std dev assumed as specified by API 661 662 /* Log */ 663 LOC_LOGD("%s:%d]: Lat=%lf, Lon=%lf, Acc=%.2lf rawAcc=%.2lf", __func__, __LINE__, 664 inject_pos_msg.latitude, inject_pos_msg.longitude, 665 inject_pos_msg.horUncCircular, inject_pos_msg.rawHorUncCircular); 666 667 req_union.pInjectPositionReq = &inject_pos_msg; 668 669 status = loc_sync_send_req(clientHandle, 670 QMI_LOC_INJECT_POSITION_REQ_V02, 671 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 672 QMI_LOC_INJECT_POSITION_IND_V02, 673 &inject_pos_ind); 674 675 if (status != eLOC_CLIENT_SUCCESS || 676 eQMI_LOC_SUCCESS_V02 != inject_pos_ind.status) 677 { 678 LOC_LOGE ("%s:%d]: error! status = %s, inject_pos_ind.status = %s\n", 679 __func__, __LINE__, 680 loc_get_v02_client_status_name(status), 681 loc_get_v02_qmi_status_name(inject_pos_ind.status)); 682 } 683 684 return convertErr(status); 685 } 686 687 /* delete assistance date */ 688 enum loc_api_adapter_err LocApiV02 :: deleteAidingData(GpsAidingData f) 689 { 690 locClientReqUnionType req_union; 691 locClientStatusEnumType status; 692 qmiLocDeleteAssistDataReqMsgT_v02 delete_req; 693 qmiLocDeleteAssistDataIndMsgT_v02 delete_resp; 694 695 memset(&delete_req, 0, sizeof(delete_req)); 696 memset(&delete_resp, 0, sizeof(delete_resp)); 697 698 if( f == GPS_DELETE_ALL ) 699 { 700 delete_req.deleteAllFlag = true; 701 } 702 703 else 704 { 705 /* to keep track of svInfoList for GPS and GLO*/ 706 uint32_t curr_sv_len = 0; 707 uint32_t curr_sv_idx = 0; 708 uint32_t sv_id = 0; 709 710 if((f & GPS_DELETE_EPHEMERIS ) || ( f & GPS_DELETE_ALMANAC )) 711 { 712 /* do delete for all GPS SV's */ 713 714 curr_sv_len += SV_ID_RANGE; 715 716 sv_id = GPS_SV_ID_OFFSET; 717 718 delete_req.deleteSvInfoList_valid = 1; 719 720 delete_req.deleteSvInfoList_len = curr_sv_len; 721 722 LOC_LOGV("%s:%d]: Delete GPS SV info for index %d to %d" 723 "and sv id %d to %d \n", 724 __func__, __LINE__, curr_sv_idx, curr_sv_len - 1, 725 sv_id, sv_id+SV_ID_RANGE-1); 726 727 for( uint32_t i = curr_sv_idx; i< curr_sv_len ; i++, sv_id++ ) 728 { 729 delete_req.deleteSvInfoList[i].gnssSvId = sv_id; 730 731 delete_req.deleteSvInfoList[i].system = eQMI_LOC_SV_SYSTEM_GPS_V02; 732 733 if(f & GPS_DELETE_EPHEMERIS ) 734 { 735 // set ephemeris mask for all GPS SV's 736 delete_req.deleteSvInfoList[i].deleteSvInfoMask |= 737 QMI_LOC_MASK_DELETE_EPHEMERIS_V02; 738 } 739 740 if( f & GPS_DELETE_ALMANAC ) 741 { 742 delete_req.deleteSvInfoList[i].deleteSvInfoMask |= 743 QMI_LOC_MASK_DELETE_ALMANAC_V02; 744 } 745 } 746 // increment the current index 747 curr_sv_idx += SV_ID_RANGE; 748 749 } 750 751 if(f & GPS_DELETE_POSITION ) 752 { 753 delete_req.deleteGnssDataMask_valid = 1; 754 delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_POSITION_V02; 755 } 756 757 if(f & GPS_DELETE_TIME ) 758 { 759 delete_req.deleteGnssDataMask_valid = 1; 760 delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_TIME_V02; 761 } 762 763 if(f & GPS_DELETE_IONO ) 764 { 765 delete_req.deleteGnssDataMask_valid = 1; 766 delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_IONO_V02; 767 } 768 769 if(f & GPS_DELETE_UTC ) 770 { 771 delete_req.deleteGnssDataMask_valid = 1; 772 delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_UTC_V02; 773 } 774 775 if(f & GPS_DELETE_HEALTH ) 776 { 777 delete_req.deleteGnssDataMask_valid = 1; 778 delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_HEALTH_V02; 779 } 780 781 if(f & GPS_DELETE_SVDIR ) 782 { 783 delete_req.deleteGnssDataMask_valid = 1; 784 delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_GPS_SVDIR_V02; 785 } 786 if(f & GPS_DELETE_SADATA ) 787 { 788 delete_req.deleteGnssDataMask_valid = 1; 789 delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_SADATA_V02; 790 } 791 if(f & GPS_DELETE_RTI ) 792 { 793 delete_req.deleteGnssDataMask_valid = 1; 794 delete_req.deleteGnssDataMask |= QMI_LOC_MASK_DELETE_RTI_V02; 795 } 796 if(f & GPS_DELETE_CELLDB_INFO ) 797 { 798 delete_req.deleteCellDbDataMask_valid = 1; 799 delete_req.deleteCellDbDataMask = 800 ( QMI_LOC_MASK_DELETE_CELLDB_POS_V02 | 801 QMI_LOC_MASK_DELETE_CELLDB_LATEST_GPS_POS_V02 | 802 QMI_LOC_MASK_DELETE_CELLDB_OTA_POS_V02 | 803 QMI_LOC_MASK_DELETE_CELLDB_EXT_REF_POS_V02 | 804 QMI_LOC_MASK_DELETE_CELLDB_TIMETAG_V02 | 805 QMI_LOC_MASK_DELETE_CELLDB_CELLID_V02 | 806 QMI_LOC_MASK_DELETE_CELLDB_CACHED_CELLID_V02 | 807 QMI_LOC_MASK_DELETE_CELLDB_LAST_SRV_CELL_V02 | 808 QMI_LOC_MASK_DELETE_CELLDB_CUR_SRV_CELL_V02 | 809 QMI_LOC_MASK_DELETE_CELLDB_NEIGHBOR_INFO_V02) ; 810 811 } 812 #ifndef PDK_FEATURE_SET 813 #endif 814 815 } 816 817 req_union.pDeleteAssistDataReq = &delete_req; 818 819 status = loc_sync_send_req(clientHandle, 820 QMI_LOC_DELETE_ASSIST_DATA_REQ_V02, 821 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 822 QMI_LOC_DELETE_ASSIST_DATA_IND_V02, 823 &delete_resp); 824 825 if (status != eLOC_CLIENT_SUCCESS || 826 eQMI_LOC_SUCCESS_V02 != delete_resp.status) 827 { 828 LOC_LOGE ("%s:%d]: error! status = %s, delete_resp.status = %s\n", 829 __func__, __LINE__, 830 loc_get_v02_client_status_name(status), 831 loc_get_v02_qmi_status_name(delete_resp.status)); 832 } 833 834 return convertErr(status); 835 } 836 837 /* send NI user repsonse to the engine */ 838 enum loc_api_adapter_err LocApiV02 :: 839 informNiResponse(GpsUserResponseType userResponse, 840 const void* passThroughData) 841 { 842 locClientReqUnionType req_union; 843 locClientStatusEnumType status; 844 845 qmiLocNiUserRespReqMsgT_v02 ni_resp; 846 qmiLocNiUserRespIndMsgT_v02 ni_resp_ind; 847 848 qmiLocEventNiNotifyVerifyReqIndMsgT_v02 *request_pass_back = 849 (qmiLocEventNiNotifyVerifyReqIndMsgT_v02 *)passThroughData; 850 851 memset(&ni_resp,0, sizeof(ni_resp)); 852 853 memset(&ni_resp_ind,0, sizeof(ni_resp_ind)); 854 855 switch (userResponse) 856 { 857 case GPS_NI_RESPONSE_ACCEPT: 858 ni_resp.userResp = eQMI_LOC_NI_LCS_NOTIFY_VERIFY_ACCEPT_V02; 859 break; 860 case GPS_NI_RESPONSE_DENY: 861 ni_resp.userResp = eQMI_LOC_NI_LCS_NOTIFY_VERIFY_DENY_V02; 862 break; 863 case GPS_NI_RESPONSE_NORESP: 864 ni_resp.userResp = eQMI_LOC_NI_LCS_NOTIFY_VERIFY_NORESP_V02; 865 break; 866 default: 867 return LOC_API_ADAPTER_ERR_INVALID_PARAMETER; 868 } 869 870 LOC_LOGV(" %s:%d]: NI response: %d\n", __func__, __LINE__, 871 ni_resp.userResp); 872 873 ni_resp.notificationType = request_pass_back->notificationType; 874 875 // copy SUPL payload from request 876 if(request_pass_back->NiSuplInd_valid == 1) 877 { 878 ni_resp.NiSuplPayload_valid = 1; 879 memcpy(&(ni_resp.NiSuplPayload), &(request_pass_back->NiSuplInd), 880 sizeof(qmiLocNiSuplNotifyVerifyStructT_v02)); 881 882 } 883 // should this be an "else if"?? we don't need to decide 884 885 // copy UMTS-CP payload from request 886 if( request_pass_back->NiUmtsCpInd_valid == 1 ) 887 { 888 ni_resp.NiUmtsCpPayload_valid = 1; 889 memcpy(&(ni_resp.NiUmtsCpPayload), &(request_pass_back->NiUmtsCpInd), 890 sizeof(qmiLocNiUmtsCpNotifyVerifyStructT_v02)); 891 } 892 893 //copy Vx payload from the request 894 if( request_pass_back->NiVxInd_valid == 1) 895 { 896 ni_resp.NiVxPayload_valid = 1; 897 memcpy(&(ni_resp.NiVxPayload), &(request_pass_back->NiVxInd), 898 sizeof(qmiLocNiVxNotifyVerifyStructT_v02)); 899 } 900 901 // copy Vx service interaction payload from the request 902 if(request_pass_back->NiVxServiceInteractionInd_valid == 1) 903 { 904 ni_resp.NiVxServiceInteractionPayload_valid = 1; 905 memcpy(&(ni_resp.NiVxServiceInteractionPayload), 906 &(request_pass_back->NiVxServiceInteractionInd), 907 sizeof(qmiLocNiVxServiceInteractionStructT_v02)); 908 } 909 910 // copy Network Initiated SUPL Version 2 Extension 911 if (request_pass_back->NiSuplVer2ExtInd_valid == 1) 912 { 913 ni_resp.NiSuplVer2ExtPayload_valid = 1; 914 memcpy(&(ni_resp.NiSuplVer2ExtPayload), 915 &(request_pass_back->NiSuplVer2ExtInd), 916 sizeof(qmiLocNiSuplVer2ExtStructT_v02)); 917 } 918 919 // copy SUPL Emergency Notification 920 if(request_pass_back->suplEmergencyNotification_valid) 921 { 922 ni_resp.suplEmergencyNotification_valid = 1; 923 memcpy(&(ni_resp.suplEmergencyNotification), 924 &(request_pass_back->suplEmergencyNotification), 925 sizeof(qmiLocEmergencyNotificationStructT_v02)); 926 } 927 928 req_union.pNiUserRespReq = &ni_resp; 929 930 status = loc_sync_send_req ( 931 clientHandle, QMI_LOC_NI_USER_RESPONSE_REQ_V02, 932 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 933 QMI_LOC_NI_USER_RESPONSE_IND_V02, &ni_resp_ind); 934 935 if (status != eLOC_CLIENT_SUCCESS || 936 eQMI_LOC_SUCCESS_V02 != ni_resp_ind.status) 937 { 938 LOC_LOGE ("%s:%d]: error! status = %s, ni_resp_ind.status = %s\n", 939 __func__, __LINE__, 940 loc_get_v02_client_status_name(status), 941 loc_get_v02_qmi_status_name(ni_resp_ind.status)); 942 } 943 944 return convertErr(status); 945 } 946 947 /* Set UMTs SLP server URL */ 948 enum loc_api_adapter_err LocApiV02 :: setServer( 949 const char* url, int len) 950 { 951 locClientReqUnionType req_union; 952 locClientStatusEnumType status; 953 qmiLocSetServerReqMsgT_v02 set_server_req; 954 qmiLocSetServerIndMsgT_v02 set_server_ind; 955 956 if(len < 0 || len > sizeof(set_server_req.urlAddr)) 957 { 958 LOC_LOGE("%s:%d]: len = %d greater than max allowed url length\n", 959 __func__, __LINE__, len); 960 961 return LOC_API_ADAPTER_ERR_INVALID_PARAMETER; 962 } 963 964 memset(&set_server_req, 0, sizeof(set_server_req)); 965 966 LOC_LOGD("%s:%d]:, url = %s, len = %d\n", __func__, __LINE__, url, len); 967 968 set_server_req.serverType = eQMI_LOC_SERVER_TYPE_UMTS_SLP_V02; 969 970 set_server_req.urlAddr_valid = 1; 971 972 strlcpy(set_server_req.urlAddr, url, sizeof(set_server_req.urlAddr)); 973 974 req_union.pSetServerReq = &set_server_req; 975 976 status = loc_sync_send_req(clientHandle, 977 QMI_LOC_SET_SERVER_REQ_V02, 978 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 979 QMI_LOC_SET_SERVER_IND_V02, 980 &set_server_ind); 981 982 if (status != eLOC_CLIENT_SUCCESS || 983 eQMI_LOC_SUCCESS_V02 != set_server_ind.status) 984 { 985 LOC_LOGE ("%s:%d]: error status = %s, set_server_ind.status = %s\n", 986 __func__,__LINE__, 987 loc_get_v02_client_status_name(status), 988 loc_get_v02_qmi_status_name(set_server_ind.status)); 989 } 990 991 return convertErr(status); 992 } 993 994 enum loc_api_adapter_err LocApiV02 :: 995 setServer(unsigned int ip, int port, LocServerType type) 996 { 997 locClientReqUnionType req_union; 998 locClientStatusEnumType status; 999 qmiLocSetServerReqMsgT_v02 set_server_req; 1000 qmiLocSetServerIndMsgT_v02 set_server_ind; 1001 qmiLocServerTypeEnumT_v02 set_server_cmd; 1002 1003 switch (type) { 1004 case LOC_AGPS_MPC_SERVER: 1005 set_server_cmd = eQMI_LOC_SERVER_TYPE_CDMA_MPC_V02; 1006 break; 1007 case LOC_AGPS_CUSTOM_PDE_SERVER: 1008 set_server_cmd = eQMI_LOC_SERVER_TYPE_CUSTOM_PDE_V02; 1009 break; 1010 default: 1011 set_server_cmd = eQMI_LOC_SERVER_TYPE_CDMA_PDE_V02; 1012 break; 1013 } 1014 1015 memset(&set_server_req, 0, sizeof(set_server_req)); 1016 1017 LOC_LOGD("%s:%d]:, ip = %u, port = %d\n", __func__, __LINE__, ip, port); 1018 1019 set_server_req.serverType = set_server_cmd; 1020 set_server_req.ipv4Addr_valid = 1; 1021 set_server_req.ipv4Addr.addr = ip; 1022 set_server_req.ipv4Addr.port = port; 1023 1024 req_union.pSetServerReq = &set_server_req; 1025 1026 status = loc_sync_send_req(clientHandle, 1027 QMI_LOC_SET_SERVER_REQ_V02, 1028 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 1029 QMI_LOC_SET_SERVER_IND_V02, 1030 &set_server_ind); 1031 1032 if (status != eLOC_CLIENT_SUCCESS || 1033 eQMI_LOC_SUCCESS_V02 != set_server_ind.status) 1034 { 1035 LOC_LOGE ("%s:%d]: error status = %s, set_server_ind.status = %s\n", 1036 __func__,__LINE__, 1037 loc_get_v02_client_status_name(status), 1038 loc_get_v02_qmi_status_name(set_server_ind.status)); 1039 } 1040 1041 return convertErr(status); 1042 } 1043 1044 /* Inject XTRA data, this module breaks down the XTRA 1045 file into "chunks" and injects them one at a time */ 1046 enum loc_api_adapter_err LocApiV02 :: setXtraData( 1047 char* data, int length) 1048 { 1049 locClientStatusEnumType status = eLOC_CLIENT_SUCCESS; 1050 int total_parts; 1051 uint8_t part; 1052 uint16_t len_injected; 1053 1054 locClientReqUnionType req_union; 1055 qmiLocInjectPredictedOrbitsDataReqMsgT_v02 inject_xtra; 1056 qmiLocInjectPredictedOrbitsDataIndMsgT_v02 inject_xtra_ind; 1057 1058 req_union.pInjectPredictedOrbitsDataReq = &inject_xtra; 1059 1060 LOC_LOGD("%s:%d]: xtra size = %d\n", __func__, __LINE__, length); 1061 1062 inject_xtra.formatType_valid = 1; 1063 inject_xtra.formatType = eQMI_LOC_PREDICTED_ORBITS_XTRA_V02; 1064 inject_xtra.totalSize = length; 1065 1066 total_parts = ((length - 1) / QMI_LOC_MAX_PREDICTED_ORBITS_PART_LEN_V02) + 1; 1067 1068 inject_xtra.totalParts = total_parts; 1069 1070 len_injected = 0; // O bytes injected 1071 1072 // XTRA injection starts with part 1 1073 for (part = 1; part <= total_parts; part++) 1074 { 1075 inject_xtra.partNum = part; 1076 1077 if (QMI_LOC_MAX_PREDICTED_ORBITS_PART_LEN_V02 > (length - len_injected)) 1078 { 1079 inject_xtra.partData_len = length - len_injected; 1080 } 1081 else 1082 { 1083 inject_xtra.partData_len = QMI_LOC_MAX_PREDICTED_ORBITS_PART_LEN_V02; 1084 } 1085 1086 // copy data into the message 1087 memcpy(inject_xtra.partData, data+len_injected, inject_xtra.partData_len); 1088 1089 LOC_LOGD("[%s:%d] part %d/%d, len = %d, total injected = %d\n", 1090 __func__, __LINE__, 1091 inject_xtra.partNum, total_parts, inject_xtra.partData_len, 1092 len_injected); 1093 1094 status = loc_sync_send_req( clientHandle, 1095 QMI_LOC_INJECT_PREDICTED_ORBITS_DATA_REQ_V02, 1096 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 1097 QMI_LOC_INJECT_PREDICTED_ORBITS_DATA_IND_V02, 1098 &inject_xtra_ind); 1099 1100 if (status != eLOC_CLIENT_SUCCESS || 1101 eQMI_LOC_SUCCESS_V02 != inject_xtra_ind.status || 1102 inject_xtra.partNum != inject_xtra_ind.partNum) 1103 { 1104 LOC_LOGE ("%s:%d]: failed status = %s, inject_pos_ind.status = %s," 1105 " part num = %d, ind.partNum = %d\n", __func__, __LINE__, 1106 loc_get_v02_client_status_name(status), 1107 loc_get_v02_qmi_status_name(inject_xtra_ind.status), 1108 inject_xtra.partNum, inject_xtra_ind.partNum); 1109 } else { 1110 len_injected += inject_xtra.partData_len; 1111 LOC_LOGD("%s:%d]: XTRA injected length: %d\n", __func__, __LINE__, 1112 len_injected); 1113 } 1114 } 1115 1116 return convertErr(status); 1117 } 1118 1119 /* Request the Xtra Server Url from the modem */ 1120 enum loc_api_adapter_err LocApiV02 :: requestXtraServer() 1121 { 1122 locClientStatusEnumType status = eLOC_CLIENT_SUCCESS; 1123 1124 locClientReqUnionType req_union; 1125 qmiLocGetPredictedOrbitsDataSourceIndMsgT_v02 request_xtra_server_ind; 1126 1127 status = loc_sync_send_req( clientHandle, 1128 QMI_LOC_GET_PREDICTED_ORBITS_DATA_SOURCE_REQ_V02, 1129 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 1130 QMI_LOC_GET_PREDICTED_ORBITS_DATA_SOURCE_IND_V02, 1131 &request_xtra_server_ind); 1132 1133 if (status == eLOC_CLIENT_SUCCESS && 1134 eQMI_LOC_SUCCESS_V02 == request_xtra_server_ind.status && 1135 false != request_xtra_server_ind.serverList_valid && 1136 0 != request_xtra_server_ind.serverList.serverList_len) 1137 { 1138 if (request_xtra_server_ind.serverList.serverList_len == 1) 1139 { 1140 reportXtraServer(request_xtra_server_ind.serverList.serverList[0].serverUrl, 1141 "", 1142 "", 1143 QMI_LOC_MAX_SERVER_ADDR_LENGTH_V02); 1144 } 1145 else if (request_xtra_server_ind.serverList.serverList_len == 2) 1146 { 1147 reportXtraServer(request_xtra_server_ind.serverList.serverList[0].serverUrl, 1148 request_xtra_server_ind.serverList.serverList[1].serverUrl, 1149 "", 1150 QMI_LOC_MAX_SERVER_ADDR_LENGTH_V02); 1151 } 1152 else 1153 { 1154 reportXtraServer(request_xtra_server_ind.serverList.serverList[0].serverUrl, 1155 request_xtra_server_ind.serverList.serverList[1].serverUrl, 1156 request_xtra_server_ind.serverList.serverList[2].serverUrl, 1157 QMI_LOC_MAX_SERVER_ADDR_LENGTH_V02); 1158 } 1159 } 1160 1161 return convertErr(status); 1162 } 1163 1164 enum loc_api_adapter_err LocApiV02 :: atlOpenStatus( 1165 int handle, int is_succ, char* apn, AGpsBearerType bear, 1166 AGpsType agpsType) 1167 { 1168 locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; 1169 locClientReqUnionType req_union; 1170 qmiLocInformLocationServerConnStatusReqMsgT_v02 conn_status_req; 1171 qmiLocInformLocationServerConnStatusIndMsgT_v02 conn_status_ind; 1172 1173 1174 LOC_LOGD("%s:%d]: ATL open handle = %d, is_succ = %d, " 1175 "APN = [%s], bearer = %d \n", __func__, __LINE__, 1176 handle, is_succ, apn, bear); 1177 1178 memset(&conn_status_req, 0, sizeof(conn_status_req)); 1179 memset(&conn_status_ind, 0, sizeof(conn_status_ind)); 1180 1181 // Fill in data 1182 conn_status_req.connHandle = handle; 1183 1184 conn_status_req.requestType = eQMI_LOC_SERVER_REQUEST_OPEN_V02; 1185 1186 if(is_succ) 1187 { 1188 conn_status_req.statusType = eQMI_LOC_SERVER_REQ_STATUS_SUCCESS_V02; 1189 1190 if(apn != NULL) 1191 strlcpy(conn_status_req.apnProfile.apnName, apn, 1192 sizeof(conn_status_req.apnProfile.apnName) ); 1193 1194 switch(bear) 1195 { 1196 case AGPS_APN_BEARER_IPV4: 1197 conn_status_req.apnProfile.pdnType = 1198 eQMI_LOC_APN_PROFILE_PDN_TYPE_IPV4_V02; 1199 conn_status_req.apnProfile_valid = 1; 1200 break; 1201 1202 case AGPS_APN_BEARER_IPV6: 1203 conn_status_req.apnProfile.pdnType = 1204 eQMI_LOC_APN_PROFILE_PDN_TYPE_IPV6_V02; 1205 conn_status_req.apnProfile_valid = 1; 1206 break; 1207 1208 case AGPS_APN_BEARER_IPV4V6: 1209 conn_status_req.apnProfile.pdnType = 1210 eQMI_LOC_APN_PROFILE_PDN_TYPE_IPV4V6_V02; 1211 conn_status_req.apnProfile_valid = 1; 1212 break; 1213 1214 case AGPS_APN_BEARER_INVALID: 1215 conn_status_req.apnProfile_valid = 0; 1216 break; 1217 1218 default: 1219 LOC_LOGE("%s:%d]:invalid bearer type\n",__func__,__LINE__); 1220 conn_status_req.apnProfile_valid = 0; 1221 return LOC_API_ADAPTER_ERR_INVALID_HANDLE; 1222 } 1223 1224 } 1225 else 1226 { 1227 conn_status_req.statusType = eQMI_LOC_SERVER_REQ_STATUS_FAILURE_V02; 1228 } 1229 1230 req_union.pInformLocationServerConnStatusReq = &conn_status_req; 1231 1232 result = loc_sync_send_req(clientHandle, 1233 QMI_LOC_INFORM_LOCATION_SERVER_CONN_STATUS_REQ_V02, 1234 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 1235 QMI_LOC_INFORM_LOCATION_SERVER_CONN_STATUS_IND_V02, 1236 &conn_status_ind); 1237 1238 if(result != eLOC_CLIENT_SUCCESS || 1239 eQMI_LOC_SUCCESS_V02 != conn_status_ind.status) 1240 { 1241 LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ", 1242 __func__, __LINE__, 1243 loc_get_v02_client_status_name(result), 1244 loc_get_v02_qmi_status_name(conn_status_ind.status)); 1245 } 1246 1247 return convertErr(result); 1248 1249 } 1250 1251 1252 /* close atl connection */ 1253 enum loc_api_adapter_err LocApiV02 :: atlCloseStatus( 1254 int handle, int is_succ) 1255 { 1256 locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; 1257 locClientReqUnionType req_union; 1258 qmiLocInformLocationServerConnStatusReqMsgT_v02 conn_status_req; 1259 qmiLocInformLocationServerConnStatusIndMsgT_v02 conn_status_ind; 1260 1261 LOC_LOGD("%s:%d]: ATL close handle = %d, is_succ = %d\n", 1262 __func__, __LINE__, handle, is_succ); 1263 1264 memset(&conn_status_req, 0, sizeof(conn_status_req)); 1265 memset(&conn_status_ind, 0, sizeof(conn_status_ind)); 1266 1267 // Fill in data 1268 conn_status_req.connHandle = handle; 1269 1270 conn_status_req.requestType = eQMI_LOC_SERVER_REQUEST_CLOSE_V02; 1271 1272 if(is_succ) 1273 { 1274 conn_status_req.statusType = eQMI_LOC_SERVER_REQ_STATUS_SUCCESS_V02; 1275 } 1276 else 1277 { 1278 conn_status_req.statusType = eQMI_LOC_SERVER_REQ_STATUS_FAILURE_V02; 1279 } 1280 1281 req_union.pInformLocationServerConnStatusReq = &conn_status_req; 1282 1283 result = loc_sync_send_req(clientHandle, 1284 QMI_LOC_INFORM_LOCATION_SERVER_CONN_STATUS_REQ_V02, 1285 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 1286 QMI_LOC_INFORM_LOCATION_SERVER_CONN_STATUS_IND_V02, 1287 &conn_status_ind); 1288 1289 if(result != eLOC_CLIENT_SUCCESS || 1290 eQMI_LOC_SUCCESS_V02 != conn_status_ind.status) 1291 { 1292 LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ", 1293 __func__, __LINE__, 1294 loc_get_v02_client_status_name(result), 1295 loc_get_v02_qmi_status_name(conn_status_ind.status)); 1296 } 1297 1298 return convertErr(result); 1299 } 1300 1301 /* set the SUPL version */ 1302 enum loc_api_adapter_err LocApiV02 :: setSUPLVersion(uint32_t version) 1303 { 1304 locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; 1305 locClientReqUnionType req_union; 1306 1307 qmiLocSetProtocolConfigParametersReqMsgT_v02 supl_config_req; 1308 qmiLocSetProtocolConfigParametersIndMsgT_v02 supl_config_ind; 1309 1310 LOC_LOGD("%s:%d]: supl version = %d\n", __func__, __LINE__, version); 1311 1312 1313 memset(&supl_config_req, 0, sizeof(supl_config_req)); 1314 memset(&supl_config_ind, 0, sizeof(supl_config_ind)); 1315 1316 supl_config_req.suplVersion_valid = 1; 1317 // SUPL version from MSByte to LSByte: 1318 // (reserved)(major version)(minor version)(serviceIndicator) 1319 1320 supl_config_req.suplVersion = (version == 0x00020000)? 1321 eQMI_LOC_SUPL_VERSION_2_0_V02 : eQMI_LOC_SUPL_VERSION_1_0_V02; 1322 1323 req_union.pSetProtocolConfigParametersReq = &supl_config_req; 1324 1325 result = loc_sync_send_req(clientHandle, 1326 QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_REQ_V02, 1327 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 1328 QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_IND_V02, 1329 &supl_config_ind); 1330 1331 if(result != eLOC_CLIENT_SUCCESS || 1332 eQMI_LOC_SUCCESS_V02 != supl_config_ind.status) 1333 { 1334 LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ", 1335 __func__, __LINE__, 1336 loc_get_v02_client_status_name(result), 1337 loc_get_v02_qmi_status_name(supl_config_ind.status)); 1338 } 1339 1340 return convertErr(result); 1341 } 1342 1343 /* set the configuration for LTE positioning profile (LPP) */ 1344 enum loc_api_adapter_err LocApiV02 :: setLPPConfig(uint32_t profile) 1345 { 1346 locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; 1347 locClientReqUnionType req_union; 1348 qmiLocSetProtocolConfigParametersReqMsgT_v02 lpp_config_req; 1349 qmiLocSetProtocolConfigParametersIndMsgT_v02 lpp_config_ind; 1350 1351 LOC_LOGD("%s:%d]: lpp profile = %d\n", __func__, __LINE__, profile); 1352 1353 memset(&lpp_config_req, 0, sizeof(lpp_config_req)); 1354 memset(&lpp_config_ind, 0, sizeof(lpp_config_ind)); 1355 1356 lpp_config_req.lppConfig_valid = 1; 1357 1358 lpp_config_req.lppConfig = profile; 1359 1360 req_union.pSetProtocolConfigParametersReq = &lpp_config_req; 1361 1362 result = loc_sync_send_req(clientHandle, 1363 QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_REQ_V02, 1364 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 1365 QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_IND_V02, 1366 &lpp_config_ind); 1367 1368 if(result != eLOC_CLIENT_SUCCESS || 1369 eQMI_LOC_SUCCESS_V02 != lpp_config_ind.status) 1370 { 1371 LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ", 1372 __func__, __LINE__, 1373 loc_get_v02_client_status_name(result), 1374 loc_get_v02_qmi_status_name(lpp_config_ind.status)); 1375 } 1376 1377 return convertErr(result); 1378 } 1379 1380 /* set the Sensor Configuration */ 1381 enum loc_api_adapter_err LocApiV02 :: setSensorControlConfig( 1382 int sensorsDisabled, int sensorProvider) 1383 { 1384 locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; 1385 locClientReqUnionType req_union; 1386 1387 qmiLocSetSensorControlConfigReqMsgT_v02 sensor_config_req; 1388 qmiLocSetSensorControlConfigIndMsgT_v02 sensor_config_ind; 1389 1390 LOC_LOGD("%s:%d]: sensors disabled = %d\n", __func__, __LINE__, sensorsDisabled); 1391 1392 memset(&sensor_config_req, 0, sizeof(sensor_config_req)); 1393 memset(&sensor_config_ind, 0, sizeof(sensor_config_ind)); 1394 1395 sensor_config_req.sensorsUsage_valid = 1; 1396 sensor_config_req.sensorsUsage = (sensorsDisabled == 1) ? eQMI_LOC_SENSOR_CONFIG_SENSOR_USE_DISABLE_V02 1397 : eQMI_LOC_SENSOR_CONFIG_SENSOR_USE_ENABLE_V02; 1398 1399 sensor_config_req.sensorProvider_valid = 1; 1400 sensor_config_req.sensorProvider = (sensorProvider == 1 || sensorProvider == 4) ? 1401 eQMI_LOC_SENSOR_CONFIG_USE_PROVIDER_SSC_V02 : 1402 eQMI_LOC_SENSOR_CONFIG_USE_PROVIDER_NATIVE_V02; 1403 1404 req_union.pSetSensorControlConfigReq = &sensor_config_req; 1405 1406 result = loc_sync_send_req(clientHandle, 1407 QMI_LOC_SET_SENSOR_CONTROL_CONFIG_REQ_V02, 1408 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 1409 QMI_LOC_SET_SENSOR_CONTROL_CONFIG_IND_V02, 1410 &sensor_config_ind); 1411 1412 if(result != eLOC_CLIENT_SUCCESS || 1413 eQMI_LOC_SUCCESS_V02 != sensor_config_ind.status) 1414 { 1415 LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ", 1416 __func__, __LINE__, 1417 loc_get_v02_client_status_name(result), 1418 loc_get_v02_qmi_status_name(sensor_config_ind.status)); 1419 } 1420 1421 return convertErr(result); 1422 } 1423 1424 /* set the Sensor Properties */ 1425 enum loc_api_adapter_err LocApiV02 :: setSensorProperties(bool gyroBiasVarianceRandomWalk_valid, float gyroBiasVarianceRandomWalk, 1426 bool accelBiasVarianceRandomWalk_valid, float accelBiasVarianceRandomWalk, 1427 bool angleBiasVarianceRandomWalk_valid, float angleBiasVarianceRandomWalk, 1428 bool rateBiasVarianceRandomWalk_valid, float rateBiasVarianceRandomWalk, 1429 bool velocityBiasVarianceRandomWalk_valid, float velocityBiasVarianceRandomWalk) 1430 { 1431 locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; 1432 locClientReqUnionType req_union; 1433 1434 qmiLocSetSensorPropertiesReqMsgT_v02 sensor_prop_req; 1435 qmiLocSetSensorPropertiesIndMsgT_v02 sensor_prop_ind; 1436 1437 LOC_LOGI("%s:%d]: sensors prop: gyroBiasRandomWalk = %f, accelRandomWalk = %f, " 1438 "angleRandomWalk = %f, rateRandomWalk = %f, velocityRandomWalk = %f\n", 1439 __func__, __LINE__, gyroBiasVarianceRandomWalk, accelBiasVarianceRandomWalk, 1440 angleBiasVarianceRandomWalk, rateBiasVarianceRandomWalk, velocityBiasVarianceRandomWalk); 1441 1442 memset(&sensor_prop_req, 0, sizeof(sensor_prop_req)); 1443 memset(&sensor_prop_ind, 0, sizeof(sensor_prop_ind)); 1444 1445 /* Set the validity bit and value for each sensor property */ 1446 sensor_prop_req.gyroBiasVarianceRandomWalk_valid = gyroBiasVarianceRandomWalk_valid; 1447 sensor_prop_req.gyroBiasVarianceRandomWalk = gyroBiasVarianceRandomWalk; 1448 1449 sensor_prop_req.accelerationRandomWalkSpectralDensity_valid = accelBiasVarianceRandomWalk_valid; 1450 sensor_prop_req.accelerationRandomWalkSpectralDensity = accelBiasVarianceRandomWalk; 1451 1452 sensor_prop_req.angleRandomWalkSpectralDensity_valid = angleBiasVarianceRandomWalk_valid; 1453 sensor_prop_req.angleRandomWalkSpectralDensity = angleBiasVarianceRandomWalk; 1454 1455 sensor_prop_req.rateRandomWalkSpectralDensity_valid = rateBiasVarianceRandomWalk_valid; 1456 sensor_prop_req.rateRandomWalkSpectralDensity = rateBiasVarianceRandomWalk; 1457 1458 sensor_prop_req.velocityRandomWalkSpectralDensity_valid = velocityBiasVarianceRandomWalk_valid; 1459 sensor_prop_req.velocityRandomWalkSpectralDensity = velocityBiasVarianceRandomWalk; 1460 1461 req_union.pSetSensorPropertiesReq = &sensor_prop_req; 1462 1463 result = loc_sync_send_req(clientHandle, 1464 QMI_LOC_SET_SENSOR_PROPERTIES_REQ_V02, 1465 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 1466 QMI_LOC_SET_SENSOR_PROPERTIES_IND_V02, 1467 &sensor_prop_ind); 1468 1469 if(result != eLOC_CLIENT_SUCCESS || 1470 eQMI_LOC_SUCCESS_V02 != sensor_prop_ind.status) 1471 { 1472 LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ", 1473 __func__, __LINE__, 1474 loc_get_v02_client_status_name(result), 1475 loc_get_v02_qmi_status_name(sensor_prop_ind.status)); 1476 } 1477 1478 return convertErr(result); 1479 } 1480 1481 /* set the Sensor Performance Config */ 1482 enum loc_api_adapter_err LocApiV02 :: setSensorPerfControlConfig(int controlMode, 1483 int accelSamplesPerBatch, int accelBatchesPerSec, 1484 int gyroSamplesPerBatch, int gyroBatchesPerSec, 1485 int accelSamplesPerBatchHigh, int accelBatchesPerSecHigh, 1486 int gyroSamplesPerBatchHigh, int gyroBatchesPerSecHigh, 1487 int algorithmConfig) 1488 { 1489 locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; 1490 locClientReqUnionType req_union; 1491 1492 qmiLocSetSensorPerformanceControlConfigReqMsgT_v02 sensor_perf_config_req; 1493 qmiLocSetSensorPerformanceControlConfigIndMsgT_v02 sensor_perf_config_ind; 1494 1495 LOC_LOGD("%s:%d]: Sensor Perf Control Config (performanceControlMode)(%u) " 1496 "accel(#smp,#batches) (%u,%u) gyro(#smp,#batches) (%u,%u) " 1497 "accel_high(#smp,#batches) (%u,%u) gyro_high(#smp,#batches) (%u,%u) " 1498 "algorithmConfig(%u)\n", 1499 __FUNCTION__, 1500 __LINE__, 1501 controlMode, 1502 accelSamplesPerBatch, 1503 accelBatchesPerSec, 1504 gyroSamplesPerBatch, 1505 gyroBatchesPerSec, 1506 accelSamplesPerBatchHigh, 1507 accelBatchesPerSecHigh, 1508 gyroSamplesPerBatchHigh, 1509 gyroBatchesPerSecHigh, 1510 algorithmConfig 1511 ); 1512 1513 memset(&sensor_perf_config_req, 0, sizeof(sensor_perf_config_req)); 1514 memset(&sensor_perf_config_ind, 0, sizeof(sensor_perf_config_ind)); 1515 1516 sensor_perf_config_req.performanceControlMode_valid = 1; 1517 sensor_perf_config_req.performanceControlMode = (qmiLocSensorPerformanceControlModeEnumT_v02)controlMode; 1518 sensor_perf_config_req.accelSamplingSpec_valid = 1; 1519 sensor_perf_config_req.accelSamplingSpec.batchesPerSecond = accelBatchesPerSec; 1520 sensor_perf_config_req.accelSamplingSpec.samplesPerBatch = accelSamplesPerBatch; 1521 sensor_perf_config_req.gyroSamplingSpec_valid = 1; 1522 sensor_perf_config_req.gyroSamplingSpec.batchesPerSecond = gyroBatchesPerSec; 1523 sensor_perf_config_req.gyroSamplingSpec.samplesPerBatch = gyroSamplesPerBatch; 1524 sensor_perf_config_req.accelSamplingSpecHigh_valid = 1; 1525 sensor_perf_config_req.accelSamplingSpecHigh.batchesPerSecond = accelBatchesPerSecHigh; 1526 sensor_perf_config_req.accelSamplingSpecHigh.samplesPerBatch = accelSamplesPerBatchHigh; 1527 sensor_perf_config_req.gyroSamplingSpecHigh_valid = 1; 1528 sensor_perf_config_req.gyroSamplingSpecHigh.batchesPerSecond = gyroBatchesPerSecHigh; 1529 sensor_perf_config_req.gyroSamplingSpecHigh.samplesPerBatch = gyroSamplesPerBatchHigh; 1530 sensor_perf_config_req.algorithmConfig_valid = 1; 1531 sensor_perf_config_req.algorithmConfig = algorithmConfig; 1532 1533 req_union.pSetSensorPerformanceControlConfigReq = &sensor_perf_config_req; 1534 1535 result = loc_sync_send_req(clientHandle, 1536 QMI_LOC_SET_SENSOR_PERFORMANCE_CONTROL_CONFIGURATION_REQ_V02, 1537 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 1538 QMI_LOC_SET_SENSOR_PERFORMANCE_CONTROL_CONFIGURATION_IND_V02, 1539 &sensor_perf_config_ind); 1540 1541 if(result != eLOC_CLIENT_SUCCESS || 1542 eQMI_LOC_SUCCESS_V02 != sensor_perf_config_ind.status) 1543 { 1544 LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ", 1545 __func__, __LINE__, 1546 loc_get_v02_client_status_name(result), 1547 loc_get_v02_qmi_status_name(sensor_perf_config_ind.status)); 1548 } 1549 1550 return convertErr(result); 1551 } 1552 1553 /* set the External Power Config */ 1554 enum loc_api_adapter_err LocApiV02 :: setExtPowerConfig(int isBatteryCharging) 1555 { 1556 locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; 1557 locClientReqUnionType req_union; 1558 1559 qmiLocSetExternalPowerConfigReqMsgT_v02 ext_pwr_req; 1560 qmiLocGetExternalPowerConfigIndMsgT_v02 ext_pwr_ind; 1561 1562 LOC_LOGI("%s:%d]: Ext Pwr Config (isBatteryCharging)(%u)", 1563 __FUNCTION__, 1564 __LINE__, 1565 isBatteryCharging 1566 ); 1567 1568 memset(&ext_pwr_req, 0, sizeof(ext_pwr_req)); 1569 memset(&ext_pwr_ind, 0, sizeof(ext_pwr_ind)); 1570 1571 switch(isBatteryCharging) 1572 { 1573 /* Charging */ 1574 case 1: 1575 ext_pwr_req.externalPowerState = eQMI_LOC_EXTERNAL_POWER_CONNECTED_V02; 1576 break; 1577 1578 /* Not charging */ 1579 case 0: 1580 ext_pwr_req.externalPowerState = eQMI_LOC_EXTERNAL_POWER_NOT_CONNECTED_V02; 1581 break; 1582 1583 default: 1584 LOC_LOGE("%s:%d]: Invalid ext power state = %d!", 1585 __FUNCTION__, 1586 __LINE__, 1587 isBatteryCharging); 1588 return LOC_API_ADAPTER_ERR_INVALID_PARAMETER; 1589 break; 1590 } 1591 1592 req_union.pSetExternalPowerConfigReq = &ext_pwr_req; 1593 1594 result = loc_sync_send_req(clientHandle, 1595 QMI_LOC_SET_EXTERNAL_POWER_CONFIG_REQ_V02, 1596 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 1597 QMI_LOC_SET_EXTERNAL_POWER_CONFIG_IND_V02, 1598 &ext_pwr_ind); 1599 1600 if(result != eLOC_CLIENT_SUCCESS || 1601 eQMI_LOC_SUCCESS_V02 != ext_pwr_ind.status) 1602 { 1603 LOC_LOGE ("%s:%d]: Error status = %d, ind..status = %d ", 1604 __func__, __LINE__, result, ext_pwr_ind.status); 1605 } 1606 1607 return convertErr(result); 1608 } 1609 1610 /* set the Positioning Protocol on A-GLONASS system */ 1611 enum loc_api_adapter_err LocApiV02 :: setAGLONASSProtocol(unsigned long aGlonassProtocol) 1612 { 1613 locClientStatusEnumType result = eLOC_CLIENT_SUCCESS; 1614 locClientReqUnionType req_union; 1615 qmiLocSetProtocolConfigParametersReqMsgT_v02 aGlonassProtocol_req; 1616 qmiLocSetProtocolConfigParametersIndMsgT_v02 aGlonassProtocol_ind; 1617 1618 memset(&aGlonassProtocol_req, 0, sizeof(aGlonassProtocol_req)); 1619 memset(&aGlonassProtocol_ind, 0, sizeof(aGlonassProtocol_ind)); 1620 1621 aGlonassProtocol_req.assistedGlonassProtocolMask_valid = 1; 1622 aGlonassProtocol_req.assistedGlonassProtocolMask = aGlonassProtocol; 1623 1624 req_union.pSetProtocolConfigParametersReq = &aGlonassProtocol_req; 1625 1626 LOC_LOGD("%s:%d]: aGlonassProtocolMask = 0x%x\n", __func__, __LINE__, 1627 aGlonassProtocol_req.assistedGlonassProtocolMask); 1628 1629 result = loc_sync_send_req(clientHandle, 1630 QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_REQ_V02, 1631 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 1632 QMI_LOC_SET_PROTOCOL_CONFIG_PARAMETERS_IND_V02, 1633 &aGlonassProtocol_ind); 1634 1635 if(result != eLOC_CLIENT_SUCCESS || 1636 eQMI_LOC_SUCCESS_V02 != aGlonassProtocol_ind.status) 1637 { 1638 LOC_LOGE ("%s:%d]: Error status = %s, ind..status = %s ", 1639 __func__, __LINE__, 1640 loc_get_v02_client_status_name(result), 1641 loc_get_v02_qmi_status_name(aGlonassProtocol_ind.status)); 1642 } 1643 1644 return convertErr(result); 1645 } 1646 1647 /* Convert event mask from loc eng to loc_api_v02 format */ 1648 locClientEventMaskType LocApiV02 :: convertMask( 1649 LOC_API_ADAPTER_EVENT_MASK_T mask) 1650 { 1651 locClientEventMaskType eventMask = 0; 1652 LOC_LOGD("%s:%d]: adapter mask = %u\n", __func__, __LINE__, mask); 1653 1654 if (mask & LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT) 1655 eventMask |= QMI_LOC_EVENT_MASK_POSITION_REPORT_V02; 1656 1657 if (mask & LOC_API_ADAPTER_BIT_SATELLITE_REPORT) 1658 eventMask |= QMI_LOC_EVENT_MASK_GNSS_SV_INFO_V02; 1659 1660 /* treat NMEA_1Hz and NMEA_POSITION_REPORT the same*/ 1661 if ((mask & LOC_API_ADAPTER_BIT_NMEA_POSITION_REPORT) || 1662 (mask & LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT) ) 1663 eventMask |= QMI_LOC_EVENT_MASK_NMEA_V02; 1664 1665 if (mask & LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST) 1666 eventMask |= QMI_LOC_EVENT_MASK_NI_NOTIFY_VERIFY_REQ_V02; 1667 1668 if (mask & LOC_API_ADAPTER_BIT_ASSISTANCE_DATA_REQUEST) 1669 { 1670 // TBD: This needs to be decoupled in the HAL 1671 eventMask |= QMI_LOC_EVENT_MASK_INJECT_PREDICTED_ORBITS_REQ_V02; 1672 eventMask |= QMI_LOC_EVENT_MASK_INJECT_TIME_REQ_V02; 1673 eventMask |= QMI_LOC_EVENT_MASK_INJECT_POSITION_REQ_V02; 1674 } 1675 1676 if (mask & LOC_API_ADAPTER_BIT_STATUS_REPORT) 1677 { 1678 eventMask |= (QMI_LOC_EVENT_MASK_ENGINE_STATE_V02); 1679 } 1680 1681 if (mask & LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST) 1682 eventMask |= QMI_LOC_EVENT_MASK_LOCATION_SERVER_CONNECTION_REQ_V02; 1683 1684 if (mask & LOC_API_ADAPTER_BIT_REQUEST_WIFI) 1685 eventMask |= QMI_LOC_EVENT_MASK_WIFI_REQ_V02; 1686 1687 if (mask & LOC_API_ADAPTER_BIT_SENSOR_STATUS) 1688 eventMask |= QMI_LOC_EVENT_MASK_SENSOR_STREAMING_READY_STATUS_V02; 1689 1690 if (mask & LOC_API_ADAPTER_BIT_REQUEST_TIME_SYNC) 1691 eventMask |= QMI_LOC_EVENT_MASK_TIME_SYNC_REQ_V02; 1692 1693 if (mask & LOC_API_ADAPTER_BIT_REPORT_SPI) 1694 eventMask |= QMI_LOC_EVENT_MASK_SET_SPI_STREAMING_REPORT_V02; 1695 1696 if (mask & LOC_API_ADAPTER_BIT_REPORT_NI_GEOFENCE) 1697 eventMask |= QMI_LOC_EVENT_MASK_NI_GEOFENCE_NOTIFICATION_V02; 1698 1699 if (mask & LOC_API_ADAPTER_BIT_GEOFENCE_GEN_ALERT) 1700 eventMask |= QMI_LOC_EVENT_MASK_GEOFENCE_GEN_ALERT_V02; 1701 1702 if (mask & LOC_API_ADAPTER_BIT_REPORT_GENFENCE_BREACH) 1703 eventMask |= QMI_LOC_EVENT_MASK_GEOFENCE_BREACH_NOTIFICATION_V02; 1704 1705 if (mask & LOC_API_ADAPTER_BIT_BATCHED_GENFENCE_BREACH_REPORT) 1706 eventMask |= QMI_LOC_EVENT_MASK_GEOFENCE_BATCH_BREACH_NOTIFICATION_V02; 1707 1708 if (mask & LOC_API_ADAPTER_BIT_REPORT_GENFENCE_DWELL) 1709 eventMask |= QMI_LOC_EVENT_MASK_GEOFENCE_BATCH_DWELL_NOTIFICATION_V02; 1710 1711 if (mask & LOC_API_ADAPTER_BIT_PEDOMETER_CTRL) 1712 eventMask |= QMI_LOC_EVENT_MASK_PEDOMETER_CONTROL_V02; 1713 1714 if (mask & LOC_API_ADAPTER_BIT_MOTION_CTRL) 1715 eventMask |= QMI_LOC_EVENT_MASK_MOTION_DATA_CONTROL_V02; 1716 1717 if (mask & LOC_API_ADAPTER_BIT_REQUEST_WIFI_AP_DATA) 1718 eventMask |= QMI_LOC_EVENT_MASK_INJECT_WIFI_AP_DATA_REQ_V02; 1719 1720 if(mask & LOC_API_ADAPTER_BIT_BATCH_FULL) 1721 eventMask |= QMI_LOC_EVENT_MASK_BATCH_FULL_NOTIFICATION_V02; 1722 1723 if(mask & LOC_API_ADAPTER_BIT_BATCHED_POSITION_REPORT) 1724 eventMask |= QMI_LOC_EVENT_MASK_LIVE_BATCHED_POSITION_REPORT_V02; 1725 1726 // for GDT 1727 if(mask & LOC_API_ADAPTER_BIT_GDT_UPLOAD_BEGIN_REQ) 1728 eventMask |= QMI_LOC_EVENT_MASK_GDT_UPLOAD_BEGIN_REQ_V02; 1729 1730 if(mask & LOC_API_ADAPTER_BIT_GDT_UPLOAD_END_REQ) 1731 eventMask |= QMI_LOC_EVENT_MASK_GDT_UPLOAD_END_REQ_V02; 1732 1733 if (mask & LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT) 1734 eventMask |= QMI_LOC_EVENT_MASK_GNSS_MEASUREMENT_REPORT_V02; 1735 1736 if(mask & LOC_API_ADAPTER_BIT_REQUEST_TIMEZONE) 1737 eventMask |= QMI_LOC_EVENT_MASK_GET_TIME_ZONE_REQ_V02; 1738 return eventMask; 1739 } 1740 1741 qmiLocLockEnumT_v02 LocApiV02 :: convertGpsLockMask(LOC_GPS_LOCK_MASK lockMask) 1742 { 1743 /* GPS HAL uses power voting through GPS Lock mask. 1744 When QCA1530 daemon is present two values are used: 101 and 103.*/ 1745 if ( 101 == lockMask || 103 == lockMask ) 1746 { 1747 return (qmiLocLockEnumT_v02)lockMask; 1748 } 1749 if (isGpsLockAll(lockMask)) 1750 return eQMI_LOC_LOCK_ALL_V02; 1751 if (isGpsLockMO(lockMask)) 1752 return eQMI_LOC_LOCK_MI_V02; 1753 if (isGpsLockMT(lockMask)) 1754 return eQMI_LOC_LOCK_MT_V02; 1755 if (isGpsLockNone(lockMask)) 1756 return eQMI_LOC_LOCK_NONE_V02; 1757 return (qmiLocLockEnumT_v02)lockMask; 1758 } 1759 1760 /* Convert error from loc_api_v02 to loc eng format*/ 1761 enum loc_api_adapter_err LocApiV02 :: convertErr( 1762 locClientStatusEnumType status) 1763 { 1764 switch( status) 1765 { 1766 case eLOC_CLIENT_SUCCESS: 1767 return LOC_API_ADAPTER_ERR_SUCCESS; 1768 1769 case eLOC_CLIENT_FAILURE_GENERAL: 1770 return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; 1771 1772 case eLOC_CLIENT_FAILURE_UNSUPPORTED: 1773 return LOC_API_ADAPTER_ERR_UNSUPPORTED; 1774 1775 case eLOC_CLIENT_FAILURE_INVALID_PARAMETER: 1776 return LOC_API_ADAPTER_ERR_INVALID_PARAMETER; 1777 1778 case eLOC_CLIENT_FAILURE_ENGINE_BUSY: 1779 return LOC_API_ADAPTER_ERR_ENGINE_BUSY; 1780 1781 case eLOC_CLIENT_FAILURE_PHONE_OFFLINE: 1782 return LOC_API_ADAPTER_ERR_PHONE_OFFLINE; 1783 1784 case eLOC_CLIENT_FAILURE_TIMEOUT: 1785 return LOC_API_ADAPTER_ERR_TIMEOUT; 1786 1787 case eLOC_CLIENT_FAILURE_INVALID_HANDLE: 1788 return LOC_API_ADAPTER_ERR_INVALID_HANDLE; 1789 1790 case eLOC_CLIENT_FAILURE_SERVICE_NOT_PRESENT: 1791 return LOC_API_ADAPTER_ERR_SERVICE_NOT_PRESENT; 1792 1793 case eLOC_CLIENT_FAILURE_INTERNAL: 1794 return LOC_API_ADAPTER_ERR_INTERNAL; 1795 1796 default: 1797 return LOC_API_ADAPTER_ERR_FAILURE; 1798 } 1799 } 1800 1801 /* convert position report to loc eng format and send the converted 1802 position to loc eng */ 1803 1804 void LocApiV02 :: reportPosition ( 1805 const qmiLocEventPositionReportIndMsgT_v02 *location_report_ptr) 1806 { 1807 UlpLocation location; 1808 LocPosTechMask tech_Mask = LOC_POS_TECH_MASK_DEFAULT; 1809 LOC_LOGD("Reporting position from V2 Adapter\n"); 1810 memset(&location, 0, sizeof (UlpLocation)); 1811 location.size = sizeof(location); 1812 GpsLocationExtended locationExtended; 1813 memset(&locationExtended, 0, sizeof (GpsLocationExtended)); 1814 locationExtended.size = sizeof(locationExtended); 1815 // Process the position from final and intermediate reports 1816 1817 if( (location_report_ptr->sessionStatus == eQMI_LOC_SESS_STATUS_SUCCESS_V02) || 1818 (location_report_ptr->sessionStatus == eQMI_LOC_SESS_STATUS_IN_PROGRESS_V02) 1819 ) 1820 { 1821 // Latitude & Longitude 1822 if( (1 == location_report_ptr->latitude_valid) && 1823 (1 == location_report_ptr->longitude_valid)) 1824 { 1825 location.gpsLocation.flags |= GPS_LOCATION_HAS_LAT_LONG; 1826 location.gpsLocation.latitude = location_report_ptr->latitude; 1827 location.gpsLocation.longitude = location_report_ptr->longitude; 1828 1829 // Time stamp (UTC) 1830 if(location_report_ptr->timestampUtc_valid == 1) 1831 { 1832 location.gpsLocation.timestamp = location_report_ptr->timestampUtc; 1833 } 1834 1835 // Altitude 1836 if(location_report_ptr->altitudeWrtEllipsoid_valid == 1 ) 1837 { 1838 location.gpsLocation.flags |= GPS_LOCATION_HAS_ALTITUDE; 1839 location.gpsLocation.altitude = location_report_ptr->altitudeWrtEllipsoid; 1840 } 1841 1842 // Speed 1843 if(location_report_ptr->speedHorizontal_valid == 1) 1844 { 1845 location.gpsLocation.flags |= GPS_LOCATION_HAS_SPEED; 1846 location.gpsLocation.speed = location_report_ptr->speedHorizontal; 1847 } 1848 1849 // Heading 1850 if(location_report_ptr->heading_valid == 1) 1851 { 1852 location.gpsLocation.flags |= GPS_LOCATION_HAS_BEARING; 1853 location.gpsLocation.bearing = location_report_ptr->heading; 1854 } 1855 1856 // Uncertainty (circular) 1857 if (location_report_ptr->horUncCircular_valid) { 1858 location.gpsLocation.flags |= GPS_LOCATION_HAS_ACCURACY; 1859 location.gpsLocation.accuracy = location_report_ptr->horUncCircular; 1860 } else if (location_report_ptr->horUncEllipseSemiMinor_valid && 1861 location_report_ptr->horUncEllipseSemiMajor_valid) { 1862 location.gpsLocation.flags |= GPS_LOCATION_HAS_ACCURACY; 1863 location.gpsLocation.accuracy = 1864 sqrt((location_report_ptr->horUncEllipseSemiMinor * 1865 location_report_ptr->horUncEllipseSemiMinor) + 1866 (location_report_ptr->horUncEllipseSemiMajor * 1867 location_report_ptr->horUncEllipseSemiMajor)); 1868 } 1869 1870 // Technology Mask 1871 tech_Mask |= location_report_ptr->technologyMask; 1872 1873 //Mark the location source as from GNSS 1874 location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO; 1875 location.position_source = ULP_LOCATION_IS_FROM_GNSS; 1876 if (location_report_ptr->magneticDeviation_valid) 1877 { 1878 locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_MAG_DEV; 1879 locationExtended.magneticDeviation = location_report_ptr->magneticDeviation; 1880 } 1881 1882 if (location_report_ptr->DOP_valid) 1883 { 1884 locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_DOP; 1885 locationExtended.pdop = location_report_ptr->DOP.PDOP; 1886 locationExtended.hdop = location_report_ptr->DOP.HDOP; 1887 locationExtended.vdop = location_report_ptr->DOP.VDOP; 1888 } 1889 1890 if (location_report_ptr->altitudeWrtMeanSeaLevel_valid) 1891 { 1892 locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL; 1893 locationExtended.altitudeMeanSeaLevel = location_report_ptr->altitudeWrtMeanSeaLevel; 1894 } 1895 1896 if (location_report_ptr->vertUnc_valid) 1897 { 1898 locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_VERT_UNC; 1899 locationExtended.vert_unc = location_report_ptr->vertUnc; 1900 } 1901 1902 if (location_report_ptr->speedUnc_valid) 1903 { 1904 locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_SPEED_UNC; 1905 locationExtended.speed_unc = location_report_ptr->speedUnc; 1906 } 1907 if (location_report_ptr->headingUnc_valid) 1908 { 1909 locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_BEARING_UNC; 1910 locationExtended.bearing_unc = location_report_ptr->headingUnc; 1911 } 1912 if (location_report_ptr->horReliability_valid) 1913 { 1914 locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY; 1915 switch(location_report_ptr->horReliability) 1916 { 1917 case eQMI_LOC_RELIABILITY_NOT_SET_V02 : 1918 locationExtended.horizontal_reliability = LOC_RELIABILITY_NOT_SET; 1919 break; 1920 case eQMI_LOC_RELIABILITY_VERY_LOW_V02 : 1921 locationExtended.horizontal_reliability = LOC_RELIABILITY_VERY_LOW; 1922 break; 1923 case eQMI_LOC_RELIABILITY_LOW_V02 : 1924 locationExtended.horizontal_reliability = LOC_RELIABILITY_LOW; 1925 break; 1926 case eQMI_LOC_RELIABILITY_MEDIUM_V02 : 1927 locationExtended.horizontal_reliability = LOC_RELIABILITY_MEDIUM; 1928 break; 1929 case eQMI_LOC_RELIABILITY_HIGH_V02 : 1930 locationExtended.horizontal_reliability = LOC_RELIABILITY_HIGH; 1931 break; 1932 default: 1933 locationExtended.horizontal_reliability = LOC_RELIABILITY_NOT_SET; 1934 break; 1935 } 1936 } 1937 if (location_report_ptr->vertReliability_valid) 1938 { 1939 locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY; 1940 switch(location_report_ptr->vertReliability) 1941 { 1942 case eQMI_LOC_RELIABILITY_NOT_SET_V02 : 1943 locationExtended.vertical_reliability = LOC_RELIABILITY_NOT_SET; 1944 break; 1945 case eQMI_LOC_RELIABILITY_VERY_LOW_V02 : 1946 locationExtended.vertical_reliability = LOC_RELIABILITY_VERY_LOW; 1947 break; 1948 case eQMI_LOC_RELIABILITY_LOW_V02 : 1949 locationExtended.vertical_reliability = LOC_RELIABILITY_LOW; 1950 break; 1951 case eQMI_LOC_RELIABILITY_MEDIUM_V02 : 1952 locationExtended.vertical_reliability = LOC_RELIABILITY_MEDIUM; 1953 break; 1954 case eQMI_LOC_RELIABILITY_HIGH_V02 : 1955 locationExtended.vertical_reliability = LOC_RELIABILITY_HIGH; 1956 break; 1957 default: 1958 locationExtended.vertical_reliability = LOC_RELIABILITY_NOT_SET; 1959 break; 1960 } 1961 } 1962 1963 if((0 == location_report_ptr->latitude) && 1964 (0 == location_report_ptr->latitude) && 1965 (1 == location_report_ptr->horReliability_valid) && 1966 (eQMI_LOC_RELIABILITY_NOT_SET_V02 == 1967 location_report_ptr->horReliability)) 1968 { 1969 /*Only BlankNMEA sentence needs to be processed and sent, position 1970 * shall not be sent to framework if both lat,long is 0 & horReliability 1971 * not set, hence we report session failure status */ 1972 LocApiBase::reportPosition( location, 1973 locationExtended, 1974 (void*)location_report_ptr, 1975 LOC_SESS_FAILURE, 1976 tech_Mask); 1977 } 1978 else 1979 { 1980 LocApiBase::reportPosition( location, 1981 locationExtended, 1982 (void*)location_report_ptr, 1983 (location_report_ptr->sessionStatus 1984 == eQMI_LOC_SESS_STATUS_IN_PROGRESS_V02 ? 1985 LOC_SESS_INTERMEDIATE : LOC_SESS_SUCCESS), 1986 tech_Mask); 1987 } 1988 } 1989 } 1990 else 1991 { 1992 LocApiBase::reportPosition(location, 1993 locationExtended, 1994 NULL, 1995 LOC_SESS_FAILURE); 1996 1997 LOC_LOGD("%s:%d]: Ignoring position report with sess status = %d, " 1998 "fix id = %u\n", __func__, __LINE__, 1999 location_report_ptr->sessionStatus, 2000 location_report_ptr->fixId ); 2001 } 2002 } 2003 2004 /* convert satellite report to loc eng format and send the converted 2005 report to loc eng */ 2006 void LocApiV02 :: reportSv ( 2007 const qmiLocEventGnssSvInfoIndMsgT_v02 *gnss_report_ptr) 2008 { 2009 GnssSvStatus SvStatus; 2010 GpsLocationExtended locationExtended; 2011 int num_svs_max, i; 2012 const qmiLocSvInfoStructT_v02 *sv_info_ptr; 2013 2014 LOC_LOGV ("%s:%d]: num of sv = %d, validity = %d, altitude assumed = %u \n", 2015 __func__, __LINE__, gnss_report_ptr->svList_len, 2016 gnss_report_ptr->svList_valid, 2017 gnss_report_ptr->altitudeAssumed); 2018 2019 num_svs_max = 0; 2020 memset (&SvStatus, 0, sizeof (GnssSvStatus)); 2021 memset(&locationExtended, 0, sizeof (GpsLocationExtended)); 2022 2023 SvStatus.size = sizeof(GnssSvStatus); 2024 locationExtended.size = sizeof(locationExtended); 2025 if(gnss_report_ptr->svList_valid == 1) 2026 { 2027 num_svs_max = gnss_report_ptr->svList_len; 2028 if(num_svs_max > GNSS_MAX_SVS) 2029 { 2030 num_svs_max = GNSS_MAX_SVS; 2031 } 2032 SvStatus.num_svs = 0; 2033 for(i = 0; i < num_svs_max; i++) 2034 { 2035 sv_info_ptr = &(gnss_report_ptr->svList[i]); 2036 if((sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_SYSTEM_V02) && 2037 (sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_GNSS_SVID_V02) 2038 && (sv_info_ptr->gnssSvId != 0 )) 2039 { 2040 GnssSvFlags flags = GNSS_SV_FLAGS_NONE; 2041 2042 SvStatus.gnss_sv_list[SvStatus.num_svs].size = sizeof(GnssSvInfo); 2043 switch (sv_info_ptr->system) 2044 { 2045 case eQMI_LOC_SV_SYSTEM_GPS_V02: 2046 SvStatus.gnss_sv_list[SvStatus.num_svs].svid = sv_info_ptr->gnssSvId; 2047 SvStatus.gnss_sv_list[SvStatus.num_svs].constellation = GNSS_CONSTELLATION_GPS; 2048 break; 2049 2050 case eQMI_LOC_SV_SYSTEM_GALILEO_V02: 2051 SvStatus.gnss_sv_list[SvStatus.num_svs].svid = sv_info_ptr->gnssSvId-300; 2052 SvStatus.gnss_sv_list[SvStatus.num_svs].constellation = GNSS_CONSTELLATION_GALILEO; 2053 break; 2054 2055 case eQMI_LOC_SV_SYSTEM_SBAS_V02: 2056 SvStatus.gnss_sv_list[SvStatus.num_svs].svid = sv_info_ptr->gnssSvId; 2057 SvStatus.gnss_sv_list[SvStatus.num_svs].constellation = GNSS_CONSTELLATION_SBAS; 2058 break; 2059 2060 case eQMI_LOC_SV_SYSTEM_GLONASS_V02: 2061 SvStatus.gnss_sv_list[SvStatus.num_svs].svid = sv_info_ptr->gnssSvId; 2062 SvStatus.gnss_sv_list[SvStatus.num_svs].constellation = GNSS_CONSTELLATION_GLONASS; 2063 break; 2064 2065 case eQMI_LOC_SV_SYSTEM_BDS_V02: 2066 SvStatus.gnss_sv_list[SvStatus.num_svs].svid = sv_info_ptr->gnssSvId - 200; 2067 SvStatus.gnss_sv_list[SvStatus.num_svs].constellation = GNSS_CONSTELLATION_BEIDOU; 2068 break; 2069 2070 case eQMI_LOC_SV_SYSTEM_QZSS_V02: 2071 SvStatus.gnss_sv_list[SvStatus.num_svs].svid = sv_info_ptr->gnssSvId; 2072 SvStatus.gnss_sv_list[SvStatus.num_svs].constellation = GNSS_CONSTELLATION_QZSS; 2073 break; 2074 2075 case eQMI_LOC_SV_SYSTEM_COMPASS_V02: 2076 default: 2077 SvStatus.gnss_sv_list[SvStatus.num_svs].svid = sv_info_ptr->gnssSvId; 2078 SvStatus.gnss_sv_list[SvStatus.num_svs].constellation = GNSS_CONSTELLATION_UNKNOWN; 2079 break; 2080 } 2081 2082 if (sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_SNR_V02) 2083 { 2084 SvStatus.gnss_sv_list[SvStatus.num_svs].c_n0_dbhz = sv_info_ptr->snr; 2085 } 2086 2087 if (sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_ELEVATION_V02) 2088 { 2089 SvStatus.gnss_sv_list[SvStatus.num_svs].elevation = sv_info_ptr->elevation; 2090 } 2091 2092 if (sv_info_ptr->validMask & QMI_LOC_SV_INFO_MASK_VALID_AZIMUTH_V02) 2093 { 2094 SvStatus.gnss_sv_list[SvStatus.num_svs].azimuth = sv_info_ptr->azimuth; 2095 } 2096 2097 if (sv_info_ptr->validMask & 2098 QMI_LOC_SV_INFO_MASK_VALID_SVINFO_MASK_V02) 2099 { 2100 if (sv_info_ptr->svInfoMask & 2101 QMI_LOC_SVINFO_MASK_HAS_EPHEMERIS_V02) 2102 { 2103 flags |= GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA; 2104 } 2105 if (sv_info_ptr->svInfoMask & 2106 QMI_LOC_SVINFO_MASK_HAS_ALMANAC_V02) 2107 { 2108 flags |= GNSS_SV_FLAGS_HAS_ALMANAC_DATA; 2109 } 2110 } 2111 2112 /* Even if modem stops tracking some SVs, it reports them in the measurement 2113 report with Ephermeris/Alamanac data with 0 SNR. So in addition to check for 2114 availability of Alm or Eph data, also check for SNR > 0 to indicate SV is 2115 used in fix. */ 2116 if ((sv_info_ptr->validMask & 2117 QMI_LOC_SV_INFO_MASK_VALID_PROCESS_STATUS_V02) 2118 && 2119 (sv_info_ptr->svStatus == eQMI_LOC_SV_STATUS_TRACK_V02) 2120 && 2121 (sv_info_ptr->snr > 0) 2122 && 2123 ((flags & GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA)||(flags & GNSS_SV_FLAGS_HAS_ALMANAC_DATA))) 2124 { 2125 flags |= GNSS_SV_FLAGS_USED_IN_FIX; 2126 } 2127 2128 SvStatus.gnss_sv_list[SvStatus.num_svs].flags = flags; 2129 2130 SvStatus.num_svs++; 2131 } 2132 } 2133 } 2134 2135 if (SvStatus.num_svs >= 0) 2136 { 2137 LOC_LOGV ("%s:%d]: firing SV callback\n", __func__, __LINE__); 2138 LocApiBase::reportSv(SvStatus, 2139 locationExtended, 2140 (void*)gnss_report_ptr); 2141 } 2142 } 2143 2144 /* convert engine state report to loc eng format and send the converted 2145 report to loc eng */ 2146 void LocApiV02 :: reportEngineState ( 2147 const qmiLocEventEngineStateIndMsgT_v02 *engine_state_ptr) 2148 { 2149 2150 LOC_LOGV("%s:%d]: state = %d\n", __func__, __LINE__, 2151 engine_state_ptr->engineState); 2152 2153 struct MsgUpdateEngineState : public LocMsg { 2154 LocApiV02* mpLocApiV02; 2155 bool mEngineOn; 2156 inline MsgUpdateEngineState(LocApiV02* pLocApiV02, bool engineOn) : 2157 LocMsg(), mpLocApiV02(pLocApiV02), mEngineOn(engineOn) {} 2158 inline virtual void proc() const { 2159 // If EngineOn is true and InSession is false and Engine is just turned off, 2160 // then unregister the gps tracking specific event masks 2161 if (mpLocApiV02->mEngineOn && !mpLocApiV02->mInSession && !mEngineOn) { 2162 mpLocApiV02->registerEventMask(mpLocApiV02->mQmiMask); 2163 } 2164 mpLocApiV02->mEngineOn = mEngineOn; 2165 2166 if (mEngineOn) { 2167 // if EngineOn and not InSession, then we have already stopped 2168 // the fix, so do not send ENGINE_ON 2169 if (mpLocApiV02->mInSession) { 2170 mpLocApiV02->reportStatus(GPS_STATUS_ENGINE_ON); 2171 mpLocApiV02->reportStatus(GPS_STATUS_SESSION_BEGIN); 2172 } 2173 } else { 2174 mpLocApiV02->reportStatus(GPS_STATUS_SESSION_END); 2175 mpLocApiV02->reportStatus(GPS_STATUS_ENGINE_OFF); 2176 } 2177 } 2178 }; 2179 2180 if (engine_state_ptr->engineState == eQMI_LOC_ENGINE_STATE_ON_V02) 2181 { 2182 sendMsg(new MsgUpdateEngineState(this, true)); 2183 } 2184 else if (engine_state_ptr->engineState == eQMI_LOC_ENGINE_STATE_OFF_V02) 2185 { 2186 sendMsg(new MsgUpdateEngineState(this, false)); 2187 } 2188 else 2189 { 2190 reportStatus(GPS_STATUS_NONE); 2191 } 2192 2193 } 2194 2195 /* convert fix session state report to loc eng format and send the converted 2196 report to loc eng */ 2197 void LocApiV02 :: reportFixSessionState ( 2198 const qmiLocEventFixSessionStateIndMsgT_v02 *fix_session_state_ptr) 2199 { 2200 GpsStatusValue status; 2201 LOC_LOGD("%s:%d]: state = %d\n", __func__, __LINE__, 2202 fix_session_state_ptr->sessionState); 2203 2204 status = GPS_STATUS_NONE; 2205 if (fix_session_state_ptr->sessionState == eQMI_LOC_FIX_SESSION_STARTED_V02) 2206 { 2207 status = GPS_STATUS_SESSION_BEGIN; 2208 } 2209 else if (fix_session_state_ptr->sessionState 2210 == eQMI_LOC_FIX_SESSION_FINISHED_V02) 2211 { 2212 status = GPS_STATUS_SESSION_END; 2213 } 2214 reportStatus(status); 2215 } 2216 2217 /* convert NMEA report to loc eng format and send the converted 2218 report to loc eng */ 2219 void LocApiV02 :: reportNmea ( 2220 const qmiLocEventNmeaIndMsgT_v02 *nmea_report_ptr) 2221 { 2222 2223 LocApiBase::reportNmea(nmea_report_ptr->nmea, 2224 strlen(nmea_report_ptr->nmea)); 2225 2226 LOC_LOGD("NMEA <%s", nmea_report_ptr->nmea); 2227 } 2228 2229 /* convert and report an ATL request to loc engine */ 2230 void LocApiV02 :: reportAtlRequest( 2231 const qmiLocEventLocationServerConnectionReqIndMsgT_v02 * server_request_ptr) 2232 { 2233 uint32_t connHandle = server_request_ptr->connHandle; 2234 // service ATL open request; copy the WWAN type 2235 if(server_request_ptr->requestType == eQMI_LOC_SERVER_REQUEST_OPEN_V02 ) 2236 { 2237 AGpsType agpsType; 2238 switch(server_request_ptr->wwanType) 2239 { 2240 case eQMI_LOC_WWAN_TYPE_INTERNET_V02: 2241 agpsType = AGPS_TYPE_WWAN_ANY; 2242 requestATL(connHandle, agpsType); 2243 break; 2244 case eQMI_LOC_WWAN_TYPE_AGNSS_V02: 2245 agpsType = AGPS_TYPE_SUPL; 2246 requestATL(connHandle, agpsType); 2247 break; 2248 case eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02: 2249 requestSuplES(connHandle); 2250 break; 2251 default: 2252 agpsType = AGPS_TYPE_WWAN_ANY; 2253 requestATL(connHandle, agpsType); 2254 break; 2255 } 2256 } 2257 // service the ATL close request 2258 else if (server_request_ptr->requestType == eQMI_LOC_SERVER_REQUEST_CLOSE_V02) 2259 { 2260 releaseATL(connHandle); 2261 } 2262 } 2263 2264 /* conver the NI report to loc eng format and send t loc engine */ 2265 void LocApiV02 :: reportNiRequest( 2266 const qmiLocEventNiNotifyVerifyReqIndMsgT_v02 *ni_req_ptr) 2267 { 2268 GpsNiNotification notif; 2269 2270 /* initialize the notification*/ 2271 memset(notif.extras, 0, sizeof notif.extras); 2272 memset(notif.text, 0, sizeof notif.text); 2273 memset(notif.requestor_id, 0, sizeof notif.requestor_id); 2274 2275 /* NI timeout gets overwritten in LocApiEngAdapter, 2276 initializing to 0 here */ 2277 notif.timeout = 0; 2278 2279 notif.text_encoding = GPS_ENC_NONE ; 2280 2281 notif.requestor_id_encoding = GPS_ENC_UNKNOWN; 2282 2283 notif.notify_flags = 0; 2284 2285 notif.default_response = GPS_NI_RESPONSE_NORESP; 2286 2287 /*Handle Vx request */ 2288 if(ni_req_ptr->NiVxInd_valid == 1) 2289 { 2290 const qmiLocNiVxNotifyVerifyStructT_v02 *vx_req = &(ni_req_ptr->NiVxInd); 2291 2292 notif.ni_type = GPS_NI_TYPE_VOICE; 2293 2294 // Requestor ID, the requestor id recieved is NULL terminated 2295 hexcode(notif.requestor_id, sizeof notif.requestor_id, 2296 (char *)vx_req->requestorId, vx_req->requestorId_len ); 2297 } 2298 2299 /* Handle UMTS CP request*/ 2300 else if(ni_req_ptr->NiUmtsCpInd_valid == 1) 2301 { 2302 const qmiLocNiUmtsCpNotifyVerifyStructT_v02 *umts_cp_req = 2303 &ni_req_ptr->NiUmtsCpInd; 2304 2305 notif.ni_type = GPS_NI_TYPE_UMTS_CTRL_PLANE; 2306 2307 /* notificationText should always be a NULL terminated string */ 2308 hexcode(notif.text, sizeof notif.text, 2309 (char *)umts_cp_req->notificationText, 2310 umts_cp_req->notificationText_len); 2311 2312 /* Store requestor ID */ 2313 hexcode(notif.requestor_id, sizeof(notif.requestor_id), 2314 (char *)umts_cp_req->requestorId.codedString, 2315 umts_cp_req->requestorId.codedString_len); 2316 2317 /* convert encodings */ 2318 notif.text_encoding = convertNiEncoding(umts_cp_req->dataCodingScheme); 2319 2320 notif.requestor_id_encoding = 2321 convertNiEncoding(umts_cp_req->requestorId.dataCodingScheme); 2322 2323 /* LCS address (using extras field) */ 2324 if ( umts_cp_req->clientAddress_len != 0) 2325 { 2326 char lcs_addr[32]; // Decoded LCS address for UMTS CP NI 2327 2328 // Copy LCS Address into notif.extras in the format: Address = 012345 2329 strlcat(notif.extras, LOC_NI_NOTIF_KEY_ADDRESS, sizeof (notif.extras)); 2330 strlcat(notif.extras, " = ", sizeof notif.extras); 2331 int addr_len = 0; 2332 const char *address_source = NULL; 2333 address_source = (char *)umts_cp_req->clientAddress; 2334 // client Address is always NULL terminated 2335 addr_len = decodeAddress(lcs_addr, sizeof(lcs_addr), address_source, 2336 umts_cp_req->clientAddress_len); 2337 2338 // The address is ASCII string 2339 if (addr_len) 2340 { 2341 strlcat(notif.extras, lcs_addr, sizeof notif.extras); 2342 } 2343 } 2344 2345 } 2346 else if(ni_req_ptr->NiSuplInd_valid == 1) 2347 { 2348 const qmiLocNiSuplNotifyVerifyStructT_v02 *supl_req = 2349 &ni_req_ptr->NiSuplInd; 2350 2351 notif.ni_type = GPS_NI_TYPE_UMTS_SUPL; 2352 2353 // Client name 2354 if (supl_req->valid_flags & QMI_LOC_SUPL_CLIENT_NAME_MASK_V02) 2355 { 2356 hexcode(notif.text, sizeof(notif.text), 2357 (char *)supl_req->clientName.formattedString, 2358 supl_req->clientName.formattedString_len); 2359 LOC_LOGV("%s:%d]: SUPL NI: client_name: %s \n", __func__, __LINE__, 2360 notif.text); 2361 } 2362 else 2363 { 2364 LOC_LOGV("%s:%d]: SUPL NI: client_name not present.", 2365 __func__, __LINE__); 2366 } 2367 2368 // Requestor ID 2369 if (supl_req->valid_flags & QMI_LOC_SUPL_REQUESTOR_ID_MASK_V02) 2370 { 2371 hexcode(notif.requestor_id, sizeof notif.requestor_id, 2372 (char*)supl_req->requestorId.formattedString, 2373 supl_req->requestorId.formattedString_len ); 2374 2375 LOC_LOGV("%s:%d]: SUPL NI: requestor_id: %s \n", __func__, __LINE__, 2376 notif.requestor_id); 2377 } 2378 else 2379 { 2380 LOC_LOGV("%s:%d]: SUPL NI: requestor_id not present.", 2381 __func__, __LINE__); 2382 } 2383 2384 // Encoding type 2385 if (supl_req->valid_flags & QMI_LOC_SUPL_DATA_CODING_SCHEME_MASK_V02) 2386 { 2387 notif.text_encoding = convertNiEncoding(supl_req->dataCodingScheme); 2388 2389 notif.requestor_id_encoding = convertNiEncoding(supl_req->dataCodingScheme); 2390 } 2391 else 2392 { 2393 notif.text_encoding = notif.requestor_id_encoding = GPS_ENC_UNKNOWN; 2394 } 2395 2396 // ES SUPL 2397 if(ni_req_ptr->suplEmergencyNotification_valid ==1) 2398 { 2399 const qmiLocEmergencyNotificationStructT_v02 *supl_emergency_request = 2400 &ni_req_ptr->suplEmergencyNotification; 2401 2402 notif.ni_type = GPS_NI_TYPE_EMERGENCY_SUPL; 2403 } 2404 2405 } //ni_req_ptr->NiSuplInd_valid == 1 2406 else 2407 { 2408 LOC_LOGE("%s:%d]: unknown request event \n",__func__, __LINE__); 2409 return; 2410 } 2411 2412 // Set default_response & notify_flags 2413 convertNiNotifyVerifyType(¬if, ni_req_ptr->notificationType); 2414 2415 qmiLocEventNiNotifyVerifyReqIndMsgT_v02 *ni_req_copy_ptr = 2416 (qmiLocEventNiNotifyVerifyReqIndMsgT_v02 *)malloc(sizeof(*ni_req_copy_ptr)); 2417 2418 if( NULL != ni_req_copy_ptr) 2419 { 2420 memcpy(ni_req_copy_ptr, ni_req_ptr, sizeof(*ni_req_copy_ptr)); 2421 2422 requestNiNotify(notif, (const void*)ni_req_copy_ptr); 2423 } 2424 else 2425 { 2426 LOC_LOGE("%s:%d]: Error copying NI request\n", __func__, __LINE__); 2427 } 2428 2429 } 2430 2431 /* Report the Xtra Server Url from the modem to HAL*/ 2432 void LocApiV02 :: reportXtraServerUrl( 2433 const qmiLocEventInjectPredictedOrbitsReqIndMsgT_v02* 2434 server_request_ptr) 2435 { 2436 2437 if (server_request_ptr->serverList.serverList_len == 1) 2438 { 2439 reportXtraServer(server_request_ptr->serverList.serverList[0].serverUrl, 2440 "", 2441 "", 2442 QMI_LOC_MAX_SERVER_ADDR_LENGTH_V02); 2443 } 2444 else if (server_request_ptr->serverList.serverList_len == 2) 2445 { 2446 reportXtraServer(server_request_ptr->serverList.serverList[0].serverUrl, 2447 server_request_ptr->serverList.serverList[1].serverUrl, 2448 "", 2449 QMI_LOC_MAX_SERVER_ADDR_LENGTH_V02); 2450 } 2451 else 2452 { 2453 reportXtraServer(server_request_ptr->serverList.serverList[0].serverUrl, 2454 server_request_ptr->serverList.serverList[1].serverUrl, 2455 server_request_ptr->serverList.serverList[2].serverUrl, 2456 QMI_LOC_MAX_SERVER_ADDR_LENGTH_V02); 2457 } 2458 2459 } 2460 2461 /* convert Ni Encoding type from QMI_LOC to loc eng format */ 2462 GpsNiEncodingType LocApiV02 ::convertNiEncoding( 2463 qmiLocNiDataCodingSchemeEnumT_v02 loc_encoding) 2464 { 2465 GpsNiEncodingType enc = GPS_ENC_UNKNOWN; 2466 2467 switch (loc_encoding) 2468 { 2469 case eQMI_LOC_NI_SUPL_UTF8_V02: 2470 enc = GPS_ENC_SUPL_UTF8; 2471 break; 2472 case eQMI_LOC_NI_SUPL_UCS2_V02: 2473 enc = GPS_ENC_SUPL_UCS2; 2474 break; 2475 case eQMI_LOC_NI_SUPL_GSM_DEFAULT_V02: 2476 enc = GPS_ENC_SUPL_GSM_DEFAULT; 2477 break; 2478 case eQMI_LOC_NI_SS_LANGUAGE_UNSPEC_V02: 2479 enc = GPS_ENC_SUPL_GSM_DEFAULT; // SS_LANGUAGE_UNSPEC = GSM 2480 break; 2481 default: 2482 break; 2483 } 2484 2485 return enc; 2486 } 2487 2488 /*convert NI notify verify type from QMI LOC to loc eng format*/ 2489 bool LocApiV02 :: convertNiNotifyVerifyType ( 2490 GpsNiNotification *notif, 2491 qmiLocNiNotifyVerifyEnumT_v02 notif_priv) 2492 { 2493 switch (notif_priv) 2494 { 2495 case eQMI_LOC_NI_USER_NO_NOTIFY_NO_VERIFY_V02: 2496 notif->notify_flags = 0; 2497 break; 2498 2499 case eQMI_LOC_NI_USER_NOTIFY_ONLY_V02: 2500 notif->notify_flags = GPS_NI_NEED_NOTIFY; 2501 break; 2502 2503 case eQMI_LOC_NI_USER_NOTIFY_VERIFY_ALLOW_NO_RESP_V02: 2504 notif->notify_flags = GPS_NI_NEED_NOTIFY | GPS_NI_NEED_VERIFY; 2505 notif->default_response = GPS_NI_RESPONSE_ACCEPT; 2506 break; 2507 2508 case eQMI_LOC_NI_USER_NOTIFY_VERIFY_NOT_ALLOW_NO_RESP_V02: 2509 notif->notify_flags = GPS_NI_NEED_NOTIFY | GPS_NI_NEED_VERIFY; 2510 notif->default_response = GPS_NI_RESPONSE_DENY; 2511 break; 2512 2513 case eQMI_LOC_NI_USER_NOTIFY_VERIFY_PRIVACY_OVERRIDE_V02: 2514 notif->notify_flags = GPS_NI_PRIVACY_OVERRIDE; 2515 break; 2516 2517 default: 2518 return false; 2519 } 2520 2521 return true; 2522 } 2523 2524 /* convert and report GNSS measurement data to loc eng */ 2525 void LocApiV02 :: reportGnssMeasurementData( 2526 const qmiLocEventGnssSvMeasInfoIndMsgT_v02& gnss_measurement_report_ptr) 2527 { 2528 LOC_LOGV ("%s:%d]: entering\n", __func__, __LINE__); 2529 2530 GnssData gnssMeasurementData; 2531 memset (&gnssMeasurementData, 0, sizeof(GnssData)); 2532 2533 int svMeasurment_len = 0; 2534 2535 // size 2536 gnssMeasurementData.size = sizeof(GnssData); 2537 2538 // number of measurements 2539 if (gnss_measurement_report_ptr.svMeasurement_valid) { 2540 svMeasurment_len = 2541 gnss_measurement_report_ptr.svMeasurement_len; 2542 gnssMeasurementData.measurement_count = svMeasurment_len; 2543 LOC_LOGV ("%s:%d]: there are %d valid SV measurements\n", 2544 __func__, __LINE__, svMeasurment_len); 2545 } else { 2546 LOC_LOGV ("%s:%d]: there are no valid SV measurements\n", 2547 __func__, __LINE__); 2548 } 2549 2550 LOC_LOGV("%s:%d]: There are %d GNSS measurements\n", 2551 __func__, __LINE__, svMeasurment_len); 2552 if (gnss_measurement_report_ptr.system == eQMI_LOC_SV_SYSTEM_GPS_V02) { 2553 2554 // the array of measurements 2555 int index = 0; 2556 while(svMeasurment_len > 0) { 2557 convertGnssMeasurements(gnssMeasurementData.measurements[index], 2558 gnss_measurement_report_ptr.svMeasurement[index]); 2559 index++; 2560 svMeasurment_len--; 2561 } 2562 2563 // the GPS clock time reading 2564 convertGnssClock(gnssMeasurementData.clock, 2565 gnss_measurement_report_ptr); 2566 2567 // calling the base 2568 LOC_LOGV ("%s:%d]: calling LocApiBase::reportGnssMeasurementData.\n", 2569 __func__, __LINE__); 2570 LocApiBase::reportGnssMeasurementData(gnssMeasurementData); 2571 } else { 2572 LOC_LOGV ("%s:%d]: There is no GPS measurement, constellation=%d\n", 2573 __func__, __LINE__, gnss_measurement_report_ptr.system); 2574 } 2575 } 2576 2577 /*convert GnssMeasurement type from QMI LOC to loc eng format*/ 2578 void LocApiV02 :: convertGnssMeasurements (GnssMeasurement& gnssMeasurement, 2579 const qmiLocSVMeasurementStructT_v02& gnss_measurement_info) 2580 { 2581 LOC_LOGV ("%s:%d]: entering\n", __func__, __LINE__); 2582 2583 // size 2584 gnssMeasurement.size = sizeof(GnssMeasurement); 2585 2586 // flag initiation 2587 GnssMeasurementFlags flags = 0; 2588 2589 // svid 2590 gnssMeasurement.svid = gnss_measurement_info.gnssSvId; 2591 2592 // constellation 2593 gnssMeasurement.constellation = GNSS_CONSTELLATION_GPS; 2594 2595 // time_offset_ns 2596 if (0 != gnss_measurement_info.measLatency) 2597 { 2598 LOC_LOGV("%s:%d]: measLatency is not 0\n", __func__, __LINE__); 2599 } 2600 gnssMeasurement.time_offset_ns = 0.0; 2601 2602 // state & received_sv_time_in_ns & received_gps_tow_uncertainty_ns 2603 uint64_t validMask = gnss_measurement_info.measurementStatus & 2604 gnss_measurement_info.validMeasStatusMask; 2605 uint64_t bitSynMask = QMI_LOC_MASK_MEAS_STATUS_BE_CONFIRM_V02 | 2606 QMI_LOC_MASK_MEAS_STATUS_SB_VALID_V02; 2607 double gpsTowUncNs = (double)gnss_measurement_info.svTimeSpeed.svTimeUncMs * 1e6; 2608 2609 if (validMask & QMI_LOC_MASK_MEAS_STATUS_MS_VALID_V02) { 2610 /* sub-frame decode & TOW decode */ 2611 gnssMeasurement.state = GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC | 2612 GNSS_MEASUREMENT_STATE_TOW_DECODED | 2613 GNSS_MEASUREMENT_STATE_BIT_SYNC | 2614 GNSS_MEASUREMENT_STATE_CODE_LOCK; 2615 gnssMeasurement.received_sv_time_in_ns = 2616 (int64_t)(((double)gnss_measurement_info.svTimeSpeed.svTimeMs + 2617 (double)gnss_measurement_info.svTimeSpeed.svTimeSubMs) * 1e6); 2618 2619 gnssMeasurement.received_sv_time_uncertainty_in_ns = (int64_t)gpsTowUncNs; 2620 2621 } else if ((validMask & bitSynMask) == bitSynMask) { 2622 /* bit sync */ 2623 gnssMeasurement.state = GNSS_MEASUREMENT_STATE_BIT_SYNC | 2624 GNSS_MEASUREMENT_STATE_CODE_LOCK; 2625 gnssMeasurement.received_sv_time_in_ns = 2626 (int64_t)(fmod(((double)gnss_measurement_info.svTimeSpeed.svTimeMs + 2627 (double)gnss_measurement_info.svTimeSpeed.svTimeSubMs), 20) * 1e6); 2628 gnssMeasurement.received_sv_time_uncertainty_in_ns = (int64_t)gpsTowUncNs; 2629 2630 } else if (validMask & QMI_LOC_MASK_MEAS_STATUS_SM_VALID_V02) { 2631 /* code lock */ 2632 gnssMeasurement.state = GNSS_MEASUREMENT_STATE_CODE_LOCK; 2633 gnssMeasurement.received_sv_time_in_ns = 2634 (int64_t)((double)gnss_measurement_info.svTimeSpeed.svTimeSubMs * 1e6); 2635 gnssMeasurement.received_sv_time_uncertainty_in_ns = (int64_t)gpsTowUncNs; 2636 2637 } else { 2638 /* by default */ 2639 gnssMeasurement.state = GNSS_MEASUREMENT_STATE_UNKNOWN; 2640 gnssMeasurement.received_sv_time_in_ns = 0; 2641 gnssMeasurement.received_sv_time_uncertainty_in_ns = 0; 2642 } 2643 2644 // c_n0_dbhz 2645 gnssMeasurement.c_n0_dbhz = gnss_measurement_info.CNo/10.0; 2646 2647 if (QMI_LOC_MASK_MEAS_STATUS_VELOCITY_FINE_V02 == (gnss_measurement_info.measurementStatus & QMI_LOC_MASK_MEAS_STATUS_VELOCITY_FINE_V02)) 2648 { 2649 LOC_LOGV ("%s:%d]: FINE mS=0x%4X fS=%f fSU=%f dS=%f dSU=%f\n", __func__, __LINE__, gnss_measurement_info.measurementStatus, 2650 gnss_measurement_info.fineSpeed, gnss_measurement_info.fineSpeedUnc, 2651 gnss_measurement_info.svTimeSpeed.dopplerShift, gnss_measurement_info.svTimeSpeed.dopplerShiftUnc); 2652 // pseudorange_rate_mps 2653 gnssMeasurement.pseudorange_rate_mps = gnss_measurement_info.fineSpeed; 2654 2655 // pseudorange_rate_uncertainty_mps 2656 gnssMeasurement.pseudorange_rate_uncertainty_mps = gnss_measurement_info.fineSpeedUnc; 2657 } 2658 else 2659 { 2660 LOC_LOGV ("%s:%d]: COARSE mS=0x%4X fS=%f fSU=%f dS=%f dSU=%f\n", __func__, __LINE__, gnss_measurement_info.measurementStatus, 2661 gnss_measurement_info.fineSpeed, gnss_measurement_info.fineSpeedUnc, 2662 gnss_measurement_info.svTimeSpeed.dopplerShift, gnss_measurement_info.svTimeSpeed.dopplerShiftUnc); 2663 // pseudorange_rate_mps 2664 gnssMeasurement.pseudorange_rate_mps = gnss_measurement_info.svTimeSpeed.dopplerShift; 2665 2666 // pseudorange_rate_uncertainty_mps 2667 gnssMeasurement.pseudorange_rate_uncertainty_mps = gnss_measurement_info.svTimeSpeed.dopplerShiftUnc; 2668 } 2669 2670 // accumulated_delta_range_state 2671 gnssMeasurement.accumulated_delta_range_state = GNSS_ADR_STATE_UNKNOWN; 2672 2673 // multipath_indicator 2674 gnssMeasurement.multipath_indicator = GNSS_MULTIPATH_INDICATOR_UNKNOWN; 2675 2676 gnssMeasurement.flags = flags; 2677 2678 LOC_LOGV(" %s:%d]: GNSS measurement raw data received form modem: \n", __func__, __LINE__); 2679 LOC_LOGV(" Input => gnssSvId=%d CNo=%d measurementStatus=0x%04x%04x\n", 2680 gnss_measurement_info.gnssSvId, // %d 2681 gnss_measurement_info.CNo, // %d 2682 (uint32_t)(gnss_measurement_info.measurementStatus >> 32), // %04x Upper 32 2683 (uint32_t)(gnss_measurement_info.measurementStatus & 0xFFFFFFFF)); // %04x Lower 32 2684 2685 LOC_LOGV(" dopplerShift=%f dopplerShiftUnc=%f fineSpeed=%f fineSpeedUnc=%f\n", 2686 gnss_measurement_info.svTimeSpeed.dopplerShift, // %f 2687 gnss_measurement_info.svTimeSpeed.dopplerShiftUnc, // %f 2688 gnss_measurement_info.fineSpeed, // %f 2689 gnss_measurement_info.fineSpeedUnc); // %f 2690 2691 LOC_LOGV(" svTimeMs=%u svTimeSubMs=%f svTimeUncMs=%f\n", 2692 gnss_measurement_info.svTimeSpeed.svTimeMs, // %u 2693 gnss_measurement_info.svTimeSpeed.svTimeSubMs, // %f 2694 gnss_measurement_info.svTimeSpeed.svTimeUncMs); // %f 2695 2696 LOC_LOGV(" svStatus=0x%02x validMeasStatusMask=0x%04x%04x\n", 2697 (uint32_t)(gnss_measurement_info.svStatus), // %02x 2698 (uint32_t)(gnss_measurement_info.validMeasStatusMask >> 32), // %04x Upper 32 2699 (uint32_t)(gnss_measurement_info.validMeasStatusMask & 0xFFFFFFFF)); // %04x Lower 32 2700 2701 LOC_LOGV(" %s:%d]: GNSS measurement data after conversion:\n", __func__, __LINE__); 2702 LOC_LOGV(" Output => size=%d svid=%d time_offset_ns=%f state=%d\n", 2703 gnssMeasurement.size, // %d 2704 gnssMeasurement.svid, // %d 2705 gnssMeasurement.time_offset_ns, // %f 2706 gnssMeasurement.state); // %d 2707 2708 LOC_LOGV(" received_sv_time_in_ns=%lld received_sv_time_uncertainty_in_ns=%lld c_n0_dbhz=%g\n", 2709 gnssMeasurement.received_sv_time_in_ns, // %lld 2710 gnssMeasurement.received_sv_time_uncertainty_in_ns,// %lld 2711 gnssMeasurement.c_n0_dbhz); // %g 2712 2713 LOC_LOGV(" pseudorange_rate_mps=%g pseudorange_rate_uncertainty_mps=%g\n", 2714 gnssMeasurement.pseudorange_rate_mps, // %g 2715 gnssMeasurement.pseudorange_rate_uncertainty_mps); // %g 2716 } 2717 2718 /*convert GnssClock type from QMI LOC to loc eng format*/ 2719 void LocApiV02 :: convertGnssClock (GnssClock& gnssClock, 2720 const qmiLocEventGnssSvMeasInfoIndMsgT_v02& gnss_measurement_info) 2721 { 2722 static uint32_t oldRefFCount = 0; 2723 static uint32_t newRefFCount = 0; 2724 static uint32_t oldDiscCount = 0; 2725 static uint32_t newDiscCount = 0; 2726 static uint32_t localDiscCount = 0; 2727 2728 LOC_LOGV ("%s:%d]: entering\n", __func__, __LINE__); 2729 2730 // size 2731 gnssClock.size = sizeof(GnssClock); 2732 2733 // flag initiation 2734 GnssClockFlags flags = 0; 2735 2736 if (gnss_measurement_info.systemTimeExt_valid && 2737 gnss_measurement_info.numClockResets_valid) { 2738 newRefFCount = gnss_measurement_info.systemTimeExt.refFCount; 2739 newDiscCount = gnss_measurement_info.numClockResets; 2740 if ((true == mMeasurementsStarted) || 2741 (oldDiscCount != newDiscCount) || 2742 (newRefFCount <= oldRefFCount)) 2743 { 2744 if (true == mMeasurementsStarted) 2745 { 2746 mMeasurementsStarted = false; 2747 } 2748 localDiscCount++; 2749 } 2750 oldDiscCount = newDiscCount; 2751 oldRefFCount = newRefFCount; 2752 2753 // time_ns & time_uncertainty_ns 2754 gnssClock.time_ns = (int64_t)gnss_measurement_info.systemTimeExt.refFCount * 1e6; 2755 gnssClock.hw_clock_discontinuity_count = localDiscCount; 2756 gnssClock.time_uncertainty_ns = 0.0; 2757 2758 if (gnss_measurement_info.systemTime_valid) { 2759 uint16_t systemWeek = gnss_measurement_info.systemTime.systemWeek; 2760 uint32_t systemMsec = gnss_measurement_info.systemTime.systemMsec; 2761 float sysClkBias = gnss_measurement_info.systemTime.systemClkTimeBias; 2762 float sysClkUncMs = gnss_measurement_info.systemTime.systemClkTimeUncMs; 2763 bool isTimeValid = (sysClkUncMs <= 16.0f); // 16ms 2764 double gps_time_ns; 2765 2766 if (systemWeek != C_GPS_WEEK_UNKNOWN && isTimeValid) { 2767 // full_bias_ns, bias_ns & bias_uncertainty_ns 2768 double temp = (double)(systemWeek)* (double)WEEK_MSECS + (double)systemMsec; 2769 gps_time_ns = (double)temp*1e6 - (double)((int)(sysClkBias*1e6)); 2770 gnssClock.full_bias_ns = (int64_t)(gnssClock.time_ns - gps_time_ns); 2771 gnssClock.bias_ns = (double)(gnssClock.time_ns - gps_time_ns) - gnssClock.full_bias_ns; 2772 gnssClock.bias_uncertainty_ns = (double)sysClkUncMs * 1e6; 2773 flags |= (GNSS_CLOCK_HAS_FULL_BIAS | GNSS_CLOCK_HAS_BIAS | GNSS_CLOCK_HAS_BIAS_UNCERTAINTY); 2774 } 2775 } 2776 } 2777 2778 // drift_nsps & drift_uncertainty_nsps 2779 if (gnss_measurement_info.rcvrClockFrequencyInfo_valid) 2780 { 2781 double driftMPS = gnss_measurement_info.rcvrClockFrequencyInfo.clockDrift; 2782 double driftUncMPS = gnss_measurement_info.rcvrClockFrequencyInfo.clockDriftUnc; 2783 2784 gnssClock.drift_nsps = driftMPS * MPS_TO_NSPS; 2785 gnssClock.drift_uncertainty_nsps = driftUncMPS * MPS_TO_NSPS; 2786 2787 flags |= (GNSS_CLOCK_HAS_DRIFT | GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY); 2788 } 2789 2790 gnssClock.flags = flags; 2791 2792 LOC_LOGV(" %s:%d]: GNSS measurement clock data received from modem: \n", __func__, __LINE__); 2793 LOC_LOGV(" Input => systemTime_valid=%d systemTimeExt_valid=%d numClockResets_valid=%d\n", 2794 gnss_measurement_info.systemTime_valid, // %d 2795 gnss_measurement_info.systemTimeExt_valid, // %d 2796 gnss_measurement_info.numClockResets_valid); // %d 2797 2798 LOC_LOGV(" systemWeek=%d systemMsec=%d systemClkTimeBias=%f\n", 2799 gnss_measurement_info.systemTime.systemWeek, // %d 2800 gnss_measurement_info.systemTime.systemMsec, // %d 2801 gnss_measurement_info.systemTime.systemClkTimeBias); // %f 2802 2803 LOC_LOGV(" systemClkTimeUncMs=%f refFCount=%d numClockResets=%d\n", 2804 gnss_measurement_info.systemTime.systemClkTimeUncMs, // %f 2805 gnss_measurement_info.systemTimeExt.refFCount, // %d 2806 gnss_measurement_info.numClockResets); // %d 2807 2808 LOC_LOGV(" clockDrift=%f clockDriftUnc=%f\n", 2809 gnss_measurement_info.rcvrClockFrequencyInfo.clockDrift, // %f 2810 gnss_measurement_info.rcvrClockFrequencyInfo.clockDriftUnc); // %f 2811 2812 2813 LOC_LOGV(" %s:%d]: GNSS measurement clock after conversion: \n", __func__, __LINE__); 2814 LOC_LOGV(" Output => time_ns=%lld\n", 2815 gnssClock.time_ns); // %lld 2816 2817 LOC_LOGV(" full_bias_ns=%lld bias_ns=%g bias_uncertainty_ns=%g\n", 2818 gnssClock.full_bias_ns, // %lld 2819 gnssClock.bias_ns, // %g 2820 gnssClock.bias_uncertainty_ns); // %g 2821 2822 LOC_LOGV(" drift_nsps=%g drift_uncertainty_nsps=%g\n", 2823 gnssClock.drift_nsps, // %g 2824 gnssClock.drift_uncertainty_nsps); // %g 2825 2826 LOC_LOGV(" hw_clock_discontinuity_count=%d flags=0x%04x\n", 2827 gnssClock.hw_clock_discontinuity_count, // %lld 2828 gnssClock.flags); // %04x 2829 } 2830 2831 /* event callback registered with the loc_api v02 interface */ 2832 void LocApiV02 :: eventCb(locClientHandleType clientHandle, 2833 uint32_t eventId, locClientEventIndUnionType eventPayload) 2834 { 2835 LOC_LOGD("%s:%d]: event id = %d\n", __func__, __LINE__, 2836 eventId); 2837 2838 switch(eventId) 2839 { 2840 //Position Report 2841 case QMI_LOC_EVENT_POSITION_REPORT_IND_V02: 2842 reportPosition(eventPayload.pPositionReportEvent); 2843 break; 2844 2845 // Satellite report 2846 case QMI_LOC_EVENT_GNSS_SV_INFO_IND_V02: 2847 reportSv(eventPayload.pGnssSvInfoReportEvent); 2848 break; 2849 2850 // Status report 2851 case QMI_LOC_EVENT_ENGINE_STATE_IND_V02: 2852 reportEngineState(eventPayload.pEngineState); 2853 break; 2854 2855 case QMI_LOC_EVENT_FIX_SESSION_STATE_IND_V02: 2856 reportFixSessionState(eventPayload.pFixSessionState); 2857 break; 2858 2859 // NMEA 2860 case QMI_LOC_EVENT_NMEA_IND_V02: 2861 reportNmea(eventPayload.pNmeaReportEvent); 2862 break; 2863 2864 // XTRA request 2865 case QMI_LOC_EVENT_INJECT_PREDICTED_ORBITS_REQ_IND_V02: 2866 LOC_LOGD("%s:%d]: XTRA download request\n", __func__, 2867 __LINE__); 2868 reportXtraServerUrl(eventPayload.pInjectPredictedOrbitsReqEvent); 2869 requestXtraData(); 2870 break; 2871 2872 // time request 2873 case QMI_LOC_EVENT_INJECT_TIME_REQ_IND_V02: 2874 LOC_LOGD("%s:%d]: Time request\n", __func__, 2875 __LINE__); 2876 requestTime(); 2877 break; 2878 2879 //position request 2880 case QMI_LOC_EVENT_INJECT_POSITION_REQ_IND_V02: 2881 LOC_LOGD("%s:%d]: Position request\n", __func__, 2882 __LINE__); 2883 requestLocation(); 2884 break; 2885 2886 // NI request 2887 case QMI_LOC_EVENT_NI_NOTIFY_VERIFY_REQ_IND_V02: 2888 reportNiRequest(eventPayload.pNiNotifyVerifyReqEvent); 2889 break; 2890 2891 // AGPS connection request 2892 case QMI_LOC_EVENT_LOCATION_SERVER_CONNECTION_REQ_IND_V02: 2893 reportAtlRequest(eventPayload.pLocationServerConnReqEvent); 2894 break; 2895 2896 // GNSS Measurement Report 2897 case QMI_LOC_EVENT_GNSS_MEASUREMENT_REPORT_IND_V02: 2898 reportGnssMeasurementData(*eventPayload.pGnssSvRawInfoEvent); 2899 break; 2900 } 2901 } 2902 2903 /* Call the service LocAdapterBase down event*/ 2904 void LocApiV02 :: errorCb(locClientHandleType handle, 2905 locClientErrorEnumType errorId) 2906 { 2907 if(errorId == eLOC_CLIENT_ERROR_SERVICE_UNAVAILABLE) 2908 { 2909 LOC_LOGE("%s:%d]: Service unavailable error\n", 2910 __func__, __LINE__); 2911 2912 handleEngineDownEvent(); 2913 2914 /* immediately send the engine up event so that 2915 the loc engine re-initializes the adapter and the 2916 loc-api_v02 interface */ 2917 2918 handleEngineUpEvent(); 2919 } 2920 } 2921 2922 static void ds_client_global_event_cb(ds_client_status_enum_type result, 2923 void *loc_adapter_cookie) 2924 { 2925 LocApiV02 *locApiV02Instance = (LocApiV02 *)loc_adapter_cookie; 2926 2927 locApiV02Instance->ds_client_event_cb(result); 2928 return; 2929 } 2930 2931 void LocApiV02::ds_client_event_cb(ds_client_status_enum_type result) 2932 { 2933 if(result == E_DS_CLIENT_DATA_CALL_CONNECTED) { 2934 LOC_LOGD("%s:%d]: Emergency call is up", __func__, __LINE__); 2935 reportDataCallOpened(); 2936 } 2937 else if(result == E_DS_CLIENT_DATA_CALL_DISCONNECTED) { 2938 LOC_LOGE("%s:%d]: Emergency call is stopped", __func__, __LINE__); 2939 reportDataCallClosed(); 2940 } 2941 return; 2942 } 2943 2944 static const ds_client_cb_data ds_client_cb = { 2945 ds_client_global_event_cb 2946 }; 2947 2948 int LocApiV02 :: initDataServiceClient() 2949 { 2950 int ret=0; 2951 if (NULL == dsLibraryHandle) 2952 { 2953 dsLibraryHandle = dlopen(DS_CLIENT_LIB_NAME, RTLD_NOW); 2954 if (NULL == dsLibraryHandle) 2955 { 2956 const char * err = dlerror(); 2957 if (NULL == err) 2958 { 2959 err = "Unknown"; 2960 } 2961 LOC_LOGE("%s:%d]: failed to load library %s; error=%s", 2962 __func__, __LINE__, 2963 DS_CLIENT_LIB_NAME, 2964 err); 2965 ret = 1; 2966 } 2967 if (NULL != dsLibraryHandle) 2968 { 2969 ds_client_get_iface_fn *getIface = NULL; 2970 2971 getIface = (ds_client_get_iface_fn*)dlsym(dsLibraryHandle, 2972 DS_CLIENT_GET_INTERFACE_FN); 2973 if (NULL != getIface) 2974 { 2975 dsClientIface = getIface(); 2976 } 2977 else 2978 { 2979 const char * err = dlerror(); 2980 if (NULL == err) 2981 { 2982 err = "Unknown"; 2983 } 2984 LOC_LOGE("%s:%d]: failed to find symbol %s; error=%s", 2985 __func__, __LINE__, 2986 DS_CLIENT_GET_INTERFACE_FN, 2987 err); 2988 } 2989 } 2990 } 2991 if (NULL != dsClientIface && NULL != dsClientIface->pfn_init) 2992 { 2993 ds_client_status_enum_type dsret = dsClientIface->pfn_init(); 2994 if (dsret != E_DS_CLIENT_SUCCESS) 2995 { 2996 LOC_LOGE("%s:%d]: Error during client initialization %d", 2997 __func__, __LINE__, 2998 (int)dsret); 2999 3000 ret = 3; 3001 } 3002 } 3003 else 3004 { 3005 ret = 2; 3006 } 3007 LOC_LOGD("%s:%d]: ret = %d\n", __func__, __LINE__,ret); 3008 return ret; 3009 } 3010 3011 int LocApiV02 :: openAndStartDataCall() 3012 { 3013 loc_api_adapter_err ret = LOC_API_ADAPTER_ERR_GENERAL_FAILURE; 3014 int profile_index = -1; 3015 int pdp_type = -1; 3016 ds_client_status_enum_type result = E_DS_CLIENT_FAILURE_NOT_INITIALIZED; 3017 3018 if (NULL != dsClientIface && 3019 NULL != dsClientIface->pfn_open_call && 3020 NULL != dsClientIface->pfn_start_call) 3021 { 3022 result = dsClientIface->pfn_open_call(&dsClientHandle, 3023 &ds_client_cb, 3024 (void *)this, 3025 &profile_index, 3026 &pdp_type); 3027 } 3028 if (E_DS_CLIENT_SUCCESS == result) 3029 { 3030 result = dsClientIface->pfn_start_call(dsClientHandle, 3031 profile_index, 3032 pdp_type); 3033 3034 if(result == E_DS_CLIENT_SUCCESS) { 3035 LOC_LOGD("%s:%d]: Request to start Emergency call sent\n", 3036 __func__, __LINE__); 3037 ret = LOC_API_ADAPTER_ERR_SUCCESS; 3038 } 3039 else { 3040 LOC_LOGE("%s:%d]: Unable to bring up emergency call using DS. result = %d", 3041 __func__, __LINE__, (int)result); 3042 ret = LOC_API_ADAPTER_ERR_UNSUPPORTED; 3043 } 3044 } 3045 else if(result == E_DS_CLIENT_RETRY_LATER) { 3046 LOC_LOGE("%s:%d]: Could not start emergency call. Retry after delay\n", 3047 __func__, __LINE__); 3048 ret = LOC_API_ADAPTER_ERR_ENGINE_BUSY; 3049 } 3050 else { 3051 LOC_LOGE("%s:%d]: Unable to bring up emergency call using DS. ret = %d", 3052 __func__, __LINE__, (int)ret); 3053 ret = LOC_API_ADAPTER_ERR_UNSUPPORTED; 3054 } 3055 3056 return (int)ret; 3057 } 3058 3059 void LocApiV02 :: stopDataCall() 3060 { 3061 ds_client_status_enum_type ret = E_DS_CLIENT_FAILURE_NOT_INITIALIZED; 3062 3063 if (NULL != dsClientIface && 3064 NULL != dsClientIface->pfn_stop_call) 3065 { 3066 ret = dsClientIface->pfn_stop_call(dsClientHandle); 3067 } 3068 3069 if (ret == E_DS_CLIENT_SUCCESS) { 3070 LOC_LOGD("%s:%d]: Request to Close SUPL ES call sent", 3071 __func__, __LINE__); 3072 } 3073 else { 3074 if (ret == E_DS_CLIENT_FAILURE_INVALID_HANDLE) { 3075 LOC_LOGE("%s:%d]: Conn handle not found for SUPL ES", 3076 __func__, __LINE__); 3077 } 3078 LOC_LOGE("%s:%d]: Could not close SUPL ES call. Ret: %d", 3079 __func__, __LINE__, ret); 3080 } 3081 return; 3082 } 3083 3084 void LocApiV02 :: closeDataCall() 3085 { 3086 int ret = 1; 3087 3088 if (NULL != dsClientIface && 3089 NULL != dsClientIface->pfn_close_call) 3090 { 3091 dsClientIface->pfn_close_call(&dsClientHandle); 3092 ret = 0; 3093 } 3094 3095 LOC_LOGD("%s:%d]: Release data client handle; ret=%d", 3096 __func__, __LINE__, ret); 3097 } 3098 3099 enum loc_api_adapter_err LocApiV02 :: 3100 getWwanZppFix(GpsLocation &zppLoc) 3101 { 3102 locClientReqUnionType req_union; 3103 qmiLocGetAvailWwanPositionReqMsgT_v02 zpp_req; 3104 qmiLocGetAvailWwanPositionIndMsgT_v02 zpp_ind; 3105 memset(&zpp_ind, 0, sizeof(zpp_ind)); 3106 memset(&zpp_req, 0, sizeof(zpp_req)); 3107 memset(&zppLoc, 0, sizeof(zppLoc)); 3108 3109 req_union.pGetAvailWwanPositionReq = &zpp_req; 3110 3111 LOC_LOGD("%s:%d]: Get ZPP Fix from available wwan position\n", __func__, __LINE__); 3112 3113 locClientStatusEnumType status = 3114 loc_sync_send_req(clientHandle, 3115 QMI_LOC_GET_AVAILABLE_WWAN_POSITION_REQ_V02, 3116 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 3117 QMI_LOC_GET_AVAILABLE_WWAN_POSITION_IND_V02, 3118 &zpp_ind); 3119 3120 if (status != eLOC_CLIENT_SUCCESS || 3121 eQMI_LOC_SUCCESS_V02 != zpp_ind.status) { 3122 LOC_LOGD ("%s:%d]: getWwanZppFix may not be supported by modem" 3123 " so will fallback to getBestAvailableZppFix" 3124 " status = %s, zpp_ind.status = %s ", 3125 __func__, __LINE__, 3126 loc_get_v02_client_status_name(status), 3127 loc_get_v02_qmi_status_name(zpp_ind.status)); 3128 3129 LocPosTechMask tech_mask; 3130 loc_api_adapter_err ret; 3131 ret = getBestAvailableZppFix(zppLoc, tech_mask); 3132 if (ret == LOC_API_ADAPTER_ERR_SUCCESS && 3133 tech_mask != LOC_POS_TECH_MASK_DEFAULT && 3134 tech_mask & LOC_POS_TECH_MASK_CELLID) { 3135 return LOC_API_ADAPTER_ERR_SUCCESS; 3136 } else { 3137 LOC_LOGD ("%s:%d]: getBestAvailableZppFix failed or" 3138 " technoloy source includes GNSS that is not allowed" 3139 " ret = %u, tech_mask = 0x%X ", 3140 __func__, __LINE__, ret, tech_mask); 3141 return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; 3142 } 3143 } 3144 3145 LOC_LOGD("Got Zpp fix location validity (lat:%d, lon:%d, timestamp:%d accuracy:%d)", 3146 zpp_ind.latitude_valid, 3147 zpp_ind.longitude_valid, 3148 zpp_ind.timestampUtc_valid, 3149 zpp_ind.horUncCircular_valid); 3150 3151 LOC_LOGD("(%.7f, %.7f), timestamp %llu, accuracy %f", 3152 zpp_ind.latitude, 3153 zpp_ind.longitude, 3154 zpp_ind.timestampUtc, 3155 zpp_ind.horUncCircular); 3156 3157 zppLoc.size = sizeof(GpsLocation); 3158 if (zpp_ind.timestampUtc_valid) { 3159 zppLoc.timestamp = zpp_ind.timestampUtc; 3160 } 3161 else { 3162 /* The UTC time from modem is not valid. 3163 In this case, we use current system time instead.*/ 3164 3165 struct timespec time_info_current; 3166 clock_gettime(CLOCK_REALTIME,&time_info_current); 3167 zppLoc.timestamp = (time_info_current.tv_sec)*1e3 + 3168 (time_info_current.tv_nsec)/1e6; 3169 LOC_LOGD("zpp timestamp got from system: %llu", zppLoc.timestamp); 3170 } 3171 3172 if ((zpp_ind.latitude_valid == false) || 3173 (zpp_ind.longitude_valid == false) || 3174 (zpp_ind.horUncCircular_valid == false)) { 3175 return LOC_API_ADAPTER_ERR_GENERAL_FAILURE; 3176 } 3177 3178 zppLoc.flags = GPS_LOCATION_HAS_LAT_LONG | GPS_LOCATION_HAS_ACCURACY; 3179 zppLoc.latitude = zpp_ind.latitude; 3180 zppLoc.longitude = zpp_ind.longitude; 3181 zppLoc.accuracy = zpp_ind.horUncCircular; 3182 3183 if (zpp_ind.altitudeWrtEllipsoid_valid) { 3184 zppLoc.flags |= GPS_LOCATION_HAS_ALTITUDE; 3185 zppLoc.altitude = zpp_ind.altitudeWrtEllipsoid; 3186 } 3187 3188 return LOC_API_ADAPTER_ERR_SUCCESS; 3189 } 3190 3191 enum loc_api_adapter_err LocApiV02 :: getBestAvailableZppFix(GpsLocation & zppLoc) 3192 { 3193 LocPosTechMask tech_mask; 3194 return getBestAvailableZppFix(zppLoc, tech_mask); 3195 } 3196 3197 enum loc_api_adapter_err LocApiV02 :: 3198 getBestAvailableZppFix(GpsLocation &zppLoc, LocPosTechMask &tech_mask) 3199 { 3200 locClientReqUnionType req_union; 3201 3202 qmiLocGetBestAvailablePositionIndMsgT_v02 zpp_ind; 3203 qmiLocGetBestAvailablePositionReqMsgT_v02 zpp_req; 3204 3205 memset(&zpp_ind, 0, sizeof(zpp_ind)); 3206 memset(&zpp_req, 0, sizeof(zpp_req)); 3207 memset(&zppLoc, 0, sizeof(zppLoc)); 3208 tech_mask = LOC_POS_TECH_MASK_DEFAULT; 3209 3210 req_union.pGetBestAvailablePositionReq = &zpp_req; 3211 3212 LOC_LOGD("%s:%d]: Get ZPP Fix from best available source\n", __func__, __LINE__); 3213 3214 locClientStatusEnumType status = 3215 loc_sync_send_req(clientHandle, 3216 QMI_LOC_GET_BEST_AVAILABLE_POSITION_REQ_V02, 3217 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 3218 QMI_LOC_GET_BEST_AVAILABLE_POSITION_IND_V02, 3219 &zpp_ind); 3220 3221 if (status != eLOC_CLIENT_SUCCESS || 3222 eQMI_LOC_SUCCESS_V02 != zpp_ind.status) { 3223 LOC_LOGE ("%s:%d]: error! status = %s, zpp_ind.status = %s\n", 3224 __func__, __LINE__, 3225 loc_get_v02_client_status_name(status), 3226 loc_get_v02_qmi_status_name(zpp_ind.status)); 3227 } else { 3228 LOC_LOGD("Got Zpp fix location validity (lat:%d, lon:%d, timestamp:%d accuracy:%d)" 3229 " (%.7f, %.7f), timestamp %llu, accuracy %f", 3230 zpp_ind.latitude_valid, 3231 zpp_ind.longitude_valid, 3232 zpp_ind.timestampUtc_valid, 3233 zpp_ind.horUncCircular_valid, 3234 zpp_ind.latitude, 3235 zpp_ind.longitude, 3236 zpp_ind.timestampUtc, 3237 zpp_ind.horUncCircular); 3238 3239 zppLoc.size = sizeof(GpsLocation); 3240 if (zpp_ind.timestampUtc_valid) { 3241 zppLoc.timestamp = zpp_ind.timestampUtc; 3242 } 3243 else { 3244 /* The UTC time from modem is not valid. 3245 In this case, we use current system time instead.*/ 3246 3247 struct timespec time_info_current; 3248 clock_gettime(CLOCK_REALTIME,&time_info_current); 3249 zppLoc.timestamp = (time_info_current.tv_sec)*1e3 + 3250 (time_info_current.tv_nsec)/1e6; 3251 LOC_LOGD("zpp timestamp got from system: %llu", zppLoc.timestamp); 3252 } 3253 3254 if (zpp_ind.latitude_valid && 3255 zpp_ind.longitude_valid && 3256 zpp_ind.horUncCircular_valid ) { 3257 zppLoc.flags = GPS_LOCATION_HAS_LAT_LONG | GPS_LOCATION_HAS_ACCURACY; 3258 zppLoc.latitude = zpp_ind.latitude; 3259 zppLoc.longitude = zpp_ind.longitude; 3260 zppLoc.accuracy = zpp_ind.horUncCircular; 3261 3262 if (zpp_ind.altitudeWrtEllipsoid_valid) { 3263 zppLoc.flags |= GPS_LOCATION_HAS_ALTITUDE; 3264 zppLoc.altitude = zpp_ind.altitudeWrtEllipsoid; 3265 } 3266 3267 if (zpp_ind.horSpeed_valid) { 3268 zppLoc.flags |= GPS_LOCATION_HAS_SPEED; 3269 zppLoc.speed = zpp_ind.horSpeed; 3270 } 3271 3272 if (zpp_ind.heading_valid) { 3273 zppLoc.flags |= GPS_LOCATION_HAS_BEARING; 3274 zppLoc.bearing = zpp_ind.heading; 3275 } 3276 3277 if (zpp_ind.technologyMask_valid) { 3278 tech_mask = zpp_ind.technologyMask; 3279 } 3280 } 3281 } 3282 3283 return convertErr(status); 3284 } 3285 3286 /*Values for lock 3287 1 = Do not lock any position sessions 3288 2 = Lock MI position sessions 3289 3 = Lock MT position sessions 3290 4 = Lock all position sessions 3291 3292 Returns values: 3293 zero on success; non-zero on failure 3294 */ 3295 int LocApiV02 :: setGpsLock(LOC_GPS_LOCK_MASK lockMask) 3296 { 3297 qmiLocSetEngineLockReqMsgT_v02 setEngineLockReq; 3298 qmiLocSetEngineLockIndMsgT_v02 setEngineLockInd; 3299 locClientStatusEnumType status; 3300 locClientReqUnionType req_union; 3301 int ret=0; 3302 3303 LOC_LOGD("%s:%d]: Set Gps Lock: %x\n", __func__, __LINE__, lockMask); 3304 setEngineLockReq.lockType = convertGpsLockMask(lockMask); 3305 req_union.pSetEngineLockReq = &setEngineLockReq; 3306 memset(&setEngineLockInd, 0, sizeof(setEngineLockInd)); 3307 status = loc_sync_send_req(clientHandle, 3308 QMI_LOC_SET_ENGINE_LOCK_REQ_V02, 3309 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 3310 QMI_LOC_SET_ENGINE_LOCK_IND_V02, 3311 &setEngineLockInd); 3312 3313 if(status != eLOC_CLIENT_SUCCESS || setEngineLockInd.status != eQMI_LOC_SUCCESS_V02) { 3314 LOC_LOGE("%s:%d]: Set engine lock failed. status: %s, ind status:%s\n", 3315 __func__, __LINE__, 3316 loc_get_v02_client_status_name(status), 3317 loc_get_v02_qmi_status_name(setEngineLockInd.status)); 3318 ret = -1; 3319 } 3320 LOC_LOGD("%s:%d]: exit\n", __func__, __LINE__); 3321 return ret; 3322 } 3323 /* 3324 Returns 3325 Current value of GPS Lock on success 3326 -1 on failure 3327 */ 3328 int LocApiV02 :: getGpsLock() 3329 { 3330 qmiLocGetEngineLockReqMsgT_v02 getEngineLockReq; 3331 qmiLocGetEngineLockIndMsgT_v02 getEngineLockInd; 3332 locClientStatusEnumType status; 3333 locClientReqUnionType req_union; 3334 int ret=0; 3335 LOC_LOGD("%s:%d]: Enter\n", __func__, __LINE__); 3336 memset(&getEngineLockInd, 0, sizeof(getEngineLockInd)); 3337 3338 //Passing req_union as a parameter even though this request has no payload 3339 //since NULL or 0 gives an error during compilation 3340 status = loc_sync_send_req(clientHandle, 3341 QMI_LOC_GET_ENGINE_LOCK_REQ_V02, 3342 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 3343 QMI_LOC_GET_ENGINE_LOCK_IND_V02, 3344 &getEngineLockInd); 3345 if(status != eLOC_CLIENT_SUCCESS || getEngineLockInd.status != eQMI_LOC_SUCCESS_V02) { 3346 LOC_LOGE("%s:%d]: Set engine lock failed. status: %s, ind status:%s\n", 3347 __func__, __LINE__, 3348 loc_get_v02_client_status_name(status), 3349 loc_get_v02_qmi_status_name(getEngineLockInd.status)); 3350 ret = -1; 3351 } 3352 else { 3353 if(getEngineLockInd.lockType_valid) { 3354 ret = (int)getEngineLockInd.lockType; 3355 LOC_LOGD("%s:%d]: Lock Type: %d\n", __func__, __LINE__, ret); 3356 } 3357 else { 3358 LOC_LOGE("%s:%d]: Lock Type not valid\n", __func__, __LINE__); 3359 ret = -1; 3360 } 3361 } 3362 LOC_LOGD("%s:%d]: Exit\n", __func__, __LINE__); 3363 return ret; 3364 } 3365 3366 enum loc_api_adapter_err LocApiV02:: setXtraVersionCheck(enum xtra_version_check check) 3367 { 3368 qmiLocSetXtraVersionCheckReqMsgT_v02 req; 3369 qmiLocSetXtraVersionCheckIndMsgT_v02 ind; 3370 locClientStatusEnumType status; 3371 locClientReqUnionType req_union; 3372 enum loc_api_adapter_err ret = LOC_API_ADAPTER_ERR_SUCCESS; 3373 3374 LOC_LOGD("%s:%d]: Enter. check: %d", __func__, __LINE__, check); 3375 memset(&req, 0, sizeof(req)); 3376 memset(&ind, 0, sizeof(ind)); 3377 switch (check) { 3378 case DISABLED: 3379 req.xtraVersionCheckMode = eQMI_LOC_XTRA_VERSION_CHECK_DISABLE_V02; 3380 break; 3381 case AUTO: 3382 req.xtraVersionCheckMode = eQMI_LOC_XTRA_VERSION_CHECK_AUTO_V02; 3383 break; 3384 case XTRA2: 3385 req.xtraVersionCheckMode = eQMI_LOC_XTRA_VERSION_CHECK_XTRA2_V02; 3386 break; 3387 case XTRA3: 3388 req.xtraVersionCheckMode = eQMI_LOC_XTRA_VERSION_CHECK_XTRA3_V02; 3389 break; 3390 default: 3391 req.xtraVersionCheckMode = eQMI_LOC_XTRA_VERSION_CHECK_DISABLE_V02; 3392 break; 3393 } 3394 3395 req_union.pSetXtraVersionCheckReq = &req; 3396 status = loc_sync_send_req(clientHandle, 3397 QMI_LOC_SET_XTRA_VERSION_CHECK_REQ_V02, 3398 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 3399 QMI_LOC_SET_XTRA_VERSION_CHECK_IND_V02, 3400 &ind); 3401 if(status != eLOC_CLIENT_SUCCESS || ind.status != eQMI_LOC_SUCCESS_V02) { 3402 LOC_LOGE("%s:%d]: Set xtra version check failed. status: %s, ind status:%s\n", 3403 __func__, __LINE__, 3404 loc_get_v02_client_status_name(status), 3405 loc_get_v02_qmi_status_name(ind.status)); 3406 ret = LOC_API_ADAPTER_ERR_GENERAL_FAILURE; 3407 } 3408 3409 LOC_LOGD("%s:%d]: Exit. ret: %d", __func__, __LINE__, (int)ret); 3410 return ret; 3411 } 3412 3413 void LocApiV02 :: installAGpsCert(const DerEncodedCertificate* pData, 3414 size_t numberOfCerts, 3415 uint32_t slotBitMask) 3416 { 3417 LOC_LOGD("%s:%d]:, slot mask=%u number of certs=%u", 3418 __func__, __LINE__, slotBitMask, numberOfCerts); 3419 3420 uint8_t certIndex = 0; 3421 for (uint8_t slot = 0; slot <= AGPS_CERTIFICATE_MAX_SLOTS-1; slot++, slotBitMask >>= 1) 3422 { 3423 if (slotBitMask & 1) //slot is writable 3424 { 3425 if (certIndex < numberOfCerts && pData[certIndex].data && pData[certIndex].length > 0) 3426 { 3427 LOC_LOGD("%s:%d]:, Inject cert#%u slot=%u length=%u", 3428 __func__, __LINE__, certIndex, slot, pData[certIndex].length); 3429 3430 locClientReqUnionType req_union; 3431 locClientStatusEnumType status; 3432 qmiLocInjectSuplCertificateReqMsgT_v02 injectCertReq; 3433 qmiLocInjectSuplCertificateIndMsgT_v02 injectCertInd; 3434 3435 memset(&injectCertReq, 0, sizeof(injectCertReq)); 3436 injectCertReq.suplCertId = slot; 3437 injectCertReq.suplCertData_len = pData[certIndex].length; 3438 memcpy(injectCertReq.suplCertData, pData[certIndex].data, pData[certIndex].length); 3439 3440 req_union.pInjectSuplCertificateReq = &injectCertReq; 3441 3442 status = loc_sync_send_req(clientHandle, 3443 QMI_LOC_INJECT_SUPL_CERTIFICATE_REQ_V02, 3444 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 3445 QMI_LOC_INJECT_SUPL_CERTIFICATE_IND_V02, 3446 &injectCertInd); 3447 3448 if (status != eLOC_CLIENT_SUCCESS || 3449 eQMI_LOC_SUCCESS_V02 != injectCertInd.status) 3450 { 3451 LOC_LOGE ("%s:%d]: inject-error status = %s, set_server_ind.status = %s", 3452 __func__,__LINE__, 3453 loc_get_v02_client_status_name(status), 3454 loc_get_v02_qmi_status_name(injectCertInd.status)); 3455 } 3456 3457 certIndex++; //move to next cert 3458 3459 } else { 3460 3461 LOC_LOGD("%s:%d]:, Delete slot=%u", 3462 __func__, __LINE__, slot); 3463 3464 // A fake cert is injected first before delete is called to workaround 3465 // an issue that is seen with trying to delete an empty slot. 3466 { 3467 locClientReqUnionType req_union; 3468 locClientStatusEnumType status; 3469 qmiLocInjectSuplCertificateReqMsgT_v02 injectFakeCertReq; 3470 qmiLocInjectSuplCertificateIndMsgT_v02 injectFakeCertInd; 3471 3472 memset(&injectFakeCertReq, 0, sizeof(injectFakeCertReq)); 3473 injectFakeCertReq.suplCertId = slot; 3474 injectFakeCertReq.suplCertData_len = 1; 3475 injectFakeCertReq.suplCertData[0] = 1; 3476 3477 req_union.pInjectSuplCertificateReq = &injectFakeCertReq; 3478 3479 status = loc_sync_send_req(clientHandle, 3480 QMI_LOC_INJECT_SUPL_CERTIFICATE_REQ_V02, 3481 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 3482 QMI_LOC_INJECT_SUPL_CERTIFICATE_IND_V02, 3483 &injectFakeCertInd); 3484 3485 if (status != eLOC_CLIENT_SUCCESS || 3486 eQMI_LOC_SUCCESS_V02 != injectFakeCertInd.status) 3487 { 3488 LOC_LOGE ("%s:%d]: inject-fake-error status = %s, set_server_ind.status = %s", 3489 __func__,__LINE__, 3490 loc_get_v02_client_status_name(status), 3491 loc_get_v02_qmi_status_name(injectFakeCertInd.status)); 3492 } 3493 } 3494 3495 locClientReqUnionType req_union; 3496 locClientStatusEnumType status; 3497 qmiLocDeleteSuplCertificateReqMsgT_v02 deleteCertReq; 3498 qmiLocDeleteSuplCertificateIndMsgT_v02 deleteCertInd; 3499 3500 memset(&deleteCertReq, 0, sizeof(deleteCertReq)); 3501 deleteCertReq.suplCertId = slot; 3502 deleteCertReq.suplCertId_valid = 1; 3503 3504 req_union.pDeleteSuplCertificateReq = &deleteCertReq; 3505 3506 status = loc_sync_send_req(clientHandle, 3507 QMI_LOC_DELETE_SUPL_CERTIFICATE_REQ_V02, 3508 req_union, LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 3509 QMI_LOC_DELETE_SUPL_CERTIFICATE_IND_V02, 3510 &deleteCertInd); 3511 3512 if (status != eLOC_CLIENT_SUCCESS || 3513 eQMI_LOC_SUCCESS_V02 != deleteCertInd.status) 3514 { 3515 LOC_LOGE("%s:%d]: delete-error status = %s, set_server_ind.status = %s", 3516 __func__,__LINE__, 3517 loc_get_v02_client_status_name(status), 3518 loc_get_v02_qmi_status_name(deleteCertInd.status)); 3519 } 3520 } 3521 } else { 3522 LOC_LOGD("%s:%d]:, Not writable slot=%u", 3523 __func__, __LINE__, slot); 3524 } 3525 } 3526 } 3527 3528 /* 3529 Returns 3530 0: update the gps reporting event successfully 3531 -1: on failure 3532 */ 3533 int LocApiV02 :: updateRegistrationMask(LOC_API_ADAPTER_EVENT_MASK_T event, 3534 loc_registration_mask_status isEnabled) 3535 { 3536 LOC_LOGD("%s:%d]: Enter\n", __func__, __LINE__); 3537 3538 return open((isEnabled == LOC_REGISTRATION_MASK_ENABLED)?(mMask|event):(mMask&~event)); 3539 } 3540 3541 bool LocApiV02 :: gnssConstellationConfig() 3542 { 3543 return mGnssMeasurementSupported == sup_yes; 3544 } 3545 3546 void LocApiV02 :: cacheGnssMeasurementSupport() 3547 { 3548 if (sup_unknown == mGnssMeasurementSupported) { 3549 if ((mQmiMask & QMI_LOC_EVENT_MASK_POSITION_REPORT_V02) == 3550 QMI_LOC_EVENT_MASK_POSITION_REPORT_V02) { 3551 /*for GNSS Measurement service, use 3552 QMI_LOC_SET_GNSS_CONSTELL_REPORT_CONFIG_V02 3553 to check if modem support this feature or not*/ 3554 LOC_LOGD("%s:%d]: set GNSS measurement to report gps measurement only.\n", 3555 __func__, __LINE__); 3556 3557 qmiLocSetGNSSConstRepConfigReqMsgT_v02 setGNSSConstRepConfigReq; 3558 qmiLocSetGNSSConstRepConfigIndMsgT_v02 setGNSSConstRepConfigInd; 3559 memset(&setGNSSConstRepConfigReq, 0, sizeof(setGNSSConstRepConfigReq)); 3560 memset(&setGNSSConstRepConfigInd, 0, sizeof(setGNSSConstRepConfigInd)); 3561 3562 locClientStatusEnumType status; 3563 locClientReqUnionType req_union; 3564 3565 setGNSSConstRepConfigReq.measReportConfig_valid = true; 3566 setGNSSConstRepConfigReq.measReportConfig = eQMI_SYSTEM_GPS_V02; 3567 req_union.pSetGNSSConstRepConfigReq = &setGNSSConstRepConfigReq; 3568 3569 status = loc_sync_send_req(clientHandle, 3570 QMI_LOC_SET_GNSS_CONSTELL_REPORT_CONFIG_V02, 3571 req_union, 3572 LOC_ENGINE_SYNC_REQUEST_TIMEOUT, 3573 QMI_LOC_SET_GNSS_CONSTELL_REPORT_CONFIG_IND_V02, 3574 &setGNSSConstRepConfigInd); 3575 3576 if(status != eLOC_CLIENT_SUCCESS || 3577 setGNSSConstRepConfigInd.status != eQMI_LOC_SUCCESS_V02) { 3578 LOC_LOGD("%s:%d]: Set GNSS constellation failed." 3579 " status: %s, ind status:%s\n", 3580 __func__, __LINE__, 3581 loc_get_v02_client_status_name(status), 3582 loc_get_v02_qmi_status_name(setGNSSConstRepConfigInd.status)); 3583 mGnssMeasurementSupported = sup_no; 3584 } else { 3585 LOC_LOGD("%s:%d]: Set GNSS constellation succeeded.\n", 3586 __func__, __LINE__); 3587 mGnssMeasurementSupported = sup_yes; 3588 } 3589 } 3590 } 3591 3592 LOC_LOGV("%s:%d]: mGnssMeasurementSupported is %d\n", __func__, __LINE__, mGnssMeasurementSupported); 3593 } 3594