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