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