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 Foundation, 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_NDDEBUG 0
30 #define LOG_TAG "LocSvc_api_rpc"
31
32 #include <unistd.h>
33 #include <math.h>
34 #ifndef USE_GLIB
35 #include <utils/SystemClock.h>
36 #endif /* USE_GLIB */
37 #include <LocApiRpc.h>
38 #include <LocAdapterBase.h>
39 #include <loc_api_fixup.h>
40 #include <loc_api_rpc_glue.h>
41 #include <log_util.h>
42 #include <loc_log.h>
43 #include <loc_api_log.h>
44 #ifdef USE_GLIB
45 #include <glib.h>
46 #endif
47 #include <librpc.h>
48 #include <platform_lib_includes.h>
49
50 using namespace loc_core;
51
52 #define LOC_XTRA_INJECT_DEFAULT_TIMEOUT (3100)
53 #define XTRA_BLOCK_SIZE (3072)
54 #define LOC_IOCTL_DEFAULT_TIMEOUT 1000 // 1000 milli-seconds
55 #define LOC_NI_NOTIF_KEY_ADDRESS "Address"
56
57 /*===========================================================================
58 FUNCTION loc_event_cb
59
60 DESCRIPTION
61 This is the callback function registered by loc_open.
62
63 DEPENDENCIES
64 N/A
65
66 RETURN VALUE
67 RPC_LOC_API_SUCCESS
68
69 SIDE EFFECTS
70 N/A
71
72 ===========================================================================*/
loc_event_cb(void * user,rpc_loc_client_handle_type client_handle,rpc_loc_event_mask_type loc_event,const rpc_loc_event_payload_u_type * loc_event_payload)73 static int32 loc_event_cb
74 (
75 void* user,
76 rpc_loc_client_handle_type client_handle,
77 rpc_loc_event_mask_type loc_event,
78 const rpc_loc_event_payload_u_type* loc_event_payload
79 )
80 {
81 MODEM_LOG_CALLFLOW(%s, loc_get_event_name(loc_event));
82 loc_callback_log(loc_event, loc_event_payload);
83 int32 ret_val = ((LocApiRpc*)user)->locEventCB(client_handle, loc_event, loc_event_payload);
84 EXIT_LOG(%d, ret_val);
85 return ret_val;
86 }
87
88 /*===========================================================================
89 FUNCTION loc_eng_rpc_global_cb
90
91 DESCRIPTION
92 This is the callback function registered by loc_open for RPC global events
93
94 DEPENDENCIES
95 N/A
96
97 RETURN VALUE
98 RPC_LOC_API_SUCCESS
99
100 SIDE EFFECTS
101 N/A
102
103 ===========================================================================*/
loc_rpc_global_cb(void * user,CLIENT * clnt,enum rpc_reset_event event)104 static void loc_rpc_global_cb(void* user, CLIENT* clnt, enum rpc_reset_event event)
105 {
106 MODEM_LOG_CALLFLOW(%s, loc_get_rpc_reset_event_name(event));
107 ((LocApiRpc*)user)->locRpcGlobalCB(clnt, event);
108 EXIT_LOG(%p, VOID_RET);
109 }
110
111 const LOC_API_ADAPTER_EVENT_MASK_T LocApiRpc::maskAll =
112 LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT |
113 LOC_API_ADAPTER_BIT_SATELLITE_REPORT |
114 LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST |
115 LOC_API_ADAPTER_BIT_ASSISTANCE_DATA_REQUEST |
116 LOC_API_ADAPTER_BIT_IOCTL_REPORT |
117 LOC_API_ADAPTER_BIT_STATUS_REPORT |
118 LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT |
119 LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST;
120
121 const rpc_loc_event_mask_type LocApiRpc::locBits[] =
122 {
123 RPC_LOC_EVENT_PARSED_POSITION_REPORT,
124 RPC_LOC_EVENT_SATELLITE_REPORT,
125 RPC_LOC_EVENT_NMEA_1HZ_REPORT,
126 RPC_LOC_EVENT_NMEA_POSITION_REPORT,
127 RPC_LOC_EVENT_NI_NOTIFY_VERIFY_REQUEST,
128 RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST,
129 RPC_LOC_EVENT_LOCATION_SERVER_REQUEST,
130 RPC_LOC_EVENT_IOCTL_REPORT,
131 RPC_LOC_EVENT_STATUS_REPORT,
132 RPC_LOC_EVENT_WPS_NEEDED_REQUEST
133 };
134
135 // constructor
LocApiRpc(const MsgTask * msgTask,LOC_API_ADAPTER_EVENT_MASK_T exMask,ContextBase * context)136 LocApiRpc::LocApiRpc(const MsgTask* msgTask,
137 LOC_API_ADAPTER_EVENT_MASK_T exMask,
138 ContextBase* context) :
139 LocApiBase(msgTask, exMask, context),
140 client_handle(RPC_LOC_CLIENT_HANDLE_INVALID),
141 dataEnableLastSet(-1)
142 {
143 memset(apnLastSet, 0, sizeof(apnLastSet));
144 loc_api_glue_init();
145 }
146
~LocApiRpc()147 LocApiRpc::~LocApiRpc()
148 {
149 close();
150 }
151
152 rpc_loc_event_mask_type
convertMask(LOC_API_ADAPTER_EVENT_MASK_T mask)153 LocApiRpc::convertMask(LOC_API_ADAPTER_EVENT_MASK_T mask)
154 {
155 rpc_loc_event_mask_type newMask = 0;
156
157 for (unsigned int i = 0, bit=1; 0 != mask; i++, bit<<=1) {
158 if (mask & bit) {
159 newMask |= locBits[i];
160 mask ^= bit;
161 }
162 }
163
164 return newMask;
165 }
166
167 rpc_loc_lock_e_type
convertGpsLockMask(LOC_GPS_LOCK_MASK lockMask)168 LocApiRpc::convertGpsLockMask(LOC_GPS_LOCK_MASK lockMask)
169 {
170 if (isGpsLockAll(lockMask))
171 return RPC_LOC_LOCK_ALL;
172 if (isGpsLockMO(lockMask))
173 return RPC_LOC_LOCK_MI;
174 if (isGpsLockMT(lockMask))
175 return RPC_LOC_LOCK_MT;
176 if (isGpsLockNone(lockMask))
177 return RPC_LOC_LOCK_NONE;
178 return (rpc_loc_lock_e_type)lockMask;
179 }
180
181 enum loc_api_adapter_err
convertErr(int rpcErr)182 LocApiRpc::convertErr(int rpcErr)
183 {
184 switch(rpcErr)
185 {
186 case RPC_LOC_API_SUCCESS:
187 return LOC_API_ADAPTER_ERR_SUCCESS;
188 case RPC_LOC_API_GENERAL_FAILURE:
189 return LOC_API_ADAPTER_ERR_GENERAL_FAILURE;
190 case RPC_LOC_API_UNSUPPORTED:
191 return LOC_API_ADAPTER_ERR_UNSUPPORTED;
192 case RPC_LOC_API_INVALID_HANDLE:
193 return LOC_API_ADAPTER_ERR_INVALID_HANDLE;
194 case RPC_LOC_API_INVALID_PARAMETER:
195 return LOC_API_ADAPTER_ERR_INVALID_PARAMETER;
196 case RPC_LOC_API_ENGINE_BUSY:
197 return LOC_API_ADAPTER_ERR_ENGINE_BUSY;
198 case RPC_LOC_API_PHONE_OFFLINE:
199 return LOC_API_ADAPTER_ERR_PHONE_OFFLINE;
200 case RPC_LOC_API_TIMEOUT:
201 return LOC_API_ADAPTER_ERR_TIMEOUT;
202 case RPC_LOC_API_RPC_MODEM_RESTART:
203 return LOC_API_ADAPTER_ERR_ENGINE_DOWN;
204 case RPC_LOC_API_RPC_FAILURE:
205 return LOC_API_ADAPTER_ERR_FAILURE;
206 default:
207 return LOC_API_ADAPTER_ERR_UNKNOWN;
208 }
209 }
210
locRpcGlobalCB(CLIENT * clnt,enum rpc_reset_event event)211 void LocApiRpc::locRpcGlobalCB(CLIENT* clnt, enum rpc_reset_event event)
212 {
213 static rpc_loc_engine_state_e_type last_state = RPC_LOC_ENGINE_STATE_MAX;
214
215 switch (event) {
216 case RPC_SUBSYSTEM_RESTART_BEGIN:
217 if (RPC_LOC_ENGINE_STATE_OFF != last_state) {
218 last_state = RPC_LOC_ENGINE_STATE_OFF;
219 handleEngineDownEvent();
220 }
221 break;
222 case RPC_SUBSYSTEM_RESTART_END:
223 if (RPC_LOC_ENGINE_STATE_ON != last_state) {
224 last_state = RPC_LOC_ENGINE_STATE_ON;
225 handleEngineUpEvent();
226 }
227 break;
228 }
229 }
230
locEventCB(rpc_loc_client_handle_type client_handle,rpc_loc_event_mask_type loc_event,const rpc_loc_event_payload_u_type * loc_event_payload)231 int32 LocApiRpc::locEventCB(rpc_loc_client_handle_type client_handle,
232 rpc_loc_event_mask_type loc_event,
233 const rpc_loc_event_payload_u_type* loc_event_payload)
234 {
235 // Parsed report
236 if (loc_event & RPC_LOC_EVENT_PARSED_POSITION_REPORT)
237 {
238 reportPosition(&loc_event_payload->rpc_loc_event_payload_u_type_u.
239 parsed_location_report);
240 }
241
242 // Satellite report
243 if (loc_event & RPC_LOC_EVENT_SATELLITE_REPORT)
244 {
245 reportSv(&loc_event_payload->rpc_loc_event_payload_u_type_u.gnss_report);
246 }
247
248 // Status report
249 if (loc_event & RPC_LOC_EVENT_STATUS_REPORT)
250 {
251 reportStatus(&loc_event_payload->rpc_loc_event_payload_u_type_u.status_report);
252 }
253
254 // NMEA
255 if (loc_event & RPC_LOC_EVENT_NMEA_1HZ_REPORT)
256 {
257 reportNmea(&(loc_event_payload->rpc_loc_event_payload_u_type_u.nmea_report));
258 }
259 // XTRA support: supports only XTRA download
260 if (loc_event & RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST)
261 {
262 if (loc_event_payload->rpc_loc_event_payload_u_type_u.assist_data_request.event ==
263 RPC_LOC_ASSIST_DATA_PREDICTED_ORBITS_REQ)
264 {
265 requestXtraData();
266 } else if (loc_event_payload->rpc_loc_event_payload_u_type_u.assist_data_request.event ==
267 RPC_LOC_ASSIST_DATA_TIME_REQ)
268 {
269 requestTime();
270 } else if (loc_event_payload->rpc_loc_event_payload_u_type_u.assist_data_request.event ==
271 RPC_LOC_ASSIST_DATA_POSITION_INJECTION_REQ)
272 {
273 requestLocation();
274 }
275 }
276
277 // AGPS data request
278 if (loc_event & RPC_LOC_EVENT_LOCATION_SERVER_REQUEST)
279 {
280 ATLEvent(&loc_event_payload->rpc_loc_event_payload_u_type_u.
281 loc_server_request);
282 }
283
284 // NI notify request
285 if (loc_event & RPC_LOC_EVENT_NI_NOTIFY_VERIFY_REQUEST)
286 {
287 NIEvent(&loc_event_payload->rpc_loc_event_payload_u_type_u.ni_request);
288 }
289
290 return RPC_LOC_API_SUCCESS;//We simply want to return sucess here as we do not want to
291 // cause any issues in RPC thread context
292 }
293
294 enum loc_api_adapter_err
open(LOC_API_ADAPTER_EVENT_MASK_T mask)295 LocApiRpc::open(LOC_API_ADAPTER_EVENT_MASK_T mask)
296 {
297 enum loc_api_adapter_err ret_val = LOC_API_ADAPTER_ERR_SUCCESS;
298
299 // RPC does not dynamically update the event mask. And in the
300 // case of RPC, all we support are positioning (gps + agps)
301 // masks anyways, so we simply mask all of them on always.
302 // After doing so the first time in a power cycle, we know there
303 // will the following if condition will never be true any more.
304 mask = maskAll;
305
306 if (mask != mMask) {
307 if (RPC_LOC_CLIENT_HANDLE_INVALID != client_handle) {
308 close();
309 }
310
311 mMask = mask;
312 // it is important to cap the mask here, because not all LocApi's
313 // can enable the same bits, e.g. foreground and bckground.
314 client_handle = loc_open(convertMask(mask),
315 loc_event_cb,
316 loc_rpc_global_cb, this);
317
318 if (client_handle < 0) {
319 mMask = 0;
320 client_handle = RPC_LOC_CLIENT_HANDLE_INVALID;
321 ret_val = LOC_API_ADAPTER_ERR_INVALID_HANDLE;
322 }
323 }
324
325 return ret_val;
326 }
327
328 enum loc_api_adapter_err
close()329 LocApiRpc::close()
330 {
331 if (RPC_LOC_CLIENT_HANDLE_INVALID != client_handle) {
332 loc_clear(client_handle);
333 }
334
335 loc_close(client_handle);
336 mMask = 0;
337 client_handle = RPC_LOC_CLIENT_HANDLE_INVALID;
338
339 return LOC_API_ADAPTER_ERR_SUCCESS;
340 }
341
342 enum loc_api_adapter_err
startFix(const LocPosMode & posMode)343 LocApiRpc::startFix(const LocPosMode& posMode) {
344 LOC_LOGD("LocApiRpc::startFix() called");
345 return convertErr(
346 loc_start_fix(client_handle)
347 );
348 }
349
350 enum loc_api_adapter_err
stopFix()351 LocApiRpc::stopFix() {
352 LOC_LOGD("LocApiRpc::stopFix() called");
353 return convertErr(
354 loc_stop_fix(client_handle)
355 );
356 }
357
358 enum loc_api_adapter_err
setPositionMode(const LocPosMode & posMode)359 LocApiRpc::setPositionMode(const LocPosMode& posMode)
360 {
361 rpc_loc_ioctl_data_u_type ioctl_data;
362 rpc_loc_fix_criteria_s_type *fix_criteria_ptr =
363 &ioctl_data.rpc_loc_ioctl_data_u_type_u.fix_criteria;
364 rpc_loc_ioctl_e_type ioctl_type = RPC_LOC_IOCTL_SET_FIX_CRITERIA;
365 rpc_loc_operation_mode_e_type op_mode;
366 int ret_val;
367 const LocPosMode* fixCriteria = &posMode;
368
369 ALOGD ("loc_eng_set_position mode, client = %d, interval = %d, mode = %d\n",
370 (int32) client_handle, fixCriteria->min_interval, fixCriteria->mode);
371
372 switch (fixCriteria->mode)
373 {
374 case LOC_POSITION_MODE_MS_BASED:
375 op_mode = RPC_LOC_OPER_MODE_MSB;
376 break;
377 case LOC_POSITION_MODE_MS_ASSISTED:
378 op_mode = RPC_LOC_OPER_MODE_MSA;
379 break;
380 case LOC_POSITION_MODE_RESERVED_1:
381 op_mode = RPC_LOC_OPER_MODE_SPEED_OPTIMAL;
382 break;
383 case LOC_POSITION_MODE_RESERVED_2:
384 op_mode = RPC_LOC_OPER_MODE_ACCURACY_OPTIMAL;
385 break;
386 case LOC_POSITION_MODE_RESERVED_3:
387 op_mode = RPC_LOC_OPER_MODE_DATA_OPTIMAL;
388 break;
389 case LOC_POSITION_MODE_RESERVED_4:
390 case LOC_POSITION_MODE_RESERVED_5:
391 op_mode = RPC_LOC_OPER_MODE_MSA;
392 fix_criteria_ptr->preferred_response_time = 0;
393 break;
394 default:
395 op_mode = RPC_LOC_OPER_MODE_STANDALONE;
396 }
397
398 fix_criteria_ptr->valid_mask = RPC_LOC_FIX_CRIT_VALID_PREFERRED_OPERATION_MODE |
399 RPC_LOC_FIX_CRIT_VALID_RECURRENCE_TYPE;
400 fix_criteria_ptr->min_interval = fixCriteria->min_interval;
401 fix_criteria_ptr->preferred_operation_mode = op_mode;
402
403 fix_criteria_ptr->min_interval = fixCriteria->min_interval;
404 fix_criteria_ptr->valid_mask |= RPC_LOC_FIX_CRIT_VALID_MIN_INTERVAL;
405
406 if (fixCriteria->preferred_accuracy > 0) {
407 fix_criteria_ptr->preferred_accuracy = fixCriteria->preferred_accuracy;
408 fix_criteria_ptr->valid_mask |= RPC_LOC_FIX_CRIT_VALID_PREFERRED_ACCURACY;
409 }
410 if (fixCriteria->preferred_time > 0) {
411 fix_criteria_ptr->preferred_response_time = fixCriteria->preferred_time;
412 fix_criteria_ptr->valid_mask |= RPC_LOC_FIX_CRIT_VALID_PREFERRED_RESPONSE_TIME;
413 }
414
415 switch (fixCriteria->recurrence) {
416 case GPS_POSITION_RECURRENCE_SINGLE:
417 fix_criteria_ptr->recurrence_type = RPC_LOC_SINGLE_FIX;
418 break;
419 case GPS_POSITION_RECURRENCE_PERIODIC:
420 default:
421 fix_criteria_ptr->recurrence_type = RPC_LOC_PERIODIC_FIX;
422 break;
423 }
424 ioctl_data.disc = ioctl_type;
425
426 ret_val = loc_eng_ioctl (client_handle,
427 ioctl_type,
428 &ioctl_data,
429 LOC_IOCTL_DEFAULT_TIMEOUT,
430 NULL /* No output information is expected*/);
431
432 return convertErr(ret_val);
433 }
434
435 enum loc_api_adapter_err
setTime(GpsUtcTime time,int64_t timeReference,int uncertainty)436 LocApiRpc::setTime(GpsUtcTime time, int64_t timeReference, int uncertainty)
437 {
438 rpc_loc_ioctl_data_u_type ioctl_data;
439 rpc_loc_assist_data_time_s_type *time_info_ptr;
440 rpc_loc_ioctl_e_type ioctl_type = RPC_LOC_IOCTL_INJECT_UTC_TIME;
441 int ret_val;
442
443 LOC_LOGD ("loc_eng_inject_time, uncertainty = %d\n", uncertainty);
444
445 time_info_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.assistance_data_time;
446 time_info_ptr->time_utc = time;
447 time_info_ptr->time_utc += (int64_t)(ELAPSED_MILLIS_SINCE_BOOT_PLATFORM_LIB_ABSTRACTION - timeReference);
448 time_info_ptr->uncertainty = uncertainty; // Uncertainty in ms
449
450 ioctl_data.disc = ioctl_type;
451
452 ret_val = loc_eng_ioctl (client_handle,
453 ioctl_type,
454 &ioctl_data,
455 LOC_IOCTL_DEFAULT_TIMEOUT,
456 NULL /* No output information is expected*/);
457
458 return convertErr(ret_val);
459 }
460
461 enum loc_api_adapter_err
injectPosition(double latitude,double longitude,float accuracy)462 LocApiRpc::injectPosition(double latitude, double longitude, float accuracy)
463 {
464 /* IOCTL data */
465 rpc_loc_ioctl_data_u_type ioctl_data;
466 rpc_loc_assist_data_pos_s_type *assistance_data_position =
467 &ioctl_data.rpc_loc_ioctl_data_u_type_u.assistance_data_position;
468 int ret_val;
469
470 /************************************************
471 * Fill in latitude, longitude & accuracy
472 ************************************************/
473
474 /* This combo is required */
475 assistance_data_position->valid_mask =
476 RPC_LOC_ASSIST_POS_VALID_LATITUDE |
477 RPC_LOC_ASSIST_POS_VALID_LONGITUDE |
478 RPC_LOC_ASSIST_POS_VALID_HOR_UNC_CIRCULAR |
479 RPC_LOC_ASSIST_POS_VALID_CONFIDENCE_HORIZONTAL;
480
481 assistance_data_position->latitude = latitude;
482 assistance_data_position->longitude = longitude;
483 assistance_data_position->hor_unc_circular = accuracy; /* Meters assumed */
484 assistance_data_position->confidence_horizontal = 63; /* 63% (1 std dev) assumed */
485
486 /* Log */
487 LOC_LOGD("Inject coarse position Lat=%lf, Lon=%lf, Acc=%.2lf\n",
488 (double) assistance_data_position->latitude,
489 (double) assistance_data_position->longitude,
490 (double) assistance_data_position->hor_unc_circular);
491
492 ret_val = loc_eng_ioctl( client_handle,
493 RPC_LOC_IOCTL_INJECT_POSITION,
494 &ioctl_data,
495 LOC_IOCTL_DEFAULT_TIMEOUT,
496 NULL /* No output information is expected*/);
497 return convertErr(ret_val);
498 }
499
500 enum loc_api_adapter_err
informNiResponse(GpsUserResponseType userResponse,const void * passThroughData)501 LocApiRpc::informNiResponse(GpsUserResponseType userResponse,
502 const void* passThroughData)
503 {
504 rpc_loc_ioctl_data_u_type data;
505 rpc_loc_ioctl_callback_s_type callback_payload;
506
507 memcpy(&data.rpc_loc_ioctl_data_u_type_u.user_verify_resp.ni_event_pass_back,
508 passThroughData, sizeof (rpc_loc_ni_event_s_type));
509
510 rpc_loc_ni_user_resp_e_type resp;
511 switch (userResponse)
512 {
513 case GPS_NI_RESPONSE_ACCEPT:
514 data.rpc_loc_ioctl_data_u_type_u.user_verify_resp.user_resp =
515 RPC_LOC_NI_LCS_NOTIFY_VERIFY_ACCEPT;
516 break;
517 case GPS_NI_RESPONSE_DENY:
518 data.rpc_loc_ioctl_data_u_type_u.user_verify_resp.user_resp =
519 RPC_LOC_NI_LCS_NOTIFY_VERIFY_DENY;
520 break;
521 case GPS_NI_RESPONSE_NORESP:
522 default:
523 data.rpc_loc_ioctl_data_u_type_u.user_verify_resp.user_resp =
524 RPC_LOC_NI_LCS_NOTIFY_VERIFY_NORESP;
525 break;
526 }
527
528 return convertErr(
529 loc_eng_ioctl(client_handle,
530 RPC_LOC_IOCTL_INFORM_NI_USER_RESPONSE,
531 &data,
532 LOC_IOCTL_DEFAULT_TIMEOUT,
533 &callback_payload)
534 );
535 }
536
537 enum loc_api_adapter_err
setAPN(char * apn,int len,boolean force)538 LocApiRpc::setAPN(char* apn, int len, boolean force)
539 {
540 enum loc_api_adapter_err rtv = LOC_API_ADAPTER_ERR_SUCCESS;
541 int size = sizeof(apnLastSet);
542 if (force || memcmp(apnLastSet, apn, size)) {
543 if (len < size) {
544 // size will be not larger than its original value
545 size = len + 1;
546 }
547 memcpy(apnLastSet, apn, size);
548
549 if (!isInSession()) {
550 rpc_loc_ioctl_data_u_type ioctl_data = {RPC_LOC_IOCTL_SET_LBS_APN_PROFILE, {0}};
551 ioctl_data.rpc_loc_ioctl_data_u_type_u.apn_profiles[0].srv_system_type = LOC_APN_PROFILE_SRV_SYS_MAX;
552 ioctl_data.rpc_loc_ioctl_data_u_type_u.apn_profiles[0].pdp_type = LOC_APN_PROFILE_PDN_TYPE_IPV4;
553 memcpy(&(ioctl_data.rpc_loc_ioctl_data_u_type_u.apn_profiles[0].apn_name), apn, size);
554
555 rtv = convertErr(
556 loc_eng_ioctl (client_handle,
557 RPC_LOC_IOCTL_SET_LBS_APN_PROFILE,
558 &ioctl_data,
559 LOC_IOCTL_DEFAULT_TIMEOUT,
560 NULL)
561 );
562 }
563 }
564 return rtv;
565 }
566
setInSession(bool inSession)567 void LocApiRpc::setInSession(bool inSession)
568 {
569 if (!inSession) {
570 enableData(dataEnableLastSet, true);
571 setAPN(apnLastSet, sizeof(apnLastSet)-1, true);
572 }
573 }
574
575 enum loc_api_adapter_err
setServer(const char * url,int len)576 LocApiRpc::setServer(const char* url, int len)
577 {
578 rpc_loc_ioctl_data_u_type ioctl_data;
579 rpc_loc_server_info_s_type *server_info_ptr;
580 rpc_loc_ioctl_e_type ioctl_cmd;
581
582 ioctl_cmd = RPC_LOC_IOCTL_SET_UMTS_SLP_SERVER_ADDR;
583 ioctl_data.disc = ioctl_cmd;
584 server_info_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.server_addr;
585 server_info_ptr->addr_type = RPC_LOC_SERVER_ADDR_URL;
586 server_info_ptr->addr_info.disc = server_info_ptr->addr_type;
587 server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.length = len;
588 #if (AMSS_VERSION==3200)
589 server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.addr.addr_val = (char*) url;
590 server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.addr.addr_len= len;
591 #else
592 strlcpy(server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.addr, url,
593 sizeof server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.url.addr);
594 #endif /* #if (AMSS_VERSION==3200) */
595 LOC_LOGD ("loc_eng_set_server, addr = %s\n", url);
596
597 return convertErr(
598 loc_eng_ioctl (client_handle,
599 ioctl_cmd,
600 &ioctl_data,
601 LOC_IOCTL_DEFAULT_TIMEOUT,
602 NULL /* No output information is expected*/)
603 );
604 }
605
606 enum loc_api_adapter_err
setServer(unsigned int ip,int port,LocServerType type)607 LocApiRpc::setServer(unsigned int ip, int port, LocServerType type)
608 {
609 rpc_loc_ioctl_data_u_type ioctl_data;
610 rpc_loc_server_info_s_type *server_info_ptr;
611 rpc_loc_ioctl_e_type ioctl_cmd;
612
613 switch (type) {
614 case LOC_AGPS_MPC_SERVER:
615 ioctl_cmd = RPC_LOC_IOCTL_SET_CDMA_MPC_SERVER_ADDR;
616 break;
617 case LOC_AGPS_CUSTOM_PDE_SERVER:
618 ioctl_cmd = RPC_LOC_IOCTL_SET_CUSTOM_PDE_SERVER_ADDR;
619 break;
620 default:
621 ioctl_cmd = RPC_LOC_IOCTL_SET_CDMA_PDE_SERVER_ADDR;
622 break;
623 }
624 ioctl_data.disc = ioctl_cmd;
625 server_info_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.server_addr;
626 server_info_ptr->addr_type = RPC_LOC_SERVER_ADDR_IPV4;
627 server_info_ptr->addr_info.disc = server_info_ptr->addr_type;
628 server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.ipv4.addr = ip;
629 server_info_ptr->addr_info.rpc_loc_server_addr_u_type_u.ipv4.port = port;
630 LOC_LOGD ("setServer, addr = %X:%d\n", (unsigned int) ip, (unsigned int) port);
631
632 return convertErr(
633 loc_eng_ioctl (client_handle,
634 ioctl_cmd,
635 &ioctl_data,
636 LOC_IOCTL_DEFAULT_TIMEOUT,
637 NULL /* No output information is expected*/)
638 );
639 }
640
641 enum loc_api_adapter_err
enableData(int enable,boolean force)642 LocApiRpc::enableData(int enable, boolean force)
643 {
644 enum loc_api_adapter_err rtv = LOC_API_ADAPTER_ERR_SUCCESS;
645 if (force || dataEnableLastSet != enable) {
646 dataEnableLastSet = enable;
647
648 if (!isInSession()) {
649 rpc_loc_ioctl_data_u_type ioctl_data = {RPC_LOC_IOCTL_SET_DATA_ENABLE, {0}};
650
651 ioctl_data.rpc_loc_ioctl_data_u_type_u.data_enable = enable;
652 rtv = convertErr(
653 loc_eng_ioctl (client_handle,
654 RPC_LOC_IOCTL_SET_DATA_ENABLE,
655 &ioctl_data,
656 LOC_IOCTL_DEFAULT_TIMEOUT,
657 NULL)
658 );
659 }
660 }
661 return rtv;
662 }
663
664 enum loc_api_adapter_err
deleteAidingData(GpsAidingData bits)665 LocApiRpc::deleteAidingData(GpsAidingData bits)
666 {
667 rpc_loc_ioctl_data_u_type ioctl_data = {RPC_LOC_IOCTL_DELETE_ASSIST_DATA, {0}};
668 ioctl_data.rpc_loc_ioctl_data_u_type_u.assist_data_delete.type = bits;
669
670 return convertErr(
671 loc_eng_ioctl (client_handle,
672 RPC_LOC_IOCTL_DELETE_ASSIST_DATA,
673 &ioctl_data,
674 LOC_IOCTL_DEFAULT_TIMEOUT,
675 NULL)
676 );
677 }
678
reportPosition(const rpc_loc_parsed_position_s_type * location_report_ptr)679 void LocApiRpc::reportPosition(const rpc_loc_parsed_position_s_type *location_report_ptr)
680 {
681 LocPosTechMask tech_Mask = LOC_POS_TECH_MASK_DEFAULT;
682
683 UlpLocation location = {0};
684 GpsLocationExtended locationExtended = {0};
685
686 location.size = sizeof(location);
687 locationExtended.size = sizeof(locationExtended);
688 if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_SESSION_STATUS)
689 {
690 // Process the position from final and intermediate reports
691 if (location_report_ptr->session_status == RPC_LOC_SESS_STATUS_SUCCESS ||
692 location_report_ptr->session_status == RPC_LOC_SESS_STATUS_IN_PROGESS)
693 {
694 // Latitude & Longitude
695 if ((location_report_ptr->valid_mask & RPC_LOC_POS_VALID_LATITUDE) &&
696 (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_LONGITUDE) &&
697 (location_report_ptr->latitude != 0 ||
698 location_report_ptr->longitude != 0))
699 {
700 location.gpsLocation.flags |= GPS_LOCATION_HAS_LAT_LONG;
701 location.gpsLocation.latitude = location_report_ptr->latitude;
702 location.gpsLocation.longitude = location_report_ptr->longitude;
703
704 // Time stamp (UTC)
705 if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_TIMESTAMP_UTC)
706 {
707 location.gpsLocation.timestamp = location_report_ptr->timestamp_utc;
708 }
709
710 // Altitude
711 if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_ALTITUDE_WRT_ELLIPSOID )
712 {
713 location.gpsLocation.flags |= GPS_LOCATION_HAS_ALTITUDE;
714 location.gpsLocation.altitude = location_report_ptr->altitude_wrt_ellipsoid;
715 }
716
717 // Speed
718 if ((location_report_ptr->valid_mask & RPC_LOC_POS_VALID_SPEED_HORIZONTAL) &&
719 (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_SPEED_VERTICAL))
720 {
721 location.gpsLocation.flags |= GPS_LOCATION_HAS_SPEED;
722 location.gpsLocation.speed = sqrt(location_report_ptr->speed_horizontal * location_report_ptr->speed_horizontal +
723 location_report_ptr->speed_vertical * location_report_ptr->speed_vertical);
724 }
725
726 // Heading
727 if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_HEADING)
728 {
729 location.gpsLocation.flags |= GPS_LOCATION_HAS_BEARING;
730 location.gpsLocation.bearing = location_report_ptr->heading;
731 }
732
733 // Uncertainty (circular)
734 if ( (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_HOR_UNC_CIRCULAR) )
735 {
736 location.gpsLocation.flags |= GPS_LOCATION_HAS_ACCURACY;
737 location.gpsLocation.accuracy = location_report_ptr->hor_unc_circular;
738 }
739
740 // Technology Mask
741
742 tech_Mask |= location_report_ptr->technology_mask;
743 //Mark the location source as from GNSS
744 location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO;
745 location.position_source = ULP_LOCATION_IS_FROM_GNSS;
746 if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_ALTITUDE_WRT_MEAN_SEA_LEVEL)
747 {
748 locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL;
749 locationExtended.altitudeMeanSeaLevel = location_report_ptr->altitude_wrt_mean_sea_level;
750 }
751
752 if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_MAGNETIC_VARIATION )
753 {
754 locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_MAG_DEV;
755 locationExtended.magneticDeviation = location_report_ptr->magnetic_deviation;
756 }
757
758 if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_VERTICAL_UNC)
759 {
760 locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_VERT_UNC;
761 locationExtended.vert_unc = location_report_ptr->vert_unc;
762 }
763
764 if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_SPEED_UNC)
765 {
766 locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_SPEED_UNC;
767 locationExtended.speed_unc = location_report_ptr->speed_unc;
768 }
769
770 LOC_LOGV("reportPosition: fire callback\n");
771 enum loc_sess_status fixStatus =
772 (location_report_ptr->session_status
773 == RPC_LOC_SESS_STATUS_IN_PROGESS ?
774 LOC_SESS_INTERMEDIATE : LOC_SESS_SUCCESS);
775 LocApiBase::reportPosition(location,
776 locationExtended,
777 (void*)location_report_ptr,
778 fixStatus,
779 tech_Mask);
780 }
781 }
782 else
783 {
784 LocApiBase::reportPosition(location,
785 locationExtended,
786 NULL,
787 LOC_SESS_FAILURE);
788 LOC_LOGV("loc_eng_report_position: ignore position report "
789 "when session status = %d\n",
790 location_report_ptr->session_status);
791 }
792 }
793 else
794 {
795 LOC_LOGV("loc_eng_report_position: ignore position report "
796 "when session status is not set\n");
797 }
798 }
799
reportSv(const rpc_loc_gnss_info_s_type * gnss_report_ptr)800 void LocApiRpc::reportSv(const rpc_loc_gnss_info_s_type *gnss_report_ptr)
801 {
802 GpsSvStatus SvStatus = {0};
803 GpsLocationExtended locationExtended = {0};
804 locationExtended.size = sizeof(locationExtended);
805 int num_svs_max = 0;
806 const rpc_loc_sv_info_s_type *sv_info_ptr;
807
808 if (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_SV_COUNT)
809 {
810 num_svs_max = gnss_report_ptr->sv_count;
811 if (num_svs_max > GPS_MAX_SVS)
812 {
813 num_svs_max = GPS_MAX_SVS;
814 }
815 }
816
817 if (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_SV_LIST)
818 {
819 SvStatus.num_svs = 0;
820
821 for (int i = 0; i < num_svs_max; i++)
822 {
823 sv_info_ptr = &(gnss_report_ptr->sv_list.sv_list_val[i]);
824 if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_SYSTEM)
825 {
826 if (sv_info_ptr->system == RPC_LOC_SV_SYSTEM_GPS)
827 {
828 SvStatus.sv_list[SvStatus.num_svs].size = sizeof(GpsSvStatus);
829 SvStatus.sv_list[SvStatus.num_svs].prn = sv_info_ptr->prn;
830
831 // We only have the data field to report gps eph and alm mask
832 if ((sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_HAS_EPH) &&
833 (sv_info_ptr->has_eph == 1))
834 {
835 SvStatus.ephemeris_mask |= (1 << (sv_info_ptr->prn-1));
836 }
837
838 if ((sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_HAS_ALM) &&
839 (sv_info_ptr->has_alm == 1))
840 {
841 SvStatus.almanac_mask |= (1 << (sv_info_ptr->prn-1));
842 }
843
844 if ((sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_PROCESS_STATUS) &&
845 (sv_info_ptr->process_status == RPC_LOC_SV_STATUS_TRACK))
846 {
847 SvStatus.used_in_fix_mask |= (1 << (sv_info_ptr->prn-1));
848 }
849 }
850 // SBAS: GPS RPN: 120-151,
851 // In exteneded measurement report, we follow nmea standard, which is from 33-64.
852 else if (sv_info_ptr->system == RPC_LOC_SV_SYSTEM_SBAS)
853 {
854 SvStatus.sv_list[SvStatus.num_svs].prn = sv_info_ptr->prn + 33 - 120;
855 }
856 // Gloness: Slot id: 1-32
857 // In extended measurement report, we follow nmea standard, which is 65-96
858 else if (sv_info_ptr->system == RPC_LOC_SV_SYSTEM_GLONASS)
859 {
860 SvStatus.sv_list[SvStatus.num_svs].prn = sv_info_ptr->prn + (65-1);
861 }
862 // Unsupported SV system
863 else
864 {
865 continue;
866 }
867 }
868
869 if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_SNR)
870 {
871 SvStatus.sv_list[SvStatus.num_svs].snr = sv_info_ptr->snr;
872 }
873
874 if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_ELEVATION)
875 {
876 SvStatus.sv_list[SvStatus.num_svs].elevation = sv_info_ptr->elevation;
877 }
878
879 if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_AZIMUTH)
880 {
881 SvStatus.sv_list[SvStatus.num_svs].azimuth = sv_info_ptr->azimuth;
882 }
883
884 SvStatus.num_svs++;
885 }
886 }
887
888 if ((gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_POS_DOP) &&
889 (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_HOR_DOP) &&
890 (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_VERT_DOP))
891 {
892 locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_DOP;
893 locationExtended.pdop = gnss_report_ptr->position_dop;
894 locationExtended.hdop = gnss_report_ptr->horizontal_dop;
895 locationExtended.vdop = gnss_report_ptr->vertical_dop;
896 }
897
898 if (SvStatus.num_svs >= 0)
899 {
900 LocApiBase::reportSv(SvStatus,
901 locationExtended,
902 (void*)gnss_report_ptr);
903 }
904 }
905
reportStatus(const rpc_loc_status_event_s_type * status_report_ptr)906 void LocApiRpc::reportStatus(const rpc_loc_status_event_s_type *status_report_ptr)
907 {
908
909 if (status_report_ptr->event == RPC_LOC_STATUS_EVENT_ENGINE_STATE) {
910 if (status_report_ptr->payload.rpc_loc_status_event_payload_u_type_u.engine_state == RPC_LOC_ENGINE_STATE_ON)
911 {
912 LocApiBase::reportStatus(GPS_STATUS_ENGINE_ON);
913 LocApiBase::reportStatus(GPS_STATUS_SESSION_BEGIN);
914 }
915 else if (status_report_ptr->payload.rpc_loc_status_event_payload_u_type_u.engine_state == RPC_LOC_ENGINE_STATE_OFF)
916 {
917 LocApiBase::reportStatus(GPS_STATUS_SESSION_END);
918 LocApiBase::reportStatus(GPS_STATUS_ENGINE_OFF);
919 }
920 else
921 {
922 LocApiBase::reportStatus(GPS_STATUS_NONE);
923 }
924 }
925
926 }
927
reportNmea(const rpc_loc_nmea_report_s_type * nmea_report_ptr)928 void LocApiRpc::reportNmea(const rpc_loc_nmea_report_s_type *nmea_report_ptr)
929 {
930
931 #if (AMSS_VERSION==3200)
932 LocApiBase::reportNmea(nmea_report_ptr->nmea_sentences.nmea_sentences_val,
933 nmea_report_ptr->nmea_sentences.nmea_sentences_len);
934 #else
935 LocApiBase::reportNmea(nmea_report_ptr->nmea_sentences,
936 nmea_report_ptr->length);
937 LOC_LOGD("loc_eng_report_nmea: $%c%c%c\n",
938 nmea_report_ptr->nmea_sentences[3],
939 nmea_report_ptr->nmea_sentences[4],
940 nmea_report_ptr->nmea_sentences[5]);
941 #endif /* #if (AMSS_VERSION==3200) */
942 }
943
944 enum loc_api_adapter_err
setXtraData(char * data,int length)945 LocApiRpc::setXtraData(char* data, int length)
946 {
947 int rpc_ret_val = RPC_LOC_API_GENERAL_FAILURE;
948 int total_parts;
949 uint8 part;
950 uint16 part_len;
951 uint16 len_injected;
952 rpc_loc_ioctl_data_u_type ioctl_data;
953 rpc_loc_ioctl_e_type ioctl_type = RPC_LOC_IOCTL_INJECT_PREDICTED_ORBITS_DATA;
954 rpc_loc_predicted_orbits_data_s_type *predicted_orbits_data_ptr;
955
956 LOC_LOGD("qct_loc_eng_inject_xtra_data, xtra size = %d, data ptr = 0x%lx\n", length, (long) data);
957
958 predicted_orbits_data_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.predicted_orbits_data;
959 predicted_orbits_data_ptr->format_type = RPC_LOC_PREDICTED_ORBITS_XTRA;
960 predicted_orbits_data_ptr->total_size = length;
961 total_parts = (length - 1) / XTRA_BLOCK_SIZE + 1;
962 predicted_orbits_data_ptr->total_parts = total_parts;
963
964 len_injected = 0; // O bytes injected
965 ioctl_data.disc = ioctl_type;
966
967 // XTRA injection starts with part 1
968 for (part = 1; part <= total_parts; part++)
969 {
970 predicted_orbits_data_ptr->part = part;
971 predicted_orbits_data_ptr->part_len = XTRA_BLOCK_SIZE;
972 if (XTRA_BLOCK_SIZE > (length - len_injected))
973 {
974 predicted_orbits_data_ptr->part_len = length - len_injected;
975 }
976 predicted_orbits_data_ptr->data_ptr.data_ptr_len = predicted_orbits_data_ptr->part_len;
977 predicted_orbits_data_ptr->data_ptr.data_ptr_val = data + len_injected;
978
979 LOC_LOGD("qct_loc_eng_inject_xtra_data, part %d/%d, len = %d, total = %d\n",
980 predicted_orbits_data_ptr->part,
981 total_parts,
982 predicted_orbits_data_ptr->part_len,
983 len_injected);
984
985 if (part < total_parts)
986 {
987 // No callback in this case
988 rpc_ret_val = loc_ioctl (client_handle,
989 ioctl_type,
990 &ioctl_data);
991
992 if (rpc_ret_val != RPC_LOC_API_SUCCESS)
993 {
994 LOC_LOGE("loc_ioctl for xtra error: %s\n", loc_get_ioctl_status_name(rpc_ret_val));
995 break;
996 }
997 //Add a delay of 10 ms so that repeated RPC calls dont starve the modem processor
998 usleep(10 * 1000);
999 }
1000 else // part == total_parts
1001 {
1002 // Last part injection, will need to wait for callback
1003 if (!loc_eng_ioctl(client_handle,
1004 ioctl_type,
1005 &ioctl_data,
1006 LOC_XTRA_INJECT_DEFAULT_TIMEOUT,
1007 NULL))
1008 {
1009 rpc_ret_val = RPC_LOC_API_GENERAL_FAILURE;
1010 }
1011 break; // done with injection
1012 }
1013
1014 len_injected += predicted_orbits_data_ptr->part_len;
1015 LOC_LOGD("loc_ioctl XTRA injected length: %d\n", len_injected);
1016 }
1017
1018 return convertErr(rpc_ret_val);
1019 }
1020
1021 /* Request the Xtra Server Url from the modem */
1022 enum loc_api_adapter_err
requestXtraServer()1023 LocApiRpc::requestXtraServer()
1024 {
1025 loc_api_adapter_err err;
1026 rpc_loc_ioctl_data_u_type data;
1027 rpc_loc_ioctl_callback_s_type callback_data;
1028
1029 err = convertErr(loc_eng_ioctl(client_handle,
1030 RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE,
1031 &data,
1032 LOC_IOCTL_DEFAULT_TIMEOUT,
1033 &callback_data));
1034
1035 if (LOC_API_ADAPTER_ERR_SUCCESS != err)
1036 {
1037 LOC_LOGE("RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE failed!: err=%d\n", err);
1038 return err;
1039 }
1040 else if (RPC_LOC_SESS_STATUS_SUCCESS != callback_data.status)
1041 {
1042 LOC_LOGE("RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE failed!: status=%ld\n", callback_data.status);
1043 return LOC_API_ADAPTER_ERR_GENERAL_FAILURE;
1044 }
1045 else if (RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE != callback_data.type)
1046 {
1047 LOC_LOGE("RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE is not the type expected! type=%d\n", callback_data.type);
1048 return LOC_API_ADAPTER_ERR_GENERAL_FAILURE;
1049 }
1050 else if (RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE != callback_data.data.disc)
1051 {
1052 LOC_LOGE("RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE is not the disc expected! disc=%d\n", callback_data.data.disc);
1053 return LOC_API_ADAPTER_ERR_GENERAL_FAILURE;
1054 }
1055
1056 reportXtraServer(callback_data.data.rpc_loc_ioctl_callback_data_u_type_u.
1057 predicted_orbits_data_source.servers[0],
1058 callback_data.data.rpc_loc_ioctl_callback_data_u_type_u.
1059 predicted_orbits_data_source.servers[1],
1060 callback_data.data.rpc_loc_ioctl_callback_data_u_type_u.
1061 predicted_orbits_data_source.servers[2],
1062 255);
1063
1064 return LOC_API_ADAPTER_ERR_SUCCESS;
1065 }
1066
1067 enum loc_api_adapter_err
atlOpenStatus(int handle,int is_succ,char * apn,AGpsBearerType bearer,AGpsType agpsType)1068 LocApiRpc::atlOpenStatus(int handle, int is_succ, char* apn, AGpsBearerType bearer, AGpsType agpsType)
1069 {
1070 rpc_loc_server_open_status_e_type open_status = is_succ ? RPC_LOC_SERVER_OPEN_SUCCESS : RPC_LOC_SERVER_OPEN_FAIL;
1071 rpc_loc_ioctl_data_u_type ioctl_data;
1072
1073 if (AGPS_TYPE_INVALID == agpsType) {
1074 rpc_loc_server_open_status_s_type *conn_open_status_ptr =
1075 &ioctl_data.rpc_loc_ioctl_data_u_type_u.conn_open_status;
1076
1077 // Fill in data
1078 ioctl_data.disc = RPC_LOC_IOCTL_INFORM_SERVER_OPEN_STATUS;
1079 conn_open_status_ptr->conn_handle = handle;
1080 conn_open_status_ptr->open_status = open_status;
1081 #if (AMSS_VERSION==3200)
1082 conn_open_status_ptr->apn_name = apn; /* requires APN */
1083 #else
1084 if (is_succ) {
1085 strlcpy(conn_open_status_ptr->apn_name, apn,
1086 sizeof conn_open_status_ptr->apn_name);
1087 } else {
1088 conn_open_status_ptr->apn_name[0] = 0;
1089 }
1090 #endif /* #if (AMSS_VERSION==3200) */
1091
1092 LOC_LOGD("ATL RPC_LOC_IOCTL_INFORM_SERVER_OPEN_STATUS open %s, APN name = [%s]\n",
1093 log_succ_fail_string(is_succ),
1094 apn);
1095 } else {
1096 rpc_loc_server_multi_open_status_s_type *conn_multi_open_status_ptr =
1097 &ioctl_data.rpc_loc_ioctl_data_u_type_u.multi_conn_open_status;
1098
1099 // Fill in data
1100 ioctl_data.disc = RPC_LOC_IOCTL_INFORM_SERVER_MULTI_OPEN_STATUS;
1101 conn_multi_open_status_ptr->conn_handle = handle;
1102 conn_multi_open_status_ptr->open_status = open_status;
1103 if (is_succ) {
1104 strlcpy(conn_multi_open_status_ptr->apn_name, apn,
1105 sizeof conn_multi_open_status_ptr->apn_name);
1106 } else {
1107 conn_multi_open_status_ptr->apn_name[0] = 0;
1108 }
1109
1110 switch(bearer)
1111 {
1112 case AGPS_APN_BEARER_IPV4:
1113 conn_multi_open_status_ptr->pdp_type = RPC_LOC_SERVER_PDP_IP;
1114 break;
1115 case AGPS_APN_BEARER_IPV6:
1116 conn_multi_open_status_ptr->pdp_type = RPC_LOC_SERVER_PDP_IPV6;
1117 break;
1118 case AGPS_APN_BEARER_IPV4V6:
1119 conn_multi_open_status_ptr->pdp_type = RPC_LOC_SERVER_PDP_IPV4V6;
1120 break;
1121 default:
1122 conn_multi_open_status_ptr->pdp_type = RPC_LOC_SERVER_PDP_PPP;
1123 }
1124
1125 LOC_LOGD("ATL RPC_LOC_IOCTL_INFORM_SERVER_MULTI_OPEN_STATUS open %s, APN name = [%s], pdp_type = %d\n",
1126 log_succ_fail_string(is_succ),
1127 apn,
1128 conn_multi_open_status_ptr->pdp_type);
1129 }
1130
1131 // Make the IOCTL call
1132 return convertErr(
1133 loc_eng_ioctl(client_handle,
1134 ioctl_data.disc,
1135 &ioctl_data,
1136 LOC_IOCTL_DEFAULT_TIMEOUT,
1137 NULL)
1138 );
1139 }
1140
1141 enum loc_api_adapter_err
atlCloseStatus(int handle,int is_succ)1142 LocApiRpc::atlCloseStatus(int handle, int is_succ)
1143 {
1144 rpc_loc_ioctl_data_u_type ioctl_data;
1145 ioctl_data.disc = RPC_LOC_IOCTL_INFORM_SERVER_CLOSE_STATUS;
1146
1147 rpc_loc_server_close_status_s_type *conn_close_status_ptr =
1148 &ioctl_data.rpc_loc_ioctl_data_u_type_u.conn_close_status;
1149 conn_close_status_ptr->conn_handle = handle;
1150 conn_close_status_ptr->close_status = is_succ ? RPC_LOC_SERVER_CLOSE_SUCCESS : RPC_LOC_SERVER_CLOSE_FAIL;
1151
1152 // Make the IOCTL call
1153 return convertErr(
1154 loc_eng_ioctl(client_handle,
1155 ioctl_data.disc,
1156 &ioctl_data,
1157 LOC_IOCTL_DEFAULT_TIMEOUT,
1158 NULL)
1159 );
1160 }
1161
ATLEvent(const rpc_loc_server_request_s_type * server_request_ptr)1162 void LocApiRpc::ATLEvent(const rpc_loc_server_request_s_type *server_request_ptr)
1163 {
1164 int connHandle;
1165 AGpsType agps_type;
1166
1167 LOC_LOGV("RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST event %s)",
1168 loc_get_event_atl_open_name(server_request_ptr->event));
1169 switch (server_request_ptr->event)
1170 {
1171 case RPC_LOC_SERVER_REQUEST_MULTI_OPEN:
1172 connHandle = server_request_ptr->payload.rpc_loc_server_request_u_type_u.multi_open_req.conn_handle;
1173 if (server_request_ptr->payload.rpc_loc_server_request_u_type_u.multi_open_req.connection_type
1174 == RPC_LOC_SERVER_CONNECTION_LBS) {
1175 agps_type = AGPS_TYPE_SUPL;
1176 LOC_LOGV("ATLEvent: event - RPC_LOC_SERVER_REQUEST_MULTI_OPEN\n type - AGPS_TYPE_SUPL\n handle - %d", connHandle);
1177 } else {
1178 agps_type = AGPS_TYPE_WWAN_ANY;
1179 LOC_LOGV("ATLEvent: event - RPC_LOC_SERVER_REQUEST_MULTI_OPEN\n type - AGPS_TYPE_WWAN_ANY\n handle - %d", connHandle);
1180 }
1181 requestATL(connHandle, agps_type);
1182 break;
1183 case RPC_LOC_SERVER_REQUEST_OPEN:
1184 connHandle = server_request_ptr->payload.rpc_loc_server_request_u_type_u.open_req.conn_handle;
1185 LOC_LOGV("ATLEvent: event - RPC_LOC_SERVER_REQUEST_OPEN\n handle - %d", connHandle);
1186 requestATL(connHandle, AGPS_TYPE_INVALID);
1187 break;
1188 case RPC_LOC_SERVER_REQUEST_CLOSE:
1189 connHandle = server_request_ptr->payload.rpc_loc_server_request_u_type_u.close_req.conn_handle;
1190 LOC_LOGV("ATLEvent: event - RPC_LOC_SERVER_REQUEST_CLOSE\n handle - %d", connHandle);
1191 releaseATL(connHandle);
1192 break;
1193 default:
1194 LOC_LOGE("ATLEvent: event type %d invalid", server_request_ptr->event);
1195 }
1196 }
1197
NIEvent(const rpc_loc_ni_event_s_type * ni_req)1198 void LocApiRpc::NIEvent(const rpc_loc_ni_event_s_type *ni_req)
1199 {
1200 GpsNiNotification notif = {0};
1201
1202 switch (ni_req->event)
1203 {
1204 case RPC_LOC_NI_EVENT_VX_NOTIFY_VERIFY_REQ:
1205 {
1206 const rpc_loc_ni_vx_notify_verify_req_s_type *vx_req =
1207 &ni_req->payload.rpc_loc_ni_event_payload_u_type_u.vx_req;
1208 LOC_LOGI("VX Notification");
1209 notif.ni_type = GPS_NI_TYPE_VOICE;
1210 // Requestor ID
1211 hexcode(notif.requestor_id, sizeof notif.requestor_id,
1212 vx_req->requester_id.requester_id,
1213 vx_req->requester_id.requester_id_length);
1214 notif.text_encoding = 0; // No text and no encoding
1215 notif.requestor_id_encoding = convertNiEncodingType(vx_req->encoding_scheme);
1216 NIEventFillVerfiyType(notif, vx_req->notification_priv_type);
1217 }
1218 break;
1219
1220 case RPC_LOC_NI_EVENT_UMTS_CP_NOTIFY_VERIFY_REQ:
1221 {
1222 const rpc_loc_ni_umts_cp_notify_verify_req_s_type *umts_cp_req =
1223 &ni_req->payload.rpc_loc_ni_event_payload_u_type_u.umts_cp_req;
1224 LOC_LOGI("UMTS CP Notification\n");
1225 notif.ni_type= GPS_NI_TYPE_UMTS_CTRL_PLANE; // Stores notification text
1226 #if (AMSS_VERSION==3200)
1227 hexcode(notif.text, sizeof notif.text,
1228 umts_cp_req->notification_text.notification_text_val,
1229 umts_cp_req->notification_length);
1230 hexcode(notif.requestor_id, sizeof notif.requestor_id,
1231 umts_cp_req->requestor_id.requestor_id_string.requestor_id_string_val,
1232 umts_cp_req->requestor_id.string_len);
1233 #else
1234 hexcode(notif.text, sizeof notif.text,
1235 umts_cp_req->notification_text,
1236 umts_cp_req->notification_length);
1237 hexcode(notif.requestor_id, sizeof notif.requestor_id,
1238 umts_cp_req->requestor_id.requestor_id_string,
1239 umts_cp_req->requestor_id.string_len);
1240 #endif
1241 notif.text_encoding = convertNiEncodingType(umts_cp_req->datacoding_scheme);
1242 notif.requestor_id_encoding = notif.text_encoding;
1243 NIEventFillVerfiyType(notif, umts_cp_req->notification_priv_type);
1244
1245 // LCS address (using extras field)
1246 if (umts_cp_req->ext_client_address_data.ext_client_address_len != 0)
1247 {
1248 // Copy LCS Address into notif.extras in the format: Address = 012345
1249 strlcat(notif.extras, LOC_NI_NOTIF_KEY_ADDRESS, sizeof notif.extras);
1250 strlcat(notif.extras, " = ", sizeof notif.extras);
1251 int addr_len = 0;
1252 const char *address_source = NULL;
1253
1254 #if (AMSS_VERSION==3200)
1255 address_source = umts_cp_req->ext_client_address_data.ext_client_address.ext_client_address_val;
1256 #else
1257 address_source = umts_cp_req->ext_client_address_data.ext_client_address;
1258 #endif /* #if (AMSS_VERSION==3200) */
1259
1260 char lcs_addr[32]; // Decoded LCS address for UMTS CP NI
1261 addr_len = decodeAddress(lcs_addr, sizeof lcs_addr, address_source,
1262 umts_cp_req->ext_client_address_data.ext_client_address_len);
1263
1264 // The address is ASCII string
1265 if (addr_len)
1266 {
1267 strlcat(notif.extras, lcs_addr, sizeof notif.extras);
1268 }
1269 }
1270 }
1271 break;
1272
1273 case RPC_LOC_NI_EVENT_SUPL_NOTIFY_VERIFY_REQ:
1274 {
1275 const rpc_loc_ni_supl_notify_verify_req_s_type *supl_req =
1276 &ni_req->payload.rpc_loc_ni_event_payload_u_type_u.supl_req;
1277 LOC_LOGI("SUPL Notification\n");
1278 notif.ni_type = GPS_NI_TYPE_UMTS_SUPL;
1279
1280 if (supl_req->flags & RPC_LOC_NI_CLIENT_NAME_PRESENT)
1281 {
1282 #if (AMSS_VERSION==3200)
1283 hexcode(notif.text, sizeof notif.text,
1284 supl_req->client_name.client_name_string.client_name_string_val, /* buffer */
1285 supl_req->client_name.string_len /* length */
1286 );
1287 #else
1288 hexcode(notif.text, sizeof notif.text,
1289 supl_req->client_name.client_name_string, /* buffer */
1290 supl_req->client_name.string_len /* length */
1291 );
1292 #endif /* #if (AMSS_VERSION==3200) */
1293 LOC_LOGV("SUPL NI: client_name: %s len=%d", notif.text, supl_req->client_name.string_len);
1294 }
1295 else {
1296 LOC_LOGV("SUPL NI: client_name not present.");
1297 }
1298
1299 // Requestor ID
1300 if (supl_req->flags & RPC_LOC_NI_REQUESTOR_ID_PRESENT)
1301 {
1302 #if (AMSS_VERSION==3200)
1303 hexcode(notif.requestor_id, sizeof notif.requestor_id,
1304 supl_req->requestor_id.requestor_id_string.requestor_id_string_val, /* buffer */
1305 supl_req->requestor_id.string_len /* length */
1306 );
1307 #else
1308 hexcode(notif.requestor_id, sizeof notif.requestor_id,
1309 supl_req->requestor_id.requestor_id_string, /* buffer */
1310 supl_req->requestor_id.string_len /* length */
1311 );
1312 #endif /* #if (AMSS_VERSION==3200) */
1313 LOC_LOGV("SUPL NI: requestor_id: %s len=%d", notif.requestor_id, supl_req->requestor_id.string_len);
1314 }
1315 else {
1316 LOC_LOGV("SUPL NI: requestor_id not present.");
1317 }
1318
1319 // Encoding type
1320 if (supl_req->flags & RPC_LOC_NI_ENCODING_TYPE_PRESENT)
1321 {
1322 notif.text_encoding = convertNiEncodingType(supl_req->datacoding_scheme);
1323 notif.requestor_id_encoding = notif.text_encoding;
1324 }
1325 else {
1326 notif.text_encoding = notif.requestor_id_encoding = GPS_ENC_UNKNOWN;
1327 }
1328
1329 NIEventFillVerfiyType(notif, ni_req->payload.rpc_loc_ni_event_payload_u_type_u.supl_req.notification_priv_type);
1330 }
1331 break;
1332
1333 default:
1334 LOC_LOGE("Unknown NI event: %x\n", (int) ni_req->event);
1335 return;
1336 }
1337
1338 // this copy will get freed in loc_eng_ni when loc_ni_respond() is called
1339 rpc_loc_ni_event_s_type *copy = (rpc_loc_ni_event_s_type *)malloc(sizeof(*copy));
1340 memcpy(copy, ni_req, sizeof(*copy));
1341 requestNiNotify(notif, (const void*)copy);
1342 }
1343
NIEventFillVerfiyType(GpsNiNotification & notif,rpc_loc_ni_notify_verify_e_type notif_priv)1344 int LocApiRpc::NIEventFillVerfiyType(GpsNiNotification ¬if,
1345 rpc_loc_ni_notify_verify_e_type notif_priv)
1346 {
1347 switch (notif_priv)
1348 {
1349 case RPC_LOC_NI_USER_NO_NOTIFY_NO_VERIFY:
1350 notif.notify_flags = 0;
1351 notif.default_response = GPS_NI_RESPONSE_NORESP;
1352 return 1;
1353 case RPC_LOC_NI_USER_NOTIFY_ONLY:
1354 notif.notify_flags = GPS_NI_NEED_NOTIFY;
1355 notif.default_response = GPS_NI_RESPONSE_NORESP;
1356 return 1;
1357 case RPC_LOC_NI_USER_NOTIFY_VERIFY_ALLOW_NO_RESP:
1358 notif.notify_flags = GPS_NI_NEED_NOTIFY | GPS_NI_NEED_VERIFY;
1359 notif.default_response = GPS_NI_RESPONSE_ACCEPT;
1360 return 1;
1361 case RPC_LOC_NI_USER_NOTIFY_VERIFY_NOT_ALLOW_NO_RESP:
1362 notif.notify_flags = GPS_NI_NEED_NOTIFY | GPS_NI_NEED_VERIFY;
1363 notif.default_response = GPS_NI_RESPONSE_DENY;
1364 return 1;
1365 case RPC_LOC_NI_USER_PRIVACY_OVERRIDE:
1366 notif.notify_flags = GPS_NI_PRIVACY_OVERRIDE;
1367 notif.default_response = GPS_NI_RESPONSE_NORESP;
1368 return 1;
1369 default:
1370 return 0;
1371 }
1372 }
1373
1374 enum loc_api_adapter_err
setSUPLVersion(uint32_t version)1375 LocApiRpc::setSUPLVersion(uint32_t version)
1376 {
1377 rpc_loc_ioctl_data_u_type ioctl_data = {RPC_LOC_IOCTL_SET_SUPL_VERSION, {0}};
1378 ioctl_data.rpc_loc_ioctl_data_u_type_u.supl_version = (int)version;
1379 return convertErr(
1380 loc_eng_ioctl (client_handle,
1381 RPC_LOC_IOCTL_SET_SUPL_VERSION,
1382 &ioctl_data,
1383 LOC_IOCTL_DEFAULT_TIMEOUT,
1384 NULL)
1385 );
1386 }
1387
convertNiEncodingType(int loc_encoding)1388 GpsNiEncodingType LocApiRpc::convertNiEncodingType(int loc_encoding)
1389 {
1390 switch (loc_encoding)
1391 {
1392 case RPC_LOC_NI_SUPL_UTF8:
1393 return GPS_ENC_SUPL_UTF8;
1394 case RPC_LOC_NI_SUPL_UCS2:
1395 return GPS_ENC_SUPL_UCS2;
1396 case RPC_LOC_NI_SUPL_GSM_DEFAULT:
1397 return GPS_ENC_SUPL_GSM_DEFAULT;
1398 case RPC_LOC_NI_SS_LANGUAGE_UNSPEC:
1399 return GPS_ENC_SUPL_GSM_DEFAULT; // SS_LANGUAGE_UNSPEC = GSM
1400 default:
1401 return GPS_ENC_UNKNOWN;
1402 }
1403 }
1404
getLocApi(const MsgTask * msgTask,LOC_API_ADAPTER_EVENT_MASK_T exMask,ContextBase * context)1405 LocApiBase* getLocApi(const MsgTask* msgTask,
1406 LOC_API_ADAPTER_EVENT_MASK_T exMask,
1407 ContextBase *context) {
1408 return new LocApiRpc(msgTask, exMask, context);
1409 }
1410
1411 /*Values for lock
1412 1 = Do not lock any position sessions
1413 2 = Lock MI position sessions
1414 3 = Lock MT position sessions
1415 4 = Lock all position sessions
1416 */
setGpsLock(LOC_GPS_LOCK_MASK lockMask)1417 int LocApiRpc::setGpsLock(LOC_GPS_LOCK_MASK lockMask)
1418 {
1419 rpc_loc_ioctl_data_u_type ioctl_data;
1420 boolean ret_val;
1421 LOC_LOGD("%s:%d]: lock: %x\n", __func__, __LINE__, lockMask);
1422 ioctl_data.rpc_loc_ioctl_data_u_type_u.engine_lock = convertGpsLockMask(lockMask);
1423 ioctl_data.disc = RPC_LOC_IOCTL_SET_ENGINE_LOCK;
1424 ret_val = loc_eng_ioctl (loc_eng_data.client_handle,
1425 RPC_LOC_IOCTL_SET_ENGINE_LOCK,
1426 &ioctl_data,
1427 LOC_IOCTL_DEFAULT_TIMEOUT,
1428 NULL /* No output information is expected*/);
1429
1430 LOC_LOGD("%s:%d]: ret_val: %d\n", __func__, __LINE__, (int)ret_val);
1431 return (ret_val == TRUE ? 0 : -1);
1432 }
1433
1434 /*
1435 Returns
1436 Current value of GPS lock on success
1437 -1 on failure
1438 */
getGpsLock()1439 int LocApiRpc :: getGpsLock()
1440 {
1441 rpc_loc_ioctl_data_u_type ioctl_data;
1442 rpc_loc_ioctl_callback_s_type callback_payload;
1443 boolean ret_val;
1444 int ret=0;
1445 LOC_LOGD("%s:%d]: Enter\n", __func__, __LINE__);
1446 ret_val = loc_eng_ioctl (loc_eng_data.client_handle,
1447 RPC_LOC_IOCTL_GET_ENGINE_LOCK,
1448 &ioctl_data,
1449 LOC_IOCTL_DEFAULT_TIMEOUT,
1450 &callback_payload);
1451 if(ret_val == TRUE) {
1452 ret = (int)callback_payload.data.engine_lock;
1453 LOC_LOGD("%s:%d]: Lock type: %d\n", __func__, __LINE__, ret);
1454 }
1455 else {
1456 LOC_LOGE("%s:%d]: Ioctl failed", __func__, __LINE__);
1457 ret = -1;
1458 }
1459 LOC_LOGD("%s:%d]: Exit\n", __func__, __LINE__);
1460 return ret;
1461 }
1462