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                    (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
800void 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
906void 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
928void 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
944enum loc_api_adapter_err
945LocApiRpc::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 */
1022enum loc_api_adapter_err
1023LocApiRpc::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
1067enum loc_api_adapter_err
1068LocApiRpc::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
1141enum loc_api_adapter_err
1142LocApiRpc::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
1162void 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
1198void 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
1344int 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
1374enum loc_api_adapter_err
1375LocApiRpc::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
1388GpsNiEncodingType 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
1405LocApiBase* 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*/
1417int 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*/
1439int 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