Add basic change for v1453

Change-Id: I9497a61bbc3717f66413794a4e7dee0347c0bc33
diff --git a/mbtk/libql_lib_v2_rilv2/ql_voice.c b/mbtk/libql_lib_v2_rilv2/ql_voice.c
new file mode 100755
index 0000000..367753d
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_voice.c
@@ -0,0 +1,869 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_voice.h
+  @brief Voice service API.
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  Copyright (c) 2019 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
+  Quectel Wireless Solution Proprietary and Confidential.
+-------------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  EDIT HISTORY
+  This section contains comments describing changes made to the file.
+  Notice that changes are listed in reverse chronological order.
+  $Header: $
+  when       who          what, where, why
+  --------   ---          ----------------------------------------------------------
+  20210622   Rambo.shan   Added Voice DSDA API.
+  20210203   Rambo.shan   Added Voice bind API for DSDA.
+  20210104   Rambo.shan   Added DTMF event indication.
+  20200928   Rambo.shan   Added eCall set option of T3.
+  20200907   Rambo.shan   Added SETUP voice state.
+  20200622   Rambo.shan   Add eCall auto answer function
+  20191225   solomon.cui  Modify fucntion description.
+  20191111   solomon.cui  Add eCall APIs.
+  20190815   solomon.cui  Add service type for sending message.
+  20190625   solomon.cui  Created.
+-------------------------------------------------------------------------------------------------*/
+#include "mbtk_type.h"
+#include "mbtk_ril_api.h"
+#include "mbtk_log.h"
+#include "ql_voice.h"
+#include "ql_type.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/epoll.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+#include <string.h>
+#include <fcntl.h>
+#include <time.h>
+
+#define MBTK_ERR_OK             0
+
+typedef struct {
+    mbtk_ril_handle*         handle;
+    int                         state_t;
+    ql_voice_record_array_t     record_array;
+    ql_voice_call_cb_f          call_cb;
+    ql_voice_service_error_cb_f server_cb;
+}ql_voice_info_handle_t;
+
+
+static ql_voice_info_handle_t* voice_handle = NULL;
+
+
+typedef struct {
+    mbtk_voice_end_reason_enum mbtk_end_reason;
+    QL_VOICE_END_REASON_E ql_end_reason;
+}end_reason_t;
+
+
+
+end_reason_t g_end_reason[] = {
+{MBTK_VOICE_END_REASON_UNASSIGNED_NUMBER, QL_VOICE_END_REASON_UNASSIGNED_NUMBER}, 
+{MBTK_VOICE_END_REASON_NO_ROUTE_DES, QL_VOICE_END_REASON_NO_ROUTE_TO_DESTINATION}, 
+{MBTK_VOICE_END_REASON_CHANNEL_UNACCEPTABLE, QL_VOICE_END_REASON_CHANNEL_UNACCEPTABLE}, 
+{MBTK_VOICE_END_REASON_OPERATOR_DETERMINED_BARRING, QL_VOICE_END_REASON_OPERATOR_DETERMINED_BARRING}, 
+{MBTK_VOICE_END_REASON_NORMAL_CALL_CLEARING, QL_VOICE_END_REASON_NORMAL_CALL_CLEARING}, 
+{MBTK_VOICE_END_REASON_USER_BUSY, QL_VOICE_END_REASON_USER_BUSY}, 
+
+{MBTK_VOICE_END_REASON_NO_USER_RESPONDING, QL_VOICE_END_REASON_NO_USER_RESPONDING}, 
+{MBTK_VOICE_END_REASON_USER_ALERTING_NO_ANSWER, QL_VOICE_END_REASON_USER_ALERTING_NO_ANSWER}, 
+{MBTK_VOICE_END_REASON_CALL_REJECTED, QL_VOICE_END_REASON_CALL_REJECTED}, 
+{MBTK_VOICE_END_REASON_NUMBER_CHANGED, QL_VOICE_END_REASON_NUMBER_CHANGED}, 
+{MBTK_VOICE_END_REASON_PREEMPTION, QL_VOICE_END_REASON_PREEMPTION}, 
+{MBTK_VOICE_END_REASON_NON_SELECTED_USER_CLEARING, QL_VOICE_END_REASON_NONE}, 
+{MBTK_VOICE_END_REASON_DESTINATION_OUT_OF_ORDER, QL_VOICE_END_REASON_DESTINATION_OUT_OF_ORDER}, 
+{MBTK_VOICE_END_REASON_INVALID_NUMBER_FORMAT, QL_VOICE_END_REASON_INVALID_NUMBER_FORMAT}, 
+{MBTK_VOICE_END_REASON_FACILITY_REJECTED, QL_VOICE_END_REASON_FACILITY_REJECTED}, 
+{MBTK_VOICE_END_REASON_STATUS_ENQUIRY, QL_VOICE_END_REASON_RESP_TO_STATUS_ENQUIRY}, 
+{MBTK_VOICE_END_REASON_NORMAL_UNSPECIFIED, QL_VOICE_END_REASON_NORMAL_UNSPECIFIED}, 
+{MBTK_VOICE_END_REASON_NO_CIRCUIT_AVAILABLE, QL_VOICE_END_REASON_NO_CIRCUIT_OR_CHANNEL_AVAILABLE}, 
+{MBTK_VOICE_END_REASON_NETWORK_OUT_OF_ORDER, QL_VOICE_END_REASON_NETWORK_OUT_OF_ORDER}, 
+{MBTK_VOICE_END_REASON_TEMPORARY_FAILURE, QL_VOICE_END_REASON_TEMPORARY_FAILURE}, 
+{MBTK_VOICE_END_REASON_SWITCHING_EQUIPMENT_CONGESTION, QL_VOICE_END_REASON_SWITCHING_EQUIPMENT_CONGESTION}, 
+{MBTK_VOICE_END_REASON_ACCESS_INFORMATION_DISCARDED, QL_VOICE_END_REASON_ACCESS_INFORMATION_DISCARDED}, 
+{MBTK_VOICE_END_REASON_REQUESTED_CIRCUIT_UNAVAILABLE, QL_VOICE_END_REASON_REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE}, 
+
+{MBTK_VOICE_END_REASON_SERVICE_NOT_AVAILABLE, QL_VOICE_END_REASON_SERVICE_OPTION_NOT_AVAILABLE},
+
+{MBTK_VOICE_END_REASON_END, QL_VOICE_END_REASON_NONE}
+
+};
+
+
+
+    static int end_reason_mbtk_to_ql(char* mbtk_reason, int* ql_reason)
+{
+    int bufefer_i = 0;
+    *ql_reason = QL_VOICE_END_REASON_NONE;
+
+    bufefer_i = atoi(mbtk_reason);
+
+    for(int i = 0; g_end_reason[i].mbtk_end_reason != MBTK_VOICE_END_REASON_END; i++)
+    {
+         if(bufefer_i == g_end_reason[i].mbtk_end_reason)
+         {
+            *ql_reason = g_end_reason[i].ql_end_reason;
+            break;
+         }
+    }
+
+    return 0;
+}
+
+
+static void ql_voice_state_change_cb(const void* data, int data_len)
+{
+    if(NULL == data)
+    {
+        LOGE("[ql_voice_state_change_cb] data is null.");
+        return;
+    }
+
+    if(voice_handle->call_cb == NULL) {
+        LOGW("voice_state_change_cb not set.");
+        return;
+    }
+    
+    mbtk_call_info_t *reg = (mbtk_call_info_t *)data;
+
+    int ql_reason = 0;
+    end_reason_mbtk_to_ql((char*)reg->end_reason, &ql_reason);
+    LOG("ql_voice_state_change_cb ql_reason:%d", ql_reason);
+        
+
+    if(MBTK_RIL_CALL_STATE_DISCONNECT != reg->state)
+    {
+        LOG("ql_voice_state_change_cb : %d, %d, %d, %d, %d, %s, %d, %s", reg->dir1, reg->dir, reg->state, reg->mode, reg->mpty, reg->phone_number, reg->type, reg->end_reason);
+
+        switch(reg->state)
+        {
+            case 0:
+            voice_handle->state_t = QL_VOICE_STATE_ACTIVE;
+            break;
+            case 1:
+            voice_handle->state_t = QL_VOICE_STATE_HOLDING;
+            break;
+            case 2:
+            voice_handle->state_t = QL_VOICE_STATE_DIALING;
+            break;
+            case 3:
+            voice_handle->state_t = QL_VOICE_STATE_ALERTING;
+            break;
+            case 4:
+            voice_handle->state_t = QL_VOICE_STATE_INCOMING;
+            break;
+            case 5:
+            voice_handle->state_t = QL_VOICE_STATE_WAITING;
+            break;
+            case 7:
+            voice_handle->state_t = QL_VOICE_STATE_END;
+            break;
+        }
+
+        if (voice_handle->record_array.records[0].id == 0 || voice_handle->record_array.records[0].id == reg->dir1)
+        {
+            voice_handle->record_array.len = 1;
+            voice_handle->record_array.records[0].id = reg->dir1;
+            voice_handle->record_array.records[0].tech = 1;
+            voice_handle->record_array.records[0].dir = reg->dir;
+            voice_handle->record_array.records[0].end_reason = ql_reason;
+            voice_handle->record_array.records[0].state = voice_handle->state_t;
+            memcpy(voice_handle->record_array.records[0].number, reg->phone_number, strlen(reg->phone_number));
+        }
+        else if (voice_handle->record_array.records[0].id != reg->dir1)
+        {
+            voice_handle->record_array.len = 2;
+            voice_handle->record_array.records[1].id = reg->dir1;
+            voice_handle->record_array.records[1].tech = 1;
+            voice_handle->record_array.records[1].dir = reg->dir;
+            voice_handle->record_array.records[1].end_reason = ql_reason;
+            voice_handle->record_array.records[1].state = voice_handle->state_t;
+            memcpy(voice_handle->record_array.records[1].number, reg->phone_number, strlen(reg->phone_number));
+        }
+
+        voice_handle->call_cb(&voice_handle->record_array);
+    }
+    else
+    {
+        LOGI("RING : call dis connected!");
+        voice_handle->record_array.records[0].end_reason = ql_reason;
+        voice_handle->record_array.records[1].end_reason = ql_reason;
+        if(voice_handle->record_array.records[0].id == reg->dir1)
+        {
+            voice_handle->record_array.records[0].state = QL_VOICE_STATE_END;
+            voice_handle->record_array.records[0].id = 0;
+        }
+        if(voice_handle->record_array.records[1].id == reg->dir1)
+        {
+            voice_handle->record_array.records[1].state = QL_VOICE_STATE_END;
+            voice_handle->record_array.records[1].id = 0;
+            voice_handle->record_array.len = 1;
+        }
+        if (reg->disconnected_id == voice_handle->record_array.records[1].id)
+            voice_handle->call_cb(&voice_handle->record_array);
+        else
+            voice_handle->call_cb(&voice_handle->record_array);
+    }
+
+}
+
+static void ql_voice_server_change_cb(const void* data, int data_len)
+{
+    if(data_len != sizeof(int))
+    {
+        LOGE("[ql_voice_server_change_cb] data_len[%d] than int[%d] fail. ", data_len, sizeof(int));
+    }
+    else
+    {
+        int server_state = *(int *)data;
+        if(server_state == 1 && voice_handle->server_cb)
+        {
+            voice_handle->server_cb(QL_ERR_ABORTED);
+        }
+    }
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Initializes voice service.
+  @return Whether the voice service was initialized successfully.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_init(void)
+{
+     if(NULL == voice_handle)
+    {
+        voice_handle = (ql_voice_info_handle_t*)malloc(sizeof(ql_voice_info_handle_t));
+        memset(voice_handle, 0, sizeof(ql_voice_info_handle_t));
+        voice_handle->record_array.records[0].id = 0;
+        if(NULL == voice_handle)
+        {
+            LOGE("[ql_voice_init] voice handle malloc fail.");
+            return QL_ERR_FAILED;
+        }
+
+        voice_handle->handle = mbtk_ril_open(MBTK_AT_PORT_DEF);
+        if(NULL == voice_handle->handle)
+        {
+            LOGE("[ql_voice_init] mbtk handle init fail.");
+            if(voice_handle)
+            {
+                free(voice_handle);
+                voice_handle = NULL;
+                return QL_ERR_FAILED;
+            }
+        }
+
+        int ret = mbtk_call_state_change_cb_reg( ql_voice_state_change_cb);
+        if(ret != MBTK_ERR_OK)
+        {
+            LOGE("[ql_voice_init] set voice state cb fail.[%d]", ret);
+             if(voice_handle->handle)
+            {
+                mbtk_ril_close(MBTK_AT_PORT_DEF);
+                voice_handle->handle = NULL;
+                return QL_ERR_FAILED;
+            }
+        }
+
+        ret = mbtk_ril_ser_state_change_cb_reg(ql_voice_server_change_cb);
+        if(ret != MBTK_ERR_OK)
+        {
+            LOGE("[ql_sim_init] set sim server cb fail.[%d]", ret);
+             if(voice_handle->handle)
+            {
+                mbtk_ril_close(MBTK_AT_PORT_DEF);
+                voice_handle->handle = NULL;
+                return QL_ERR_FAILED;
+            }
+        }
+
+        voice_handle->call_cb = NULL;
+        voice_handle->server_cb = NULL;
+    }
+     return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Deinitializes voice service.
+  @return Whether the voice service was deinitialized successfully.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_deinit(void)
+{
+    if(NULL == voice_handle)
+    {
+        LOGE("[ql_voice_deinit] voice handle not init.");
+        return QL_ERR_NOT_INIT;
+    }
+
+    int ret = 0;
+    voice_handle->server_cb = NULL;
+    voice_handle->call_cb = NULL;
+
+    if(NULL != voice_handle->handle)
+    {
+        ret = mbtk_ril_close(MBTK_AT_PORT_DEF);
+        if(ret != MBTK_ERR_OK)
+        {
+            LOGE("[ql_voice_deinit] mbtk handle deinit fail.[%d]", ret);
+            return QL_ERR_FAILED;
+        }
+        voice_handle->handle = NULL;
+    }
+
+    if(ret != QL_ERR_OK)
+    {
+        LOGE("[ql_voice_deinit] cb thread free deinit fail.");
+        return QL_ERR_FAILED;
+    }
+
+    free(voice_handle);
+    voice_handle = NULL;
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Dials a call.
+  @param[in] num    phone number to dial.
+  @param[in] len    length of phone number, should be less than
+                    or euqnal to QL_VOICE_MAX_PHONE_NUMBER.
+  @param[out] id    call id.
+  @return Whether a voice call was successfully dialed.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_dial(char *num, int len, uint32_t *id)
+{
+    char* phone_num_t = NULL;
+    mbtk_call_info_t reg = {0};
+    int err;
+
+    if(voice_handle->handle == NULL)
+    {
+        LOGE("ql_voice_call_start call_info_handle NULL");
+        return QL_ERR_FAILED;
+    }
+
+    if (num == NULL)
+    {
+        LOGE("ql_voice_call_start phone_number NULL");
+        return QL_ERR_FAILED;
+
+    }
+
+    phone_num_t  = num;
+
+    err = mbtk_call_start(voice_handle->handle, phone_num_t);
+    if(err)
+    {
+        LOGE("Error : %d\n", err);
+        return QL_ERR_FAILED;
+    }
+    else
+    {
+        LOGI("Call success.");
+    }
+
+    mbtk_call_reg_get(voice_handle->handle, &reg);
+    *id = reg.dir1;
+    LOG("ql_voice_dial call_id: %d\n", reg.dir1, *id);
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Cancels dialing with given id.
+  @param[in] id call id returned from dial.
+  @return Whether the voice call was successfully cancelled.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_cancel_dial(uint32_t id);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  hangup all dialing.
+  @return Whether all voice call were successfully hangup.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_hangup_all(void)
+{
+    int err;
+
+    if(voice_handle->handle == NULL)
+    {
+        LOGE("ql_voice_call_end call_info_handle NULL");
+        return QL_ERR_FAILED;
+    }
+
+    err = mbtk_call_hang(voice_handle->handle);
+    if(err)
+    {
+        LOGE("Error : %d", err);
+        return QL_ERR_FAILED;
+    }
+    else
+    {
+        LOGI("Call hang up a all.");
+    }
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Answers the call.
+  @param[in] id call id returned from dial.
+  @return Whether the voice call was successfully answered.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_answer(uint32_t id)
+{
+    int err;
+
+    if(voice_handle->handle == NULL)
+    {
+        LOGE("ql_voice_call_anser call_info_handle NULL");
+        return QL_ERR_FAILED;
+    }
+
+    err = mbtk_call_answer(voice_handle->handle);
+    if(err)
+    {
+        LOGE("Error : %d", err);
+        return QL_ERR_FAILED;
+    }
+    else
+    {
+        LOGI("Answer success.");
+    }
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Hangs up the call.
+  @param[in] id call id returned from dial.
+  @return Whether the voice call was successfully hung up.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_hangup(uint32_t id);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Holds the call when mutil calls is activated.
+  @param[in] id call id returned from dial.
+  @return Whether the voice call was successfully held.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_hold(uint32_t id);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Releases the call from hold when mutil calls is activated.
+  @param[in] id call id returned from dial.
+  @return Whether the voice call was successfully unheld.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_unhold(uint32_t id);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Gets call records.
+  @param[in] p_arr  pointer to ql_voice_record_array_t.
+  @return Whether the call records were successfully obtained.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_get_records(ql_voice_record_array_t *p_arr)
+{
+    if(NULL == p_arr)
+    {
+        LOGE("ql_voice_get_records p_arr NULL");
+        return QL_ERR_FAILED;
+    }
+    memcpy(p_arr, &voice_handle->record_array, sizeof(voice_handle->record_array));
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Registers or Unregisters forwarding.
+  @param[in] reg    0 - unregister, 1 - register.
+  @param[in] cond   forwarding condition.
+  @param[in] num    phone number.
+  @param[in] len    length of phone numebr.
+  @return Whether the voice call forward was registered or unregistered successfully.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_forwarding(int reg, QL_VOICE_FW_COND_E cond, char *num, int len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Gets forwarding status.
+  @param[in]  cond      forwarding condition.
+  @param[out] p_status  pointer to ql_voice_fw_status_t.
+  @return Whether the voice call forward status was successfully obtained.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_get_forwarding_status(QL_VOICE_FW_COND_E cond, ql_voice_fw_status_t *p_status);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Enables or disables call waiting.
+  @param[in] enable 0 - disable, other - enable.
+  @return Whether the voice call waiting was enabled or disabled successfully.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_waiting(int enable);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Gets call waiting status.
+  @param[out] enabled 0 - waiting is disabled, 1 - waiting is enabled.
+  @return Whether the voice call waiting status was successfully obtained.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_get_waiting_status(int *enabled);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Enables or disables auto answer.
+  @param[in] enable 0 - disable, other - enable.
+  @param[in] sec    wait this `sec' seconds before auto answer.
+  @return Whether the voice call autoanswer was enabled or disabled successfully.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_autoanswer(int enable, uint32_t sec);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Sends a DTMF(Dual Tone Multi Frequency) character over the call ID.
+  @param[in] id call id returned from dial.
+  @param[in] c DTMF character to be sent. Valid DTMF characters are 0-9, A-D, '*', '#'.
+  @return Whether a DTMF character was successfully sent.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_send_dtmf_char(uint32_t id, char c)
+{
+    int ret = 0;
+    int tmp;
+    char callnum_c;
+    mbtk_call_dtmf_info_t *dtmf = NULL;
+
+    if(voice_handle->handle == NULL)
+    {
+        LOGE("ql_voice_set_dtmf call_info_handle NULL");
+        return QL_ERR_FAILED;
+    }
+
+    dtmf = (mbtk_call_dtmf_info_t*)malloc(sizeof(mbtk_call_dtmf_info_t));
+    memset(dtmf,0x00, sizeof(mbtk_call_dtmf_info_t));
+
+    tmp = (int)c;
+
+    callnum_c = c;
+
+    if ((tmp >= 48 && tmp <= 57) || (tmp >= 65 && tmp <= 68) || (tmp == 42) ||  (tmp == 35))
+    {
+        dtmf->duration = 300;
+        dtmf->character = callnum_c;
+
+        ret = mbtk_dtmf_send(voice_handle->handle, dtmf);
+        if (ret)
+        {
+            LOGE("mbtk_dtmf_send Error : %d", ret);
+            ret = QL_ERR_FAILED;
+            goto err;
+        }
+    }
+    else
+    {
+        LOGE("ql_voice_set_dtmf callnum demand ERR");
+        ret = QL_ERR_FAILED;
+        goto err;
+    }
+
+err:
+    free(dtmf);
+    return ret;
+
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Sets voice call callback handler.
+  @param[in] cb call back handler.
+  @return Whether the voice call callback handler was successfully set.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_set_call_cb(ql_voice_call_cb_f cb)
+{
+    if(NULL == voice_handle)
+    {
+        LOGE("[ql_voice_set_msg_recv_cb] voice handle not init.");
+        return QL_ERR_NOT_INIT;
+    }
+
+    voice_handle->call_cb = cb;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Sets voice dtmf callback handler.
+  @param[in] cb call back handler.
+  @return Whether the voice call DTMF repcetion callback handler was successfully set.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_set_dtmf_cb(ql_voice_dtmf_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Dials eCall.
+  @param[in] p_info eCall info.
+  @return Whether a eCall was successfully dialed.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_ecall_dial(ql_voice_ecall_info_t *p_info);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Hangs up eCall.
+  @return Whether the eCall was successfully hung up.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_ecall_hangup(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Updates eCall MSD.
+  @param[in] msd Minimum Set of Data.
+  @param[in] msd_len Length of Minimum Set of Data.
+  @return Whether the eCall MSD was successfully updated.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_ecall_update_msd(const uint8_t *msd, uint32_t msd_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Pushes eCall MSD.
+  @param[out] state eCall state.
+  @return Whether the eCall MSD was successfully pushed.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_ecall_push_msd(QL_VOICE_ECALL_STATE_E *state);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Gets eCall config.
+  @param[in] p_config eCall config.
+  @return Whether the eCall config was successfully obtained.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_ecall_get_config(ql_voice_ecall_config_t *p_config);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Sets eCall config.
+  @param[in] item Items to set.
+  @param[in] p_config eCall config.
+  @return Whether the eCall config was successfully set.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_ecall_set_config(int item, ql_voice_ecall_config_t *p_config);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Sets eCall event callback handler.
+  @param[in] cb call back handler.
+  @return Whether the eCall event callback handler was successfully set.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_ecall_set_event_cb(ql_voice_ecall_event_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Sets eCall status callback handler.
+  @param[in] cb call back handler.
+  @return Whether the eCall status callback handler was successfully set.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_ecall_set_status_cb(ql_voice_ecall_status_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Registration server error callback. Currently, only if the server exits abnormally,
+  the callback function will be executed, and the error code is QL_ERR_ABORTED;
+  @param[in] cb  Callback function
+  @return
+  QL_ERR_OK - successful
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_voice_set_service_error_cb(ql_voice_service_error_cb_f cb)
+{
+     if(NULL == voice_handle)
+    {
+        LOGE("[ql_voice_set_service_error_cb] voice handle not init.");
+        return QL_ERR_NOT_INIT;
+    }
+
+    voice_handle->server_cb = cb;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Binds the current control point to a specific subscription.
+  @param[in] sub  Subscription type.
+  @return Whether the subscription was successfully bound.
+  @retval QL_ERR_OK successful.
+  @retval QL_ERR_INVALID_ARG invalid argument.
+  @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+//int ql_voice_bind_subscription(QL_VOICE_SUBSCRIPTION_E sub);
+
+