• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /******************************************************************************
3   @file:  loc_eng.cpp
4   @brief:
5 
6   DESCRIPTION
7     This file defines the implemenation for GPS hardware abstraction layer.
8 
9   INITIALIZATION AND SEQUENCING REQUIREMENTS
10 
11   -----------------------------------------------------------------------------
12 Copyright (c) 2009, QUALCOMM USA, INC.
13 
14 All rights reserved.
15 
16 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
17 
18 �         Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
19 
20 �         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.
21 
22 �         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.
23 
24 THIS 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.
25   -----------------------------------------------------------------------------
26 
27 ******************************************************************************/
28 
29 /*=====================================================================
30 $Header: $
31 $DateTime: $
32 $Author: $
33 ======================================================================*/
34 #define LOG_NDDEBUG 0
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <errno.h>
39 #include <unistd.h>
40 #include <ctype.h>
41 #include <math.h>
42 #include <pthread.h>
43 
44 #include <rpc/rpc.h>
45 #include <loc_api_rpc_glue.h>
46 
47 #include <hardware/gps.h>
48 
49 #include <loc_eng.h>
50 
51 #define LOG_TAG "lib_locapi"
52 #include <utils/Log.h>
53 
54 // comment this out to enable logging
55 // #undef LOGD
56 // #define LOGD(...) {}
57 
58 // Function declarations
59 static boolean loc_eng_ioctl_setup_cb(
60     rpc_loc_client_handle_type    handle,
61     rpc_loc_ioctl_e_type          ioctl_type
62 );
63 
64 static boolean loc_eng_ioctl_wait_cb(
65     int                            timeout_msec,  // Timeout in this number of msec
66     rpc_loc_ioctl_callback_s_type *cb_data_ptr    // Output parameter for IOCTL calls
67 );
68 
69 /*===========================================================================
70 
71 FUNCTION    loc_eng_ioctl
72 
73 DESCRIPTION
74    This function calls loc_ioctl and waits for the callback result before
75    returning back to the user.
76 
77 DEPENDENCIES
78    N/A
79 
80 RETURN VALUE
81    TRUE                 if successful
82    FALSE                if failed
83 
84 SIDE EFFECTS
85    N/A
86 
87 ===========================================================================*/
loc_eng_ioctl(rpc_loc_client_handle_type handle,rpc_loc_ioctl_e_type ioctl_type,rpc_loc_ioctl_data_u_type * ioctl_data_ptr,uint32 timeout_msec,rpc_loc_ioctl_callback_s_type * cb_data_ptr)88 boolean loc_eng_ioctl(
89     rpc_loc_client_handle_type           handle,
90     rpc_loc_ioctl_e_type                 ioctl_type,
91     rpc_loc_ioctl_data_u_type*           ioctl_data_ptr,
92     uint32                               timeout_msec,
93     rpc_loc_ioctl_callback_s_type       *cb_data_ptr
94     )
95 {
96     boolean                    ret_val;
97     int                        rpc_ret_val;
98     loc_eng_ioctl_data_s_type *ioctl_cb_data_ptr;
99 
100     LOGV ("loc_eng_ioctl: client = %d, ioctl_type = %d, cb_data =0x%x\n", (int32) handle, ioctl_type, (uint32) cb_data_ptr);
101 
102     ioctl_cb_data_ptr = &(loc_eng_data.ioctl_data);
103     // Select the callback we are waiting for
104     ret_val = loc_eng_ioctl_setup_cb (handle, ioctl_type);
105 
106     if (ret_val == TRUE)
107     {
108         rpc_ret_val =  loc_ioctl (handle,
109                                     ioctl_type,
110                                     ioctl_data_ptr);
111 
112         LOGV ("loc_eng_ioctl: loc_ioctl returned %d \n", rpc_ret_val);
113 
114         if (rpc_ret_val == RPC_LOC_API_SUCCESS)
115         {
116             // Wait for the callback of loc_ioctl
117             ret_val = loc_eng_ioctl_wait_cb (timeout_msec, cb_data_ptr);
118         }
119         else
120         {
121             ret_val = FALSE;
122         }
123     }
124 
125     // Reset the state when we are done
126     pthread_mutex_lock(&ioctl_cb_data_ptr->cb_data_mutex);
127     ioctl_cb_data_ptr->cb_is_selected = FALSE;
128     ioctl_cb_data_ptr->cb_is_waiting  = FALSE;
129     ioctl_cb_data_ptr->cb_has_arrived = FALSE;
130     pthread_mutex_unlock(&ioctl_cb_data_ptr->cb_data_mutex);
131 
132     return ret_val;
133 }
134 
135 
136 /*===========================================================================
137 
138 FUNCTION    loc_eng_ioctl_setup_cb
139 
140 DESCRIPTION
141    Selects which callback is going to be waited for
142 
143 DEPENDENCIES
144    N/A
145 
146 RETURN VALUE
147    TRUE                 if successful
148    FALSE                if failed
149 
150 SIDE EFFECTS
151    N/A
152 
153 ===========================================================================*/
loc_eng_ioctl_setup_cb(rpc_loc_client_handle_type handle,rpc_loc_ioctl_e_type ioctl_type)154 static boolean loc_eng_ioctl_setup_cb(
155     rpc_loc_client_handle_type    handle,
156     rpc_loc_ioctl_e_type          ioctl_type
157     )
158 {
159     boolean ret_val;
160     loc_eng_ioctl_data_s_type *ioctl_cb_data_ptr;
161 
162     ioctl_cb_data_ptr = &(loc_eng_data.ioctl_data);
163 
164     pthread_mutex_lock(&ioctl_cb_data_ptr->cb_data_mutex);
165     if (ioctl_cb_data_ptr->cb_is_selected == TRUE)
166     {
167         LOGD ("loc_eng_ioctl_setup_cb: ERROR, another ioctl in progress \n");
168         ret_val = FALSE;
169     }
170     else
171     {
172         ioctl_cb_data_ptr->cb_is_selected = TRUE;
173         ioctl_cb_data_ptr->cb_is_waiting  = FALSE;
174         ioctl_cb_data_ptr->cb_has_arrived = FALSE;
175         ioctl_cb_data_ptr->client_handle  = handle;
176         ioctl_cb_data_ptr->ioctl_type     = ioctl_type;
177         memset (&(ioctl_cb_data_ptr->cb_payload), 0, sizeof (rpc_loc_ioctl_callback_s_type));
178         ret_val = TRUE;
179     }
180     pthread_mutex_unlock(&ioctl_cb_data_ptr->cb_data_mutex);
181 
182     return ret_val;
183 }
184 
185 /*===========================================================================
186 
187 FUNCTION    loc_eng_ioctl_wait_cb
188 
189 DESCRIPTION
190    Waits for a selected callback. The wait expires in timeout_msec.
191 
192    If the function is called before an existing wait has finished, it will
193    immediately return EBUSY.
194 
195 DEPENDENCIES
196    N/A
197 
198 RETURN VALUE
199    TRUE                 if successful
200    FALSE                if failed
201 
202 SIDE EFFECTS
203    N/A
204 
205 ===========================================================================*/
loc_eng_ioctl_wait_cb(int timeout_msec,rpc_loc_ioctl_callback_s_type * cb_data_ptr)206 boolean loc_eng_ioctl_wait_cb(
207     int                            timeout_msec,  // Timeout in this number of msec
208     rpc_loc_ioctl_callback_s_type *cb_data_ptr
209     )
210 {
211     boolean ret_val = FALSE; // the return value of this function
212     int rc;                  // return code from pthread calls
213 
214     struct timeval present_time;
215     struct timespec expire_time;
216     loc_eng_ioctl_data_s_type *ioctl_cb_data_ptr;
217 
218     ioctl_cb_data_ptr = &(loc_eng_data.ioctl_data);
219 
220     pthread_mutex_lock(&ioctl_cb_data_ptr->cb_data_mutex);
221 
222     do {
223         if (ioctl_cb_data_ptr->cb_is_selected == FALSE)
224         {
225             LOGD ("loc_eng_ioctl_wait_cb: ERROR called when cb_is_waiting is set to FALSE \n");
226             ret_val = FALSE;
227             break;
228         }
229 
230         // Calculate absolute expire time
231         gettimeofday(&present_time, NULL);
232         expire_time.tv_sec  = present_time.tv_sec;
233         expire_time.tv_sec  +=  timeout_msec / 1000;
234         if ((present_time.tv_usec + timeout_msec) >= 1000)
235         {
236             expire_time.tv_sec += 1;
237         }
238         expire_time.tv_nsec = (present_time.tv_usec + timeout_msec) % 1000 * 1000;
239 
240         // Special case where callback is issued before loc_ioctl ever returns
241         if (ioctl_cb_data_ptr->cb_has_arrived == TRUE)
242         {
243             LOGD ("loc_eng_ioctl_wait_cb: cb has arrived without waiting \n");
244             ret_val = TRUE;
245             break;
246         }
247 
248         ioctl_cb_data_ptr->cb_is_waiting = TRUE;
249         // Wait for the callback until timeout expires
250         rc = pthread_cond_timedwait(&ioctl_cb_data_ptr->cb_arrived_cond,
251                                     &ioctl_cb_data_ptr->cb_data_mutex,
252                                     &expire_time);
253 
254         if (rc == 0)
255         {
256             ret_val = TRUE;
257         }
258         else
259         {
260             ret_val = FALSE;
261         }
262 
263         LOGV ("loc_eng_ioctl_wait_cb: pthread_cond_timedwait returned %d\n", rc);
264 
265     } while (0);
266 
267     // Process the ioctl callback data when IOCTL is successful
268     if (ret_val == TRUE)
269     {
270         ioctl_cb_data_ptr = &(loc_eng_data.ioctl_data);
271         if (ioctl_cb_data_ptr->cb_payload.status == RPC_LOC_API_SUCCESS)
272         {
273             ret_val = TRUE;
274             if (cb_data_ptr != NULL)
275             {
276                 memcpy (cb_data_ptr,
277                         &(ioctl_cb_data_ptr->cb_payload),
278                         sizeof (rpc_loc_ioctl_callback_s_type));
279             }
280         }
281         else
282         {
283             ret_val = FALSE;
284         }
285     }
286 
287     pthread_mutex_unlock(&ioctl_cb_data_ptr->cb_data_mutex);
288 
289     LOGV ("loc_eng_ioctl_wait_cb: returned %d\n", ret_val);
290     return ret_val;
291 }
292 
293 /*===========================================================================
294 
295 FUNCTION    loc_eng_ioctl_process_cb
296 
297 DESCRIPTION
298    This function process the IOCTL callback, parameter specifies the client
299    that receives the IOCTL callback.
300 
301 DEPENDENCIES
302    N/A
303 
304 RETURN VALUE
305    TRUE                 if successful
306    FALSE                if failed
307 
308 SIDE EFFECTS
309    N/A
310 
311 ===========================================================================*/
loc_eng_ioctl_process_cb(rpc_loc_client_handle_type client_handle,const rpc_loc_ioctl_callback_s_type * cb_data_ptr)312 boolean loc_eng_ioctl_process_cb (
313     rpc_loc_client_handle_type           client_handle,
314     const rpc_loc_ioctl_callback_s_type *cb_data_ptr
315     )
316 {
317     boolean ret_val = FALSE; // the return value of this function
318     loc_eng_ioctl_data_s_type *ioctl_cb_data_ptr;
319     ioctl_cb_data_ptr = &(loc_eng_data.ioctl_data);
320 
321     pthread_mutex_lock(&ioctl_cb_data_ptr->cb_data_mutex);
322     if (client_handle != ioctl_cb_data_ptr->client_handle)
323     {
324         LOGD ("loc_eng_ioctl_process_cb: client handle mismatch, received = %d, expected = %d \n",
325                 (int32) client_handle, (int32) ioctl_cb_data_ptr->client_handle);
326         ret_val = FALSE;
327     }
328     else if (cb_data_ptr->type != ioctl_cb_data_ptr->ioctl_type)
329     {
330         LOGD ("loc_eng_ioctl_process_cb: ioctl type mismatch, received = %d, expected = %d \n",
331                  cb_data_ptr->type, ioctl_cb_data_ptr->ioctl_type);
332         ret_val = FALSE;
333     }
334     else // both matches
335     {
336         memcpy (&(ioctl_cb_data_ptr->cb_payload),
337                 cb_data_ptr,
338                 sizeof (rpc_loc_ioctl_callback_s_type));
339 
340         ioctl_cb_data_ptr->cb_has_arrived = TRUE;
341 
342         LOGV ("loc_eng_ioctl_process_cb: callback arrived for client = %d, ioctl = %d, status = %d\n",
343                 (int32) ioctl_cb_data_ptr->client_handle, ioctl_cb_data_ptr->ioctl_type,
344                 (int32) ioctl_cb_data_ptr->cb_payload.status);
345 
346         ret_val = TRUE;
347     }
348 
349     pthread_mutex_unlock(&ioctl_cb_data_ptr->cb_data_mutex);
350 
351     // Signal the waiting thread that callback has arrived
352     if (ret_val == TRUE)
353     {
354         pthread_cond_signal (&ioctl_cb_data_ptr->cb_arrived_cond);
355     }
356 
357     return ret_val;
358 }
359