Add support for SUPL Emergency Services
Introduced support for handling modem request to start an emergency call using QMI WDS profiles or fallback to an ATL request if the call does not succeed. Change-Id: I29b617687db0d3f26610bc74f8dc95940574f52d
This commit is contained in:
parent
711863f2f3
commit
0f66892e50
16 changed files with 1576 additions and 88 deletions
|
@ -27,6 +27,7 @@ endif
|
|||
|
||||
ifeq ($(call is-board-platform-in-list,$(QMI_BOARD_PLATFORM_LIST)),true)
|
||||
GPS_DIR_LIST += $(LOCAL_PATH)/loc_api_v02/
|
||||
GPS_DIR_LIST += $(LOCAL_PATH)/ds_api/
|
||||
endif #is-board-platform-in-list
|
||||
|
||||
GPS_DIR_LIST += $(LOCAL_PATH)/libloc_api_50001/
|
||||
|
|
49
loc_api/ds_api/Android.mk
Normal file
49
loc_api/ds_api/Android.mk
Normal file
|
@ -0,0 +1,49 @@
|
|||
ifneq ($(BUILD_TINY_ANDROID),true)
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := libds_api
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libutils \
|
||||
libcutils \
|
||||
libqmi_cci \
|
||||
libqmi_csi \
|
||||
libqmi_common_so \
|
||||
libgps.utils \
|
||||
libdsi_netctrl \
|
||||
libqmiservices
|
||||
|
||||
|
||||
LOCAL_SRC_FILES += \
|
||||
ds_client.c
|
||||
|
||||
LOCAL_CFLAGS += \
|
||||
-fno-short-enums \
|
||||
-D_ANDROID_
|
||||
|
||||
LOCAL_COPY_HEADERS_TO:= ds_api/
|
||||
|
||||
LOCAL_COPY_HEADERS:= \
|
||||
ds_client.h
|
||||
|
||||
LOCAL_LDFLAGS += -Wl,--export-dynamic
|
||||
|
||||
## Includes
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(TARGET_OUT_HEADERS)/libloc_eng \
|
||||
$(TARGET_OUT_HEADERS)/qmi-framework/inc \
|
||||
$(TARGET_OUT_HEADERS)/qmi/inc \
|
||||
$(TARGET_OUT_HEADERS)/gps.utils \
|
||||
$(TARGET_OUT_HEADERS)/data/inc
|
||||
|
||||
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
endif # not BUILD_TINY_ANDROID
|
704
loc_api/ds_api/ds_client.c
Normal file
704
loc_api/ds_api/ds_client.c
Normal file
|
@ -0,0 +1,704 @@
|
|||
/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * 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.
|
||||
* * Neither the name of The Linux Foundation, nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#define LOG_NDEBUG 0
|
||||
#define LOG_TAG "LocSvc_ds_client"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <wireless_data_service_v01.h>
|
||||
#include <utils/Log.h>
|
||||
#include <log_util.h>
|
||||
#include <loc_log.h>
|
||||
#include <qmi_client.h>
|
||||
#include <qmi_idl_lib.h>
|
||||
#include <qmi_cci_target_ext.h>
|
||||
#include <qmi_cci_target.h>
|
||||
#include <qmi_cci_common.h>
|
||||
#include <dsi_netctrl.h>
|
||||
#include <ds_client.h>
|
||||
|
||||
#include<sys/time.h>
|
||||
|
||||
//Timeout to wait for wds service notification from qmi
|
||||
#define DS_CLIENT_SERVICE_TIMEOUT (4000)
|
||||
//Max timeout for the service to come up
|
||||
#define DS_CLIENT_SERVICE_TIMEOUT_TOTAL (40000)
|
||||
//Timeout for the service to respond to sync msg
|
||||
#define DS_CLIENT_SYNC_MSG_TIMEOUT (5000)
|
||||
/*Request messages the WDS client can send to the WDS service*/
|
||||
typedef union
|
||||
{
|
||||
/*Requests the service for a list of all profiles present*/
|
||||
wds_get_profile_list_req_msg_v01 *p_get_profile_list_req;
|
||||
/*Requests the service for a profile's settings*/
|
||||
wds_get_profile_settings_req_msg_v01 *p_get_profile_settings_req;
|
||||
}ds_client_req_union_type;
|
||||
|
||||
/*Response indications that are sent by the WDS service*/
|
||||
typedef union
|
||||
{
|
||||
wds_get_profile_list_resp_msg_v01 *p_get_profile_list_resp;
|
||||
wds_get_profile_settings_resp_msg_v01 *p_get_profile_setting_resp;
|
||||
}ds_client_resp_union_type;
|
||||
|
||||
struct event_strings_s
|
||||
{
|
||||
char * str;
|
||||
dsi_net_evt_t evt;
|
||||
};
|
||||
|
||||
struct event_strings_s event_string_tbl[DSI_EVT_MAX] =
|
||||
{
|
||||
NAME_VAL(DSI_EVT_INVALID),
|
||||
NAME_VAL(DSI_EVT_NET_IS_CONN),
|
||||
NAME_VAL(DSI_EVT_NET_NO_NET),
|
||||
NAME_VAL(DSI_EVT_PHYSLINK_DOWN_STATE),
|
||||
NAME_VAL(DSI_EVT_PHYSLINK_UP_STATE),
|
||||
NAME_VAL(DSI_EVT_NET_RECONFIGURED),
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ds_client_event_ind_cb_type event_cb;
|
||||
void *caller_cookie;
|
||||
}ds_caller_data;
|
||||
|
||||
typedef struct {
|
||||
//Global dsi handle
|
||||
dsi_hndl_t dsi_net_handle;
|
||||
//Handle to caller's data
|
||||
ds_caller_data caller_data;
|
||||
} ds_client_session_data;
|
||||
|
||||
void net_ev_cb(dsi_hndl_t handle, void* user_data,
|
||||
dsi_net_evt_t evt, dsi_evt_payload_t *payload_ptr)
|
||||
{
|
||||
int i;
|
||||
(void)handle;
|
||||
(void)user_data;
|
||||
(void)payload_ptr;
|
||||
ds_caller_data *callback_data = (ds_caller_data *)user_data;
|
||||
|
||||
LOC_LOGD("%s:%d]:Enter\n", __func__, __LINE__);
|
||||
|
||||
if(evt > DSI_EVT_INVALID && evt < DSI_EVT_MAX)
|
||||
{
|
||||
for(i=0;i<DSI_EVT_MAX;i++)
|
||||
{
|
||||
if(event_string_tbl[i].evt == evt)
|
||||
LOC_LOGE("%s:%d]: Callback received: %s",
|
||||
__func__, __LINE__, event_string_tbl[i].str);
|
||||
}
|
||||
switch(evt) {
|
||||
case DSI_EVT_NET_IS_CONN:
|
||||
{
|
||||
LOC_LOGD("%s:%d]: Emergency call started\n", __func__, __LINE__);
|
||||
callback_data->event_cb(E_DS_CLIENT_DATA_CALL_CONNECTED,
|
||||
callback_data->caller_cookie);
|
||||
break;
|
||||
}
|
||||
case DSI_EVT_NET_NO_NET:
|
||||
{
|
||||
LOC_LOGD("%s:%d]: Emergency call stopped\n", __func__, __LINE__);
|
||||
callback_data->event_cb(E_DS_CLIENT_DATA_CALL_DISCONNECTED,
|
||||
callback_data->caller_cookie);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOC_LOGD("%s:%d]: uninteresting event\n", __func__, __LINE__);
|
||||
}
|
||||
}
|
||||
LOC_LOGD("%s:%d]:Exit\n", __func__, __LINE__);
|
||||
}
|
||||
|
||||
/*This function is called to obtain a handle to the QMI WDS service*/
|
||||
static ds_client_status_enum_type
|
||||
ds_client_qmi_ctrl_point_init(qmi_client_type *p_wds_qmi_client)
|
||||
{
|
||||
qmi_client_type wds_qmi_client, notifier = NULL;
|
||||
ds_client_status_enum_type status = E_DS_CLIENT_SUCCESS;
|
||||
qmi_service_info *p_service_info = NULL;
|
||||
uint32_t num_services = 0, num_entries = 0;
|
||||
qmi_client_error_type ret = QMI_NO_ERR;
|
||||
unsigned char no_signal = 0;
|
||||
qmi_client_os_params os_params;
|
||||
int timeout = 0;
|
||||
|
||||
LOC_LOGD("%s:%d]:Enter\n", __func__, __LINE__);
|
||||
|
||||
//Get service object for QMI_WDS service
|
||||
qmi_idl_service_object_type ds_client_service_object =
|
||||
wds_get_service_object_v01();
|
||||
if(ds_client_service_object == NULL) {
|
||||
LOC_LOGE("%s:%d]: wds_get_service_object_v01 failed\n" ,
|
||||
__func__, __LINE__);
|
||||
status = E_DS_CLIENT_FAILURE_INTERNAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
//get service addressing information
|
||||
ret = qmi_client_get_service_list(ds_client_service_object, NULL, NULL,
|
||||
&num_services);
|
||||
LOC_LOGD("%s:%d]: qmi_client_get_service_list() first try ret %d, "
|
||||
"num_services %d]\n", __func__, __LINE__, ret, num_services);
|
||||
if(ret != QMI_NO_ERR) {
|
||||
//Register for service notification
|
||||
ret = qmi_client_notifier_init(ds_client_service_object, &os_params, ¬ifier);
|
||||
if (ret != QMI_NO_ERR) {
|
||||
LOC_LOGE("%s:%d]: qmi_client_notifier_init failed %d\n",
|
||||
__func__, __LINE__, ret);
|
||||
status = E_DS_CLIENT_FAILURE_INTERNAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
do {
|
||||
QMI_CCI_OS_SIGNAL_CLEAR(&os_params);
|
||||
ret = qmi_client_get_service_list(ds_client_service_object, NULL,
|
||||
NULL, &num_services);
|
||||
if(ret != QMI_NO_ERR) {
|
||||
QMI_CCI_OS_SIGNAL_WAIT(&os_params, DS_CLIENT_SERVICE_TIMEOUT);
|
||||
no_signal = QMI_CCI_OS_SIGNAL_TIMED_OUT(&os_params);
|
||||
if(!no_signal)
|
||||
ret = qmi_client_get_service_list(ds_client_service_object, NULL,
|
||||
NULL, &num_services);
|
||||
}
|
||||
timeout += DS_CLIENT_SERVICE_TIMEOUT;
|
||||
LOC_LOGV("%s:%d]: qmi_client_get_service_list() returned ret: %d,"
|
||||
"no_signal: %d, total timeout: %d\n", __func__, __LINE__,
|
||||
ret, no_signal, timeout);
|
||||
} while( (timeout < DS_CLIENT_SERVICE_TIMEOUT_TOTAL) &&
|
||||
no_signal &&
|
||||
(ret != QMI_NO_ERR) );
|
||||
}
|
||||
|
||||
//Handle failure cases
|
||||
if(num_services == 0 || ret != QMI_NO_ERR) {
|
||||
if(!no_signal) {
|
||||
LOC_LOGE("%s:%d]: qmi_client_get_service_list failed even though"
|
||||
"service is up! Error: %d \n", __func__, __LINE__, ret);
|
||||
status = E_DS_CLIENT_FAILURE_INTERNAL;
|
||||
}
|
||||
else {
|
||||
LOC_LOGE("%s:%d]: qmi_client_get_service_list failed after retries"
|
||||
"Error: %d \n", __func__, __LINE__, ret);
|
||||
status = E_DS_CLIENT_FAILURE_TIMEOUT;
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
LOC_LOGD("%s:%d]: qmi_client_get_service_list succeeded\n", __func__, __LINE__);
|
||||
|
||||
//Success
|
||||
p_service_info = (qmi_service_info *)malloc(num_services * sizeof(qmi_service_info));
|
||||
if(p_service_info == NULL) {
|
||||
LOC_LOGE("%s:%d]: could not allocate memory for serviceInfo !!\n",
|
||||
__func__, __LINE__);
|
||||
status = E_DS_CLIENT_FAILURE_INTERNAL;
|
||||
goto err;
|
||||
}
|
||||
num_entries = num_services;
|
||||
|
||||
//Populate service info
|
||||
ret = qmi_client_get_service_list(ds_client_service_object, p_service_info,
|
||||
&num_entries, &num_services);
|
||||
if(ret != QMI_NO_ERR) {
|
||||
LOC_LOGE("%s:%d]: qmi_client_get_service_list failed. ret: %d \n",
|
||||
__func__, __LINE__, ret);
|
||||
status = E_DS_CLIENT_FAILURE_INTERNAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
//Initialize wds_qmi_client
|
||||
LOC_LOGD("%s:%d]: Initializing WDS client with qmi_client_init\n", __func__,
|
||||
__LINE__);
|
||||
ret = qmi_client_init(&p_service_info[0], ds_client_service_object,
|
||||
NULL, NULL, NULL, &wds_qmi_client);
|
||||
if(ret != QMI_NO_ERR) {
|
||||
LOC_LOGE("%s:%d]: qmi_client_init Error. ret: %d\n", __func__, __LINE__, ret);
|
||||
status = E_DS_CLIENT_FAILURE_INTERNAL;
|
||||
goto err;
|
||||
}
|
||||
LOC_LOGD("%s:%d]: WDS client initialized with qmi_client_init\n", __func__,
|
||||
__LINE__);
|
||||
|
||||
//Store WDS QMI client handle in the parameter passed in
|
||||
*p_wds_qmi_client = wds_qmi_client;
|
||||
|
||||
status = E_DS_CLIENT_SUCCESS;
|
||||
LOC_LOGD("%s:%d]: init success\n", __func__, __LINE__);
|
||||
|
||||
if(notifier)
|
||||
qmi_client_release(notifier);
|
||||
|
||||
err:
|
||||
if(p_service_info)
|
||||
free(p_service_info);
|
||||
|
||||
LOC_LOGD("%s:%d]:Exit\n", __func__, __LINE__);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*This function reads the error code from within the response struct*/
|
||||
static ds_client_status_enum_type ds_client_convert_qmi_response(
|
||||
uint32_t req_id,
|
||||
ds_client_resp_union_type *resp_union)
|
||||
{
|
||||
ds_client_status_enum_type ret = E_DS_CLIENT_FAILURE_GENERAL;
|
||||
LOC_LOGD("%s:%d]:Enter\n", __func__, __LINE__);
|
||||
switch(req_id)
|
||||
{
|
||||
case QMI_WDS_GET_PROFILE_LIST_REQ_V01 :
|
||||
{
|
||||
if(resp_union->p_get_profile_list_resp->resp.error !=
|
||||
QMI_ERR_NONE_V01) {
|
||||
LOC_LOGE("%s:%d]: Response error: %d", __func__, __LINE__,
|
||||
resp_union->p_get_profile_list_resp->resp.error);
|
||||
}
|
||||
else
|
||||
ret = E_DS_CLIENT_SUCCESS;
|
||||
}
|
||||
break;
|
||||
|
||||
case QMI_WDS_GET_PROFILE_SETTINGS_REQ_V01 :
|
||||
{
|
||||
if(resp_union->p_get_profile_setting_resp->resp.error !=
|
||||
QMI_ERR_NONE_V01) {
|
||||
LOC_LOGE("%s:%d]: Response error: %d", __func__, __LINE__,
|
||||
resp_union->p_get_profile_setting_resp->resp.error);
|
||||
}
|
||||
else
|
||||
ret = E_DS_CLIENT_SUCCESS;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LOC_LOGE("%s:%d]: Unknown request ID\n", __func__, __LINE__);
|
||||
}
|
||||
LOC_LOGD("%s:%d]:Exit\n", __func__, __LINE__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static ds_client_status_enum_type ds_client_send_qmi_sync_req(
|
||||
qmi_client_type *ds_client_handle,
|
||||
uint32_t req_id,
|
||||
ds_client_resp_union_type *resp_union,
|
||||
ds_client_req_union_type *req_union)
|
||||
{
|
||||
uint32_t req_len = 0;
|
||||
uint32_t resp_len = 0;
|
||||
ds_client_status_enum_type ret = E_DS_CLIENT_SUCCESS;
|
||||
qmi_client_error_type qmi_ret = QMI_NO_ERR;
|
||||
LOC_LOGD("%s:%d]:Enter\n", __func__, __LINE__);
|
||||
switch(req_id)
|
||||
{
|
||||
case QMI_WDS_GET_PROFILE_LIST_REQ_V01 :
|
||||
{
|
||||
req_len = sizeof(wds_get_profile_list_req_msg_v01);
|
||||
resp_len = sizeof(wds_get_profile_list_resp_msg_v01);
|
||||
LOC_LOGD("%s:%d]: req_id = GET_PROFILE_LIST_REQ\n",
|
||||
__func__, __LINE__);
|
||||
}
|
||||
break;
|
||||
|
||||
case QMI_WDS_GET_PROFILE_SETTINGS_REQ_V01 :
|
||||
{
|
||||
req_len = sizeof(wds_get_profile_settings_req_msg_v01);
|
||||
resp_len = sizeof(wds_get_profile_settings_resp_msg_v01);
|
||||
LOC_LOGD("%s:%d]: req_id = GET_PROFILE_SETTINGS_REQ\n",
|
||||
__func__, __LINE__);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LOC_LOGE("%s:%d]: Error unknown req_id=%d\n", __func__, __LINE__,
|
||||
req_id);
|
||||
ret = E_DS_CLIENT_FAILURE_INVALID_PARAMETER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
LOC_LOGD("%s:%d]: req_id=%d, len = %d; resp_len= %d\n", __func__, __LINE__,
|
||||
req_id, req_len, resp_len);
|
||||
//Send msg through QCCI
|
||||
qmi_ret = qmi_client_send_msg_sync(
|
||||
*ds_client_handle,
|
||||
req_id,
|
||||
(void *)req_union->p_get_profile_list_req,
|
||||
req_len,
|
||||
(void *)resp_union->p_get_profile_list_resp,
|
||||
resp_len,
|
||||
DS_CLIENT_SYNC_MSG_TIMEOUT);
|
||||
LOC_LOGD("%s:%d]: qmi_client_send_msg_sync returned: %d", __func__, __LINE__, qmi_ret);
|
||||
|
||||
if(qmi_ret != QMI_NO_ERR) {
|
||||
ret = E_DS_CLIENT_FAILURE_INTERNAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = ds_client_convert_qmi_response(req_id, resp_union);
|
||||
|
||||
err:
|
||||
LOC_LOGD("%s:%d]:Exit\n", __func__, __LINE__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*This function obtains the list of supported profiles*/
|
||||
static ds_client_status_enum_type ds_client_get_profile_list(
|
||||
qmi_client_type *ds_client_handle,
|
||||
ds_client_resp_union_type *profile_list_resp_msg,
|
||||
wds_profile_type_enum_v01 profile_type)
|
||||
{
|
||||
ds_client_status_enum_type ret = E_DS_CLIENT_SUCCESS;
|
||||
ds_client_req_union_type req_union;
|
||||
LOC_LOGD("%s:%d]:Enter\n", __func__, __LINE__);
|
||||
|
||||
req_union.p_get_profile_list_req = NULL;
|
||||
req_union.p_get_profile_list_req = (wds_get_profile_list_req_msg_v01 *)
|
||||
calloc(1, sizeof(wds_get_profile_list_req_msg_v01));
|
||||
if(req_union.p_get_profile_list_req == NULL) {
|
||||
LOC_LOGE("%s:%d]: Could not allocate memory for"
|
||||
"wds_get_profile_list_req_msg_v01\n", __func__, __LINE__);
|
||||
goto err;
|
||||
}
|
||||
//Populate required members of the request structure
|
||||
req_union.p_get_profile_list_req->profile_type_valid = 1;
|
||||
req_union.p_get_profile_list_req->profile_type = profile_type;
|
||||
ret = ds_client_send_qmi_sync_req(ds_client_handle,
|
||||
QMI_WDS_GET_PROFILE_LIST_REQ_V01,
|
||||
profile_list_resp_msg, &req_union);
|
||||
if(ret != E_DS_CLIENT_SUCCESS) {
|
||||
LOC_LOGE("%s:%d]: ds_client_send_qmi_req failed. ret: %d\n",
|
||||
__func__, __LINE__, ret);
|
||||
goto err;
|
||||
}
|
||||
err:
|
||||
LOC_LOGD("%s:%d]:Exit\n", __func__, __LINE__);
|
||||
if(req_union.p_get_profile_list_req)
|
||||
free(req_union.p_get_profile_list_req);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*This function obtains settings for the profile specified by
|
||||
the profile_identifier*/
|
||||
static ds_client_status_enum_type ds_client_get_profile_settings(
|
||||
qmi_client_type *ds_client_handle,
|
||||
ds_client_resp_union_type *profile_settings_resp_msg,
|
||||
wds_profile_identifier_type_v01 *profile_identifier)
|
||||
{
|
||||
ds_client_status_enum_type ret = E_DS_CLIENT_SUCCESS;
|
||||
ds_client_req_union_type req_union;
|
||||
|
||||
LOC_LOGD("%s:%d]:Enter\n", __func__, __LINE__);
|
||||
//Since it's a union containing a pointer to a structure,
|
||||
//following entities have the same address
|
||||
//- req_union
|
||||
//- req_union.p_get_profile_settings_req
|
||||
//- req_union.p_get_profile_settings_req->profile
|
||||
//so we can very well assign req_union = profile_identifier
|
||||
req_union.p_get_profile_settings_req =
|
||||
(wds_get_profile_settings_req_msg_v01 *)profile_identifier;
|
||||
ret = ds_client_send_qmi_sync_req(ds_client_handle,
|
||||
QMI_WDS_GET_PROFILE_SETTINGS_REQ_V01,
|
||||
profile_settings_resp_msg, &req_union);
|
||||
if(ret != E_DS_CLIENT_SUCCESS) {
|
||||
LOC_LOGE("%s:%d]: ds_client_send_qmi_req failed. ret: %d\n",
|
||||
__func__, __LINE__, ret);
|
||||
goto err;
|
||||
}
|
||||
err:
|
||||
LOC_LOGD("%s:%d]:Exit\n", __func__, __LINE__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
Starts data call using the handle and the profile index
|
||||
*/
|
||||
ds_client_status_enum_type
|
||||
ds_client_start_call(dsClientHandleType client_handle, int profile_index)
|
||||
{
|
||||
ds_client_status_enum_type ret = E_DS_CLIENT_FAILURE_GENERAL;
|
||||
dsi_call_param_value_t param_info;
|
||||
dsi_hndl_t dsi_handle;
|
||||
ds_client_session_data *ds_global_data = (ds_client_session_data *)client_handle;
|
||||
LOC_LOGD("%s:%d]:Enter\n", __func__, __LINE__);
|
||||
if(ds_global_data == NULL) {
|
||||
LOC_LOGE("%s:%d]: Null callback parameter\n", __func__, __LINE__);
|
||||
goto err;
|
||||
}
|
||||
dsi_handle = ds_global_data->dsi_net_handle;
|
||||
//Set profile index as call parameter
|
||||
param_info.buf_val = NULL;
|
||||
param_info.num_val = profile_index;
|
||||
dsi_set_data_call_param(dsi_handle,
|
||||
DSI_CALL_INFO_UMTS_PROFILE_IDX,
|
||||
¶m_info);
|
||||
LOC_LOGD("%s:%d]: Starting emergency call with profile index %d\n",
|
||||
__func__, __LINE__, param_info.num_val);
|
||||
if(dsi_start_data_call(dsi_handle) == DSI_SUCCESS) {
|
||||
LOC_LOGD("%s:%d]: Sent request to start data call\n",
|
||||
__func__, __LINE__);
|
||||
ret = E_DS_CLIENT_SUCCESS;
|
||||
}
|
||||
else {
|
||||
LOC_LOGE("%s:%d]: Could not send req to start data call \n", __func__, __LINE__);
|
||||
ret = E_DS_CLIENT_FAILURE_GENERAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
err:
|
||||
LOC_LOGD("%s:%d]:Exit\n", __func__, __LINE__);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/*Function to open an emergency call. Does the following things:
|
||||
- Obtains a handle to the WDS service
|
||||
- Obtains a list of profiles configured in the modem
|
||||
- Queries each profile and obtains settings to check if emergency calls
|
||||
are supported
|
||||
- Returns the profile index that supports emergency calls
|
||||
- Returns handle to dsi_netctrl*/
|
||||
ds_client_status_enum_type
|
||||
ds_client_open_call(dsClientHandleType *client_handle,
|
||||
ds_client_cb_data *callback,
|
||||
void *caller_cookie,
|
||||
int *profile_index)
|
||||
{
|
||||
ds_client_status_enum_type ret = E_DS_CLIENT_FAILURE_GENERAL;
|
||||
ds_client_resp_union_type profile_list_resp_msg;
|
||||
ds_client_resp_union_type profile_settings_resp_msg;
|
||||
wds_profile_identifier_type_v01 profile_identifier;
|
||||
uint32_t i=0;
|
||||
dsi_hndl_t dsi_handle;
|
||||
ds_client_session_data **ds_global_data = (ds_client_session_data **)client_handle;
|
||||
unsigned char call_profile_index_found = 0;
|
||||
uint32_t emergency_profile_index=0;
|
||||
qmi_client_type wds_qmi_client;
|
||||
|
||||
profile_list_resp_msg.p_get_profile_list_resp = NULL;
|
||||
profile_settings_resp_msg.p_get_profile_setting_resp = NULL;
|
||||
|
||||
LOC_LOGD("%s:%d]:Enter\n", __func__, __LINE__);
|
||||
if(callback == NULL || ds_global_data == NULL) {
|
||||
LOC_LOGE("%s:%d]: Null callback parameter\n", __func__, __LINE__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = ds_client_qmi_ctrl_point_init(&wds_qmi_client);
|
||||
if(ret != E_DS_CLIENT_SUCCESS) {
|
||||
LOC_LOGE("%s:%d]: ds_client_qmi_ctrl_point_init failed. ret: %d\n",
|
||||
__func__, __LINE__, ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
//Allocate memory for the response msg to obtain a list of profiles
|
||||
profile_list_resp_msg.p_get_profile_list_resp = (wds_get_profile_list_resp_msg_v01 *)
|
||||
calloc(1, sizeof(wds_get_profile_list_resp_msg_v01));
|
||||
if(profile_list_resp_msg.p_get_profile_list_resp == NULL) {
|
||||
LOC_LOGE("%s:%d]: Could not allocate memory for"
|
||||
"p_get_profile_list_resp\n", __func__, __LINE__);
|
||||
ret = E_DS_CLIENT_FAILURE_NOT_ENOUGH_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
LOC_LOGD("%s:%d]: Getting profile list\n", __func__, __LINE__);
|
||||
ret = ds_client_get_profile_list(&wds_qmi_client,
|
||||
&profile_list_resp_msg,
|
||||
WDS_PROFILE_TYPE_3GPP_V01);
|
||||
if(ret != E_DS_CLIENT_SUCCESS) {
|
||||
LOC_LOGE("%s:%d]: ds_client_get_profile_list failed. ret: %d\n",
|
||||
__func__, __LINE__, ret);
|
||||
goto err;
|
||||
}
|
||||
LOC_LOGD("%s:%d]: Got profile list; length = %d\n", __func__, __LINE__,
|
||||
profile_list_resp_msg.p_get_profile_list_resp->profile_list_len);
|
||||
|
||||
//Allocate memory for the response msg to obtain profile settings
|
||||
//We allocate memory for only one response msg and keep re-using it
|
||||
profile_settings_resp_msg.p_get_profile_setting_resp =
|
||||
(wds_get_profile_settings_resp_msg_v01 *)
|
||||
calloc(1, sizeof(wds_get_profile_settings_resp_msg_v01));
|
||||
if(profile_settings_resp_msg.p_get_profile_setting_resp == NULL) {
|
||||
LOC_LOGE("%s:%d]: Could not allocate memory for"
|
||||
"p_get_profile_setting_resp\n", __func__, __LINE__);
|
||||
ret = E_DS_CLIENT_FAILURE_NOT_ENOUGH_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
//Loop over the list of profiles to find a profile that supports
|
||||
//emergency calls
|
||||
for(i=0; i < profile_list_resp_msg.p_get_profile_list_resp->profile_list_len; i++) {
|
||||
/*QMI_WDS_GET_PROFILE_SETTINGS_REQ requires an input data
|
||||
structure that is of type wds_profile_identifier_type_v01
|
||||
We have to fill that structure for each profile from the
|
||||
info obtained from the profile list*/
|
||||
//copy profile type
|
||||
profile_identifier.profile_type =
|
||||
profile_list_resp_msg.p_get_profile_list_resp->profile_list[i].profile_type;
|
||||
//copy profile index
|
||||
profile_identifier.profile_index =
|
||||
profile_list_resp_msg.p_get_profile_list_resp->profile_list[i].profile_index;
|
||||
|
||||
ret = ds_client_get_profile_settings(&wds_qmi_client,
|
||||
&profile_settings_resp_msg,
|
||||
&profile_identifier);
|
||||
if(ret != E_DS_CLIENT_SUCCESS) {
|
||||
LOC_LOGE("%s:%d]: ds_client_get_profile_settings failed. ret: %d\n",
|
||||
__func__, __LINE__, ret);
|
||||
goto err;
|
||||
}
|
||||
LOC_LOGD("%s:%d]: Got profile setting for profile %d\n", __func__, __LINE__, i);
|
||||
LOC_LOGD("%s:%d]: Profile name: %s\n", __func__, __LINE__,
|
||||
profile_settings_resp_msg.p_get_profile_setting_resp->profile_name);
|
||||
|
||||
if(profile_settings_resp_msg.p_get_profile_setting_resp->support_emergency_calls_valid) {
|
||||
if(profile_settings_resp_msg.p_get_profile_setting_resp->support_emergency_calls) {
|
||||
LOC_LOGD("%s:%d]: Found emergency profile in profile %d"
|
||||
, __func__, __LINE__, i);
|
||||
call_profile_index_found = 1;
|
||||
emergency_profile_index = profile_identifier.profile_index;
|
||||
break;
|
||||
}
|
||||
else
|
||||
LOC_LOGE("%s:%d]: Emergency profile valid but not supported in profile: %d "
|
||||
, __func__, __LINE__, i);
|
||||
}
|
||||
//Since this struct is loaded with settings for the next profile,
|
||||
//it is important to clear out the memory to avoid values/flags
|
||||
//from being carried over
|
||||
memset((void *)profile_settings_resp_msg.p_get_profile_setting_resp,
|
||||
0, sizeof(wds_get_profile_settings_resp_msg_v01));
|
||||
}
|
||||
|
||||
//Release qmi client handle
|
||||
if(qmi_client_release(wds_qmi_client) != QMI_NO_ERR) {
|
||||
LOC_LOGE("%s:%d]: Could not release qmi client handle\n",
|
||||
__func__, __LINE__);
|
||||
ret = E_DS_CLIENT_FAILURE_GENERAL;
|
||||
}
|
||||
|
||||
if(call_profile_index_found) {
|
||||
*profile_index = emergency_profile_index;
|
||||
*ds_global_data = (ds_client_session_data *)calloc(1, sizeof(ds_client_session_data));
|
||||
if(*ds_global_data == NULL) {
|
||||
LOC_LOGE("%s:%d]: Could not allocate memory for ds_global_data. Failing\n",
|
||||
__func__, __LINE__);
|
||||
ret = E_DS_CLIENT_FAILURE_NOT_ENOUGH_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
(*ds_global_data)->caller_data.event_cb = callback->event_cb;
|
||||
(*ds_global_data)->caller_data.caller_cookie = caller_cookie;
|
||||
dsi_handle = dsi_get_data_srvc_hndl(net_ev_cb, &(*ds_global_data)->caller_data);
|
||||
if(dsi_handle == NULL) {
|
||||
LOC_LOGE("%s:%d]: Could not get data handle. Retry Later\n",
|
||||
__func__, __LINE__);
|
||||
ret = E_DS_CLIENT_RETRY_LATER;
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
(*ds_global_data)->dsi_net_handle = dsi_handle;
|
||||
}
|
||||
else {
|
||||
LOC_LOGE("%s:%d]: Could not find a profile that supports emergency calls",
|
||||
__func__, __LINE__);
|
||||
ret = E_DS_CLIENT_FAILURE_GENERAL;
|
||||
}
|
||||
err:
|
||||
if(profile_list_resp_msg.p_get_profile_list_resp)
|
||||
free(profile_list_resp_msg.p_get_profile_list_resp);
|
||||
if(profile_settings_resp_msg.p_get_profile_setting_resp)
|
||||
free(profile_settings_resp_msg.p_get_profile_setting_resp);
|
||||
LOC_LOGD("%s:%d]:Exit\n", __func__, __LINE__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ds_client_status_enum_type ds_client_stop_call(dsClientHandleType client_handle)
|
||||
{
|
||||
ds_client_status_enum_type ret = E_DS_CLIENT_SUCCESS;
|
||||
ds_client_session_data *p_ds_global_data = (ds_client_session_data *)client_handle;
|
||||
LOC_LOGD("%s:%d]:Enter\n", __func__, __LINE__);
|
||||
|
||||
if(client_handle == NULL) {
|
||||
LOC_LOGE("%s:%d]: Null argument received. Failing\n", __func__, __LINE__);
|
||||
ret = E_DS_CLIENT_FAILURE_GENERAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(dsi_stop_data_call(p_ds_global_data->dsi_net_handle) == DSI_SUCCESS) {
|
||||
LOC_LOGD("%s:%d]: Sent request to stop data call\n", __func__, __LINE__);
|
||||
}
|
||||
else {
|
||||
LOC_LOGE("%s:%d]: Could not send request to stop data call\n",
|
||||
__func__, __LINE__);
|
||||
ret = E_DS_CLIENT_FAILURE_GENERAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
err:
|
||||
LOC_LOGD("%s:%d]:Exit\n", __func__, __LINE__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
Stops data call associated with the data handle
|
||||
*/
|
||||
void ds_client_close_call(dsClientHandleType *client_handle)
|
||||
{
|
||||
ds_client_session_data **ds_global_data = (ds_client_session_data **)client_handle;
|
||||
LOC_LOGD("%s:%d]:Enter\n", __func__, __LINE__);
|
||||
if(client_handle == NULL || *client_handle == NULL) {
|
||||
LOC_LOGE("%s:%d]: Null argument received. Failing\n", __func__, __LINE__);
|
||||
goto err;
|
||||
}
|
||||
dsi_rel_data_srvc_hndl((*ds_global_data)->dsi_net_handle);
|
||||
(*ds_global_data)->dsi_net_handle = NULL;
|
||||
free(*ds_global_data);
|
||||
*ds_global_data = NULL;
|
||||
LOC_LOGD("%s:%d]: Released Data handle\n", __func__, __LINE__);
|
||||
err:
|
||||
LOC_LOGD("%s:%d]:Exit\n", __func__, __LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
int ds_client_init()
|
||||
{
|
||||
int ret = 0;
|
||||
LOC_LOGD("%s:%d]:Enter\n", __func__, __LINE__);
|
||||
if(DSI_SUCCESS != dsi_init(DSI_MODE_GENERAL))
|
||||
{
|
||||
LOC_LOGE("%s:%d]:dsi_init failed\n", __func__, __LINE__);
|
||||
ret = -1;
|
||||
}
|
||||
LOC_LOGD("%s:%d]:Exit\n", __func__, __LINE__);
|
||||
return ret;
|
||||
}
|
142
loc_api/ds_api/ds_client.h
Normal file
142
loc_api/ds_api/ds_client.h
Normal file
|
@ -0,0 +1,142 @@
|
|||
/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * 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.
|
||||
* * Neither the name of The Linux Foundation, nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef _DS_CLIENT_H_
|
||||
#define _DS_CLIENT_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void* dsClientHandleType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
E_DS_CLIENT_SUCCESS = 0,
|
||||
/**< Request was successful. */
|
||||
|
||||
E_DS_CLIENT_FAILURE_GENERAL = 1,
|
||||
/**< Failed because of a general failure. */
|
||||
|
||||
E_DS_CLIENT_FAILURE_UNSUPPORTED = 2,
|
||||
/**< Failed because the service does not support the command. */
|
||||
|
||||
E_DS_CLIENT_FAILURE_INVALID_PARAMETER = 3,
|
||||
/**< Failed because the request contained invalid parameters. */
|
||||
|
||||
E_DS_CLIENT_FAILURE_ENGINE_BUSY = 4,
|
||||
/**< Failed because the engine is busy. */
|
||||
|
||||
E_DS_CLIENT_FAILURE_PHONE_OFFLINE = 5,
|
||||
/**< Failed because the phone is offline. */
|
||||
|
||||
E_DS_CLIENT_FAILURE_TIMEOUT = 6,
|
||||
/**< Failed because of a timeout. */
|
||||
|
||||
E_DS_CLIENT_FAILURE_SERVICE_NOT_PRESENT = 7,
|
||||
/**< Failed because the service is not present. */
|
||||
|
||||
E_DS_CLIENT_FAILURE_SERVICE_VERSION_UNSUPPORTED = 8,
|
||||
/**< Failed because the service version is unsupported. */
|
||||
|
||||
E_DS_CLIENT_FAILURE_CLIENT_VERSION_UNSUPPORTED = 9,
|
||||
/**< Failed because the service does not support client version. */
|
||||
|
||||
E_DS_CLIENT_FAILURE_INVALID_HANDLE = 10,
|
||||
/**< Failed because an invalid handle was specified. */
|
||||
|
||||
E_DS_CLIENT_FAILURE_INTERNAL = 11,
|
||||
/**< Failed because of an internal error in the service. */
|
||||
|
||||
E_DS_CLIENT_FAILURE_NOT_INITIALIZED = 12,
|
||||
/**< Failed because the service has not been initialized. */
|
||||
|
||||
E_DS_CLIENT_FAILURE_NOT_ENOUGH_MEMORY = 13,
|
||||
/**< Failed because not rnough memory to do the operation.*/
|
||||
|
||||
E_DS_CLIENT_SERVICE_ALREADY_STARTED = 14,
|
||||
/*Service is already started*/
|
||||
|
||||
E_DS_CLIENT_DATA_CALL_CONNECTED = 15,
|
||||
|
||||
E_DS_CLIENT_DATA_CALL_DISCONNECTED = 16,
|
||||
|
||||
E_DS_CLIENT_RETRY_LATER = 17
|
||||
}ds_client_status_enum_type;
|
||||
|
||||
typedef enum {
|
||||
DATA_CALL_NONE = 0,
|
||||
DATA_CALL_OPEN,
|
||||
DATA_CALL_CLOSE
|
||||
}data_call_request_enum_type;
|
||||
|
||||
typedef void (*ds_client_event_ind_cb_type)(ds_client_status_enum_type result,
|
||||
void* loc_adapter_cookie);
|
||||
typedef struct {
|
||||
ds_client_event_ind_cb_type event_cb;
|
||||
}ds_client_cb_data;
|
||||
|
||||
/*
|
||||
This function is to be called as a first step by each process that
|
||||
needs to use data services. This call internally calls dsi_init()
|
||||
and prepares the module for making data calls.
|
||||
Needs to be called once for every process
|
||||
*/
|
||||
int ds_client_init();
|
||||
|
||||
/*
|
||||
Obtains a handle to the dsi_netctrl layer and looks up the profile
|
||||
to make the call. As of now. It only searches for profiles that
|
||||
support emergency calls
|
||||
*/
|
||||
ds_client_status_enum_type ds_client_open_call(dsClientHandleType *client_handle,
|
||||
ds_client_cb_data *callback,
|
||||
void *loc_adapter_cookie,
|
||||
int *profile_index);
|
||||
|
||||
/*
|
||||
Starts a data call using the profile number provided
|
||||
*/
|
||||
ds_client_status_enum_type ds_client_start_call(dsClientHandleType client_handle,
|
||||
int profile_index);
|
||||
|
||||
/*
|
||||
Stops a data call associated with the handle
|
||||
*/
|
||||
ds_client_status_enum_type ds_client_stop_call(dsClientHandleType client_handle);
|
||||
|
||||
/*
|
||||
Releases the handle used for making data calls
|
||||
*/
|
||||
void ds_client_close_call(dsClientHandleType *client_handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -186,6 +186,18 @@ void LocApiAdapter::requestATL(int connHandle, AGpsType agps_type)
|
|||
locEngHandle.sendMsge(locEngHandle.owner, msg);
|
||||
}
|
||||
|
||||
void LocApiAdapter::requestSuplES(int connHandle)
|
||||
{
|
||||
loc_eng_msg_request_supl_es *msg(new loc_eng_msg_request_supl_es(locEngHandle.owner, connHandle));
|
||||
locEngHandle.sendMsge(locEngHandle.owner, msg);
|
||||
}
|
||||
|
||||
void LocApiAdapter::releaseDataHandle(void)
|
||||
{
|
||||
loc_eng_msg_close_data_call *msg(new loc_eng_msg_close_data_call(locEngHandle.owner));
|
||||
locEngHandle.sendMsge(locEngHandle.owner, msg);
|
||||
}
|
||||
|
||||
void LocApiAdapter::releaseATL(int connHandle)
|
||||
{
|
||||
loc_eng_msg_release_atl *msg(new loc_eng_msg_release_atl(locEngHandle.owner, connHandle));
|
||||
|
@ -234,3 +246,18 @@ void LocApiAdapter::handleEngineUpEvent()
|
|||
loc_eng_msg *msg(new loc_eng_msg(locEngHandle.owner, LOC_ENG_MSG_ENGINE_UP));
|
||||
locEngHandle.sendMsge(locEngHandle.owner, msg);
|
||||
}
|
||||
|
||||
void LocApiAdapter::reportDataCallOpened()
|
||||
{
|
||||
loc_eng_msg_atl_open_success *msg(new loc_eng_msg_atl_open_success(locEngHandle.owner,
|
||||
AGPS_TYPE_INVALID,
|
||||
NULL, 0, 0));
|
||||
locEngHandle.sendMsge(locEngHandle.owner, msg);
|
||||
}
|
||||
|
||||
void LocApiAdapter::reportDataCallClosed()
|
||||
{
|
||||
loc_eng_msg_atl_closed *msg(new loc_eng_msg_atl_closed(locEngHandle.owner,
|
||||
AGPS_TYPE_INVALID));
|
||||
locEngHandle.sendMsge(locEngHandle.owner, msg);
|
||||
}
|
||||
|
|
|
@ -141,7 +141,10 @@ public:
|
|||
void requestNiNotify(GpsNiNotification ¬ify, const void* data);
|
||||
void handleEngineDownEvent();
|
||||
void handleEngineUpEvent();
|
||||
|
||||
void requestSuplES(int connHandle);
|
||||
void releaseDataHandle(void);
|
||||
void reportDataCallOpened(void);
|
||||
void reportDataCallClosed(void);
|
||||
// All below functions are to be defined by adapter specific modules:
|
||||
// RPC, QMI, etc. The default implementation is empty.
|
||||
inline virtual enum loc_api_adapter_err
|
||||
|
@ -230,6 +233,15 @@ public:
|
|||
|
||||
inline bool isInSession() { return navigating; }
|
||||
inline virtual void setInSession(bool inSession) { navigating = inSession; }
|
||||
inline virtual int openAndStartDataCall()
|
||||
{LOC_LOGW("%s: default implementation invoked", __func__); return -1;}
|
||||
inline virtual void stopDataCall()
|
||||
{LOC_LOGW("%s: default implementation invoked", __func__);}
|
||||
inline virtual void closeDataCall()
|
||||
{LOC_LOGW("%s: default implementation invoked", __func__);}
|
||||
inline virtual int initDataServiceClient()
|
||||
{LOC_LOGW("%s: default implementation invoked", __func__); return -1;}
|
||||
|
||||
};
|
||||
|
||||
extern "C" LocApiAdapter* getLocApiAdapter(LocEng &locEng);
|
||||
|
|
|
@ -60,7 +60,6 @@
|
|||
#include <loc_eng_nmea.h>
|
||||
#include <msg_q.h>
|
||||
#include <loc.h>
|
||||
|
||||
#include "log_util.h"
|
||||
#include "loc_eng_log.h"
|
||||
|
||||
|
@ -810,6 +809,38 @@ static void loc_inform_gps_status(loc_eng_data_s_type &loc_eng_data, GpsStatusVa
|
|||
EXIT_LOG(%s, VOID_RET);
|
||||
}
|
||||
|
||||
/*
|
||||
Callback function passed to Data Services State Machine
|
||||
This becomes part of the state machine's servicer and
|
||||
is used to send requests to the data services client
|
||||
*/
|
||||
static int dataCallCb(void *cb_data)
|
||||
{
|
||||
LOC_LOGD("Enter dataCallCb\n");
|
||||
int ret=0;
|
||||
if(cb_data != NULL) {
|
||||
dsCbData *cbData = (dsCbData *)cb_data;
|
||||
LocApiAdapter *locAdapter = (LocApiAdapter *)cbData->mAdapter;
|
||||
if(cbData->action == GPS_REQUEST_AGPS_DATA_CONN) {
|
||||
LOC_LOGD("dataCallCb GPS_REQUEST_AGPS_DATA_CONN\n");
|
||||
ret = locAdapter->openAndStartDataCall();
|
||||
}
|
||||
else if(cbData->action == GPS_RELEASE_AGPS_DATA_CONN) {
|
||||
LOC_LOGD("dataCallCb GPS_RELEASE_AGPS_DATA_CONN\n");
|
||||
locAdapter->stopDataCall();
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOC_LOGE("NULL argument received. Failing.\n");
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
err:
|
||||
LOC_LOGD("Exit dataCallCb ret = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*===========================================================================
|
||||
FUNCTION loc_eng_agps_reinit
|
||||
|
||||
|
@ -876,17 +907,27 @@ void loc_eng_agps_init(loc_eng_data_s_type &loc_eng_data, AGpsCallbacks* callbac
|
|||
}
|
||||
loc_eng_data.agps_status_cb = callbacks->status_cb;
|
||||
|
||||
loc_eng_data.agnss_nif = new AgpsStateMachine(loc_eng_data.agps_status_cb,
|
||||
loc_eng_data.agnss_nif = new AgpsStateMachine(servicerTypeAgps,
|
||||
(void *)loc_eng_data.agps_status_cb,
|
||||
AGPS_TYPE_SUPL,
|
||||
false);
|
||||
#ifdef FEATURE_IPV6
|
||||
loc_eng_data.internet_nif = new AgpsStateMachine(loc_eng_data.agps_status_cb,
|
||||
loc_eng_data.internet_nif = new AgpsStateMachine(servicerTypeAgps,
|
||||
(void *)loc_eng_data.agps_status_cb,
|
||||
AGPS_TYPE_WWAN_ANY,
|
||||
false);
|
||||
loc_eng_data.wifi_nif = new AgpsStateMachine(loc_eng_data.agps_status_cb,
|
||||
loc_eng_data.wifi_nif = new AgpsStateMachine(servicerTypeAgps,
|
||||
(void *)loc_eng_data.agps_status_cb,
|
||||
AGPS_TYPE_WIFI,
|
||||
true);
|
||||
#endif
|
||||
if(!loc_eng_data.client_handle->initDataServiceClient()) {
|
||||
LOC_LOGD("%s:%d]: Creating new ds state machine\n", __func__, __LINE__);
|
||||
loc_eng_data.ds_nif = new DSStateMachine(servicerTypeExt,
|
||||
(void *)dataCallCb,
|
||||
loc_eng_data.client_handle);
|
||||
LOC_LOGD("%s:%d]: Created new ds state machine\n", __func__, __LINE__);
|
||||
}
|
||||
|
||||
loc_eng_dmn_conn_loc_api_server_launch(callbacks->create_thread_cb,
|
||||
NULL, NULL, &loc_eng_data);
|
||||
|
@ -1741,14 +1782,27 @@ static void loc_eng_deferred_action_thread(void* arg)
|
|||
loc_eng_data_p->client_handle,
|
||||
false);
|
||||
// attempt to unsubscribe from agnss_nif first
|
||||
if (! loc_eng_data_p->agnss_nif->unsubscribeRsrc((Subscriber*)&s1)) {
|
||||
if (loc_eng_data_p->agnss_nif->unsubscribeRsrc((Subscriber*)&s1)) {
|
||||
#ifdef FEATURE_IPV6
|
||||
LOC_LOGD("%s:%d]: Unsubscribed from agnss_nif", __func__, __LINE__);
|
||||
}
|
||||
else {
|
||||
ATLSubscriber s2(arlMsg->handle,
|
||||
loc_eng_data_p->internet_nif,
|
||||
loc_eng_data_p->client_handle,
|
||||
false);
|
||||
// if unsuccessful, try internet_nif
|
||||
loc_eng_data_p->internet_nif->unsubscribeRsrc((Subscriber*)&s2);
|
||||
if(loc_eng_data_p->internet_nif->unsubscribeRsrc((Subscriber*)&s2)) {
|
||||
LOC_LOGD("%s:%d]: Unsubscribed from internet_nif", __func__, __LINE__);
|
||||
}
|
||||
else {
|
||||
DSSubscriber s3(loc_eng_data_p->ds_nif,
|
||||
arlMsg->handle);
|
||||
LOC_LOGD("%s:%d]: Request to stop Emergency call. Handle: %d\n",
|
||||
__func__, __LINE__, arlMsg->handle);
|
||||
loc_eng_data_p->ds_nif->unsubscribeRsrc((Subscriber*)&s3);
|
||||
LOC_LOGD("%s:%d]: Unsubscribed from ds_nif", __func__, __LINE__);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1827,16 +1881,25 @@ static void loc_eng_deferred_action_thread(void* arg)
|
|||
loc_eng_msg_atl_open_success *aosMsg = (loc_eng_msg_atl_open_success*)msg;
|
||||
AgpsStateMachine* stateMachine;
|
||||
#ifdef FEATURE_IPV6
|
||||
LOC_LOGD("%s:%d]: AGPS_TYPE: %d\n", __func__, __LINE__, (int)aosMsg->agpsType);
|
||||
switch (aosMsg->agpsType) {
|
||||
case AGPS_TYPE_WIFI: {
|
||||
LOC_LOGD("%s:%d]: AGPS Type wifi\n", __func__, __LINE__);
|
||||
stateMachine = loc_eng_data_p->wifi_nif;
|
||||
break;
|
||||
}
|
||||
case AGPS_TYPE_SUPL: {
|
||||
LOC_LOGD("%s:%d]: AGPS Type supl\n", __func__, __LINE__);
|
||||
stateMachine = loc_eng_data_p->agnss_nif;
|
||||
break;
|
||||
}
|
||||
case AGPS_TYPE_INVALID: {
|
||||
stateMachine = loc_eng_data_p->ds_nif;
|
||||
LOC_LOGD("%s:%d]: AGPS Type invalid\n", __func__, __LINE__);
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
LOC_LOGD("%s:%d]: AGPS Type default internet\n", __func__, __LINE__);
|
||||
stateMachine = loc_eng_data_p->internet_nif;
|
||||
}
|
||||
}
|
||||
|
@ -1864,6 +1927,10 @@ static void loc_eng_deferred_action_thread(void* arg)
|
|||
stateMachine = loc_eng_data_p->agnss_nif;
|
||||
break;
|
||||
}
|
||||
case AGPS_TYPE_INVALID: {
|
||||
stateMachine = loc_eng_data_p->ds_nif;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
stateMachine = loc_eng_data_p->internet_nif;
|
||||
}
|
||||
|
@ -1928,7 +1995,7 @@ static void loc_eng_deferred_action_thread(void* arg)
|
|||
{
|
||||
loc_eng_msg_request_phone_context *contextReqMsg = (loc_eng_msg_request_phone_context*)msg;
|
||||
LOC_LOGD("Received phone context request from ULP.context_type 0x%x,request_type 0x%x ",
|
||||
contextReqMsg->contextRequest.context_type,contextReqMsg->contextRequest.request_type)
|
||||
contextReqMsg->contextRequest.context_type,contextReqMsg->contextRequest.request_type);
|
||||
if(loc_eng_data_p->ulp_phone_context_req_cb != NULL)
|
||||
{
|
||||
loc_eng_data_p->ulp_phone_context_req_cb((UlpPhoneContextRequest*)&(contextReqMsg->contextRequest));
|
||||
|
@ -1944,6 +2011,25 @@ static void loc_eng_deferred_action_thread(void* arg)
|
|||
}
|
||||
break;
|
||||
|
||||
case LOC_ENG_MSG_REQUEST_SUPL_ES:
|
||||
{
|
||||
loc_eng_msg_request_supl_es *reqMsg =
|
||||
(loc_eng_msg_request_supl_es *)msg;
|
||||
AgpsStateMachine *stateMachine = loc_eng_data_p->ds_nif;
|
||||
DSSubscriber subscriber(stateMachine, reqMsg->handle);
|
||||
LOC_LOGD("%s:%d]: Starting data call\n", __func__, __LINE__);
|
||||
stateMachine->subscribeRsrc((Subscriber *)&subscriber);
|
||||
}
|
||||
break;
|
||||
|
||||
case LOC_ENG_MSG_CLOSE_DATA_CALL:
|
||||
{
|
||||
loc_eng_data_p->client_handle->closeDataCall();
|
||||
LOC_LOGD("%s:%d]: Request to close data call\n",
|
||||
__func__, __LINE__);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LOC_LOGE("unsupported msgid = %d\n", msg->msgid);
|
||||
break;
|
||||
|
@ -2273,4 +2359,3 @@ int loc_eng_read_config(void)
|
|||
EXIT_LOG(%d, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -121,6 +121,8 @@ typedef struct
|
|||
AgpsStateMachine* agnss_nif;
|
||||
AgpsStateMachine* internet_nif;
|
||||
AgpsStateMachine* wifi_nif;
|
||||
//State machine for Data Services
|
||||
AgpsStateMachine* ds_nif;
|
||||
|
||||
// GPS engine status
|
||||
GpsStatusValue engine_status;
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <log_util.h>
|
||||
#include <loc_eng_dmn_conn_handler.h>
|
||||
#include <loc_eng_dmn_conn.h>
|
||||
#include<sys/time.h>
|
||||
|
||||
//======================================================================
|
||||
// C callbacks
|
||||
|
@ -84,8 +85,8 @@ static bool notifySubscriber(void* fromCaller, void* fromList)
|
|||
const int Notification::BROADCAST_ALL = 0x80000000;
|
||||
const int Notification::BROADCAST_ACTIVE = 0x80000001;
|
||||
const int Notification::BROADCAST_INACTIVE = 0x80000002;
|
||||
|
||||
|
||||
const unsigned char DSStateMachine::MAX_START_DATA_CALL_RETRIES = 4;
|
||||
const unsigned int DSStateMachine::DATA_CALL_RETRY_DELAY_MSEC = 500;
|
||||
//======================================================================
|
||||
// Subscriber: BITSubscriber / ATLSubscriber / WIFISubscriber
|
||||
//======================================================================
|
||||
|
@ -227,7 +228,29 @@ bool WIFISubscriber::notifyRsrcStatus(Notification ¬ification)
|
|||
return notify;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool DSSubscriber::notifyRsrcStatus(Notification ¬ification)
|
||||
{
|
||||
bool notify = forMe(notification);
|
||||
LOC_LOGD("DSSubscriber::notifyRsrcStatus. notify:%d \n",(int)(notify));
|
||||
if(notify) {
|
||||
switch(notification.rsrcStatus) {
|
||||
case RSRC_UNSUBSCRIBE:
|
||||
case RSRC_RELEASED:
|
||||
case RSRC_DENIED:
|
||||
case RSRC_GRANTED:
|
||||
((DSStateMachine *)mStateMachine)->informStatus(notification.rsrcStatus, ID);
|
||||
break;
|
||||
default:
|
||||
notify = false;
|
||||
}
|
||||
}
|
||||
return notify;
|
||||
}
|
||||
void DSSubscriber :: setInactive()
|
||||
{
|
||||
mIsInactive = true;
|
||||
((DSStateMachine *)mStateMachine)->informStatus(RSRC_UNSUBSCRIBE, ID);
|
||||
}
|
||||
//======================================================================
|
||||
// AgpsState: AgpsReleasedState / AgpsPendingState / AgpsAcquiredState
|
||||
//======================================================================
|
||||
|
@ -249,13 +272,14 @@ public:
|
|||
|
||||
AgpsState* AgpsReleasedState::onRsrcEvent(AgpsRsrcStatus event, void* data)
|
||||
{
|
||||
LOC_LOGD("AgpsReleasedState::onRsrcEvent; event:%d\n", (int)event);
|
||||
if (mStateMachine->hasSubscribers()) {
|
||||
LOC_LOGE("Error: %s subscriber list not empty!!!", whoami());
|
||||
// I don't know how to recover from it. I am adding this rather
|
||||
// for debugging purpose.
|
||||
}
|
||||
|
||||
AgpsState* nextState = this;;
|
||||
AgpsState* nextState = this;
|
||||
switch (event)
|
||||
{
|
||||
case RSRC_SUBSCRIBE:
|
||||
|
@ -263,11 +287,14 @@ AgpsState* AgpsReleasedState::onRsrcEvent(AgpsRsrcStatus event, void* data)
|
|||
// no notification until we get RSRC_GRANTED
|
||||
// but we need to add subscriber to the list
|
||||
mStateMachine->addSubscriber((Subscriber*)data);
|
||||
// request from connecivity service for NIF
|
||||
//The if condition is added so that if the data call setup fails
|
||||
//for DS State Machine, we want to retry in released state.
|
||||
//for AGps State Machine, sendRsrcRequest() will always return success
|
||||
if(!mStateMachine->sendRsrcRequest(GPS_REQUEST_AGPS_DATA_CONN)) {
|
||||
// move the state to PENDING
|
||||
nextState = mPendingState;
|
||||
|
||||
// request from connecivity service for NIF
|
||||
mStateMachine->sendRsrcRequest(GPS_REQUEST_AGPS_DATA_CONN);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -313,6 +340,7 @@ public:
|
|||
AgpsState* AgpsPendingState::onRsrcEvent(AgpsRsrcStatus event, void* data)
|
||||
{
|
||||
AgpsState* nextState = this;;
|
||||
LOC_LOGD("AgpsPendingState::onRsrcEvent; event:%d\n", (int)event);
|
||||
switch (event)
|
||||
{
|
||||
case RSRC_SUBSCRIBE:
|
||||
|
@ -408,6 +436,7 @@ public:
|
|||
AgpsState* AgpsAcquiredState::onRsrcEvent(AgpsRsrcStatus event, void* data)
|
||||
{
|
||||
AgpsState* nextState = this;
|
||||
LOC_LOGD("AgpsAcquiredState::onRsrcEvent; event:%d\n", (int)event);
|
||||
switch (event)
|
||||
{
|
||||
case RSRC_SUBSCRIBE:
|
||||
|
@ -441,7 +470,8 @@ AgpsState* AgpsAcquiredState::onRsrcEvent(AgpsRsrcStatus event, void* data)
|
|||
|
||||
// tell connecivity service we can release NIF
|
||||
mStateMachine->sendRsrcRequest(GPS_RELEASE_AGPS_DATA_CONN);
|
||||
} else if (!mStateMachine->hasActiveSubscribers()) {
|
||||
}
|
||||
else if (!mStateMachine->hasActiveSubscribers()) {
|
||||
// only inactive subscribers, move to RELEASING state
|
||||
nextState = mReleasingState;
|
||||
|
||||
|
@ -500,6 +530,8 @@ public:
|
|||
AgpsState* AgpsReleasingState::onRsrcEvent(AgpsRsrcStatus event, void* data)
|
||||
{
|
||||
AgpsState* nextState = this;;
|
||||
LOC_LOGD("AgpsReleasingState::onRsrcEvent; event:%d\n", (int)event);
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case RSRC_SUBSCRIBE:
|
||||
|
@ -541,7 +573,7 @@ AgpsState* AgpsReleasingState::onRsrcEvent(AgpsRsrcStatus event, void* data)
|
|||
// by setting false, we keep subscribers on the linked list
|
||||
mStateMachine->notifySubscribers(notification);
|
||||
|
||||
if (mStateMachine->hasSubscribers()) {
|
||||
if (mStateMachine->hasActiveSubscribers()) {
|
||||
nextState = mPendingState;
|
||||
// request from connecivity service for NIF
|
||||
mStateMachine->sendRsrcRequest(GPS_REQUEST_AGPS_DATA_CONN);
|
||||
|
@ -561,20 +593,58 @@ AgpsState* AgpsReleasingState::onRsrcEvent(AgpsRsrcStatus event, void* data)
|
|||
whoami(), nextState->whoami(), event);
|
||||
return nextState;
|
||||
}
|
||||
//======================================================================
|
||||
//Servicer
|
||||
//======================================================================
|
||||
Servicer* Servicer :: getServicer(servicerType type, void *cb_func)
|
||||
{
|
||||
LOC_LOGD(" Enter getServicer type:%d\n", (int)type);
|
||||
switch(type) {
|
||||
case servicerTypeNoCbParam:
|
||||
return (new Servicer(cb_func));
|
||||
case servicerTypeExt:
|
||||
return (new ExtServicer(cb_func));
|
||||
case servicerTypeAgps:
|
||||
return (new AGpsServicer(cb_func));
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int Servicer :: requestRsrc(void *cb_data)
|
||||
{
|
||||
callback();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExtServicer :: requestRsrc(void *cb_data)
|
||||
{
|
||||
int ret=-1;
|
||||
LOC_LOGD("Enter ExtServicer :: requestRsrc\n");
|
||||
ret = callbackExt(cb_data);
|
||||
LOC_LOGD("Exit ExtServicer :: requestRsrc\n");
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int AGpsServicer :: requestRsrc(void *cb_data)
|
||||
{
|
||||
callbackAGps((AGpsStatus *)cb_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// AgpsStateMachine
|
||||
//======================================================================
|
||||
|
||||
AgpsStateMachine::AgpsStateMachine(void (*servicer)(AGpsStatus* status),
|
||||
AgpsStateMachine::AgpsStateMachine(servicerType servType,
|
||||
void *cb_func,
|
||||
AGpsType type,
|
||||
bool enforceSingleSubscriber) :
|
||||
mServicer(servicer), mType(type),
|
||||
mStatePtr(new AgpsReleasedState(this)),
|
||||
mStatePtr(new AgpsReleasedState(this)),mType(type),
|
||||
mAPN(NULL),
|
||||
mAPNLen(0),
|
||||
mEnforceSingleSubscriber(enforceSingleSubscriber)
|
||||
mEnforceSingleSubscriber(enforceSingleSubscriber),
|
||||
mServicer(Servicer :: getServicer(servType, (void *)cb_func))
|
||||
{
|
||||
linked_list_init(&mSubscribers);
|
||||
|
||||
|
@ -615,6 +685,7 @@ AgpsStateMachine::~AgpsStateMachine()
|
|||
delete releasedState;
|
||||
delete pendindState;
|
||||
delete releasingState;
|
||||
delete mServicer;
|
||||
linked_list_destroy(&mSubscribers);
|
||||
|
||||
if (NULL != mAPN) {
|
||||
|
@ -669,6 +740,7 @@ void AgpsStateMachine::notifySubscribers(Notification& notification) const
|
|||
// rest of the list unprocessed. So we need a loop.
|
||||
linked_list_search(mSubscribers, (void**)&s, notifySubscriber,
|
||||
(void*)¬ification, true);
|
||||
delete s;
|
||||
}
|
||||
} else {
|
||||
// no loop needed if it the last param sets to false, which
|
||||
|
@ -690,7 +762,7 @@ void AgpsStateMachine::addSubscriber(Subscriber* subscriber) const
|
|||
}
|
||||
}
|
||||
|
||||
void AgpsStateMachine::sendRsrcRequest(AGpsStatusValue action) const
|
||||
int AgpsStateMachine::sendRsrcRequest(AGpsStatusValue action) const
|
||||
{
|
||||
Subscriber* s = NULL;
|
||||
Notification notification(Notification::BROADCAST_ACTIVE);
|
||||
|
@ -722,8 +794,9 @@ void AgpsStateMachine::sendRsrcRequest(AGpsStatusValue action) const
|
|||
#endif
|
||||
|
||||
CALLBACK_LOG_CALLFLOW("agps_cb", %s, loc_get_agps_status_name(action));
|
||||
(*mServicer)(&nifRequest);
|
||||
mServicer->requestRsrc((void *)&nifRequest);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AgpsStateMachine::subscribeRsrc(Subscriber *subscriber)
|
||||
|
@ -758,3 +831,163 @@ bool AgpsStateMachine::hasActiveSubscribers() const
|
|||
hasSubscriber, (void*)¬ification, false);
|
||||
return NULL != s;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// DSStateMachine
|
||||
//======================================================================
|
||||
void delay_callback(void *callbackData, int result)
|
||||
{
|
||||
if(callbackData) {
|
||||
DSStateMachine *DSSMInstance = (DSStateMachine *)callbackData;
|
||||
DSSMInstance->retryCallback();
|
||||
}
|
||||
else {
|
||||
LOC_LOGE(" NULL argument received. Failing.\n");
|
||||
goto err;
|
||||
}
|
||||
err:
|
||||
return;
|
||||
}
|
||||
|
||||
DSStateMachine :: DSStateMachine(servicerType type, void *cb_func,
|
||||
LocApiAdapter* adapterHandle):
|
||||
AgpsStateMachine(type, cb_func, AGPS_TYPE_INVALID,false),
|
||||
mLocAdapter(adapterHandle)
|
||||
{
|
||||
LOC_LOGD("%s:%d]: New DSStateMachine\n", __func__, __LINE__);
|
||||
mRetries = 0;
|
||||
}
|
||||
|
||||
void DSStateMachine :: retryCallback(void)
|
||||
{
|
||||
DSSubscriber *subscriber = NULL;
|
||||
Notification notification(Notification::BROADCAST_ACTIVE);
|
||||
linked_list_search(mSubscribers, (void**)&subscriber, hasSubscriber,
|
||||
(void*)¬ification, false);
|
||||
if(subscriber)
|
||||
mLocAdapter->requestSuplES(subscriber->ID);
|
||||
else
|
||||
LOC_LOGE("DSStateMachine :: retryCallback: No subscriber found." \
|
||||
"Cannot retry data call\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int DSStateMachine :: sendRsrcRequest(AGpsStatusValue action) const
|
||||
{
|
||||
DSSubscriber* s = NULL;
|
||||
dsCbData cbData;
|
||||
int ret=-1;
|
||||
int connHandle=-1;
|
||||
LOC_LOGD("Enter DSStateMachine :: sendRsrcRequest\n");
|
||||
Notification notification(Notification::BROADCAST_ACTIVE);
|
||||
linked_list_search(mSubscribers, (void**)&s, hasSubscriber,
|
||||
(void*)¬ification, false);
|
||||
if(s) {
|
||||
connHandle = s->ID;
|
||||
LOC_LOGD("DSStateMachine :: sendRsrcRequest - subscriber found\n");
|
||||
}
|
||||
else
|
||||
LOC_LOGD("DSStateMachine :: sendRsrcRequest - No subscriber found\n");
|
||||
|
||||
cbData.action = action;
|
||||
cbData.mAdapter = mLocAdapter;
|
||||
ret = mServicer->requestRsrc((void *)&cbData);
|
||||
//Only the request to start data call returns a success/failure
|
||||
//The request to stop data call will always succeed
|
||||
//Hence, the below block will only be executed when the
|
||||
//request to start the data call fails
|
||||
switch(ret) {
|
||||
case LOC_API_ADAPTER_ERR_ENGINE_BUSY:
|
||||
LOC_LOGD("DSStateMachine :: sendRsrcRequest - Failure returned: %d\n",ret);
|
||||
((DSStateMachine *)this)->incRetries();
|
||||
if(mRetries > MAX_START_DATA_CALL_RETRIES) {
|
||||
LOC_LOGE(" Failed to start Data call. Fallback to normal ATL SUPL\n");
|
||||
informStatus(RSRC_DENIED, connHandle);
|
||||
}
|
||||
else {
|
||||
if(loc_timer_start(DATA_CALL_RETRY_DELAY_MSEC, delay_callback, (void *)this)) {
|
||||
LOC_LOGE("Error: Could not start delay thread\n");
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LOC_API_ADAPTER_ERR_UNSUPPORTED:
|
||||
LOC_LOGE("No profile found for emergency call. Fallback to normal SUPL ATL\n");
|
||||
informStatus(RSRC_DENIED, connHandle);
|
||||
break;
|
||||
case LOC_API_ADAPTER_ERR_SUCCESS:
|
||||
LOC_LOGD("%s:%d]: Request to start data call sent\n", __func__, __LINE__);
|
||||
break;
|
||||
case -1:
|
||||
//One of the ways this case can be encountered is if the callback function
|
||||
//receives a null argument, it just exits with -1 error
|
||||
LOC_LOGE("Error: Something went wrong somewhere. Falling back to normal SUPL ATL\n");
|
||||
informStatus(RSRC_DENIED, connHandle);
|
||||
break;
|
||||
default:
|
||||
LOC_LOGE("%s:%d]: Unrecognized return value\n", __func__, __LINE__);
|
||||
}
|
||||
err:
|
||||
LOC_LOGD("EXIT DSStateMachine :: sendRsrcRequest; ret = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DSStateMachine :: onRsrcEvent(AgpsRsrcStatus event)
|
||||
{
|
||||
void* currState = (void *)mStatePtr;
|
||||
LOC_LOGD("Enter DSStateMachine :: onRsrcEvent. event = %d\n", (int)event);
|
||||
switch (event)
|
||||
{
|
||||
case RSRC_GRANTED:
|
||||
LOC_LOGD("DSStateMachine :: onRsrcEvent RSRC_GRANTED\n");
|
||||
mStatePtr = mStatePtr->onRsrcEvent(event, NULL);
|
||||
break;
|
||||
case RSRC_RELEASED:
|
||||
LOC_LOGD("DSStateMachine :: onRsrcEvent RSRC_RELEASED\n");
|
||||
mStatePtr = mStatePtr->onRsrcEvent(event, NULL);
|
||||
//To handle the case where we get a RSRC_RELEASED in
|
||||
//pending state, we translate that to a RSRC_DENIED state
|
||||
//since the callback from DSI is either RSRC_GRANTED or RSRC_RELEASED
|
||||
//for when the call is connected or disconnected respectively.
|
||||
if((void *)mStatePtr != currState)
|
||||
break;
|
||||
else {
|
||||
event = RSRC_DENIED;
|
||||
LOC_LOGE(" Switching event to RSRC_DENIED\n");
|
||||
}
|
||||
case RSRC_DENIED:
|
||||
mStatePtr = mStatePtr->onRsrcEvent(event, NULL);
|
||||
break;
|
||||
default:
|
||||
LOC_LOGW("AgpsStateMachine: unrecognized event %d", event);
|
||||
break;
|
||||
}
|
||||
LOC_LOGD("Exit DSStateMachine :: onRsrcEvent. event = %d\n", (int)event);
|
||||
}
|
||||
|
||||
void DSStateMachine :: informStatus(AgpsRsrcStatus status, int ID) const
|
||||
{
|
||||
LOC_LOGD("DSStateMachine :: informStatus. Status=%d\n",(int)status);
|
||||
switch(status) {
|
||||
case RSRC_UNSUBSCRIBE:
|
||||
((LocApiAdapter*)mLocAdapter)->atlCloseStatus(ID, 1);
|
||||
break;
|
||||
case RSRC_RELEASED:
|
||||
((LocApiAdapter*)mLocAdapter)->releaseDataHandle();
|
||||
break;
|
||||
case RSRC_DENIED:
|
||||
((DSStateMachine *)this)->mRetries = 0;
|
||||
mLocAdapter->requestATL(ID, AGPS_TYPE_SUPL);
|
||||
break;
|
||||
case RSRC_GRANTED:
|
||||
((LocApiAdapter*)mLocAdapter)->atlOpenStatus(ID, 1,
|
||||
NULL,
|
||||
AGPS_APN_BEARER_INVALID,
|
||||
AGPS_TYPE_INVALID);
|
||||
break;
|
||||
default:
|
||||
LOC_LOGW("DSStateMachine :: informStatus - unknown status");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <linked_list.h>
|
||||
#include <LocApiAdapter.h>
|
||||
#include "loc_eng_msg.h"
|
||||
#include <loc_timer.h>
|
||||
|
||||
// forward declaration
|
||||
class AgpsStateMachine;
|
||||
|
@ -53,6 +54,18 @@ typedef enum {
|
|||
RSRC_STATUS_MAX
|
||||
} AgpsRsrcStatus;
|
||||
|
||||
typedef enum {
|
||||
servicerTypeNoCbParam,
|
||||
servicerTypeAgps,
|
||||
servicerTypeExt
|
||||
}servicerType;
|
||||
|
||||
//DS Callback struct
|
||||
typedef struct {
|
||||
LocApiAdapter *mAdapter;
|
||||
AGpsStatusValue action;
|
||||
}dsCbData;
|
||||
|
||||
// information bundle for subscribers
|
||||
struct Notification {
|
||||
// goes to every subscriber
|
||||
|
@ -101,7 +114,7 @@ class AgpsState {
|
|||
// no class members are public. We don't want
|
||||
// anyone but state machine to use state.
|
||||
friend class AgpsStateMachine;
|
||||
|
||||
friend class DSStateMachine;
|
||||
// state transitions are done here.
|
||||
// Each state implements its own transitions (of course).
|
||||
inline virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data) = 0;
|
||||
|
@ -129,21 +142,56 @@ public:
|
|||
inline virtual char* whoami() = 0;
|
||||
};
|
||||
|
||||
class Servicer {
|
||||
void (*callback)(void);
|
||||
public:
|
||||
static Servicer* getServicer(servicerType type, void *cb_func);
|
||||
virtual int requestRsrc(void *cb_data);
|
||||
Servicer() {}
|
||||
Servicer(void *cb_func)
|
||||
{ callback = (void(*)(void))(cb_func); }
|
||||
virtual ~Servicer(){}
|
||||
inline virtual char *whoami() {return (char*)"Servicer";}
|
||||
};
|
||||
|
||||
class ExtServicer : public Servicer {
|
||||
int (*callbackExt)(void *cb_data);
|
||||
public:
|
||||
int requestRsrc(void *cb_data);
|
||||
ExtServicer() {}
|
||||
ExtServicer(void *cb_func)
|
||||
{ callbackExt = (int(*)(void *))(cb_func); }
|
||||
virtual ~ExtServicer(){}
|
||||
inline virtual char *whoami() {return (char*)"ExtServicer";}
|
||||
};
|
||||
|
||||
class AGpsServicer : public Servicer {
|
||||
void (*callbackAGps)(AGpsStatus* status);
|
||||
public:
|
||||
int requestRsrc(void *cb_data);
|
||||
AGpsServicer() {}
|
||||
AGpsServicer(void *cb_func)
|
||||
{ callbackAGps = (void(*)(AGpsStatus *))(cb_func); }
|
||||
virtual ~AGpsServicer(){}
|
||||
inline virtual char *whoami() {return (char*)"AGpsServicer";}
|
||||
};
|
||||
|
||||
class AgpsStateMachine {
|
||||
protected:
|
||||
// a linked list of subscribers.
|
||||
void* mSubscribers;
|
||||
//handle to whoever provides the service
|
||||
Servicer *mServicer;
|
||||
// allows AgpsState to access private data
|
||||
// each state is really internal data to the
|
||||
// state machine, so it should be able to
|
||||
// access anything within the state machine.
|
||||
friend class AgpsState;
|
||||
|
||||
// handle to whoever provides the service
|
||||
void (* const mServicer)(AGpsStatus* status);
|
||||
// NIF type: AGNSS or INTERNET.
|
||||
const AGpsType mType;
|
||||
// pointer to the current state.
|
||||
AgpsState* mStatePtr;
|
||||
// a linked list of subscribers.
|
||||
void* mSubscribers;
|
||||
private:
|
||||
// NIF type: AGNSS or INTERNET.
|
||||
const AGpsType mType;
|
||||
// apn to the NIF. Each state machine tracks
|
||||
// resource state of a particular NIF. For each
|
||||
// NIF, there is also an active APN.
|
||||
|
@ -158,7 +206,8 @@ class AgpsStateMachine {
|
|||
bool mEnforceSingleSubscriber;
|
||||
|
||||
public:
|
||||
AgpsStateMachine(void (*servicer)(AGpsStatus* status), AGpsType type, bool enforceSingleSubscriber);
|
||||
AgpsStateMachine(servicerType servType, void *cb_func,
|
||||
AGpsType type, bool enforceSingleSubscriber);
|
||||
virtual ~AgpsStateMachine();
|
||||
|
||||
// self explanatory methods below
|
||||
|
@ -179,11 +228,15 @@ public:
|
|||
// add a subscriber in the linked list, if not already there.
|
||||
void addSubscriber(Subscriber* subscriber) const;
|
||||
|
||||
void onRsrcEvent(AgpsRsrcStatus event);
|
||||
virtual void onRsrcEvent(AgpsRsrcStatus event);
|
||||
|
||||
// put the data together and send the FW
|
||||
void sendRsrcRequest(AGpsStatusValue action) const;
|
||||
virtual int sendRsrcRequest(AGpsStatusValue action) const;
|
||||
|
||||
//if list is empty, linked_list_empty returns 1
|
||||
//else if list is not empty, returns 0
|
||||
//so hasSubscribers() returns 1 if list is not empty
|
||||
//and returns 0 if list is empty
|
||||
inline bool hasSubscribers() const
|
||||
{ return !linked_list_empty(mSubscribers); }
|
||||
|
||||
|
@ -194,6 +247,24 @@ public:
|
|||
|
||||
// private. Only a state gets to call this.
|
||||
void notifySubscribers(Notification& notification) const;
|
||||
|
||||
};
|
||||
|
||||
class DSStateMachine : public AgpsStateMachine {
|
||||
static const unsigned char MAX_START_DATA_CALL_RETRIES;
|
||||
static const unsigned int DATA_CALL_RETRY_DELAY_MSEC;
|
||||
LocApiAdapter* mLocAdapter;
|
||||
unsigned char mRetries;
|
||||
public:
|
||||
DSStateMachine(servicerType type,
|
||||
void *cb_func,
|
||||
LocApiAdapter* adapterHandle);
|
||||
int sendRsrcRequest(AGpsStatusValue action) const;
|
||||
void onRsrcEvent(AgpsRsrcStatus event);
|
||||
void retryCallback();
|
||||
void informStatus(AgpsRsrcStatus status, int ID) const;
|
||||
inline void incRetries() {mRetries++;}
|
||||
inline virtual char *whoami() {return (char*)"DSStateMachine";}
|
||||
};
|
||||
|
||||
// each subscriber is a AGPS client. In the case of ATL, there could be
|
||||
|
@ -252,7 +323,7 @@ struct BITSubscriber : public Subscriber {
|
|||
}
|
||||
|
||||
virtual bool equals(const Subscriber *s) const;
|
||||
|
||||
inline virtual ~BITSubscriber(){}
|
||||
private:
|
||||
char ipv6Addr[16];
|
||||
};
|
||||
|
@ -277,6 +348,7 @@ struct ATLSubscriber : public Subscriber {
|
|||
return new ATLSubscriber(ID, mStateMachine, mLocAdapter,
|
||||
mBackwardCompatibleMode);
|
||||
}
|
||||
inline virtual ~ATLSubscriber(){}
|
||||
};
|
||||
|
||||
#ifdef FEATURE_IPV6
|
||||
|
@ -325,7 +397,28 @@ struct WIFISubscriber : public Subscriber {
|
|||
{
|
||||
return new WIFISubscriber(mStateMachine, mSSID, mPassword, senderId);
|
||||
}
|
||||
inline virtual ~WIFISubscriber(){}
|
||||
};
|
||||
#endif
|
||||
|
||||
struct DSSubscriber : public Subscriber {
|
||||
bool mIsInactive;
|
||||
inline DSSubscriber(const AgpsStateMachine *stateMachine,
|
||||
const int id) :
|
||||
Subscriber(id, stateMachine)
|
||||
{
|
||||
mIsInactive = false;
|
||||
}
|
||||
inline virtual void setIPAddresses(uint32_t &v4, char* v6) {}
|
||||
virtual Subscriber* clone()
|
||||
{return new DSSubscriber(mStateMachine, ID);}
|
||||
virtual bool notifyRsrcStatus(Notification ¬ification);
|
||||
inline virtual bool waitForCloseComplete() { return true; }
|
||||
virtual void setInactive();
|
||||
inline virtual bool isInactive()
|
||||
{ return mIsInactive; }
|
||||
inline virtual ~DSSubscriber(){}
|
||||
inline virtual char *whoami() {return (char*)"DSSubscriber";}
|
||||
};
|
||||
|
||||
#endif //__LOC_ENG_AGPS_H__
|
||||
|
|
|
@ -108,7 +108,9 @@ static loc_name_val_s_type loc_eng_msgs[] =
|
|||
NAME_VAL( LOC_ENG_MSG_LPP_CONFIG ),
|
||||
NAME_VAL( ULP_MSG_INJECT_RAW_COMMAND ),
|
||||
NAME_VAL( LOC_ENG_MSG_A_GLONASS_PROTOCOL ),
|
||||
NAME_VAL( LOC_ENG_MSG_LOC_INIT )
|
||||
NAME_VAL( LOC_ENG_MSG_LOC_INIT ),
|
||||
NAME_VAL( LOC_ENG_MSG_REQUEST_SUPL_ES ),
|
||||
NAME_VAL( LOC_ENG_MSG_CLOSE_DATA_CALL)
|
||||
};
|
||||
static int loc_eng_msgs_num = sizeof(loc_eng_msgs) / sizeof(loc_name_val_s_type);
|
||||
|
||||
|
|
|
@ -597,6 +597,23 @@ struct loc_eng_msg_request_atl : public loc_eng_msg {
|
|||
}
|
||||
};
|
||||
|
||||
struct loc_eng_msg_request_supl_es : public loc_eng_msg {
|
||||
const int handle;
|
||||
inline loc_eng_msg_request_supl_es(void* instance, int hndl) :
|
||||
loc_eng_msg(instance, LOC_ENG_MSG_REQUEST_SUPL_ES),
|
||||
handle(hndl)
|
||||
{
|
||||
LOC_LOGV("handle: %d\n", handle);
|
||||
}
|
||||
};
|
||||
|
||||
struct loc_eng_msg_close_data_call: public loc_eng_msg {
|
||||
inline loc_eng_msg_close_data_call(void *instance) :
|
||||
loc_eng_msg(instance, LOC_ENG_MSG_CLOSE_DATA_CALL)
|
||||
{
|
||||
LOC_LOGV("%s:%d]Close data call: ", __func__, __LINE__);
|
||||
}
|
||||
};
|
||||
struct loc_eng_msg_release_atl : public loc_eng_msg {
|
||||
const int handle;
|
||||
inline loc_eng_msg_release_atl(void* instance, int hndl) :
|
||||
|
@ -722,12 +739,12 @@ struct loc_eng_msg_inject_xtra_data : public loc_eng_msg {
|
|||
|
||||
#ifdef FEATURE_IPV6
|
||||
struct loc_eng_msg_atl_open_success : public loc_eng_msg {
|
||||
const AGpsStatusValue agpsType;
|
||||
const AGpsType agpsType;
|
||||
const int length;
|
||||
char* const apn;
|
||||
const AGpsBearerType bearerType;
|
||||
inline loc_eng_msg_atl_open_success(void* instance,
|
||||
AGpsStatusValue atype,
|
||||
AGpsType atype,
|
||||
const char* name,
|
||||
int len,
|
||||
AGpsBearerType btype) :
|
||||
|
@ -794,9 +811,9 @@ struct loc_eng_msg_atl_open_failed : public loc_eng_msg {
|
|||
|
||||
#ifdef FEATURE_IPV6
|
||||
struct loc_eng_msg_atl_closed : public loc_eng_msg {
|
||||
const AGpsStatusValue agpsType;
|
||||
const AGpsType agpsType;
|
||||
inline loc_eng_msg_atl_closed(void* instance,
|
||||
AGpsStatusValue atype) :
|
||||
AGpsType atype) :
|
||||
loc_eng_msg(instance, LOC_ENG_MSG_ATL_CLOSED),
|
||||
agpsType(atype)
|
||||
{
|
||||
|
|
|
@ -134,6 +134,12 @@ enum loc_eng_msg_ids_t {
|
|||
|
||||
//Message is sent by LOC to do LOC INIT
|
||||
LOC_ENG_MSG_LOC_INIT,
|
||||
|
||||
/*Message is sent by modem to request emergency call setup*/
|
||||
LOC_ENG_MSG_REQUEST_SUPL_ES,
|
||||
|
||||
/*Ask the DS client to close the data call by releasing the handle*/
|
||||
LOC_ENG_MSG_CLOSE_DATA_CALL,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -15,7 +15,8 @@ LOCAL_SHARED_LIBRARIES := \
|
|||
libqmi_csi \
|
||||
libqmi_common_so \
|
||||
libloc_adapter \
|
||||
libgps.utils
|
||||
libgps.utils \
|
||||
libds_api
|
||||
|
||||
LOCAL_SRC_FILES += \
|
||||
LocApiV02Adapter.cpp \
|
||||
|
@ -41,7 +42,8 @@ LOCAL_C_INCLUDES := \
|
|||
$(TARGET_OUT_HEADERS)/libloc_eng \
|
||||
$(TARGET_OUT_HEADERS)/qmi-framework/inc \
|
||||
$(TARGET_OUT_HEADERS)/qmi/inc \
|
||||
$(TARGET_OUT_HEADERS)/gps.utils
|
||||
$(TARGET_OUT_HEADERS)/gps.utils \
|
||||
$(TARGET_OUT_HEADERS)/ds_api
|
||||
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#include "LocApiAdapter.h"
|
||||
#include "loc_util_log.h"
|
||||
|
||||
|
||||
/* Default session id ; TBD needs incrementing for each */
|
||||
#define LOC_API_V02_DEF_SESSION_ID (1)
|
||||
|
||||
|
@ -160,6 +159,7 @@ locClientCallbacksType globalCallbacks =
|
|||
|
||||
/* Constructor for LocApiV02Adapter */
|
||||
LocApiV02Adapter :: LocApiV02Adapter(LocEng &locEng):
|
||||
dsClientHandle(NULL),
|
||||
LocApiAdapter(locEng), clientHandle( LOC_CLIENT_INVALID_HANDLE_VALUE),
|
||||
eventMask(convertMask(locEng.eventMask))
|
||||
{
|
||||
|
@ -1059,6 +1059,7 @@ enum loc_api_adapter_err LocApiV02Adapter :: atlOpenStatus(
|
|||
{
|
||||
conn_status_req.statusType = eQMI_LOC_SERVER_REQ_STATUS_SUCCESS_V02;
|
||||
|
||||
if(apn != NULL)
|
||||
strlcpy(conn_status_req.apnProfile.apnName, apn,
|
||||
sizeof(conn_status_req.apnProfile.apnName) );
|
||||
|
||||
|
@ -1068,16 +1069,23 @@ enum loc_api_adapter_err LocApiV02Adapter :: atlOpenStatus(
|
|||
case AGPS_APN_BEARER_IPV4:
|
||||
conn_status_req.apnProfile.pdnType =
|
||||
eQMI_LOC_APN_PROFILE_PDN_TYPE_IPV4_V02;
|
||||
conn_status_req.apnProfile_valid = 1;
|
||||
break;
|
||||
|
||||
case AGPS_APN_BEARER_IPV6:
|
||||
conn_status_req.apnProfile.pdnType =
|
||||
eQMI_LOC_APN_PROFILE_PDN_TYPE_IPV6_V02;
|
||||
conn_status_req.apnProfile_valid = 1;
|
||||
break;
|
||||
|
||||
case AGPS_APN_BEARER_IPV4V6:
|
||||
conn_status_req.apnProfile.pdnType =
|
||||
eQMI_LOC_APN_PROFILE_PDN_TYPE_IPV4V6_V02;
|
||||
conn_status_req.apnProfile_valid = 1;
|
||||
break;
|
||||
|
||||
case AGPS_APN_BEARER_INVALID:
|
||||
conn_status_req.apnProfile_valid = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1089,7 +1097,6 @@ enum loc_api_adapter_err LocApiV02Adapter :: atlOpenStatus(
|
|||
eQMI_LOC_APN_PROFILE_PDN_TYPE_IPV4_V02;
|
||||
#endif
|
||||
|
||||
conn_status_req.apnProfile_valid = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1523,7 +1530,6 @@ enum loc_api_adapter_err LocApiV02Adapter :: setAGLONASSProtocol(unsigned long a
|
|||
return LOC_API_ADAPTER_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Convert event mask from loc eng to loc_api_v02 format */
|
||||
locClientEventMaskType LocApiV02Adapter :: convertMask(
|
||||
LOC_API_ADAPTER_EVENT_MASK_T mask)
|
||||
|
@ -1920,22 +1926,25 @@ void LocApiV02Adapter :: reportAtlRequest(
|
|||
{
|
||||
case eQMI_LOC_WWAN_TYPE_INTERNET_V02:
|
||||
agpsType = AGPS_TYPE_WWAN_ANY;
|
||||
LocApiAdapter::requestATL(connHandle, agpsType);
|
||||
break;
|
||||
|
||||
case eQMI_LOC_WWAN_TYPE_AGNSS_V02:
|
||||
agpsType = AGPS_TYPE_SUPL;
|
||||
LocApiAdapter::requestATL(connHandle, agpsType);
|
||||
break;
|
||||
case eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02:
|
||||
LocApiAdapter::requestSuplES(connHandle);
|
||||
break;
|
||||
|
||||
default:
|
||||
agpsType = AGPS_TYPE_WWAN_ANY;
|
||||
LocApiAdapter::requestATL(connHandle, agpsType);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
agpsType = AGPS_TYPE_SUPL;
|
||||
#endif
|
||||
LocApiAdapter::requestATL(connHandle, agpsType);
|
||||
#endif
|
||||
}
|
||||
|
||||
// service the ATL close request
|
||||
else if (server_request_ptr->requestType == eQMI_LOC_SERVER_REQUEST_CLOSE_V02)
|
||||
{
|
||||
|
@ -2255,3 +2264,98 @@ LocApiAdapter* getLocApiAdapter(LocEng &locEng)
|
|||
{
|
||||
return(new LocApiV02Adapter(locEng));
|
||||
}
|
||||
|
||||
static void ds_client_global_event_cb(ds_client_status_enum_type result,
|
||||
void *loc_adapter_cookie)
|
||||
{
|
||||
LocApiV02Adapter *locApiV02AdapterInstance =
|
||||
(LocApiV02Adapter *)loc_adapter_cookie;
|
||||
locApiV02AdapterInstance->ds_client_event_cb(result);
|
||||
return;
|
||||
}
|
||||
|
||||
void LocApiV02Adapter::ds_client_event_cb(ds_client_status_enum_type result)
|
||||
{
|
||||
if(result == E_DS_CLIENT_DATA_CALL_CONNECTED) {
|
||||
LOC_LOGD("%s:%d]: Emergency call is up", __func__, __LINE__);
|
||||
LocApiAdapter::reportDataCallOpened();
|
||||
}
|
||||
else if(result == E_DS_CLIENT_DATA_CALL_DISCONNECTED) {
|
||||
LOC_LOGE("%s:%d]: Emergency call is stopped", __func__, __LINE__);
|
||||
LocApiAdapter::reportDataCallClosed();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ds_client_cb_data ds_client_cb{
|
||||
ds_client_global_event_cb
|
||||
};
|
||||
|
||||
int LocApiV02Adapter :: openAndStartDataCall()
|
||||
{
|
||||
enum loc_api_adapter_err ret;
|
||||
int profile_index;
|
||||
ds_client_status_enum_type result = ds_client_open_call(&dsClientHandle,
|
||||
&ds_client_cb,
|
||||
(void *)this,
|
||||
&profile_index);
|
||||
if(result == E_DS_CLIENT_SUCCESS) {
|
||||
result = ds_client_start_call(dsClientHandle, profile_index);
|
||||
|
||||
if(result == E_DS_CLIENT_SUCCESS) {
|
||||
LOC_LOGD("%s:%d]: Request to start Emergency call sent\n",
|
||||
__func__, __LINE__);
|
||||
ret = LOC_API_ADAPTER_ERR_SUCCESS;
|
||||
}
|
||||
else {
|
||||
LOC_LOGE("%s:%d]: Unable to bring up emergency call using DS. ret = %d",
|
||||
__func__, __LINE__, (int)ret);
|
||||
ret = LOC_API_ADAPTER_ERR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
else if(result == E_DS_CLIENT_RETRY_LATER) {
|
||||
LOC_LOGE("%s:%d]: Could not start emergency call. Retry after delay\n",
|
||||
__func__, __LINE__);
|
||||
ret = LOC_API_ADAPTER_ERR_ENGINE_BUSY;
|
||||
}
|
||||
else {
|
||||
LOC_LOGE("%s:%d]: Unable to bring up emergency call using DS. ret = %d",
|
||||
__func__, __LINE__, (int)ret);
|
||||
ret = LOC_API_ADAPTER_ERR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
void LocApiV02Adapter :: stopDataCall()
|
||||
{
|
||||
ds_client_status_enum_type ret =
|
||||
ds_client_stop_call(dsClientHandle);
|
||||
if (ret == E_DS_CLIENT_SUCCESS) {
|
||||
LOC_LOGD("%s:%d]: Request to Close SUPL ES call sent\n", __func__, __LINE__);
|
||||
}
|
||||
else {
|
||||
if (ret == E_DS_CLIENT_FAILURE_INVALID_HANDLE) {
|
||||
LOC_LOGE("%s:%d]: Conn handle not found for SUPL ES",
|
||||
__func__, __LINE__);
|
||||
}
|
||||
LOC_LOGE("%s:%d]: Could not close SUPL ES call. Ret: %d\n"
|
||||
,__func__, __LINE__, ret);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void LocApiV02Adapter :: closeDataCall()
|
||||
{
|
||||
ds_client_close_call(&dsClientHandle);
|
||||
LOC_LOGD("%s:%d]: Release data client handle\n", __func__, __LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
int LocApiV02Adapter :: initDataServiceClient()
|
||||
{
|
||||
int ret=0;
|
||||
ret = ds_client_init();
|
||||
LOC_LOGD("%s:%d]: ret = %d\n", __func__, __LINE__,ret);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "loc_api_v02_client.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "ds_client.h"
|
||||
|
||||
/* This class derives from the LocApiAdapter class.
|
||||
The members of this class are responsible for converting
|
||||
|
@ -40,6 +41,8 @@
|
|||
This class also implements some of the virtual functions that
|
||||
handle the requests from loc engine. */
|
||||
class LocApiV02Adapter : public LocApiAdapter {
|
||||
/*ds client handle*/
|
||||
dsClientHandleType dsClientHandle;
|
||||
|
||||
/* loc api v02 handle*/
|
||||
locClientHandleType clientHandle;
|
||||
|
@ -110,6 +113,12 @@ public:
|
|||
void errorCb(locClientHandleType handle,
|
||||
locClientErrorEnumType errorId);
|
||||
|
||||
void ds_client_event_cb(ds_client_status_enum_type result);
|
||||
int openAndStartDataCall();
|
||||
void stopDataCall();
|
||||
void closeDataCall();
|
||||
int initDataServiceClient();
|
||||
|
||||
virtual enum loc_api_adapter_err reinit();
|
||||
|
||||
virtual enum loc_api_adapter_err startFix();
|
||||
|
|
Loading…
Reference in a new issue