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