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