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