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