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 ----------------------------------------------------------------------------- 12Copyright (c) 2009, QUALCOMM USA, INC. 13 14All rights reserved. 15 16Redistribution 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 24THIS 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 ALOGD 56// #define ALOGD(...) {} 57 58// Function declarations 59static boolean loc_eng_ioctl_setup_cb( 60 rpc_loc_client_handle_type handle, 61 rpc_loc_ioctl_e_type ioctl_type 62); 63 64static 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 71FUNCTION loc_eng_ioctl 72 73DESCRIPTION 74 This function calls loc_ioctl and waits for the callback result before 75 returning back to the user. 76 77DEPENDENCIES 78 N/A 79 80RETURN VALUE 81 TRUE if successful 82 FALSE if failed 83 84SIDE EFFECTS 85 N/A 86 87===========================================================================*/ 88boolean 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 ALOGV ("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 ALOGV ("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 138FUNCTION loc_eng_ioctl_setup_cb 139 140DESCRIPTION 141 Selects which callback is going to be waited for 142 143DEPENDENCIES 144 N/A 145 146RETURN VALUE 147 TRUE if successful 148 FALSE if failed 149 150SIDE EFFECTS 151 N/A 152 153===========================================================================*/ 154static 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 ALOGD ("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 187FUNCTION loc_eng_ioctl_wait_cb 188 189DESCRIPTION 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 195DEPENDENCIES 196 N/A 197 198RETURN VALUE 199 TRUE if successful 200 FALSE if failed 201 202SIDE EFFECTS 203 N/A 204 205===========================================================================*/ 206boolean 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 ALOGD ("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 ALOGD ("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 ALOGV ("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 ALOGV ("loc_eng_ioctl_wait_cb: returned %d\n", ret_val); 290 return ret_val; 291} 292 293/*=========================================================================== 294 295FUNCTION loc_eng_ioctl_process_cb 296 297DESCRIPTION 298 This function process the IOCTL callback, parameter specifies the client 299 that receives the IOCTL callback. 300 301DEPENDENCIES 302 N/A 303 304RETURN VALUE 305 TRUE if successful 306 FALSE if failed 307 308SIDE EFFECTS 309 N/A 310 311===========================================================================*/ 312boolean 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 ALOGD ("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 ALOGD ("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 ALOGV ("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