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