1/* Copyright (c) 2011-2012, 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/*===================================================================== 30 31 INCLUDE FILES FOR MODULE 32 33======================================================================*/ 34#include <stdio.h> 35#include <pthread.h> 36#include <errno.h> 37#include <string.h> 38#include <sys/select.h> 39#include <sys/time.h> 40#include <sys/types.h> 41#include <sys/stat.h> 42#include <fcntl.h> 43#include <sys/mman.h> 44#include <unistd.h> 45#include <stdlib.h> 46#include <assert.h> 47#include <loc_api_log.h> 48 49#include <rpc/rpc.h> 50 51/* Include RPC headers */ 52#include "rpc_inc/loc_api_rpc_glue.h" 53 54/* Callback init */ 55#include "rpc_inc/loc_apicb_appinit.h" 56 57/* Logging */ 58#define LOG_TAG "LocSvc_api_rpc_glue" 59#define LOG_NDDEBUG 0 60#ifndef USE_GLIB 61#include <utils/Log.h> 62#endif /* USE_GLIB */ 63 64/* Logging Improvement */ 65#include "log_util.h" 66#include "platform_lib_includes.h" 67/*Maximum number of Modem init*/ 68#define RPC_TRY_NUM 10 69 70/*Maximum number of Modem init*/ 71#define RPC_TRY_NUM 10 72 73/* Uncomment to force ALOGD messages */ 74// #define ALOGD ALOGI 75 76/*===================================================================== 77 External declarations 78======================================================================*/ 79 80CLIENT* loc_api_clnt = NULL; 81 82/* Callback ID and pointer */ 83#define LOC_API_CB_MAX_CLIENTS 16 84typedef struct 85{ 86 uint32 cb_id; /* same as rpc/types.h */ 87 loc_event_cb_f_type *cb_func; /* callback func */ 88 loc_reset_notif_cb_f_type *rpc_cb; /* callback from RPC */ 89 rpc_loc_client_handle_type handle; /* stores handle for client closing */ 90 void* user; /* user's own data handle */ 91} loc_glue_cb_entry_s_type; 92 93loc_glue_cb_entry_s_type loc_glue_callback_table[LOC_API_CB_MAX_CLIENTS]; 94 95#define RPC_FUNC_VERSION_BASE(a,b) a ## b 96#define RPC_FUNC_VERSION(a,b) RPC_FUNC_VERSION_BASE(a,b) 97 98#define RPC_CALLBACK_FUNC_VERSION_BASE(a,v,b) a ## v ## b 99#define RPC_CALLBACK_FUNC_VERSION(a,v,b) RPC_CALLBACK_FUNC_VERSION_BASE(a,v,b) 100 101#define LOC_GLUE_CHECK_INIT(ret_type) \ 102 if (loc_api_clnt == NULL) { EXIT_LOG_CALLFLOW(%d, RPC_LOC_API_RPC_FAILURE); return (ret_type) RPC_LOC_API_RPC_FAILURE; } 103 104#define LOC_GLUE_CHECK_RESULT(stat, ret_type) \ 105 if (stat != RPC_SUCCESS) { \ 106 LOC_LOGE("%s:%d] failure code %d", __func__, __LINE__, stat); \ 107 return (ret_type)((stat == RPC_SUBSYSTEM_RESTART) ? \ 108 RPC_LOC_API_RPC_MODEM_RESTART : RPC_LOC_API_RPC_FAILURE); \ 109 } 110 111/* Callback functions */ 112/* Returns 1 if successful */ 113bool_t rpc_loc_event_cb_f_type_svc( 114 rpc_loc_event_cb_f_type_args *argp, 115 rpc_loc_event_cb_f_type_rets *ret, 116 struct svc_req *req) 117{ 118 // The lower word of cd_id is the index 119 int index = argp->cb_id & 0xFFFF; 120 121 /* Callback not registered, or unexpected ID (shouldn't happen) */ 122 if (index >= LOC_API_CB_MAX_CLIENTS || loc_glue_callback_table[index].cb_func == NULL) 123 { 124 LOC_LOGE("Warning: No callback handler %d.\n", index); 125 ret->loc_event_cb_f_type_result = 0; 126 return 1; /* simply return */ 127 } 128 129 LOC_LOGV("proc: %x prog: %x vers: %x\n", 130 (int) req->rq_proc, 131 (int) req->rq_prog, 132 (int) req->rq_vers); 133 134 LOC_LOGV("Callback received: %x (cb_id=%p handle=%d ret_ptr=%d)\n", 135 (int) argp->loc_event, 136 argp->cb_id, 137 (int) argp->loc_handle, 138 (int) ret); 139 140 /* Forward callback to real callback procedure */ 141 rpc_loc_client_handle_type loc_handle = argp->loc_handle; 142 rpc_loc_event_mask_type loc_event = argp->loc_event; 143 const rpc_loc_event_payload_u_type* loc_event_payload = 144 (const rpc_loc_event_payload_u_type*) argp->loc_event_payload; 145 146 /* Gives control to synchronous call handler */ 147 loc_api_callback_process_sync_call(loc_handle, loc_event, loc_event_payload); 148 149 int32 rc = (loc_glue_callback_table[index].cb_func)(loc_glue_callback_table[index].user, 150 loc_handle, loc_event, loc_event_payload); 151 152 LOC_LOGV("cb_func=%p", loc_glue_callback_table[index].cb_func); 153 154 ret->loc_event_cb_f_type_result = rc; 155 156 return 1; /* ok */ 157} 158 159int loc_apicbprog_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result) 160{ 161 xdr_free (xdr_result, result); 162 163 /* 164 * Insert additional freeing code here, if needed 165 */ 166 // LOC_LOGD("***** loc_apicbprog_freeresult\n"); 167 168 return 1; 169} 170 171/*=========================================================================== 172 173FUNCTION rpc_loc_event_cb_f_type_<version>_svc (MACRO) 174 175DESCRIPTION 176 Callback function for Loc API 177 178RETURN VALUE 179 1 for success 180 0 for failure 181 182===========================================================================*/ 183bool_t RPC_CALLBACK_FUNC_VERSION(rpc_loc_event_cb_f_type_, RPC_LOC_EVENT_CB_F_TYPE_VERSION, _svc) ( 184 rpc_loc_event_cb_f_type_args *argp, 185 rpc_loc_event_cb_f_type_rets *ret, 186 struct svc_req *req) 187{ 188 return rpc_loc_event_cb_f_type_svc(argp, ret, req); 189} 190 191/*=========================================================================== 192 193FUNCTION loc_apicbprog_<version>_freeresult (MACRO) 194 195DESCRIPTION 196 Free up RPC data structure 197 198RETURN VALUE 199 1 for success 200 0 for failure 201 202===========================================================================*/ 203#define VERSION_CONCAT(MAJOR,MINOR) MAJOR##MINOR 204#define loc_apicb_prog_VER_freeresult(M,N) \ 205int RPC_CALLBACK_FUNC_VERSION(loc_apicbprog_, VERSION_CONCAT(M,N), _freeresult) \ 206(SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result) \ 207{ \ 208 return loc_apicbprog_freeresult(transp, xdr_result, result); \ 209} 210 211/* Define all of the possible minors */ 212loc_apicb_prog_VER_freeresult(RPC_LOC_API_API_MAJOR_NUM, 0001); 213loc_apicb_prog_VER_freeresult(RPC_LOC_API_API_MAJOR_NUM, 0002); 214loc_apicb_prog_VER_freeresult(RPC_LOC_API_API_MAJOR_NUM, 0003); 215loc_apicb_prog_VER_freeresult(RPC_LOC_API_API_MAJOR_NUM, 0004); 216loc_apicb_prog_VER_freeresult(RPC_LOC_API_API_MAJOR_NUM, 0005); 217loc_apicb_prog_VER_freeresult(RPC_LOC_API_API_MAJOR_NUM, 0006); 218 219/*=========================================================================== 220 221FUNCTION rpc_loc_api_cb_null_<version>_svc (MACRO) [Patch for wrong RPCGEN stubs] 222 223DESCRIPTION 224 Null callback function for Loc API 225 226RETURN VALUE 227 1 for success 228 229===========================================================================*/ 230#define rpc_loc_api_cb_null_VER_svc(M,N) \ 231bool_t RPC_CALLBACK_FUNC_VERSION(rpc_loc_api_cb_null_, VERSION_CONCAT(M,N), _svc) ( \ 232 void *a, int *b, struct svc_req *req) \ 233{ \ 234 return 1; \ 235} 236 237/* Define all of the possible minors */ 238rpc_loc_api_cb_null_VER_svc(RPC_LOC_API_API_MAJOR_NUM, 0001); 239rpc_loc_api_cb_null_VER_svc(RPC_LOC_API_API_MAJOR_NUM, 0002); 240rpc_loc_api_cb_null_VER_svc(RPC_LOC_API_API_MAJOR_NUM, 0003); 241rpc_loc_api_cb_null_VER_svc(RPC_LOC_API_API_MAJOR_NUM, 0004); 242rpc_loc_api_cb_null_VER_svc(RPC_LOC_API_API_MAJOR_NUM, 0005); 243rpc_loc_api_cb_null_VER_svc(RPC_LOC_API_API_MAJOR_NUM, 0006); 244 245static void loc_api_glue_rpc_cb(CLIENT* client, enum rpc_reset_event event) 246{ 247 int i; 248 for (i = 0; i < LOC_API_CB_MAX_CLIENTS; i++) { 249 if (NULL != loc_glue_callback_table[i].rpc_cb) { 250 loc_glue_callback_table[i].rpc_cb(loc_glue_callback_table[i].user, client, event); 251 } 252 } 253} 254 255/*=========================================================================== 256 257FUNCTION loc_api_glue_init 258 259DESCRIPTION 260 Initiates the RPC client 261 262RETURN VALUE 263 1 for success 264 0 for failure 265 266===========================================================================*/ 267int loc_api_glue_init(void) 268{ 269 if (loc_api_clnt == NULL) 270 { 271 /* Initialize data */ 272 int i; 273 int pid = getpid(); 274 for (i = 0; i < LOC_API_CB_MAX_CLIENTS; i++) 275 { 276 loc_glue_callback_table[i].cb_id = i | (pid << 16); 277 loc_glue_callback_table[i].cb_func = NULL; 278 loc_glue_callback_table[i].handle = -1; 279 loc_glue_callback_table[i].rpc_cb = NULL; 280 loc_glue_callback_table[i].user = NULL; 281 } 282 283 /* Print msg */ 284 LOC_LOGV("Trying to create RPC client...\n"); 285 loc_api_clnt = clnt_create(NULL, LOC_APIPROG, LOC_APIVERS, NULL); 286 LOC_LOGV("Created loc_api_clnt ---- %x\n", (unsigned int)loc_api_clnt); 287 288 if (loc_api_clnt == NULL) 289 { 290 LOC_LOGE("Error: cannot create RPC client.\n"); 291 return 0; 292 } 293 294 /* Init RPC callbacks */ 295 loc_api_sync_call_init(); 296 297 int rc = loc_apicb_app_init(); 298 if (rc >= 0) 299 { 300 LOC_LOGD("Loc API RPC client initialized.\n"); 301 clnt_register_reset_notification_cb(loc_api_clnt, loc_api_glue_rpc_cb); 302 } 303 else { 304 LOC_LOGE("Loc API callback initialization failed.\n"); 305 return 0; 306 } 307 } 308 309 return 1; 310} 311 312rpc_loc_client_handle_type loc_open ( 313 rpc_loc_event_mask_type event_reg_mask, 314 loc_event_cb_f_type *event_callback, 315 loc_reset_notif_cb_f_type *rpc_cb, 316 void* userData 317) 318{ 319 int try_num = RPC_TRY_NUM; 320 ENTRY_LOG(); 321 LOC_GLUE_CHECK_INIT(rpc_loc_client_handle_type); 322 323 rpc_loc_client_handle_type ret_val; 324 325 rpc_loc_open_args args; 326 args.event_reg_mask = event_reg_mask; 327 328 int i, j = LOC_API_CB_MAX_CLIENTS; 329 for (i = 0; i < LOC_API_CB_MAX_CLIENTS; i++) 330 { 331 if (loc_glue_callback_table[i].user == userData) 332 { 333 LOC_LOGW("Client already opened service (callback=%p)...\n", 334 event_callback); 335 break; 336 } else if (j == LOC_API_CB_MAX_CLIENTS && 337 loc_glue_callback_table[i].user == NULL) { 338 j = i; 339 } 340 } 341 342 if (i == LOC_API_CB_MAX_CLIENTS) 343 { 344 i = j; 345 } 346 347 if (i == LOC_API_CB_MAX_CLIENTS) 348 { 349 LOC_LOGE("Too many clients opened at once...\n"); 350 return RPC_LOC_CLIENT_HANDLE_INVALID; 351 } 352 353 loc_glue_callback_table[i].cb_func = event_callback; 354 loc_glue_callback_table[i].rpc_cb = rpc_cb; 355 loc_glue_callback_table[i].user = userData; 356 357 args.event_callback = loc_glue_callback_table[i].cb_id; 358 LOC_LOGV("cb_id=%d, func=0x%x", i, (unsigned int) event_callback); 359 360 rpc_loc_open_rets rets; 361 enum clnt_stat stat = RPC_SUCCESS; 362 363 EXIT_LOG_CALLFLOW(%s, "loc client open"); 364 365 /*try more for rpc_loc_open_xx()*/ 366 367 do 368 { 369 stat = RPC_FUNC_VERSION(rpc_loc_open_, RPC_LOC_OPEN_VERSION)(&args, &rets, loc_api_clnt); 370 ret_val = (rpc_loc_client_handle_type) rets.loc_open_result; 371 try_num--; 372 373 }while( (RPC_SUCCESS != stat||0 > ret_val) && 0 != try_num ); 374 375 LOC_GLUE_CHECK_RESULT(stat, int32); 376 377 /* save the handle in the table */ 378 loc_glue_callback_table[i].handle = (rpc_loc_client_handle_type) rets.loc_open_result; 379 380 return ret_val; 381 382} 383 384int32 loc_close 385( 386 rpc_loc_client_handle_type handle 387) 388{ 389 ENTRY_LOG(); 390 LOC_GLUE_CHECK_INIT(int32); 391 392 int32 ret_val; 393 394 rpc_loc_close_args args; 395 args.handle = handle; 396 397 rpc_loc_close_rets rets; 398 enum clnt_stat stat = RPC_SUCCESS; 399 400 EXIT_LOG_CALLFLOW(%s, "loc client close"); 401 stat = RPC_FUNC_VERSION(rpc_loc_close_, RPC_LOC_CLOSE_VERSION)(&args, &rets, loc_api_clnt); 402 403 loc_clear(handle); 404 405 LOC_GLUE_CHECK_RESULT(stat, int32); 406 ret_val = (int32) rets.loc_close_result; 407 408 return ret_val; 409} 410 411void loc_clear(rpc_loc_client_handle_type handle) { 412 /* Clean the client's callback function in callback table */ 413 int i; 414 for (i = 0; i < LOC_API_CB_MAX_CLIENTS; i++) 415 { 416 if (loc_glue_callback_table[i].handle == handle) 417 { 418 /* Found the client */ 419 loc_glue_callback_table[i].cb_func = NULL; 420 loc_glue_callback_table[i].rpc_cb = NULL; 421 loc_glue_callback_table[i].handle = -1; 422 loc_glue_callback_table[i].user = NULL; 423 break; 424 } 425 } 426 427 if (i == LOC_API_CB_MAX_CLIENTS) 428 { 429 LOC_LOGW("Handle not found (handle=%d)...\n", (int) handle); 430 } 431} 432 433int32 loc_start_fix 434( 435 rpc_loc_client_handle_type handle 436) 437{ 438 ENTRY_LOG(); 439 LOC_GLUE_CHECK_INIT(int32); 440 441 int32 ret_val; 442 443 rpc_loc_start_fix_args args; 444 args.handle = handle; 445 446 rpc_loc_start_fix_rets rets; 447 enum clnt_stat stat = RPC_SUCCESS; 448 449 EXIT_LOG_CALLFLOW(%s, "loc start fix"); 450 stat = RPC_FUNC_VERSION(rpc_loc_start_fix_, RPC_LOC_START_FIX_VERSION)(&args, &rets, loc_api_clnt); 451 LOC_GLUE_CHECK_RESULT(stat, int32); 452 453 ret_val = (int32) rets.loc_start_fix_result; 454 455 return ret_val; 456} 457 458int32 loc_stop_fix 459( 460 rpc_loc_client_handle_type handle 461) 462{ 463 ENTRY_LOG(); 464 LOC_GLUE_CHECK_INIT(int32); 465 466 int32 ret_val; 467 468 rpc_loc_stop_fix_args args; 469 args.handle = handle; 470 471 rpc_loc_stop_fix_rets rets; 472 enum clnt_stat stat = RPC_SUCCESS; 473 474 EXIT_LOG_CALLFLOW(%s, "loc stop fix"); 475 stat = RPC_FUNC_VERSION(rpc_loc_stop_fix_, RPC_LOC_STOP_FIX_VERSION)(&args, &rets, loc_api_clnt); 476 LOC_GLUE_CHECK_RESULT(stat, int32); 477 478 ret_val = (int32) rets.loc_stop_fix_result; 479 480 return ret_val; 481} 482 483int32 loc_ioctl 484( 485 rpc_loc_client_handle_type handle, 486 rpc_loc_ioctl_e_type ioctl_type, 487 rpc_loc_ioctl_data_u_type* ioctl_data 488) 489{ 490 ENTRY_LOG(); 491 LOC_GLUE_CHECK_INIT(int32); 492 493 int32 ret_val; 494 495 rpc_loc_ioctl_args args; 496 args.handle = handle; 497 args.ioctl_data = ioctl_data; 498 args.ioctl_type = ioctl_type; 499 if (ioctl_data != NULL) 500 { 501 /* Assign ioctl union discriminator */ 502 ioctl_data->disc = ioctl_type; 503 504 /* In case the user hasn't filled in other disc fields, 505 automatically fill them in here */ 506 switch (ioctl_type) 507 { 508 case RPC_LOC_IOCTL_GET_API_VERSION: 509 break; 510 case RPC_LOC_IOCTL_SET_FIX_CRITERIA: 511 break; 512 case RPC_LOC_IOCTL_GET_FIX_CRITERIA: 513 break; 514 case RPC_LOC_IOCTL_INFORM_NI_USER_RESPONSE: 515 break; 516 case RPC_LOC_IOCTL_INJECT_PREDICTED_ORBITS_DATA: 517 break; 518 case RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_VALIDITY: 519 break; 520 case RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE: 521 break; 522 case RPC_LOC_IOCTL_SET_PREDICTED_ORBITS_DATA_AUTO_DOWNLOAD: 523 break; 524 case RPC_LOC_IOCTL_INJECT_UTC_TIME: 525 break; 526 case RPC_LOC_IOCTL_INJECT_RTC_VALUE: 527 break; 528 case RPC_LOC_IOCTL_INJECT_POSITION: 529 break; 530 case RPC_LOC_IOCTL_QUERY_ENGINE_STATE: 531 break; 532 case RPC_LOC_IOCTL_INFORM_SERVER_OPEN_STATUS: 533 break; 534 case RPC_LOC_IOCTL_INFORM_SERVER_CLOSE_STATUS: 535 break; 536 case RPC_LOC_IOCTL_SET_ENGINE_LOCK: 537 break; 538 case RPC_LOC_IOCTL_GET_ENGINE_LOCK: 539 break; 540 case RPC_LOC_IOCTL_SET_SBAS_CONFIG: 541 break; 542 case RPC_LOC_IOCTL_GET_SBAS_CONFIG: 543 break; 544 case RPC_LOC_IOCTL_SET_NMEA_TYPES: 545 break; 546 case RPC_LOC_IOCTL_GET_NMEA_TYPES: 547 break; 548 case RPC_LOC_IOCTL_SET_CDMA_PDE_SERVER_ADDR: 549 case RPC_LOC_IOCTL_SET_CDMA_MPC_SERVER_ADDR: 550 case RPC_LOC_IOCTL_SET_UMTS_SLP_SERVER_ADDR: 551 case RPC_LOC_IOCTL_SET_CUSTOM_PDE_SERVER_ADDR: 552 args.ioctl_data->rpc_loc_ioctl_data_u_type_u.server_addr.addr_info.disc = 553 args.ioctl_data->rpc_loc_ioctl_data_u_type_u.server_addr.addr_type; 554 break; 555 case RPC_LOC_IOCTL_GET_CDMA_PDE_SERVER_ADDR: 556 case RPC_LOC_IOCTL_GET_CDMA_MPC_SERVER_ADDR: 557 case RPC_LOC_IOCTL_GET_UMTS_SLP_SERVER_ADDR: 558 case RPC_LOC_IOCTL_GET_CUSTOM_PDE_SERVER_ADDR: 559 break; 560 case RPC_LOC_IOCTL_SET_ON_DEMAND_LPM: 561 break; 562 case RPC_LOC_IOCTL_GET_ON_DEMAND_LPM: 563 break; 564 case RPC_LOC_IOCTL_DELETE_ASSIST_DATA: 565 break; 566 default: 567 break; 568 } /* switch */ 569 } /* ioctl_data != NULL */ 570 571 rpc_loc_ioctl_rets rets; 572 enum clnt_stat stat = RPC_SUCCESS; 573 574 EXIT_LOG_CALLFLOW(%s, loc_get_ioctl_type_name(ioctl_type)); 575 stat = RPC_FUNC_VERSION(rpc_loc_ioctl_, RPC_LOC_IOCTL_VERSION)(&args, &rets, loc_api_clnt); 576 LOC_GLUE_CHECK_RESULT(stat, int32); 577 578 ret_val = (int32) rets.loc_ioctl_result; 579 580 return ret_val; 581} 582 583/* Returns 0 if error */ 584int32 loc_api_null(void) 585{ 586 LOC_GLUE_CHECK_INIT(int32); 587 588 int32 rets; 589 enum clnt_stat stat = RPC_SUCCESS; 590 591 clnt_unregister_reset_notification_cb(loc_api_clnt); 592 stat = RPC_FUNC_VERSION(rpc_loc_api_null_, RPC_LOC_API_NULL_VERSION)(NULL, &rets, loc_api_clnt); 593 LOC_GLUE_CHECK_RESULT(stat, int32); 594 595 return (int32) rets; 596} 597 598/*=========================================================================== 599 600FUNCTION loc_eng_ioctl 601 602DESCRIPTION 603 This function calls loc_ioctl and waits for the callback result before 604 returning back to the user. 605 606DEPENDENCIES 607 N/A 608 609RETURN VALUE 610 TRUE if successful 611 FALSE if failed 612 613SIDE EFFECTS 614 N/A 615 616===========================================================================*/ 617int loc_eng_ioctl 618( 619 rpc_loc_client_handle_type handle, 620 rpc_loc_ioctl_e_type ioctl_type, 621 rpc_loc_ioctl_data_u_type* ioctl_data_ptr, 622 uint32 timeout_msec, 623 rpc_loc_ioctl_callback_s_type *cb_data_ptr 624) 625{ 626 int ret_val = RPC_LOC_API_SUCCESS; 627 628 ret_val = loc_api_sync_ioctl(handle, ioctl_type, ioctl_data_ptr, timeout_msec, cb_data_ptr); 629 630 LOC_LOGD("loc_eng_ioctl result: client = %d, ioctl_type = %s, returt %s\n", 631 (int32) handle, 632 loc_get_ioctl_type_name(ioctl_type), 633 loc_get_ioctl_status_name(ret_val) ); 634 635 return ret_val; 636} 637