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
50using 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/*===========================================================================
58FUNCTION    loc_event_cb
59
60DESCRIPTION
61   This is the callback function registered by loc_open.
62
63DEPENDENCIES
64   N/A
65
66RETURN VALUE
67   RPC_LOC_API_SUCCESS
68
69SIDE EFFECTS
70   N/A
71
72===========================================================================*/
73static 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/*===========================================================================
89FUNCTION    loc_eng_rpc_global_cb
90
91DESCRIPTION
92   This is the callback function registered by loc_open for RPC global events
93
94DEPENDENCIES
95   N/A
96
97RETURN VALUE
98   RPC_LOC_API_SUCCESS
99
100SIDE EFFECTS
101   N/A
102
103===========================================================================*/
104static 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
111const 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
121const 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
136LocApiRpc::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
147LocApiRpc::~LocApiRpc()
148{
149    close();
150}
151
152rpc_loc_event_mask_type
153LocApiRpc::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
167rpc_loc_lock_e_type
168LocApiRpc::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
181enum loc_api_adapter_err
182LocApiRpc::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
211void 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
231int32 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
294enum loc_api_adapter_err
295LocApiRpc::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
328enum loc_api_adapter_err
329LocApiRpc::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
342enum loc_api_adapter_err
343LocApiRpc::startFix(const LocPosMode& posMode) {
344   LOC_LOGD("LocApiRpc::startFix() called");
345   return convertErr(
346       loc_start_fix(client_handle)
347       );
348}
349
350enum loc_api_adapter_err
351LocApiRpc::stopFix() {
352   LOC_LOGD("LocApiRpc::stopFix() called");
353   return convertErr(
354       loc_stop_fix(client_handle)
355       );
356}
357
358enum loc_api_adapter_err
359LocApiRpc::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
435enum loc_api_adapter_err
436LocApiRpc::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
461enum loc_api_adapter_err
462LocApiRpc::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
500enum loc_api_adapter_err
501LocApiRpc::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
537enum loc_api_adapter_err
538LocApiRpc::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
567void LocApiRpc::setInSession(bool inSession)
568{
569    if (!inSession) {
570        enableData(dataEnableLastSet, true);
571        setAPN(apnLastSet, sizeof(apnLastSet)-1, true);
572    }
573}
574
575enum loc_api_adapter_err
576LocApiRpc::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
606enum loc_api_adapter_err
607LocApiRpc::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
641enum loc_api_adapter_err
642LocApiRpc::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
664enum loc_api_adapter_err
665LocApiRpc::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
679void 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                {
720                    location.gpsLocation.flags    |= GPS_LOCATION_HAS_SPEED;
721                    location.gpsLocation.speed = location_report_ptr->speed_horizontal;
722                }
723
724                // Heading
725                if (location_report_ptr->valid_mask &  RPC_LOC_POS_VALID_HEADING)
726                {
727                    location.gpsLocation.flags    |= GPS_LOCATION_HAS_BEARING;
728                    location.gpsLocation.bearing = location_report_ptr->heading;
729                }
730
731                // Uncertainty (circular)
732                if ( (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_HOR_UNC_CIRCULAR) )
733                {
734                    location.gpsLocation.flags    |= GPS_LOCATION_HAS_ACCURACY;
735                    location.gpsLocation.accuracy = location_report_ptr->hor_unc_circular;
736                }
737
738                // Technology Mask
739
740                tech_Mask  |= location_report_ptr->technology_mask;
741                //Mark the location source as from GNSS
742                location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO;
743                location.position_source = ULP_LOCATION_IS_FROM_GNSS;
744                if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_ALTITUDE_WRT_MEAN_SEA_LEVEL)
745                {
746                    locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL;
747                    locationExtended.altitudeMeanSeaLevel = location_report_ptr->altitude_wrt_mean_sea_level;
748                }
749
750                if (location_report_ptr->valid_mask &  RPC_LOC_POS_VALID_MAGNETIC_VARIATION )
751                {
752                    locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_MAG_DEV;
753                    locationExtended.magneticDeviation = location_report_ptr->magnetic_deviation;
754                }
755
756                if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_VERTICAL_UNC)
757                {
758                   locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_VERT_UNC;
759                   locationExtended.vert_unc = location_report_ptr->vert_unc;
760                }
761
762                if (location_report_ptr->valid_mask & RPC_LOC_POS_VALID_SPEED_UNC)
763                {
764                   locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_SPEED_UNC;
765                   locationExtended.speed_unc = location_report_ptr->speed_unc;
766                }
767
768                LOC_LOGV("reportPosition: fire callback\n");
769                enum loc_sess_status fixStatus =
770                    (location_report_ptr->session_status
771                     == RPC_LOC_SESS_STATUS_IN_PROGESS ?
772                     LOC_SESS_INTERMEDIATE : LOC_SESS_SUCCESS);
773                LocApiBase::reportPosition(location,
774                                           locationExtended,
775                                           (void*)location_report_ptr,
776                                           fixStatus,
777                                           tech_Mask);
778            }
779        }
780        else
781        {
782            LocApiBase::reportPosition(location,
783                                       locationExtended,
784                                       NULL,
785                                       LOC_SESS_FAILURE);
786            LOC_LOGV("loc_eng_report_position: ignore position report "
787                     "when session status = %d\n",
788                     location_report_ptr->session_status);
789        }
790    }
791    else
792    {
793        LOC_LOGV("loc_eng_report_position: ignore position report "
794                 "when session status is not set\n");
795    }
796}
797
798void LocApiRpc::reportSv(const rpc_loc_gnss_info_s_type *gnss_report_ptr)
799{
800    QtiGnssSvStatus     SvStatus = {0};
801    GpsLocationExtended locationExtended = {0};
802    locationExtended.size = sizeof(locationExtended);
803    int             num_svs_max = 0;
804    const rpc_loc_sv_info_s_type *sv_info_ptr;
805
806    if (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_SV_COUNT)
807    {
808        num_svs_max = gnss_report_ptr->sv_count;
809        if (num_svs_max > GPS_MAX_SVS)
810        {
811            num_svs_max = GPS_MAX_SVS;
812        }
813    }
814
815    if (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_SV_LIST)
816    {
817        SvStatus.num_svs = 0;
818
819        for (int i = 0; i < num_svs_max; i++)
820        {
821            sv_info_ptr = &(gnss_report_ptr->sv_list.sv_list_val[i]);
822            if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_SYSTEM)
823            {
824                if (sv_info_ptr->system == RPC_LOC_SV_SYSTEM_GPS)
825                {
826                    SvStatus.sv_list[SvStatus.num_svs].size = sizeof(GpsSvInfo);
827                    SvStatus.sv_list[SvStatus.num_svs].prn = sv_info_ptr->prn;
828
829                    // We only have the data field to report gps eph and alm mask
830                    if ((sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_HAS_EPH) &&
831                        (sv_info_ptr->has_eph == 1))
832                    {
833                        SvStatus.ephemeris_mask |= (1 << (sv_info_ptr->prn-1));
834                    }
835
836                    if ((sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_HAS_ALM) &&
837                        (sv_info_ptr->has_alm == 1))
838                    {
839                        SvStatus.almanac_mask |= (1 << (sv_info_ptr->prn-1));
840                    }
841
842                    if ((sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_PROCESS_STATUS) &&
843                        (sv_info_ptr->process_status == RPC_LOC_SV_STATUS_TRACK))
844                    {
845                        SvStatus.gps_used_in_fix_mask |= (1 << (sv_info_ptr->prn-1));
846                    }
847                }
848                // SBAS: GPS RPN: 120-151,
849                // In exteneded measurement report, we follow nmea standard, which is from 33-64.
850                else if (sv_info_ptr->system == RPC_LOC_SV_SYSTEM_SBAS)
851                {
852                    SvStatus.sv_list[SvStatus.num_svs].prn = sv_info_ptr->prn + 33 - 120;
853                }
854                // Gloness: Slot id: 1-32
855                // In extended measurement report, we follow nmea standard, which is 65-96
856                else if (sv_info_ptr->system == RPC_LOC_SV_SYSTEM_GLONASS)
857                {
858                    if ((sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_PROCESS_STATUS) &&
859                        (sv_info_ptr->process_status == RPC_LOC_SV_STATUS_TRACK))
860                    {
861                        SvStatus.glo_used_in_fix_mask |= (1 << (sv_info_ptr->prn-1));
862                    }
863
864                    SvStatus.sv_list[SvStatus.num_svs].prn = sv_info_ptr->prn + (65-1);
865                }
866                // Unsupported SV system
867                else
868                {
869                    continue;
870                }
871            }
872
873            if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_SNR)
874            {
875                SvStatus.sv_list[SvStatus.num_svs].snr = sv_info_ptr->snr;
876            }
877
878            if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_ELEVATION)
879            {
880                SvStatus.sv_list[SvStatus.num_svs].elevation = sv_info_ptr->elevation;
881            }
882
883            if (sv_info_ptr->valid_mask & RPC_LOC_SV_INFO_VALID_AZIMUTH)
884            {
885                SvStatus.sv_list[SvStatus.num_svs].azimuth = sv_info_ptr->azimuth;
886            }
887
888            SvStatus.num_svs++;
889        }
890    }
891
892    if ((gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_POS_DOP) &&
893        (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_HOR_DOP) &&
894        (gnss_report_ptr->valid_mask & RPC_LOC_GNSS_INFO_VALID_VERT_DOP))
895    {
896        locationExtended.flags |= GPS_LOCATION_EXTENDED_HAS_DOP;
897        locationExtended.pdop = gnss_report_ptr->position_dop;
898        locationExtended.hdop = gnss_report_ptr->horizontal_dop;
899        locationExtended.vdop = gnss_report_ptr->vertical_dop;
900    }
901
902    if (SvStatus.num_svs >= 0)
903    {
904        LocApiBase::reportSv(SvStatus,
905                             locationExtended,
906                             (void*)gnss_report_ptr);
907    }
908}
909
910void LocApiRpc::reportStatus(const rpc_loc_status_event_s_type *status_report_ptr)
911{
912
913    if (status_report_ptr->event == RPC_LOC_STATUS_EVENT_ENGINE_STATE) {
914        if (status_report_ptr->payload.rpc_loc_status_event_payload_u_type_u.engine_state == RPC_LOC_ENGINE_STATE_ON)
915        {
916            LocApiBase::reportStatus(GPS_STATUS_ENGINE_ON);
917            LocApiBase::reportStatus(GPS_STATUS_SESSION_BEGIN);
918        }
919        else if (status_report_ptr->payload.rpc_loc_status_event_payload_u_type_u.engine_state == RPC_LOC_ENGINE_STATE_OFF)
920        {
921            LocApiBase::reportStatus(GPS_STATUS_SESSION_END);
922            LocApiBase::reportStatus(GPS_STATUS_ENGINE_OFF);
923        }
924        else
925        {
926            LocApiBase::reportStatus(GPS_STATUS_NONE);
927        }
928    }
929
930}
931
932void LocApiRpc::reportNmea(const rpc_loc_nmea_report_s_type *nmea_report_ptr)
933{
934
935#if (AMSS_VERSION==3200)
936    LocApiBase::reportNmea(nmea_report_ptr->nmea_sentences.nmea_sentences_val,
937                           nmea_report_ptr->nmea_sentences.nmea_sentences_len);
938#else
939    LocApiBase::reportNmea(nmea_report_ptr->nmea_sentences,
940                           nmea_report_ptr->length);
941    LOC_LOGD("loc_eng_report_nmea: $%c%c%c\n",
942             nmea_report_ptr->nmea_sentences[3],
943             nmea_report_ptr->nmea_sentences[4],
944             nmea_report_ptr->nmea_sentences[5]);
945#endif /* #if (AMSS_VERSION==3200) */
946}
947
948enum loc_api_adapter_err
949LocApiRpc::setXtraData(char* data, int length)
950{
951    int     rpc_ret_val = RPC_LOC_API_GENERAL_FAILURE;
952    int     total_parts;
953    uint8   part;
954    uint16  part_len;
955    uint16  len_injected;
956    rpc_loc_ioctl_data_u_type            ioctl_data;
957    rpc_loc_ioctl_e_type                 ioctl_type = RPC_LOC_IOCTL_INJECT_PREDICTED_ORBITS_DATA;
958    rpc_loc_predicted_orbits_data_s_type *predicted_orbits_data_ptr;
959
960    LOC_LOGD("qct_loc_eng_inject_xtra_data, xtra size = %d, data ptr = 0x%lx\n", length, (long) data);
961
962    predicted_orbits_data_ptr = &ioctl_data.rpc_loc_ioctl_data_u_type_u.predicted_orbits_data;
963    predicted_orbits_data_ptr->format_type = RPC_LOC_PREDICTED_ORBITS_XTRA;
964    predicted_orbits_data_ptr->total_size = length;
965    total_parts = (length - 1) / XTRA_BLOCK_SIZE + 1;
966    predicted_orbits_data_ptr->total_parts = total_parts;
967
968    len_injected = 0; // O bytes injected
969    ioctl_data.disc = ioctl_type;
970
971    // XTRA injection starts with part 1
972    for (part = 1; part <= total_parts; part++)
973    {
974        predicted_orbits_data_ptr->part = part;
975        predicted_orbits_data_ptr->part_len = XTRA_BLOCK_SIZE;
976        if (XTRA_BLOCK_SIZE > (length - len_injected))
977        {
978            predicted_orbits_data_ptr->part_len = length - len_injected;
979        }
980        predicted_orbits_data_ptr->data_ptr.data_ptr_len = predicted_orbits_data_ptr->part_len;
981        predicted_orbits_data_ptr->data_ptr.data_ptr_val = data + len_injected;
982
983        LOC_LOGD("qct_loc_eng_inject_xtra_data, part %d/%d, len = %d, total = %d\n",
984                 predicted_orbits_data_ptr->part,
985                 total_parts,
986                 predicted_orbits_data_ptr->part_len,
987                 len_injected);
988
989        if (part < total_parts)
990        {
991            // No callback in this case
992            rpc_ret_val = loc_ioctl (client_handle,
993                                     ioctl_type,
994                                     &ioctl_data);
995
996            if (rpc_ret_val != RPC_LOC_API_SUCCESS)
997            {
998                LOC_LOGE("loc_ioctl for xtra error: %s\n", loc_get_ioctl_status_name(rpc_ret_val));
999                break;
1000            }
1001            //Add a delay of 10 ms so that repeated RPC calls dont starve the modem processor
1002            usleep(10 * 1000);
1003        }
1004        else // part == total_parts
1005        {
1006            // Last part injection, will need to wait for callback
1007            if (!loc_eng_ioctl(client_handle,
1008                               ioctl_type,
1009                               &ioctl_data,
1010                               LOC_XTRA_INJECT_DEFAULT_TIMEOUT,
1011                               NULL))
1012            {
1013                rpc_ret_val = RPC_LOC_API_GENERAL_FAILURE;
1014            }
1015            break; // done with injection
1016        }
1017
1018        len_injected += predicted_orbits_data_ptr->part_len;
1019        LOC_LOGD("loc_ioctl XTRA injected length: %d\n", len_injected);
1020    }
1021
1022    return convertErr(rpc_ret_val);
1023}
1024
1025/* Request the Xtra Server Url from the modem */
1026enum loc_api_adapter_err
1027LocApiRpc::requestXtraServer()
1028{
1029    loc_api_adapter_err           err;
1030    rpc_loc_ioctl_data_u_type     data;
1031    rpc_loc_ioctl_callback_s_type callback_data;
1032
1033    err = convertErr(loc_eng_ioctl(client_handle,
1034                                   RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE,
1035                                   &data,
1036                                   LOC_IOCTL_DEFAULT_TIMEOUT,
1037                                   &callback_data));
1038
1039    if (LOC_API_ADAPTER_ERR_SUCCESS != err)
1040    {
1041        LOC_LOGE("RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE failed!: err=%d\n", err);
1042        return err;
1043    }
1044    else if (RPC_LOC_SESS_STATUS_SUCCESS != callback_data.status)
1045    {
1046        LOC_LOGE("RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE failed!: status=%ld\n", callback_data.status);
1047        return LOC_API_ADAPTER_ERR_GENERAL_FAILURE;
1048    }
1049    else if (RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE != callback_data.type)
1050    {
1051        LOC_LOGE("RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE is not the type expected! type=%d\n", callback_data.type);
1052        return LOC_API_ADAPTER_ERR_GENERAL_FAILURE;
1053    }
1054    else if (RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE != callback_data.data.disc)
1055    {
1056        LOC_LOGE("RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE is not the disc expected! disc=%d\n", callback_data.data.disc);
1057        return LOC_API_ADAPTER_ERR_GENERAL_FAILURE;
1058    }
1059
1060    reportXtraServer(callback_data.data.rpc_loc_ioctl_callback_data_u_type_u.
1061                     predicted_orbits_data_source.servers[0],
1062                     callback_data.data.rpc_loc_ioctl_callback_data_u_type_u.
1063                     predicted_orbits_data_source.servers[1],
1064                     callback_data.data.rpc_loc_ioctl_callback_data_u_type_u.
1065                     predicted_orbits_data_source.servers[2],
1066                     255);
1067
1068    return LOC_API_ADAPTER_ERR_SUCCESS;
1069}
1070
1071enum loc_api_adapter_err
1072LocApiRpc::atlOpenStatus(int handle, int is_succ, char* apn, AGpsBearerType bearer, AGpsType agpsType)
1073{
1074    rpc_loc_server_open_status_e_type open_status = is_succ ? RPC_LOC_SERVER_OPEN_SUCCESS : RPC_LOC_SERVER_OPEN_FAIL;
1075   rpc_loc_ioctl_data_u_type           ioctl_data;
1076
1077    if (AGPS_TYPE_INVALID == agpsType) {
1078        rpc_loc_server_open_status_s_type  *conn_open_status_ptr =
1079            &ioctl_data.rpc_loc_ioctl_data_u_type_u.conn_open_status;
1080
1081        // Fill in data
1082        ioctl_data.disc = RPC_LOC_IOCTL_INFORM_SERVER_OPEN_STATUS;
1083        conn_open_status_ptr->conn_handle = handle;
1084        conn_open_status_ptr->open_status = open_status;
1085#if (AMSS_VERSION==3200)
1086        conn_open_status_ptr->apn_name = apn; /* requires APN */
1087#else
1088        if (is_succ) {
1089            strlcpy(conn_open_status_ptr->apn_name, apn,
1090                    sizeof conn_open_status_ptr->apn_name);
1091        } else {
1092            conn_open_status_ptr->apn_name[0] = 0;
1093        }
1094#endif /* #if (AMSS_VERSION==3200) */
1095
1096        LOC_LOGD("ATL RPC_LOC_IOCTL_INFORM_SERVER_OPEN_STATUS open %s, APN name = [%s]\n",
1097                 log_succ_fail_string(is_succ),
1098                 apn);
1099    } else {
1100        rpc_loc_server_multi_open_status_s_type  *conn_multi_open_status_ptr =
1101            &ioctl_data.rpc_loc_ioctl_data_u_type_u.multi_conn_open_status;
1102
1103        // Fill in data
1104        ioctl_data.disc = RPC_LOC_IOCTL_INFORM_SERVER_MULTI_OPEN_STATUS;
1105        conn_multi_open_status_ptr->conn_handle = handle;
1106        conn_multi_open_status_ptr->open_status = open_status;
1107        if (is_succ) {
1108            strlcpy(conn_multi_open_status_ptr->apn_name, apn,
1109                    sizeof conn_multi_open_status_ptr->apn_name);
1110        } else {
1111            conn_multi_open_status_ptr->apn_name[0] = 0;
1112        }
1113
1114        switch(bearer)
1115        {
1116        case AGPS_APN_BEARER_IPV4:
1117            conn_multi_open_status_ptr->pdp_type = RPC_LOC_SERVER_PDP_IP;
1118            break;
1119        case AGPS_APN_BEARER_IPV6:
1120            conn_multi_open_status_ptr->pdp_type = RPC_LOC_SERVER_PDP_IPV6;
1121            break;
1122        case AGPS_APN_BEARER_IPV4V6:
1123            conn_multi_open_status_ptr->pdp_type = RPC_LOC_SERVER_PDP_IPV4V6;
1124            break;
1125        default:
1126            conn_multi_open_status_ptr->pdp_type = RPC_LOC_SERVER_PDP_PPP;
1127        }
1128
1129        LOC_LOGD("ATL RPC_LOC_IOCTL_INFORM_SERVER_MULTI_OPEN_STATUS open %s, APN name = [%s], pdp_type = %d\n",
1130                 log_succ_fail_string(is_succ),
1131                 apn,
1132                 conn_multi_open_status_ptr->pdp_type);
1133    }
1134
1135    // Make the IOCTL call
1136    return convertErr(
1137        loc_eng_ioctl(client_handle,
1138                      ioctl_data.disc,
1139                      &ioctl_data,
1140                      LOC_IOCTL_DEFAULT_TIMEOUT,
1141                      NULL)
1142        );
1143}
1144
1145enum loc_api_adapter_err
1146LocApiRpc::atlCloseStatus(int handle, int is_succ)
1147{
1148    rpc_loc_ioctl_data_u_type           ioctl_data;
1149    ioctl_data.disc = RPC_LOC_IOCTL_INFORM_SERVER_CLOSE_STATUS;
1150
1151    rpc_loc_server_close_status_s_type *conn_close_status_ptr =
1152        &ioctl_data.rpc_loc_ioctl_data_u_type_u.conn_close_status;
1153    conn_close_status_ptr->conn_handle = handle;
1154    conn_close_status_ptr->close_status = is_succ ? RPC_LOC_SERVER_CLOSE_SUCCESS : RPC_LOC_SERVER_CLOSE_FAIL;
1155
1156    // Make the IOCTL call
1157    return convertErr(
1158        loc_eng_ioctl(client_handle,
1159                      ioctl_data.disc,
1160                      &ioctl_data,
1161                      LOC_IOCTL_DEFAULT_TIMEOUT,
1162                      NULL)
1163        );
1164}
1165
1166void LocApiRpc::ATLEvent(const rpc_loc_server_request_s_type *server_request_ptr)
1167{
1168    int connHandle;
1169    AGpsType agps_type;
1170
1171    LOC_LOGV("RPC_LOC_EVENT_ASSISTANCE_DATA_REQUEST event %s)",
1172             loc_get_event_atl_open_name(server_request_ptr->event));
1173    switch (server_request_ptr->event)
1174    {
1175    case RPC_LOC_SERVER_REQUEST_MULTI_OPEN:
1176        connHandle = server_request_ptr->payload.rpc_loc_server_request_u_type_u.multi_open_req.conn_handle;
1177        if (server_request_ptr->payload.rpc_loc_server_request_u_type_u.multi_open_req.connection_type
1178            == RPC_LOC_SERVER_CONNECTION_LBS) {
1179            agps_type = AGPS_TYPE_SUPL;
1180            LOC_LOGV("ATLEvent: event - RPC_LOC_SERVER_REQUEST_MULTI_OPEN\n            type - AGPS_TYPE_SUPL\n            handle - %d", connHandle);
1181        } else {
1182            agps_type = AGPS_TYPE_WWAN_ANY;
1183            LOC_LOGV("ATLEvent: event - RPC_LOC_SERVER_REQUEST_MULTI_OPEN\n            type - AGPS_TYPE_WWAN_ANY\n            handle - %d", connHandle);
1184        }
1185        requestATL(connHandle, agps_type);
1186        break;
1187    case RPC_LOC_SERVER_REQUEST_OPEN:
1188        connHandle = server_request_ptr->payload.rpc_loc_server_request_u_type_u.open_req.conn_handle;
1189        LOC_LOGV("ATLEvent: event - RPC_LOC_SERVER_REQUEST_OPEN\n            handle - %d", connHandle);
1190        requestATL(connHandle, AGPS_TYPE_INVALID);
1191        break;
1192    case RPC_LOC_SERVER_REQUEST_CLOSE:
1193        connHandle = server_request_ptr->payload.rpc_loc_server_request_u_type_u.close_req.conn_handle;
1194        LOC_LOGV("ATLEvent: event - RPC_LOC_SERVER_REQUEST_CLOSE\n            handle - %d", connHandle);
1195        releaseATL(connHandle);
1196        break;
1197    default:
1198        LOC_LOGE("ATLEvent: event type %d invalid", server_request_ptr->event);
1199   }
1200}
1201
1202void LocApiRpc::NIEvent(const rpc_loc_ni_event_s_type *ni_req)
1203{
1204    GpsNiNotification notif = {0};
1205
1206    switch (ni_req->event)
1207    {
1208    case RPC_LOC_NI_EVENT_VX_NOTIFY_VERIFY_REQ:
1209    {
1210        const rpc_loc_ni_vx_notify_verify_req_s_type *vx_req =
1211            &ni_req->payload.rpc_loc_ni_event_payload_u_type_u.vx_req;
1212        LOC_LOGI("VX Notification");
1213        notif.ni_type = GPS_NI_TYPE_VOICE;
1214        // Requestor ID
1215        hexcode(notif.requestor_id, sizeof notif.requestor_id,
1216                vx_req->requester_id.requester_id,
1217                vx_req->requester_id.requester_id_length);
1218        notif.text_encoding = 0; // No text and no encoding
1219        notif.requestor_id_encoding = convertNiEncodingType(vx_req->encoding_scheme);
1220        NIEventFillVerfiyType(notif, vx_req->notification_priv_type);
1221    }
1222        break;
1223
1224    case RPC_LOC_NI_EVENT_UMTS_CP_NOTIFY_VERIFY_REQ:
1225    {
1226        const rpc_loc_ni_umts_cp_notify_verify_req_s_type *umts_cp_req =
1227            &ni_req->payload.rpc_loc_ni_event_payload_u_type_u.umts_cp_req;
1228        LOC_LOGI("UMTS CP Notification\n");
1229        notif.ni_type= GPS_NI_TYPE_UMTS_CTRL_PLANE;         // Stores notification text
1230#if (AMSS_VERSION==3200)
1231        hexcode(notif.text, sizeof notif.text,
1232                umts_cp_req->notification_text.notification_text_val,
1233                umts_cp_req->notification_length);
1234        hexcode(notif.requestor_id, sizeof notif.requestor_id,
1235                umts_cp_req->requestor_id.requestor_id_string.requestor_id_string_val,
1236                umts_cp_req->requestor_id.string_len);
1237#else
1238        hexcode(notif.text, sizeof notif.text,
1239                umts_cp_req->notification_text,
1240                umts_cp_req->notification_length);
1241        hexcode(notif.requestor_id, sizeof notif.requestor_id,
1242                umts_cp_req->requestor_id.requestor_id_string,
1243                umts_cp_req->requestor_id.string_len);
1244#endif
1245        notif.text_encoding = convertNiEncodingType(umts_cp_req->datacoding_scheme);
1246        notif.requestor_id_encoding = notif.text_encoding;
1247        NIEventFillVerfiyType(notif, umts_cp_req->notification_priv_type);
1248
1249        // LCS address (using extras field)
1250        if (umts_cp_req->ext_client_address_data.ext_client_address_len != 0)
1251        {
1252            // Copy LCS Address into notif.extras in the format: Address = 012345
1253            strlcat(notif.extras, LOC_NI_NOTIF_KEY_ADDRESS, sizeof notif.extras);
1254            strlcat(notif.extras, " = ", sizeof notif.extras);
1255            int addr_len = 0;
1256            const char *address_source = NULL;
1257
1258#if (AMSS_VERSION==3200)
1259            address_source = umts_cp_req->ext_client_address_data.ext_client_address.ext_client_address_val;
1260#else
1261            address_source = umts_cp_req->ext_client_address_data.ext_client_address;
1262#endif /* #if (AMSS_VERSION==3200) */
1263
1264            char lcs_addr[32]; // Decoded LCS address for UMTS CP NI
1265            addr_len = decodeAddress(lcs_addr, sizeof lcs_addr, address_source,
1266                                     umts_cp_req->ext_client_address_data.ext_client_address_len);
1267
1268            // The address is ASCII string
1269            if (addr_len)
1270            {
1271                strlcat(notif.extras, lcs_addr, sizeof notif.extras);
1272            }
1273        }
1274    }
1275        break;
1276
1277    case RPC_LOC_NI_EVENT_SUPL_NOTIFY_VERIFY_REQ:
1278    {
1279        const rpc_loc_ni_supl_notify_verify_req_s_type *supl_req =
1280            &ni_req->payload.rpc_loc_ni_event_payload_u_type_u.supl_req;
1281        LOC_LOGI("SUPL Notification\n");
1282        notif.ni_type = GPS_NI_TYPE_UMTS_SUPL;
1283
1284        if (supl_req->flags & RPC_LOC_NI_CLIENT_NAME_PRESENT)
1285        {
1286#if (AMSS_VERSION==3200)
1287            hexcode(notif.text, sizeof notif.text,
1288                    supl_req->client_name.client_name_string.client_name_string_val,   /* buffer */
1289                    supl_req->client_name.string_len                                   /* length */
1290            );
1291#else
1292            hexcode(notif.text, sizeof notif.text,
1293                            supl_req->client_name.client_name_string,   /* buffer */
1294                            supl_req->client_name.string_len            /* length */
1295            );
1296#endif /* #if (AMSS_VERSION==3200) */
1297            LOC_LOGV("SUPL NI: client_name: %s len=%d", notif.text, supl_req->client_name.string_len);
1298        }
1299        else {
1300            LOC_LOGV("SUPL NI: client_name not present.");
1301        }
1302
1303        // Requestor ID
1304        if (supl_req->flags & RPC_LOC_NI_REQUESTOR_ID_PRESENT)
1305        {
1306#if (AMSS_VERSION==3200)
1307            hexcode(notif.requestor_id, sizeof notif.requestor_id,
1308                    supl_req->requestor_id.requestor_id_string.requestor_id_string_val,  /* buffer */
1309                    supl_req->requestor_id.string_len                                    /* length */
1310                );
1311#else
1312            hexcode(notif.requestor_id, sizeof notif.requestor_id,
1313                    supl_req->requestor_id.requestor_id_string,  /* buffer */
1314                    supl_req->requestor_id.string_len            /* length */
1315                );
1316#endif /* #if (AMSS_VERSION==3200) */
1317            LOC_LOGV("SUPL NI: requestor_id: %s len=%d", notif.requestor_id, supl_req->requestor_id.string_len);
1318        }
1319        else {
1320            LOC_LOGV("SUPL NI: requestor_id not present.");
1321        }
1322
1323        // Encoding type
1324        if (supl_req->flags & RPC_LOC_NI_ENCODING_TYPE_PRESENT)
1325        {
1326            notif.text_encoding = convertNiEncodingType(supl_req->datacoding_scheme);
1327            notif.requestor_id_encoding = notif.text_encoding;
1328        }
1329        else {
1330            notif.text_encoding = notif.requestor_id_encoding = GPS_ENC_UNKNOWN;
1331        }
1332
1333        NIEventFillVerfiyType(notif, ni_req->payload.rpc_loc_ni_event_payload_u_type_u.supl_req.notification_priv_type);
1334    }
1335        break;
1336
1337    default:
1338        LOC_LOGE("Unknown NI event: %x\n", (int) ni_req->event);
1339        return;
1340    }
1341
1342    // this copy will get freed in loc_eng_ni when loc_ni_respond() is called
1343    rpc_loc_ni_event_s_type *copy = (rpc_loc_ni_event_s_type *)malloc(sizeof(*copy));
1344    memcpy(copy, ni_req, sizeof(*copy));
1345    requestNiNotify(notif, (const void*)copy);
1346}
1347
1348int LocApiRpc::NIEventFillVerfiyType(GpsNiNotification &notif,
1349                                rpc_loc_ni_notify_verify_e_type notif_priv)
1350{
1351   switch (notif_priv)
1352   {
1353   case RPC_LOC_NI_USER_NO_NOTIFY_NO_VERIFY:
1354       notif.notify_flags = 0;
1355       notif.default_response = GPS_NI_RESPONSE_NORESP;
1356       return 1;
1357   case RPC_LOC_NI_USER_NOTIFY_ONLY:
1358       notif.notify_flags = GPS_NI_NEED_NOTIFY;
1359       notif.default_response = GPS_NI_RESPONSE_NORESP;
1360       return 1;
1361   case RPC_LOC_NI_USER_NOTIFY_VERIFY_ALLOW_NO_RESP:
1362       notif.notify_flags = GPS_NI_NEED_NOTIFY | GPS_NI_NEED_VERIFY;
1363       notif.default_response = GPS_NI_RESPONSE_ACCEPT;
1364       return 1;
1365   case RPC_LOC_NI_USER_NOTIFY_VERIFY_NOT_ALLOW_NO_RESP:
1366       notif.notify_flags = GPS_NI_NEED_NOTIFY | GPS_NI_NEED_VERIFY;
1367       notif.default_response = GPS_NI_RESPONSE_DENY;
1368       return 1;
1369   case RPC_LOC_NI_USER_PRIVACY_OVERRIDE:
1370       notif.notify_flags = GPS_NI_PRIVACY_OVERRIDE;
1371       notif.default_response = GPS_NI_RESPONSE_NORESP;
1372       return 1;
1373   default:
1374      return 0;
1375   }
1376}
1377
1378enum loc_api_adapter_err
1379LocApiRpc::setSUPLVersion(uint32_t version)
1380{
1381   rpc_loc_ioctl_data_u_type ioctl_data = {RPC_LOC_IOCTL_SET_SUPL_VERSION, {0}};
1382   ioctl_data.rpc_loc_ioctl_data_u_type_u.supl_version = (int)version;
1383   return convertErr(
1384       loc_eng_ioctl (client_handle,
1385                      RPC_LOC_IOCTL_SET_SUPL_VERSION,
1386                      &ioctl_data,
1387                      LOC_IOCTL_DEFAULT_TIMEOUT,
1388                      NULL)
1389       );
1390}
1391
1392GpsNiEncodingType LocApiRpc::convertNiEncodingType(int loc_encoding)
1393{
1394   switch (loc_encoding)
1395   {
1396   case RPC_LOC_NI_SUPL_UTF8:
1397       return GPS_ENC_SUPL_UTF8;
1398   case RPC_LOC_NI_SUPL_UCS2:
1399       return GPS_ENC_SUPL_UCS2;
1400   case RPC_LOC_NI_SUPL_GSM_DEFAULT:
1401      return GPS_ENC_SUPL_GSM_DEFAULT;
1402   case RPC_LOC_NI_SS_LANGUAGE_UNSPEC:
1403      return GPS_ENC_SUPL_GSM_DEFAULT; // SS_LANGUAGE_UNSPEC = GSM
1404   default:
1405       return GPS_ENC_UNKNOWN;
1406   }
1407}
1408
1409LocApiBase* getLocApi(const MsgTask* msgTask,
1410                      LOC_API_ADAPTER_EVENT_MASK_T exMask,
1411                      ContextBase *context) {
1412    return new LocApiRpc(msgTask, exMask, context);
1413}
1414
1415/*Values for lock
1416  1 = Do not lock any position sessions
1417  2 = Lock MI position sessions
1418  3 = Lock MT position sessions
1419  4 = Lock all position sessions
1420*/
1421int LocApiRpc::setGpsLock(LOC_GPS_LOCK_MASK lockMask)
1422{
1423    rpc_loc_ioctl_data_u_type    ioctl_data;
1424    boolean ret_val;
1425    LOC_LOGD("%s:%d]: lock: %x\n", __func__, __LINE__, lockMask);
1426    ioctl_data.rpc_loc_ioctl_data_u_type_u.engine_lock = convertGpsLockMask(lockMask);
1427    ioctl_data.disc = RPC_LOC_IOCTL_SET_ENGINE_LOCK;
1428    ret_val = loc_eng_ioctl (loc_eng_data.client_handle,
1429                            RPC_LOC_IOCTL_SET_ENGINE_LOCK,
1430                            &ioctl_data,
1431                            LOC_IOCTL_DEFAULT_TIMEOUT,
1432                            NULL /* No output information is expected*/);
1433
1434    LOC_LOGD("%s:%d]: ret_val: %d\n", __func__, __LINE__, (int)ret_val);
1435    return (ret_val == TRUE ? 0 : -1);
1436}
1437
1438/*
1439  Returns
1440  Current value of GPS lock on success
1441  -1 on failure
1442*/
1443int LocApiRpc :: getGpsLock()
1444{
1445    rpc_loc_ioctl_data_u_type    ioctl_data;
1446    rpc_loc_ioctl_callback_s_type callback_payload;
1447    boolean ret_val;
1448    int ret=0;
1449    LOC_LOGD("%s:%d]: Enter\n", __func__, __LINE__);
1450    ret_val = loc_eng_ioctl (loc_eng_data.client_handle,
1451                            RPC_LOC_IOCTL_GET_ENGINE_LOCK,
1452                            &ioctl_data,
1453                            LOC_IOCTL_DEFAULT_TIMEOUT,
1454                            &callback_payload);
1455    if(ret_val == TRUE) {
1456        ret = (int)callback_payload.data.engine_lock;
1457        LOC_LOGD("%s:%d]: Lock type: %d\n", __func__, __LINE__, ret);
1458    }
1459    else {
1460        LOC_LOGE("%s:%d]: Ioctl failed", __func__, __LINE__);
1461        ret = -1;
1462    }
1463    LOC_LOGD("%s:%d]: Exit\n", __func__, __LINE__);
1464    return ret;
1465}
1466