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