Home | History | Annotate | Download | only in libloc_api
      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 ===========================================================================*/
     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 ===========================================================================*/
    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 ===========================================================================*/
    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 ===========================================================================*/
    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