blob: 700f93d7cac9353e5b3b505c429b5e5c1288c02c [file] [log] [blame]
/**
* \file ql_call.c
* \brief A Documented file.
*
* Detailed description
* \Author: js.wang<js.wang@mobiletek.cn>
* \Version: 1.0.0
* \Date: 2022-01-18
*/
#include "ql/ql_mcm_call.h"
#include <telephony/ril.h>
#include <telephony/ril_ext.h>
#include "ql/ql_mcm.h"
#include "rilutil.h"
#include "mbtk_log.h"
// #define DEBUG 1
#ifdef DEBUG
#define mbtk_call_log(...) printf(__VA_ARGS__)
#else
#define mbtk_call_log(...)
#endif
struct ql_call_ubus_t
{
struct ubus_context *ctx;
/* RIL */
struct ubus_subscriber ril_ind_event;
uint32_t ril_subscriber_id;
uint32_t ril_request_id;
uint8_t auto_answer;
uint32_t answer_time;
pthread_t call_status_pthread;
ql_mcm_voice_calls_state_t call_state;
QL_VoiceCall_CommonStateHandlerFunc_t _voice_call_common_state_handler;
QL_VoiceCall_StateHandlerFunc_t _voice_call_state_handler;
};
const char *RIL_MessageMap[] =
{
"RIL_CALL_ACTIVE", //0,
"RIL_CALL_HOLDING", //1,
"RIL_CALL_DIALING", //2, /* MO call only */
"RIL_CALL_ALERTING", //3, /* MO call only */
"RIL_CALL_INCOMING", //4, /* MT call only */
"RIL_CALL_WAITING", //5, /* MT call only */
"RIL_CALL_OFFERING", //6, /* MT call offering (call setup) */
"RIL_CALL_DISCONNECTING",//7, /* call in disconnect procedure */
"RIL_CALL_DISCONNECTED" //8, /* call is disconnected */
};
static struct ql_call_ubus_t *ql_call_ubus = NULL;
static void ql_voice_call_answer(struct uloop_timeout *timeout);
static struct uloop_timeout voice_call_answer_timeout =
{
.cb = ql_voice_call_answer,
};
static void ql_voice_call_answer(struct uloop_timeout *timeout)
{
QL_Voice_Call_Answer(ql_call_ubus, 0);
// uloop_timeout_set(timeout, 2000);
return;
}
int ql_call_handle_ril_ind(struct ubus_context *ctx, unsigned int rilid, unsigned int rilerror, char *data, int data_len)
{
UNUSED(data_len);
UNUSED(ctx);
int datalen = 0, callID = 0;
int ret = 0;
if (rilerror) {
return -1;
}
mbtk_call_log("call_handle_ril_ind: rcv %d\n", rilid);
switch(rilid)
{
case RIL_UNSOL_ECALLDATA: //+ecalldata
// ecallHandleEcalldata(data);
break;
case RIL_UNSOL_ECALLONLY: //+ecallonly
// ecallHandleEcallonly(data);
break;
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED_EXT: /*"CC" 1510*/
{
RIL_Call *rilCall = (RIL_Call *)data;
callID = rilCall->index;
mbtk_call_log("%s: id %d=RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED_EXT (len=%d) (state=%s), call index=%d\n",
__FUNCTION__, rilid, datalen, RIL_MessageMap[(int)rilCall->state], callID);
mbtk_call_log("Received from Ril, name=%s, num=%s\n", rilCall->name, rilCall->number);
ql_call_ubus->call_state.calls_len = 1;
ql_call_ubus->call_state.calls[0].call_id;
memcpy(ql_call_ubus->call_state.calls[0].number, rilCall->number, strlen(rilCall->number));
ql_call_ubus->call_state.calls[0].state = rilCall->state;
switch (rilCall->state)
{
//Call connected, for MO & MT both
case RIL_CALL_ACTIVE:
mbtk_call_log("%s, RIL_CALL_ACTIVE, call index=%d connected!!\n", __FUNCTION__, callID);
ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_ACTIVE;
break;
//MT call only
case RIL_CALL_INCOMING:
mbtk_call_log("%s, RIL_CALL_INCOMING!!\n", __FUNCTION__);
ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_INCOMING;
if(!ql_call_ubus->auto_answer)
{
mbtk_call_log("%s, auto_answer:%d!!\n", __FUNCTION__, ql_call_ubus->answer_time);
uloop_timeout_set(&voice_call_answer_timeout, ql_call_ubus->answer_time);
}
break;
//MO call only
case RIL_CALL_ALERTING:
mbtk_call_log("%s, RIL_CALL_ALERTING, call index=%d alerting!!\n", __FUNCTION__, callID);
ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_ALERTING;
break;
case RIL_CALL_WAITING: //MT call only
mbtk_call_log("%s, RIL_CALL_WAITING, call index=%d alerting!!\n", __FUNCTION__, callID);
ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_WAITING;
break;
case RIL_CALL_DISCONNECTED:
mbtk_call_log("%s, RIL_CALL_DISCONNECTED, call index=%d disconnected!!\n", __FUNCTION__, callID);
ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_END;
break;
case RIL_CALL_HOLDING:
ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_HOLDING;
mbtk_call_log("%s, RIL_CALL_HOLDING, call index=%d hold!!\n", __FUNCTION__, callID);
break;
case RIL_CALL_DIALING: //MO call only
ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_DIALING;
mbtk_call_log("%s, RIL_CALL_DIALING, call index=%d hold!!\n", __FUNCTION__, callID);
break;
case RIL_CALL_OFFERING:
case RIL_CALL_DISCONNECTING:
default:
printf("%s, state=%s ignored!!\n", __FUNCTION__, RIL_MessageMap[(int)rilCall->state]);
ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_END;
break;
}
if(ql_call_ubus->_voice_call_common_state_handler && ql_call_ubus)
{
ql_call_ubus->_voice_call_common_state_handler(E_QL_MCM_VOICE_CALL_IND, &ql_call_ubus->call_state, sizeof(ql_mcm_voice_call_ind));
}
}
break;
case RIL_UNSOL_CALL_NO_CARRIER_EXT: /*"CC" 1511*/
mbtk_call_log("%s: id %d=RIL_UNSOL_CALL_NO_CARRIER_EXT (len=%d)\n",
__FUNCTION__, rilid, datalen);
ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_END;
if(ql_call_ubus->_voice_call_common_state_handler && ql_call_ubus)
{
ql_call_ubus->_voice_call_common_state_handler(E_QL_MCM_VOICE_CALL_IND, &ql_call_ubus->call_state, sizeof(ql_mcm_voice_call_ind));
}
break;
case RIL_UNSOL_CALL_RING: /*"CC" 1018*/
printf("%s: id %d=RIL_UNSOL_CALL_RING (len=%d), ignored!!\n",
__FUNCTION__, rilid, datalen);
break;
case RIL_UNSOL_DISCONNECT_CALLID: /*"CC" 1538*/
callID = *(int *)data;
ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_END;
mbtk_call_log("%s: id %d=RIL_UNSOL_DISCONNECT_CALLID (len=%d), call index=%d!\n",
__FUNCTION__, rilid, datalen, *(int *)data);
break;
default:
break;
}
return ret;
}
static void ql_call_requset_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
unsigned int requestid;
unsigned int rilerrno;
void *response = NULL;
int responselen;
int ret = 0;
ret = rilutil_parseResponse(msg, &requestid, &rilerrno, &response, &responselen);
if(ret)
{
fprintf(stderr, "parse blob error\n");
goto done;
}
if(rilerrno)
{
// RIL_REQUEST_RELEASE_CALL
fprintf(stderr, "unsolicited id %d, error code %d\n", requestid, rilerrno);
goto done;
}
//process response here
done:
if(response)
rilutil_freeResponseData(requestid, response, responselen);
return;
}
int ql_call_subscriber_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
UNUSED(ctx);
UNUSED(obj);
UNUSED(req);
UNUSED(method);
unsigned int requestid = 0;
unsigned int rilerrno = 0;
void *response = NULL;
int responselen = 0;
int ret = 0;
ret = rilutil_parseResponse(msg, &requestid, &rilerrno, &response, &responselen);
if (ret)
goto end;
mbtk_call_log("call_subscriber_cb: rcv %d\n", requestid);
ql_call_handle_ril_ind(ctx, requestid, rilerrno, response, responselen);
end:
if (response)
rilutil_freeResponseData(requestid,response,responselen);
return 0;
}
void ql_call_subscriber_remove_cb(struct ubus_context *ctx, struct ubus_subscriber *obj, uint32_t id)
{
UNUSED(ctx);
UNUSED(obj);
UNUSED(id);
mbtk_call_log("ql_call_subscriber_remove_cb\n");
}
static void ql_call_register_ril(void* hdl)
{
static struct ubus_request req;
struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)hdl;
int ret;
if(hdl == NULL || ql_call_ubus == NULL)
{
printf("ARG error or not inited.");
return -1;
}
pthread_detach(pthread_self());
ret = ubus_register_subscriber(voice_call_ubus->ctx, &voice_call_ubus->ril_ind_event);
if (ret) {
printf("call_daemon: Failed to add ecall_subscriber: %s\n", ubus_strerror(ret));
return ret;
}
voice_call_ubus->ril_ind_event.cb = ql_call_subscriber_cb;
voice_call_ubus->ril_ind_event.remove_cb = ql_call_subscriber_remove_cb;
//register for CC ind
if (ubus_lookup_id(voice_call_ubus->ctx, "ril.unsol.cc", &voice_call_ubus->ril_subscriber_id)) {
printf("call_daemon: Failed to look up ril.unsol.cc object\n");
return ret;
}
ubus_subscribe(voice_call_ubus->ctx, &voice_call_ubus->ril_ind_event, voice_call_ubus->ril_subscriber_id);
mbtk_call_log("call_daemon: subscribe ril.unsol.cc object ok\n");
mbtk_call_log("%s!\n", __FUNCTION__);
while(1)
{
uloop_run();
printf("%s uloop_run done!\n", __FUNCTION__);
}
pthread_exit(NULL);
}
/* Init voice module and return h_voice, this should be called before any other APIs */
int QL_Voice_Call_Client_Init(voice_client_handle_type *ph_voice)
{
int id;
// Set call handle.
//*ph_voice = 1;
if(ph_voice == NULL)
{
printf("ARG error or has inited.");
return -1;
}
ql_call_ubus = malloc(sizeof(struct ql_call_ubus_t));
if(NULL == ql_call_ubus)
{
printf("malloc memory error\n");
}
memset(ql_call_ubus, 0, sizeof(struct ql_call_ubus_t));
uloop_init();
ql_call_ubus->ctx = ubus_connect(NULL);
if(!ql_call_ubus->ctx)
{
printf("Failed to connect to ubus");
goto out;
}
ubus_add_uloop(ql_call_ubus->ctx);
if (ubus_lookup_id(ql_call_ubus->ctx, "ril", &ql_call_ubus->ril_request_id)) {
fprintf(stderr, "%s, Failed to look up test object\n", __FUNCTION__);
return -1;
}
ql_call_ubus->auto_answer = E_QL_MCM_VOICE_AUTO_ANSWER_DISABLE;
ql_call_ubus->call_state.calls[0].state = E_QL_MCM_VOICE_CALL_STATE_END;
pthread_create(&ql_call_ubus->call_status_pthread, NULL, (void *)ql_call_register_ril, (void *)ql_call_ubus);
*ph_voice = ql_call_ubus;
return 0;
out:
//uloop_done();
return 0;
}
/* DeInit voice module and release resources, this should be called at last */
int QL_Voice_Call_Client_Deinit(voice_client_handle_type h_voice)
{
int ret;
struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice;
// Free handle.
if(h_voice == NULL || ql_call_ubus == NULL)
{
LOGE("ARG error or not inited.");
printf("ARG error or not inited.");
return -1;
}
ret = pthread_cancel(voice_call_ubus->call_status_pthread);
mbtk_call_log("kill pthread : %d \n", ret);
pthread_join(voice_call_ubus->call_status_pthread, NULL);
do{
ret = pthread_kill(voice_call_ubus->call_status_pthread, 0);
mbtk_call_log("kill pthread: %d \n", ret);
if(ret == ESRCH)
printf("The specified thread does not exist or has terminated\n");
else if(ret == EINVAL)
printf("Useless signal\n");
else
mbtk_call_log("The thread exists\n");
usleep(100000);
}while(0 == ret);
free(h_voice);
ql_call_ubus = NULL;
uloop_done();
ubus_free(voice_call_ubus->ctx);
return 0;
}
/* Add callback function, if any call state changed, handlerPtr will be called to notify App */
int QL_Voice_Call_AddStateHandler(voice_client_handle_type h_voice,
QL_VoiceCall_StateHandlerFunc_t handlerPtr,
void* contextPtr)
{
static struct ubus_request req;
struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice;
int ret;
if(h_voice == NULL || ql_call_ubus == NULL)
{
printf("ARG error or not inited.");
return -1;
}
ret = pthread_kill(voice_call_ubus->call_status_pthread, 0);
mbtk_call_log("kill pthread: %d \n", ret);
if(ret == ESRCH)
mbtk_call_log("The specified thread does not exist or has terminated\n");
else if(ret == EINVAL)
printf("Useless signal\n");
else
mbtk_call_log("The thread exists\n");
if(voice_call_ubus->ril_subscriber_id)
{
voice_call_ubus->_voice_call_state_handler = handlerPtr;
}
else
{
printf("%s error!!\n", __func__);
return -1;
}
return 0;
}
/* Remove callback function, won't receive any notify anymore */
int QL_Voice_Call_RemoveStateHandler(voice_client_handle_type h_voice)
{
struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice;
if(h_voice == NULL || ql_call_ubus == NULL)
{
LOGE("ARG error or not inited.");
return -1;
}
voice_call_ubus->_voice_call_state_handler = NULL;
return 0;
}
/* Add callback function, if any call state changed, handlerPtr will be called to notify App */
int QL_Voice_Call_AddCommonStateHandler(voice_client_handle_type h_voice,
QL_VoiceCall_CommonStateHandlerFunc_t handlerPtr)
{
static struct ubus_request req;
struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice;
int ret;
if(h_voice == NULL || ql_call_ubus == NULL)
{
LOGE("ARG error or not inited.");
return -1;
}
ret = pthread_kill(voice_call_ubus->call_status_pthread, 0);
mbtk_call_log("kill pthread: %d \n", ret);
if(ret == ESRCH)
mbtk_call_log("The specified thread does not exist or has terminated\n");
else if(ret == EINVAL)
printf("Useless signal\n");
else
mbtk_call_log("The thread exists\n");
if(voice_call_ubus->ril_subscriber_id)
{
voice_call_ubus->_voice_call_common_state_handler = handlerPtr;
}
else
{
printf("%s error!!\n", __func__);
return -1;
}
return 0;
}
/* Remove callback function, won't receive any notify anymore */
int QL_Voice_Call_RemoveCommonStateHandler(voice_client_handle_type h_voice)
{
struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice;
if(h_voice == NULL || ql_call_ubus == NULL)
{
LOGE("ARG error or not inited.");
return -1;
}
voice_call_ubus->_voice_call_common_state_handler = NULL;
return 0;
}
/* Start call and return call_id, this can be used in the later */
int QL_Voice_Call_Start(voice_client_handle_type h_voice,
E_QL_VCALL_ID_T simId,
char* phone_number, ///< [IN] Destination identifier for the voice
int *call_id) ///< [OUT] call id
{
static struct ubus_request req;
struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice;
static struct blob_buf b;
int id, ret;
RIL_Dial dial_data;
if(h_voice == NULL || ql_call_ubus == NULL)
{
printf("ARG error or not inited.");
return -1;
}
if(voice_call_ubus->call_state.calls[0].state == E_QL_MCM_VOICE_CALL_STATE_ACTIVE ||
voice_call_ubus->call_state.calls[0].state == E_QL_MCM_VOICE_CALL_STATE_INCOMING ||
voice_call_ubus->call_state.calls[0].state == E_QL_MCM_VOICE_CALL_STATE_ALERTING)
{
printf("A call already exists, Voice Call incoming or active!!\n");
return -1;
}
memset(&dial_data, 0, sizeof(RIL_Dial));
dial_data.address = phone_number;
printf("call number %s\n", dial_data.address);
if (ubus_lookup_id(ql_call_ubus->ctx, "ril", &ql_call_ubus->ril_request_id)) {
fprintf(stderr, "%s, Failed to look up test object\n", __FUNCTION__);
return -1;
}
rilutil_makeRequestBlob(&b, RIL_REQUEST_DIAL, &dial_data, 0);
ret = ubus_invoke(voice_call_ubus->ctx, voice_call_ubus->ril_request_id, "ril_request", b.head, ql_call_requset_cb, 0,0);
if(ret != 0)
{
printf("sim_get_imsi,ubus_invoke Failed %s\n", ubus_strerror(ret));
return E_QL_ERROR_GENERIC;
}
return 0;
}
/* End call of call_id, which returned by QL_Voice_Call_Start or callback func register via QL_Voice_Call_AddStateHandler */
int QL_Voice_Call_End(voice_client_handle_type h_voice,
int call_id) ///< [IN] call id, return by QL_Voice_Start
{
static struct ubus_request req;
static struct blob_buf b;
int ret;
struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice;
if(h_voice == NULL || ql_call_ubus == NULL)
{
printf("ARG error or not inited.");
return -1;
}
mbtk_call_log("Voice Call State:%s, %d\n", voice_call_ubus->call_state.calls[0].number, voice_call_ubus->call_state.calls[0].state);
if(voice_call_ubus->call_state.calls[0].state != E_QL_MCM_VOICE_CALL_STATE_ACTIVE &&
voice_call_ubus->call_state.calls[0].state != E_QL_MCM_VOICE_CALL_STATE_INCOMING &&
voice_call_ubus->call_state.calls[0].state != E_QL_MCM_VOICE_CALL_STATE_ALERTING)
{
printf("No Voice Call incoming or active!!\n");
return -1;
}
//use rilutil's API, just a example
rilutil_makeRequestBlob(&b, RIL_REQUEST_RELEASE_CALL, NULL, 0);
ret = ubus_invoke(voice_call_ubus->ctx, voice_call_ubus->ril_request_id, "ril_request", b.head, ql_call_requset_cb, 0,0);
if(ret != 0)
{
printf("sim_get_imsi,ubus_invoke Failed %s", ubus_strerror(ret));
return E_QL_ERROR_GENERIC;
}
return 0;
}
/* Answer the call of call_id, which returned by callback func register via QL_Voice_Call_AddStateHandler */
int QL_Voice_Call_Answer(voice_client_handle_type h_voice,
int call_id )
{
static struct ubus_request req;
static struct blob_buf b;
struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice;
int ret;
if(h_voice == NULL || ql_call_ubus == NULL)
{
printf("ARG error or not inited.");
return -1;
}
rilutil_makeRequestBlob(&b, RIL_REQUEST_ANSWER, NULL, 0);
ret = ubus_invoke(voice_call_ubus->ctx, voice_call_ubus->ril_request_id, "ril_request", b.head, ql_call_requset_cb, 0,0);
if(ret != 0)
{
printf("ql call, ubus_invoke Failed %s", ubus_strerror(ret));
return E_QL_ERROR_GENERIC;
}
return 0;
}
int QL_Voice_Call_Hold( voice_client_handle_type h_voice)
{
static struct ubus_request req;
struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice;
static struct blob_buf b;
int ret;
if(h_voice == NULL || ql_call_ubus == NULL)
{
printf("ARG error or not inited.");
return -1;
}
rilutil_makeRequestBlob(&b, RIL_REQUEST_HANGUP, NULL, 0);
ret = ubus_invoke(voice_call_ubus->ctx, voice_call_ubus->ril_request_id, "ril_request", b.head, ql_call_requset_cb, 0,0);
if(ret != 0)
{
printf("ql call, ubus_invoke Failed %s", ubus_strerror(ret));
return E_QL_ERROR_GENERIC;
}
return 0;
}
int QL_Voice_Call_UnHold( voice_client_handle_type h_voice)
{
return 0;
}
int QL_Voice_Call_Conference( voice_client_handle_type h_voice)
{
static struct ubus_request req;
struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice;
static struct blob_buf b;
int ret;
if(h_voice == NULL || ql_call_ubus == NULL)
{
printf("ARG error or not inited.");
return -1;
}
rilutil_makeRequestBlob(&b, RIL_REQUEST_CONFERENCE, NULL, 0);
ret = ubus_invoke(voice_call_ubus->ctx, voice_call_ubus->ril_request_id, "ril_request", b.head, ql_call_requset_cb, 0,0);
if(ret != 0)
{
printf("ql call, ubus_invoke Failed %s", ubus_strerror(ret));
return E_QL_ERROR_GENERIC;
}
return 0;
}
int QL_Voice_Call_EndConference( voice_client_handle_type h_voice)
{
return 0;
}
int QL_Voice_Call_Ecall(voice_client_handle_type h_voice,
E_QL_VCALL_ID_T simId,
char* phone_number,
ql_mcm_ecall_info ecall_info,
int *call_id)
{
// RIL_REQUEST_SET_CECALL
// RIL_REQUEST_GET_CECALL
// RIL_REQUEST_SET_ECALLONLY
// RIL_REQUEST_GET_ECALLONLY
// RIL_REQUEST_SET_ECALLREG
static struct ubus_request req;
struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice;
static struct blob_buf b;
int ret;
if(h_voice == NULL || ql_call_ubus == NULL)
{
printf("ARG error or not inited.");
return -1;
}
//use rilutil's API, just a example
rilutil_makeRequestBlob(&b, RIL_REQUEST_CONFERENCE, NULL, 0);
ret = ubus_invoke(voice_call_ubus->ctx, voice_call_ubus->ril_request_id, "ril_request", b.head, ql_call_requset_cb, 0,0);
if(ret != 0)
{
printf("ql call, ubus_invoke Failed %s", ubus_strerror(ret));
return E_QL_ERROR_GENERIC;
}
return 0;
}
int QL_Voice_Call_SetAutoAnswer(voice_client_handle_type h_voice,
E_QL_MCM_VOICE_AUTO_ANSWER_T eAnswerType,
uint32_t uAnswerTime)
{
struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice;
if(h_voice == NULL || ql_call_ubus == NULL)
{
printf("ARG error or not inited.");
return -1;
}
voice_call_ubus->auto_answer = eAnswerType;
voice_call_ubus->answer_time = uAnswerTime;
return 0;
}
int QL_Voice_Call_Ecall_HangUp(voice_client_handle_type h_voice)
{
return 0;
}
int QL_Voice_Call_Ecall_UpdateMsd(voice_client_handle_type h_voice,const char *msd,uint32_t msd_len)
{
return 0;
}
//Ecall Push caommand
int QL_Voice_Call_Ecall_MsdPush(voice_client_handle_type h_voice,
E_QL_MCM_ECALL_STATE_T *ecall_state)
{
return 0;
}
//Get Ecall config info
int QL_Voice_Call_Ecall_GetConfigInfo(voice_client_handle_type h_voice,
ql_mcm_ecall_config_info *ecall_config)
{
// RIL_REQUEST_SET_ECALLCFG
// RIL_REQUEST_GET_ECALLCFG
return 0;
}
int QL_Voice_Call_Ecall_SetConfigInfo(voice_client_handle_type h_voice,
E_QL_MCM_ECALL_CONFIG_T ecall_config_type,
uint8_t value)
{
return 0;
}
//Cancel dial
int QL_Voice_Call_CancelDial( voice_client_handle_type h_voice)
{
static struct ubus_request req;
static struct blob_buf b;
int ret;
struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice;
if(h_voice == NULL || ql_call_ubus == NULL)
{
printf("ARG error or not inited.");
return -1;
}
//use rilutil's API, just a example
rilutil_makeRequestBlob(&b, RIL_REQUEST_RELEASE_CALL, NULL, 0);
ret = ubus_invoke(voice_call_ubus->ctx, voice_call_ubus->ril_request_id, "ril_request", b.head, ql_call_requset_cb, 0,0);
if(ret != 0)
{
printf("sim_get_imsi,ubus_invoke Failed %s", ubus_strerror(ret));
return E_QL_ERROR_GENERIC;
}
return 0;
}
//VTS API
int QL_Voice_Call_Dtmf(voice_client_handle_type h_voice, uint8_t digit, int call_id)
{
static struct ubus_request req;
struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice;
static struct blob_buf b;
int ret;
char code = digit;
if(h_voice == NULL || ql_call_ubus == NULL)
{
printf("ARG error or not inited.");
return -1;
}
rilutil_makeRequestBlob(&b, RIL_REQUEST_DTMF, &code, 0);
ret = ubus_invoke(voice_call_ubus->ctx, voice_call_ubus->ril_request_id, "ril_request", b.head, ql_call_requset_cb, 0,0);
if(ret != 0)
{
printf("ql call, ubus_invoke Failed %s", ubus_strerror(ret));
return E_QL_ERROR_GENERIC;
}
return 0;
}
int QL_Voice_Call_GetCallStatus
(
int h_voice,
int call_id, // If call_id<0, means to get all calls state, or get specified call_id info
ql_mcm_voice_calls_state_t *pt_callstate
)
{
struct ql_call_ubus_t *voice_call_ubus = (struct ql_call_ubus_t *)h_voice;
if(h_voice == NULL || ql_call_ubus == NULL)
{
printf("ARG error or not inited.");
return -1;
}
memcpy((void *)pt_callstate, &voice_call_ubus->call_state, sizeof(ql_mcm_voice_calls_state_t));
return 0;
}
//Set forwarding
int QL_Voice_Call_SetForwarding
(
int h_voice,
E_QL_MCM_VOICE_CALL_SERVICE_T service,
E_QL_MCM_VOICE_CALL_FORWARDING_REASON_T reason,
char *number
)
{
return 0;
}
//Get forwarding status
int QL_Voice_Call_GetForwardingStatus(
int h_voice,
E_QL_MCM_VOICE_CALL_FORWARDING_REASON_T reason,
ql_mcm_voice_call_forwarding_status_list_t *pt_status)
{
return 0;
}
//Set voice call waiting
int QL_Voice_Call_SetWaiting
(
int h_voice,
ql_mcm_voice_call_waiting_service_t e_service
)
{
// RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND
return 0;
}
//Get voice call waiting status
int QL_Voice_Call_GetWaitingStatus
(
int h_voice,
ql_mcm_voice_call_waiting_service_t *pe_service
)
{
return 0;
}