コード例 #1
0
/*===========================================================================

FUNCTION    loc_sync_send_req

DESCRIPTION
   Synchronous req call (thread safe)

DEPENDENCIES
   N/A

RETURN VALUE
   Loc API 2.0 status

SIDE EFFECTS
   N/A

===========================================================================*/
locClientStatusEnumType loc_sync_send_req
(
      locClientHandleType       client_handle,
      uint32_t                  req_id,        /* req id */
      locClientReqUnionType     req_payload,
      uint32_t                  timeout_msec,
      uint32_t                  ind_id,  //ind ID to block for, usually the same as req_id */
      void                      *ind_payload_ptr /* can be NULL*/
)
{
   locClientStatusEnumType status = eLOC_CLIENT_SUCCESS ;
   int select_id;
   int rc = 0;

   // Select the callback we are waiting for
   select_id = loc_sync_select_ind(client_handle, ind_id, req_id,
                                   ind_payload_ptr);

   if (select_id >= 0)
   {
      status =  locClientSendReq (client_handle, req_id, req_payload);
      LOC_LOGV("%s:%d]: select_id = %d,locClientSendReq returned %d\n",
                    __func__, __LINE__, select_id, status);

      if (status != eLOC_CLIENT_SUCCESS )
      {
         loc_free_slot(select_id);
      }
      else
      {
         // Wait for the indication callback
         if (( rc = loc_sync_wait_for_ind( select_id,
                                           timeout_msec / 1000,
                                           ind_id) ) < 0)
         {
            if ( rc == -ETIMEDOUT)
               status = eLOC_CLIENT_FAILURE_TIMEOUT;
            else
               status = eLOC_CLIENT_FAILURE_INTERNAL;

            // Callback waiting failed
            LOC_LOGE("%s:%d]: loc_api_wait_for_ind failed, err %d, "
                     "select id %d, status %s", __func__, __LINE__, rc ,
                     select_id, loc_get_v02_client_status_name(status));
         }
         else
         {
            status =  eLOC_CLIENT_SUCCESS;
            LOC_LOGV("%s:%d]: success (select id %d)\n",
                          __func__, __LINE__, select_id);
         }
      }
   } /* select id */

   return status;
}
コード例 #2
0
/*===========================================================================

FUNCTION    loc_api_sync_ioctl

DESCRIPTION
   Synchronous IOCTL call (reentrant version)

DEPENDENCIES
   N/A

RETURN VALUE
   Loc API error code (0 = success)

SIDE EFFECTS
   N/A

===========================================================================*/
int loc_api_sync_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
)
{
   int                              rc = RPC_LOC_API_ENGINE_BUSY;
   int                              select_id;
   rpc_loc_ioctl_callback_s_type    callback_data;

   // Select the callback we are waiting for
   select_id = loc_api_select_callback(handle, 0, ioctl_type);

   if (select_id >= 0)
   {
      pthread_mutex_lock(&loc_sync_data.lock);
      rc = loc_ioctl(handle, ioctl_type, ioctl_data_ptr);
      while (rc == RPC_LOC_API_ENGINE_BUSY)
      {
         /* TODO: Use timeout? */
         ALOGD("loc_api_sync_ioctl: select_id = %d, engine busy, waiting...\n", select_id);
         pthread_cond_wait(&loc_sync_data.loc_cb_arrived_cond, &loc_sync_data.lock);
         rc = loc_ioctl(handle, ioctl_type, ioctl_data_ptr);
      }
      pthread_mutex_unlock(&loc_sync_data.lock);
      ALOGV("loc_api_sync_ioctl: select_id = %d, loc_ioctl returned %d\n", select_id, rc);

      if (rc != RPC_LOC_API_SUCCESS)
      {
         ALOGE("loc_api_sync_ioctl: select_id = %d, loc_ioctl returned %d\n", select_id, rc);
         loc_free_slot(select_id);
      }
      else {
         // Wait for the callback of loc_ioctl
         if ((rc = loc_api_wait_callback(select_id, timeout_msec / 1000, NULL, &callback_data)) != 0)
         {
            // Callback waiting failed
            ALOGE("loc_api_sync_ioctl: loc_api_wait_callback failed, returned %d (select id %d)\n", rc, select_id);
         }
         else
         {
            if (cb_data_ptr) memcpy(cb_data_ptr, &callback_data, sizeof *cb_data_ptr);
            if (callback_data.status != RPC_LOC_API_SUCCESS)
            {
               rc = callback_data.status;
               ALOGE("loc_api_sync_ioctl: IOCTL result failed, result: %d (select id %d)\n", rc, select_id);
            }
         } /* wait callback */
      } /* loc_ioctl */
   } /* select id */

   return rc;
}
コード例 #3
0
/*===========================================================================

FUNCTION    loc_sync_wait_for_ind

DESCRIPTION
   Waits for a selected indication. The wait expires in timeout_seconds seconds.
   If the function is called before an existing wait has finished, it will
   immediately return error.

DEPENDENCIES
   N/A

RETURN VALUE
  0 on SUCCESS, -ve value on failure

SIDE EFFECTS
   N/A

===========================================================================*/
static int loc_sync_wait_for_ind(
      int select_id,        /* ID from loc_sync_select_ind() */
      int timeout_seconds,  /* Timeout in this number of seconds  */
      uint32_t ind_id
)
{
   if (select_id < 0 || select_id >= LOC_SYNC_REQ_BUFFER_SIZE || !loc_sync_array.slot_in_use[select_id])
   {
      LOC_LOGE("%s:%d]: invalid select_id: %d \n",
                    __func__, __LINE__, select_id);

      return (-EINVAL);
   }

   loc_sync_req_data_s_type *slot = &loc_sync_array.slots[select_id];

   int ret_val = 0;  /* the return value of this function: 0 = no error */
   int rc;          /* return code from pthread calls */

   struct timeval present_time;
   struct timespec expire_time;

   pthread_mutex_lock(&slot->sync_req_lock);

  do
  {
      if (slot->ind_has_arrived)
      {
         ret_val = 0;    /* success */
         break;
      }

      if (slot->ind_is_waiting)
      {
         LOC_LOGW("%s:%d]: already waiting in this slot %d\n", __func__,
                       __LINE__, select_id);
         ret_val = -EBUSY; // busy
         break;
      }

      /* Calculate absolute expire time */
      gettimeofday(&present_time, NULL);
      expire_time.tv_sec  = present_time.tv_sec;
      expire_time.tv_nsec = present_time.tv_usec * 1000;
      expire_time.tv_sec += timeout_seconds;

      /* Take new wait request */
      slot->ind_is_waiting = true;

      /* Waiting */
      rc = pthread_cond_timedwait(&slot->ind_arrived_cond,
            &slot->sync_req_lock, &expire_time);

      slot->ind_is_waiting = false;

      if(rc == ETIMEDOUT)
      {
         LOC_LOGE("%s:%d]: slot %d, timed out for ind_id %s\n",
                    __func__, __LINE__, select_id, loc_get_v02_event_name(ind_id));
         ret_val = -ETIMEDOUT; //time out
      }

  } while (0);

   pthread_mutex_unlock(&slot->sync_req_lock);
   loc_free_slot(select_id);

   return ret_val;
}
コード例 #4
0
/*===========================================================================

FUNCTION    loc_api_wait_callback

DESCRIPTION
   Waits for a selected callback. The wait expires in timeout_seconds seconds.

   If the function is called before an existing wait has finished, it will
   immediately return EBUSY.

DEPENDENCIES
   N/A

RETURN VALUE
   RPC_LOC_API_SUCCESS              if successful (0)
   RPC_LOC_API_TIMEOUT              if timed out
   RPC_LOC_API_ENGINE_BUSY          if already in a wait
   RPC_LOC_API_INVALID_PARAMETER    if callback is not yet selected

SIDE EFFECTS
   N/A

===========================================================================*/
int loc_api_wait_callback(
      int select_id,        /* ID from loc_select_callback() */
      int timeout_seconds,  /* Timeout in this number of seconds  */
      rpc_loc_event_payload_u_type     *callback_payload,    /* Pointer to callback payload buffer, can be NULL */
      rpc_loc_ioctl_callback_s_type    *ioctl_payload        /* Pointer to IOCTL payload, can be NULL */
)
{
   if (select_id < 0 || select_id >= loc_sync_data.size || !loc_sync_data.slot_in_use[select_id])
   {
      ALOGE("loc_wait_callback: invalid select_id: %d", select_id);
      return RPC_LOC_API_INVALID_PARAMETER;
   }

   loc_sync_call_data_s_type *slot = &loc_sync_data.slots[select_id];

   int ret_val = RPC_LOC_API_SUCCESS;  /* the return value of this function: 0 = no error */
   int rc;                             /* return code from pthread calls */

   struct timeval present_time;
   struct timespec expire_time;

   pthread_mutex_lock(&slot->lock);

   if (slot->loc_cb_has_arrived)
   {
      loc_save_user_payload(callback_payload, ioctl_payload, &slot->loc_cb_received_payload);
      pthread_mutex_unlock(&slot->lock);
      loc_free_slot(select_id);
      ret_val = RPC_LOC_API_SUCCESS;
      return ret_val;    /* success */
   }

   if (slot->loc_cb_is_waiting)
   {
      pthread_mutex_unlock(&slot->lock);
      loc_free_slot(select_id);
      ret_val = RPC_LOC_API_ENGINE_BUSY; /* busy, rejected */
      ALOGE("loc_wait_callback: already waiting on select_id: %d\n", select_id);
      return ret_val;  /* exit */
   }

   /* Calculate absolute expire time */
   gettimeofday(&present_time, NULL);
   expire_time.tv_sec  = present_time.tv_sec;
   expire_time.tv_nsec = present_time.tv_usec * 1000;
   expire_time.tv_sec += timeout_seconds;

   /* Take new wait request */
   slot->loc_cb_is_waiting = TRUE;

   /* Waiting */
   rc = pthread_cond_timedwait(&slot->loc_cb_arrived_cond,
         &slot->lock, &expire_time);

   if (rc == ETIMEDOUT)
   {
      slot->loc_cb_is_waiting = FALSE;
      ret_val = RPC_LOC_API_TIMEOUT; /* Timed out */
   }
   else {
      /* Obtained the first awaited callback */
      slot->loc_cb_is_waiting = FALSE;     /* stop waiting */
      ret_val = RPC_LOC_API_SUCCESS;       /* Successful */
      loc_save_user_payload(callback_payload, ioctl_payload, &slot->loc_cb_received_payload);
   }

   pthread_mutex_unlock(&slot->lock);

   loc_free_slot(select_id);

   return ret_val;
}