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 &notif,
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