Add mbtk/liblynq_lib_v2/ mbtk/libql_lib_v2/
Change-Id: Idbb802cd805b34603ccf65bff9818725a6955e51
diff --git a/mbtk/libql_lib_v2/src/ql_call.c b/mbtk/libql_lib_v2/src/ql_call.c
new file mode 100755
index 0000000..700f93d
--- /dev/null
+++ b/mbtk/libql_lib_v2/src/ql_call.c
@@ -0,0 +1,821 @@
+/**
+ * \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;
+}