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