1/******************************************************************************
2  @file  loc_api_rpc_glue.c
3  @brief Android Loc API glue code using rpcgen.
4
5  DESCRIPTION
6  Loc API glue code for Android
7
8  -----------------------------------------------------------------------------
9Copyright (c) 2009, QUALCOMM USA, INC.
10
11All rights reserved.
12
13Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
14
15·         Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
16
17·         Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
18
19·         Neither the name of the QUALCOMM USA, INC.  nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
20
21THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22  -----------------------------------------------------------------------------
23 ******************************************************************************/
24/*=====================================================================
25                        EDIT HISTORY FOR MODULE
26
27  This section contains comments describing changes made to the module.
28  Notice that changes are listed in reverse chronological order.
29
30when       who      what, where, why
31--------   ---      -------------------------------------------------------
3203/05/2009   dx       Initial version
33
34======================================================================*/
35/*=====================================================================
36
37                     INCLUDE FILES FOR MODULE
38
39======================================================================*/
40//#define LOG_NDDEBUG 0
41
42#include <stdio.h>
43#include <pthread.h>
44#include <errno.h>
45#include <string.h>
46#include <sys/select.h>
47#include <sys/time.h>
48#include <sys/types.h>
49#include <sys/stat.h>
50#include <fcntl.h>
51#include <sys/mman.h>
52#include <unistd.h>
53#include <stdlib.h>
54#include <assert.h>
55
56#include <rpc/rpc.h>
57#include <rpc/clnt.h>
58
59/* Include RPC headers */
60#include "loc_api_rpc_glue.h"
61
62/* Callback init */
63#include "loc_apicb_appinit.h"
64
65/* Logging */
66#define LOG_TAG "lib_api_rpc_glue"
67#include <utils/Log.h>
68
69/* Comment this out to enable logging */
70#undef ALOGD
71#define ALOGD(...) {}
72
73/*=====================================================================
74     External declarations
75======================================================================*/
76
77CLIENT* loc_api_clnt = NULL;
78
79/* Callback ID and pointer */
80#define LOC_API_CB_ID 1
81loc_event_cb_f_type *loc_api_saved_cb = NULL;  /* the only callback of Loc API client */
82
83#define RPC_FUNC_VERSION_BASE(a,b) a ## b
84#define RPC_FUNC_VERSION(a,b) RPC_FUNC_VERSION_BASE(a,b)
85
86#define LOC_GLUE_CHECK_INIT(ret_type) \
87   if (loc_api_clnt == NULL) { return (ret_type) RPC_LOC_API_RPC_FAILURE; }
88
89#define LOC_GLUE_CHECK_RESULT(stat, ret_type) \
90   if (stat != RPC_SUCCESS) { return (ret_type) RPC_LOC_API_RPC_FAILURE; }
91
92/* Callback functions */
93/* Returns 1 if successful */
94bool_t rpc_loc_event_cb_f_type_0x00040001_svc(
95        rpc_loc_event_cb_f_type_args *argp,
96        rpc_loc_event_cb_f_type_rets *ret,
97        struct svc_req *req)
98{
99    /* Callback not registered, or unexpected ID (shouldn't happen) */
100    if (loc_api_saved_cb == NULL || argp->cb_id != LOC_API_CB_ID)
101    {
102        ALOGD("Warning: No callback handler.\n");
103        ret->loc_event_cb_f_type_result = 0;
104        return 1; /* simply return */
105    }
106
107    ALOGD("proc: %x  prog: %x  vers: %x\n",
108            (int) req->rq_proc,
109            (int) req->rq_prog,
110            (int) req->rq_vers);
111
112    ALOGD("Callback received: %x (handle=%d ret_ptr=%d)\n",
113            (int) argp->loc_event,
114            (int) argp->loc_handle,
115            (int) ret);
116
117    /* Forward callback to real callback procedure */
118    rpc_loc_client_handle_type        loc_handle = argp->loc_handle;
119    rpc_loc_event_mask_type           loc_event  = argp->loc_event;
120    const rpc_loc_event_payload_u_type*  loc_event_payload =
121        (const rpc_loc_event_payload_u_type*) argp->loc_event_payload;
122
123    int32 rc = loc_api_saved_cb(loc_handle, loc_event, loc_event_payload);
124    ret->loc_event_cb_f_type_result = rc;
125
126    return 1; /* ok */
127}
128
129int loc_apicbprog_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
130{
131    xdr_free (xdr_result, result);
132
133    /*
134     * Insert additional freeing code here, if needed
135     */
136    // ALOGD("***** loc_apicbprog_freeresult\n");
137
138    return 1;
139}
140
141int loc_apicbprog_0x00040001_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
142{
143    return loc_apicbprog_freeresult (transp, xdr_result, result);
144}
145
146/*===========================================================================
147
148FUNCTION loc_api_glue_init
149
150DESCRIPTION
151   Initiates the RPC client
152
153RETURN VALUE
154   1 for success
155   0 for failure
156
157===========================================================================*/
158int loc_api_glue_init(void)
159{
160    if (loc_api_clnt == NULL)
161    {
162        /* Print msg */
163        ALOGD("Trying to create RPC client...\n");
164        loc_api_clnt = clnt_create(NULL, LOC_APIPROG, LOC_APIVERS, NULL);
165        ALOGD("Created loc_api_clnt ---- %x\n", (unsigned int)loc_api_clnt);
166
167        if (loc_api_clnt == NULL)
168        {
169            fprintf(stderr, "Error: cannot create RPC client.\n");
170            return 0;
171        }
172
173        /* Init RPC callbacks */
174        int rc = loc_apicb_app_init();
175        if (rc >= 0)
176        {
177            ALOGD("Loc API callback initialized.\n");
178        } else {
179            fprintf(stderr, "Loc API callback initialization failed.\n");
180            return 0;
181        }
182    }
183
184    return 1;
185}
186
187rpc_loc_client_handle_type loc_open (
188        rpc_loc_event_mask_type  event_reg_mask,
189        loc_event_cb_f_type      *event_callback
190    )
191{
192    LOC_GLUE_CHECK_INIT(rpc_loc_client_handle_type);
193
194    rpc_loc_open_args args;
195    args.event_reg_mask = event_reg_mask;
196    args.event_callback = LOC_API_CB_ID;
197    loc_api_saved_cb = event_callback;
198
199    rpc_loc_open_rets rets;
200    enum clnt_stat stat = RPC_SUCCESS;
201
202    stat = RPC_FUNC_VERSION(rpc_loc_open_, /* LOC_APIVERS */ 0x00040001)(&args, &rets, loc_api_clnt);
203    LOC_GLUE_CHECK_RESULT(stat, int32);
204
205    return (rpc_loc_client_handle_type) rets.loc_open_result;
206}
207
208int32 loc_close(rpc_loc_client_handle_type handle)
209{
210    LOC_GLUE_CHECK_INIT(int32);
211
212    rpc_loc_close_args args;
213    args.handle = handle;
214
215    rpc_loc_close_rets rets;
216    enum clnt_stat stat = RPC_SUCCESS;
217
218    stat = RPC_FUNC_VERSION(rpc_loc_close_, /* LOC_APIVERS */ 0x00040001)(&args, &rets, loc_api_clnt);
219    LOC_GLUE_CHECK_RESULT(stat, int32);
220
221    return (int32) rets.loc_close_result;
222}
223
224int32 loc_start_fix(rpc_loc_client_handle_type handle)
225{
226    LOC_GLUE_CHECK_INIT(int32);
227
228    rpc_loc_start_fix_args args;
229    args.handle = handle;
230
231    rpc_loc_start_fix_rets rets;
232    enum clnt_stat stat = RPC_SUCCESS;
233
234    stat = RPC_FUNC_VERSION(rpc_loc_start_fix_, /* LOC_APIVERS */ 0x00040001)(&args, &rets, loc_api_clnt);
235    LOC_GLUE_CHECK_RESULT(stat, int32);
236
237    return (int32) rets.loc_start_fix_result;
238}
239
240int32 loc_stop_fix(rpc_loc_client_handle_type handle)
241{
242    LOC_GLUE_CHECK_INIT(int32);
243
244    rpc_loc_stop_fix_args args;
245    args.handle = handle;
246
247    rpc_loc_stop_fix_rets rets;
248    enum clnt_stat stat = RPC_SUCCESS;
249
250    stat = RPC_FUNC_VERSION(rpc_loc_stop_fix_, /* LOC_APIVERS */ 0x00040001)(&args, &rets, loc_api_clnt);
251    LOC_GLUE_CHECK_RESULT(stat, int32);
252
253    return (int32) rets.loc_stop_fix_result;
254}
255
256int32 loc_ioctl(
257    rpc_loc_client_handle_type           handle,
258    rpc_loc_ioctl_e_type                 ioctl_type,
259    rpc_loc_ioctl_data_u_type*           ioctl_data
260    )
261{
262    LOC_GLUE_CHECK_INIT(int32);
263
264    rpc_loc_ioctl_args args;
265    args.handle = handle;
266    args.ioctl_data = ioctl_data;
267    args.ioctl_type = ioctl_type;
268    if (ioctl_data != NULL)
269    {
270        /* Assign ioctl union discriminator */
271        ioctl_data->disc = ioctl_type;
272
273        /* In case the user hasn't filled in other disc fields,
274           automatically fill them in here */
275        switch (ioctl_type)
276        {
277            case RPC_LOC_IOCTL_GET_API_VERSION:
278            case RPC_LOC_IOCTL_SET_FIX_CRITERIA:
279            case RPC_LOC_IOCTL_GET_FIX_CRITERIA:
280            case RPC_LOC_IOCTL_INFORM_NI_USER_RESPONSE:
281            case RPC_LOC_IOCTL_INJECT_PREDICTED_ORBITS_DATA:
282            case RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_VALIDITY:
283            case RPC_LOC_IOCTL_QUERY_PREDICTED_ORBITS_DATA_SOURCE:
284            case RPC_LOC_IOCTL_SET_PREDICTED_ORBITS_DATA_AUTO_DOWNLOAD:
285            case RPC_LOC_IOCTL_INJECT_UTC_TIME:
286            case RPC_LOC_IOCTL_INJECT_RTC_VALUE:
287            case RPC_LOC_IOCTL_INJECT_POSITION:
288            case RPC_LOC_IOCTL_QUERY_ENGINE_STATE:
289            case RPC_LOC_IOCTL_INFORM_SERVER_OPEN_STATUS:
290            case RPC_LOC_IOCTL_INFORM_SERVER_CLOSE_STATUS:
291            case RPC_LOC_IOCTL_SET_ENGINE_LOCK:
292            case RPC_LOC_IOCTL_GET_ENGINE_LOCK:
293            case RPC_LOC_IOCTL_SET_SBAS_CONFIG:
294            case RPC_LOC_IOCTL_GET_SBAS_CONFIG:
295            case RPC_LOC_IOCTL_SET_NMEA_TYPES:
296            case RPC_LOC_IOCTL_GET_NMEA_TYPES:
297                break;
298            case RPC_LOC_IOCTL_SET_CDMA_PDE_SERVER_ADDR:
299            case RPC_LOC_IOCTL_SET_CDMA_MPC_SERVER_ADDR:
300            case RPC_LOC_IOCTL_SET_UMTS_SLP_SERVER_ADDR:
301                args.ioctl_data->rpc_loc_ioctl_data_u_type_u.server_addr.addr_info.disc =
302                    args.ioctl_data->rpc_loc_ioctl_data_u_type_u.server_addr.addr_type;
303                break;
304            case RPC_LOC_IOCTL_GET_CDMA_PDE_SERVER_ADDR:
305            case RPC_LOC_IOCTL_GET_CDMA_MPC_SERVER_ADDR:
306            case RPC_LOC_IOCTL_GET_UMTS_SLP_SERVER_ADDR:
307                break;
308            case RPC_LOC_IOCTL_SET_ON_DEMAND_LPM:
309            case RPC_LOC_IOCTL_GET_ON_DEMAND_LPM:
310            case RPC_LOC_IOCTL_DELETE_ASSIST_DATA:
311            case RPC_LOC_IOCTL_SET_CUSTOM_PDE_SERVER_ADDR:
312            case RPC_LOC_IOCTL_GET_CUSTOM_PDE_SERVER_ADDR:
313            default:
314                break;
315        } /* switch */
316    } /* ioctl_data != NULL */
317
318    rpc_loc_ioctl_rets rets;
319    enum clnt_stat stat = RPC_SUCCESS;
320
321    stat = RPC_FUNC_VERSION(rpc_loc_ioctl_, /* LOC_APIVERS */ 0x00040001)(&args, &rets, loc_api_clnt);
322    LOC_GLUE_CHECK_RESULT(stat, int32);
323
324    return (int32) rets.loc_ioctl_result;
325}
326
327/* Returns 0 if error */
328int32 loc_api_null(void)
329{
330    LOC_GLUE_CHECK_INIT(int32);
331
332    int32 rets;
333    enum clnt_stat stat = RPC_SUCCESS;
334
335    stat = RPC_FUNC_VERSION(rpc_loc_api_null_, LOC_APIVERS)(NULL, &rets, loc_api_clnt);
336    LOC_GLUE_CHECK_RESULT(stat, int32);
337
338    return (int32) rets;
339}
340