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