android_device_xiaomi_sdm66.../loc_api/ds_api/ds_client.c
Tushar Janefalkar 0f66892e50 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
2013-06-20 10:21:41 -07:00

704 lines
26 KiB
C

/* 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, &notifier);
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,
&param_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;
}