Add basic change for v1453

Change-Id: I9497a61bbc3717f66413794a4e7dee0347c0bc33
diff --git a/mbtk/libql_lib_v2_rilv2/Makefile b/mbtk/libql_lib_v2_rilv2/Makefile
new file mode 100755
index 0000000..bd35f0d
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/Makefile
@@ -0,0 +1,94 @@
+BUILD_ROOT = $(shell pwd)/..
+include $(BUILD_ROOT)/Make.defines
+
+LOCAL_PATH=$(BUILD_ROOT)/libql_lib_v2_rilv2
+
+INC_DIR += \
+		-I$(LOCAL_PATH)
+
+LIB_DIR +=
+
+LIBS += -lmbtk_lib -llog -lubus -lubox -lblobmsg_json -lrilutil -lm
+
+CFLAGS += -shared -Wl,-shared,-Bsymbolic
+
+DEFINE +=
+
+#MY_FILES_PATH:=$(LOCAL_PATH)
+#ifeq ($(CONFIG_MBTK_QL_SUPPORT),y)
+#MY_FILES_PATH += $(LOCAL_PATH)/ql
+#endif
+
+#ifeq ($(CONFIG_MBTK_PLATFORM),linux)
+#MY_FILES_PATH += $(LOCAL_PATH)/platform/linux
+#endif
+
+#MY_FILES_SUFFIX:=%.c %.cpp
+#My_All_Files := $(foreach src_path,$(MY_FILES_PATH), $(shell find "$(src_path)" -type f))
+#MY_SRC_LIST  := $(filter $(MY_FILES_SUFFIX),$(My_All_Files))
+#MY_SRC_LIST  := $(MY_SRC_LIST:$(LOCAL_PATH)/%=%)
+#LOCAL_SRC_FILES += $(MY_SRC_LIST)
+#$(info LOCAL_SRC_FILES = $(LOCAL_SRC_FILES))
+
+#LOCAL_SRC_FILES = $(wildcard *.c) $(wildcard *.cpp)
+ LOCAL_SRC_FILES = ql_sim.c \
+	ql_nw.c \
+   ql_sms.c \
+   ql_voice.c \
+    ql_data_call_v1.c \
+   ql_wifi.c \
+   ql_test_utils.c \
+    ql_absys_api.c \
+    ql_adc.c \
+    ql_atc.c \
+    ql_audio_cfg.c \
+    ql_audio_pcm.c \
+    ql_cell_locator.c \
+    ql_dm.c \
+    ql_fota.c \
+    ql_fota_api.c \
+    ql_fota_common.c \
+    ql_gnss.c \
+    ql_gpio.c \
+    ql_gpio_internal.c \
+    ql_lanhost.c \
+    ql_lpm.c \
+    ql_ms_data_call.c \
+    ql_ms_dm.c \
+    ql_ms_nw.c \
+    ql_ms_sim.c \
+    ql_ms_sms.c \
+    ql_ms_voice.c \
+    ql_net_usb_dev.c \
+    ql_nf.c \
+    ql_nslookup.c \
+    ql_sleep_wakelock.c \
+   ql_ecall.c   
+    
+
+
+
+OBJS = $(patsubst %.c, %.o, $(patsubst %.cpp, %.o, $(LOCAL_SRC_FILES)))
+$(info OBJS = $(OBJS))
+
+lib_name := libql_lib.so
+lib_version := 2
+
+dtarget := $(OUT_DIR)/lib/$(lib_name).$(lib_version)
+
+all: $(dtarget)
+
+$(dtarget): $(OBJS)
+	$(CC) $(CFLAGS) $(LIB_DIR) $(LIBS) $(OBJS) -o $@
+	cp $@ $(BUILD_ROOT)/rootfs/lib
+	ln -sf $(lib_name).$(lib_version) $(BUILD_ROOT)/rootfs/lib/$(lib_name)
+
+%.o:%.c
+	$(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+%.o:%.cpp
+	$(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+clean:
+	rm -f $(OBJS) $(dtarget)
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_absys_api.c b/mbtk/libql_lib_v2_rilv2/ql_absys_api.c
new file mode 100755
index 0000000..5d0b253
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_absys_api.c
@@ -0,0 +1,103 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "ql_absys_api.h"
+#include "mbtk_type.h"
+#include "mbtk_fota.h"
+#include "mbtk_log.h"
+#include "mbtk_utils.h"
+
+int ql_absys_get_cur_active_part(absystem_t *cur_system)
+{
+    int active;
+
+    active = mbtk_fota_get_active_absys_type();
+    if (active == 0)
+    {
+        *cur_system = SYSTEM_A;
+    }
+    else if (active == 1)
+    {
+        *cur_system = SYSTEM_B;
+    }
+    else
+    {
+        LOGE("ql_absys_get_cur_active_part fail");
+        return -1;
+    }
+
+    return 0;
+}
+
+int ql_absys_switch(void)
+{
+    int absys_t, active, tmp_active, reboot_cnt;
+
+    active = mbtk_fota_get_active_absys_type();
+    tmp_active = mbtk_fota_get_tmp_absys_type();
+    absys_t = mbtk_fota_get_sync_absys_type();
+    reboot_cnt = mbtk_fota_get_asr_reboot_cnt_flag();
+    LOGI("ql_absys_get_cur_active_part active=%d,tmp_active=%d,absys_t=%d,reboot_cnt=%d",active,tmp_active,absys_t,reboot_cnt);
+
+    if (reboot_cnt == 0 && (active == tmp_active))
+    {
+        return 0;
+    }
+
+    if ((active == tmp_active) && absys_t == 0)
+    {
+        return -2;
+    }
+
+    if ((active != tmp_active) && absys_t == 0)
+    {
+        return -3;
+    }
+
+    return -1;
+}
+
+int ql_absys_getstatus(sysstatus_t *sys_state)
+{
+    int active, tmp_active, mtd_check;
+    char tmp_ac, ac;
+    char out[8]={0};
+
+    active = mbtk_fota_get_active_absys_type();
+    tmp_active = mbtk_fota_get_tmp_absys_type();
+    mtd_check = mbtk_fota_get_mtd_check_type();
+    LOGI("ql_absys_get_cur_active_part tmp_active=%d active=%d mtd_check=%d",tmp_active,active,mtd_check);
+
+    if (mtd_check == 0)
+    {
+        sys_state->is_damaged = 0;
+    }
+    else
+    {
+        if (tmp_active == 0)
+            tmp_ac = 'A';
+        else
+            tmp_ac = 'B';
+
+        if (active == 0)
+            ac = 'A';
+        else
+            ac = 'B';
+
+        sys_state->is_damaged = 1;
+        sprintf(out, "%c to %c",tmp_ac, ac);
+        memcpy(sys_state->damaged_partname, out, strlen(out));
+    }
+
+    return 0;
+}
+
+int ql_absys_sync(void)
+{
+    mbtk_system("sync");
+
+    return 0;
+}
+
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_adc.c b/mbtk/libql_lib_v2_rilv2/ql_adc.c
new file mode 100755
index 0000000..d3baeaf
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_adc.c
@@ -0,0 +1,35 @@
+#include "ql_adc.h"
+#include "mbtk_adc.h"
+
+
+/*========================================================================
+  FUNCTION:  ql_adc_show
+=========================================================================*/
+/** @brief
+    This function retrieves the ADC voltage value with the specified
+    ADC channel.
+    Support input vol value:
+    ADC0 : 0V-VBAT_BB
+    ADC1 : 0V-VBAT_BB
+
+    @param[in] qadc, adc channel definitions, one value of ADC_CHANNEL_E.
+
+    @return
+    adc value(mv) on success
+    on failure, the return value is -1;
+*/
+/*=======================================================================*/
+int ql_adc_show(ADC_CHANNEL_E qadc)
+{
+    if(qadc >= ADC0 && qadc <= ADC2) {
+        int result = mbtk_adc_get(ADC_DEVICE_AUX, (mbtk_adc_enum)(qadc - 1));
+        if(result < 0) {
+            return -1;
+        } else {
+            return result;
+        }
+    } else {
+        return -1;
+    }
+}
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_atc.c b/mbtk/libql_lib_v2_rilv2/ql_atc.c
new file mode 100755
index 0000000..5626121
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_atc.c
@@ -0,0 +1,71 @@
+#include "ql_atc.h"
+#include "ql_type.h"
+
+#include "mbtk_at.h"
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Initialize ATC service.
+  @note You must call this function before other functions can be used in this module.
+  @return Whether the ATC service was successfully intialized.
+  @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_atc_init(void)
+{
+	return mbtk_at_init();
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief send at command async.
+  @param[in] req_buf At command request content
+  @param[out] async_index Async AT command index
+  @param[in] async_cb Async callback function
+  @return Whether to successfully send the AT command asynchronously
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_atc_send_async(char *req_buf, int *async_index, void *async_cb)
+{
+	return QL_ERR_UNSUPPORTED;
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief send AT command.
+  @param[in] req_buf At command request content
+  @param[in] rsp_buf At command response content
+  @param[in] rsp_len The length of rsp_buf
+  @return Whether to successfully send AT command
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_atc_send(char *req_buf, char *rsp_buf, int rsp_len)
+{
+	return mbtk_at_send(req_buf, rsp_buf, rsp_len);
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Deinitialize ATC service.
+  @return Whether the DM service was successfully deintialized.
+  @retval QL_ERR_OK successful.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_atc_deinit(void)
+{
+	return mbtk_at_deinit();
+}
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_audio_cfg.c b/mbtk/libql_lib_v2_rilv2/ql_audio_cfg.c
new file mode 100755
index 0000000..4f521e5
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_audio_cfg.c
@@ -0,0 +1,714 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_audio_cfg.h
+  @brief audio config API, including audio initlization, audio configuration
+
+  @detailes
+  Quectel AG55x series module AUDIO service.
+
+  @htmlonly
+  <span style="font-weight: bold">History</span>
+  @endhtmlonly
+
+  when       |   who      	|    what, where, why
+  --------   |   ---      	|    ----------------------------------------------------------
+  2021-11-03 |   dameng.lin |    Created .
+
+  Copyright (c) 2019 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
+  Quectel Wireless Solution Proprietary and Confidential.
+-------------------------------------------------------------------------------------------------*/
+#ifndef __QL_AUDIO_CFG_H__
+#define __QL_AUDIO_CFG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <math.h>
+#include <stdint.h>
+#include "mbtk_log.h"
+#include "mbtk_audio2.h"
+#include "mbtk_audio_gain.h"
+#include "mbtk_audio_ubus.h"
+#include "ql_v2/ql_type.h"
+
+#define QL_AUDIO_STATE_0  0
+#define QL_AUDIO_STATE_1  1
+
+#define AUDIO_MODE_NORMAL   0
+#define AUDIO_MODE_RINGTONE 1
+#define AUDIO_MODE_IN_CALL  2
+#define DEVICE_EARPIECE 0
+#define DEVICE_SPEAKER  1
+#define DEVICE_HEADSET  2
+
+#define MIC_GAIN_MIN 0
+#define MIC_GAIN_MAX 65535
+#define VOLUME_MIN 0
+#define VOLUME_MAX 100
+
+static int32_t stored_mic_gain = -1;
+static int32_t stored_down_volume = -1;
+
+
+/**
+  @brief  The audio service error callback function
+  @param  error  error code.See ql_type.h for details.
+*/
+typedef void (*ql_audio_service_error_cb_f)(int error);
+
+ql_audio_service_error_cb_f audio_error_callback = NULL;
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function initializes an audio service.
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_SERVICE_NOT_READY  Audio service not ready. Try again later.
+  @retval  Others Failed execution.See ql_type.h for error codes
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_init(void)
+{
+    int result = mbtk_audio_pcm_init();
+    if (result != 0) {
+        LOGE("Error: mbtk_audio_wav_init failed with error code %d\n", result);
+        if (audio_error_callback) {
+            audio_error_callback(result);
+        }
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    return QL_ERR_OK;
+}
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function deinitializes audio services.
+
+  @retval  QL_ERR_OK Successful
+  @retval  QL_ERR_SERVICE_NOT_READY Service is not ready, need to retry
+  @retval  Others Failed execution.See ql_type.h for error codes.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_deinit(void)
+{
+    int result = mbtk_audio_wav_deinit();
+    if (result != 0) {
+        LOGE("Error: mbtk_audio_wav_deinit failed with error code %d\n", result);
+        if (audio_error_callback) {
+            audio_error_callback(result);
+        }
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the value of a mixer.
+
+  @param[in] control    the name of the mixer
+  @param[in] val_list   the value of the mixer to be set. String type value.Multiple values are separated by spaces.
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others Failed execution.See ql_type.h for error codes.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_set_mixer_control(const char *control, const char *val_list);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the value of the mixer.
+
+  @param[in]  control       the name of the mixer
+  @param[out] val_list_buf  buffer for storing mixer values
+  @param[in]  buf_size      the buffer size. Unit:Byte
+
+  @retval  QL_ERR_OK Successful execution.
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others Failed execution.See ql_type.h for error codes.
+
+  @note  Generally, 64 bytes is enough
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_get_mixer_control(const char *control, char *val_list_buf, uint32_t buf_size);
+
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the microphone gain for voice call uplink.
+
+  @param[in] mic_gain  the microphone gain to be set. range:0-65535
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+
+  @note  The API should be called before a voice call
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_set_tx_voice_mic_gain(int32_t mic_gain)
+{
+    if (mic_gain < MIC_GAIN_MIN || mic_gain > MIC_GAIN_MAX) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    stored_mic_gain = mic_gain;
+
+    float mapped_gain = MBTK_AUDIO_GAIN_MIN + ((float)mic_gain * (MBTK_AUDIO_GAIN_MAX - MBTK_AUDIO_GAIN_MIN) / MIC_GAIN_MAX);
+    int result = mbtk_dsp_gain_set(CONFIG_DSPGAIN_TX, (int)round(mapped_gain));
+    if (result != 0) {
+        LOGE("Error: mbtk_dsp_gain_set failed with error code %d\n", result);
+        if (audio_error_callback) {
+            audio_error_callback(result);
+        }
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the microphone gain for voice call uplink.
+
+  @param[out] p_mic_gain  the current microphone gain for voice call uplink.
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_get_tx_voice_mic_gain(int32_t *p_mic_gain)
+{
+    if (p_mic_gain == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    if (stored_mic_gain != -1) {
+        *p_mic_gain = stored_mic_gain;
+    } else {
+        int rx_gain, tx_gain;
+        int result = mbtk_dsp_gain_get(&rx_gain, &tx_gain);
+        if (result != 0) {
+            LOGE("Error: mbtk_dsp_gain_get failed with error code %d\n", result);
+            if (audio_error_callback) {
+                audio_error_callback(result);
+            }
+            return QL_ERR_SERVICE_NOT_READY;
+        }
+        *p_mic_gain = (tx_gain - MBTK_AUDIO_GAIN_MIN) * MIC_GAIN_MAX / (MBTK_AUDIO_GAIN_MAX - MBTK_AUDIO_GAIN_MIN);
+    }
+    LOGD("Retrieved mic gain: %d\n", *p_mic_gain);
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the speaker gain for voice call downlink.
+
+  @param[in] spkr_gain   the speaker gain to be set. range:0-65535
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+
+  @note  The API should be called before a voice call
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_set_rx_voice_spkr_gain(int32_t spkr_gain);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the speaker gain for voice call downlink.
+
+  @param[out] p_spkr_gain   the current speaker gain for voice call downlink.
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_get_rx_voice_spkr_gain(int32_t *p_spkr_gain);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the mute state of voice call uplink.
+
+  @param[in] mute_state  the mute state to be set.
+             QL_AUDIO_STATE_0: unmute, QL_AUDIO_STATE_1: mute
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+
+  @note  The API should be called during the call
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_set_tx_voice_mute_state(int32_t mute_state);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the mute state of voice call uplink.
+
+  @param[out] p_mute_state  the current mute state of voice call uplink. QL_AUDIO_STATE_0 or QL_AUDIO_STATE_1
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_get_tx_voice_mute_state(int32_t *p_mute_state);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the mute state of voice call downlink.
+
+  @param[in] mute_state  the mute state to be set.
+             QL_AUDIO_STATE_0: unmute, QL_AUDIO_STATE_1: mute
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+
+  @note  The API should be called during the call
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_set_rx_voice_mute_state(int32_t mute_state);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the mute state of voice call downlink.
+
+  @param[out] p_mute_state  the current mute state of voice call downlink. QL_AUDIO_STATE_0 or QL_AUDIO_STATE_1
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_get_rx_voice_mute_state(int32_t *p_mute_state);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the uplink volume of a codec.
+
+  @param[in] up_volume  the uplink volume to be set. range:0-100
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_set_codec_up_vol(int32_t up_volume);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the uplink volume of a codec.
+
+  @param[out] p_up_volume  the current uplink volume of codec. range:0-100
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_get_codec_up_vol(int32_t *p_up_volume);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the downlink volume of a codec.
+
+  @param[in] down_volume  the volume to be set. range:0-100
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_set_codec_down_vol(int32_t down_volume)
+{
+    if (down_volume < VOLUME_MIN || down_volume > VOLUME_MAX) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    stored_down_volume = down_volume;
+
+    float mapped_volume = MBTK_AUDIO_GAIN_MIN + ((float)down_volume * (MBTK_AUDIO_GAIN_MAX - MBTK_AUDIO_GAIN_MIN) / VOLUME_MAX);
+    int result = mbtk_dsp_gain_set(CONFIG_DSPGAIN_RX, (int)round(mapped_volume));
+    if (result != 0) {
+        LOGE("Error: mbtk_dsp_gain_set failed with error code %d\n", result);
+        if (audio_error_callback) {
+            audio_error_callback(result);
+        }
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the downlink volume of a codec.
+
+  @param[out] p_down_volume  the current downlink volume of codec. range:0-100
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_get_codec_down_vol(int32_t *p_down_volume)
+{
+    if (p_down_volume == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    if (stored_down_volume != -1) {
+        *p_down_volume = stored_down_volume;
+    } else {
+        int rx_gain, tx_gain;
+        int result = mbtk_dsp_gain_get(&rx_gain, &tx_gain);
+        if (result != 0) {
+            LOGE("Error: mbtk_dsp_gain_get failed with error code %d\n", result);
+            if (audio_error_callback) {
+                audio_error_callback(result);
+            }
+            return QL_ERR_SERVICE_NOT_READY;
+        }
+        *p_down_volume = (rx_gain - MBTK_AUDIO_GAIN_MIN) * VOLUME_MAX / (MBTK_AUDIO_GAIN_MAX - MBTK_AUDIO_GAIN_MIN);
+    }
+    LOGD("Retrieved codec downlink volume: %d\n", *p_down_volume);
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the microphone mute state of a codec.
+
+  @param[in] mute_state  the muute state to be set.
+             QL_AUDIO_STATE_0: unmute, QL_AUDIO_STATE_1: mute
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+
+  @note  The API should be called during the call or audio playback
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_set_codec_mic_mute_state(int32_t mute_state);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the microphone mute state of a codec.
+
+  @param[out] p_mute_state  the current microphone mute state of codec. QL_AUDIO_STATE_0 or QL_AUDIO_STATE_1
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_get_codec_mic_mute_state(int32_t *p_mute_state);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the speaker mute state of a codec.
+
+  @param[in] mute_state  the mute state to be set.
+             QL_AUDIO_STATE_0: unmute, QL_AUDIO_STATE_1: mute
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+
+  @note  The API should be called during the call or audio playback
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_set_codec_spk_mute_state(int32_t mute_state);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the speaker mute state of a codec.
+
+  @param[out] p_mute_state  the current speaker mute state of codec. QL_AUDIO_STATE_0 or QL_AUDIO_STATE_1
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_get_codec_spk_mute_state(int32_t *p_mute_state);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function enables/disables loopback.
+
+  @param[in] enable_state  enable/disable the loopback to be set.
+             QL_AUDIO_STATE_0: disable, QL_AUDIO_STATE_1: enable
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_set_loopback_enable_state(int32_t enable_state)
+{
+    int result;
+    int device = DEVICE_SPEAKER;
+
+    if (enable_state == QL_AUDIO_STATE_1) {
+        result = mbtk_audio_set_loopback_enable_state(device, enable_state);
+        if (result != 0) {
+            LOGE("Error: mbtk_audio_set_loopback_enable_state failed\n");
+            if (audio_error_callback) {
+                audio_error_callback(result);
+            }
+            return QL_ERR_SERVICE_NOT_READY;
+        }
+        LOGD("Loopback started successfully\n");
+    } else if (enable_state == QL_AUDIO_STATE_0) {
+        result = mbtk_audio_set_loopback_enable_state(device, enable_state);
+        if (result != 0) {
+            LOGE("Error: mbtk_audio_set_loopback_enable_state failed\n");
+            if (audio_error_callback) {
+                audio_error_callback(result);
+            }
+            return QL_ERR_SERVICE_NOT_READY;
+        }
+    } else {
+        LOGD("Error: Invalid enable_state %d\n", enable_state);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  The function gets the loopback state.
+
+  @param[out] p_enable_state  the current loopback state. QL_AUDIO_STATE_0 or QL_AUDIO_STATE_1
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_get_loopback_enable_state(int32_t *p_enable_state)
+{
+    if (p_enable_state == NULL) {
+        LOGE("Error: p_enable_state is NULL\n");
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int device;
+    int result = mbtk_audio_get_loopback_enable_state(&device, p_enable_state);
+    if (result != 0) {
+        LOGE("Error: mbtk_audio_get_loopback_enable_state failed\n");
+        if (audio_error_callback) {
+            audio_error_callback(result);
+        }
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    LOGD("Current loopback state: %d\n", *p_enable_state);
+    return QL_ERR_OK;
+}
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the sidetone gain.
+
+  @param[in] sidetone_gain  sidetone gain to be set. range: 0-65535
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_set_sidetone_gain(int32_t sidetone_gain);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the sidetone gain.
+
+  @param[out] p_sidetone_gain  the current sidetone gain. range: 0-65535, default value: 1298
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_get_sidetone_gain(int32_t *p_sidetone_gain);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the voice call manager state. By default, voice call services such as ringtones, ringback
+tones, third-party ringtones and voice stream status control are all implemented by ql_audiod program
+automatically.
+
+  @param[in] manager_state  The manager state to be set. Voice call services include ringtones, ringback tones, the third-party
+ringtones and voice stream status control. range: QL_AUDIO_STATE_0 and QL_AUDIO_STATE_1
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+
+  @note  The voice service, such as call ring, beep tone, will not work during a voice call
+         If the manager_state is set to QL_AUDIO_STATE_1
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_set_voice_call_manager_state(int32_t manager_state);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the voice call manager state.
+
+  @param[out] p_manager_state  the current voice call manager state.
+              QL_AUDIO_STATE_0: close, QL_AUDIO_STATE_1:open
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_get_voice_call_manager_state(int32_t *p_manager_state);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the voice stream state.
+
+  @param[in] stream_state  voice stream state to be set.
+             QL_AUDIO_STATE_0: close, QL_AUDIO_STATE_1:open
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+
+  @note  After the voice call manager state is set to QL_AUDIO_STATE_1 by calling
+ql_audio_set_voice_call_manager_state(), the service program ql_audiod will not enable voice stream
+while establishing a voice call. In such a case, call ql_audio_set_voice_stream_state() to enable voice
+stream state by setting stream_state to QL_AUDIO_STATE_1, and then the voice stream can be disabled
+by setting stream_state to QL_AUDIO_STATE_0.*/
+/*-----------------------------------------------------------------------------------------------*/
+//int ql_audio_set_voice_stream_state(int32_t stream_state);
+int ql_audio_set_voice_stream_state(int32_t stream_state);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  The function gets the voice stream state.
+
+  @param[out] p_stream_state  the current voice stream state. QL_AUDIO_STATE_0 or QL_AUDIO_STATE_1
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+//int ql_audio_get_voice_stream_state(int32_t *p_stream_state);
+int ql_audio_get_voice_stream_state(int32_t *p_stream_state);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the callback function for audio service errors. 
+  @param[in] cb  The callback function for audio service errors.Only when the audioservice exit abnormally,the callback function is executed.
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_set_service_error_cb(ql_audio_service_error_cb_f cb)
+{
+    if (cb == NULL) {
+        LOGE("Error: Callback function is NULL\n");
+        return QL_ERR_INVALID_ARG;
+    }
+
+    audio_error_callback = cb;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function switch codec.
+
+  @param[in] codec_switch  the which codec to be switch.
+             0:GSSP  1:internal codec
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_set_codec_switch(int32_t codec_switch);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the tone state.
+
+  @param[out] p_codec_switch  which codec has switch.    
+
+  @retval  QL_ERR_OK Successful execution
+  @retval  QL_ERR_INVALID_ARG Failed execution.Invalid arguments
+  @retval  Others errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_get_codec_switch(int32_t *p_codec_switch);
+
+
+typedef struct ql_audio_tone_config_struct
+{
+    int32_t low_fre;
+    int32_t high_fre;
+    int32_t on_duration;
+    int32_t off_duration;
+    int32_t volume;
+    int32_t count;
+}ql_audio_tone_config_t;
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Set tone enable state
+
+  @param[in] low_fre   low frequency, range: 100~4000
+  @param[in] high_fre  high frequency, range: 100~4000
+  @param[in] on_duration  tone play time,  unit is millisecond
+  @param[in] off_duration  tone pause time,  unit is millisecond
+  @param[in] volume  tone play volume, range: 0~5000
+  @param[in] count  tone play count
+
+  @return  QL_ERR_OK - Successful
+           QL_ERR_INVALID_ARG - Invalid arguments
+           Other errorcode defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_set_tone_enable_state(int32_t enable_state,ql_audio_tone_config_t *p_tone_config);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Get tone enable state
+
+  @param[out] p_enable_state  tone enable state,
+              QL_AUDIO_STATE_0: close, QL_AUDIO_STATE_1:open
+
+  @return  QL_ERR_OK - Successful
+           QL_ERR_INVALID_ARG - Invalid arguments
+           Other errorcode defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_get_tone_enable_state(int32_t *p_enable_state);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_audio_pcm.c b/mbtk/libql_lib_v2_rilv2/ql_audio_pcm.c
new file mode 100755
index 0000000..c98a335
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_audio_pcm.c
@@ -0,0 +1,729 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_audio_pcm.h
+  @brief playback or capture API
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  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
+  --------     ---          ----------------------------------------------------------
+  2021-11-03   dameng.lin     Created .
+-------------------------------------------------------------------------------------------------*/
+
+#ifndef __QL_AUDIO_PCM_H
+#define __QL_AUDIO_PCM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include "mbtk_log.h"
+#include "mbtk_audio2.h"
+#include "ql_v2/ql_type.h"
+#include "mbtk_ril_api.h"
+#include "ql_v2/ql_audio_cfg.h"
+
+typedef int ql_audio_handle_t;
+
+static const char *g_wav_file_name = NULL;
+static mbtk_ril_handle* call_info_handle = NULL;
+
+
+typedef enum QL_AUDIO_STREAM_FORMAT_ENUM
+{
+    QL_AUDIO_STREAM_FORMAT_PCM = 1,         /**< PCM*/
+    QL_AUDIO_STREAM_FORMAT_MP3,             /**< MP3*/
+    QL_AUDIO_STREAM_FORMAT_AMR,             /**< AMR*/
+    QL_AUDIO_STREAM_FORMAT_AMRNB,           /**< AMR-NB*/
+    QL_AUDIO_STREAM_FORMAT_AMRWB,           /**< AMR-WB*/
+}QL_AUDIO_STREAM_FORMAT_E;
+
+
+/**The structure of PCM configuration parameters*/
+typedef struct ql_audio_pcm_config_struct
+{
+    /**  Each sound card maintains a hardware buffer to store audio data. The hardware
+    *  buffer is divided into several periods. The sound card uses period as a unit to transmit data,
+    *  and one period stores some data frames.period_size sets the size of periods in hardware buffer.
+    *  When period_size is set to 0,it means that the period size is calculated by the bottom layer to
+    *  obtain a default value. If period_size is not 0, the recommended value is 128–960. The larger the
+    *  perod_size is, the larger the kernel overhead is
+    */
+    uint32_t period_size;
+    /**  period_count indicates the count of period that the data occupies, when the application reads data
+    *  from or writes data to the hardware buffer.The size of the data that the application reads from or
+    *  writes to the hardware buffer every time equals period_count multiplied by period_size. The hardware
+    *  buffer has a maximum of 8 periods by default. The recommended value of period_count is 1–3.
+    */
+    uint32_t period_count;
+    uint32_t num_channels;  /**< Number of channels. 1 Mono 2 Stereo*/
+    uint32_t sample_rate;   /**< Sampling rate. A PCM interface supports 8000 and 16000,and an I2s interface supports 48000.Unit:Hz*/
+    uint32_t pcm_format;        /**< PCM data format.Presently supports 2 only,which means 16-bit little endian format*/
+} ql_audio_pcm_config_t;
+
+#define QL_AUDIO_INVALID_HANDLE  ((ql_audio_handle_t)(void *)NULL)
+
+typedef enum
+{
+    QL_AUDIO_STREAM_DIRECTION_PLAYBACK = 0,
+    QL_AUDIO_STREAM_DIRECTION_CAPTURE,
+    QL_AUDIO_STREAM_DIRECTION_MAX
+}QL_AUDIO_STREAM_DIRECTION_E;
+
+
+/**The enumeration of the front end PCM device types*/
+typedef enum QL_AUDIO_FE_PCM_DEV_ENUM
+{
+    QL_AUDIO_FE_PCM_DEV_MIN = -1,
+    QL_AUDIO_FE_PCM_DEV_MULTIMEDIA1 = 0,    /**< The first PCM device available for general-purpose audio playback and capturing.*/
+	QL_AUDIO_FE_PCM_DEV_MULTIMEDIA2 = 1,    /**< The sencond PCM device available for general-purpose audio playback and capturing.*/
+	QL_AUDIO_FE_PCM_DEV_MULTIMEDIA3 = 2,    /**< The third PCM device available for general-purpose audio playback and capturing.*/
+	QL_AUDIO_FE_PCM_DEV_MAX
+} QL_AUDIO_FE_PCM_DEV_E;
+
+
+
+typedef enum QL_AUDIO_BE_DAI_ENUM
+{
+    QL_AUDIO_BE_DAI_MIN = -1,
+    QL_AUDIO_BE_DAI_PLAYBACK_PRI_PCM = 0,   /**< Play back audio to the first PCM interface.*/
+    QL_AUDIO_BE_DAI_PLAYBACK_VOICE_TX,      /**< play back audio to the voice call uplink*/
+    QL_AUDIO_BE_DAI_CAPTURE_PRI_PCM,        /**< Capture audio from the first PCM interface*/
+    QL_AUDIO_BE_DAI_CAPTURE_VOICE_UL,       /**< Capture voice stream from voice call uplink*/
+    QL_AUDIO_BE_DAI_CAPTURE_VOICE_DL,       /**< Capture voice stream from voice call downlink*/
+    QL_AUDIO_BE_DAI_MAX
+}QL_AUDIO_BE_DAI_E;
+
+#define QL_AUDIO_BE_DAI_MASK_PLAYBACK_PRI_PCM       (1 << QL_AUDIO_BE_DAI_PLAYBACK_PRI_PCM)
+#define QL_AUDIO_BE_DAI_MASK_PLAYBACK_VOICE_TX      (1 << QL_AUDIO_BE_DAI_PLAYBACK_VOICE_TX)
+#define QL_AUDIO_BE_DAI_MASK_CAPTURE_PRI_PCM        (1 << QL_AUDIO_BE_DAI_CAPTURE_PRI_PCM)
+#define QL_AUDIO_BE_DAI_MASK_CAPTURE_VOICE_UL       (1 << QL_AUDIO_BE_DAI_CAPTURE_VOICE_UL)
+#define QL_AUDIO_BE_DAI_MASK_CAPTURE_VOICE_DL       (1 << QL_AUDIO_BE_DAI_CAPTURE_VOICE_DL)
+
+/**The enumeration of audio playback state*/
+typedef enum  QL_AUDIO_PLAYBACK_STATE_ENUM
+{
+    QL_AUDIO_PLAYBACK_STATE_CLOSE = 0,      /**< Close*/
+    QL_AUDIO_PLAYBACK_STATE_OPEN,           /**< Open*/
+    QL_AUDIO_PLAYBACK_STATE_PREPARE,        /**< Ready*/
+    QL_AUDIO_PLAYBACK_STATE_PLAYING,        /**< Playing*/
+    QL_AUDIO_PLAYBACK_STATE_FINISHED,       /**< Finished*/
+    QL_AUDIO_PLAYBACK_STATE_PAUSE,          /**< Pause*/
+    QL_AUDIO_PLAYBACK_STATE_ERROR,          /**< Error*/
+} QL_AUDIO_PLAYBACK_STATE_E;
+
+/**The enumeration of audio capture state*/
+typedef enum QL_AUDIO_CAPTURE_STATE_ENUM
+{
+    QL_AUDIO_CAPTURE_STATE_CLOSE = 0,       /**< Close*/
+    QL_AUDIO_CAPTURE_STATE_OPEN,            /**< Open*/
+    QL_AUDIO_CAPTURE_STATE_PREPARE,         /**< Prepare*/
+    QL_AUDIO_CAPTURE_STATE_CAPTURING,       /**< Capturing*/
+    QL_AUDIO_CAPTURE_STATE_FINISHED,        /**< Finished*/
+    QL_AUDIO_CAPTURE_STATE_PAUSE,           /**< Pause*/
+    QL_AUDIO_CAPTURE_STATE_ERROR,           /**< Error*/
+} QL_AUDIO_CAPTURE_STATE_E;
+
+
+#define  QL_AUDIO_PLAYBACK_NONBLOCK  0
+#define  QL_AUDIO_PLAYBACK_BLOCK     1
+
+
+/**
+    @brief  The audio capturing state callback function
+    @param  handle Recording handle,which is the return value of ql_audio_capture_open().
+    @param  params Parameters carried by the callback function
+    @param  state  The current audio capturing state.
+*/
+typedef int (*ql_audio_capture_state_cb_f)(ql_audio_handle_t handle, void *params, QL_AUDIO_CAPTURE_STATE_E state);
+
+/**
+    @brief  The playback state callback function
+    @param  handle Playback handle, which is the return value of ql_audio_playback_open().
+    @param  params Parameters carried by the callback function.
+    @param  state  The current playback state.
+*/
+typedef int (*ql_audio_playback_state_cb_f)(ql_audio_handle_t handle, void *params, QL_AUDIO_PLAYBACK_STATE_E state);
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief This function opens the audio context for playback.
+
+  @param[in] fe_pcm_dev  Front end PCM device type. defined by QL_AUDIO_FE_PCM_DEV_E
+  @param[in] be_dai_mask  Backend digit audio interface mask, support follow:
+             QL_AUDIO_BE_DAI_MASK_PLAYBACK_PRI_PCM  Play back audio to the 1 st PCM interface
+             QL_AUDIO_BE_DAI_MASK_PLAYBACK_SEC_PCM  Play back audio to the 2 nd PCM interface
+             QL_AUDIO_BE_DAI_MASK_PLAYBACK_PRI_I2S  Play back audio to the 1 st I2S interface
+             QL_AUDIO_BE_DAI_MASK_PLAYBACK_SEC_I2S  Play back audio to the 2 nd I2S interface
+             QL_AUDIO_BE_DAI_MASK_PLAYBACK_VOICE_TX Play back audio to the voice call uplink
+
+  @retval  A_valid_handle   Successful execution.
+  @retval  QL_AUDIO_INVALID_HANDLE  Failed execution.Invalid handle
+  */
+/*-----------------------------------------------------------------------------------------------*/
+ql_audio_handle_t ql_audio_playback_open(QL_AUDIO_FE_PCM_DEV_E fe_pcm_dev, uint32_t be_dai_mask)
+{
+    if (fe_pcm_dev == QL_AUDIO_FE_PCM_DEV_MULTIMEDIA1 && be_dai_mask == QL_AUDIO_BE_DAI_MASK_PLAYBACK_PRI_PCM)
+    {
+        int init_result = mbtk_audio_pcm_init();
+
+        if (init_result != 0) {
+            LOGE("Error: mbtk_audio_pcm_init failed with error code %d\n", init_result);
+            if (audio_error_callback) {
+                audio_error_callback(init_result);
+            }
+            return QL_AUDIO_INVALID_HANDLE;
+        }
+    } else {
+        printf("Error: Unsupported PCM device or DAI mask\n");
+        return QL_AUDIO_INVALID_HANDLE;
+    }
+
+    return (ql_audio_handle_t)1;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function prepares for audio file playback.
+
+  @param[in] handle     The handle returned by ql_audio_playback_open().
+  @param[in] file_name  The name of the file to be played back.
+  @param[in] pcm_config  Pcm config, including sample rate, channel nums,
+             defined by ql_audio_pcm_config_t. Generally, it is NULL.
+  @param[in] playback_state_cb  Callback function to report the current playback state
+             The states defined by QL_AUDIO_PLAYBACK_STATE_E
+  @param[in] params Parameters carried by the callback function.
+
+  @retval  QL_ERR_OK    Successful execution.
+  @retval  QL_ERR_INVALID_HANDLE    Failed execution. Invalid handle.
+  @retval  QL_ERR_INVALID_STATE     Failed execution. Invalid state.
+  @retval  Others   Failed execution. See ql_type.h for error codes.
+
+  @note   Before calling this function, call ql_audio_playback_open() first to obtain a handle.
+          If an audio file is expected to be played back, call this function first to prepare for
+          the playback and then ql_audio_playback_play() to start playback.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_playback_file_prepare(ql_audio_handle_t handle,
+                                   const char *file_name,
+                                   ql_audio_pcm_config_t *pcm_config,
+                                   ql_audio_playback_state_cb_f playback_state_cb,
+                                   void *params)
+{
+    if (handle == QL_AUDIO_INVALID_HANDLE) {
+        LOGE("Error: Invalid handle\n");
+        if (audio_error_callback) {
+            audio_error_callback(-1);
+        }
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if (file_name == NULL) {
+        LOGE("Error: File name is NULL\n");
+        if (audio_error_callback) {
+            audio_error_callback(-1);
+        }
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    g_wav_file_name = file_name;
+
+    if (pcm_config != NULL) {
+        printf("Warning: PCM configuration provided but not supported\n");
+    } else {
+        LOGD("No PCM configuration provided\n");
+    }
+
+    if (playback_state_cb != NULL) {
+        printf("Warning: Playback state callback provided but not supported\n");
+    } else {
+        LOGD("No playback state callback provided\n");
+    }
+
+    LOGD("Audio file prepared for playback: %s\n", file_name);
+    return QL_ERR_OK;
+}
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function prepares for audio stream playback.
+
+  @param[in] handle  The API ql_audio_playback_open return results
+  @param[in] pcm_config  Pcm config, including sample rate, channel nums,
+             defined by ql_audio_pcm_config_t. If it is NULL, the API use defaule value.
+  @param[in] playback_state_cb  Callback function to report the current playback state.
+  @param[in] params  Parameters carried by the callback function.
+
+  @retval  QL_ERR_OK    Successful execution.
+  @retval  QL_ERR_INVALID_HANDLE    Failed execution. Invalid handle.
+  @retval  QL_ERR_INVALID_STATE     Failed execution. Invalid state.
+  @retval  Others   Failed execution. See ql_type.h for error codes.
+
+  @note   Before calling this function, call ql_audio_playback_open() first to obtain a handle.
+          If an audio stream is expected to be played back, call this function first to prepare
+          for the audio stream playback and then ql_audio_playback_push_stream() to start playback.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_playback_stream_prepare(ql_audio_handle_t handle,
+                                     ql_audio_pcm_config_t *pcm_config,
+                                     ql_audio_playback_state_cb_f playback_state_cb,
+                                     void *params);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function starts playback of the audio data.
+
+  @param[in] handle  The handle returned by ql_audio_playback_open().
+
+  @retval  QL_ERR_OK    Successful execution.
+  @retval  QL_ERR_INVALID_HANDLE    Failed execution. Invalid handle.
+  @retval  QL_ERR_INVALID_STATE     Failed execution. Invalid state.
+  @retval  Others   Failed execution. See ql_type.h for error codes.
+
+  @note     Before calling this function, call ql_audio_playback_file_prepare() first to prepare the audio file
+            to be played back, otherwise the audio data cannot be played back successfully.This function also supports
+            playback of audio stream data. In this case, call ql_audio_playback_stream_prepare() first to prepare
+            the audio stream to be played back, then this function to start playback, and finally
+            ql_audio_playback_push_stream() to play back the audio stream in buffer.
+ */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_playback_play(ql_audio_handle_t handle)
+{
+    if (handle == QL_AUDIO_INVALID_HANDLE) {
+        LOGE("Error: Invalid handle\n");
+        if (audio_error_callback) {
+            audio_error_callback(-1);
+        }
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if (g_wav_file_name == NULL) {
+        LOGE("Error: No audio file prepared for playback\n");
+        if (audio_error_callback) {
+            audio_error_callback(-1);
+        }
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    int err = mbtk_audio_wav_play_start(g_wav_file_name);
+    if (err != 0) {
+        LOGE("Error playing audio file: %d\n", err);
+        if (audio_error_callback) {
+            audio_error_callback(err);
+        }
+        return QL_ERR_SERVICE_NOT_READY;
+    } else {
+        LOGD("Audio file playback started successfully\n");
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function plays back the audio stream in buffer.
+
+  @param[in] handle  The handle returned by ql_audio_playback_open().
+  @param[in] stream_buf  The buffer that stores the audio stream to be played back.
+  @param[in] buf_size  The size of the audio stream to be played back. Unit: Byte.
+
+  @retval  QL_ERR_OK    Successful execution.
+  @retval  QL_ERR_INVALID_HANDLE    Failed execution. Invalid handle.
+  @retval  QL_ERR_INVALID_STATE     Failed execution. Invalid state.
+  @retval  Others   Failed execution. See ql_type.h for error codes.
+
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_playback_push_stream(ql_audio_handle_t handle, void *stream_buf, uint32_t buf_size);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief    This function pauses the audio playback.
+
+  @param[in] handle  The handle returned by ql_audio_playback_open().
+
+  @retval  QL_ERR_OK    Successful execution.
+  @retval  QL_ERR_INVALID_HANDLE    Failed execution. Invalid handle.
+  @retval  Others   Failed execution. See ql_type.h for error codes.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_playback_pause(ql_audio_handle_t handle);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief    This function resumes the audio playback.
+
+  @param[in] handle  The handle returned by ql_audio_playback_open().
+
+  @retval  QL_ERR_OK    Successful execution.
+  @retval  QL_ERR_INVALID_HANDLE    Failed execution. Invalid handle.
+  @retval  Others   Failed execution. See ql_type.h for error codes.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_playback_resume(ql_audio_handle_t handle);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief This function stops the audio playback.
+
+  @param[in] handle  The handle returned by ql_audio_playback_open().
+
+  @retval  QL_ERR_OK    Successful execution.
+  @retval  QL_ERR_INVALID_HANDLE    Failed execution. Invalid handle.
+  @retval  Others   Failed execution. See ql_type.h for error codes.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_playback_stop(ql_audio_handle_t handle);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief    This function closes the audio context for playback.
+
+  @param[in] handle  The handle returned by ql_audio_playback_open().
+
+  @retval  QL_ERR_OK    Successful execution.
+  @retval  QL_ERR_INVALID_HANDLE    Failed execution. Invalid handle.
+  @retval  Others   Failed execution. See ql_type.h for error codes.
+
+  @Note     After an audio playback ends, you must call this function to close the audio context,
+            otherwise subsequent call of ql_audio_playback_open() will fail.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_playback_close(ql_audio_handle_t handle)
+{
+    if (handle == QL_AUDIO_INVALID_HANDLE) {
+        LOGE("Error: Invalid handle\n");
+        if (audio_error_callback) {
+            audio_error_callback(-1);
+        }
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    int deinit_result = mbtk_audio_wav_deinit();
+    if (deinit_result != 0) {
+        LOGE("Error: mbtk_audio_wav_deinit failed with error code %d\n", deinit_result);
+        if (audio_error_callback) {
+            audio_error_callback(deinit_result);
+        }
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    LOGD("Audio playback context closed successfully\n");
+    return QL_ERR_OK;
+}
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief This function gets the audio playback state.
+
+  @param[in] handle  The handle returned by ql_audio_playback_open().
+  @param[out] playback_state  the current audio playback state, defined by QL_AUDIO_PLAYBACK_STATE_E
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_playback_get_state(ql_audio_handle_t handle, QL_AUDIO_PLAYBACK_STATE_E *playback_state);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief This function handles the call state changes.
+
+  @param[in] data     Pointer to the call information data.
+  @param[in] data_len Length of the call information data.
+
+  This function is a callback that processes different call states. When a call is waiting (MBTK_CLCC),
+  it pauses the audio playback. When a call is disconnected (MBTK_DISCONNECTED), it resumes the audio playback.
+  For other states, it logs the current call wait state.
+
+  @note The function uses mbtk_audio_wav_play_pause() and mbtk_audio_wav_play_resume() to control audio playback.
+        Error handling is performed by logging errors if the playback control functions fail.
+*/
+/*-----------------------------------------------------------------------------------------------*/
+static void call_state_handler(const void* data, int data_len)
+{
+    mbtk_call_info_t *reg = (mbtk_call_info_t *)data;
+    switch (reg->call_wait)
+    {
+        case MBTK_CLCC:
+            {
+                int result = mbtk_audio_wav_play_pause();
+                if (result != 0) {
+                    LOGE("Error: mbtk_audio_wav_play_pause failed with error code %d\n", result);
+                    if (audio_error_callback) {
+                        audio_error_callback(result);
+                    }
+                    return;
+                }
+                LOGD("Incoming call!\n");
+            }
+            break;
+        case MBTK_DISCONNECTED:
+            {
+                int result = mbtk_audio_wav_play_resume();
+                if (result != 0) {
+                    LOGE("Error: mbtk_audio_wav_play_resume failed with error code %d\n", result);
+                    if (audio_error_callback) {
+                        audio_error_callback(result);
+                    }
+                    return;
+                }
+                LOGD("Call disconnected!\n");
+            }
+            break;
+        default:
+            LOGD("RING: None call_wait = %d", reg->call_wait);
+            break;
+    }
+}
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief This function sets the block flag for audio playback.
+
+  @param[in] handle  The handle returned by ql_audio_playback_open().
+  @param[in] flags  block flag, including QL_AUDIO_PLAYBACK_NONBLOCK and QL_AUDIO_PLAYBACK_BLOCK
+
+  @retval  QL_ERR_OK    Successful execution.
+  @retval  QL_ERR_INVALID_HANDLE    Failed execution. Invalid handle.
+  @retval  QL_ERR_INVALID_ARG   Illegal argument.
+  @retval  QL_ERR_INVALID_STATE     Failed execution. Invalid state.
+  @retval  Others   Failed execution. See ql_type.h for error codes.
+
+  @note     Call this function as per the function call sequence below, to make sure the audio playback can be blocked successfully.
+                1) ql_audio_playback_open()
+                2) ql_audio_playback_set_block_flag()
+                3) ql_audio_playback_file_prepare()
+                4) ql_audio_playback_play()
+            If the audio playback is blocked successfully by calling ql_audio_playback_set_block_flag(), then
+                1) If you dial a call or there is an incoming call during the audio playback, the playback will pause;
+                    after the call is hung up, the playback resumes automatically.
+                2) During a voice call, no function can be used to realize audio playback. In this case,
+                    the call of ql_auido_palyback_file_prepare() will fail, which means audio files cannot be played back.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_playback_set_block_flag(ql_audio_handle_t handle, uint8_t flags)
+{
+    if (handle == QL_AUDIO_INVALID_HANDLE) {
+        LOGE("Error: Invalid handle\n");
+        if (audio_error_callback) {
+            audio_error_callback(-1);
+        }
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if (flags == QL_AUDIO_PLAYBACK_BLOCK) {
+        LOGD("Set to blocking mode\n");
+
+        if (call_info_handle == NULL) {
+            call_info_handle = mbtk_ril_open(MBTK_AT_PORT_DEF);
+            if (call_info_handle) {
+                LOGD("Successfully created qser_voice_call_client_init\n");
+            } else {
+                LOGE("Failed to create qser_voice_call_client_init\n");
+                if (audio_error_callback) {
+                    audio_error_callback(-1);
+                }
+                return QL_ERR_SERVICE_NOT_READY;
+            }
+        }
+
+        int err = mbtk_call_state_change_cb_reg(call_state_handler);
+        if (err) {
+            LOGE("Error registering call state change callback: %d\n", err);
+            if (audio_error_callback) {
+                audio_error_callback(err);
+            }
+            return QL_ERR_SERVICE_NOT_READY;
+        }
+
+    } else if (flags == QL_AUDIO_PLAYBACK_NONBLOCK) {
+        LOGD("Set to non-blocking mode\n");
+    } else {
+        LOGE("Invalid flags parameter: %d\n", flags);
+        if (audio_error_callback) {
+            audio_error_callback(-1);
+        }
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    return QL_ERR_OK;
+}
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief This function opens the audio context for capturing.
+
+  @param[in] fe_pcm_dev     Front end PCM device type.
+  @param[in] be_dai_mask    Back end DAI mask,support follow:
+             QL_AUDIO_BE_DAI_MASK_CAPTURE_PRI_PCM
+             QL_AUDIO_BE_DAI_MASK_CAPTURE_VOICE_UL
+             QL_AUDIO_BE_DAI_MASK_CAPTURE_VOICE_DL
+
+@retval  A_valid_handle     Successful execution
+@retval  QL_AUDIO_INVALID_HANDLE    Failed execution.Invalid handle
+  */
+/*-----------------------------------------------------------------------------------------------*/
+ql_audio_handle_t ql_audio_capture_open(QL_AUDIO_FE_PCM_DEV_E fe_pcm_dev, uint32_t be_dai_mask);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function prepares for audio file capturing.
+
+  @param[in] handle  The handle returned by ql_audio_capture_open().
+  @param[in] file_name  The name of the audio file to be captured.
+  @param[in] type  The format of the audio data in the audio file.
+  @param[in] pcm_config  Pcm config, including sample rate, channel nums,
+             defined by ql_audio_pcm_config_t, If it is NULL, the API use defaule value
+  @param[in] capture_state_cb   Callback function to report the current audio capturing state.
+  @param[in] params     Parameters carried by the callback function.
+
+  @retval  QL_ERR_OK    Successful execution.
+  @retval  QL_ERR_INVALID_HANDLE    Failed execution. Invalid handle.
+  @retval  QL_ERR_INVALID_STATE     Failed execution. Invalid state.
+  @retval  Others   Failed execution. See ql_type.h for error codes.
+
+  @note     Before calling this function, call ql_audio_capture_open() first to obtain a handle.
+            If an audio file is expected to be captured, call this function first to prepare for the audio file
+            capturing and then ql_audio_capture_record() to start capturing.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_capture_file_prepare(ql_audio_handle_t handle,
+                                  const char *file_name,
+                                  QL_AUDIO_STREAM_FORMAT_E type,
+                                  ql_audio_pcm_config_t *pcm_config,
+                                  ql_audio_capture_state_cb_f capture_state_cb,
+                                  void *params);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief    This function prepares for audio stream capturing.
+
+  @param[in] handle  This function prepares for audio stream capturing.
+  @param[in] pcm_config     PCM configuration parameters.
+  @param[in] capture_state_cb   Callback function to report the current audio capturing state.
+  @param[in] params     Parameters carried by the callback function.
+
+  @retval  QL_ERR_OK    Successful execution.
+  @retval  QL_ERR_INVALID_HANDLE    Failed execution. Invalid handle.
+  @retval  QL_ERR_INVALID_STATE     Failed execution. Invalid state.
+  @retval  Others   Failed execution. See ql_type.h for error codes.
+
+  @note     Before calling this function, call ql_audio_capture_open() first to obtain a handle.
+            If an audio stream is expected to be captured, call this function first to prepare for
+            the audio stream capturing and then ql_audio_capture_push_stream() to start capturing.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_capture_stream_prepare(ql_audio_handle_t handle,
+                                    ql_audio_pcm_config_t *pcm_config,
+                                    ql_audio_capture_state_cb_f capture_state_cb,
+                                    void *params);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief    This function starts to capture the audio data.
+
+  @param[in] handle  The handle returned by ql_audio_capture_open().
+
+  @retval  QL_ERR_OK    Successful execution.
+  @retval  QL_ERR_INVALID_HANDLE    Failed execution. Invalid handle.
+  @retval  QL_ERR_INVALID_STATE     Failed execution. Invalid state.
+  @retval  Others   Failed execution. See ql_type.h for error codes.
+
+  @note Before calling this function, call ql_audio_capture_file_prepare() first to prepare the audio
+        file to be captured, otherwise the audio data cannot be captured successfully.This function also
+        supports capturing of audio stream data. In this case, call ql_audio_capture_stream_prepare()
+        first to prepare the audio stream to be captured, then this function to start capturing,
+        and finally ql_audio_capture_pull_stream() to capture the audio stream in buffer.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_capture_record(ql_audio_handle_t handle);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function captures the audio stream data to the buffer.
+
+  @param[in] handle  The handle returned by ql_audio_capture_open().
+  @param[out] stream_buf  The buffer that stores the audio stream data to be captured.
+  @param[in] buf_size  Buffer size. Unit: Byte.
+
+  @retval  QL_ERR_OK    Successful execution.
+  @retval  QL_ERR_INVALID_HANDLE    Failed execution. Invalid handle.
+  @retval  Others   Failed execution. See ql_type.h for error codes.
+
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_capture_pull_stream(ql_audio_handle_t handle, void *stream_buf, uint32_t buf_size);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief    This function pauses the audio capturing.
+
+  @param[in] handle     The handle returned by ql_audio_capture_open().
+
+  @retval  QL_ERR_OK    Successful execution.
+  @retval  QL_ERR_INVALID_HANDLE    Failed execution. Invalid handle.
+  @retval  Others   Failed execution. See ql_type.h for error codes.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_capture_pause(ql_audio_handle_t handle);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief    This function resumes the audio capturing.
+
+  @param[in] handle  The handle returned by ql_audio_capture_open().
+
+  @retval  QL_ERR_OK    Successful execution.
+  @retval  QL_ERR_INVALID_HANDLE    Failed execution. Invalid handle.
+  @retval  Others   Failed execution. See ql_type.h for error codes.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_capture_resume(ql_audio_handle_t handle);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief    This function stops the audio capturing.
+
+  @param[in] handle  The handle returned by ql_audio_capture_open().
+
+  @retval  QL_ERR_OK    Successful execution.
+  @retval  QL_ERR_INVALID_HANDLE    Failed execution. Invalid handle.
+  @retval  Others   Failed execution. See ql_type.h for error codes.
+
+  @note     Calling this function will stop audio capturing regardless of whether the capturing is in
+            progress or paused,and the capturing cannot be resumed after it is stopped.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_capture_stop(ql_audio_handle_t handle);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function closes the audio context for capturing.
+
+  @param[in] handle  The handle returned by ql_audio_capture_open().
+
+  @retval  QL_ERR_OK    Successful execution.
+  @retval  QL_ERR_INVALID_HANDLE    Failed execution. Invalid handle.
+  @retval  Others   Failed execution. See ql_type.h for error codes.
+  @note     After audio capturing ends, you must call this function to close the audio context,
+            otherwise subsequent call of ql_audio_capture_open() will fail.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_audio_capture_close(ql_audio_handle_t handle);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief This function gets the current audio capturing state.
+
+  @param[in] handle     The handle returned by ql_audio_capture_open().
+  @param[out] capture_state  The current audio capturing state.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+void ql_audio_capture_get_state(ql_audio_handle_t handle, QL_AUDIO_CAPTURE_STATE_E *capture_state);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_cell_locator.c b/mbtk/libql_lib_v2_rilv2/ql_cell_locator.c
new file mode 100755
index 0000000..b7c0b95
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_cell_locator.c
@@ -0,0 +1,188 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file  ql_cell_locator.h
+  @brief cell_locator service API
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  Copyright (c) 2018 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
+  --------   ---          ----------------------------------------------------------
+  20220810    sunshine     Created .
+-------------------------------------------------------------------------------------------------*/
+
+#ifndef __QL_CELL_LOCATOR_H__
+#define __QL_CELL_LOCATOR_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned short uint16_t;
+
+
+typedef struct 
+{
+    char *ptr;
+    //size_t len;
+} curl_rsp_msg_t;
+
+
+
+typedef struct
+{
+    double   latitude;
+    double   longitude;
+    double   altitude;
+} ql_inject_location_t;
+
+typedef struct
+{
+    /*longtitude*/
+    double lon;
+    /*latitude*/
+    double lat;
+    /*accuracy*/
+    unsigned short accuracy;
+
+    char err_msg[256];
+} ql_perform_rsp;
+
+typedef void (*ql_cell_locator_ind_cb_f)(void *msg);
+
+typedef void (*ql_cell_locator_error_cb_f)(int error);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Initialize the cell_locator client
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_cell_locator_init(void);
+
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief set locator query server and port, server length must be less than 255 bytes.
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_cell_locator_set_server(char *server, uint16_t port);
+
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief set locator query timeout, the value must between 1-300 [seconds]
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_cell_locator_set_timeout(uint16_t timeout);
+
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief set locator query token, token length must be 16 bytes. the token Used to verify that 
+         the client accessing the service is valid.
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_cell_locator_set_token(char *token);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Register cell_locator callback
+  @param[in] cb
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_cell_locator_set_ind_cb(ql_cell_locator_ind_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_cell_locator_set_service_error_cb(ql_cell_locator_error_cb_f cb);
+
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Deinitialize the  cell_locator client
+  @return
+  QL_ERR_OK - successful
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_cell_locator_deinit(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief cell_locator start
+  @return
+  QL_ERR_OK - successful
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_cell_locator_start(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief cell_locator stop
+  @return
+  QL_ERR_OK - successful
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_cell_locator_stop(void);
+
+int ql_cell_locator_perform(ql_perform_rsp *rsp_ptr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_data_call.c b/mbtk/libql_lib_v2_rilv2/ql_data_call.c
new file mode 100755
index 0000000..0f18e77
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_data_call.c
@@ -0,0 +1,1621 @@
+#include "ql_type.h"
+#include "ql_data_call.h"
+#include "mbtk_info_api.h"
+
+typedef struct {
+    int apn_id;
+    ql_data_call_apn_config_t apn_info;
+} mbtk_data_call_apn_param_info_t;
+
+typedef struct {
+    QL_NET_DATA_CALL_RECONNECT_MODE_E reconnect_mode;
+    int time_num;
+    int time_list[QL_NET_MAX_RECONNECT_INTERVAL_LEN];
+    mbtk_data_call_apn_param_info_t *apn_param;     // Point to data_call_apn_param_list.
+} mbtk_data_call_param_info_t;
+
+typedef struct {
+    ql_data_call_item_t call_info;
+    int is_background;
+
+    ql_data_call_status_t call_state;
+
+    mbtk_data_call_param_info_t call_param_info;
+} mbtk_data_call_info_t;
+
+static mbtk_info_handle_t* ql_info_handle = NULL;
+static mbtk_data_call_info_t data_call_info[QL_NET_MAX_DATA_CALL_NUM];
+static mbtk_data_call_apn_param_info_t data_call_apn_param_list[QL_NET_MAX_DATA_CALL_NUM];
+static ql_data_call_service_error_cb_f data_call_service_error_cb = NULL;
+static ql_data_call_status_ind_cb_f data_call_status_ind_cb = NULL;
+
+static int call_index_get_by_call_id(int call_id)
+{
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].call_info.call_id == call_id) {
+            break;
+        }
+        i++;
+    }
+
+    if(i == QL_NET_MAX_DATA_CALL_NUM) {
+        return -1;
+    } else {
+        return i;
+    }
+}
+
+static int call_index_get_by_apn_id(int apn_id)
+{
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].call_param_info.apn_param &&
+            data_call_info[i].call_param_info.apn_param->apn_id == apn_id) {
+            break;
+        }
+        i++;
+    }
+
+    if(i == QL_NET_MAX_DATA_CALL_NUM) {
+        return -1;
+    } else {
+        return i;
+    }
+}
+
+static void data_call_info_list_print()
+{
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].call_info.call_id > 0) {
+            LOGD("CALL START : call_id - %d, call_name - %s, is_background - %d", data_call_info[i].call_info.call_id, data_call_info[i].call_info.call_name,
+                data_call_info[i].is_background);
+            LOGD("call_state : ip_ver - %d, call_status - %d, device - %s", data_call_info[i].call_state.ip_ver,
+            data_call_info[i].call_state.call_status, data_call_info[i].call_state.device);
+            LOGD("param_info : reconnect_mode - %d, time_num - %d", data_call_info[i].call_param_info.reconnect_mode,
+                data_call_info[i].call_param_info.time_num);
+            int j = 0;
+            while(j < data_call_info[i].call_param_info.time_num) {
+                LOGD("time_item[%d] - %d", j, data_call_info[i].call_param_info.time_list[j]);
+                j++;
+            }
+
+            if(data_call_info[i].call_param_info.apn_param) {
+                LOGD("apn_param : apn_id - %d, auth_pref - %d, ip_ver - %d, apn_name - %s, username - %s, password - %s", data_call_info[i].call_param_info.apn_param->apn_id,
+                    data_call_info[i].call_param_info.apn_param->apn_info.auth_pref,
+                    data_call_info[i].call_param_info.apn_param->apn_info.ip_ver,
+                    data_call_info[i].call_param_info.apn_param->apn_info.apn_name,
+                    data_call_info[i].call_param_info.apn_param->apn_info.username,
+                    data_call_info[i].call_param_info.apn_param->apn_info.password);
+            } else {
+                LOGE("data_call_info[i]->call_param_info->apn_param is NULL.");
+            }
+        }
+        i++;
+    }
+}
+
+static void data_call_info_item_print(int call_id)
+{
+    int i = call_index_get_by_call_id(call_id);
+    if(i >= 0) {
+        LOGD("CALL START : call_id - %d, call_name - %s, is_background - %d", data_call_info[i].call_info.call_id, data_call_info[i].call_info.call_name,
+            data_call_info[i].is_background);
+        LOGD("call_state : ip_ver - %d, call_status - %d, device - %s", data_call_info[i].call_state.ip_ver,
+        data_call_info[i].call_state.call_status, data_call_info[i].call_state.device);
+        LOGD("param_info : reconnect_mode - %d, time_num - %d", data_call_info[i].call_param_info.reconnect_mode,
+            data_call_info[i].call_param_info.time_num);
+        int j = 0;
+        while(j < data_call_info[i].call_param_info.time_num) {
+            LOGD("time_item[%d] - %d", j, data_call_info[i].call_param_info.time_list[j]);
+            j++;
+        }
+
+        if(data_call_info[i].call_param_info.apn_param) {
+            LOGD("apn_param : apn_id - %d, auth_pref - %d, ip_ver - %d, apn_name - %s, username - %s, password - %s", data_call_info[i].call_param_info.apn_param->apn_id,
+                data_call_info[i].call_param_info.apn_param->apn_info.auth_pref,
+                data_call_info[i].call_param_info.apn_param->apn_info.ip_ver,
+                data_call_info[i].call_param_info.apn_param->apn_info.apn_name,
+                data_call_info[i].call_param_info.apn_param->apn_info.username,
+                data_call_info[i].call_param_info.apn_param->apn_info.password);
+        } else {
+            LOGE("data_call_info[i]->call_param_info->apn_param is NULL.");
+        }
+    }
+}
+
+
+static void ril_server_state_cb(const void* data, int data_len)
+{
+    if(data != NULL && data_len == sizeof(int)) {
+        const int *state = (const int*)data;
+        if(*state) {
+            if(data_call_service_error_cb) {
+                data_call_service_error_cb(QL_ERR_ABORTED);
+            }
+        }
+    }
+}
+
+static void data_call_state_change_cb(const void* data, int data_len)
+{
+    LOGD("data_call_state_change_cb() start.");
+    if(data == NULL || data_len == 0)
+    {
+        return;
+    }
+
+    // data_call_info_print();
+
+    uint8 *net_data = NULL;
+    net_data = (uint8 *)data;
+
+    if(*net_data > 100 && *net_data < 200)
+    {
+        int apn_id = *net_data - 100;
+        if(apn_id <= QL_NET_MAX_DATA_CALL_NUM)
+        {
+            int i = 0;
+            while(i < QL_NET_MAX_DATA_CALL_NUM) {
+
+                if(data_call_info[i].call_param_info.apn_param) {
+                    if(data_call_info[i].call_param_info.apn_param->apn_id == apn_id) {
+                        break;
+                    } else {
+                        LOGD("call_id = %d, apn_id = %d", data_call_info[i].call_info.call_id,
+                            data_call_info[i].call_param_info.apn_param->apn_id);
+                    }
+                }
+                i++;
+            }
+
+            if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this apn_id.
+                LOGW("Unknown apn_id : %d", apn_id);
+                return;
+            } else {
+                QL_NET_DATA_CALL_STATUS_E pre_call_status = data_call_info[i].call_state.call_status;
+                data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED;
+                if(data_call_status_ind_cb) {
+                    data_call_status_ind_cb(data_call_info[i].call_info.call_id, pre_call_status,
+                        &(data_call_info[i].call_state));
+                }
+            }
+        }
+        else
+        {
+            LOGE("[qser_data] cb fail,idx is %d.", apn_id);
+        }
+
+    }
+    else if(*net_data > 200 && *net_data < 220)
+    {
+        LOGE("[qser_data] cid[%d] is open.", *net_data - 200);
+    }
+    else if(*net_data > 220)
+    {
+        LOGE("[qser_data] cid[%d] is reopen.", *net_data - 220);
+        int apn_id = *net_data - 220;
+        if(apn_id <= QL_NET_MAX_DATA_CALL_NUM)
+        {
+            int i = 0;
+            while(i < QL_NET_MAX_DATA_CALL_NUM) {
+                if(data_call_info[i].call_param_info.apn_param
+                    && data_call_info[i].call_param_info.apn_param->apn_id == apn_id) {
+                    break;
+                }
+                i++;
+            }
+
+            if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this apn_id.
+                LOGW("Unknown apn_id : %d", apn_id);
+                return;
+            } else {
+                QL_NET_DATA_CALL_STATUS_E pre_call_status = data_call_info[i].call_state.call_status;
+                data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_CONNECTED;
+                if(data_call_status_ind_cb) {
+                    data_call_status_ind_cb(data_call_info[i].call_info.call_id, pre_call_status,
+                        &(data_call_info[i].call_state));
+                }
+            }
+        }
+    }
+    else if(*net_data == 1)
+    {
+        LOGE("[qser_data] pdp is open.");
+    }
+    else
+    {
+        LOGE("[qser_data] unkonwn param [%d].", *net_data);
+    }
+}
+
+static int data_call_state_query(int call_id)
+{
+    int i = call_index_get_by_call_id(call_id);
+    if(i < 0) {
+        LOGE("Unknown call_id : %d", call_id);
+        return -1;
+    }
+
+    // Get network information.
+    mbtk_ipv4_info_t ipv4;
+    mbtk_ipv6_info_t ipv6;
+    QL_NET_DATA_CALL_STATUS_E pre_call_status = data_call_info[i].call_state.call_status;
+    int ret = mbtk_data_call_state_get(ql_info_handle, data_call_info[i].call_param_info.apn_param->apn_id, &ipv4, &ipv6);
+    if(ret != 0)
+    {
+        LOGE("mbtk_data_call_state_get fail.[ret = %d]", ret);
+        data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_ERROR;
+        return -1;
+    }
+    else
+    {
+        data_call_info[i].call_state.has_addr = ipv4.valid;
+        if(ipv4.valid)
+        {
+            if(inet_ntop(AF_INET, &(ipv4.IPAddr), data_call_info[i].call_state.addr.addr , QL_NET_MAX_ADDR_LEN) == NULL) {
+                LOGE("IPv4 error.");
+            } else {
+                LOGD("IPv4 : %s", data_call_info[i].call_state.addr.addr);
+            }
+
+            if(inet_ntop(AF_INET, &(ipv4.NetMask), data_call_info[i].call_state.addr.netmask , QL_NET_MAX_ADDR_LEN) == NULL) {
+                LOGE("NetMask error.");
+            } else {
+                LOGD("NetMask : %s", data_call_info[i].call_state.addr.netmask);
+            }
+
+            if(inet_ntop(AF_INET, &(ipv4.GateWay), data_call_info[i].call_state.addr.gateway , QL_NET_MAX_ADDR_LEN) == NULL) {
+                LOGE("GateWay error.");
+            } else {
+                LOGD("GateWay : %s", data_call_info[i].call_state.addr.gateway);
+            }
+
+            if(inet_ntop(AF_INET, &(ipv4.PrimaryDNS), data_call_info[i].call_state.addr.dnsp , QL_NET_MAX_ADDR_LEN) == NULL) {
+                LOGE("PrimaryDNS error.");
+            } else {
+                LOGD("PrimaryDNS : %s", data_call_info[i].call_state.addr.dnsp);
+            }
+
+            if(inet_ntop(AF_INET, &(ipv4.SecondaryDNS), data_call_info[i].call_state.addr.dnss , QL_NET_MAX_ADDR_LEN) == NULL) {
+                LOGE("SecondaryDNS error.");
+            } else {
+                LOGD("SecondaryDNS : %s", data_call_info[i].call_state.addr.dnss);
+            }
+        }
+
+        data_call_info[i].call_state.has_addr6 = ipv6.valid;
+        if(ipv6.valid)
+        {
+            if(ipv6_2_str(&(ipv6.IPV6Addr), data_call_info[i].call_state.addr6.addr)) {
+                LOGE("IPv6 error.");
+            } else {
+                LOGD("IPv6 : %s", data_call_info[i].call_state.addr6.addr);
+            }
+
+            if(ipv6_2_str(&(ipv6.NetMask), data_call_info[i].call_state.addr6.prefix)) {
+                LOGE("prefix error.");
+            } else {
+                LOGD("prefix : %s", data_call_info[i].call_state.addr6.prefix);
+            }
+
+            if(ipv6_2_str(&(ipv6.GateWay), data_call_info[i].call_state.addr6.gateway)) {
+                LOGE("GateWay error.");
+            } else {
+                LOGD("GateWay : %s", data_call_info[i].call_state.addr6.gateway);
+            }
+
+            if(ipv6_2_str(&(ipv6.PrimaryDNS), data_call_info[i].call_state.addr6.dnsp)) {
+                LOGE("PrimaryDNS error.");
+            } else {
+                LOGD("PrimaryDNS : %s", data_call_info[i].call_state.addr6.dnsp);
+            }
+
+            if(ipv6_2_str(&(ipv6.SecondaryDNS), data_call_info[i].call_state.addr6.dnsp)) {
+                LOGE("SecondaryDNS error.");
+            } else {
+                LOGD("SecondaryDNS : %s", data_call_info[i].call_state.addr6.dnsp);
+            }
+        }
+
+        pre_call_status = data_call_info[i].call_state.call_status;
+#if 1
+        if(data_call_info[i].call_state.ip_ver == QL_NET_IP_VER_V4V6) {
+            if(ipv4.valid && !ipv6.valid) {
+                data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_PARTIAL_V4_CONNECTED;
+            } else if(!ipv4.valid && ipv6.valid) {
+                data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_PARTIAL_V6_CONNECTED;
+            } else if(ipv4.valid && ipv6.valid) {
+                data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_CONNECTED;
+            } else {
+                data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED;
+            }
+        } else if(data_call_info[i].call_state.ip_ver == QL_NET_IP_VER_V4) {
+            if(ipv4.valid) {
+                data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_CONNECTED;
+            } else {
+                data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED;
+            }
+        } else if(data_call_info[i].call_state.ip_ver == QL_NET_IP_VER_V6) {
+            if(ipv6.valid) {
+                data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_CONNECTED;
+            } else {
+                data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED;
+            }
+        } else {
+            data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED;
+        }
+#else
+        if(ipv4.valid && ipv6.valid) {
+            data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_CONNECTED;
+        } else if(!ipv4.valid && ipv6.valid) {
+            data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_PARTIAL_V6_CONNECTED;
+        } else if(ipv4.valid && !ipv6.valid) {
+            data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_PARTIAL_V4_CONNECTED;
+        } else {
+            data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED;
+        }
+#endif
+
+        if(data_call_status_ind_cb) {
+            data_call_status_ind_cb(call_id, pre_call_status,
+                &(data_call_info[i].call_state));
+        }
+    }
+
+    return 0;
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Initialize the data call service
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_init(void)
+{
+    if(ql_info_handle == NULL)
+    {
+
+        mbtk_log_init("radio", "QL_DATA_CALL");
+
+        ql_info_handle = mbtk_info_handle_get();
+        if(ql_info_handle)
+        {
+            memset(&data_call_info, 0, sizeof(data_call_info));
+            memset(&data_call_apn_param_list, 0, sizeof(data_call_apn_param_list));
+            return QL_ERR_OK;
+        } else {
+            LOGE("mbtk_info_handle_get() fail.");
+            return QL_ERR_UNKNOWN;
+        }
+    } else {
+        return QL_ERR_UNKNOWN;
+    }
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Create a data call instance
+  @param[in] call_id The unique identifier of the data call instance, specified by the user
+  @param[in] call_name Friendly data call name,  specified by the user
+  @param[in] is_background Whether the data call status is maintained by the data call service daemon.
+  If it is 0, the data call instance will be deleted after the data call process exits.
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_create(int call_id, const char *call_name, int is_background)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(call_id <= 0 || call_name == NULL || strlen(call_name) == 0
+        || strlen(call_name) > QL_NET_MAX_NAME_LEN) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].call_info.call_id == 0) { // Not use.
+            break;
+        }
+        i++;
+    }
+
+    if(i == QL_NET_MAX_DATA_CALL_NUM) { // data_call item full.
+        LOGW("data_call instance is full.");
+        return QL_ERR_UNKNOWN;
+    }
+
+    data_call_info[i].call_info.call_id = call_id;
+    memcpy(data_call_info[i].call_info.call_name, call_name, strlen(call_name));
+    data_call_info[i].call_state.call_id = call_id;
+    memcpy(data_call_info[i].call_state.call_name, call_name, strlen(call_name));
+
+    data_call_info[i].is_background = is_background;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Alloc for a data call configuration instance
+  @return
+  NULL - Not enough memory
+  Other - successful
+  */
+/*-----------------------------------------------------------------------------------------------*/
+ql_data_call_param_t *ql_data_call_param_alloc(void)
+{
+    ql_data_call_param_t *result = malloc(sizeof(mbtk_data_call_param_info_t));
+    if(result) {
+        memset(result, 0, sizeof(mbtk_data_call_param_info_t));
+    }
+
+    return result;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Initialize the data call configuration instance
+  @param[in] param Point to the data call configuration instance
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_init(ql_data_call_param_t *param)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    memset(info, 0, sizeof(mbtk_data_call_param_info_t));
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Release the data call configuration instance
+  @param[in] param Point to the data call configuration instance
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_free(ql_data_call_param_t *param)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    free(param);
+
+    return QL_ERR_OK;
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Bind APN ID, range:1-16
+  @param[in] param Point to the data call configuration instance
+  @param[in] apn_id APN ID, range:1-16
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_set_apn_id(ql_data_call_param_t *param, int apn_id)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    // 1 - 7
+    if(param == NULL || apn_id <= 0 || apn_id > QL_NET_MAX_APN_ID) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_apn_param_list[i].apn_id == apn_id) {
+            break;
+        }
+        i++;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param != NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    if(i == QL_NET_MAX_DATA_CALL_NUM) {
+        LOGW("No found apn_id : %d.", apn_id);
+        // Found next empty apn item.
+        int j = 0;
+        while(j < QL_NET_MAX_DATA_CALL_NUM) {
+            if(data_call_apn_param_list[j].apn_id <= 0) {
+                break;
+            }
+            j++;
+        }
+        if(j == QL_NET_MAX_DATA_CALL_NUM) { // Full
+            return QL_ERR_UNKNOWN;
+        }
+
+        info->apn_param = &(data_call_apn_param_list[j]);
+        info->apn_param->apn_id = apn_id;
+    } else {
+        // Found apn_id
+        info->apn_param = &(data_call_apn_param_list[i]);
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get APN name from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] buf APN ID
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_get_apn_id(ql_data_call_param_t *param, int *apn_id)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || apn_id == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    *apn_id = info->apn_param->apn_id;
+
+    return QL_ERR_OK;
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure APN name
+  @param[in] param Point to the data call configuration instance
+  @param[in] apn_name APN name
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_set_apn_name(ql_data_call_param_t *param, const char *apn_name)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || apn_name == NULL || strlen(apn_name) == 0
+        || strlen(apn_name) > QL_NET_MAX_APN_NAME_LEN) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    memcpy(info->apn_param->apn_info.apn_name, apn_name, strlen(apn_name));
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get APN name from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] buf APN name buffer
+  @param[in] buf_len APN name buffer size
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_get_apn_name(ql_data_call_param_t *param, char *buf, int buf_len)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || buf == NULL || buf_len <= 0) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    if(strlen(info->apn_param->apn_info.apn_name) + 1 > buf_len) {
+        return QL_ERR_INVALID_ARG;
+    }
+    memcpy(buf, info->apn_param->apn_info.apn_name, strlen(info->apn_param->apn_info.apn_name));
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure APN user name
+  @param[in] param Point to the data call configuration instance
+  @param[in] user_name APN user name
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_set_user_name(ql_data_call_param_t *param, const char *user_name)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || user_name == NULL || strlen(user_name) == 0
+        || strlen(user_name) > QL_NET_MAX_APN_USERNAME_LEN) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    memcpy(info->apn_param->apn_info.username, user_name, strlen(user_name));
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get APN user name from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] buf APN user name buffer
+  @param[in] buf_len APN user name buffer size
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_get_user_name(ql_data_call_param_t *param, char *buf, int buf_len)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || buf == NULL || buf_len <= 0) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    if(strlen(info->apn_param->apn_info.username) + 1 > buf_len) {
+        return QL_ERR_INVALID_ARG;
+    }
+    memcpy(buf, info->apn_param->apn_info.username, strlen(info->apn_param->apn_info.username));
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure APN user password
+  @param[in] param Point to the data call configuration instance
+  @param[in] user_password APN user password
+  @return
+  QL_ERR_OK - Not enough memory
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_set_user_password(ql_data_call_param_t *param, const char *user_password)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || user_password == NULL || strlen(user_password) == 0
+        || strlen(user_password) > QL_NET_MAX_APN_PASSWORD_LEN) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    memcpy(info->apn_param->apn_info.password, user_password, strlen(user_password));
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get APN user password from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] buf APN user password buffer
+  @param[in] buf_len APN user password buffer size
+  @return
+  QL_ERR_OK - Not enough memory
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_get_user_password(ql_data_call_param_t *param, char *buf, int buf_len)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || buf == NULL || buf_len <= 0) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    if(strlen(info->apn_param->apn_info.password) + 1 > buf_len) {
+        return QL_ERR_INVALID_ARG;
+    }
+    memcpy(buf, info->apn_param->apn_info.password, strlen(info->apn_param->apn_info.password));
+
+    return QL_ERR_OK;
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the data call authentication method
+  @param[in] param Point to the data call configuration instance
+  @param[in] auth_pref Defined by QL_DATA_CALL_AUTH_PREF_E
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_set_auth_pref(ql_data_call_param_t *param, int auth_pref)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    info->apn_param->apn_info.auth_pref = (QL_NET_AUTH_PREF_E)auth_pref;
+
+    return QL_ERR_OK;
+
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the data call authentication method
+  @param[in] param Point to the data call configuration instance
+  @param[out] p_data Store return value
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_get_auth_pref(ql_data_call_param_t *param, int *p_data)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || p_data == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    *p_data = info->apn_param->apn_info.auth_pref;
+
+    return QL_ERR_OK;
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the data call IP version
+  @param[in] param Point to the data call configuration instance
+  @param[in] ip_ver Defined by QL_NET_IP_VER_E
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_set_ip_version(ql_data_call_param_t *param, int ip_ver)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    info->apn_param->apn_info.ip_ver = (QL_NET_IP_VER_E)ip_ver;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get IP version from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] p_ver Store return value
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_get_ip_version(ql_data_call_param_t *param, int *p_ver)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || p_ver == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    *p_ver = info->apn_param->apn_info.ip_ver;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the data call auto reconnection mode
+  @param[in] param Point to the data call configuration instance
+  @param[in] mode Defined by QL_NET_DATA_CALL_RECONNECT_MODE_E
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_set_reconnect_mode(ql_data_call_param_t *param, int reconnect_mode)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    info->reconnect_mode = reconnect_mode;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get auto reconnection mode from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] p_mode Store return value
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_get_reconnect_mode(ql_data_call_param_t *param, int *p_mode)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || p_mode == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    *p_mode = info->reconnect_mode;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the data call auto reconnection interval
+  @param[in] param Point to the data call configuration instance
+  @param[in] time_list Interval time list in ms
+  @param[in] num Number of time list
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_set_reconnect_interval(ql_data_call_param_t *param, int *time_list, int num)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || time_list == NULL || num <= 0 || num > QL_NET_MAX_RECONNECT_INTERVAL_LEN) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    info->time_num = num;
+    memcpy(&(info->time_list), time_list, sizeof(int) * num);
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get auto reconnection interval from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] time_list Store return value
+  @param[in,out] p_num
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_get_reconnect_interval(ql_data_call_param_t *param, int *time_list, int *p_num)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || time_list == NULL || p_num == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    *p_num = info->time_num;
+    int i = 0;
+    for(; i < info->time_num; i++) {
+        *(time_list + i) = info->time_list[i];
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the specified data call instance
+  @param[in] call_id Specify a data call instance
+  @param[in] param Point to the data call configuration instance
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_config(int call_id, ql_data_call_param_t *param)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].call_info.call_id == call_id) {
+            break;
+        }
+        i++;
+    }
+
+    if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this call_id.
+        LOGW("Unknown call_id : %d", call_id);
+        return QL_ERR_UNKNOWN;
+    }
+
+    memcpy(&(data_call_info[i].call_param_info), param, sizeof(mbtk_data_call_param_info_t));;
+
+    if(data_call_info[i].call_param_info.apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    snprintf(data_call_info[i].call_state.device, QL_NET_MAX_NAME_LEN, "ccinet%d",
+        data_call_info[i].call_param_info.apn_param->apn_id - 1);
+    data_call_info[i].call_state.ip_ver = data_call_info[i].call_param_info.apn_param->apn_info.ip_ver;
+    data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_IDLE;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get the specified data call configuration instance
+  @param[in] call_id Specify a data call instance
+  @param[in] param Point to the data call configuration instance
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_get_config(int call_id, ql_data_call_param_t *param)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].call_info.call_id == call_id) {
+            break;
+        }
+        i++;
+    }
+
+    if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this call_id.
+        LOGW("Unknown call_id : %d", call_id);
+        return QL_ERR_UNKNOWN;
+    }
+
+    memcpy(param, &(data_call_info[i].call_param_info), sizeof(mbtk_data_call_param_info_t));
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Start data call
+  @param[in] call_id Specify a data call instance
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_start(int call_id)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    int i = call_index_get_by_call_id(call_id);
+    if(i < 0) {
+        LOGE("Unknown call_id : %d", call_id);
+        return QL_ERR_UNKNOWN;
+    }
+
+    if(data_call_info[i].call_param_info.apn_param == NULL) {
+        LOGE("data_call_info[i]->call_param_info->apn_param is NULL.");
+        return QL_ERR_UNKNOWN;
+    }
+
+    int ret = data_call_state_query(call_id);
+    if(ret) {
+        LOGE("data_call_state_query fail.");
+        data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_IDLE;
+        // return QL_ERR_UNKNOWN;
+    }
+
+    if(data_call_info[i].call_state.call_status == QL_NET_DATA_CALL_STATUS_PARTIAL_V4_CONNECTED
+        || data_call_info[i].call_state.call_status == QL_NET_DATA_CALL_STATUS_PARTIAL_V6_CONNECTED
+        || data_call_info[i].call_state.call_status == QL_NET_DATA_CALL_STATUS_CONNECTED) {
+        LOGW("call_id %d has connected.", call_id);
+        return QL_ERR_UNKNOWN;
+    }
+
+    LOGD("Start Data Call : %d", call_id);
+    data_call_info_item_print(call_id);
+
+    // Set APN in the first.
+    mbtk_ip_type_enum ip_type;
+    switch(data_call_info[i].call_param_info.apn_param->apn_info.ip_ver) {
+        case QL_NET_IP_VER_V4:
+            ip_type = MBTK_IP_TYPE_IP;
+            break;
+        case QL_NET_IP_VER_V6:
+            ip_type = MBTK_IP_TYPE_IPV6;
+            break;
+        case QL_NET_IP_VER_V4V6:
+            ip_type = MBTK_IP_TYPE_IPV4V6;
+            break;
+        default:
+            LOGE("Unknown ip_ver.");
+            return QL_ERR_UNKNOWN;
+    }
+
+    char auth_type[64]={0};
+    switch(data_call_info[i].call_param_info.apn_param->apn_info.auth_pref) {
+        case QL_NET_AUTH_PREF_PAP_CHAP_NOT_ALLOWED:
+            memcpy(auth_type,"NONE",strlen("NONE"));
+            break;
+        case QL_NET_AUTH_PREF_PAP_ONLY_ALLOWED:
+            memcpy(auth_type,"PAP",strlen("PAP"));
+            break;
+        case QL_NET_AUTH_PREF_CHAP_ONLY_ALLOWED:
+            memcpy(auth_type,"CHAP",strlen("CHAP"));
+            break;
+#if 0
+        case QL_NET_AUTH_PREF_PAP_CHAP_BOTH_ALLOWED:
+            apninfo.auth_proto = MBTK_APN_AUTH_PROTO_PAP_CHAP;
+            break;
+#endif
+        default:
+            LOGE("Unknown auth_pref.");
+            return QL_ERR_UNKNOWN;
+    }
+
+    ret = mbtk_apn_set(ql_info_handle, data_call_info[i].call_param_info.apn_param->apn_id, ip_type,
+                data_call_info[i].call_param_info.apn_param->apn_info.apn_name,
+                data_call_info[i].call_param_info.apn_param->apn_info.username,
+                data_call_info[i].call_param_info.apn_param->apn_info.password, auth_type);
+    if(ret) {
+        LOGE("mbtk_apn_set fail.");
+        return QL_ERR_UNKNOWN;
+    }
+
+    // Start data call.
+    int auto_conn_interval = 0;
+    QL_NET_DATA_CALL_STATUS_E pre_call_status = data_call_info[i].call_state.call_status;
+    data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_CONNECTING;
+    if(data_call_status_ind_cb) {
+        data_call_status_ind_cb(call_id, pre_call_status,
+            &(data_call_info[i].call_state));
+    }
+
+    if(data_call_info[i].call_param_info.reconnect_mode == QL_NET_DATA_CALL_RECONNECT_NORMAL
+        || data_call_info[i].call_param_info.reconnect_mode == QL_NET_DATA_CALL_RECONNECT_MODE_1
+        || data_call_info[i].call_param_info.reconnect_mode == QL_NET_DATA_CALL_RECONNECT_MODE_2) {
+        if(data_call_info[i].call_param_info.time_num > 0) {
+            auto_conn_interval = data_call_info[i].call_param_info.time_list[0];
+        }
+    } else {
+        auto_conn_interval = 0;
+    }
+
+    ret = mbtk_data_call_start(ql_info_handle, data_call_info[i].call_param_info.apn_param->apn_id, auto_conn_interval,
+                FALSE, 0);
+    if(ret) {
+        LOGE("mbtk_data_call_start fail.");
+        data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_ERROR;
+        return QL_ERR_UNKNOWN;
+    }
+
+    ret = data_call_state_query(call_id);
+    if(ret) {
+        LOGE("data_call_state_query fail.");
+        data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_ERROR;
+        return QL_ERR_UNKNOWN;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Stop data call
+  @param[in] call_id Specify a data call instance
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_stop(int call_id)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].call_info.call_id == call_id) {
+            break;
+        }
+        i++;
+    }
+
+    if(data_call_info[i].call_param_info.apn_param) {
+        int ret = mbtk_data_call_stop(ql_info_handle, data_call_info[i].call_param_info.apn_param->apn_id, 15);
+        if(ret) {
+            LOGE("mbtk_data_call_stop() fail.");
+            return QL_ERR_UNKNOWN;
+        }
+    } else {
+        LOGE("data_call_info[i]->call_param_info->apn_param is NULL.");
+        return QL_ERR_UNKNOWN;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Delete a data call instance
+  @param[in] call_id Specify a data call instance
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_delete(int call_id)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].call_info.call_id == call_id) {
+            break;
+        }
+        i++;
+    }
+
+    if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this call_id.
+        LOGW("Unknown call_id : %d", call_id);
+        return QL_ERR_UNKNOWN;
+    }
+
+    if(data_call_info[i].call_param_info.apn_param) {
+        memset(data_call_info[i].call_param_info.apn_param, 0, sizeof(mbtk_data_call_apn_param_info_t));
+    }
+    memset(&(data_call_info[i]), 0, sizeof(mbtk_data_call_info_t));
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get the current data call instance list
+  @param[out] list Data call instance array
+  @param[in,out] list_len, in-> Data call instance array size, out->current data call instance number
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_get_list(ql_data_call_item_t *list, int *list_len)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(list == NULL || list_len == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int i = 0;
+    *list_len = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].call_info.call_id > 0) {
+            memset(&(list[*list_len]), 0, sizeof(ql_data_call_item_t));
+            list[*list_len].call_id = data_call_info[i].call_info.call_id;
+            memcpy(list[*list_len].call_name, data_call_info[i].call_info.call_name,
+                strlen(data_call_info[i].call_info.call_name));
+
+            (*list_len)++;
+        }
+        i++;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get the data call status
+  @param[in] call_id Specify a data call instance
+  @param[out] p_sta Point to status instance
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_get_status(int call_id, ql_data_call_status_t *p_sta)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(p_sta == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].call_info.call_id == call_id) {
+            break;
+        }
+        i++;
+    }
+
+    if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this call_id.
+        LOGW("Unknown call_id : %d", call_id);
+        return QL_ERR_UNKNOWN;
+    }
+
+    memcpy(p_sta, &(data_call_info[i].call_state), sizeof(ql_data_call_status_t));
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Register data call status change event
+  @param[in] cb
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_set_status_ind_cb(ql_data_call_status_ind_cb_f cb)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_UNKNOWN;
+    } else {
+        if(mbtk_pdp_state_change_cb_reg(ql_info_handle, data_call_state_change_cb))
+        {
+            return QL_ERR_UNKNOWN;
+        }
+
+        data_call_status_ind_cb = cb;
+        return QL_ERR_OK;
+    }
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Set APN related configuration.If the apn does not exist, it is automatically created.
+  @param[in] apn_id APN ID, range:1-16
+  @param[in] p_info APN configuration
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_set_apn_config(int apn_id, ql_data_call_apn_config_t *p_info)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(p_info == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].call_param_info.apn_param
+            && data_call_info[i].call_param_info.apn_param->apn_id == apn_id) {
+            break;
+        }
+        i++;
+    }
+
+    if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this apn_id.
+        LOGW("New apn_id : %d", apn_id);
+        // New data call param.
+        int j = 0;
+        while(j < QL_NET_MAX_DATA_CALL_NUM) {
+            if(data_call_apn_param_list[j].apn_id <= 0) {
+                break;
+            }
+            j++;
+        }
+
+        if(j == QL_NET_MAX_DATA_CALL_NUM) { // Full
+            LOGW("data_call_apn_param_list is full.");
+            return QL_ERR_UNKNOWN;
+        }
+
+        data_call_apn_param_list[j].apn_id = apn_id;
+        memcpy(&(data_call_apn_param_list[j].apn_info), p_info, sizeof(ql_data_call_apn_config_t));
+    } else {
+        memcpy(&(data_call_info[i].call_param_info.apn_param->apn_info), p_info, sizeof(ql_data_call_apn_config_t));
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Set APN related configuration. If the apn does not exist, it is automatically created and
+  the default parameters are set.
+  @param[in] apn_id APN ID, range:1-16
+  @param[out] p_info APN configuration
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_get_apn_config(int apn_id, ql_data_call_apn_config_t *p_info)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(p_info == NULL || p_info == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].call_param_info.apn_param
+            && data_call_info[i].call_param_info.apn_param->apn_id == apn_id) {
+            break;
+        }
+        i++;
+    }
+
+    if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this apn_id.
+        LOGE("Unknown apn_id : %d", apn_id);
+        return QL_ERR_UNKNOWN;
+    } else {
+        memcpy(p_info, &(data_call_info[i].call_param_info.apn_param->apn_info), sizeof(ql_data_call_apn_config_t));
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Set APN related configuration,APN ID:1
+  @param[in] p_info APN configuration
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_set_attach_apn_config(ql_data_call_apn_config_t *p_info)
+{
+    return ql_data_call_set_apn_config(1, p_info);
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @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_data_call_set_service_error_cb(ql_data_call_service_error_cb_f cb)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_UNKNOWN;
+    } else {
+        if(mbtk_ril_server_state_change_reg(ql_info_handle, ril_server_state_cb))
+        {
+            return QL_ERR_UNKNOWN;
+        }
+
+        data_call_service_error_cb = cb;
+        return QL_ERR_OK;
+    }
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Deinitialize the data call service
+  @return
+  QL_ERR_OK - successful
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_deinit(void)
+{
+    if(ql_info_handle == NULL)
+    {
+        return QL_ERR_UNKNOWN;
+    } else {
+        if(mbtk_info_handle_free(&ql_info_handle))
+        {
+            return QL_ERR_UNKNOWN;
+        }
+
+        return QL_ERR_OK;
+    }
+}
diff --git a/mbtk/libql_lib_v2_rilv2/ql_data_call_v1.c b/mbtk/libql_lib_v2_rilv2/ql_data_call_v1.c
new file mode 100755
index 0000000..4e3c905
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_data_call_v1.c
@@ -0,0 +1,1867 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "ql_type.h"
+#include "ql_data_call.h"
+#include "mbtk_ril_api.h"
+
+typedef struct {
+    int apn_id;
+    ql_data_call_apn_config_t apn_info;
+} mbtk_data_call_apn_param_info_t;
+
+typedef struct {
+    QL_NET_DATA_CALL_RECONNECT_MODE_E reconnect_mode;
+    int time_num;
+    int time_list[QL_NET_MAX_RECONNECT_INTERVAL_LEN];
+    mbtk_data_call_apn_param_info_t *apn_param;     // Point to data_call_apn_list.
+} mbtk_data_call_param_info_t;
+
+typedef struct {
+//    ql_data_call_item_t call_info;
+    int is_background;
+
+    ql_data_call_status_t call_state;
+
+    mbtk_data_call_param_info_t *param_info;
+} ql_data_call_info_t;
+
+static mbtk_ril_handle* ql_ril_handle = NULL;
+static ql_data_call_info_t data_call_info[QL_NET_MAX_DATA_CALL_NUM];
+static mbtk_data_call_apn_param_info_t data_call_apn_list[QL_NET_MAX_DATA_CALL_NUM];
+static ql_data_call_service_error_cb_f data_call_service_error_cb = NULL;
+static ql_data_call_status_ind_cb_f data_call_status_ind_cb = NULL;
+
+static int call_index_get_by_call_id(int call_id)
+{
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].call_state.call_id == call_id) {
+            break;
+        }
+        i++;
+    }
+
+    if(i == QL_NET_MAX_DATA_CALL_NUM) {
+        return -1;
+    } else {
+        return i;
+    }
+}
+
+static int call_index_get_by_apn_id(int apn_id)
+{
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].param_info && data_call_info[i].param_info->apn_param
+            && data_call_info[i].param_info->apn_param->apn_id == apn_id) {
+            break;
+        }
+        i++;
+    }
+
+    if(i == QL_NET_MAX_DATA_CALL_NUM) {
+        return -1;
+    } else {
+        return i;
+    }
+}
+
+#if 0
+static void data_call_info_list_print()
+{
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].call_info.call_id > 0) {
+            LOGD("CALL START : call_id - %d, call_name - %s, is_background - %d", data_call_info[i].call_info.call_id, data_call_info[i].call_info.call_name,
+                data_call_info[i].is_background);
+            LOGD("call_state : ip_ver - %d, call_status - %d, device - %s", data_call_info[i].call_state.ip_ver,
+            data_call_info[i].call_state.call_status, data_call_info[i].call_state.device);
+            LOGD("param_info : reconnect_mode - %d, time_num - %d", data_call_info[i].call_param_info.reconnect_mode,
+                data_call_info[i].call_param_info.time_num);
+            int j = 0;
+            while(j < data_call_info[i].call_param_info.time_num) {
+                LOGD("time_item[%d] - %d", j, data_call_info[i].call_param_info.time_list[j]);
+                j++;
+            }
+
+            if(data_call_info[i].call_param_info.apn_param) {
+                LOGD("apn_param : apn_id - %d, auth_pref - %d, ip_ver - %d, apn_name - %s, username - %s, password - %s", data_call_info[i].call_param_info.apn_param->apn_id,
+                    data_call_info[i].call_param_info.apn_param->apn_info.auth_pref,
+                    data_call_info[i].call_param_info.apn_param->apn_info.ip_ver,
+                    data_call_info[i].call_param_info.apn_param->apn_info.apn_name,
+                    data_call_info[i].call_param_info.apn_param->apn_info.username,
+                    data_call_info[i].call_param_info.apn_param->apn_info.password);
+            } else {
+                LOGE("data_call_info[i]->call_param_info->apn_param is NULL.");
+            }
+        }
+        i++;
+    }
+}
+
+
+static void data_call_info_item_print(int call_id)
+{
+    int i = call_index_get_by_call_id(call_id);
+    if(i >= 0) {
+        LOGD("CALL START : call_id - %d, call_name - %s, is_background - %d", data_call_info[i].call_info.call_id, data_call_info[i].call_info.call_name,
+            data_call_info[i].is_background);
+        LOGD("call_state : ip_ver - %d, call_status - %d, device - %s", data_call_info[i].call_state.ip_ver,
+        data_call_info[i].call_state.call_status, data_call_info[i].call_state.device);
+        LOGD("param_info : reconnect_mode - %d, time_num - %d", data_call_info[i].call_param_info.reconnect_mode,
+            data_call_info[i].call_param_info.time_num);
+        int j = 0;
+        while(j < data_call_info[i].call_param_info.time_num) {
+            LOGD("time_item[%d] - %d", j, data_call_info[i].call_param_info.time_list[j]);
+            j++;
+        }
+
+        if(data_call_info[i].call_param_info.apn_param) {
+            LOGD("apn_param : apn_id - %d, auth_pref - %d, ip_ver - %d, apn_name - %s, username - %s, password - %s", data_call_info[i].call_param_info.apn_param->apn_id,
+                data_call_info[i].call_param_info.apn_param->apn_info.auth_pref,
+                data_call_info[i].call_param_info.apn_param->apn_info.ip_ver,
+                data_call_info[i].call_param_info.apn_param->apn_info.apn_name,
+                data_call_info[i].call_param_info.apn_param->apn_info.username,
+                data_call_info[i].call_param_info.apn_param->apn_info.password);
+        } else {
+            LOGE("data_call_info[i]->call_param_info->apn_param is NULL.");
+        }
+    }
+}
+#endif
+
+
+static void ril_server_state_cb(const void* data, int data_len)
+{
+    if(data != NULL && data_len == sizeof(int)) {
+        const int *state = (const int*)data;
+        if(*state) {
+            if(data_call_service_error_cb) {
+                data_call_service_error_cb(QL_ERR_ABORTED);
+            }
+        }
+    }
+}
+
+static int data_call_status_update_by_ipv4v6(const mbtk_ip_info_t *ip_info, ql_data_call_status_t *p_sta)
+{
+    if(ip_info->ipv4.valid)
+    {
+        p_sta->has_addr = ip_info->ipv4.valid;
+        if(inet_ntop(AF_INET, &(ip_info->ipv4.IPAddr), p_sta->addr.addr , QL_NET_MAX_ADDR_LEN) == NULL) {
+            LOGE("IPv4 error.");
+        } else {
+            LOGD("IPv4 : %s", p_sta->addr.addr);
+        }
+
+        if(inet_ntop(AF_INET, &(ip_info->ipv4.NetMask), p_sta->addr.netmask , QL_NET_MAX_ADDR_LEN) == NULL) {
+            LOGE("NetMask error.");
+        } else {
+            LOGD("NetMask : %s", p_sta->addr.netmask);
+        }
+
+        if(inet_ntop(AF_INET, &(ip_info->ipv4.GateWay), p_sta->addr.gateway , QL_NET_MAX_ADDR_LEN) == NULL) {
+            LOGE("GateWay error.");
+        } else {
+            LOGD("GateWay : %s", p_sta->addr.gateway);
+        }
+
+        if(inet_ntop(AF_INET, &(ip_info->ipv4.PrimaryDNS), p_sta->addr.dnsp , QL_NET_MAX_ADDR_LEN) == NULL) {
+            LOGE("PrimaryDNS error.");
+        } else {
+            LOGD("PrimaryDNS : %s", p_sta->addr.dnsp);
+        }
+
+        if(inet_ntop(AF_INET, &(ip_info->ipv4.SecondaryDNS), p_sta->addr.dnss , QL_NET_MAX_ADDR_LEN) == NULL) {
+            LOGE("SecondaryDNS error.");
+        } else {
+            LOGD("SecondaryDNS : %s", p_sta->addr.dnss);
+        }
+    }
+
+    if(ip_info->ipv6.valid)
+    {
+        p_sta->has_addr6 = ip_info->ipv6.valid;
+        if(ipv6_2_str(&(ip_info->ipv6.IPV6Addr), p_sta->addr6.addr)) {
+            LOGE("IPv6 error.");
+        } else {
+            LOGD("IPv6 : %s", p_sta->addr6.addr);
+        }
+
+        if(ipv6_2_str(&(ip_info->ipv6.NetMask), p_sta->addr6.prefix)) {
+            LOGE("prefix error.");
+        } else {
+            LOGD("prefix : %s", p_sta->addr6.prefix);
+        }
+
+        if(ipv6_2_str(&(ip_info->ipv6.GateWay), p_sta->addr6.gateway)) {
+            LOGE("GateWay error.");
+        } else {
+            LOGD("GateWay : %s", p_sta->addr6.gateway);
+        }
+
+        if(ipv6_2_str(&(ip_info->ipv6.PrimaryDNS), p_sta->addr6.dnsp)) {
+            LOGE("PrimaryDNS error.");
+        } else {
+            LOGD("PrimaryDNS : %s", p_sta->addr6.dnsp);
+        }
+
+        if(ipv6_2_str(&(ip_info->ipv6.SecondaryDNS), p_sta->addr6.dnsp)) {
+            LOGE("SecondaryDNS error.");
+        } else {
+            LOGD("SecondaryDNS : %s", p_sta->addr6.dnsp);
+        }
+    }
+
+#if 1
+    if(p_sta->ip_ver == QL_NET_IP_VER_V4V6) {
+        if(ip_info->ipv4.valid && !ip_info->ipv6.valid) {
+            p_sta->call_status = QL_NET_DATA_CALL_STATUS_PARTIAL_V4_CONNECTED;
+        } else if(!ip_info->ipv4.valid && ip_info->ipv6.valid) {
+            p_sta->call_status = QL_NET_DATA_CALL_STATUS_PARTIAL_V6_CONNECTED;
+        } else if(ip_info->ipv4.valid && ip_info->ipv6.valid) {
+            p_sta->call_status = QL_NET_DATA_CALL_STATUS_CONNECTED;
+        } else {
+            p_sta->call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED;
+        }
+    } else if(p_sta->ip_ver == QL_NET_IP_VER_V4) {
+        if(ip_info->ipv4.valid) {
+            p_sta->call_status = QL_NET_DATA_CALL_STATUS_CONNECTED;
+        } else {
+            p_sta->call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED;
+        }
+    } else if(p_sta->ip_ver == QL_NET_IP_VER_V6) {
+        if(ip_info->ipv6.valid) {
+            p_sta->call_status = QL_NET_DATA_CALL_STATUS_CONNECTED;
+        } else {
+            p_sta->call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED;
+        }
+    }
+#else
+    if(ipv4.valid && ipv6.valid) {
+        data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_CONNECTED;
+    } else if(!ipv4.valid && ipv6.valid) {
+        data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_PARTIAL_V6_CONNECTED;
+    } else if(ipv4.valid && !ipv6.valid) {
+        data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_PARTIAL_V4_CONNECTED;
+    } else {
+        data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED;
+    }
+
+    if(data_call_status_ind_cb) {
+        data_call_status_ind_cb(call_id, pre_call_status,
+            &(data_call_info[i].call_state));
+    }
+#endif
+
+    return 0;
+}
+
+
+static void data_call_state_change_cb(const void* data, int data_len)
+{
+    LOGD("data_call_state_change_cb() start.");
+    if(data == NULL || data_len == 0)
+    {
+        return;
+    }
+
+    mbtk_ril_pdp_state_info_t *pdp_info = (mbtk_ril_pdp_state_info_t*)data;
+    if(pdp_info->action) { // Connect
+        LOGE("cid[%d] is open.", pdp_info->cid);
+        int i = call_index_get_by_apn_id(pdp_info->cid);;
+        if(i < 0) { // No found this apn_id.
+            LOGW("Unknown apn_id : %d", pdp_info->cid);
+            return;
+        } else {
+            QL_NET_DATA_CALL_STATUS_E pre_call_status = data_call_info[i].call_state.call_status;
+            data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_CONNECTED;
+            data_call_status_update_by_ipv4v6(&(pdp_info->ip_info) ,&data_call_info[i].call_state);
+            if(data_call_status_ind_cb) {
+                data_call_status_ind_cb(data_call_info[i].call_state.call_id, pre_call_status,
+                    &(data_call_info[i].call_state));
+            }
+        }
+    } else { // Disconnect
+        int apn_id = pdp_info->cid;
+        if(apn_id <= QL_NET_MAX_DATA_CALL_NUM)
+        {
+            int i = call_index_get_by_apn_id(apn_id);
+            if(i < 0) { // No found this apn_id.
+                LOGW("Unknown apn_id : %d", apn_id);
+                return;
+            } else {
+                QL_NET_DATA_CALL_STATUS_E pre_call_status = data_call_info[i].call_state.call_status;
+                data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED;
+
+                // Delete IP
+                data_call_info[i].call_state.has_addr = 0;
+                memset(&(data_call_info[i].call_state.addr), 0, sizeof(ql_net_addr_t));
+                data_call_info[i].call_state.has_addr6 = 0;
+                memset(&(data_call_info[i].call_state.addr6), 0, sizeof(ql_net_addr6_t));
+                if(data_call_status_ind_cb) {
+                    data_call_status_ind_cb(data_call_info[i].call_state.call_id, pre_call_status,
+                        &(data_call_info[i].call_state));
+                }
+            }
+        }
+        else
+        {
+            LOGE("[qser_data] cb fail,idx is %d.", apn_id);
+        }
+    }
+
+#if 0
+
+    uint8 *net_data = NULL;
+    net_data = (uint8 *)data;
+
+    if(*net_data > 100 && *net_data < 200) // Disconnect
+    {
+        int apn_id = *net_data - 100;
+        if(apn_id <= QL_NET_MAX_DATA_CALL_NUM)
+        {
+            int i = call_index_get_by_apn_id(apn_id);
+            if(i < 0) { // No found this apn_id.
+                LOGW("Unknown apn_id : %d", apn_id);
+                return;
+            } else {
+                QL_NET_DATA_CALL_STATUS_E pre_call_status = data_call_info[i].call_state.call_status;
+                data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_DISCONNECTED;
+
+                // Delete IP
+                data_call_info[i].call_state.has_addr = 0;
+                memset(&(data_call_info[i].call_state.addr), 0, sizeof(ql_net_addr_t));
+                data_call_info[i].call_state.has_addr6 = 0;
+                memset(&(data_call_info[i].call_state.addr6), 0, sizeof(ql_net_addr6_t));
+                if(data_call_status_ind_cb) {
+                    data_call_status_ind_cb(data_call_info[i].call_state.call_id, pre_call_status,
+                        &(data_call_info[i].call_state));
+                }
+            }
+        }
+        else
+        {
+            LOGE("[qser_data] cb fail,idx is %d.", apn_id);
+        }
+
+    }
+    else if(*net_data > 200) // Connect
+    {
+        LOGE("[qser_data] cid[%d] is reopen.", *net_data - 220);
+        int apn_id;
+        if(*net_data > 220)
+        {
+            apn_id = *net_data - 220;
+        } else {
+            apn_id = *net_data - 200;
+        }
+
+        if(apn_id <= QL_NET_MAX_DATA_CALL_NUM)
+        {
+            int i = call_index_get_by_apn_id(apn_id);;
+            if(i < 0) { // No found this apn_id.
+                LOGW("Unknown apn_id : %d", apn_id);
+                return;
+            } else {
+                QL_NET_DATA_CALL_STATUS_E pre_call_status = data_call_info[i].call_state.call_status;
+                data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_CONNECTED;
+
+                mbtk_pdp_act_info_t *act_info = (mbtk_pdp_act_info_t*)data;
+                data_call_status_update_by_ipv4v6(&(act_info->ipv4), &(act_info->ipv6),&data_call_info[i].call_state);
+
+                if(data_call_status_ind_cb) {
+                    data_call_status_ind_cb(data_call_info[i].call_state.call_id, pre_call_status,
+                        &(data_call_info[i].call_state));
+                }
+            }
+        }
+    }
+    else if(*net_data == 1)
+    {
+        LOGE("[qser_data] pdp is open.");
+    }
+    else
+    {
+        LOGE("[qser_data] unkonwn param [%d].", *net_data);
+    }
+#endif
+}
+
+static int data_call_state_query(int apn_id, ql_data_call_status_t *p_sta)
+{
+    // Get network information.
+    mbtk_ip_info_t ip_info;
+    int ret = mbtk_data_call_state_get(ql_ril_handle, apn_id, &ip_info);
+    if(ret != 0)
+    {
+        LOGE("mbtk_data_call_state_get fail.[ret = %d]", ret);
+        return -1;
+    }
+    else
+    {
+        return data_call_status_update_by_ipv4v6(&ip_info, p_sta);
+    }
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Initialize the data call service
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_init(void)
+{
+    if(ql_ril_handle == NULL)
+    {
+
+        mbtk_log_init("radio", "QL_DATA_CALL");
+
+        ql_ril_handle = mbtk_ril_open(MBTK_AT_PORT_DEF);
+        if(ql_ril_handle)
+        {
+            memset(&data_call_info, 0, sizeof(data_call_info));
+            memset(&data_call_apn_list, 0, sizeof(data_call_apn_list));
+
+            // Get all APN list.
+            mbtk_apn_info_array_t apn_list;
+            memset(&apn_list, 0, sizeof(mbtk_apn_info_array_t));
+            mbtk_ril_err_enum ret = mbtk_apn_get(ql_ril_handle, &apn_list);
+            if(ret) {
+                LOGE("mbtk_apn_get fail:%d", ret);
+                return QL_ERR_UNKNOWN;
+            } else {
+                int i = 0;
+                while(i < apn_list.num) {
+                    data_call_apn_list[i].apn_id = apn_list.apns[i].cid;
+                    switch(apn_list.apns[i].ip_type) {
+                        case MBTK_IP_TYPE_IP:
+                            data_call_apn_list[i].apn_info.ip_ver = QL_NET_IP_VER_V4;
+                            break;
+                        case MBTK_IP_TYPE_IPV6:
+                            data_call_apn_list[i].apn_info.ip_ver = QL_NET_IP_VER_V6;
+                            break;
+                        case MBTK_IP_TYPE_IPV4V6:
+                            data_call_apn_list[i].apn_info.ip_ver = QL_NET_IP_VER_V4V6;
+                            break;
+                        default:
+                            LOGE("Unknown ip_ver.");
+                            return QL_ERR_UNKNOWN;
+                    }
+
+                    if(apn_list.apns[i].auth == MBTK_APN_AUTH_PROTO_NONE) {
+                        data_call_apn_list[i].apn_info.auth_pref = QL_NET_AUTH_PREF_PAP_CHAP_NOT_ALLOWED;
+                    } else if(apn_list.apns[i].auth == MBTK_APN_AUTH_PROTO_PAP) {
+                        data_call_apn_list[i].apn_info.auth_pref = QL_NET_AUTH_PREF_PAP_ONLY_ALLOWED;
+                    } else if(apn_list.apns[i].auth == MBTK_APN_AUTH_PROTO_CHAP) {
+                        data_call_apn_list[i].apn_info.auth_pref = QL_NET_AUTH_PREF_CHAP_ONLY_ALLOWED;
+                    } else { // Default is "NONE"
+                        data_call_apn_list[i].apn_info.auth_pref = QL_NET_AUTH_PREF_PAP_CHAP_NOT_ALLOWED;
+                    }
+
+                    if(strlen((char*)apn_list.apns[i].apn) > 0)
+                        memcpy(data_call_apn_list[i].apn_info.apn_name, apn_list.apns[i].apn, strlen((char*)apn_list.apns[i].apn));
+
+                    if(strlen((char*)apn_list.apns[i].user) > 0)
+                        memcpy(data_call_apn_list[i].apn_info.username, apn_list.apns[i].user, strlen((char*)apn_list.apns[i].user));
+
+                    if(strlen((char*)apn_list.apns[i].pass) > 0)
+                        memcpy(data_call_apn_list[i].apn_info.password, apn_list.apns[i].pass, strlen((char*)apn_list.apns[i].pass));
+
+                    i++;
+                }
+                return QL_ERR_OK;
+            }
+        } else {
+            LOGE("mbtk_info_handle_get() fail.");
+            return QL_ERR_UNKNOWN;
+        }
+    } else {
+        return QL_ERR_UNKNOWN;
+    }
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Create a data call instance
+  @param[in] call_id The unique identifier of the data call instance, specified by the user
+  @param[in] call_name Friendly data call name,  specified by the user
+  @param[in] is_background Whether the data call status is maintained by the data call service daemon.
+  If it is 0, the data call instance will be deleted after the data call process exits.
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_create(int call_id, const char *call_name, int is_background)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(call_id <= 0 || call_name == NULL || strlen(call_name) == 0
+        || strlen(call_name) > QL_NET_MAX_NAME_LEN) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].call_state.call_id == 0) { // Not use.
+            break;
+        }
+        i++;
+    }
+
+    if(i == QL_NET_MAX_DATA_CALL_NUM) { // data_call item full.
+        LOGW("data_call instance is full.");
+        return QL_ERR_UNKNOWN;
+    }
+
+    data_call_info[i].call_state.call_id = call_id;
+    memcpy(data_call_info[i].call_state.call_name, call_name, strlen(call_name));
+    data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_CREATED;
+
+    data_call_info[i].is_background = is_background;
+    data_call_info[i].param_info = NULL;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Alloc for a data call configuration instance
+  @return
+  NULL - Not enough memory
+  Other - successful
+  */
+/*-----------------------------------------------------------------------------------------------*/
+ql_data_call_param_t *ql_data_call_param_alloc(void)
+{
+    ql_data_call_param_t *result = (ql_data_call_param_t*)malloc(sizeof(mbtk_data_call_param_info_t));
+    if(result) {
+        memset(result, 0, sizeof(mbtk_data_call_param_info_t));
+    }
+
+    return result;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Initialize the data call configuration instance
+  @param[in] param Point to the data call configuration instance
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_init(ql_data_call_param_t *param)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    memset(info, 0, sizeof(mbtk_data_call_param_info_t));
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Release the data call configuration instance
+  @param[in] param Point to the data call configuration instance
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_free(ql_data_call_param_t *param)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    free(param);
+
+    return QL_ERR_OK;
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Bind APN ID, range:1-16
+  @param[in] param Point to the data call configuration instance
+  @param[in] apn_id APN ID, range:1-16
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_set_apn_id(ql_data_call_param_t *param, int apn_id)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    // 1 - 7
+    if(param == NULL || apn_id <= 0 || apn_id > QL_NET_MAX_APN_ID) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_apn_list[i].apn_id == apn_id) {
+            break;
+        }
+        i++;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param != NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    if(i == QL_NET_MAX_DATA_CALL_NUM) {
+        LOGW("No found apn_id : %d.", apn_id);
+        // Found next empty apn item.
+        int j = 0;
+        while(j < QL_NET_MAX_DATA_CALL_NUM) {
+            if(data_call_apn_list[j].apn_id <= 0) {
+                break;
+            }
+            j++;
+        }
+        if(j == QL_NET_MAX_DATA_CALL_NUM) { // Full
+            return QL_ERR_UNKNOWN;
+        }
+
+        info->apn_param = &(data_call_apn_list[j]);
+        info->apn_param->apn_id = apn_id;
+    } else {
+        // Found apn_id
+        info->apn_param = &(data_call_apn_list[i]);
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get APN name from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] buf APN ID
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_get_apn_id(ql_data_call_param_t *param, int *apn_id)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || apn_id == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    *apn_id = info->apn_param->apn_id;
+
+    return QL_ERR_OK;
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure APN name
+  @param[in] param Point to the data call configuration instance
+  @param[in] apn_name APN name
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_set_apn_name(ql_data_call_param_t *param, const char *apn_name)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || apn_name == NULL || strlen(apn_name) == 0
+        || strlen(apn_name) > QL_NET_MAX_APN_NAME_LEN) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    memcpy(info->apn_param->apn_info.apn_name, apn_name, strlen(apn_name));
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get APN name from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] buf APN name buffer
+  @param[in] buf_len APN name buffer size
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_get_apn_name(ql_data_call_param_t *param, char *buf, int buf_len)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || buf == NULL || buf_len <= 0) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    if(strlen(info->apn_param->apn_info.apn_name) + 1 > buf_len) {
+        return QL_ERR_INVALID_ARG;
+    }
+    memcpy(buf, info->apn_param->apn_info.apn_name, strlen(info->apn_param->apn_info.apn_name));
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure APN user name
+  @param[in] param Point to the data call configuration instance
+  @param[in] user_name APN user name
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_set_user_name(ql_data_call_param_t *param, const char *user_name)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || user_name == NULL || strlen(user_name) == 0
+        || strlen(user_name) > QL_NET_MAX_APN_USERNAME_LEN) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    memcpy(info->apn_param->apn_info.username, user_name, strlen(user_name));
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get APN user name from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] buf APN user name buffer
+  @param[in] buf_len APN user name buffer size
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_get_user_name(ql_data_call_param_t *param, char *buf, int buf_len)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || buf == NULL || buf_len <= 0) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    if(strlen(info->apn_param->apn_info.username) + 1 > buf_len) {
+        return QL_ERR_INVALID_ARG;
+    }
+    memcpy(buf, info->apn_param->apn_info.username, strlen(info->apn_param->apn_info.username));
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure APN user password
+  @param[in] param Point to the data call configuration instance
+  @param[in] user_password APN user password
+  @return
+  QL_ERR_OK - Not enough memory
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_set_user_password(ql_data_call_param_t *param, const char *user_password)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || user_password == NULL || strlen(user_password) == 0
+        || strlen(user_password) > QL_NET_MAX_APN_PASSWORD_LEN) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    memcpy(info->apn_param->apn_info.password, user_password, strlen(user_password));
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get APN user password from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] buf APN user password buffer
+  @param[in] buf_len APN user password buffer size
+  @return
+  QL_ERR_OK - Not enough memory
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_get_user_password(ql_data_call_param_t *param, char *buf, int buf_len)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || buf == NULL || buf_len <= 0) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    if(strlen(info->apn_param->apn_info.password) + 1 > buf_len) {
+        return QL_ERR_INVALID_ARG;
+    }
+    memcpy(buf, info->apn_param->apn_info.password, strlen(info->apn_param->apn_info.password));
+
+    return QL_ERR_OK;
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the data call authentication method
+  @param[in] param Point to the data call configuration instance
+  @param[in] auth_pref Defined by QL_DATA_CALL_AUTH_PREF_E
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_set_auth_pref(ql_data_call_param_t *param, int auth_pref)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    info->apn_param->apn_info.auth_pref = (QL_NET_AUTH_PREF_E)auth_pref;
+
+    return QL_ERR_OK;
+
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the data call authentication method
+  @param[in] param Point to the data call configuration instance
+  @param[out] p_data Store return value
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_get_auth_pref(ql_data_call_param_t *param, int *p_data)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || p_data == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    *p_data = info->apn_param->apn_info.auth_pref;
+
+    return QL_ERR_OK;
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the data call IP version
+  @param[in] param Point to the data call configuration instance
+  @param[in] ip_ver Defined by QL_NET_IP_VER_E
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_set_ip_version(ql_data_call_param_t *param, int ip_ver)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    info->apn_param->apn_info.ip_ver = (QL_NET_IP_VER_E)ip_ver;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get IP version from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] p_ver Store return value
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_get_ip_version(ql_data_call_param_t *param, int *p_ver)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || p_ver == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    if(info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+    *p_ver = info->apn_param->apn_info.ip_ver;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the data call auto reconnection mode
+  @param[in] param Point to the data call configuration instance
+  @param[in] mode Defined by QL_NET_DATA_CALL_RECONNECT_MODE_E
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_set_reconnect_mode(ql_data_call_param_t *param, int reconnect_mode)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    info->reconnect_mode = reconnect_mode;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get auto reconnection mode from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] p_mode Store return value
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_get_reconnect_mode(ql_data_call_param_t *param, int *p_mode)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || p_mode == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    *p_mode = info->reconnect_mode;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the data call auto reconnection interval
+  @param[in] param Point to the data call configuration instance
+  @param[in] time_list Interval time list in ms
+  @param[in] num Number of time list
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_set_reconnect_interval(ql_data_call_param_t *param, int *time_list, int num)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || time_list == NULL || num <= 0 || num > QL_NET_MAX_RECONNECT_INTERVAL_LEN) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    info->time_num = num;
+    memcpy(&(info->time_list), time_list, sizeof(int) * num);
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get auto reconnection interval from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] time_list Store return value
+  @param[in,out] p_num
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_param_get_reconnect_interval(ql_data_call_param_t *param, int *time_list, int *p_num)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL || time_list == NULL || p_num == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_data_call_param_info_t *info = (mbtk_data_call_param_info_t*)param;
+    *p_num = info->time_num;
+    int i = 0;
+    for(; i < info->time_num; i++) {
+        *(time_list + i) = info->time_list[i];
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the specified data call instance
+  @param[in] call_id Specify a data call instance
+  @param[in] param Point to the data call configuration instance
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_config(int call_id, ql_data_call_param_t *param)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int i = call_index_get_by_call_id(call_id);
+    if(i < 0) {
+        LOGE("Unknown call_id : %d", call_id);
+        return QL_ERR_UNKNOWN;
+    }
+
+    data_call_info[i].param_info = memdup(param, sizeof(mbtk_data_call_param_info_t));
+
+    if(data_call_info[i].param_info->apn_param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    snprintf(data_call_info[i].call_state.device, QL_NET_MAX_NAME_LEN, "ccinet%d",
+        data_call_info[i].param_info->apn_param->apn_id - 1);
+    data_call_info[i].call_state.ip_ver = data_call_info[i].param_info->apn_param->apn_info.ip_ver;
+
+    mbtk_apn_info_t apn_info;
+    memset(&apn_info, 0, sizeof(mbtk_apn_info_t));
+    // Set APN.
+    switch(data_call_info[i].param_info->apn_param->apn_info.ip_ver) {
+        case QL_NET_IP_VER_V4:
+            apn_info.ip_type = MBTK_IP_TYPE_IP;
+            break;
+        case QL_NET_IP_VER_V6:
+            apn_info.ip_type = MBTK_IP_TYPE_IPV6;
+            break;
+        case QL_NET_IP_VER_V4V6:
+            apn_info.ip_type = MBTK_IP_TYPE_IPV4V6;
+            break;
+        default:
+            LOGE("Unknown ip_ver.");
+            return QL_ERR_UNKNOWN;
+    }
+
+    switch(data_call_info[i].param_info->apn_param->apn_info.auth_pref) {
+        case QL_NET_AUTH_PREF_PAP_CHAP_NOT_ALLOWED:
+            apn_info.auth = MBTK_APN_AUTH_PROTO_NONE;
+            break;
+        case QL_NET_AUTH_PREF_PAP_ONLY_ALLOWED:
+            apn_info.auth = MBTK_APN_AUTH_PROTO_PAP;
+            break;
+        case QL_NET_AUTH_PREF_CHAP_ONLY_ALLOWED:
+            apn_info.auth = MBTK_APN_AUTH_PROTO_CHAP;
+            break;
+#if 0
+        case QL_NET_AUTH_PREF_PAP_CHAP_BOTH_ALLOWED:
+            apninfo.auth_proto = MBTK_APN_AUTH_PROTO_PAP_CHAP;
+            break;
+#endif
+        default:
+            LOGE("Unknown auth_pref.");
+            return QL_ERR_UNKNOWN;
+    }
+
+    /*
+        data_call_info[i].param_info->apn_param->apn_id, ip_type,
+                data_call_info[i].param_info->apn_param->apn_info.apn_name,
+                data_call_info[i].param_info->apn_param->apn_info.username,
+                data_call_info[i].param_info->apn_param->apn_info.password, auth_type
+    */
+    apn_info.cid = (mbtk_ril_cid_enum)data_call_info[i].param_info->apn_param->apn_id;
+    apn_info.auto_save = (uint8)1;
+    apn_info.auto_boot_call = (uint8)0;
+    apn_info.def_route = (uint8)0;
+    apn_info.as_dns = (uint8)0;
+
+    if(strlen(data_call_info[i].param_info->apn_param->apn_info.apn_name) > 0) {
+        memcpy(apn_info.apn, data_call_info[i].param_info->apn_param->apn_info.apn_name,
+            strlen(data_call_info[i].param_info->apn_param->apn_info.apn_name));
+    }
+
+    if(strlen(data_call_info[i].param_info->apn_param->apn_info.username) > 0) {
+        memcpy(apn_info.user, data_call_info[i].param_info->apn_param->apn_info.username,
+            strlen(data_call_info[i].param_info->apn_param->apn_info.username));
+    }
+
+    if(strlen(data_call_info[i].param_info->apn_param->apn_info.password) > 0) {
+        memcpy(apn_info.pass, data_call_info[i].param_info->apn_param->apn_info.password,
+            strlen(data_call_info[i].param_info->apn_param->apn_info.password));
+    }
+
+    mbtk_ril_err_enum ret = mbtk_apn_set(ql_ril_handle, &apn_info);
+    if(ret) {
+        LOGE("mbtk_apn_set fail : %d", ret);
+        return QL_ERR_UNKNOWN;
+    } else {
+        return QL_ERR_OK;
+    }
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get the specified data call configuration instance
+  @param[in] call_id Specify a data call instance
+  @param[in] param Point to the data call configuration instance
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_get_config(int call_id, ql_data_call_param_t *param)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(param == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int i = call_index_get_by_call_id(call_id);
+    if(i < 0) {
+        LOGE("Unknown call_id : %d", call_id);
+        return QL_ERR_UNKNOWN;
+    }
+
+    if(data_call_info[i].param_info == NULL)
+    {
+        LOGE("param_info is NULL");
+        return QL_ERR_FAILED;
+    }
+    
+    memcpy(param, data_call_info[i].param_info, sizeof(mbtk_data_call_param_info_t));
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Start data call
+  @param[in] call_id Specify a data call instance
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_start(int call_id)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    int i = call_index_get_by_call_id(call_id);
+    if(i < 0) {
+        LOGE("Unknown call_id : %d", call_id);
+        return QL_ERR_UNKNOWN;
+    }
+
+    if(data_call_info[i].param_info == NULL) {
+        LOGE("data_call_info[i].param_info is NULL.");
+        return QL_ERR_UNKNOWN;
+    }
+
+    int ret = data_call_state_query(data_call_info[i].param_info->apn_param->apn_id, &(data_call_info[i].call_state));
+    if(ret) {
+        LOGE("data_call_state_query fail.");
+        data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_IDLE;
+        // return QL_ERR_UNKNOWN;
+    }
+
+    if(data_call_info[i].call_state.call_status == QL_NET_DATA_CALL_STATUS_PARTIAL_V4_CONNECTED
+        || data_call_info[i].call_state.call_status == QL_NET_DATA_CALL_STATUS_PARTIAL_V6_CONNECTED
+        || data_call_info[i].call_state.call_status == QL_NET_DATA_CALL_STATUS_CONNECTED) {
+        LOGW("call_id %d has connected.", call_id);
+        return QL_ERR_UNKNOWN;
+    }
+
+    LOGD("Start Data Call : %d", call_id);
+    // data_call_info_item_print(call_id);
+
+    // Start data call.
+//    int auto_conn_interval = 0;
+    QL_NET_DATA_CALL_STATUS_E pre_call_status = data_call_info[i].call_state.call_status;
+    data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_CONNECTING;
+    if(data_call_status_ind_cb) {
+        data_call_status_ind_cb(call_id, pre_call_status, &data_call_info[i].call_state);
+    }
+
+#if 0
+    if(data_call_info[i].param_info->reconnect_mode == QL_NET_DATA_CALL_RECONNECT_NORMAL
+        || data_call_info[i].param_info->reconnect_mode == QL_NET_DATA_CALL_RECONNECT_MODE_1
+        || data_call_info[i].param_info->reconnect_mode == QL_NET_DATA_CALL_RECONNECT_MODE_2) {
+        if(data_call_info[i].param_info->time_num > 0) {
+            auto_conn_interval = data_call_info[i].param_info->time_list[0];
+        }
+    } else {
+        auto_conn_interval = 0;
+    }
+#endif
+
+/*
+mbtk_ril_err_enum mbtk_data_call_start(mbtk_ril_handle* handle,
+mbtk_ril_cid_enum cid,
+mbtk_data_call_item_state_enum auto_boot_call,
+            mbtk_data_call_item_state_enum def_route, mbtk_data_call_item_state_enum as_dns,
+            int *retry_interval, int retry_interval_num,
+            int timeout, mbtk_ip_info_t *rsp_info);
+*/
+
+    mbtk_ip_info_t rsp_info;
+    memset(&rsp_info, 0, sizeof(mbtk_ip_info_t));
+    ret = mbtk_data_call_start(ql_ril_handle,
+            (mbtk_ril_cid_enum)data_call_info[i].param_info->apn_param->apn_id,
+            MBTK_DATA_CALL_ITEM_STATE_NON, MBTK_DATA_CALL_ITEM_STATE_NON, MBTK_DATA_CALL_ITEM_STATE_NON,
+            data_call_info[i].param_info->time_list, data_call_info[i].param_info->time_num,
+            0, &rsp_info);
+    if(ret) {
+        LOGE("mbtk_data_call_start fail.");
+        pre_call_status = data_call_info[i].call_state.call_status;
+        data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_ERROR;
+        if(data_call_status_ind_cb) {
+            data_call_status_ind_cb(call_id, pre_call_status, &data_call_info[i].call_state);
+        }
+        return QL_ERR_UNKNOWN;
+    }
+
+    pre_call_status = data_call_info[i].call_state.call_status;
+    ret = data_call_status_update_by_ipv4v6(&rsp_info, &data_call_info[i].call_state);
+    if(ret) {
+        LOGE("data_call_status_update_by_ipv4v6() fail.");
+        data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_ERROR;
+        if(data_call_status_ind_cb) {
+            data_call_status_ind_cb(call_id, pre_call_status, &data_call_info[i].call_state);
+        }
+        return QL_ERR_UNKNOWN;
+    }
+
+    if(data_call_status_ind_cb) {
+        data_call_status_ind_cb(call_id, pre_call_status, &data_call_info[i].call_state);
+    }
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Stop data call
+  @param[in] call_id Specify a data call instance
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_stop(int call_id)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    int i = call_index_get_by_call_id(call_id);
+    if(i < 0) {
+        LOGE("Unknown call_id : %d", call_id);
+        return QL_ERR_UNKNOWN;
+    }
+
+    if(data_call_info[i].param_info == NULL) {
+        LOGE("data_call_info[i].param_info is NULL.");
+        return QL_ERR_UNKNOWN;
+    }
+
+    int ret = mbtk_data_call_stop(ql_ril_handle, data_call_info[i].param_info->apn_param->apn_id, 15);
+    if(ret) {
+        LOGE("mbtk_data_call_stop() fail.");
+        return QL_ERR_UNKNOWN;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Delete a data call instance
+  @param[in] call_id Specify a data call instance
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_delete(int call_id)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    int i = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].call_state.call_id == call_id) {
+            break;
+        }
+        i++;
+    }
+
+    if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this call_id.
+        LOGW("Unknown call_id : %d", call_id);
+        return QL_ERR_UNKNOWN;
+    }
+
+    if(data_call_info[i].param_info) {
+        free(data_call_info[i].param_info);
+        data_call_info[i].param_info = NULL;
+    }
+    memset(&(data_call_info[i]), 0, sizeof(ql_data_call_info_t));
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get the current data call instance list
+  @param[out] list Data call instance array
+  @param[in,out] list_len, in-> Data call instance array size, out->current data call instance number
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_get_list(ql_data_call_item_t *list, int *list_len)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(list == NULL || list_len == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int i = 0;
+    *list_len = 0;
+    while(i < QL_NET_MAX_DATA_CALL_NUM) {
+        if(data_call_info[i].call_state.call_id > 0) {
+            memset(&(list[*list_len]), 0, sizeof(ql_data_call_item_t));
+            list[*list_len].call_id = data_call_info[i].call_state.call_id;
+            memcpy(list[*list_len].call_name, data_call_info[i].call_state.call_name,
+                strlen(data_call_info[i].call_state.call_name));
+
+            (*list_len)++;
+        }
+        i++;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get the data call status
+  @param[in] call_id Specify a data call instance
+  @param[out] p_sta Point to status instance
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_get_status(int call_id, ql_data_call_status_t *p_sta)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    int i = call_index_get_by_call_id(call_id);
+    if(i < 0) {
+        LOGE("Unknown call_id : %d", call_id);
+        return QL_ERR_UNKNOWN;
+    }
+
+    if(data_call_info[i].param_info == NULL || p_sta == NULL) {
+        LOGE("data_call_info[i].param_info is NULL.");
+        return QL_ERR_UNKNOWN;
+    }
+
+    int ret = data_call_state_query(data_call_info[i].param_info->apn_param->apn_id, &(data_call_info[i].call_state));
+    if(ret) {
+        LOGE("data_call_state_query fail.");
+        data_call_info[i].call_state.call_status = QL_NET_DATA_CALL_STATUS_IDLE;
+        memcpy(p_sta, &(data_call_info[i].call_state), sizeof(ql_data_call_status_t));
+        return QL_ERR_UNKNOWN;
+    } else {
+        memcpy(p_sta, &(data_call_info[i].call_state), sizeof(ql_data_call_status_t));
+        return QL_ERR_OK;
+    }
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Register data call status change event
+  @param[in] cb
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_set_status_ind_cb(ql_data_call_status_ind_cb_f cb)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_UNKNOWN;
+    } else {
+        if(mbtk_pdp_state_change_cb_reg(data_call_state_change_cb))
+        {
+            return QL_ERR_UNKNOWN;
+        }
+
+        data_call_status_ind_cb = cb;
+        return QL_ERR_OK;
+    }
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Set APN related configuration.If the apn does not exist, it is automatically created.
+  @param[in] apn_id APN ID, range:1-16
+  @param[in] p_info APN configuration
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_set_apn_config(int apn_id, ql_data_call_apn_config_t *p_info)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(p_info == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_apn_info_t apn_info;
+    memset(&apn_info, 0, sizeof(mbtk_apn_info_t));
+    // Set APN.
+    switch(p_info->ip_ver) {
+        case QL_NET_IP_VER_V4:
+            apn_info.ip_type = MBTK_IP_TYPE_IP;
+            break;
+        case QL_NET_IP_VER_V6:
+            apn_info.ip_type = MBTK_IP_TYPE_IPV6;
+            break;
+        case QL_NET_IP_VER_V4V6:
+            apn_info.ip_type = MBTK_IP_TYPE_IPV4V6;
+            break;
+        default:
+            LOGE("Unknown ip_ver.");
+            return QL_ERR_UNKNOWN;
+    }
+
+    switch(p_info->auth_pref) {
+        case QL_NET_AUTH_PREF_PAP_CHAP_NOT_ALLOWED:
+            apn_info.auth = MBTK_APN_AUTH_PROTO_NONE;
+            break;
+        case QL_NET_AUTH_PREF_PAP_ONLY_ALLOWED:
+            apn_info.auth = MBTK_APN_AUTH_PROTO_PAP;
+            break;
+        case QL_NET_AUTH_PREF_CHAP_ONLY_ALLOWED:
+            apn_info.auth = MBTK_APN_AUTH_PROTO_CHAP;
+            break;
+#if 0
+        case QL_NET_AUTH_PREF_PAP_CHAP_BOTH_ALLOWED:
+            apninfo.auth_proto = MBTK_APN_AUTH_PROTO_PAP_CHAP;
+            break;
+#endif
+        default:
+            LOGE("Unknown auth_pref.");
+            return QL_ERR_UNKNOWN;
+    }
+
+    /*
+        data_call_info[i].param_info->apn_param->apn_id, ip_type,
+                data_call_info[i].param_info->apn_param->apn_info.apn_name,
+                data_call_info[i].param_info->apn_param->apn_info.username,
+                data_call_info[i].param_info->apn_param->apn_info.password, auth_type
+    */
+    apn_info.cid = (mbtk_ril_cid_enum)apn_id;
+    apn_info.auto_save = (uint8)1;
+    apn_info.auto_boot_call = (uint8)0;
+    apn_info.def_route = (uint8)0;
+    apn_info.as_dns = (uint8)0;
+
+    if(strlen(p_info->apn_name) > 0) {
+        memcpy(apn_info.apn, p_info->apn_name, strlen(p_info->apn_name));
+    }
+
+    if(strlen(p_info->username) > 0) {
+        memcpy(apn_info.user, p_info->username, strlen(p_info->username));
+    }
+
+    if(strlen(p_info->password) > 0) {
+        memcpy(apn_info.pass, p_info->password, strlen(p_info->password));
+    }
+
+    mbtk_ril_err_enum ret = mbtk_apn_set(ql_ril_handle, &apn_info);
+    if(ret) {
+        LOGE("mbtk_apn_set fail : %d", ret);
+        return QL_ERR_UNKNOWN;
+    } else {
+        return QL_ERR_OK;
+    }
+
+    if(ret) {
+        LOGE("mbtk_apn_set fail.");
+        return QL_ERR_UNKNOWN;
+    } else {
+
+        // Save to data_call_apn_list
+        int i = 0;
+        while(i < QL_NET_MAX_DATA_CALL_NUM) {
+            if(data_call_info[i].param_info && data_call_info[i].param_info->apn_param
+                && data_call_info[i].param_info->apn_param->apn_id == apn_id) {
+                break;
+            }
+            i++;
+        }
+
+        if(i == QL_NET_MAX_DATA_CALL_NUM) { // No found this apn_id.
+            LOGW("New apn_id : %d", apn_id);
+            // New data call param.
+            int j = 0;
+            while(j < QL_NET_MAX_DATA_CALL_NUM) {
+                if(data_call_apn_list[j].apn_id <= 0) {
+                    break;
+                }
+                j++;
+            }
+
+            if(j == QL_NET_MAX_DATA_CALL_NUM) { // Full
+                LOGW("data_call_apn_param_list is full.");
+                return QL_ERR_UNKNOWN;
+            }
+
+            data_call_apn_list[j].apn_id = apn_id;
+            memcpy(&(data_call_apn_list[j].apn_info), p_info, sizeof(ql_data_call_apn_config_t));
+        } else {
+            memcpy(&(data_call_info[i].param_info->apn_param->apn_info), p_info, sizeof(ql_data_call_apn_config_t));
+        }
+
+
+        return QL_ERR_OK;
+    }
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Set APN related configuration. If the apn does not exist, it is automatically created and
+  the default parameters are set.
+  @param[in] apn_id APN ID, range:1-16
+  @param[out] p_info APN configuration
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_get_apn_config(int apn_id, ql_data_call_apn_config_t *p_info)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_SERVICE_NOT_READY;
+    }
+
+    if(p_info == NULL) {
+        return QL_ERR_INVALID_ARG;
+    }
+
+    memset(p_info, 0, sizeof(ql_data_call_apn_config_t));
+
+    mbtk_apn_info_array_t apns;
+    memset(&apns, 0, sizeof(mbtk_apn_info_array_t));
+    int ret = mbtk_apn_get(ql_ril_handle, &apns);
+    if(ret) {
+        LOGE("mbtk_apn_get fail.");
+        return QL_ERR_UNKNOWN;
+    } else {
+        int i = 0;
+        while(i < apns.num) {
+            if(apns.apns[i].cid == apn_id)
+                break;
+            i++;
+        }
+        if(i == apns.num) {
+            LOGE("No found apn_id : %d", apn_id);
+            return QL_ERR_UNKNOWN;
+        }
+
+        switch(apns.apns[i].ip_type) {
+            case MBTK_IP_TYPE_IP:
+                p_info->ip_ver = QL_NET_IP_VER_V4;
+                break;
+            case MBTK_IP_TYPE_IPV6:
+                p_info->ip_ver = QL_NET_IP_VER_V6;
+                break;
+            case MBTK_IP_TYPE_IPV4V6:
+                p_info->ip_ver = QL_NET_IP_VER_V4V6;
+                break;
+            default:
+                LOGE("Unknown ip_ver.");
+                return QL_ERR_UNKNOWN;
+        }
+
+        if(apns.apns[i].auth == MBTK_APN_AUTH_PROTO_NONE) {
+            p_info->auth_pref = QL_NET_AUTH_PREF_PAP_CHAP_NOT_ALLOWED;
+        } else if(apns.apns[i].auth == MBTK_APN_AUTH_PROTO_PAP) {
+            p_info->auth_pref = QL_NET_AUTH_PREF_PAP_ONLY_ALLOWED;
+        } else if(apns.apns[i].auth == MBTK_APN_AUTH_PROTO_CHAP) {
+            p_info->auth_pref = QL_NET_AUTH_PREF_CHAP_ONLY_ALLOWED;
+        } else {
+            LOGE("Unknown auth_pref : %s", apns.apns[i].auth);
+            return QL_ERR_UNKNOWN;
+        }
+
+        if(strlen((char*)apns.apns[i].apn) > 0)
+            memcpy(p_info->apn_name, apns.apns[i].apn, strlen((char*)apns.apns[i].apn));
+
+        if(strlen((char*)apns.apns[i].user) > 0)
+            memcpy(p_info->username, apns.apns[i].user, strlen((char*)apns.apns[i].user));
+
+        if(strlen((char*)apns.apns[i].pass) > 0)
+            memcpy(p_info->password, apns.apns[i].pass, strlen((char*)apns.apns[i].pass));
+
+        return QL_ERR_OK;
+    }
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Set APN related configuration,APN ID:1
+  @param[in] p_info APN configuration
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_set_attach_apn_config(ql_data_call_apn_config_t *p_info)
+{
+    return ql_data_call_set_apn_config(1, p_info);
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @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_data_call_set_service_error_cb(ql_data_call_service_error_cb_f cb)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_UNKNOWN;
+    } else {
+        if(mbtk_ril_ser_state_change_cb_reg(ril_server_state_cb))
+        {
+            return QL_ERR_UNKNOWN;
+        }
+
+        data_call_service_error_cb = cb;
+        return QL_ERR_OK;
+    }
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Deinitialize the data call service
+  @return
+  QL_ERR_OK - successful
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_data_call_deinit(void)
+{
+    if(ql_ril_handle == NULL)
+    {
+        return QL_ERR_UNKNOWN;
+    } else {
+        if(mbtk_ril_close(MBTK_AT_PORT_DEF))
+        {
+            return QL_ERR_UNKNOWN;
+        }
+
+        return QL_ERR_OK;
+    }
+}
diff --git a/mbtk/libql_lib_v2_rilv2/ql_dm.c b/mbtk/libql_lib_v2_rilv2/ql_dm.c
new file mode 100755
index 0000000..867c4fd
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_dm.c
@@ -0,0 +1,882 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_dm.h 
+  @brief device management 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
+  --------   ---          ----------------------------------------------------------
+  20200316   stan.li      Optimize the ql_dm_get_modem_state interface
+  20191224   stan.li      Add radio on/off API
+  20190625   stan.li      Created .
+-------------------------------------------------------------------------------------------------*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <pthread.h>
+
+#include "mbtk_ril_api.h"
+#include "ql_type.h"
+#include "ql_dm.h"
+
+
+
+#define LYNQ_AIR_PLANE_MODE_ON      4    //at+cfun = 4
+#define LYNQ_AIR_PLANE_MODE_OFF     1   // at+cfun = 1
+
+
+#define MBTK_RILD_ERR      -1
+#define IMEI_VALID          1
+
+static mbtk_ril_handle* ql_info_handle = NULL;
+static mbtk_ril_handle* g_md_version_handle = NULL;
+
+static ql_dm_air_plane_mode_ind_cb g_air_plane_mode_cb = NULL;
+static ql_dm_service_error_cb_f global_dm_error_cb = NULL;
+static ql_dm_modem_state_ind_cb global_dm_modem_cb = NULL;
+
+
+static pthread_t g_air_plane_mode_thread;
+static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t g_cond = PTHREAD_COND_INITIALIZER;
+static bool g_thread_running = false;
+
+
+static void mbtk_send_singnal()
+{
+    pthread_mutex_lock(&g_mutex);
+    pthread_cond_signal(&g_cond);
+    pthread_mutex_unlock(&g_mutex);
+
+}
+
+static void mbtk_dm_set_service_error_func(const void* data,int data_len)
+{
+    if(data !=NULL && data_len == sizeof(int))
+    {
+        const int *state = (const int*)(data);
+        if(*state)
+        {
+            if(global_dm_error_cb)
+            {
+                global_dm_error_cb(MBTK_RILD_ERR);
+            }
+
+        }
+    }
+        
+}
+
+static void mbtk_modem_state_change_cb(const void* data, int data_len)
+{
+    uint8 *ptr = (uint8*)data;
+    if(global_dm_modem_cb)
+    {
+        global_dm_modem_cb(*ptr);
+    }
+    
+}
+
+void* air_plane_mode_monitor(void* arg) 
+{
+    int ql_info = 0;
+    int ret = -1;
+    mbtk_radio_state_enum mbtk_info;
+
+    while (g_thread_running) 
+    {
+        pthread_mutex_lock(&g_mutex);
+        pthread_cond_wait(&g_cond, &g_mutex); 
+        ret = mbtk_radio_state_get(ql_info_handle, &mbtk_info);
+        if (ret != 0)
+        {
+            LOGE("mbtk_radio_state_get fail.");
+            return NULL;
+        }
+        
+        if(mbtk_info == LYNQ_AIR_PLANE_MODE_OFF)
+        {
+            ql_info = QL_DM_AIR_PLANE_MODE_OFF;
+        }
+        
+        if(mbtk_info == LYNQ_AIR_PLANE_MODE_ON)
+        {
+            ql_info = QL_DM_AIR_PLANE_MODE_ON;
+        }
+        
+        if(mbtk_info != LYNQ_AIR_PLANE_MODE_OFF && mbtk_info !=LYNQ_AIR_PLANE_MODE_ON)
+        {
+            
+            ql_info = QL_DM_AIR_PLANE_MODE_UNKNOWN;
+        }
+       
+        if(g_air_plane_mode_cb) 
+        {
+            
+            g_air_plane_mode_cb(ql_info);
+        }
+
+        pthread_mutex_unlock(&g_mutex);
+    }
+
+    return NULL;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Initialize DM service.
+  @note You must call this function before other functions can be used in this module.
+  @return Whether the DM service was successfully intialized.
+  @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_dm_init(void)
+{
+    
+    if(ql_info_handle == NULL)
+    {
+
+        mbtk_log_init("syslog", "QL_DM");
+
+        ql_info_handle = mbtk_ril_open(MBTK_AT_PORT_DEF);
+        if(ql_info_handle)
+        {
+           
+            return QL_ERR_OK;
+        } 
+        else 
+        {
+            LOGE("mbtk_info_handle_get() fail.");
+            return QL_ERR_FAILED;
+        }
+
+     }
+     else
+     {
+        LOGE("No need init again");
+        return QL_ERR_FAILED;
+     }
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Denitialize DM service.
+  @return Whether the DM service was successfully deintialized.
+  @retval QL_ERR_OK successful.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_deinit(void)
+{
+    if(ql_info_handle)
+    {
+    
+        int ret = mbtk_ril_close(MBTK_AT_PORT_DEF);
+        if(ret != 0) 
+        {
+            LOGE("mbtk_info_handle_free fail.");
+            return QL_ERR_FAILED;
+        }
+        else 
+        {
+            LOGI("mbtk_info_handle_free success");
+            return QL_ERR_OK;
+        }
+    }
+    else
+    {
+        LOGE("DM not inited.");
+        return QL_ERR_NOT_INIT;
+    }
+   
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get device software version.
+  @param[out] soft_ver Return software version
+  @param[in] soft_ver_len The length of soft_ver
+  @return Whether to successfully get the software version
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+
+int ql_dm_get_software_version(char *soft_ver, int soft_ver_len)
+{
+
+    int ret = -1;
+    if(soft_ver == NULL || soft_ver_len <= 0)
+    {
+         LOGE("Bad parameters  ");
+         return QL_ERR_FAILED;
+    }
+    if(ql_info_handle != NULL)
+    {
+    
+        ret = mbtk_version_get(ql_info_handle,soft_ver);
+        if(ret != 0)
+        {
+            LOGE("ql_dm_get_software_version  error.");
+            return QL_ERR_FAILED;
+        }
+    }
+    else
+    {
+        mbtk_ril_handle* mbtk_info_handle = NULL;
+        mbtk_info_handle = mbtk_ril_open(MBTK_AT_PORT_DEF);
+        if(mbtk_info_handle == NULL)
+        {
+            LOGE("mbtk_info_handle_get fail.");
+            return QL_ERR_FAILED;
+        }
+        ret = mbtk_version_get(mbtk_info_handle,soft_ver);
+        if(ret != 0)
+        {
+            LOGE("ql_dm_get_software_version  error.");
+            
+        }
+        ret = mbtk_ril_close(MBTK_AT_PORT_DEF);
+        if(ret != 0) 
+        {
+            LOGE("mbtk_info_handle_free fail.");
+            return QL_ERR_FAILED;
+        }
+        
+    }
+    return QL_ERR_OK;
+    
+
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get modem state.
+  @details QL_DM_MODEM_STATE_ONLINE,if modem starts normally.
+  @details QL_DM_MODEM_STATE_OFFLINE,in modem starts abnormally.
+  @details QL_DM_MODEM_STATE_UNKNOWN,unknown error.
+  @param[out] modem_state The state of modem
+  @return Whether to successfully get the modem state
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_get_modem_state(QL_DM_MODEM_STATE_TYPE_E *modem_state);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register modem state event.
+  @param[in] cb_func modem state indication callback function
+  @return Whether the modem state event was successfully registered.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+
+int ql_dm_set_modem_state_change_ind_cb(ql_dm_modem_state_ind_cb cb_func)
+{
+    
+        int ret =-1;
+        
+        global_dm_modem_cb = cb_func;
+        
+        if(ql_info_handle != NULL)
+        {
+            
+            ret = mbtk_radio_state_change_cb_reg(mbtk_modem_state_change_cb);
+            if(ret != 0)
+            {
+                LOGE("call mbtk_radio_state_change_cb_reg failed");
+                return QL_ERR_FAILED;
+            }
+        }
+        else 
+        {
+            if(g_md_version_handle == NULL)
+            {
+                g_md_version_handle = mbtk_ril_open(MBTK_AT_PORT_DEF);
+                if(g_md_version_handle == NULL)
+                {
+                    LOGE("g_md_version_handle get fail.");
+                    return QL_ERR_FAILED;
+                }
+            }
+            
+            ret = mbtk_radio_state_change_cb_reg(mbtk_modem_state_change_cb);
+            if(ret != 0)
+            {
+                
+                ret = mbtk_ril_close(MBTK_AT_PORT_DEF);
+                if(ret < 0) 
+                {
+                    LOGE("mbtk_info_handle_free fail.");
+                    return QL_ERR_FAILED;
+                }
+                
+                LOGE("call mbtk_radio_state_change_cb_reg failed");
+                return QL_ERR_FAILED;
+            }
+            
+        }
+        
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get module temperature.
+  @param[out] temperature The current temperature
+  @return Whether to successfully get the temperature
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_get_temperature(float *temperature);
+
+    
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get device serial numbers.
+  @param[out] p_info Pointer that point to ql_dm_device_serial_numbers_info_t
+  @return Whether to successfully get the serial numbers
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_get_device_serial_numbers(ql_dm_device_serial_numbers_info_t *p_info)
+{
+    int ret = -1;
+    if(ql_info_handle == NULL )
+    {
+        LOGE("DM no init");
+        return QL_ERR_NOT_INIT;
+    }
+    
+    ret = mbtk_imei_get(ql_info_handle, p_info->imei);
+    if(ret != 0) 
+    {
+        LOGE("Error : %d\n", ret);
+        return QL_ERR_FAILED;
+    } 
+    if(strlen(p_info->imei) > 0)
+    {
+        p_info->imei_valid = IMEI_VALID;
+    }
+
+
+    return QL_ERR_OK;
+  
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get device firmware revision identification.
+  @param[out] firmware_rev_id Return device firmware revision id
+  @param[in] firmware_rev_id_len The length of firmware_rev_id
+  @return Whether to successfully get the firmware revision id
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_get_device_firmware_rev_id(char *firmware_rev_id, int firmware_rev_id_len)
+{
+    int ret = -1;
+    
+    if(ql_info_handle == NULL)
+    {
+        LOGE("DM no init");
+        return QL_ERR_NOT_INIT;
+    }
+    
+    //ret = mbtk_get_modem_version(ql_info_handle, (void *)firmware_rev_id);
+    //mbtk_v2 do not have function
+    ret = -1;
+    if(ret < 0)
+    {
+        LOGE("get modem version failed");
+        return QL_ERR_FAILED;
+    }
+    return 0;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get air plane mode.
+  @param[out] p_info Pointer that point to QL_DM_AIR_PLANE_MODE_TYPE_E
+  @return Whether to successfully get the air plane mode
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_get_air_plane_mode(QL_DM_AIR_PLANE_MODE_TYPE_E *p_info)
+{
+    
+    int ret = -1;
+    mbtk_radio_state_enum tmp_rf;
+    if(ql_info_handle == NULL)
+    {
+        LOGE("DM no init");
+        return QL_ERR_NOT_INIT;
+    }
+    ret = mbtk_radio_state_get(ql_info_handle, &tmp_rf);
+    if (ret != 0)
+    {
+        LOGE("mbtk_radio_state_get fail.");
+        return QL_ERR_FAILED;
+    }
+    if(tmp_rf == LYNQ_AIR_PLANE_MODE_OFF)
+    {
+        *p_info = QL_DM_AIR_PLANE_MODE_OFF;
+    }
+    else if(tmp_rf == LYNQ_AIR_PLANE_MODE_ON)
+    {
+        *p_info = QL_DM_AIR_PLANE_MODE_ON;
+    }
+        
+    return 0;
+
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set air plane mode.
+  @param[in] air_plane_mode 1:ON, 2:OFF
+  @return Whether to successfully set the air plane mode
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+
+
+int ql_dm_set_air_plane_mode(QL_DM_AIR_PLANE_MODE_TYPE_E air_plane_mode)
+{
+    mbtk_radio_state_enum radio = MBTK_RADIO_STATE_MINI_FUNC;
+    int reset = 0;
+    int rf_mode = -1;
+    int ret = -1;
+    
+    if(ql_info_handle == NULL)
+    {
+        LOGE("DM no init");
+        return QL_ERR_NOT_INIT;
+    }
+    if(air_plane_mode == QL_DM_AIR_PLANE_MODE_ON)
+    {
+        rf_mode = LYNQ_AIR_PLANE_MODE_ON;
+    }
+    
+    if(air_plane_mode == QL_DM_AIR_PLANE_MODE_OFF)
+    {
+        rf_mode = LYNQ_AIR_PLANE_MODE_OFF;
+
+    }
+    
+    if (rf_mode != LYNQ_AIR_PLANE_MODE_ON && rf_mode != LYNQ_AIR_PLANE_MODE_OFF) 
+    {
+        LOGE("Input mode is error!");
+        return QL_ERR_OP_UNSUPPORTED;
+    }
+
+    
+    ret = mbtk_radio_state_set(ql_info_handle, radio, reset);
+    if(ret != 0)
+    {
+        LOGE("ql_dm_set_air_plane_mode failed");
+    }
+    mbtk_send_singnal();
+    return QL_ERR_OK;
+
+
+}
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register air plane mode event.
+  @param[in] cb_func Air plane mode indication callback function
+  @return Whether the air plane mode event was successfully registered.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+
+int ql_dm_set_air_plane_mode_ind_cb(ql_dm_air_plane_mode_ind_cb cb_func) 
+{
+    if(ql_info_handle == NULL)
+    {
+        LOGE("No init ");
+        return QL_ERR_NOT_INIT;
+    }
+    
+    g_air_plane_mode_cb = cb_func;
+
+    if (!g_thread_running) 
+    {
+        g_thread_running = true;
+        if (pthread_create(&g_air_plane_mode_thread, NULL, air_plane_mode_monitor, NULL) != 0) 
+        {
+            LOGE("Failed to create air plane mode monitor thread");
+            g_thread_running = false;
+            return QL_ERR_FAILED;
+        }
+    }
+    
+    return QL_ERR_OK;
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get cpu occupancy.
+  @param[out] cpu_occupancy The percentage of cpu occupancy
+  @return Whether to successfully get the cpu occupancy
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_get_cpu_occupancy(float *cpu_occupancy);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get mem usage.
+  @param[out] mem_use The percentage of mem usage
+  @return Whether to successfully get the memory usage
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_get_mem_usage(float *mem_use);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get NV item value.
+  @param[in] nv_item_name The NV item name that is either NV item id or NV item path
+  @param[out] nv_item_value The NV value buf of nv_item_name
+  param[in] nv_item_value_len The length of nv_item_value
+  param[out] nv_len The real length of nv_item_name
+  @return Whether to successfully get the NV value
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_get_nv_item_value(char *nv_item_name, unsigned char *nv_item_value, int nv_item_value_len, 
+        int *nv_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set NV item value.
+  @param[in] nv_item_name The NV item name that is either NV item id or NV item path
+  @param[in] nv_item_value The NV value of nv_item_name
+  @param[in] nv_item_value_len The length of nv_item_value
+  param[out] nv_len The real length of nv_item_name
+  @return Whether to successfully set the NV value
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_set_nv_item_value(char *nv_item_name, unsigned char *nv_item_value, int nv_item_value_len, 
+        int *nv_len);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set radio on, its function is the same as at+cfun=1.
+  @return Whether to successfully set the radio on
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_set_radio_on(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set radio off, its function is the same as at+cfun=0.
+  @return Whether to successfully set the radio off
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_set_radio_off(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get modem mem and CPU utilization.
+  @param[out] mem_use The percentage of modem utilization
+  @return Whether to successfully get the modem utilization
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_get_modem_cpu_occupancy(float *cpu_occupancy);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get modem mem utilization.
+  @param[out] mem_use The percentage of modem utilization
+  @return Whether to successfully get the modem utilization
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_get_modem_mem_usage(float *mem_use);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get QOOS enable state
+  @param[out] enable The enable state of QOOS
+  @return Whether to successfully get the QOOS enable state
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_get_qoos_enable(char *enable);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set QOOS enable state
+  @param[in] enable The enable state of QOOS
+  @return Whether to successfully set the QOOS enable state
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_set_qoos_enable(char enable);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get QOOS configuration
+  @param[out] config The configuration of QOOS
+  @return Whether to successfully get the QOOS configuration
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+//int ql_dm_get_qoos_config(ql_dm_qoos_config_t *config);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set QOOS configuration
+  @param[in] config The configuration of QOOS
+  @return Whether to successfully set the QOOS configuration
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+//int ql_dm_set_qoos_config(ql_dm_qoos_config_t config);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get MSSR(Modem SubSysem Reset) level.
+  @param[out] p_level The MSSR level
+  @return Whether to successfully get the MSSR level
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_get_mssr_level(int *p_level);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set MSSR(Modem SubSysem Reset) level.
+  @param[in] level The MSSR level
+  @return Whether to successfully set the MSSR level
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_set_mssr_level(int level);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  bind subscription 
+  @param[in] sub_type subscription type 
+  @return Whether to successfully bind subscription.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_bind_subscription(QL_DM_BIND_SUB_TYPE_E sub_type);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @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_dm_set_service_error_cb(ql_dm_service_error_cb_f cb)
+{
+    int ret = -1;
+    if(ql_info_handle == NULL)
+    {
+        LOGE("DM no init ");
+        return QL_ERR_NOT_INIT;
+
+    }
+    global_dm_error_cb = cb;
+    ret = mbtk_ril_ser_state_change_cb_reg(mbtk_dm_set_service_error_func);
+    if(ret != 0)
+    {
+        LOGE("call mbtk_ril_server_state_change_reg failed");
+        return QL_ERR_FAILED;
+    }
+    
+    return QL_ERR_OK;
+}
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get module the last time shutdown reason 
+  @param[out] shutdown_reason the shutdown reason
+  @return
+  QL_ERR_OK - successful
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_get_shutdown_reason(QL_DM_SHUTDOWN_REASON_E *shutdown_reason);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get module this time bootup reason 
+  @param[out] bootup_reason the bootup reason
+  @return
+  QL_ERR_OK - successful
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_get_bootup_reason(QL_DM_BOOT_UP_REASON_E *bootup_reason);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief set oos config 
+  @param[out] oos param
+  @return
+  QL_ERR_OK - successful
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_set_qoos_config(int p1, int p2, int p3);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief get oos config 
+  @param[out] oos param
+  @return
+  QL_ERR_OK - successful
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_get_qoos_config(int *p1, int *p2, int *p3);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief set oos enable 
+  @param[out] oos param
+  @return
+  QL_ERR_OK - successful
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_dm_set_qoos_enable(char enable);
+#ifdef __cplusplus
+}
+#endif
+
+
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_ecall.c b/mbtk/libql_lib_v2_rilv2/ql_ecall.c
new file mode 100755
index 0000000..0d77b7d
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_ecall.c
Binary files differ
diff --git a/mbtk/libql_lib_v2_rilv2/ql_fota.c b/mbtk/libql_lib_v2_rilv2/ql_fota.c
new file mode 100755
index 0000000..ebcd03c
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_fota.c
@@ -0,0 +1,123 @@
+/**  
+  @file
+  ql_fota.h
+
+  @brief
+  This file provides the definitions for device, and declares the 
+  API functions.
+
+*/
+/*============================================================================
+  Copyright (c) 2017 Quectel Wireless Solution, Co., Ltd.  All Rights Reserved.
+  Quectel Wireless Solution Proprietary and Confidential.
+ =============================================================================*/
+/*===========================================================================
+
+                        EDIT HISTORY FOR MODULE
+
+This section contains comments describing changes made to the module.
+Notice that changes are listed in reverse chronological order.
+
+
+WHEN        WHO            WHAT, WHERE, WHY
+----------  ------------   ----------------------------------------------------
+25/11/2021  jessie.lei      create
+=============================================================================*/
+#ifndef __QL_FOTA_H__
+#define __QL_FOTA_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "fota_info.h"
+
+/*
+ * callback function define, used to get upgrade state and rate of process
+ */
+typedef int(*ql_fota_cb_f)(int state, int percent);
+
+
+/*******************************************************************************
+* @brief fota initialize
+  @param 
+  @return 
+        if success return 0, else return -1
+ *******************************************************************************/
+int ql_fota_init(void);
+
+
+/*******************************************************************************
+* @brief fota de-initialize
+  @param 
+  @return 
+        if success return 0, else return -1
+ *******************************************************************************/
+int ql_fota_deinit(void);
+
+
+/*******************************************************************************
+* @brief set fota callback
+  @param 
+    cb: callback function
+  @return 
+        if success return 0, else return -1
+ *******************************************************************************/
+int ql_fota_set_cb(ql_fota_cb_f cb);
+
+
+/*******************************************************************************
+* @brief fota initialize
+  @param 
+    otasize: The OTA firmware size
+  @return 
+        if success return 0, else return -1
+ *******************************************************************************/
+int ql_fota_start(unsigned int otasize);
+
+
+/*******************************************************************************
+* @brief write fota firmware data
+  @param 
+    buffer: The buffer 
+    size  : Data length in buffer
+  @return 
+        if success return 0, else return -1
+ *******************************************************************************/
+int ql_fota_write(unsigned char *buffer, unsigned int size);
+
+
+/*******************************************************************************
+* @brief get fota state
+  @param 
+    state: fota state, refer to fota_state_t
+  @return 
+        if success return 0, else return -1
+ *******************************************************************************/
+int ql_fota_get_state(fota_state_t *state);
+
+
+/*******************************************************************************
+* @brief set fota state
+  @param 
+    state: fota state, refer to fota_state_t
+  @return 
+        if success return 0, else return -1
+ *******************************************************************************/
+int ql_fota_set_state(fota_state_t state);
+
+
+/*******************************************************************************
+* @brief finish fota process
+  @param 
+  @return 
+        if success return 0, else return -1
+ *******************************************************************************/
+int ql_fota_done(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__QL_FOTA_H__
diff --git a/mbtk/libql_lib_v2_rilv2/ql_fota_api.c b/mbtk/libql_lib_v2_rilv2/ql_fota_api.c
new file mode 100755
index 0000000..9b833da
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_fota_api.c
@@ -0,0 +1,133 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "ql_fota_api.h"
+#include "mbtk_type.h"
+#include "mbtk_fota.h"
+#include "mbtk_log.h"
+#include "mbtk_utils.h"
+
+unsigned int Process_flag = 0;
+char addr_buf[128]={0};
+int segment_size =0;
+
+#define StatFunc(x,y) stat(x,y)
+
+int funstat(  char *filename)
+{
+    int ret = 0;
+    struct stat tmep_s;
+
+    memset(&tmep_s, 0, sizeof(stat));
+    ret = StatFunc(filename, &tmep_s);
+
+    if (ret)
+    {
+        LOGE("stat %s failed! error_code: %s", filename ,strerror(errno));
+        return -1;
+    }
+
+    if (tmep_s.st_size > 0)
+    {
+        segment_size = tmep_s.st_size;
+    }
+
+    return 0;
+}
+
+
+int ql_fota_cb(int status, int percent)
+{
+    LOGE("%d: percent: %d%%\n", percent/10, percent);
+    Process_flag = percent;
+    return 0;
+}
+
+int ql_abfota_start_update(const char *package_path)
+{
+    LOGI("%s, %d", __FUNCTION__, __LINE__);
+    int ret = 0;
+    int len = 0;
+
+    ret = mbtk_fota_init(ql_fota_cb);
+    if (ret)
+    {
+        LOGE("ql_abfota_start_update init fail");
+        return -1;
+    }
+
+    memset(addr_buf, 0, sizeof(addr_buf));
+    sprintf(addr_buf, "%supdata.bin", package_path);
+    len = strlen(addr_buf);
+    if (len > 127)
+    {
+        LOGE("ql_abfota_start_update get package_path fail");
+        return -1;
+    }
+
+    if(strncmp(addr_buf, "http", 4) == 0)
+    {
+        segment_size = 62914560;
+        ret = mbtk_fota_fw_write_by_url(addr_buf, segment_size,10, 600);
+    }
+    else
+    {
+        /*获取升级文件的大小*/
+        ret = funstat(addr_buf);
+        if (ret)
+        {
+            LOGE("ql_abfota_start_update get segment_size fail");
+            return -1;
+        }
+
+        LOGI("addr_buf:%s, segment_size:%d", addr_buf, segment_size);
+        ret = mbtk_fota_fw_write(addr_buf, segment_size);
+    }
+
+    if (ret)
+    {
+        LOGE("ql_abfota_start_update fail");
+        return -1;
+    }
+
+    mbtk_system("sync");
+
+    return 0;
+}
+
+int ql_abfota_get_update_status(update_info_t * update_info)
+{
+    int fota_t;
+
+    fota_t = mbtk_fota_status();
+
+    if (fota_t == 3)
+    {
+        update_info->ota_state = UPDATE;
+        update_info->percentage = Process_flag;
+        update_info->exit_code = E_UPDATE_PACKAGE_NOEXIST;
+    }
+    else if (fota_t == 4)
+    {
+        update_info->ota_state = WRITEDONE;
+        update_info->percentage = Process_flag;
+        update_info->exit_code = E_NO_ERROR;
+    }
+    else if (fota_t == 5)
+    {
+        update_info->ota_state = FAILED;
+        update_info->percentage = Process_flag;
+        update_info->exit_code = E_WRITE_SEG_FAILED;
+    }
+    else if (fota_t == -1)
+    {
+        LOGE("ql_abfota_get_update_status fail");
+        return -1;
+    }
+
+    return 0;
+}
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_fota_common.c b/mbtk/libql_lib_v2_rilv2/ql_fota_common.c
new file mode 100755
index 0000000..1a0cb90
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_fota_common.c
@@ -0,0 +1,48 @@
+
+/**
+  @file
+  ql_fota_common.h
+
+  @brief
+  This file provides the definitions for common functions, and declares the
+  common functions.
+
+*/
+/*============================================================================
+  Copyright (c) 2017 Quectel Wireless Solution, Co., Ltd.  All Rights Reserved.
+  Quectel Wireless Solution Proprietary and Confidential.
+ =============================================================================*/
+/*===========================================================================
+
+                        EDIT HISTORY FOR MODULE
+
+This section contains comments describing changes made to the module.
+Notice that changes are listed in reverse chronological order.
+
+
+WHEN        WHO            WHAT, WHERE, WHY
+----------  ------------   ----------------------------------------------------
+23/08/2019  Nebula.li      create
+=============================================================================*/
+
+#ifndef __QL_FOTA_COMMON_H
+#define __QL_FOTA_COMMON_H
+
+#include <stdint.h>
+
+#define QL_OTAD_CLIENT_INIT_CNT_MAX  20
+
+#define QL_OTAD_SEND_MSG_TIMEOUT     (3 * 1000)
+
+typedef void (*ql_otad_service_error_cb_f)(int error);
+
+int ql_otad_client_init(void);
+int ql_otad_client_release(void);
+int ql_otad_send_msg_sync(int32_t msg_id, 
+                          void *p_req_msg_data,
+                          uint32_t req_msg_data_len,
+                          void *p_resp_msg_data,
+                          uint32_t resp_msg_data_len,
+                          uint32_t timeout);
+
+#endif  /* __QL_FOTA_COMMON_H */
diff --git a/mbtk/libql_lib_v2_rilv2/ql_gnss.c b/mbtk/libql_lib_v2_rilv2/ql_gnss.c
new file mode 100755
index 0000000..85322e3
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_gnss.c
@@ -0,0 +1,879 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_gnss.c
+  @brief SIM service API
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  Copyright (c) 2024 mobiletek Wireless Solution, Co., Ltd. All Rights Reserved.
+  mobiletek 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
+  --------   ---------    -----------------------------------------------------------------
+  20241022    yq.wang      Created .
+-------------------------------------------------------------------------------------------------*/
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "ql_type.h"
+#include "ql_gnss.h"
+#include "mbtk_type.h"
+#include "mbtk_gnss.h"
+#include "mbtk_log.h"
+
+/*----------------------------------------------DEFINE-------------------------------------------*/
+#define QL_GNSS_LOGE LOGE
+#define QL_GNSS_LOGD LOGD
+
+#define QL_GNSS_TIMEOUT 5
+#define QL_GNSS_NMEA_SIZE_MAX 128
+#define QL_GNSS_AGPS_URL_SIZE_MAX 128
+
+#define QL_AGNSS_DOWNLOAD_TIMEPUT 60
+#define QL_AGNSS_INJECT_TIMEOUT 20
+
+#define QL_AGNSS_URL_PATH "http://uagnss.allystar.com:80/ephemeris/"
+
+#define QL_AGNSS_EPH_GPS                "HD_GPS.hdb"
+#define QL_AGNSS_EPH_BDS                "HD_BDS.hdb"
+#define QL_AGNSS_EPH_GLO                "HD_GLO.hdb"
+#define QL_AGNSS_EPH_GAL                "HD_GAL.hdb"
+#define QL_AGNSS_EPH_QZS                "HD_QZS.hdb"
+#define QL_AGNSS_EPH_GPS_BDS            "HD_GPS_BDS.hdb"
+#define QL_AGNSS_EPH_GPS_GLO            "HD_GPS_GLO.hdb"
+#define QL_AGNSS_EPH_GPS_GAL            "HD_GPS_GAL.hdb"
+#define QL_AGNSS_EPH_GPS_QZSS           "HD_GPS_QZSS.hdb"
+
+/*----------------------------------------------DEFINE-------------------------------------------*/
+
+/*----------------------------------------------ENUM---------------------------------------------*/
+typedef enum {
+    QL_GNSS_INIT_STOP  = 0,
+    QL_GNSS_INIT_START,
+}ql_gnss_init_enum;
+
+/*----------------------------------------------ENUM---------------------------------------------*/
+
+/*----------------------------------------------STRUCT-------------------------------------------*/
+typedef struct {
+    ql_gnss_init_enum  status;
+    ql_gnss_ind_cb_f   ind_cb;
+    ql_gnss_error_cb_f server_cb;
+    time_t             timestamp;
+}ql_gnss_info_handle_t;
+
+/*----------------------------------------------STRUCT-------------------------------------------*/
+
+/*----------------------------------------------GLOBAL VARIABLE----------------------------------*/
+extern long timezone;
+
+/*----------------------------------------------GLOBAL VARIABLE----------------------------------*/
+
+/*----------------------------------------------GLOBAL STATIC VARIABLE---------------------------*/
+static ql_gnss_info_handle_t* gnss_handle = NULL;
+
+/*----------------------------------------------GLOBAL STATIC VARIABLE---------------------------*/
+
+/*----------------------------------------------GNSS FUNCTION-------------------------------------*/
+static time_t ql_get_timestamp(char *time)
+{
+    char tmp_char[4] = {0};
+    struct tm tmp_time;
+
+    memset(&tmp_time, 0, sizeof(struct tm));
+    memset(tmp_char, 0, sizeof(tmp_char));
+    memcpy(tmp_char, &time[4], 2);
+    tmp_time.tm_sec = atoi(tmp_char);
+
+    memcpy(tmp_char, &time[2], 2);
+    tmp_time.tm_min = atoi(tmp_char);
+
+    memcpy(tmp_char, &time[0], 2);
+    tmp_time.tm_hour = atoi(tmp_char);
+
+    memcpy(tmp_char, &time[6], 2);
+    tmp_time.tm_mday = atoi(tmp_char);
+
+    memcpy(tmp_char, &time[8], 2);
+    tmp_time.tm_mon = atoi(tmp_char) - 1;
+
+    memcpy(tmp_char, &time[10], 2);
+    tmp_time.tm_year = 100 + atoi(tmp_char);
+
+    time_t _t = mktime(&tmp_time);
+    tzset();
+    _t = _t - timezone;
+
+    return _t;
+}
+
+static time_t ql_get_gnss_time_sec(char *data, int data_len)
+{
+//    int i = 0, num = 0;
+    char* previous_p = data;
+    char* current_p = NULL;
+    int current_get_num = 0;
+    char time[15] = {0};
+
+    //$GNRMC,024142.000,A,3039.364421,N,10403.417935,E,0.051,0.00,030124,,E,A*00
+
+    do
+    {
+        current_p = strchr(previous_p, ',');
+        if(current_p != NULL)
+        {
+            current_get_num++;
+            if(current_get_num == 2)
+            {
+                if(previous_p != current_p)
+                {
+                    memcpy(time, previous_p, 6);
+                    //QL_GNSS_LOGE("[%s] time:%s.", __func__, time);
+                }
+                else
+                {
+                    gnss_handle->timestamp = 0;
+                    return 0;
+                }
+            }
+
+            if(current_get_num == 10)
+            {
+                if(previous_p != current_p)
+                {
+                    memcpy(time + 6, previous_p, 6);
+                    //QL_GNSS_LOGE("[%s] date + time:%s.", __func__, time);
+                    break;
+                }
+                else
+                {
+                    gnss_handle->timestamp = 0;
+                    return 0;
+                }
+            }
+
+            if(current_p + 1 <= data + data_len)
+            {
+                previous_p = current_p + 1;
+            }
+            else
+            {
+                QL_GNSS_LOGE("[%s] data out of range.", __func__);
+                gnss_handle->timestamp = 0;
+                return 0;
+            }
+        }
+    }while(current_p != NULL);
+
+    gnss_handle->timestamp = ql_get_timestamp(time);
+
+    return gnss_handle->timestamp;
+}
+
+static void ql_gnss_callback(uint32 ind_type, const void* data, uint32 data_len)
+{
+    if(data == NULL || data_len <= 0)
+    {
+        QL_GNSS_LOGE("[%s] data is NULL.", __func__);
+        return;
+    }
+
+    if(gnss_handle->ind_cb != NULL)
+    {
+        if(ind_type == MBTK_GNSS_IND_NMEA)
+        {
+            nmea_srv_ind_msg nmea_msg = {0};
+            memset(&nmea_msg, 0x0, sizeof(nmea_srv_ind_msg));
+            nmea_msg.msg_id = QL_GNSS_NMEA_MSG;
+            if(data_len <= QL_GNSS_NMEA_SIZE_MAX)
+            {
+                memcpy(nmea_msg.nmea_sentence, (const char *)data, data_len);
+            }
+            else
+            {
+                QL_GNSS_LOGE("[%s] data too long. %s", __func__, (char*)data);
+                return;
+            }
+
+            if(NULL != strstr((char*)data, "RMC"))
+            {
+                nmea_msg.time = ql_get_gnss_time_sec(nmea_msg.nmea_sentence, data_len);
+            }
+            else
+            {
+                nmea_msg.time = gnss_handle->timestamp;
+            }
+
+            gnss_handle->ind_cb((void*)&nmea_msg);
+        }
+        else
+        {
+            QL_GNSS_LOGE("[%s] Unknown IND : %d.", __func__, ind_type);
+        }
+    }
+
+}
+
+/*----------------------------------------------GNSS FUNCTION-------------------------------------*/
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Initialize the gnss client
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_init(void)
+{
+    if(NULL == gnss_handle)
+    {
+        gnss_handle = (ql_gnss_info_handle_t*)malloc(sizeof(ql_gnss_info_handle_t));
+        if(NULL == gnss_handle)
+        {
+            QL_GNSS_LOGE("[%s] gnss handle malloc fail.", __func__);
+            return QL_ERR_FAILED;
+        }
+
+        gnss_err_enum ret = mbtk_gnss_init(ql_gnss_callback);
+        if(ret == GNSS_ERR_OK)
+        {
+            gnss_handle->status = QL_GNSS_INIT_STOP;
+            ret = mbtk_gnss_ind_set(MBTK_GNSS_IND_NMEA, QL_GNSS_TIMEOUT);
+            if(ret != GNSS_ERR_OK)
+            {
+                QL_GNSS_LOGE("[%s] gnss ind set fail.[%d]", __func__, ret);
+                goto error_2;
+            }
+        }
+        else
+        {
+            QL_GNSS_LOGE("[%s] gnss init fail.[%d]", __func__, ret);
+            goto error_1;
+        }
+
+        gnss_handle->ind_cb = NULL;
+        gnss_handle->server_cb = NULL;
+        gnss_handle->timestamp = 0;
+    }
+
+    return QL_ERR_OK;
+error_2:
+    if(gnss_handle->status == QL_GNSS_INIT_START)
+    {
+        mbtk_gnss_deinit();
+        gnss_handle->status = QL_GNSS_INIT_STOP;
+    }
+error_1:
+    if(gnss_handle)
+    {
+        free(gnss_handle);
+        gnss_handle = NULL;
+    }
+    return QL_ERR_FAILED;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Deinitialize the  gnss client
+  @return
+  QL_ERR_OK - successful
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_deinit(void)
+{
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    gnss_handle->timestamp = 0;
+    gnss_handle->server_cb = NULL;
+    gnss_handle->ind_cb = NULL;
+
+    gnss_err_enum ret = mbtk_gnss_deinit();
+    if(ret == GNSS_ERR_OK)
+    {
+        gnss_handle->status = QL_GNSS_INIT_STOP;
+    }
+    else
+    {
+        QL_GNSS_LOGE("[%s] gnss init fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    free(gnss_handle);
+    gnss_handle = NULL;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Start gnss
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_start(void)
+{
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    gnss_err_enum ret = GNSS_ERR_UNKNOWN;
+    ret = mbtk_gnss_open(255, QL_GNSS_TIMEOUT);
+    if(ret != GNSS_ERR_OK)
+    {
+        LOGE("[%s] gnss open fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    gnss_handle->status = QL_GNSS_INIT_START;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Stop gnss
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_stop(void)
+{
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    gnss_err_enum ret = GNSS_ERR_UNKNOWN;
+    ret = mbtk_gnss_close(QL_GNSS_TIMEOUT);
+    if(ret != GNSS_ERR_OK)
+    {
+        LOGE("[%s] gnss close fail.[%d]", ret);
+        return QL_ERR_FAILED;
+    }
+
+    gnss_handle->status = QL_GNSS_INIT_STOP;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Set gnss start mode
+  @param[in] mask Gnss start mode
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_set_start_mode(QL_GNSS_START_MODE_E mask)
+{
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    gnss_err_enum ret = GNSS_ERR_UNKNOWN;
+    char param_buf[32] = {0};
+//    int  length = 0;
+    int  mode = 0;
+
+    if(mask == QL_GNSS_COLD_START)
+    {
+        mode = 3;
+    }
+    else if(mask == QL_GNSS_WARM_START)
+    {
+        mode = 2;
+    }
+    else if(mask == QL_GNSS_HOT_START)
+    {
+        mode = 1;
+    }
+    else
+    {
+        QL_GNSS_LOGE("[%s] mask error.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    snprintf(param_buf, 32, "$RESET,%d", mode);
+    ret = mbtk_gnss_setting(param_buf, QL_GNSS_TIMEOUT);
+    if(ret != GNSS_ERR_OK)
+    {
+        LOGE("[%s] gnss setting fail.[%d]", __func__);
+        return QL_ERR_FAILED;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get gnss nmea
+  @param[in] nmea_str
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_qgpsgnmea(nmeasrc_sentences *nmea_str)
+{
+    UNUSED(nmea_str);
+
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Set gnss qgpscfg
+  @param[in] enable
+  @param[in] str
+  @param[in] len
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_set_qgpscfg(uint32_t enable, char *str, uint32_t len)
+{
+    UNUSED(enable);
+    UNUSED(str);
+    UNUSED(len);
+
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get engine state
+  @param[out] state  on/ff
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_get_engine_state(QL_GNSS_ENGINE_STATE_E *state)
+{
+    UNUSED(state);
+
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Set Constellation .
+  @param[in] mask  GPS/GLO/BDS/GAL/QZSS/SBAS
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_set_constellation(QL_GNSS_CONSTELLATION_MASK_E mask)
+{
+    UNUSED(mask);
+
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get Constellation
+  @param[out] mask   GPS/GLO/BDS/GAL/QZSS/SBAS
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_get_constellation(QL_GNSS_CONSTELLATION_MASK_E *mask)
+{
+    UNUSED(mask);
+
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Set nmea type
+  @param[in] mask type
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_set_nmea_type(uint32_t mask)
+{
+    UNUSED(mask);
+
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get nmea version
+  @param[out] version nmea version
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_get_nmea_version(QL_GNSS_NMEA_VERSION_ID_E *version)
+{
+    UNUSED(version);
+
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Set nmea version
+  @param[in] version nmea version
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_set_nmea_version(QL_GNSS_NMEA_VERSION_ID_E version)
+{
+    UNUSED(version);
+
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Set gnss agnss mode
+  @param[in] mask Gnss agnss mode
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_set_agnss_mode(uint32_t mask)
+{
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    char eph_file[32] = {0};
+    gnss_err_enum ret = GNSS_ERR_UNKNOWN;
+    char write_buff[512] = {0};
+//    int write_length = 0;
+
+    if((mask & QL_GNSS_EPH_DATA_GPS) == mask)
+    {
+        memcpy(eph_file, QL_AGNSS_EPH_GPS, strlen(QL_AGNSS_EPH_GPS));
+    }
+    else if((mask & QL_GNSS_EPH_DATA_BDS) == mask)
+    {
+        memcpy(eph_file, QL_AGNSS_EPH_BDS, strlen(QL_AGNSS_EPH_BDS));
+    }
+    else if((mask & QL_GNSS_EPH_DATA_GLO) == mask)
+    {
+        memcpy(eph_file, QL_AGNSS_EPH_GLO, strlen(QL_AGNSS_EPH_GLO));
+    }
+    else if((mask & QL_GNSS_EPH_DATA_GAL) == mask)
+    {
+        memcpy(eph_file, QL_AGNSS_EPH_GAL, strlen(QL_AGNSS_EPH_GAL));
+    }
+    else if((mask & QL_GNSS_EPH_DATA_QZSS) == mask)
+    {
+        memcpy(eph_file, QL_AGNSS_EPH_QZS, strlen(QL_AGNSS_EPH_QZS));
+    }
+    else if((mask & (QL_GNSS_EPH_DATA_GPS | QL_GNSS_EPH_DATA_BDS)) == mask)
+    {
+        memcpy(eph_file, QL_AGNSS_EPH_GPS_BDS, strlen(QL_AGNSS_EPH_GPS_BDS));
+    }
+    else if((mask & (QL_GNSS_EPH_DATA_GPS | QL_GNSS_EPH_DATA_GLO)) == mask)
+    {
+        memcpy(eph_file, QL_AGNSS_EPH_GPS_GLO, strlen(QL_AGNSS_EPH_GPS_GLO));
+    }
+    else if((mask & (QL_GNSS_EPH_DATA_GPS | QL_GNSS_EPH_DATA_GAL)) == mask)
+    {
+        memcpy(eph_file, QL_AGNSS_EPH_GPS_GAL, strlen(QL_AGNSS_EPH_GPS_GAL));
+    }
+    else if((mask & (QL_GNSS_EPH_DATA_GPS | QL_GNSS_EPH_DATA_QZSS)) == mask)
+    {
+        memcpy(eph_file, QL_AGNSS_EPH_GPS_QZSS, strlen(QL_AGNSS_EPH_GPS_QZSS));
+    }
+    else
+    {
+        QL_GNSS_LOGE("[%s] unknown mask.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    snprintf(write_buff, 512, "$AGPSCFG,%s%s,NULL,NULL", QL_AGNSS_URL_PATH, eph_file);
+    ret = mbtk_gnss_setting(write_buff, QL_GNSS_TIMEOUT);
+    if(ret != GNSS_ERR_OK)
+    {
+        LOGE("[%s] gnss setting fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Inject  agnss data
+  @param[in] data agnss data
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_inject_agnss_data(void)
+{
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    gnss_err_enum ret = GNSS_ERR_UNKNOWN;
+    ret = mbtk_gnss_eph_download(QL_AGNSS_DOWNLOAD_TIMEPUT);
+    if(ret != GNSS_ERR_OK)
+    {
+        LOGE("[%s] gnss eph download fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    ret = mbtk_gnss_eph_inject(QL_AGNSS_INJECT_TIMEOUT);
+    if(ret != GNSS_ERR_OK)
+    {
+        LOGE("[%s] gnss eph inject fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Inject UTC time to GNSS Engine.
+  @param[in] timestamp ,unit: ms
+  @return Whether to successfully Start Gnss
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_FAILED  Start Gnss Failed
+  @retval Other error code defined by ql_gnss.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_inject_utc_time(uint64_t timestamp)
+{
+    UNUSED(timestamp);
+
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Set gnss suspend
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_suspend(void)
+{
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Set gnss resume
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_resume(void)
+{
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Register gnss callback
+  @param[in] cb
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_gnss_set_ind_cb(ql_gnss_ind_cb_f cb)
+{
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    gnss_handle->ind_cb = cb;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @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_gnss_set_service_error_cb(ql_gnss_error_cb_f cb)
+{
+    if(NULL == gnss_handle)
+    {
+        QL_GNSS_LOGE("[%s] gnss handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    gnss_handle->server_cb = cb;
+
+    return QL_ERR_OK;
+}
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_gpio.c b/mbtk/libql_lib_v2_rilv2/ql_gpio.c
new file mode 100755
index 0000000..83149b2
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_gpio.c
@@ -0,0 +1,129 @@
+#include "ql_gpio.h"
+#include "mbtk_gpio.h"
+#include "mbtk_log.h"
+#include "mbtk_type.h"
+
+#include <errno.h>
+
+int ql_gpio_init(ENUM_PINNAME       pin_name, 
+                 ENUM_PIN_DIRECTION  dir, 
+                 ENUM_PIN_LEVEL      level, 
+                 ENUM_PIN_PULLSEL    pull_sel
+                 )
+{
+    if(pull_sel != PINPULLSEL_DISABLE)
+    {
+        LOGE("[ql_gpio_init] pull_sel fail.");
+        return RES_BAD_PARAMETER;
+    }
+
+    if(dir == PINDIRECTION_IN)
+    {
+        dir = MBTK_GPIO_DIRECT_IN;
+    }
+    else if(dir == PINDIRECTION_OUT)
+    {
+        dir = MBTK_GPIO_DIRECT_OUT;
+    }
+    else
+    {
+        dir = MBTK_GPIO_DIRECT_UNKNOWN;
+        LOGE("[ql_gpio_init] direction fail.");
+        return RES_BAD_PARAMETER;
+    }
+
+    if(level != PINLEVEL_LOW && level != PINLEVEL_HIGH)
+    {
+        LOGE("[ql_gpio_init] level fail.");
+        return RES_BAD_PARAMETER;
+    }
+
+    if(mbtk_gpio_export(pin_name))
+    {
+        LOGE("[ql_gpio_init]gpio_export fail.");
+        return RES_IO_ERROR;
+    }
+
+    if(mbtk_gpio_direct_set(pin_name, dir))
+    {
+        LOGE("[ql_gpio_init]gpio_direct_set fail.");
+        return RES_IO_ERROR;
+    }
+
+    if(mbtk_gpio_value_set_2(pin_name, level))
+    {
+        LOGE("[ql_gpio_init]gpio_value_set fail.");
+        return RES_IO_ERROR;
+    }
+
+    return RES_OK;
+}
+
+int ql_gpio_set_level(ENUM_PINNAME pin_name, ENUM_PIN_LEVEL level)
+{
+    if(level != PINLEVEL_LOW && level != PINLEVEL_HIGH)
+    {
+        LOGE("[ql_gpio_set_level] level fail.");
+        return RES_BAD_PARAMETER;
+    }
+
+    if(mbtk_gpio_value_set_2(pin_name, level) != 0)
+    {
+        LOGE("[ql_gpio_set_level]gpio_value_set fail.");
+        return RES_IO_ERROR;
+    }
+
+    return RES_OK;
+}
+
+int ql_gpio_get_level(ENUM_PINNAME pin_name)
+{
+    int ret;
+
+    ret = mbtk_gpio_value_get(pin_name);
+    if (ret == -1)
+    {
+        LOGE("[ql_gpio_set_level]gpio_value_set fail.");
+        return RES_IO_ERROR;
+    }
+
+    return ret;
+}
+
+int ql_gpio_set_direction(ENUM_PINNAME pin_name, ENUM_PIN_DIRECTION dir)
+{
+    if(dir == PINDIRECTION_IN)
+    {
+        dir = MBTK_GPIO_DIRECT_IN;
+    }
+    else if(dir == PINDIRECTION_OUT)
+    {
+        dir = MBTK_GPIO_DIRECT_OUT;
+    }
+    else
+    {
+        dir = MBTK_GPIO_DIRECT_UNKNOWN;
+        LOGE("[ql_gpio_init] direction fail.");
+        return RES_BAD_PARAMETER;
+    }
+
+    if(mbtk_gpio_direct_set(pin_name, dir))
+    {
+        LOGE("[ql_gpio_set_direction]gpio_direct_set fail.");
+        return RES_IO_ERROR;
+    }
+
+    return RES_OK;
+}
+
+int ql_gpio_uninit(ENUM_PINNAME pin_name)
+{
+    if(mbtk_gpio_unexport(pin_name))
+    {
+        LOGE("[ql_gpio_uninit]gpio_unexport fail.");
+        return RES_IO_ERROR;
+    }
+
+    return RES_OK;
+}
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_gpio_internal.c b/mbtk/libql_lib_v2_rilv2/ql_gpio_internal.c
new file mode 100755
index 0000000..a00a3c0
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_gpio_internal.c
@@ -0,0 +1,335 @@
+#ifndef __QL_GPIO_INTERNAL_H

+#define __QL_GPIO_INTERNAL_H

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+#include "ql_gpio.h"

+

+typedef enum{

+    INTERNAL_BEGIN = -1,

+    INTERNAL_GPIO_10 = 10,

+    INTERNAL_GPIO_11 = 11,

+    INTERNAL_GPIO_19 = 19,

+    INTERNAL_GPIO_21 = 21,

+    INTERNAL_GPIO_22 = 22,

+    INTERNAL_GPIO_23 = 23,

+    INTERNAL_GPIO_24 = 24,

+    INTERNAL_GPIO_25 = 25,

+    INTERNAL_GPIO_26 = 26,

+    INTERNAL_GPIO_27 = 27,

+    INTERNAL_GPIO_31 = 31,

+    INTERNAL_GPIO_32 = 32,

+    INTERNAL_GPIO_33 = 33,

+    INTERNAL_GPIO_34 = 34,

+    INTERNAL_GPIO_35 = 35,

+    INTERNAL_GPIO_36 = 36,

+    INTERNAL_GPIO_37 = 37,

+    INTERNAL_GPIO_38 = 38,

+    INTERNAL_GPIO_39 = 39,

+    INTERNAL_GPIO_40 = 40,

+    INTERNAL_GPIO_43 = 43,

+    INTERNAL_GPIO_48 = 48,

+    INTERNAL_GPIO_49 = 49,

+    INTERNAL_GPIO_50 = 50,

+    INTERNAL_GPIO_51 = 51,

+    INTERNAL_GPIO_52 = 52,

+    INTERNAL_GPIO_53 = 53,

+    INTERNAL_GPIO_54 = 54,

+    INTERNAL_GPIO_55 = 55,

+    INTERNAL_GPIO_56 = 56,

+    INTERNAL_GPIO_57 = 57,

+    INTERNAL_GPIO_58 = 58,

+    INTERNAL_GPIO_59 = 59,

+    INTERNAL_GPIO_99 = 99,

+    INTERNAL_GPIO_117 = 117,

+    INTERNAL_GPIO_118 = 118,

+    INTERNAL_GPIO_119 = 119,

+    INTERNAL_GPIO_120 = 120,

+    INTERNAL_GPIO_122 = 122,

+    INTERNAL_GPIO_123 = 123,

+    INTERNAL_GPIO_126 = 126,

+    INTERNAL_END = 127

+}INTERNAL_ENUM_PINNAME;

+

+

+/*****************************************************************

+* Function:     __ql_gpio_init 

+* 

+* Description:

+*               This function enables the GPIO function of the specified pin,

+*               and initialize the configurations, including direction,

+*               level and pull selection.

+*

+* Parameters:

+*               pin_name:

+*                   Pin name, one value of INTERNAL_ENUM_PINNAME.

+*               dir:

+*                   The initial direction of GPIO, one value of ENUM_PIN_DIRECTION.

+*               level:

+*                   The initial level of GPIO, one value of ENUM_PIN_LEVEL. 

+*               pullSel:

+*                   Pull selection, one value of ENUM_PIN_PULLSEL.

+* Return:        

+*               RES_OK, this function succeeds.

+*               RES_IO_NOT_SUPPORT, the input GPIO is invalid. 

+*               RES_IO_ERR, the function failed

+*               other place. For example this GPIO has been using as EINT.

+*****************************************************************/

+int __ql_gpio_init(INTERNAL_ENUM_PINNAME       pin_name, 

+                 ENUM_PIN_DIRECTION  dir, 

+                 ENUM_PIN_LEVEL      level, 

+                 ENUM_PIN_PULLSEL    pull_sel

+                 );

+

+/*****************************************************************

+* Function:     __ql_gpio_base_init 

+* 

+* Description:

+*               This function enables the GPIO function of the specified pin.

+*

+* Parameters:

+*               pin_name:

+*                   Pin name, one value of INTERNAL_ENUM_PINNAME.

+*            

+* Return:        

+*               RES_OK, this function succeeds.

+*               RES_IO_NOT_SUPPORT, the input GPIO is invalid. 

+*               RES_IO_ERR, the function failed

+*****************************************************************/

+int __ql_gpio_base_init(INTERNAL_ENUM_PINNAME pin_name );

+

+/*****************************************************************

+* Function:     __ql_gpio_set_level 

+* 

+* Description:

+*               This function sets the level of the specified GPIO.

+*

+* Parameters:

+*               pin_name:

+*                   Pin name, one value of INTERNAL_ENUM_PINNAME.

+*               level:

+*                   The initial level of GPIO, one value of ENUM_PIN_LEVEL. 

+* Return:        

+*               RES_OK, this function succeeds.

+*               RES_IO_NOT_SUPPORT, the input GPIO is invalid. 

+*               RES_IO_ERR, the function failed

+*               other place. For example this GPIO has been using as EINT.

+*****************************************************************/

+int __ql_gpio_set_level(INTERNAL_ENUM_PINNAME pin_name, ENUM_PIN_LEVEL level);

+

+/*****************************************************************

+* Function:     __ql_gpio_get_level 

+* 

+* Description:

+*               This function gets the level of the specified GPIO.

+*

+* Parameters:

+*               pin_name:

+*                   Pin name, one value of INTERNAL_ENUM_PINNAME.

+* Return:        

+*               The level value of the specified GPIO, which is 

+*               nonnegative integer.

+*               RES_IO_NOT_SUPPORT, the input GPIO is invalid.

+*****************************************************************/

+int __ql_gpio_get_level(INTERNAL_ENUM_PINNAME pin_name);

+

+/*****************************************************************

+* Function:     __ql_gpio_set_direction 

+* 

+* Description:

+*               This function sets the direction of the specified GPIO.

+*

+* Parameters:

+*               pin_name:

+*                   Pin name, one value of INTERNAL_ENUM_PINNAME.

+*               dir:

+*                   The initial direction of GPIO, one value of ENUM_PIN_DIRECTION.

+* Return:        

+*               RES_OK, this function succeeds.

+*               RES_IO_NOT_SUPPORT, the input GPIO is invalid. 

+*               RES_IO_ERR, the function failed

+*               other place. For example this GPIO has been using as EINT.

+*****************************************************************/

+int __ql_gpio_set_direction(INTERNAL_ENUM_PINNAME pin_name, ENUM_PIN_DIRECTION dir);

+

+/*****************************************************************

+* Function:     __ql_gpio_get_direction 

+* 

+* Description:

+*               This function gets the direction of the specified GPIO.

+*

+* Parameters:

+*               pin_name:

+*                   Pin name, one value of INTERNAL_ENUM_PINNAME.

+* Return:        

+*               0  INPUT

+*               1  OUTPUT

+*               RES_IO_NOT_SUPPORT, the input GPIO is invalid. 

+*               other place. For example this GPIO has been using as EINT.

+*****************************************************************/

+int __ql_gpio_get_direction(INTERNAL_ENUM_PINNAME pin_name);

+

+

+/*****************************************************************

+* Function:     __ql_gpio_set_pull_selection 

+* 

+* Description:

+*               This function sets the pull selection of the specified GPIO.

+*

+* Parameters:

+*               pin_name:

+*                   Pin name, one value of INTERNAL_ENUM_PINNAME.

+*               ENUM_PIN_PULLSEL:

+*                   Pull selection, one value of ENUM_PIN_PULLSEL.

+* Return:        

+*               RES_OK, this function succeeds.

+*               RES_IO_NOT_SUPPORT, the input GPIO is invalid. 

+*               RES_IO_ERR, the function failed

+*               other place. For example this GPIO has been using as EINT.

+*****************************************************************/

+int __ql_gpio_set_pull_selection(INTERNAL_ENUM_PINNAME pin_name, ENUM_PIN_PULLSEL pull_sel);

+

+/*****************************************************************

+* Function:     __ql_gpio_get_pull_selection 

+* 

+* Description:

+*               This function gets the pull selection of the specified GPIO.

+*

+* Parameters:

+*               pin_name:

+*                   Pin name, one value of INTERNAL_ENUM_PINNAME.

+* Return:        

+*               0   no pull

+*               1   pull down

+*               3   pull up

+*****************************************************************/

+int __ql_gpio_get_pull_selection(INTERNAL_ENUM_PINNAME pin_name);

+

+/*****************************************************************

+* Function:     __ql_gpio_uninit 

+* 

+* Description:

+*               This function releases the specified GPIO that was 

+*               initialized by calling ql_gpio_init() previously.

+*               After releasing, the GPIO can be used for other purpose.

+* Parameters:

+*               pin_name:

+*                   Pin name, one value of INTERNAL_ENUM_PINNAME.

+* Return:        

+*               RES_OK, this function succeeds.

+*               RES_IO_NOT_SUPPORT, the input GPIO is invalid. 

+*               RES_IO_ERR, the function failed

+*               other place. For example this GPIO has been using as EINT.

+*****************************************************************/

+int __ql_gpio_uninit(INTERNAL_ENUM_PINNAME pin_name);

+

+//------------------------------------------------------------------------------

+/*

+* Function:     __ql_eint_enable 

+* 

+* Description:

+*               Set the interrupt sense mode, and enable interrupt. 

+*

+* Parameters:

+*               eint_pin_name:

+*                   EINT pin name, one value of INTERNAL_ENUM_PINNAME that has 

+*                   the interrupt function.

+*

+*               eint_type:

+*                   Interrupt type, level-triggered or edge-triggered.

+*                   Now, only edge-triggered interrupt is supported.

+*

+*               eint_callback:

+*                   call back function

+*

+* Return:        

+*               RES_OK, this function succeeds.

+*               else failed to execute the function. 

+*/

+//------------------------------------------------------------------------------

+int __ql_eint_enable(INTERNAL_ENUM_PINNAME eint_pin_name, ENUM_EINT_TYPE eint_type, ql_eint_callback eint_callback);

+

+

+//------------------------------------------------------------------------------

+/*

+* Function:     __ql_eint_disable 

+* 

+* Description:

+*               Disable the interrupt sense. 

+*

+* Parameters:

+*               eint_pin_name:

+*                   EINT pin name, one value of INTERNAL_ENUM_PINNAME that has 

+*                   the interrupt function.

+*

+* Return:        

+*               RES_OK, this function succeeds.

+*               else failed to execute the function. 

+*/

+//------------------------------------------------------------------------------

+int __ql_eint_disable(INTERNAL_ENUM_PINNAME eint_pin_name);

+

+

+/*-----------------------------------------------------------------------------------------------*/

+/**

+Function:     __ql_set_gpio_function 

+* 

+* Description:

+*             set pin function. 

+*

+* Parameters:

+*            pin_name:

+*            EINT pin name, one value of INTERNAL_ENUM_PINNAME.

+*		 func:

+*		 pin function,value range from 0 to 7

+*

+* Return:        

+*               RES_OK, this function succeeds.

+*               else failed to execute the function. 

+*/

+/*-----------------------------------------------------------------------------------------------*/

+int __ql_set_gpio_function(INTERNAL_ENUM_PINNAME pin_name,unsigned int func);

+

+

+/*-----------------------------------------------------------------------------------------------*/

+/*Function:     __ql_get_gpio_function 

+* 

+* Description:

+*               get pin function. 

+*

+* Parameters:

+*               pin_name:

+*               EINT pin name, one value of INTERNAL_ENUM_PINNAME.

+*

+* Return:        

+*               return 0-7, this function succeeds.

+*               else failed to execute the function. 

+*/

+/*-----------------------------------------------------------------------------------------------*/

+int __ql_get_gpio_function(INTERNAL_ENUM_PINNAME pin_name);

+

+/*-----------------------------------------------------------------------------------------------*/

+/*Function:     __ql_check_pin_function_status 

+* 

+* Description:

+*               Check whether the pin is gpio function. 

+*

+* Parameters:

+*               pin_name:

+*               EINT pin name, one value of INTERNAL_ENUM_PINNAME.

+*

+* Return:        

+*               return 1, this pin is gpio function.

+*               return 0, this pin is not gpio function. 

+*		     else failed to execute the function.

+*/

+/*-----------------------------------------------------------------------------------------------*/

+int __ql_check_pin_function_status(INTERNAL_ENUM_PINNAME  pin_name);

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif

diff --git a/mbtk/libql_lib_v2_rilv2/ql_lanhost.c b/mbtk/libql_lib_v2_rilv2/ql_lanhost.c
new file mode 100755
index 0000000..66f28dd
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_lanhost.c
@@ -0,0 +1,105 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_lanhost.h 
+  @brief LANHOST API 
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  Copyright (c) 2018 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
+  --------   ---          ----------------------------------------------------------
+  20191016   tyler.kuang  Created .
+-------------------------------------------------------------------------------------------------*/
+
+#ifndef __QL_LANHOST_H__
+#define __QL_LANHOST_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "ql_net_common.h"
+
+
+typedef void (*ql_lanhost_ind_cb_f)(QL_LANHOST_EVENT_TYPE_E event_type, ql_lanhost_t *p_host);
+
+typedef void (*ql_lanhost_service_error_cb_f)(int error);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Initialize the lanhost service
+  @return 
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_lanhost_init(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Get all lanhost list, the maximum of lanhost is defined by QL_NET_MAX_LANHOST_NUM 
+  @param[out] list Lanhost array
+  @param[in,out] list_len, in-> array size, out->current instance number
+  @return 
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_lanhost_get_list(ql_lanhost_t *list, int *list_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Register lanhost status change event
+  @param[in] cb 
+  @return 
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_lanhost_set_ind_cb(ql_lanhost_ind_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_lanhost_set_service_error_cb(ql_lanhost_service_error_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief  Deinitialize the lanhost service 
+  @return 
+  QL_ERR_OK - successful
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_lanhost_deinit(void);
+
+#ifdef __cplusplus
+} 
+#endif
+
+#endif
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_lpm.c b/mbtk/libql_lib_v2_rilv2/ql_lpm.c
new file mode 100755
index 0000000..0c767a2
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_lpm.c
@@ -0,0 +1,24 @@
+#include "ql_lpm.h"
+#include "mbtk_lpm.h"
+#include "mbtk_type.h"
+#include "mbtk_log.h"
+
+int ql_lpm_init(ql_lpm_handler_t ql_lpm_handler)
+{
+    if(mbtk_lpm_init((mbtk_lpm_handler_t)ql_lpm_handler))
+    {
+        LOGE("ql_lpm_init fail");
+        return -1;
+    }
+
+    return 0;
+}
+
+int ql_lpm_deinit(void)
+{
+    mbtk_lpm_deinit();
+
+    return 0;
+}
+
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_ms_data_call.c b/mbtk/libql_lib_v2_rilv2/ql_ms_data_call.c
new file mode 100755
index 0000000..02d45fe
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_ms_data_call.c
@@ -0,0 +1,495 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_data_call.h
+  @brief Data service API
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  Copyright (c) 2018 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
+  --------   ---          ----------------------------------------------------------
+  20181024   tyler.kuang  Created .
+-------------------------------------------------------------------------------------------------*/
+
+#ifndef __QL_MS_DATA_CALL_H__
+#define __QL_MS_DATA_CALL_H__
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "ql_data_call.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Initialize the data call service
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_init(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Create a data call instance
+  @param[in] call_id The unique identifier of the data call instance, specified by the user
+  @param[in] call_name Friendly data call name,  specified by the user
+  @param[in] is_background Whether the data call status is maintained by the data call service daemon.
+  If it is 0, the data call instance will be deleted after the data call process exits.
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_create(int call_id, const char *call_name, int is_background);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Alloc for a data call configuration instance
+  @return
+  NULL - Not enough memory
+  Other - successful
+  */
+/*-----------------------------------------------------------------------------------------------*/
+ql_data_call_param_t *ql_ms_data_call_param_alloc(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Initialize the data call configuration instance
+  @param[in] param Point to the data call configuration instance
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_init(ql_data_call_param_t *param);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Release the data call configuration instance
+  @param[in] param Point to the data call configuration instance
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_free(ql_data_call_param_t *param);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Bind APN ID, range:1-16
+  @param[in] param Point to the data call configuration instance
+  @param[in] apn_id APN ID, range:1-16
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_set_apn_id(ql_data_call_param_t *param, int apn_id);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get APN name from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] buf APN ID
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_get_apn_id(ql_data_call_param_t *param, int *apn_id);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure APN name
+  @param[in] param Point to the data call configuration instance
+  @param[in] apn_name APN name
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_set_apn_name(ql_data_call_param_t *param, const char *apn_name);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get APN name from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] buf APN name buffer
+  @param[in] buf_len APN name buffer size
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_get_apn_name(ql_data_call_param_t *param, char *buf, int buf_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure APN user name
+  @param[in] param Point to the data call configuration instance
+  @param[in] user_name APN user name
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_set_user_name(ql_data_call_param_t *param, const char *user_name);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get APN user name from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] buf APN user name buffer
+  @param[in] buf_len APN user name buffer size
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_get_user_name(ql_data_call_param_t *param, char *buf, int buf_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure APN user password
+  @param[in] param Point to the data call configuration instance
+  @param[in] user_password APN user password
+  @return
+  QL_ERR_OK - Not enough memory
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_set_user_password(ql_data_call_param_t *param, const char *user_password);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get APN user password from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] buf APN user password buffer
+  @param[in] buf_len APN user password buffer size
+  @return
+  QL_ERR_OK - Not enough memory
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_get_user_password(ql_data_call_param_t *param, char *buf, int buf_len);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the data call authentication method
+  @param[in] param Point to the data call configuration instance
+  @param[in] auth_pref Defined by QL_DATA_CALL_AUTH_PREF_E
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_set_auth_pref(ql_data_call_param_t *param, int auth_pref);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the data call authentication method
+  @param[in] param Point to the data call configuration instance
+  @param[out] p_data Store return value
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_get_auth_pref(ql_data_call_param_t *param, int *p_data);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the data call IP version
+  @param[in] param Point to the data call configuration instance
+  @param[in] ip_ver Defined by QL_NET_IP_VER_E
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_set_ip_version(ql_data_call_param_t *param, int ip_ver);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get IP version from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] p_ver Store return value
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_get_ip_version(ql_data_call_param_t *param, int *p_ver);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the data call auto reconnection mode
+  @param[in] param Point to the data call configuration instance
+  @param[in] mode Defined by QL_NET_DATA_CALL_RECONNECT_MODE_E
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_set_reconnect_mode(ql_data_call_param_t *param, int reconnect_mode);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get auto reconnection mode from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] p_mode Store return value
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_get_reconnect_mode(ql_data_call_param_t *param, int *p_mode);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the data call auto reconnection interval
+  @param[in] param Point to the data call configuration instance
+  @param[in] time_list Interval time list in ms
+  @param[in] num Number of time list
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_set_reconnect_interval(ql_data_call_param_t *param, int *time_list, int num);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get auto reconnection interval from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] time_list Store return value
+  @param[in,out] p_num
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_get_reconnect_interval(ql_data_call_param_t *param, int *time_list, int *p_num);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the data call sim id
+  @param[in] param Point to the data call configuration instance
+  @param[in] sim_id Store return value
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_set_sim_id(ql_data_call_param_t *param, int sim_id);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get the data call sim id from configuration instance
+  @param[in] param Point to the data call configuration instance
+  @param[out] p_sim_id Store return value
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_param_get_sim_id(ql_data_call_param_t *param, int *p_sim_id);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Configure the specified data call instance
+  @param[in] call_id Specify a data call instance
+  @param[in] param Point to the data call configuration instance
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_config(int call_id, ql_data_call_param_t *param);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get the specified data call configuration instance
+  @param[in] call_id Specify a data call instance
+  @param[in] param Point to the data call configuration instance
+  @return
+  QL_ERR_OK - Successful
+  QL_ERR_INVALID_ARG - Invalid arguments
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_get_config(int call_id, ql_data_call_param_t *param);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Start data call
+  @param[in] call_id Specify a data call instance
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_start(int call_id);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Stop data call
+  @param[in] call_id Specify a data call instance
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_stop(int call_id);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Delete a data call instance
+  @param[in] call_id Specify a data call instance
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_delete(int call_id);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get the current data call instance list
+  @param[out] list Data call instance array
+  @param[in,out] list_len, in-> Data call instance array size, out->current data call instance number
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_get_list(ql_data_call_item_t *list, int *list_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Get the data call status
+  @param[in] call_id Specify a data call instance
+  @param[out] p_sta Point to status instance
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_get_status(int call_id, ql_data_call_status_t *p_sta);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Register data call status change event
+  @param[in] cb
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_set_status_ind_cb(ql_data_call_status_ind_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Set APN related configuration.If the apn does not exist, it is automatically created.
+  @param[in] sim_id SIM ID, range:1-2
+  @param[in] apn_id APN ID, range:1-16
+  @param[in] p_info APN configuration
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_set_apn_config(int sim_id, int apn_id, ql_data_call_apn_config_t *p_info);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Set APN related configuration. If the apn does not exist, it is automatically created and
+  the default parameters are set.
+  @param[in] sim_id SIM ID, range:1-2
+  @param[in] apn_id APN ID, range:1-16
+  @param[out] p_info APN configuration
+  @return
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_get_apn_config(int sim_id, int apn_id, ql_data_call_apn_config_t *p_info);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @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_ms_data_call_set_service_error_cb(ql_data_call_service_error_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Deinitialize the data call service
+  @return
+  QL_ERR_OK - successful
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_data_call_deinit(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_ms_dm.c b/mbtk/libql_lib_v2_rilv2/ql_ms_dm.c
new file mode 100755
index 0000000..b25c38f
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_ms_dm.c
@@ -0,0 +1,436 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_dm.h 
+  @brief device management API
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  Copyright (c) 2021 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
+  --------   ---          ----------------------------------------------------------
+  20200316   stan.li      Optimize the ql_dm_get_modem_state interface
+  20191224   stan.li      Add radio on/off API
+  20190625   stan.li      Created .
+-------------------------------------------------------------------------------------------------*/
+
+#ifndef __QL_MS_DM_H__
+#define __QL_MS_DM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ql_type.h"
+#include "ql_dm.h"
+
+typedef void (*ql_ms_dm_air_plane_mode_ind_cb)(int sim_id, QL_DM_AIR_PLANE_MODE_TYPE_E air_plane_mode);
+typedef void (*ql_ms_dm_modem_state_ind_cb)(int statue);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Initialize DM service.
+  @note You must call this function before other functions can be used in this module.
+  @return Whether the DM service was successfully intialized.
+  @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_ms_dm_init(void);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Deinitialize DM service.
+  @return Whether the DM service was successfully deintialized.
+  @retval QL_ERR_OK successful.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_deinit(void);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get device software version. 
+  @param[out] soft_ver Return software version
+  @param[in] soft_ver_len The length of soft_ver
+  @return Whether to successfully get the software version
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_get_software_version(char *soft_ver, int soft_ver_len);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get modem state.
+  @details QL_DM_MODEM_STATE_ONLINE,if modem starts normally.
+  @details QL_DM_MODEM_STATE_OFFLINE,in modem starts abnormally.
+  @details QL_DM_MODEM_STATE_UNKNOWN,unknown error. 
+  @param[out] modem_state The state of modem
+  @return Whether to successfully get the modem state
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_get_modem_state(QL_DM_MODEM_STATE_TYPE_E *modem_state);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register modem state event. 
+  @param[in] cb_func modem state indication callback function
+  @return Whether the modem state event was successfully registered.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_set_modem_state_change_ind_cb(ql_dm_modem_state_ind_cb cb_func);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get module temperature. 
+  @param[out] temperature The current temperature
+  @return Whether to successfully get the temperature
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_get_temperature(float *temperature);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get device serial numbers. 
+  @param[out] p_info Pointer that point to ql_dm_device_serial_numbers_info_t
+  @return Whether to successfully get the serial numbers
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_get_device_serial_numbers(ql_dm_device_serial_numbers_info_t *p_info);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get device firmware revision identification. 
+  @param[out] firmware_rev_id Return device firmware revision id
+  @param[in] firmware_rev_id_len The length of firmware_rev_id
+  @return Whether to successfully get the firmware revision id
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_get_device_firmware_rev_id(char *firmware_rev_id, int firmware_rev_id_len);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get air plane mode. 
+  @param[in] sim id number
+  @param[out] p_info Pointer that point to QL_DM_AIR_PLANE_MODE_TYPE_E
+  @return Whether to successfully get the air plane mode
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_get_air_plane_mode(int sim_id, QL_DM_AIR_PLANE_MODE_TYPE_E *p_info);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set air plane mode. 
+  @param[in] sim id number
+  @param[in] air_plane_mode 1:ON, 2:OFF
+  @return Whether to successfully set the air plane mode
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_set_air_plane_mode(int sim_id, QL_DM_AIR_PLANE_MODE_TYPE_E air_plane_mode);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register air plane mode event.
+  @param[in] sim_id Sim id number
+  @param[in] cb_func Air plane mode indication callback function
+  @return Whether the air plane mode event was successfully registered.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_set_air_plane_mode_ind_cb(int sim_id, ql_ms_dm_air_plane_mode_ind_cb cb_func);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get cpu occupancy. 
+  @param[out] cpu_occupancy The percentage of cpu occupancy
+  @return Whether to successfully get the cpu occupancy
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_get_cpu_occupancy(float *cpu_occupancy);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get mem usage. 
+  @param[out] mem_use The percentage of mem usage
+  @return Whether to successfully get the memory usage
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_get_mem_usage(float *mem_use);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get NV item value. 
+  @param[in] sim id number
+  @param[in] nv_item_name The NV item name that is either NV item id or NV item path
+  @param[out] nv_item_value The nv value buf of nv_item_name
+  param[in] nv_item_value_len The length of nv_item_value
+  param[out] nv_len The real length of nv_item_name
+  @return Whether to successfully get the NV value
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_get_nv_item_value(char *nv_item_name, unsigned char *nv_item_value, int nv_item_value_len,  int *nv_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set NV item value. 
+  @param[in] sim id number
+  @param[in] nv_item_name The NV item name that is either NV item id or NV item path
+  @param[in] nv_item_value The NV value of nv_item_name
+  @param[in] nv_item_value_len The length of nv_item_value
+  param[out] nv_len The real length of nv_item_name
+  @return Whether to successfully set the NV value
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_set_nv_item_value(char *nv_item_name, unsigned char *nv_item_value, int nv_item_value_len, int *nv_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set radio on, its function is the same as at+cfun=1. 
+  @param[in] sim id number
+  @return Whether to successfully set the radio on
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_set_radio_on(int sim_id);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set radio off, its function is the same as at+cfun=0. 
+  @param[in] sim id number
+  @return Whether to successfully set the radio off
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_set_radio_off(int sim_id);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get modem CPU utilization. 
+  @param[out] mem_use The percentage of modem utilization
+  @return Whether to successfully get the modem utilization
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_get_modem_cpu_occupancy(float *cpu_occupancy);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get modem mem utilization. 
+  @param[out] mem_use The percentage of modem utilization
+  @return Whether to successfully get the modem utilization
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_get_modem_mem_usage(float *mem_use);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get QOOS enable state 
+  @param[in] sim id number
+  @param[out] enable The enable state of QOOS
+  @return Whether to successfully get the QOOS enable state
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_get_qoos_enable(int sim_id, QL_DM_QOOS_ENABLE_TYPE_E *enable);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set QOOS enable state 
+  @param[in] sim id number
+  @param[in] enable The enable state of QOOS
+  @return Whether to successfully set the QOOS enable state
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_set_qoos_enable(int sim_id, QL_DM_QOOS_ENABLE_TYPE_E enable);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get QOOS configuration 
+  @param[in] sim id number
+  @param[out] config The configuration of QOOS
+  @return Whether to successfully get the QOOS configuration
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_get_qoos_config(int sim_id, ql_dm_qoos_config_t *config);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set QOOS configuration 
+  @param[in] sim id number
+  @param[in] config The configuration of QOOS
+  @return Whether to successfully set the QOOS configuration
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_set_qoos_config(int sim_id, char enable ,int p1, int p2, int p3);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get MSSR(Modem SubSysem Reset) level. 
+  @param[out] p_level The MSSR level
+  @return Whether to successfully get the MSSR level
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_get_mssr_level(int *p_level);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set MSSR(Modem SubSysem Reset) level. 
+  @param[in] level The MSSR level
+  @return Whether to successfully set the MSSR level
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_dm_set_mssr_level(int level);
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @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_ms_dm_set_service_error_cb(ql_dm_service_error_cb_f cb);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_ms_nw.c b/mbtk/libql_lib_v2_rilv2/ql_ms_nw.c
new file mode 100755
index 0000000..4ff5463
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_ms_nw.c
@@ -0,0 +1,459 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_ms_nw.h 
+  @brief network registration service API, support Dual Sim Dual Active(DSDA).
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  Copyright (c) 2021 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
+  --------   ---          ----------------------------------------------------------
+  20200518   rambo.shan   Add WEA and ETWS alert indication.
+  20191225   stan.li      Modify function description.
+  20191202   stan.li      change the name of ql_nw_pref_nwmode_roming_info_t
+  20190528   stan.li      Created .
+-------------------------------------------------------------------------------------------------*/
+
+#ifndef __QL_MS_NW_H__
+#define __QL_MS_NW_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ql_type.h"
+#include "ql_nw.h"
+
+typedef void (*ql_ms_nw_voice_reg_ind_cb)(int sim_id, ql_nw_reg_status_info_t *p_info);
+
+typedef void (*ql_ms_nw_data_reg_ind_cb)(int sim_id, ql_nw_reg_status_info_t *p_info);
+
+typedef void (*ql_ms_nw_signal_strength_ind_cb)(int sim_id, ql_nw_signal_strength_info_t *p_info, QL_NW_SIGNAL_STRENGTH_LEVEL_E level);
+
+typedef void (*ql_ms_nw_cell_access_status_ind_cb)(int sim_id, QL_NW_CELL_ACCESS_STATE_TYPE_E status);
+
+typedef void (*ql_ms_nw_nitz_time_update_ind_cb)(int sim_id, ql_nw_nitz_time_info_t *p_info);
+
+typedef void (*ql_ms_nw_network_scan_async_cb)(int sim_id, int async_index, ql_nw_scan_result_list_info_t *p_info);
+
+typedef void (*ql_ms_nw_wea_reg_ind_cb)(int sim_id, ql_nw_wea_alert_info_t *p_info);
+
+typedef void (*ql_ms_nw_etws_reg_ind_cb)(int sim_id, ql_nw_etws_alert_info_t *p_info);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Initialize NW service.
+  @note You must call this function before other functions can be used in this module.
+  @return Whether the NW service was successfully intialized.
+  @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_ms_nw_init(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief  Deinitializes NW service.
+  @return Whether the NW service was deinitialized successfully.
+  @retval QL_ERR_OK successful.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_deinit(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief scan network status.
+  @param[in] sim id number
+  @param[out] async_index The index of request msg
+  @param[in] async_cb The callback function of request msg
+  @return Whether to successfully trigger the network scan operation
+  @retval QL_ERR_OK  successful
+  @retval QL_ERR_NOT_INIT  uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY  service is not ready
+  @retval QL_ERR_INVALID_ARG  Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_network_scan(int sim_id, int *async_index, ql_ms_nw_network_scan_async_cb async_cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set power mode.
+  @param[in] sim id number
+  @param[in] lower_mode, defined by QL_NW_LOWER_POWER_MASK_XXX
+  @return Whether to successfully set the power mode
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_set_power_mode(int sim_id, uint8_t lower_mode);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set perferred NW mode and roaming indicator.
+  @param[in] sim id number
+  @param[in] p_info Pointer that point to ql_nw_pref_nwmode_roaming_info_t
+  @return Whether to successfully set nwmode and roaming
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_set_pref_nwmode_roaming(int sim_id, ql_nw_pref_nwmode_roaming_info_t *p_info);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get perferred NW mode and roaming indicator.
+  @param[in] sim id number
+  @param[out] p_info Pointer that point to ql_nw_pref_nwmode_roaming_info_t 
+  @return Whether to successfully get nwmode and roaming
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_get_pref_nwmode_roaming(int sim_id, ql_nw_pref_nwmode_roaming_info_t *p_info);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get mobile operator name.
+  @param[in] sim id number
+  @param[out] p_info Pointer that point to ql_nw_mobile_operator_name_info_t
+  @return Whether to successfully get the mobile operator name
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_get_mobile_operator_name(int sim_id, ql_nw_mobile_operator_name_info_t *p_info);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get cell information.
+  @param[in] sim id number
+  @param[out] p_info Pointer that point to ql_nw_cell_info_t
+  @return Whether to successfully get the cell information
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_get_cell_info(int sim_id, ql_nw_cell_info_t *p_info);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get voice registration status.
+  @param[in] sim id number
+  @param[out] p_info Pointer that point to ql_nw_reg_status_info_t
+  @return Whether to successfully get the voice registration status
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_get_voice_reg_status(int sim_id, ql_nw_reg_status_info_t *p_info);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get data registration status.
+  @param[in] sim id number
+  @param[out] p_info Pointer that point to ql_nw_reg_status_info_t
+  @return Whether to successfully get the data registration status
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_get_data_reg_status(int sim_id, ql_nw_reg_status_info_t *p_info);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get current signal strength.
+  @param[in] sim id number
+  @param[out] p_info Pointer that point to ql_nw_signal_strength_info_t
+  @param[out] p_level: signal strength level
+  @return Whether to successfully get the signal strength
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_get_signal_strength(int sim_id, ql_nw_signal_strength_info_t *p_info, QL_NW_SIGNAL_STRENGTH_LEVEL_E* p_level);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get current cell acccess status.
+  @param[in] sim id number
+  @param[out] p_info Pointer that point to QL_NW_CELL_ACCESS_STATE_TYPE_E
+  @return Whether to successfully get the cell access status
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_get_cell_access_status(int sim_id, QL_NW_CELL_ACCESS_STATE_TYPE_E *p_info);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get network time.
+  @param[in] sim id number
+  @param[out] p_info Pointer that point to ql_nw_nitz_time_info_t 
+  @return Whether to successfully get the network time
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_get_nitz_time_info(int sim_id, ql_nw_nitz_time_info_t *p_info);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register voice registration event.
+  @param[in] sim id number
+  @param[in] cb_func Voice registration indication callback function
+  @return Whether the voice registration event was successfully registered.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+ */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_set_voice_reg_ind_cb(int sim_id, ql_ms_nw_voice_reg_ind_cb cb_func);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register data registration event.
+  @param[in] sim id number
+  @param[in] cb_func Data registration indication callback function
+  @return Whether the data registration event was successfully registered.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_set_data_reg_ind_cb(int sim_id, ql_ms_nw_data_reg_ind_cb cb_func);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register signal strength event.
+  @param[in] sim id number
+  @param[in] cb_func Signal strength indication callback function
+  @return Whether the signal strength event was successfully registered
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_set_signal_strength_ind_cb(int sim_id, ql_ms_nw_signal_strength_ind_cb cb_func);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register cell access status event.
+  @param[in] sim id number
+  @param[in] cb_func Cell access status indication callback function
+  @return Whether the cell access status event was successfully registered
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_set_cell_access_status_ind_cb(int sim_id, ql_ms_nw_cell_access_status_ind_cb cb_func);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register network time event.
+  @param[in] sim id number
+  @param[in] cb_func nitz time update indication callback function
+  @return Whether the network time event was successfully registered
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_set_nitz_time_update_ind_cb(int sim_id, ql_ms_nw_nitz_time_update_ind_cb cb_func);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register wea alert event.
+  @param[in] sim id number
+  @param[in] cb_func wea alert indication callback function
+  @return Whether the network time event was successfully registered
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_set_wea_alert_ind_cb(int sim_id, ql_ms_nw_wea_reg_ind_cb cb_func);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register etws alert event.
+  @param[in] sim id number
+  @param[in] cb_func etws alert indication callback function
+  @return Whether the network time event was successfully registered
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_set_etws_alert_ind_cb(int sim_id, ql_ms_nw_etws_reg_ind_cb cb_func);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set wea alert config.
+  @param[in] sim id number
+  @param[in] item Items to set.
+  @param[in] p_info Pointer that point to ql_nw_wea_config_t.
+  @return Whether to successfully set the wea config.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_set_wea_config(int sim_id, int item, ql_nw_wea_config_t *p_info);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief  Gets wea config.
+  @param[in] sim id number
+  @param[out] p_config wea config.
+  @return Whether the wea 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_ms_nw_get_wea_config(int sim_id, ql_nw_wea_config_t *p_config);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set etws alert config.
+  @param[in] sim id number
+  @param[in] etws config.
+  @return Whether to successfully set the etws config.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_set_etws_config(int sim_id, uint8_t enable_etws);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get etws alert config.
+  @param[in] sim id number
+  @param[out] p_enable_etws Pointer.
+  @return Whether to successfully set the etws config.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_get_etws_config(int sim_id, uint8_t* p_enable_etws);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get high capability subscription.
+  @param[in] sim id number
+  @param[out] p_high_cap pointer that point to QL_NW_BIND_SUB_TYPE_E
+  @return Whether the high capability subscription was successfully obtained.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_get_high_cap_sub(QL_NW_BIND_SUB_TYPE_E *p_high_cap);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set the SIM card index that can uniquely register to the 5G network. 
+  the main difference between high and non-high capability subscription is that high capability 
+  subscription can register to 5G network while non-high capability subscription can only 
+  register to LTE or GSM.
+  @param[in] sim id number
+  @param[in] high_cap high capability subscription 
+  @return Whether to successfully set the high capability subscription.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_set_high_cap_sub(QL_NW_BIND_SUB_TYPE_E high_cap);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @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] sim id number
+  @param[in] cb  Callback function 
+  @return
+  QL_ERR_OK - successful
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_ms_nw_set_service_error_cb(ql_nw_service_error_cb_f cb);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_ms_sim.c b/mbtk/libql_lib_v2_rilv2/ql_ms_sim.c
new file mode 100755
index 0000000..01dc771
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_ms_sim.c
@@ -0,0 +1,369 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_ms_sim.h 
+  @brief subscriber identity module service API, support Dual Sim Dual Active(DSDA). 
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  Copyright (c) 2021 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
+  --------   ---          ----------------------------------------------------------
+  20200720   solomon.cui  Created .
+-------------------------------------------------------------------------------------------------*/
+#ifndef __QL_MS_SIM_H__
+#define __QL_MS_SIM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ql_type.h"
+#include "ql_sim.h"
+
+typedef void (*ql_ms_sim_card_status_cb_f)(int sim_id, ql_sim_card_info_t *p_info);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Initializes SIM service.
+  @note You must call this function before other functions can be used in this module.
+  @return Whether the SIM service was intialized 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_ms_sim_init(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Deinitializes SIM service.
+  @return Whether the SIM service was deintialized 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_ms_sim_deinit(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Gets the IMSI (for 3GPP) or IMSI_M (for 3GPP2) from the SIM in ASCII form.
+  @param [in] sim_id sim_id to be used.
+  @param [in] app_type Application type.
+  @param [out] imsi Buffer to fill IMSI data.
+  @param [in] imsi_len Buffer length.
+  @return Whether the IMSI was successfully obtained.
+  @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_ms_sim_get_imsi(int sim_id, QL_SIM_APP_TYPE_E app_type, char *imsi, int imsi_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Retrieves the Integrated Circuit Card ID (ICCID) stored on the card.
+  @param [in] sim_id sim_id to be used.
+  @param [out] iccid Buffer to fill ICCID data.
+  @param [in] iccid_len Buffer length.
+  @return Whether the ICCID was successfully obtained.
+  @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_ms_sim_get_iccid(int sim_id, char *iccid, int iccid_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Retrieves the device phone number stored on the card.
+  @param [in] sim_id sim_id to be used.
+  @param [in] app_type Application type.
+  @param [out] phone_num Buffer to fill phone number.
+  @param [in] phone_num_len Buffer length.
+  @return Whether the phone number was successfully retrieved.
+  @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_ms_sim_get_phone_num(int sim_id, QL_SIM_APP_TYPE_E app_type, 
+                          char *phone_num, int phone_num_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Retrieves the preferred operators stored on the card.
+  @param [in] sim_id sim_id to be used.
+  @param [in] list Buffer to hold operators
+  @note This function is only supported by 3GPP applications.
+  @return Whether the preferred operators were successfully retrieved.
+  @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_ms_sim_get_operators(int sim_id, ql_sim_operator_list_t *list);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Enables the PIN on an application.
+  @param [in] sim_id sim_id to be used.
+  @param [in] app_type Application type.
+  @param [in] pin PIN to be used.
+  @param [in] pin_value PIN value. NULL terminated.
+  @return Whether the PIN was successfully enabled.
+  @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_ms_sim_enable_pin(int sim_id, QL_SIM_APP_TYPE_E app_type, 
+                             QL_SIM_PIN_E pin, const char *pin_value);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Disables the PIN on an application.
+  @param [in] sim_id sim_id to be used.
+  @param [in] app_type Application type.
+  @param [in] pin PIN to be used.
+  @param [in] pin_value PIN value. NULL terminated.
+  @return Whether the PIN was successfully disabled.
+  @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_ms_sim_disable_pin(int sim_id, QL_SIM_APP_TYPE_E app_type, 
+                             QL_SIM_PIN_E pin, const char *pin_value);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Verifies the PIN value of an application.
+  @param [in] sim_id sim_id to be used.
+  @param [in] app_type Application type.
+  @param [in] pin PIN to be used.
+  @param [in] pin_value PIN value. NULL terminated.
+  @note PIN must be enabled before calling this function.
+  @return Whether the PIN was successfully verified.
+  @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_ms_sim_verify_pin(int sim_id, QL_SIM_APP_TYPE_E app_type, 
+                             QL_SIM_PIN_E pin, const char *pin_value);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Changes the PIN value of an application.
+  @param [in] sim_id sim_id to be used.
+  @param [in] app_type Application type.
+  @param [in] pin PIN to be used.
+  @param [in] old_pin_value Old PIN value. NULL terminated.
+  @param [in] new_pin_value New PIN value. NULL terminated.
+  @return Whether the PIN was successfully changed.
+  @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_ms_sim_change_pin(int sim_id, QL_SIM_APP_TYPE_E app_type, 
+                             QL_SIM_PIN_E pin, const char *old_pin_value, const char *new_pin_value);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Unblocks a blocked PIN using the PUK code.
+  @param [in] sim_id sim_id to be used.
+  @param [in] app_type Application type.
+  @param [in] pin PIN to be used.
+  @param [in] puk_value PUK value.  NULL terminated.
+  @param [in] pin_value New PIN value.  NULL terminated.
+  @note The user must pass PUK1 to unblock PIN1 or PUK2 to unblock PIN2.
+  @return Whether the PIN was successfully unblocked.
+  @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_ms_sim_unblock_pin(int sim_id, QL_SIM_APP_TYPE_E app_type, 
+                             QL_SIM_PIN_E pin, const char *puk_value, const char *pin_value);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Retrieves the card info stored on a card.
+  @param [in] sim_id sim_id to be used.
+  @param [out] p_info Pointer of ql_ms_sim_card_info_t.
+  @return Whether the card info was successfully retrieved.
+  @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_ms_sim_get_card_info(int sim_id, ql_sim_card_info_t *p_info);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Reads data from a specific file on a specified application on the card.
+  @param [in] sim_id sim_id to be used.
+  @param [in] app_type Application type.
+  @param [inout] p_file Pointer of ql_ms_sim_file_t.
+  @return Whether the file was successfully read.
+  @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_ms_sim_read_file(int sim_id, QL_SIM_APP_TYPE_E app_type, ql_sim_file_t *p_file);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Writes data to a specific file on a specified application on the card. 
+  @param [in] sim_id sim_id to be used.
+  @param [in] app_type Application type.
+  @param [in] p_file Pointer of ql_ms_sim_file_t
+  @note The type of file is determined by the record number field,
+    which indicates a transparent file when zero and a record-based file otherwise.
+  @return Whether the file was successfully written.
+  @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_ms_sim_write_file(int sim_id, QL_SIM_APP_TYPE_E app_type, ql_sim_file_t *p_file);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Retrieves the info of a specific file on a specified application on the card.
+  @param [in] sim_id sim_id to be used.
+  @param [in] app_type Application type.
+  @param [inout] p_info Pointer of ql_ms_sim_file_info_t.
+  @return Whether the file info was successfully retrieved.
+  @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_ms_sim_get_file_info(int sim_id, QL_SIM_APP_TYPE_E app_type, 
+                                 ql_sim_file_info_t *p_info);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Reads phone book on a specified application on the card.
+  @param [in] sim_id sim_id to be used.
+  @param [in] app_type Spplication type.
+  @param [in] pb_path Phone book path. NULL terminated.
+  @param [in] record_idx Record index to read. Starts from 1.
+  @param [out] p_record Pointer of ql_ms_sim_phone_book_record_t.
+  @return Whether the phone book record was successfully retrieved.
+  @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_ms_sim_read_phone_book(int sim_id, QL_SIM_APP_TYPE_E app_type,
+                                    const char *pb_path, uint8_t record_idx,
+                                    ql_sim_phone_book_record_t *p_record);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Writes phone book on a specified application on the card.
+  @param [in] sim_id sim_id to be used.
+  @param [in] app_type Application type.
+  @param [in] pb_path Phone book path. NULL terminated.
+  @param [in] record_idx Record index to write. Starts from 1.
+  @param [in] p_record Pointer of ql_ms_sim_phone_book_record_t.
+  @note If p_record->name[0] = 0 and p_record->number[0] = 0, record will be deleted.
+  @return Whether the phone book record was successfully saved.
+  @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_ms_sim_write_phone_book(int sim_id, QL_SIM_APP_TYPE_E app_type, 
+                                    const char *pb_path, uint8_t record_idx,
+                                    ql_sim_phone_book_record_t *p_record);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Opens a logical channel on a UICC card.
+  @param [in] sim_id sim_id to be used.
+  @param [out] channel_id Channel opened.
+  @return Whether the logical channel was successfully opened.
+  @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_ms_sim_open_logical_channel(int sim_id, uint8_t *channel_id);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Closes a logical channel on a UICC card.
+  @param [in] sim_id sim_id to be used.
+  @param [in] channel_id Channel to be closed.
+  @return Whether the logical channel was successfully closed.
+  @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_ms_sim_close_logical_channel(int sim_id, uint8_t channel_id);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Sends an APDU to the card.
+  @param [in] sim_id sim_id to be used.
+  @param [in] channel_id Channel to be used.
+  @param [inout] p_apdu Pointer of ql_ms_sim_apdu_t.
+  @note You must call ql_ms_sim_open_logical_channel before sending an APDU.
+  @return Whether the APDU was successfully sent.
+  @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_ms_sim_send_apdu(int sim_id, uint8_t channel_id, ql_sim_apdu_t *p_apdu);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief  Sets SIM card status callback handler
+  @param [in] sim_id sim_id to be used.
+  @param[in] cb call back handler.
+  @return Whether the card status callback handler was successfully set.
+  @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_ms_sim_set_card_status_cb(int sim_id, ql_ms_sim_card_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_ms_sim_set_service_error_cb(ql_sim_service_error_cb_f cb);
+
+int ql_ms_sim_switch_slot(int sim_id, QL_SIM_PHY_SLOT_E phy_slot);
+int ql_ms_sim_get_active_slots(int sim_id, ql_sim_active_slots_t *p_active_slots);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_ms_sms.c b/mbtk/libql_lib_v2_rilv2/ql_ms_sms.c
new file mode 100755
index 0000000..c4f90c4
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_ms_sms.c
@@ -0,0 +1,206 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_ms_sms.h 
+  @brief short message service API, support Dual Sim Dual Active(DSDA). 
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  Copyright (c) 2021 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
+  --------   ---          ----------------------------------------------------------
+  2021069   Stan.li       Created.
+-------------------------------------------------------------------------------------------------*/
+#ifndef __QL_MS_SMS_H__
+#define __QL_MS_SMS_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ql_type.h"
+#include "ql_sms.h"
+
+
+typedef void (*ql_ms_sms_msg_async_cb_f)(int sim_id, int id, int result);
+typedef void (*ql_ms_sms_msg_recv_cb_f)(int sim_id, ql_sms_msg_t *p_msg, ql_sms_timestamp_t *timestamp,
+                                             ql_sms_user_data_head_t *head);
+typedef void (*ql_ms_sms_pdu_async_cb_f)(int sim_id, int id, int result);
+typedef void (*ql_ms_sms_pdu_recv_cb_f)(int sim_id, ql_sms_pdu_t *p_pdu);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief  Initializes SMS service.
+  @return Whether the SMS service was initialized successfully.
+  @retval QL_ERR_OK successful.
+  @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_ms_sms_init(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief  Deinitializes SMS service.
+  @return Whether the SMS service was deinitialized successfully.
+  @retval QL_ERR_OK successful.
+  @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_ms_sms_deinit(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief  Sets the service center address.
+  @param[in] sim id number
+  @param[in] addr service center address.
+  @param[in] len  service center address length.
+  @return Whether the service center address was set 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_ms_sms_set_service_center_addr(int sim_id, char *addr, int len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief  Gets the service center address.
+  @param[in] sim id number
+  @param[out] addr service center address.
+  @param[in] len  service center address length.
+  @return Whether the service center address 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_ms_sms_get_service_center_addr(int sim_id, char *addr, int len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief  Sends message synchronously.
+  @param[in] sim id number
+  @param[in] p_msg pointer to ql_ms_sms_msg_t.
+  @return Whether the message was successfully sent synchronously.
+  @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_ms_sms_send_msg(int sim_id, ql_sms_msg_t *p_msg);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief  Sends message asynchronously.
+  @param[in] sim id number
+  @param[in] p_msg  pointer to ql_ms_sms_msg_t
+  @param[out] id    id for this async operation
+  @param[in] cb     async callback
+  @return Whether the message was successfully sent asynchronously.
+  @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_ms_sms_send_msg_async(int sim_id, ql_sms_msg_t *p_msg, int *id, ql_ms_sms_msg_async_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief  Sets SMS message reception callback hanlder.
+  @param[in] sim id number
+  @param[in] cb message reception callback handler.
+  @return Whether the message reception callback hanlder was set 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_ms_sms_set_msg_recv_cb(int sim_id, ql_ms_sms_msg_recv_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief  Sends PDU synchronously.
+  @param[in] sim id number
+  @param[in] p_pdu SMS PDU.
+  @return Whether the PDU was successfully sent synchronously.
+  @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_ms_sms_send_pdu(int sim_id, ql_sms_pdu_t *p_pdu);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief  Sends PDU asynchronously.
+  @param[in] sim id number
+  @param[in] p_pdu sms pdu.
+  @param[out] id id for this async operation.
+  @param[in] cb async callback.
+  @return Whether the PDU was successfully sent asynchronously.
+  @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_ms_sms_send_pdu_async(int sim_id, ql_sms_pdu_t *p_pdu, int *id, ql_ms_sms_pdu_async_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief  Sets SMS PDU reception callback hanlder.
+  @param[in] sim id number
+  @param[in] cb PDU reception callback handler.
+  @return Whether the PDU reception callback hanlder was set 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_ms_sms_set_pdu_recv_cb(int sim_id, ql_ms_sms_pdu_recv_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_ms_sms_set_service_error_cb(ql_sms_service_error_cb_f cb);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_ms_voice.c b/mbtk/libql_lib_v2_rilv2/ql_ms_voice.c
new file mode 100755
index 0000000..54707e5
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_ms_voice.c
@@ -0,0 +1,428 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_ms_voice.h 
+  @brief Voice service DSDA 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   Created, Added Voice DSDA API.
+-------------------------------------------------------------------------------------------------*/
+
+#ifndef __QL_MS_VOICE_H__
+#define __QL_MS_VOICE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include "ql_voice.h"
+
+typedef void (*ql_ms_voice_ecall_status_cb_f)(int sim_id, uint32_t id, 
+                                                   QL_VOICE_ECALL_MSD_TRANS_STATUS_E status);
+
+typedef void (*ql_ms_voice_ecall_event_cb_f)(int sim_id, ql_voice_ecall_event_t *p_event);
+
+typedef void (*ql_ms_voice_call_cb_f)(int sim_id, ql_voice_record_array_t *p_arr);
+
+/** voice dtmf event callback */
+typedef void (*ql_ms_voice_dtmf_cb_f)(int sim_id, uint32_t id, QL_VOICE_DTMF_EVENT_E event, 
+                                        char *digits, int len); /**< len: length of digits */
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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_ms_voice_init(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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_ms_voice_deinit(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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_ms_voice_dial(int sim_id, char *num, int len, uint32_t *id);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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_ms_voice_cancel_dial(int sim_id, 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_ms_voice_hangup_all(int sim_id);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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_ms_voice_answer(int sim_id, uint32_t id);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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_ms_voice_hangup(int sim_id, 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_ms_voice_hold(int sim_id, 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_ms_voice_unhold(int sim_id, 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_ms_voice_get_records(int sim_id, ql_voice_record_array_t *p_arr);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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_ms_voice_forwarding(int sim_id, 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_ms_voice_get_forwarding_status(int sim_id, 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_ms_voice_waiting(int sim_id, 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_ms_voice_get_waiting_status(int sim_id, 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_ms_voice_autoanswer(int sim_id, 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_ms_voice_send_dtmf_char(int sim_id, uint32_t id, char c);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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_ms_voice_set_call_cb(int sim_id, ql_ms_voice_call_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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_ms_voice_set_dtmf_cb(int sim_id, ql_ms_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_ms_voice_ecall_dial(int sim_id, 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_ms_voice_ecall_hangup(int sim_id);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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_ms_voice_ecall_update_msd(int sim_id, 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_ms_voice_ecall_push_msd(int sim_id, 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_ms_voice_ecall_get_config(int sim_id, 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_ms_voice_ecall_set_config(int sim_id, 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_ms_voice_ecall_set_event_cb(int sim_id, ql_ms_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_ms_voice_ecall_set_status_cb(int sim_id, ql_ms_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_ms_voice_set_service_error_cb(ql_voice_service_error_cb_f cb);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __QL_VOICE_H__ */
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_net_usb_dev.c b/mbtk/libql_lib_v2_rilv2/ql_net_usb_dev.c
new file mode 100755
index 0000000..427c88b
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_net_usb_dev.c
@@ -0,0 +1,190 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_net_usb_dev.h 
+  @brief USB net device API 
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  Copyright (c) 2018 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
+  --------   ---          ----------------------------------------------------------
+  20190709   tyler.kuang  Created .
+-------------------------------------------------------------------------------------------------*/
+
+#ifndef __QL_NET_USB_DEV_H__
+#define __QL_NET_USB_DEV_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "ql_net_common.h"
+
+
+typedef void (*ql_net_usb_dev_ind_cb_f)(const char *device,
+        QL_NET_USB_DEV_STATUS_E pre_status,
+        ql_net_usb_dev_t *p_dev);
+
+typedef void (*ql_net_usb_dev_service_error_cb_f)(int error);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Initialize the USB net device service
+  @return 
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_net_usb_dev_init(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Get USB network device status
+  @param[in] device Device name, such as ecm0, rndis0..
+  @param[out] p_dev Return device status information
+  @return 
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  QL_ERR_INTERFACE_NOT_FOUND - device does not exist
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_net_usb_dev_get_status(const char *device, ql_net_usb_dev_t *p_dev);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Get all USB network device list
+  @param[out] list USB network device array
+  @param[in,out] list_len, in-> array size, out->current instance number
+  @return 
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_net_usb_dev_get_list(ql_net_usb_dev_t *list, int *list_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Set USB network device MTU. If it does not currently exist, then set it after the device 
+  appears.
+  @param[in] device Device name, such as ecm0, rndis0..
+  @param[in] mtu MTU 
+  @return 
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_net_usb_dev_set_mtu(const char *device, int mtu);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Get USB network device MTU
+  @param[in] device Device name, such as ecm0, rndis0..
+  @param[out] p_mtu Reutn device MTU
+  @return 
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  QL_ERR_INTERFACE_NOT_FOUND - device does not exist
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_net_usb_dev_get_mtu(const char *device, int *p_mtu);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Set USB network device MAC address. If it does not currently exist, then set it after the device 
+  appears.
+  @param[in] device Device name, such as ecm0, rndis0..
+  @param[in] macaddr MAC address, format: XX:XX:XX:XX:XX:XX 
+  @return 
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  QL_ERR_INTERFACE_NOT_FOUND - device does not exist
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_net_usb_dev_set_macaddr(const char *device, const char *macaddr);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Get USB network device MAC address
+  @param[in] device Device name, such as ecm0, rndis0..
+  @param[out] macaddr_buf Return MAC address
+  @param[in] buf_len Buffer size
+  @return 
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  QL_ERR_INTERFACE_NOT_FOUND - device does not exist
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_net_usb_dev_get_macaddr(const char *device, char *macaddr_buf, int buf_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Register USB network device status change event
+  @param[in] cb 
+  @return 
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_net_usb_dev_set_ind_cb(ql_net_usb_dev_ind_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_net_usb_dev_set_service_error_cb(ql_net_usb_dev_service_error_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Deinitialize the USB net device service
+  @return 
+  QL_ERR_OK - successful
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_net_usb_dev_deinit(void);
+
+#ifdef __cplusplus
+} 
+#endif
+
+#endif
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_nf.c b/mbtk/libql_lib_v2_rilv2/ql_nf.c
new file mode 100755
index 0000000..d07a524
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_nf.c
@@ -0,0 +1,135 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_nf.h 
+  @brief Network framework API 
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  Copyright (c) 2018 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
+  --------   ---          ----------------------------------------------------------
+  20181024   tyler.kuang  Created .
+-------------------------------------------------------------------------------------------------*/
+
+#ifndef __QL_NF_H__
+#define __QL_NF_H__
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "ql_net_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    char name[QL_NET_MAX_NAME_LEN];
+    char ifname[QL_NET_MAX_NAME_LEN];
+    char pre_status[16];
+    char status[16];
+    uint8_t has_addr;
+    ql_net_addr_t addr;
+    uint8_t has_addr6;
+    ql_net_addr6_t addr6;
+} ql_nf_interface_status_t;
+
+typedef void (*ql_nf_interface_status_ind_cb_f)(ql_nf_interface_status_t *p_msg);
+
+typedef void (*ql_nf_service_error_cb_f)(int error);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Initialize network service
+  @return 
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nf_init(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Send a command and wait for a response
+  @param[in] cmd Command
+  @param[out] resp_buf Response 
+  @param[in] resp_len Response buffer length 
+  @return 
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nf_cmd(const char *cmd, char *resp_buf, int resp_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Send a command and wait for a response
+  @param[in] cmd Command
+  @param[out] resp_buf Response 
+  @param[in] resp_len Response buffer length 
+  @return 
+  QL_ERR_OK - successful
+  QL_ERR_INVALID_ARG - as defined
+  QL_ERR_UNKNOWN - unknown error, failed to connect to service
+  QL_ERR_SERVICE_NOT_READY - service is not ready, need to retry
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nf_cmd_json(const char *cmd, char *resp_buf, int resp_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Register NF interface status change event event
+  @param[in] cb 
+  @return 
+  QL_ERR_OK - successful
+  QL_ERR_NOT_INIT - uninitialized
+  QL_ERR_SERVICE_NOT_READY - service is not ready
+  QL_ERR_INVALID_ARG - Invalid arguments
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nf_set_interface_status_ind_cb(ql_nf_interface_status_ind_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_nf_set_service_error_cb(ql_nf_service_error_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Deinitialize the data call service
+  @return 
+  QL_ERR_OK - successful
+  Other - error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nf_deinit(void);
+
+#ifdef __cplusplus
+} 
+#endif
+
+#endif
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_nslookup.c b/mbtk/libql_lib_v2_rilv2/ql_nslookup.c
new file mode 100755
index 0000000..9874c04
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_nslookup.c
@@ -0,0 +1,30 @@
+/**
+ *@file     quectel_nslookup.h
+ *@date     2017-07-05
+ *@author   running.qian
+ *@brief    Simple DNS Reslove
+ */
+#ifndef _QUECTEL_NSLOOKUP_H_
+#define _QUECTEL_NSLOOKUP_H_
+
+#include <arpa/inet.h>
+
+typedef enum  {
+    QUERY_IPV4_E,
+    QUERY_IPV6_E
+} QUERY_IP_TYPE;
+
+
+typedef struct {
+    int addr_cnt;//must be set 0 when call QL_nslookup 
+    struct in_addr addr[5];
+    
+    int addr6_cnt;//must be set 0 when call QL_nslookup
+    struct in6_addr addr6[5];
+} hostaddr_info_u;
+
+/**
+ * Perform a DNS query by sending a packet
+ */
+void ql_nslookup(char *host, char *dns_server_ip, QUERY_IP_TYPE ip_type, hostaddr_info_u *resolved_addr);
+#endif
diff --git a/mbtk/libql_lib_v2_rilv2/ql_nw.c b/mbtk/libql_lib_v2_rilv2/ql_nw.c
new file mode 100755
index 0000000..8249cbd
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_nw.c
@@ -0,0 +1,1538 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_nw.c 
+  @brief network registration API
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  Copyright (c) 2024 mobiletek Wireless Solution, Co., Ltd. All Rights Reserved.
+  mobiletek 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
+  --------   ---------    -----------------------------------------------------------------
+  20241022    yq.wang      Created .
+-------------------------------------------------------------------------------------------------*/
+#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 "ql_nw.h"
+#include "ql_type.h"
+#include "mbtk_type.h"
+#include "mbtk_ril_api.h"
+
+/*----------------------------------------------DEFINE-------------------------------------------*/
+#define QL_NW_LOGE LOGE
+#define QL_NW_LOGD LOGD
+
+#define MBTK_ERR_OK 0
+
+#define MBTK_BUFF_TEMP_SIZE_8 8
+
+#define QL_NW_MCC_LENGHT  3
+#define QL_NW_MNC_MAX     3
+#define QL_NW_MCC_MNC_MAX 6
+#define QL_NW_MCC_MNC_MIN 5
+
+#define MBTK_READ_EVENT_SIZE    1
+#define MBTK_WRITE_EVENT_SIZE   1
+
+/*----------------------------------------------DEFINE-------------------------------------------*/
+
+/*----------------------------------------------ENUM---------------------------------------------*/
+typedef enum {
+    QL_NW_REG_TYPE_VOICE = 0,
+    QL_NW_REG_TYPE_DATA,
+}ql_nw_reg_type_enum;
+
+typedef enum {
+    QL_NW_EVENT_THREAD_QUIT = 0,
+    QL_NW_EVENT_SIGNAL_CB,
+    QL_NW_EVENT_VOICE_CB,
+    QL_NW_EVENT_MAX = 255,
+}ql_nw_event_enum;
+
+/*----------------------------------------------ENUM---------------------------------------------*/
+
+/*----------------------------------------------STRUCT-------------------------------------------*/
+typedef struct {
+    mbtk_ril_handle*       handle;
+    int                       control[2];
+    pthread_t                 cb_thread_id;
+    ql_nw_signal_strength_ind_cb signal_cb;
+    ql_nw_voice_reg_ind_cb       voice_cb;
+    ql_nw_service_error_cb_f     server_cb;
+}ql_nw_info_handle_t;
+
+/*----------------------------------------------STRUCT-------------------------------------------*/
+
+/*----------------------------------------------GLOBAL STATIC VARIABLE---------------------------*/
+static ql_nw_info_handle_t* nw_handle = NULL;
+
+/*----------------------------------------------GLOBAL STATIC VARIABLE---------------------------*/
+
+/*----------------------------------------------NW FUNCTION--------------------------------------*/
+static int ql_get_cops_state(ql_nw_reg_status_info_t *p_info, ql_nw_info_handle_t *p_handle)
+{
+    int ret = 0;
+    char mcc_mnc[MBTK_BUFF_TEMP_SIZE_8] = {0};
+    mbtk_net_info_t net = {0};
+    memset(&net, 0x0, sizeof(mbtk_net_info_t));
+    ret = mbtk_net_sel_mode_get(p_handle->handle, &net);
+    if(ret != MBTK_ERR_OK)
+    {
+        QL_NW_LOGE("[%s] net sel mode get fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    switch(net.net_type)
+    {
+        case MBTK_RADIO_TECH_GSM:
+        case MBTK_RADIO_TECH_GSM_COMPACT:
+        {
+            p_info->radio_tech = QL_NW_RADIO_TECH_GSM;
+            break;
+        }
+        case MBTK_RADIO_TECH_GSM_EGPRS:
+        {
+            p_info->radio_tech = QL_NW_RADIO_TECH_GPRS;
+            break;
+        }
+        case MBTK_RADIO_TECH_UTRAN:
+        {
+            p_info->radio_tech = QL_NW_RADIO_TECH_UMTS;
+            break;
+        }
+        case MBTK_RADIO_TECH_UTRAN_HSDPA:
+        {
+            p_info->radio_tech = QL_NW_RADIO_TECH_HSDPA;
+            break;
+        }
+        case MBTK_RADIO_TECH_UTRAN_HSUPA:
+        {
+            p_info->radio_tech = QL_NW_RADIO_TECH_HSUPA;
+            break;
+        }
+        case MBTK_RADIO_TECH_UTRAN_HSDPA_HSUPA:
+        {
+            p_info->radio_tech = QL_NW_RADIO_TECH_HSPA;
+            break;
+        }
+        case MBTK_RADIO_TECH_UTRAN_HSPA:
+        {
+            p_info->radio_tech = QL_NW_RADIO_TECH_HSPAP;
+            break;
+        }
+        case MBTK_RADIO_TECH_E_UTRAN:
+        {
+            p_info->radio_tech = QL_NW_RADIO_TECH_LTE;
+            break;
+        }
+        default:
+        {
+            p_info->radio_tech = QL_NW_RADIO_TECH_NONE;
+            break;
+        }
+    }
+
+    memset(mcc_mnc, 0x0, MBTK_BUFF_TEMP_SIZE_8);
+    ret = snprintf(mcc_mnc, MBTK_BUFF_TEMP_SIZE_8, "%d", net.plmn);
+    if(ret != QL_NW_MCC_MNC_MIN &&  ret != QL_NW_MCC_MNC_MAX)
+    {
+        QL_NW_LOGE("[%s] mcc mnc get fail.[%d]", __func__, ret);
+    }
+    else
+    {
+        memcpy(p_info->mcc, mcc_mnc, QL_NW_MCC_LENGHT);
+        memcpy(p_info->mnc, mcc_mnc + QL_NW_MCC_LENGHT, ret - QL_NW_MCC_LENGHT);
+    }
+
+    return QL_ERR_OK;
+}
+
+static int ql_get_creg_state(ql_nw_reg_status_info_t *p_info, ql_nw_info_handle_t *p_handle, ql_nw_reg_type_enum reg_type)
+{
+    int ret = 0;
+    uint8 reg_state = 0;
+    mbtk_net_reg_info_t reg;
+    memset(&reg, 0x0, sizeof(mbtk_net_reg_info_t));
+    ret = mbtk_net_reg_get(p_handle->handle, &reg);
+    if(ret != MBTK_ERR_OK)
+    {
+        QL_NW_LOGE("[%s] net reg get fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    if(reg_type == QL_NW_REG_TYPE_VOICE)
+    {
+        if(reg.ims_state == 0)
+        {
+            reg_state = reg.call_state;
+        }
+        else
+        {
+            reg_state = reg.ims_state;
+        }
+    }
+    else
+    {
+        if(reg.type == MBTK_RADIO_TECH_E_UTRAN)
+        {
+            reg_state = reg.data_state;
+        }
+        else
+        {
+            reg_state = reg.call_state;
+        }
+    }
+
+    p_info->deny_reason = QL_NW_CS_DOMAIN_NOT_AVAILABLE_DENY_REASON;
+    switch(reg_state)
+    {
+        case MBTK_NET_REG_STATE_HOME:
+        {
+            p_info->reg_state = QL_NW_SERVICE_FULL;
+            p_info->roaming = QL_NW_ROAM_STATE_OFF;
+            break;
+        }
+        case MBTK_NET_REG_STATE_DENIED:
+        {
+            p_info->reg_state = QL_NW_SERVICE_NONE;
+            p_info->roaming = QL_NW_ROAM_STATE_OFF;
+            p_info->deny_reason = QL_NW_CS_DOMAIN_NOT_AVAILABLE_DENY_REASON; //now not support
+            break;
+        }
+        case MBTK_NET_REG_STATE_ROAMING:
+        {
+            p_info->reg_state = QL_NW_SERVICE_FULL;
+            p_info->roaming = QL_NW_ROAM_STATE_ON;
+            break;
+        }
+        case MBTK_NET_REG_STATE_SMS_ONLY:
+        case MBTK_NET_REG_STATE_CSFB_HOME:
+        case MBTK_NET_REG_STATE_EMERGENCY_ONLY:
+        {
+            p_info->reg_state = QL_NW_SERVICE_LIMITED;
+            p_info->roaming = QL_NW_ROAM_STATE_OFF;
+            break;
+        }
+        case MBTK_NET_REG_STATE_ROAMING_SMS:
+        case MBTK_NET_REG_STATE_CSFB_ROAMING:
+        {
+            p_info->reg_state = QL_NW_SERVICE_LIMITED;
+            p_info->roaming = QL_NW_ROAM_STATE_ON;
+            break;
+        }
+        case MBTK_NET_REG_STATE_NON:
+        case MBTK_NET_REG_STATE_SEARCHING:
+        case MBTK_NET_REG_STATE_UNKNOWN:
+        case MBTK_NET_REG_STATE_ATTACHED_EMERGENCY:
+        default:
+        {
+            p_info->reg_state = QL_NW_SERVICE_NONE;
+            p_info->roaming = QL_NW_ROAM_STATE_OFF;
+            break;
+        }
+    }
+
+    p_info->cid = reg.ci;
+    p_info->lac = reg.lac;
+
+    return QL_ERR_OK;
+}
+
+static int8_t rssi_convert_to_dBm(uint8 rssi)
+{
+    if(rssi <= 31)
+    {
+        return rssi * 2 - 113;
+    }
+    else
+    {
+        return -125;
+    }
+}
+
+static int16_t rsrp_convert_to_dBm(uint8 rsrp)
+{
+    if(rsrp <= 96)
+    {
+        return rsrp - 140;
+    }
+    else
+    {
+        return -44;
+    }
+}
+
+static int16_t rsrq_convert_to_dB(uint8 rsrq)
+{
+    if(rsrq >= 1 && rsrq <= 34)
+    {
+        return (rsrq + 1) / 2 - 20;
+    }
+    else
+    {
+        return  -20; 
+    }
+}
+
+static int16_t ecno_convert_to_dB(uint8 ecno)
+{
+    if(ecno >= 48)
+    {
+        return 0;
+    }
+    else if(ecno == 255)
+    {
+        return 255;
+    }
+    else
+    {
+        return 48 - ecno;
+    }
+}
+
+static QL_NW_SIGNAL_STRENGTH_LEVEL_E ql_rssi_convert_level(uint8 rssi)
+{
+    //rssi 0 - 31,99
+    if(rssi == 0 || rssi == 99)
+    {
+        return QL_NW_SIGNAL_STRENGTH_LEVEL_NONE;
+    }
+    else if(rssi >= 1 && rssi < 10)
+    {
+        return QL_NW_SIGNAL_STRENGTH_LEVEL_POOR;
+    }
+    else if(rssi >= 10 && rssi < 20)
+    {
+        return QL_NW_SIGNAL_STRENGTH_LEVEL_MODERATE;
+    }
+    else if(rssi >= 20 && rssi <= 30)
+    {
+        return QL_NW_SIGNAL_STRENGTH_LEVEL_GOOD;
+    }
+    else
+    {
+        return QL_NW_SIGNAL_STRENGTH_LEVEL_GREAT;
+    }
+}
+
+static void ql_signal_state_change_cb(const void* data, int data_len)
+{
+    if(data && data_len == 8)
+    {
+        uint8 *net_data = (uint8*)data;
+        mbtk_radio_technology_enum type = (mbtk_radio_technology_enum)net_data[0];
+        QL_NW_LOGD("[%s] reg_type[%d].", __func__, type);
+        ql_nw_event_enum cmd = QL_NW_EVENT_SIGNAL_CB;
+        if(nw_handle->control[0] >= 0)
+        {
+            int ret = write(nw_handle->control[0], &cmd, MBTK_WRITE_EVENT_SIZE);
+            if(ret != MBTK_WRITE_EVENT_SIZE)
+            {
+                QL_NW_LOGE("[%s] write fail.[%d]", __func__, ret);
+            }
+        }
+    }
+    else
+    {
+        QL_NW_LOGD("[%s] unknown data.", __func__);
+    }
+
+}
+
+static void ql_net_state_change_cb(const void* data, int data_len)
+{
+    if(data)
+    {
+        ql_nw_event_enum cmd = QL_NW_EVENT_VOICE_CB;
+        if(nw_handle->control[0] >= 0)
+        {
+            int ret = write(nw_handle->control[0], &cmd, MBTK_WRITE_EVENT_SIZE);
+            if(ret != MBTK_WRITE_EVENT_SIZE)
+            {
+                QL_NW_LOGE("[%s] write fail.[%d]", __func__, ret);
+            }
+        }
+    }
+    else
+    {
+        QL_NW_LOGD("[%s] unknown data.", __func__);
+    }
+}
+
+static void ql_nw_server_change_cb(const void* data, int data_len)
+{
+    if(data_len != sizeof(int))
+    {
+        QL_NW_LOGE("[%s] data_len[%d] than int[%d] fail. ", __func__, data_len, sizeof(int));
+    }
+    else
+    {
+        int server_state = *(int *)data;
+        if(server_state == 1 && nw_handle->server_cb)
+        {
+            nw_handle->server_cb(QL_ERR_ABORTED);
+        }
+    }
+}
+
+static int ql_epoll_register(int epoll_fd, int fd)
+{
+    struct epoll_event  ev;
+    int    ret, flags;
+
+    /* important: make the fd non-blocking */
+    flags = fcntl(fd, F_GETFL);
+    fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+
+    ev.events  = EPOLLIN;
+    ev.data.fd = fd;
+
+    do 
+    {
+        ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev);
+        if(ret < 0)
+        {
+            QL_NW_LOGE("[%s] epoll_ctl fail.[%s]", __func__, strerror(errno));
+        }
+    } while (ret < 0 && errno == EINTR);
+    
+    return QL_ERR_OK;
+}
+
+static void* ql_cb_thread(void* arg)
+{
+    ql_nw_info_handle_t* info = (ql_nw_info_handle_t*)arg;
+    
+    if(info->control[0] < 0 && info->control[0] < 0)
+    {
+        if(socketpair(AF_LOCAL, SOCK_STREAM, 0, info->control ) < 0)
+        {
+            QL_NW_LOGE("[%s] control creat fail.", __func__);
+            return NULL;
+        }
+    }
+    
+    int ne = 0;
+    int nevents = 0;
+    int ret = 0;
+    struct epoll_event events[3];
+    int control_fd = info->control[1];
+    ql_nw_event_enum cmd = QL_NW_EVENT_THREAD_QUIT;
+    
+    //A maximum of three events can be processed simultaneously
+    int epoll_fd = epoll_create(3);
+    ql_epoll_register(epoll_fd, control_fd);
+    
+    QL_NW_LOGE("[%s] thread start run.", __func__);
+    while(1)
+    {
+        nevents = epoll_wait(epoll_fd, events, 3, -1);
+        if(nevents < 0)
+        {
+            if(errno != EINTR)
+            {
+                QL_NW_LOGE("[%s] epoll_wait fail.[%s]", __func__, strerror(errno));
+            }
+            continue;
+        }
+
+        for (ne = 0; ne < nevents; ne++)
+        {
+            if((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0)
+            {
+                QL_NW_LOGE("[%s] EPOLLERR or EPOLLHUP event error.", __func__);
+                break;
+            }
+
+            if ((events[ne].events & EPOLLIN) != 0)
+            {
+                if (events[ne].data.fd == control_fd)
+                {
+                    ret = read(control_fd, &cmd, MBTK_READ_EVENT_SIZE);
+                    if(ret != MBTK_READ_EVENT_SIZE)
+                    {
+                        QL_NW_LOGE("[%s] read fail.[%d]", __func__, ret);
+                    }
+                    else
+                    {
+                        switch(cmd)
+                        {
+                            case QL_NW_EVENT_THREAD_QUIT:
+                            {
+                                close(epoll_fd);
+                                epoll_fd = -1;
+                                if(info->control[0] >= 0)
+                                {
+                                    close(info->control[0]);
+                                    info->control[0] = -1;
+                                }
+                                if(info->control[1] >= 0)
+                                {
+                                    close(info->control[1]);
+                                    info->control[1] = -1;
+                                }
+                                QL_NW_LOGD("[%s] thread quit.", __func__);
+                                return NULL;
+                            }
+                            case QL_NW_EVENT_SIGNAL_CB:
+                            {
+                                if(info->signal_cb)
+                                {
+                                    ql_nw_signal_strength_info_t signal_info = {0};
+                                    QL_NW_SIGNAL_STRENGTH_LEVEL_E level = QL_NW_SIGNAL_STRENGTH_LEVEL_MIN;
+                                    ql_nw_get_signal_strength(&signal_info, &level);
+                                    info->signal_cb(&signal_info, level);
+                                }
+                                break;
+                            }
+                            case QL_NW_EVENT_VOICE_CB:
+                            {
+                                if(info->voice_cb)
+                                {
+                                    ql_nw_reg_status_info_t voice_reg_info = {0};
+                                    ql_nw_get_voice_reg_status(&voice_reg_info);
+                                    info->voice_cb(&voice_reg_info);
+                                }
+                                break;
+                            }
+                            default:
+                            {
+                                QL_NW_LOGE("[%s] unknown event.[%d]", __func__, cmd);
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+static int ql_cb_thread_creat(ql_nw_info_handle_t *info)
+{
+    if(info->cb_thread_id == 0)
+    {
+        pthread_attr_t thread_attr;
+        pthread_attr_init(&thread_attr);
+        if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
+        {
+            QL_NW_LOGE("[%s] pthread_attr_setdetachstate fail.", __func__);
+            return QL_ERR_FAILED;
+        }
+        if(pthread_create(&(info->cb_thread_id), &thread_attr, ql_cb_thread, info))
+        {
+            QL_NW_LOGE("[%s] pthread_create fail.[%ld]", __func__, info->cb_thread_id);
+            return QL_ERR_FAILED;
+        }
+        QL_NW_LOGD("[%s] pthread_create success.[%ld]", __func__, info->cb_thread_id);
+    }
+
+    return QL_ERR_OK;
+}
+
+static int ql_cb_thread_free(ql_nw_info_handle_t *info)
+{
+    int ret = 0;
+    if(info->cb_thread_id != 0)
+    {
+        ql_nw_event_enum cmd = QL_NW_EVENT_THREAD_QUIT;
+        if(info->control[0] >= 0)
+        {
+            ret = write(info->control[0], &cmd, MBTK_WRITE_EVENT_SIZE);
+            if(ret != MBTK_WRITE_EVENT_SIZE)
+            {
+                QL_NW_LOGE("[%s] write fail.[%d]", __func__, ret);
+                return QL_ERR_FAILED;
+            }
+        }
+        info->cb_thread_id = 0;
+        QL_NW_LOGE("[%s] pthread quit success.", __func__);
+    }
+
+    return QL_ERR_OK;
+}
+
+/*----------------------------------------------NW FUNCTION--------------------------------------*/
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief Initialize NW service.
+  @note You must call this function before other functions can be used in this module.
+  @return Whether the NW service was successfully intialized.
+  @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_nw_init(void)
+{
+    if(NULL == nw_handle)
+    {
+        nw_handle = (ql_nw_info_handle_t*)malloc(sizeof(ql_nw_info_handle_t));
+        if(NULL == nw_handle)
+        {
+            QL_NW_LOGE("[%s] nw handle malloc fail.", __func__);
+            return QL_ERR_FAILED;
+        }
+
+        nw_handle->handle = mbtk_ril_open(MBTK_AT_PORT_DEF);
+        if(NULL == nw_handle->handle)
+        {
+            QL_NW_LOGE("[%s] mbtk handle init fail.", __func__);
+            goto error_1;
+        }
+
+        int ret = mbtk_signal_state_change_cb_reg(ql_signal_state_change_cb);
+        if(ret != MBTK_ERR_OK)
+        {
+            QL_NW_LOGE("[%s] set nw signal cb fail.[%d]", __func__, ret);
+            goto error_2;
+        }
+
+        ret = mbtk_net_reg_state_change_cb_reg(ql_net_state_change_cb);
+        if(ret != MBTK_ERR_OK)
+        {
+            QL_NW_LOGE("[%s] set nw signal cb fail.[%d]", __func__, ret);
+            goto error_2;
+        }
+
+        ret = mbtk_ril_ser_state_change_cb_reg(ql_nw_server_change_cb);
+        if(ret != MBTK_ERR_OK)
+        {
+            QL_NW_LOGE("[%s] set sim server cb fail.[%d]", __func__, ret);
+            goto error_2;
+        }
+
+        nw_handle->signal_cb = NULL;
+        nw_handle->voice_cb = NULL;
+        nw_handle->control[0] = -1;
+        nw_handle->control[1] = -1;
+        nw_handle->cb_thread_id = 0;
+    }
+
+    return QL_ERR_OK;
+error_2:
+    if(nw_handle->handle)
+    {
+        mbtk_ril_close(MBTK_AT_PORT_DEF);;
+        nw_handle->handle = NULL;
+    }
+error_1:
+    if(nw_handle)
+    {
+        free(nw_handle);
+        nw_handle = NULL;
+    }
+    return QL_ERR_FAILED;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief  Deinitializes NW service.
+  @return Whether the NW service was deinitialized successfully.
+  @retval QL_ERR_OK successful.
+  @retval Other error code defined by ql_type.h.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_deinit(void)
+{
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    int ret = 0;
+    nw_handle->voice_cb = NULL;
+    nw_handle->signal_cb = NULL;
+    
+    if(NULL != nw_handle->handle)
+    {
+        ret = mbtk_ril_close(MBTK_AT_PORT_DEF);
+        if(ret != MBTK_ERR_OK)
+        {
+            QL_NW_LOGE("[%s] mbtk handle deinit fail.[%d]", __func__, ret);
+            return QL_ERR_FAILED;
+        }
+        nw_handle->handle = NULL;
+    }
+
+    ret = ql_cb_thread_free(nw_handle);
+    if(ret != QL_ERR_OK)
+    {
+        QL_NW_LOGE("[%s] cb thread free deinit fail.", __func__);
+        return QL_ERR_FAILED;
+    }
+
+    free(nw_handle);
+    nw_handle = NULL;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief scan network status.
+  @param[out] async_index The index of request msg
+  @param[in] async_cb The callback function of request msg
+  @return Whether to successfully trigger the network scan operation
+  @retval QL_ERR_OK  successful
+  @retval QL_ERR_NOT_INIT  uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY  service is not ready
+  @retval QL_ERR_INVALID_ARG  Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_network_scan(int *async_index, ql_nw_network_scan_async_cb async_cb)
+{
+    UNUSED(async_index);
+    UNUSED(async_cb);
+    
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set power mode.
+  @param[in] lower_mode, defined by QL_NW_LOWER_POWER_MASK_XXX
+  @return Whether to successfully set the power mode
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_set_power_mode(uint8_t lower_mode)
+{ 
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    uint32 mode = 0;
+    if((lower_mode & QL_NW_LOWER_POWER_MASK_NORMAL) == QL_NW_LOWER_POWER_MASK_NORMAL)
+    {
+        mode |= 0x1;
+    }
+
+    if((lower_mode & QL_NW_LOWER_POWER_MASK_NETWORK) == QL_NW_LOWER_POWER_MASK_NETWORK)
+    {
+        mode |= 0x1;
+    }
+
+    if((lower_mode & QL_NW_LOWER_POWER_MASK_SIM) == QL_NW_LOWER_POWER_MASK_SIM)
+    {
+        mode |= 0x2;
+    }
+
+    if((lower_mode & QL_NW_LOWER_POWER_MASK_SMS) == QL_NW_LOWER_POWER_MASK_SMS)
+    {
+        mode |= 0x4;
+    }
+
+    if((lower_mode & QL_NW_LOWER_POWER_MASK_VOICE) == QL_NW_LOWER_POWER_MASK_VOICE)
+    {
+        mode |= 0x8;
+    }
+
+    int ret = 0;
+    ret = mbtk_wakeup_state_set(nw_handle->handle, mode);
+    if(ret != MBTK_ERR_OK)
+    {
+        QL_NW_LOGE("[%s] wakeup state set fail.[%d]", ret);
+        return QL_ERR_FAILED;
+    }
+    
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set perferred NW mode and roaming indicator.
+  @param[in] p_info Pointer that point to ql_nw_pref_nwmode_roaming_info_t
+  @return Whether to successfully set nwmode and roaming
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_set_pref_nwmode_roaming(ql_nw_pref_nwmode_roaming_info_t *p_info)
+{
+    UNUSED(p_info);
+    
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get perferred NW mode and roaming indicator.
+  @param[out] p_info Pointer that point to ql_nw_pref_nwmode_roaming_info_t 
+  @return Whether to successfully get nwmode and roaming
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_get_pref_nwmode_roaming(ql_nw_pref_nwmode_roaming_info_t *p_info)
+{
+    UNUSED(p_info);
+    
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get mobile operator name.
+  @param[out] p_info Pointer that point to ql_nw_mobile_operator_name_info_t
+  @return Whether to successfully get the mobile operator name
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_get_mobile_operator_name(ql_nw_mobile_operator_name_info_t *p_info)
+{
+    UNUSED(p_info);
+    
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get cell information.
+  @param[out] p_info Pointer that point to ql_nw_cell_info_t
+  @return Whether to successfully get the cell information
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_get_cell_info(ql_nw_cell_info_t *p_info)
+{
+    UNUSED(p_info);
+    
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get voice registration status.
+  @param[out] p_info Pointer that point to ql_nw_reg_status_info_t
+  @return Whether to successfully get the voice registration status
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_get_voice_reg_status(ql_nw_reg_status_info_t *p_info)
+{   
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    if(NULL == p_info)
+    {
+        QL_NW_LOGE("[%s] p_info is NULL.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int ret = 0;
+    ql_nw_reg_status_info_t reg_status_info = {0};
+    memset(&reg_status_info, 0x0, sizeof(ql_nw_reg_status_info_t));
+    reg_status_info.tech_domain = QL_NW_TECH_DOMAIN_3GPP; //default
+
+    //get radio_tech mcc mnc
+    ret = ql_get_cops_state(&reg_status_info, nw_handle);
+    if(ret != QL_ERR_OK)
+    {
+        QL_NW_LOGE("[%s] get cops state fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    //get roaming deny_reason reg_state cid lac
+    ret = ql_get_creg_state(&reg_status_info, nw_handle, QL_NW_REG_TYPE_VOICE);
+    if(ret != QL_ERR_OK)
+    {
+        QL_NW_LOGE("[%s] get creg fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    memcpy(p_info, &reg_status_info, sizeof(ql_nw_reg_status_info_t));
+    return QL_ERR_OK;
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get data registration status.
+  @param[out] p_info Pointer that point to ql_nw_reg_status_info_t
+  @return Whether to successfully get the data registration status
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_get_data_reg_status(ql_nw_reg_status_info_t *p_info)
+{
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    if(NULL == p_info)
+    {
+        QL_NW_LOGE("[%s] p_info is NULL.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int ret = 0;
+    ql_nw_reg_status_info_t reg_status_info = {0};
+    memset(&reg_status_info, 0x0, sizeof(ql_nw_reg_status_info_t));
+    reg_status_info.tech_domain = QL_NW_TECH_DOMAIN_3GPP; //default
+
+    //get radio_tech mcc mnc
+    ret = ql_get_cops_state(&reg_status_info, nw_handle);
+    if(ret != QL_ERR_OK)
+    {
+        QL_NW_LOGE("[%s] get cops state fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    //get roaming deny_reason reg_state cid lac
+    ret = ql_get_creg_state(&reg_status_info, nw_handle, QL_NW_REG_TYPE_DATA);
+    if(ret != QL_ERR_OK)
+    {
+        QL_NW_LOGE("[%s] get creg fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    memcpy(p_info, &reg_status_info, sizeof(ql_nw_reg_status_info_t));
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get current signal strength.
+  @param[out] p_info Pointer that point to ql_nw_signal_strength_info_t
+  @param[out] p_level: signal strength level
+  @return Whether to successfully get the signal strength
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_get_signal_strength(ql_nw_signal_strength_info_t *p_info, QL_NW_SIGNAL_STRENGTH_LEVEL_E* p_level)
+{   
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    if(NULL == p_info || NULL == p_level)
+    {
+        QL_NW_LOGE("[%s] param is NULL.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int ret = 0;
+    mbtk_signal_info_t signal;
+    memset(&signal, 0x0, sizeof(mbtk_signal_info_t));
+    ret = mbtk_net_signal_get(nw_handle->handle, &signal);
+    if(ret != MBTK_ERR_OK)
+    {
+        QL_NW_LOGE("[%s] net signal get fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    memset(p_info, 0x0, sizeof(ql_nw_signal_strength_info_t));
+    
+    switch(signal.type)
+    {
+        case MBTK_RADIO_TECH_GSM:
+        case MBTK_RADIO_TECH_GSM_COMPACT:
+        case MBTK_RADIO_TECH_GSM_EGPRS:
+        {
+            p_info->has_gsm = TRUE;
+            p_info->gsm.rssi = rssi_convert_to_dBm(signal.rssi);
+            break;
+        }
+        case MBTK_RADIO_TECH_E_UTRAN:
+        {
+            p_info->has_lte = TRUE;
+            p_info->lte.rssi = rssi_convert_to_dBm(signal.rssi);
+            p_info->lte.rsrq = rsrq_convert_to_dB(signal.rsrq);
+            p_info->lte.rsrp = rsrp_convert_to_dBm(signal.rsrp);
+            p_info->lte.snr = 0x7FFF;//->MBTK??????(?????rssnr,??INT_MAX:0x7FFFFFFFF?????),????0x7FFFFFFFF 
+            break;
+        }
+        case MBTK_RADIO_TECH_UTRAN:
+        case MBTK_RADIO_TECH_UTRAN_HSDPA:
+        case MBTK_RADIO_TECH_UTRAN_HSUPA:
+        case MBTK_RADIO_TECH_UTRAN_HSDPA_HSUPA:
+        case MBTK_RADIO_TECH_UTRAN_HSPA:
+        {
+            p_info->has_wcdma = TRUE;
+            p_info->wcdma.rssi = rssi_convert_to_dBm(signal.rssi);
+            p_info->wcdma.ecio = ecno_convert_to_dB(signal.ecno);
+            break;
+        }
+        default:
+        {
+            QL_NW_LOGE("[%s] unknown reg type.[%d]", __func__, signal.type);
+            break;
+        }
+    }
+
+    *p_level = ql_rssi_convert_level(signal.rssi);
+    return QL_ERR_OK;
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get current cell acccess status.
+  @param[out] p_info Pointer that point to QL_NW_CELL_ACCESS_STATE_TYPE_E
+  @return Whether to successfully get the cell access status
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_get_cell_access_status(QL_NW_CELL_ACCESS_STATE_TYPE_E *p_info)
+{
+    UNUSED(p_info);
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get network time.
+  @param[out] p_info Pointer that point to ql_nw_nitz_time_info_t 
+  @return Whether to successfully get the network time
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_get_nitz_time_info(ql_nw_nitz_time_info_t *p_info)
+{
+    UNUSED(p_info);
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register voice registration event.
+  @param[in] cb_func Voice registration indication callback function
+  @return Whether the voice registration event was successfully registered.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+ */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_set_voice_reg_ind_cb(ql_nw_voice_reg_ind_cb cb_func)
+{
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    int ret = QL_ERR_OK;
+    if(NULL != cb_func)
+    {
+        ret = ql_cb_thread_creat(nw_handle);
+        if(ret != QL_ERR_OK)
+        {
+            QL_NW_LOGE("[%s] cb thread creat fail.", __func__);
+        }
+    }
+    else
+    {
+        ret = ql_cb_thread_free(nw_handle);
+        if(ret != QL_ERR_OK)
+        {
+            QL_NW_LOGE("[%s] cb thread free deinit fail.", __func__);
+            return QL_ERR_FAILED;
+        }
+    }
+
+    nw_handle->voice_cb = cb_func;
+    
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register data registration event.
+  @param[in] cb_func Data registration indication callback function
+  @return Whether the data registration event was successfully registered.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_set_data_reg_ind_cb(ql_nw_data_reg_ind_cb cb_func)
+{
+    UNUSED(cb_func);
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register signal strength event.
+  @param[in] cb_func Signal strength indication callback function
+  @return Whether the signal strength event was successfully registered
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_set_signal_strength_ind_cb(ql_nw_signal_strength_ind_cb cb_func)
+{
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    int ret = QL_ERR_OK;
+    if(NULL != cb_func)
+    {
+        ret = ql_cb_thread_creat(nw_handle);
+        if(ret != QL_ERR_OK)
+        {
+            QL_NW_LOGE("[%s] cb thread creat fail.", __func__);
+        }
+    }
+    else
+    {
+        ret = ql_cb_thread_free(nw_handle);
+        if(ret != QL_ERR_OK)
+        {
+            QL_NW_LOGE("[%s] cb thread free deinit fail.", __func__);
+            return QL_ERR_FAILED;
+        }
+    }
+
+    nw_handle->signal_cb = cb_func;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register cell access status event.
+  @param[in] cb_func Cell access status indication callback function
+  @return Whether the cell access status event was successfully registered
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_set_cell_access_status_ind_cb(ql_nw_cell_access_status_ind_cb cb_func)
+{
+    UNUSED(cb_func);
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register network time event.
+  @param[in] cb_func nitz time update indication callback function
+  @return Whether the network time event was successfully registered
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_set_nitz_time_update_ind_cb(ql_nw_nitz_time_update_ind_cb cb_func)
+{
+    UNUSED(cb_func);
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register wea alert event.
+  @param[in] cb_func wea alert indication callback function
+  @return Whether the network time event was successfully registered
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_set_wea_alert_ind_cb(ql_nw_wea_reg_ind_cb cb_func)
+{
+    UNUSED(cb_func);
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief register etws alert event.
+  @param[in] cb_func etws alert indication callback function
+  @return Whether the network time event was successfully registered
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_set_etws_alert_ind_cb(ql_nw_etws_reg_ind_cb cb_func)
+{
+    UNUSED(cb_func);
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set wea alert config.
+  @param[in] item Items to set.
+  @param[in] p_info Pointer that point to ql_nw_wea_config_t.
+  @return Whether to successfully set the wea config.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_set_wea_config(int item, ql_nw_wea_config_t *p_info)
+{
+    UNUSED(p_info);
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief  Gets wea config.
+  @param[out] p_config wea config.
+  @return Whether the wea 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_nw_get_wea_config(ql_nw_wea_config_t *p_config)
+{
+    UNUSED(p_config);
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set etws alert config.
+  @param[in] etws config.
+  @return Whether to successfully set the etws config.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_set_etws_config(uint8_t enable_etws)
+{
+    UNUSED(enable_etws);
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get etws alert config.
+  @param[out] p_enable_etws Pointer.
+  @return Whether to successfully set the etws config.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_get_etws_config(uint8_t* p_enable_etws)
+{
+    UNUSED(p_enable_etws);
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  bind subscription 
+  @param[in] sub_type subscription type 
+  @return Whether to successfully bind subscription.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_bind_subscription(QL_NW_BIND_SUB_TYPE_E sub_type)
+{
+    UNUSED(sub_type);
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief get high capability subscription.
+  @param[out] p_high_cap pointer that point to QL_NW_BIND_SUB_TYPE_E
+  @return Whether the high capability subscription was successfully obtained.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_get_high_cap_sub(QL_NW_BIND_SUB_TYPE_E *p_high_cap)
+{
+    UNUSED(p_high_cap);
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief set the SIM card index that can uniquely register to the 5G network. 
+  the main difference between high and non-high capability subscription is that high capability 
+  subscription can register to 5G network while non-high capability subscription can only 
+  register to LTE or GSM.
+  @param[in] high_cap high capability subscription 
+  @return Whether to successfully set the high capability subscription.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_set_high_cap_sub(QL_NW_BIND_SUB_TYPE_E high_cap)
+{
+    UNUSED(high_cap);
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Disable NR5G, NR5G_SA and NR5G_NSA can be disabled individually or together.
+  @param[in] opt_mask Option mask value. Value:
+  0                 - Do not disable NR5G
+  QL_NW_NR5G_SO_SA  - Disable NR5G SA
+  QL_NW_NR5G_SO_NSA - Disable NR5G NSA 
+  @return Whether to successfully disable NR5G mode.
+  @retval QL_ERR_OK successful
+  @retval QL_ERR_NOT_INIT uninitialized
+  @retval QL_ERR_SERVICE_NOT_READY service is not ready
+  @retval QL_ERR_INVALID_ARG Invalid arguments
+  @retval Other error code defined by ql_type.h
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_nw_disable_nr5g(uint16_t opt_mask)
+{
+    UNUSED(opt_mask);
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @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_nw_set_service_error_cb(ql_nw_service_error_cb_f cb)
+{
+    if(NULL == nw_handle)
+    {
+        QL_NW_LOGE("[%s] nw handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    nw_handle->server_cb = cb;
+
+    return QL_ERR_OK;
+}
+
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_sim.c b/mbtk/libql_lib_v2_rilv2/ql_sim.c
new file mode 100755
index 0000000..7028f1c
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_sim.c
@@ -0,0 +1,1497 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_sim.h
+  @brief SIM service API
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  Copyright (c) 2024 mobiletek Wireless Solution, Co., Ltd. All Rights Reserved.
+  mobiletek 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
+  --------   ---------    -----------------------------------------------------------------
+  20241022    yq.wang      Created .
+-------------------------------------------------------------------------------------------------*/
+
+#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 "ql_sim.h"
+#include "ql_type.h"
+#include "mbtk_type.h"
+#include "mbtk_ril_api.h"
+#include "mbtk_list.h"
+#include "mbtk_log.h"
+
+/*----------------------------------------------DEFINE-------------------------------------------*/
+#define MBTK_ERR_OK             0
+
+#define MBTK_PIN_VALUE_LENGTH   16
+#define MBTK_BUFF_TEMP_SIZE_16  16
+#define MBTK_BUFF_TEMP_SIZE_32  32
+#define MBTK_BUFF_TEMP_SIZE_64  64
+#define MBTK_BUFF_TEMP_SIZE_128 128
+
+#define MBTK_READ_EVENT_SIZE    1
+#define MBTK_WRITE_EVENT_SIZE   1
+
+#define QL_SIM_LOGE LOGE
+#define QL_SIM_LOGD LOGD
+
+#define MBTK_PIN_ENABLE 1
+/*----------------------------------------------DEFINE-------------------------------------------*/
+
+/*----------------------------------------------ENUM-------------------------------------------*/
+typedef enum {
+    QL_SIM_EVENT_THREAD_QUIT = 0,
+    QL_SIM_EVENT_STATE_CHANGE,
+    QL_SIM_EVENT_MAX = 255,
+}ql_sim_event_enum;
+
+/*----------------------------------------------ENUM-------------------------------------------*/
+
+/*----------------------------------------------STRUCT-------------------------------------------*/
+typedef struct {
+    mbtk_ril_handle*       handle;
+    int                       control[2];
+    pthread_t                 cb_thread_id;
+    ql_sim_card_status_cb_f   status_cb;
+    ql_sim_service_error_cb_f server_cb;
+}ql_sim_info_handle_t;
+
+/*----------------------------------------------STRUCT-------------------------------------------*/
+
+/*----------------------------------------------GLOBAL STATIC VARIABLE---------------------------*/
+static ql_sim_info_handle_t* sim_handle = NULL;
+
+/*----------------------------------------------GLOBAL STATIC VARIABLE---------------------------*/
+
+/*----------------------------------------------SIM FUNCTION-------------------------------------*/
+static void ql_sim_state_change_cb(const void* data, int data_len)
+{
+    if(data_len != sizeof(mbtk_ril_sim_state_info_t))
+    {
+        QL_SIM_LOGE("[%s] data_len[%d] than sim[%d] fail. ", __func__, data_len, sizeof(mbtk_ril_sim_state_info_t));
+    }
+    else
+    {
+        mbtk_ril_sim_state_info_t *ptr = (mbtk_ril_sim_state_info_t*)data;
+        QL_SIM_LOGD("[%s] state[%d] type[%d].", __func__, ptr->sim_state , ptr->sim_type);
+        ql_sim_event_enum cmd = QL_SIM_EVENT_STATE_CHANGE;
+        if(sim_handle->control[0] >= 0 && ptr->sim_state != MBTK_SIM_STATE_UNKNOWN)
+        {
+            int ret = write(sim_handle->control[0], &cmd, MBTK_WRITE_EVENT_SIZE);
+            if(ret != MBTK_WRITE_EVENT_SIZE)
+            {
+                QL_SIM_LOGE("[%s] write fail.[%d]", __func__, ret);
+            }
+        }
+    }
+}
+
+static void ql_sim_server_change_cb(const void* data, int data_len)
+{
+    if(data) {
+        const uint8 *ptr = (const uint8*)data;
+        mbtk_ril_ser_state_enum state = (mbtk_ril_ser_state_enum)ptr[0];
+        LOGD("ril server state : %d.\n", state);
+        if(sim_handle->server_cb && MBTK_RIL_SER_STATE_EXIT == state) {
+            sim_handle->server_cb(QL_ERR_ABORTED);
+        }
+    }
+}
+
+static int ql_epoll_register(int epoll_fd, int fd)
+{
+    struct epoll_event  ev;
+    int    ret, flags;
+
+    /* important: make the fd non-blocking */
+    flags = fcntl(fd, F_GETFL);
+    fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+
+    ev.events  = EPOLLIN;
+    ev.data.fd = fd;
+
+    do
+    {
+        ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev);
+        if(ret < 0)
+        {
+            QL_SIM_LOGE("[%s] epoll_ctl fail.[%s]", __func__, strerror(errno));
+        }
+    } while (ret < 0 && errno == EINTR);
+
+    return QL_ERR_OK;
+}
+
+static void* ql_cb_thread(void* arg)
+{
+    ql_sim_info_handle_t* info = (ql_sim_info_handle_t*)arg;
+
+    if(info->control[0] < 0 && info->control[0] < 0)
+    {
+        if(socketpair(AF_LOCAL, SOCK_STREAM, 0, info->control ) < 0)
+        {
+            QL_SIM_LOGE("[%s] control creat fail.", __func__);
+            return NULL;
+        }
+    }
+
+    int ne = 0;
+    int nevents = 0;
+    int ret = 0;
+    struct epoll_event events[3];
+    int control_fd = info->control[1];
+    ql_sim_event_enum cmd = QL_SIM_EVENT_THREAD_QUIT;
+
+    //A maximum of three events can be processed simultaneously
+    int epoll_fd = epoll_create(3);
+    ql_epoll_register(epoll_fd, control_fd);
+
+    QL_SIM_LOGE("[%s] thread start run.", __func__);
+    while(1)
+    {
+        nevents = epoll_wait(epoll_fd, events, 3, -1);
+        if(nevents < 0)
+        {
+            if(errno != EINTR)
+            {
+                QL_SIM_LOGE("[%s] epoll_wait fail.[%s]", __func__, strerror(errno));
+            }
+            continue;
+        }
+
+        for (ne = 0; ne < nevents; ne++)
+        {
+            if((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0)
+            {
+                QL_SIM_LOGE("[%s] EPOLLERR or EPOLLHUP event error.", __func__);
+                break;
+            }
+
+            if ((events[ne].events & EPOLLIN) != 0)
+            {
+                if (events[ne].data.fd == control_fd)
+                {
+                    ret = read(control_fd, &cmd, MBTK_READ_EVENT_SIZE);
+                    if(ret != MBTK_READ_EVENT_SIZE)
+                    {
+                        QL_SIM_LOGE("[%s] read fail.[%d]", __func__, ret);
+                    }
+                    else
+                    {
+                        switch(cmd)
+                        {
+                            case QL_SIM_EVENT_THREAD_QUIT:
+                            {
+                                close(epoll_fd);
+                                epoll_fd = -1;
+                                if(info->control[0] >= 0)
+                                {
+                                    close(info->control[0]);
+                                    info->control[0] = -1;
+                                }
+                                if(info->control[1] >= 0)
+                                {
+                                    close(info->control[1]);
+                                    info->control[1] = -1;
+                                }
+                                QL_SIM_LOGD("[%s] thread quit.", __func__);
+                                return NULL;
+                            }
+                            case QL_SIM_EVENT_STATE_CHANGE:
+                            {
+                                if(info->status_cb)
+                                {
+                                    ql_sim_card_info_t sim_info = {0};
+                                    ql_sim_get_card_info(QL_SIM_SLOT_1, &sim_info);
+                                    info->status_cb(QL_SIM_SLOT_1, &sim_info);
+                                }
+                                break;
+                            }
+                            default:
+                            {
+                                QL_SIM_LOGE("[%s] unknown event.[%d]", __func__, cmd);
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+static int ql_cb_thread_creat(ql_sim_info_handle_t *info)
+{
+    if(info->cb_thread_id == 0)
+    {
+        pthread_attr_t thread_attr;
+        pthread_attr_init(&thread_attr);
+        if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
+        {
+            QL_SIM_LOGE("[%s] pthread_attr_setdetachstate fail.", __func__);
+            return QL_ERR_FAILED;
+        }
+        if(pthread_create(&(info->cb_thread_id), &thread_attr, ql_cb_thread, info))
+        {
+            QL_SIM_LOGE("[%s] pthread_create fail.[%ld]", __func__, info->cb_thread_id);
+            return QL_ERR_FAILED;
+        }
+        QL_SIM_LOGD("[%s] pthread_create success.[%ld]", __func__, info->cb_thread_id);
+    }
+
+    return QL_ERR_OK;
+}
+
+static int ql_cb_thread_free(ql_sim_info_handle_t *info)
+{
+    int ret = 0;
+    if(info->cb_thread_id != 0)
+    {
+        ql_sim_event_enum cmd = QL_SIM_EVENT_THREAD_QUIT;
+        if(info->control[0] >= 0)
+        {
+            ret = write(info->control[0], &cmd, MBTK_WRITE_EVENT_SIZE);
+            if(ret != MBTK_WRITE_EVENT_SIZE)
+            {
+                QL_SIM_LOGE("[%s] write fail.[%d]", __func__, ret);
+                return QL_ERR_FAILED;
+            }
+        }
+        info->cb_thread_id = 0;
+        QL_SIM_LOGE("[%s] pthread quit success.", __func__);
+    }
+
+    return QL_ERR_OK;
+}
+
+/*----------------------------------------------SIM FUNCTION-------------------------------------*/
+
+/*----------------------------------------------SIM API------------------------------------------*/
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Initializes SIM service.
+  @note You must call this function before other functions can be used in this module.
+  @return Whether the SIM service was intialized 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_sim_init(void)
+{
+    if(NULL == sim_handle)
+    {
+        sim_handle = (ql_sim_info_handle_t*)malloc(sizeof(ql_sim_info_handle_t));
+        if(NULL == sim_handle)
+        {
+            QL_SIM_LOGE("[%s] sim handle malloc fail.", __func__);
+            return QL_ERR_FAILED;
+        }
+
+        sim_handle->handle = mbtk_ril_open(MBTK_AT_PORT_DEF);
+        if(NULL == sim_handle->handle)
+        {
+            QL_SIM_LOGE("[%s] mbtk handle init fail.", __func__);
+            goto error_1;
+        }
+
+        int ret = mbtk_sim_state_change_cb_reg(ql_sim_state_change_cb);
+        if(ret != MBTK_ERR_OK)
+        {
+            QL_SIM_LOGE("[%s] set sim state cb fail.[%d]", __func__, ret);
+            goto error_2;
+        }
+
+        ret = mbtk_ril_ser_state_change_cb_reg(ql_sim_server_change_cb);
+        if(ret != MBTK_ERR_OK)
+        {
+            QL_SIM_LOGE("[%s] set sim server cb fail.[%d]", __func__, ret);
+            goto error_2;
+        }
+
+        sim_handle->status_cb = NULL;
+        sim_handle->server_cb = NULL;
+        sim_handle->control[0] = -1;
+        sim_handle->control[1] = -1;
+        sim_handle->cb_thread_id = 0;
+    }
+
+    return QL_ERR_OK;
+
+error_2:
+    if(sim_handle->handle)
+    {
+        mbtk_ril_close(MBTK_AT_PORT_DEF);
+        sim_handle->handle = NULL;
+    }
+error_1:
+    if(sim_handle)
+    {
+        free(sim_handle);
+        sim_handle = NULL;
+    }
+    return QL_ERR_FAILED;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Deinitializes SIM service.
+  @return Whether the SIM service was deintialized 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_sim_deinit(void)
+{
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    int ret = 0;
+    sim_handle->server_cb = NULL;
+    sim_handle->status_cb = NULL;
+
+    if(NULL != sim_handle->handle)
+    {
+        ret = mbtk_ril_close(MBTK_AT_PORT_DEF);
+        if(ret != MBTK_ERR_OK)
+        {
+            QL_SIM_LOGE("[%s] mbtk handle deinit fail.[%d]", __func__, ret);
+            return QL_ERR_FAILED;
+        }
+        sim_handle->handle = NULL;
+    }
+
+    ret = ql_cb_thread_free(sim_handle);
+    if(ret != QL_ERR_OK)
+    {
+        QL_SIM_LOGE("[%s] cb thread free deinit fail.", __func__);
+        return QL_ERR_FAILED;
+    }
+
+    free(sim_handle);
+    sim_handle = NULL;
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Gets the IMSI (for 3GPP) or IMSI_M (for 3GPP2) from the SIM in ASCII form.
+  @param [in] slot Slot to be used.
+  @note This function is only supported by Identify card in slot 1
+  @param [in] app_type Application type.
+  @note This function is only supported by 3GPP applications
+  @param [out] imsi Buffer to fill IMSI data.
+  @param [in] imsi_len Buffer length.
+  @return Whether the IMSI was successfully obtained.
+  @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_sim_get_imsi(QL_SIM_SLOT_E slot, QL_SIM_APP_TYPE_E app_type, char *imsi, int imsi_len)
+{
+    UNUSED(slot);
+    UNUSED(app_type);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    if(NULL == imsi)
+    {
+        QL_SIM_LOGE("[%s] imsi is NULL.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    if(imsi_len < QL_SIM_IMSI_LENGTH)
+    {
+        QL_SIM_LOGE("[%s] imsi buf is too short.", __func__);
+        return QL_ERR_BUF_OVERFLOW;
+    }
+
+    char temp_buff[MBTK_BUFF_TEMP_SIZE_32] = {0};
+    memset(imsi, 0x0, imsi_len);
+    memset(temp_buff, 0x0, MBTK_BUFF_TEMP_SIZE_32);
+    int ret = mbtk_imsi_get(sim_handle->handle, (void *)temp_buff);
+    if(ret != MBTK_ERR_OK)
+    {
+        QL_SIM_LOGE("[%s] imsi get fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    memcpy(imsi, temp_buff, QL_SIM_IMSI_LENGTH);
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Retrieves the Integrated Circuit Card ID (ICCID) stored on the card.
+  @param [in] slot Slot to be used(the parameter currently does not support).
+  @note This function is only supported by Identify card in slot 1
+  @param [out] iccid Buffer to fill ICCID data.
+  @param [in] iccid_len Buffer length.
+  @return Whether the ICCID was successfully obtained.
+  @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_sim_get_iccid(QL_SIM_SLOT_E slot, char *iccid, int iccid_len)
+{
+    UNUSED(slot);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    if(NULL == iccid)
+    {
+        QL_SIM_LOGE("[%s] iccid is NULL.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    if(iccid_len < QL_SIM_ICCID_LENGTH)
+    {
+        QL_SIM_LOGE("[%s] imsi buf is too short.", __func__);
+        return QL_ERR_BUF_OVERFLOW;
+    }
+
+    char temp_buff[MBTK_BUFF_TEMP_SIZE_32] = {0};
+    memset(iccid, 0x0, iccid_len);
+    memset(temp_buff, 0x0, MBTK_BUFF_TEMP_SIZE_32);
+    int ret = mbtk_iccid_get(sim_handle->handle, (void *)temp_buff);
+    if(ret != MBTK_ERR_OK)
+    {
+        QL_SIM_LOGE("[%s] iccid get fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    memcpy(iccid, temp_buff, QL_SIM_ICCID_LENGTH);
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Retrieves the device phone number stored on the card.
+  @param [in] slot Slot to be used.
+  @note This function is only supported by Identify card in slot 1
+  @param [in] app_type Application type.
+  @note This function is only supported by 3GPP applications
+  @param [out] phone_num Buffer to fill phone number.
+  @param [in] phone_num_len Buffer length.
+  @return Whether the phone number was successfully retrieved.
+  @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_sim_get_phone_num(QL_SIM_SLOT_E slot, QL_SIM_APP_TYPE_E app_type,
+                          char *phone_num, int phone_num_len)
+{
+    UNUSED(slot);
+    UNUSED(app_type);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    if(NULL == phone_num)
+    {
+        QL_SIM_LOGE("[%s] phone_num is NULL.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    if(phone_num_len < QL_SIM_PHONE_NUMBER_MAX)
+    {
+        QL_SIM_LOGE("[%s] phone_num buf is too short.", __func__);
+        return QL_ERR_BUF_OVERFLOW;
+    }
+
+    char temp_buff[MBTK_BUFF_TEMP_SIZE_128] = {0};
+    memset(phone_num, 0x0, phone_num_len);
+    memset(temp_buff, 0x0, MBTK_BUFF_TEMP_SIZE_128);
+    int ret = mbtk_phone_number_get(sim_handle->handle, (void *)temp_buff);
+    if(ret != MBTK_ERR_OK)
+    {
+        QL_SIM_LOGE("[%s] phone_num get fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    memcpy(phone_num, temp_buff, QL_SIM_PHONE_NUMBER_MAX);
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Retrieves the preferred operators stored on the card.
+  @param [in] slot Slot to be used.
+  @note This function is only supported by Identify card in slot 1
+  @param [out] list Buffer to hold operators.
+  @note This function is only supported by 3GPP applications
+  @return Whether the preferred operators were successfully retrieved.
+  @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_sim_get_operators(QL_SIM_SLOT_E slot, ql_sim_operator_list_t *list)
+{
+    UNUSED(slot);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    if(NULL == list)
+    {
+        QL_SIM_LOGE("[%s] list is NULL.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+#if 0
+    list_node_t* operators_list = NULL;
+    mbtk_net_info_t* operator = NULL;
+    char temp_buff[MBTK_BUFF_TEMP_SIZE_16] = {0};
+    int operators_size = 0;
+    int ret = mbtk_available_net_get(sim_handle->handle, &operators_list);
+    if(ret != MBTK_ERR_OK)
+    {
+        QL_SIM_LOGE("[%s] available operators get fail.[%d]", __func__, ret);
+        if(NULL != operators_list)
+        {
+            list_free(operators_list);
+            operators_list = NULL;
+        }
+        return QL_ERR_FAILED;
+    }
+
+    if(NULL == operators_list)
+    {
+        QL_SIM_LOGE("[%s] operators list is NULL.", __func__);
+        return QL_ERR_FAILED;
+    }
+    else
+    {
+        list_first(operators_list);
+        memset(list, 0x0, sizeof(ql_sim_operator_list_t));
+        while ((operator = (mbtk_net_info_t*) list_next(operators_list)))
+        {
+            QL_SIM_LOGD("[%s]operators: %d, %d, %d, %d.", __func__, operator->net_sel_mode, operator->net_type, operator->net_state, operator->plmn);
+            memset(temp_buff, 0x0, MBTK_BUFF_TEMP_SIZE_16);
+            ret = sprintf(temp_buff, "%d", operator->plmn);
+            list->operators[operators_size].mnc_len = ret - QL_SIM_MCC_LENGHT;
+            if(ret > QL_SIM_MCC_LENGHT && list->operators[operators_size].mnc_len <= QL_SIM_MNC_MAX)
+            {
+                memcpy(list->operators[operators_size].mcc, temp_buff, QL_SIM_MCC_LENGHT);
+                memcpy(list->operators[operators_size].mnc, temp_buff + QL_SIM_MCC_LENGHT, list->operators[operators_size].mnc_len);
+            }
+            else
+            {
+                QL_SIM_LOGE("[%s] MCC MNC length error.", __func__);
+                list_free(operators_list);
+                operators_list = NULL;
+                return QL_ERR_FAILED;
+            }
+            operators_size++;
+        }
+        list->len = operators_size;
+    }
+    list_free(operators_list);
+    operators_list = NULL;
+#else
+    mbtk_net_info_array_t net_list;
+    mbtk_ril_err_enum err = mbtk_available_net_get(sim_handle->handle, &net_list);
+    if(err != MBTK_RIL_ERR_SUCCESS) {
+        LOGE("Error : %d", err);
+    } else {
+        LOGD("Available net number:%d\n", net_list.num);
+        int i = 0;
+        char temp_buff[MBTK_BUFF_TEMP_SIZE_16] = {0};
+        int ret;
+        memset(list, 0x0, sizeof(ql_sim_operator_list_t));
+        while(i < net_list.num) {
+            memset(temp_buff, 0x0, MBTK_BUFF_TEMP_SIZE_16);
+            LOGD("NET : %d,%d,%d,%d\n", net_list.net_info[i].net_sel_mode,
+                net_list.net_info[i].net_type, net_list.net_info[i].net_state,
+                net_list.net_info[i].plmn);
+
+            ret = sprintf(temp_buff, "%d", net_list.net_info[i].plmn);
+            list->operators[i].mnc_len = ret - QL_SIM_MCC_LENGHT;
+            if(ret > QL_SIM_MCC_LENGHT && list->operators[i].mnc_len <= QL_SIM_MNC_MAX)
+            {
+                memcpy(list->operators[i].mcc, temp_buff, QL_SIM_MCC_LENGHT);
+                memcpy(list->operators[i].mnc, temp_buff + QL_SIM_MCC_LENGHT, list->operators[i].mnc_len);
+            }
+            else
+            {
+                QL_SIM_LOGE("[%s] MCC MNC length error.", __func__);
+                return QL_ERR_FAILED;
+            }
+            i++;
+        }
+        list->len = net_list.num;
+    }
+
+#endif
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Enables the PIN on an application.
+  @param [in] slot Slot to be used.
+  @note This function is only supported by Identify card in slot 1
+  @param [in] app_type Application type.
+  @note This function is only supported by 3GPP applications
+  @param [in] pin PIN to be used.
+  @note This function is only supported by Level 1 user verification
+  @param [in] pin_value PIN value. NULL terminated.
+  @return Whether the PIN was successfully enabled.
+  @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_sim_enable_pin(QL_SIM_SLOT_E slot, QL_SIM_APP_TYPE_E app_type,
+                             QL_SIM_PIN_E pin, const char *pin_value)
+{
+    UNUSED(slot);
+    UNUSED(app_type);
+    UNUSED(pin);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    if(NULL == pin_value)
+    {
+        QL_SIM_LOGE("[%s] pin_value is NULL.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int pin_len = strlen(pin_value);
+    if(pin_len > QL_SIM_PIN_MAX)
+    {
+        QL_SIM_LOGE("[%s] pin length is too long.", __func__);
+        return QL_ERR_ARG_TOO_LONG;
+    }
+    else if(pin_len <= 0)
+    {
+        QL_SIM_LOGE("[%s] pin length is too short.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_sim_lock_info_t info = {0};
+    info.type = MBTK_SIM_LOCK_TYPE_ENABLE;
+    memcpy(info.pin1, pin_value, pin_len);
+
+    int err = mbtk_sim_lock_set(sim_handle->handle, &info);
+    if(err)
+    {
+        QL_SIM_LOGE("[%s] enable pin fail.[%d]", __func__, err);
+        return QL_ERR_FAILED;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Disables the PIN on an application.
+  @param [in] slot Slot to be used.
+  @note This function is only supported by Identify card in slot 1
+  @param [in] app_type Application type.
+  @note This function is only supported by 3GPP applications
+  @param [in] pin PIN to be used.
+  @note This function is only supported by Level 1 user verification
+  @param [in] pin_value PIN value. NULL terminated.
+  @return Whether the PIN was successfully disabled.
+  @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_sim_disable_pin(QL_SIM_SLOT_E slot, QL_SIM_APP_TYPE_E app_type,
+                             QL_SIM_PIN_E pin, const char *pin_value)
+{
+    UNUSED(slot);
+    UNUSED(app_type);
+    UNUSED(pin);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    if(NULL == pin_value)
+    {
+        QL_SIM_LOGE("[%s] pin_value is NULL.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int pin_len = strlen(pin_value);
+    if(pin_len > QL_SIM_PIN_MAX)
+    {
+        QL_SIM_LOGE("[%s] pin length is too long.", __func__);
+        return QL_ERR_ARG_TOO_LONG;
+    }
+    else if(pin_len <= 0)
+    {
+        QL_SIM_LOGE("[%s] pin length is too short.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_sim_lock_info_t info = {0};
+    info.type = MBTK_SIM_LOCK_TYPE_DISABLE;
+    memcpy(info.pin1, pin_value, pin_len);
+
+    int err = mbtk_sim_lock_set(sim_handle->handle, &info);
+    if(err)
+    {
+        QL_SIM_LOGE("[%s] disenable pin fail.[%d]", __func__, err);
+        return QL_ERR_FAILED;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Verifies the PIN value of an application.
+  @param [in] slot Slot to be used.
+  @note This function is only supported by Identify card in slot 1
+  @param [in] app_type Application type.
+  @note This function is only supported by 3GPP applications
+  @param [in] pin PIN to be used.
+  @note This function is only supported by Level 1 user verification
+  @param [in] pin_value PIN value. NULL terminated.
+  @note PIN must be enabled before calling this function.
+  @return Whether the PIN was successfully verified.
+  @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_sim_verify_pin(QL_SIM_SLOT_E slot, QL_SIM_APP_TYPE_E app_type,
+                             QL_SIM_PIN_E pin, const char *pin_value)
+{
+    UNUSED(slot);
+    UNUSED(app_type);
+    UNUSED(pin);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    if(NULL == pin_value)
+    {
+        QL_SIM_LOGE("[%s] pin_value is NULL.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int pin_len = strlen(pin_value);
+    if(pin_len > QL_SIM_PIN_MAX)
+    {
+        QL_SIM_LOGE("[%s] pin length is too long.", __func__);
+        return QL_ERR_ARG_TOO_LONG;
+    }
+    else if(pin_len <= 0)
+    {
+        QL_SIM_LOGE("[%s] pin length is too short.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_sim_lock_info_t info = {0};
+    info.type = MBTK_SIM_LOCK_TYPE_VERIFY_PIN;
+    memcpy(info.pin1, pin_value, pin_len);
+
+    int err = mbtk_sim_lock_set(sim_handle->handle, &info);
+    if(err)
+    {
+        QL_SIM_LOGE("[%s] verify pin fail.[%d]", __func__, err);
+        return QL_ERR_FAILED;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Changes the PIN value of an application.
+  @param [in] slot Slot to be used.
+  @note This function is only supported by Identify card in slot 1
+  @param [in] app_type Application type.
+  @note This function is only supported by 3GPP applications
+  @param [in] pin PIN to be used.
+  @note This function is only supported by Level 1 user verification
+  @param [in] old_pin_value Old PIN value. NULL terminated.
+  @param [in] new_pin_value New PIN value. NULL terminated.
+  @return Whether the PIN was successfully changed.
+  @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_sim_change_pin(QL_SIM_SLOT_E slot, QL_SIM_APP_TYPE_E app_type,
+                             QL_SIM_PIN_E pin, const char *old_pin_value, const char *new_pin_value)
+{
+    UNUSED(slot);
+    UNUSED(app_type);
+    UNUSED(pin);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    if(NULL == old_pin_value || NULL == new_pin_value)
+    {
+        QL_SIM_LOGE("[%s] pin_value is NULL.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int old_pin_len = strlen(old_pin_value);
+    int new_pin_len = strlen(new_pin_value);
+    if(old_pin_len > QL_SIM_PIN_MAX || new_pin_len > QL_SIM_PIN_MAX)
+    {
+        QL_SIM_LOGE("[%s] pin length is too long.", __func__);
+        return QL_ERR_ARG_TOO_LONG;
+    }
+    else if(old_pin_len <= 0 || new_pin_len <= 0)
+    {
+        QL_SIM_LOGE("[%s] pin length is too short.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_sim_lock_info_t info = {0};
+    info.type = MBTK_SIM_LOCK_TYPE_CHANGE;
+    memcpy(info.pin1, old_pin_value, old_pin_len);
+    memcpy(info.pin2, new_pin_value, new_pin_len);
+
+    int err = mbtk_sim_lock_set(sim_handle->handle, &info);
+    if(err)
+    {
+        QL_SIM_LOGE("[%s] change pin fail.[%d]", __func__, err);
+        return QL_ERR_FAILED;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Unblocks a blocked PIN using the PUK code.
+  @param [in] slot Slot to be used.
+  @note This function is only supported by Identify card in slot 1
+  @param [in] app_type Application type.
+  @note This function is only supported by 3GPP applications
+  @param [in] pin PIN to be used.
+  @note This function is only supported by Level 1 user verification
+  @param [in] puk_value PUK value.  NULL terminated.
+  @param [in] pin_value New PIN value.  NULL terminated.
+  @note The user must pass PUK1 to unblock PIN1 or PUK2 to unblock PIN2.
+  @return Whether the PIN was successfully unblocked.
+  @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_sim_unblock_pin(QL_SIM_SLOT_E slot, QL_SIM_APP_TYPE_E app_type,
+                             QL_SIM_PIN_E pin, const char *puk_value, const char *pin_value)
+{
+    UNUSED(slot);
+    UNUSED(app_type);
+    UNUSED(pin);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    if(NULL == puk_value || NULL == pin_value)
+    {
+        QL_SIM_LOGE("[%s] value is NULL.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    int puk_len = strlen(puk_value);
+    int pin_len = strlen(pin_value);
+    if(puk_len > QL_SIM_PUK_LENGTH || pin_len > QL_SIM_PIN_MAX)
+    {
+        QL_SIM_LOGE("[%s] length is too long.", __func__);
+        return QL_ERR_ARG_TOO_LONG;
+    }
+    else if(puk_len <= 0 || pin_len <= 0)
+    {
+        QL_SIM_LOGE("[%s] length is too short.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_sim_lock_info_t info = {0};
+    info.type = MBTK_SIM_LOCK_TYPE_VERIFY_PUK;
+    memcpy(info.pin1, pin_value, pin_len);
+    memcpy(info.puk, puk_value, puk_len);
+
+    int err = mbtk_sim_lock_set(sim_handle->handle, &info);
+    if(err)
+    {
+        QL_SIM_LOGE("[%s] unblock pin fail.[%d]", __func__, err);
+        return QL_ERR_FAILED;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Retrieves the card info stored on a card.
+  @param [in] slot Slot to be used.
+  @note This function is only supported by Identify card in slot 1
+  @param [out] p_info Pointer of ql_sim_card_info_t.
+  @return Whether the card info was successfully retrieved.
+  @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_sim_get_card_info(QL_SIM_SLOT_E slot, ql_sim_card_info_t *p_info)
+{
+    UNUSED(slot);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    if(NULL == p_info)
+    {
+        QL_SIM_LOGE("[%s] p_info is NULL.", __func__);
+        return QL_ERR_INVALID_ARG;
+    }
+
+    mbtk_sim_state_enum sim;
+    int ret = mbtk_sim_state_get(sim_handle->handle, &sim);
+    if(ret != MBTK_ERR_OK)
+    {
+        QL_SIM_LOGE("[%s] sim state get fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    mbtk_sim_card_type_enum sim_card_type;
+    ret = mbtk_sim_type_get(sim_handle->handle, &sim_card_type);
+    if(ret)
+    {
+        QL_SIM_LOGE("[%s] sim type get fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    mbtk_pin_puk_last_times_t sim_last_times = {0};
+    ret = mbtk_sim_lock_retry_times_get(sim_handle->handle, &sim_last_times);
+    if(ret)
+    {
+        QL_SIM_LOGE("[%s] sim pin puk times get fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    int pin_state;
+    ret = mbtk_sim_lock_get(sim_handle->handle, &pin_state);
+    if(ret)
+    {
+        QL_SIM_LOGE("[%s] sim pin state get fail.[%d]", __func__, ret);
+        return QL_ERR_FAILED;
+    }
+
+    memset(p_info, 0x0, sizeof(ql_sim_card_info_t));
+    switch(sim)
+    {
+        case MBTK_SIM_STATE_ABSENT:                   //CARD ABSENT
+        {
+            p_info->state = QL_SIM_CARD_STATE_ABSENT;
+            p_info->app_3gpp.app_state = QL_SIM_APP_STATE_UNKNOWN;
+            p_info->app_3gpp.pin1_state = QL_SIM_PIN_STATE_UNKNOWN;
+            p_info->app_3gpp.pin2_state = QL_SIM_PIN_STATE_UNKNOWN;
+            break;
+        }
+        case MBTK_SIM_STATE_READY:                    //CARD READY
+        {
+            p_info->state = QL_SIM_CARD_STATE_PRESENT;
+            p_info->app_3gpp.app_state = QL_SIM_APP_STATE_READY;
+            if(pin_state == MBTK_PIN_ENABLE)
+            {
+                p_info->app_3gpp.pin1_state = QL_SIM_PIN_STATE_ENABLED_VERIFIED;
+            }
+            else
+            {
+                p_info->app_3gpp.pin1_state = QL_SIM_PIN_STATE_DISABLED;
+            }
+            p_info->app_3gpp.pin2_state = QL_SIM_PIN_STATE_UNKNOWN;
+            break;
+        }
+        case MBTK_SIM_STATE_SIM_PIN:                      //SIM PIN
+        {
+            p_info->state = QL_SIM_CARD_STATE_PRESENT;
+            p_info->app_3gpp.app_state = QL_SIM_APP_STATE_PIN1_REQ;
+            if(pin_state == MBTK_PIN_ENABLE)
+            {
+                p_info->app_3gpp.pin1_state = QL_SIM_PIN_STATE_ENABLED_NOT_VERIFIED;
+            }
+            else
+            {
+                p_info->app_3gpp.pin1_state = QL_SIM_PIN_STATE_DISABLED;
+            }
+            p_info->app_3gpp.pin2_state = QL_SIM_PIN_STATE_UNKNOWN;
+            break;
+        }
+        case MBTK_SIM_STATE_SIM_PUK:                      //SIM PUK
+        {
+            p_info->state = QL_SIM_CARD_STATE_PRESENT;
+            p_info->app_3gpp.app_state = QL_SIM_APP_STATE_PUK1_REQ;
+            if(pin_state == MBTK_PIN_ENABLE)
+            {
+                p_info->app_3gpp.pin1_state = QL_SIM_PIN_STATE_BLOCKED;
+            }
+            else
+            {
+                p_info->app_3gpp.pin1_state = QL_SIM_PIN_STATE_DISABLED;
+            }
+            p_info->app_3gpp.pin2_state = QL_SIM_PIN_STATE_UNKNOWN;
+            break;
+        }
+        case MBTK_SIM_STATE_PH_NET_PIN:  //NETWORK PERSON PIN
+        {
+            p_info->state = QL_SIM_CARD_STATE_PRESENT;
+            p_info->app_3gpp.app_state = QL_SIM_APP_STATE_UNKNOWN;
+            if(pin_state == MBTK_PIN_ENABLE)
+            {
+                p_info->app_3gpp.pin1_state = QL_SIM_PIN_STATE_ENABLED_NOT_VERIFIED;
+            }
+            else
+            {
+                p_info->app_3gpp.pin1_state = QL_SIM_PIN_STATE_DISABLED;
+            }
+            p_info->app_3gpp.pin2_state = QL_SIM_PIN_STATE_UNKNOWN;
+            break;
+        }
+        case MBTK_SIM_STATE_NOT_READY:                //UNKNOWN STATE
+        default:
+        {
+            p_info->state = QL_SIM_CARD_STATE_UNKNOWN;
+            p_info->app_3gpp.app_state = QL_SIM_APP_STATE_UNKNOWN;
+            p_info->app_3gpp.pin1_state = QL_SIM_PIN_STATE_UNKNOWN;
+            p_info->app_3gpp.pin2_state = QL_SIM_PIN_STATE_UNKNOWN;
+            break;
+        }
+    }
+
+    switch(sim_card_type)
+    {
+        case MBTK_SIM:
+        case MBTK_TEST_SIM:
+        {
+            p_info->type = QL_SIM_CARD_TYPE_ICC;
+            break;
+        }
+        case MBTK_USIM:
+        case MBTK_TEST_USIM:
+        {
+            p_info->type = QL_SIM_CARD_TYPE_UICC;
+            break;
+        }
+        default:
+        {
+            p_info->type = QL_SIM_CARD_TYPE_UNKNOWN;
+            break;
+        }
+    }
+
+    p_info->app_3gpp.pin1_num_retries = sim_last_times.p1_retry;
+    p_info->app_3gpp.puk1_num_retries = sim_last_times.puk1_retry;
+    p_info->app_3gpp.pin2_num_retries = sim_last_times.p2_retry;
+    p_info->app_3gpp.puk2_num_retries = sim_last_times.puk2_retry;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Reads data from a specific file on a specified application on the card.
+  @param [in] slot Slot to be used.
+  @param [in] app_type Application type.
+  @param [inout] p_file Pointer of ql_sim_file_t.
+  @return Whether the file was successfully read.
+  @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_sim_read_file(QL_SIM_SLOT_E slot, QL_SIM_APP_TYPE_E app_type, ql_sim_file_t *p_file)
+{
+    UNUSED(slot);
+    UNUSED(app_type);
+    UNUSED(p_file);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Writes data to a specific file on a specified application on the card.
+  @param [in] slot Slot to be used.
+  @param [in] app_type Application type.
+  @param [in] p_file Pointer of ql_sim_file_t
+  @note The type of file is determined by the record number field,
+    which indicates a transparent file when zero and a record-based file otherwise.
+  @return Whether the file was successfully written.
+  @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_sim_write_file(QL_SIM_SLOT_E slot, QL_SIM_APP_TYPE_E app_type, ql_sim_file_t *p_file)
+{
+    UNUSED(slot);
+    UNUSED(app_type);
+    UNUSED(p_file);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Retrieves the info of a specific file on a specified application on the card.
+  @param [in] slot Slot to be used.
+  @param [in] app_type Application type.
+  @param [inout] p_info Pointer of ql_sim_file_info_t.
+  @return Whether the file info was successfully retrieved.
+  @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_sim_get_file_info(QL_SIM_SLOT_E slot, QL_SIM_APP_TYPE_E app_type,
+                                 ql_sim_file_info_t *p_info)
+{
+    UNUSED(slot);
+    UNUSED(app_type);
+    UNUSED(p_info);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Reads phone book on a specified application on the card.
+  @param [in] slot Slot to be used.
+  @param [in] app_type Spplication type.
+  @param [in] pb_path Phone book path. NULL terminated.
+  @param [in] record_idx Record index to read. Starts from 1.
+  @param [out] p_record Pointer of ql_sim_phone_book_record_t.
+  @return Whether the phone book record was successfully retrieved.
+  @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_sim_read_phone_book(QL_SIM_SLOT_E slot, QL_SIM_APP_TYPE_E app_type,
+                                    const char *pb_path, uint8_t record_idx,
+                                    ql_sim_phone_book_record_t *p_record)
+{
+    UNUSED(slot);
+    UNUSED(app_type);
+    UNUSED(pb_path);
+    UNUSED(record_idx);
+    UNUSED(p_record);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Writes phone book on a specified application on the card.
+  @param [in] slot Slot to be used.
+  @param [in] app_type Application type.
+  @param [in] pb_path Phone book path. NULL terminated.
+  @param [in] record_idx Record index to write. Starts from 1.
+  @param [in] p_record Pointer of ql_sim_phone_book_record_t.
+  @note If p_record->name[0] = 0 and p_record->number[0] = 0, record will be deleted.
+  @return Whether the phone book record was successfully saved.
+  @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_sim_write_phone_book(QL_SIM_SLOT_E slot, QL_SIM_APP_TYPE_E app_type,
+                                    const char *pb_path, uint8_t record_idx,
+                                    ql_sim_phone_book_record_t *p_record)
+{
+    UNUSED(slot);
+    UNUSED(app_type);
+    UNUSED(pb_path);
+    UNUSED(record_idx);
+    UNUSED(p_record);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Opens a logical channel on a UICC card.
+  @param [in] slot Slot to be used.
+  @param [out] channel_id Channel opened.
+  @return Whether the logical channel was successfully opened.
+  @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_sim_open_logical_channel(QL_SIM_SLOT_E slot, uint8_t *channel_id)
+{
+    UNUSED(slot);
+    UNUSED(channel_id);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Closes a logical channel on a UICC card.
+  @param [in] slot Slot to be used.
+  @param [in] channel_id Channel to be closed.
+  @return Whether the logical channel was successfully closed.
+  @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_sim_close_logical_channel(QL_SIM_SLOT_E slot, uint8_t channel_id)
+{
+    UNUSED(slot);
+    UNUSED(channel_id);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Sends an APDU to the card.
+  @param [in] slot Slot to be used.
+  @param [in] channel_id Channel to be used.
+  @param [inout] p_apdu Pointer of ql_sim_apdu_t.
+  @note You must call ql_sim_open_logical_channel before sending an APDU.
+  @return Whether the APDU was successfully sent.
+  @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_sim_send_apdu(QL_SIM_SLOT_E slot, uint8_t channel_id, ql_sim_apdu_t *p_apdu)
+{
+    UNUSED(slot);
+    UNUSED(channel_id);
+    UNUSED(p_apdu);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Sets SIM card status callback handler
+  @param[in] cb call back handler.
+  @return Whether the card status callback handler was successfully set.
+  @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_sim_set_card_status_cb(ql_sim_card_status_cb_f cb)
+{
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    int ret = QL_ERR_OK;
+    if(NULL != cb)
+    {
+        ret = ql_cb_thread_creat(sim_handle);
+        if(ret != QL_ERR_OK)
+        {
+            QL_SIM_LOGE("[%s] cb thread creat fail.", __func__);
+        }
+    }
+    else
+    {
+        ret = ql_cb_thread_free(sim_handle);
+        if(ret != QL_ERR_OK)
+        {
+            QL_SIM_LOGE("[%s] cb thread free deinit fail.", __func__);
+            return QL_ERR_FAILED;
+        }
+    }
+    sim_handle->status_cb = cb;
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Switches slot.
+  @param [in] log_slot Logical slot to be switched.
+  @param [in] phy_slot Physical slot to be switched.
+  @return Whether the slot was successfully switched.
+  @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_sim_switch_slot(QL_SIM_SLOT_E log_slot, QL_SIM_PHY_SLOT_E phy_slot)
+{
+    UNUSED(log_slot);
+    UNUSED(phy_slot);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Gets active slots.
+  @param [Out] p_active_slots Active slots.
+  @return Whether the active slots were successfully obtained.
+  @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_sim_get_active_slots(ql_sim_active_slots_t *p_active_slots)
+{
+    UNUSED(p_active_slots);
+
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @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_sim_set_service_error_cb(ql_sim_service_error_cb_f cb)
+{
+    if(NULL == sim_handle)
+    {
+        QL_SIM_LOGE("[%s] sim handle not init.", __func__);
+        return QL_ERR_NOT_INIT;
+    }
+
+    sim_handle->server_cb = cb;
+
+    return QL_ERR_OK;
+}
+
+//int ql_sim_switch_slot(QL_SIM_SLOT_E log_slot, QL_SIM_PHY_SLOT_E phy_slot);
+//int ql_sim_get_active_slots(ql_sim_active_slots_t *p_active_slots);
+/*----------------------------------------------SIM API------------------------------------------*/
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_sleep_wakelock.c b/mbtk/libql_lib_v2_rilv2/ql_sleep_wakelock.c
new file mode 100755
index 0000000..622e028
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_sleep_wakelock.c
@@ -0,0 +1,86 @@
+#include <stddef.h>
+#include "ql_sleep_wakelock.h"
+#include "mbtk_sleep.h"
+#include "mbtk_log.h"
+
+/*
+ * create wakelock, return the file description of the wakelock
+ */
+int ql_slp_wakelock_create(const char *name, size_t len)
+{
+    int ret;
+
+    ret = mbtk_wakelock_create(name, len);
+    if (ret == -1)
+    {
+        LOGE("mbtk_wakelock_create is error");
+    }
+
+    return ret;
+}
+
+/*
+ * lock the wakelock by the file description of the wakelock
+ */
+int ql_slp_wakelock_lock(int fd)
+{
+    int ret;
+
+    ret = mbtk_wakelock_lock(fd);
+    if (ret == -1)
+    {
+        LOGE("ql_slp_wakelock_lock is error");
+    }
+
+    return ret;
+}
+
+/*
+ * unlock the wakelock by the file description of the wakelock
+ */
+int ql_slp_wakelock_unlock(int fd)
+{
+    int ret;
+
+    ret = mbtk_wakelock_unlock(fd);
+    if (ret == -1)
+    {
+        LOGE("ql_slp_wakelock_unlock is error");
+    }
+
+    return ret;
+}
+
+/*
+ * destroy the wakelock by the file description of the wakelock
+ */
+int ql_slp_wakelock_destroy(int fd)
+{
+    int ret;
+
+    ret = mbtk_wakelock_destroy(fd);
+    if (ret == -1)
+    {
+        LOGE("ql_slp_wakelock_destroy is error");
+    }
+
+    return ret;
+}
+
+/*
+ * Enable/Disable autosleep function
+ */
+int ql_autosleep_enable(char enable)
+{
+    int ret;
+
+    ret = mbtk_autosuspend_enable(enable);
+    if (ret == -1)
+    {
+        LOGE("ql_autosleep_enable is error");
+    }
+
+    return ret;
+}
+
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_sms.c b/mbtk/libql_lib_v2_rilv2/ql_sms.c
new file mode 100755
index 0000000..7323949
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_sms.c
@@ -0,0 +1,660 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_sms.h
+  @brief SMS 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
+  --------   ---          ----------------------------------------------------------
+  20200107   solomon.cui      Add GSM-7bit and ISO 8859-1 conversion.
+  20191225   solomon.cui      Modify fucntion description.
+  20191017   solomon.cui      Free async reponse not user data.
+  20190815   solomon.cui      Add service type for sending message.
+  20190627   solomon.cui      Support asynchronously send msg and pdu
+  20190625   solomon.cui      Convert timestamp frome hex to dec.
+  20190614   solomon.cui      Created .
+-------------------------------------------------------------------------------------------------*/
+#include "mbtk_type.h"
+#include "mbtk_pdu_sms.h"
+#include "mbtk_ril_api.h"
+#include "mbtk_log.h"
+#include "ql_sms.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
+#define TELEPHONE_NUM_MAX 16
+#define MSM_NUMBER_MAX 2048+1
+#define RES_NUM_MIN 128
+#define TIME_ZONE_CN 32
+#define HAL_SMS_CONTENT_LEN 1024
+
+typedef struct {
+    mbtk_ril_handle*       handle;
+    ql_sms_msg_recv_cb_f      recv_cb;
+    ql_sms_service_error_cb_f server_cb;
+}ql_sms_info_handle_t;
+
+
+static ql_sms_info_handle_t* sms_handle = NULL;
+
+static void ql_sms_state_change_cb(const void* data, int data_len)
+{
+    LOGV("sms_state_change_cb()----------start\n");
+    mbtk_ril_sms_state_info_t *ptr = (mbtk_ril_sms_state_info_t *)data;
+
+    ql_sms_msg_t    sms_msg;
+    ql_sms_timestamp_t  sms_timestamp;
+    ql_sms_user_data_head_t sms_user_data_head;
+
+    memset(&sms_msg,0x00, sizeof(ql_sms_msg_t));
+    memset(&sms_timestamp,0x00, sizeof(ql_sms_timestamp_t));
+    memset(&sms_user_data_head,0x00, sizeof(ql_sms_user_data_head_t));
+
+    char smsc[MDAPI_MAX_PDU_SIZE] = {0};
+    char received_pdu[MDAPI_MAX_PDU_SIZE] = {0};
+    char msg[MDAPI_MAX_PDU_SIZE] = {0};
+    char num[MDAPI_MAX_PDU_SIZE] = {0};
+    uint8 year[8]   = {0};
+    uint8 month[4]  = {0};
+    uint8 day[4]    = {0};
+    uint8 hour[4]   = {0};
+    uint8 minutes[4]= {0};
+    uint8 seconds[4]= {0};
+    //char timezone[4] = {0};
+    char date[32] = {0};
+    int charset = 0;
+    int ret = -1;
+    int curr_pack = 1;
+    int total_pack = 1;
+    if(ptr == NULL)
+    {
+        LOGE("ptr is null");
+    }
+    LOGE("ptr: %s\n,data_len = %d\n", (char *)ptr->pdu, data_len);
+    if(data_len > MDAPI_MAX_PDU_SIZE)
+    {
+        strncpy(received_pdu, (const char *)ptr->pdu, MDAPI_MAX_PDU_SIZE-1);
+    }
+    else
+    {
+        strncpy(received_pdu, (const char *)ptr->pdu, data_len);
+    }
+    ret = smsPduDecode((const char *)received_pdu, data_len, num, smsc, msg, &charset, &curr_pack, &total_pack,date);
+    if(ret != 0)
+    {
+        LOGE("smsPduDecode fail ret: %d\n",ret);
+        return ;
+    }
+
+    LOGE("[EVENT][MT_SMS]PDU decode:smsc: %s\n, phone number: %s\ncharset: %d\n msg_len: %d\n message content: %s\n curr_pack: %d\n total_pack: %d\n date: %s", smsc, num, charset, strlen(msg), msg, curr_pack, total_pack, date);
+
+    sms_msg.format = charset;
+    memcpy(sms_msg.addr, num, strlen(num));
+    sms_msg.content_size = strlen(msg);
+    memcpy(sms_msg.content, msg, strlen(msg));
+
+    if(sscanf(date, "%4[^-]-%2[^-]-%2[^ ] %2[^:]:%2[^:]:%2s", year, month, day, hour, minutes, seconds)<=0)
+    {
+        LOGE("sscanf failed\n");
+    }
+
+    int tmp_year = atoi((char *)year);
+ 
+    sms_timestamp.year = tmp_year-2000;
+    sms_timestamp.month = atoi((char *)month);
+    sms_timestamp.day = atoi((char *)day);
+    sms_timestamp.hours = atoi((char *)hour);
+    sms_timestamp.minutes = atoi((char *)minutes);
+    sms_timestamp.seconds = atoi((char *)seconds);
+    sms_timestamp.timezone = TIME_ZONE_CN;
+
+    LOGE("Year: %d\n", sms_timestamp.year);
+    LOGE("Month: %d\n", sms_timestamp.month);
+    LOGE("Day: %d\n", sms_timestamp.day);
+    LOGE("Hour: %d\n", sms_timestamp.hours);
+    LOGE("Minute: %d\n", sms_timestamp.minutes);
+    LOGE("Second: %d\n", sms_timestamp.seconds);
+  
+    if(total_pack > 1 && curr_pack < total_pack)
+    {
+        sms_user_data_head.valid = TRUE;
+        sms_user_data_head.total_seg = total_pack;
+        sms_user_data_head.cur_seg_num = curr_pack;
+    }
+    else
+    {
+        sms_user_data_head.valid = FALSE;
+        sms_user_data_head.total_seg = total_pack;
+        sms_user_data_head.cur_seg_num = curr_pack;
+    }
+
+    if(sms_handle->recv_cb)
+    {
+          sms_handle->recv_cb(&sms_msg, &sms_timestamp, &sms_user_data_head);
+    }
+
+}
+
+static void ql_sms_server_change_cb(const void* data, int data_len)
+{
+    if(data_len != sizeof(int))
+    {
+        LOGE("[ql_sms_server_change_cb] data_len[%d] than int[%d] fail. ", data_len, sizeof(int));
+    }
+    else
+    {
+        int server_state = *(int *)data;
+        if(server_state == 1 && sms_handle->server_cb)
+        {
+            sms_handle->server_cb(QL_ERR_ABORTED);
+        }
+    }
+}
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Initializes SMS service.
+  @return Whether the SMS service was initialized successfully.
+  @retval QL_ERR_OK successful.
+  @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_sms_init(void)
+{
+    if(NULL == sms_handle)
+    {
+        sms_handle = (ql_sms_info_handle_t*)malloc(sizeof(ql_sms_info_handle_t));
+        if(NULL == sms_handle)
+        {
+            LOGE("[ql_sms_init] sms handle malloc fail.");
+            return QL_ERR_FAILED;
+        }
+
+        sms_handle->handle = mbtk_ril_open(MBTK_AT_PORT_DEF);
+        if(NULL == sms_handle->handle)
+        {
+            LOGE("[ql_sms_init] mbtk handle init fail.");
+            if(sms_handle)
+            {
+                free(sms_handle);
+                sms_handle = NULL;
+                return QL_ERR_FAILED;
+            }
+        }
+
+        int err = mbtk_sms_cnmi_set(sms_handle->handle);
+        if(err)
+        {
+            LOGE("set cnmi fail");
+            return QL_ERR_FAILED;
+        }
+
+        int ret = mbtk_sms_state_change_cb_reg( ql_sms_state_change_cb);
+        if(ret != MBTK_ERR_OK)
+        {
+            LOGE("[ql_sms_init] set sms state cb fail.[%d]", ret);
+             if(sms_handle->handle)
+            {
+                mbtk_ril_close(MBTK_AT_PORT_DEF);
+                sms_handle->handle = NULL;
+                return QL_ERR_FAILED;
+            }
+        }
+
+        ret = mbtk_net_reg_state_change_cb_reg(ql_sms_server_change_cb);
+        if(ret != MBTK_ERR_OK)
+        {
+            LOGE("[ql_sim_init] set sim server cb fail.[%d]", ret);
+             if(sms_handle->handle)
+            {
+                mbtk_ril_close(MBTK_AT_PORT_DEF);
+                sms_handle->handle = NULL;
+                return QL_ERR_FAILED;
+            }
+        }
+
+        sms_handle->recv_cb = NULL;
+        sms_handle->server_cb = NULL;
+    }
+
+    return QL_ERR_OK;
+
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Deinitializes SMS service.
+  @return Whether the SMS service was deinitialized successfully.
+  @retval QL_ERR_OK successful.
+  @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_sms_deinit(void)
+{
+     if(NULL == sms_handle)
+    {
+        LOGE("[ql_sms_deinit] sms handle not init.");
+        return QL_ERR_NOT_INIT;
+    }
+
+    int ret = 0;
+    sms_handle->server_cb = NULL;
+    sms_handle->recv_cb = NULL;
+
+    if(NULL != sms_handle->handle)
+    {
+        ret = mbtk_ril_close(MBTK_AT_PORT_DEF);
+        if(ret != MBTK_ERR_OK)
+        {
+            LOGE("[ql_sms_deinit] mbtk handle deinit fail.[%d]", ret);
+            return QL_ERR_FAILED;
+        }
+        sms_handle->handle = NULL;
+    }
+
+    if(ret != QL_ERR_OK)
+    {
+        LOGE("[ql_sms_deinit] cb thread free deinit fail.");
+        return QL_ERR_FAILED;
+    }
+
+    free(sms_handle);
+    sms_handle = NULL;
+    return QL_ERR_OK;
+
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Sets the service center address.
+  @param[in] addr service center address.
+  @param[in] len  service center address length.
+  @return Whether the service center address was set 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_sms_set_service_center_addr(char *addr, int len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Gets the service center address.
+  @param[out] addr service center address.
+  @param[in] len  service center address length.
+  @return Whether the service center address 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_sms_get_service_center_addr(char *addr, int len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Sends message synchronously.
+  @param[in] p_msg pointer to ql_sms_msg_t.
+  @return Whether the message was successfully sent synchronously.
+  @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_sms_send_msg(ql_sms_msg_t *p_msg);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Sends message asynchronously.
+  @param[in] p_msg  pointer to ql_sms_msg_t
+  @param[out] id    id for this async operation
+  @param[in] cb     async callback
+  @return Whether the message was successfully sent asynchronously.
+  @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_sms_send_msg_async(ql_sms_msg_t *p_msg, int *id, ql_sms_msg_async_cb_f cb)
+{
+    if (NULL == sms_handle)
+    {
+        LOGE("handle NULL");
+        return QL_ERR_FAILED;
+    }
+
+    if (NULL == p_msg)
+    {
+        LOGE("p_msgt NULL");
+        return QL_ERR_FAILED;
+    }
+
+    if(NULL == id)
+    {
+        LOGE("id NULL");
+        return QL_ERR_FAILED;
+    }
+
+    int8 *phone_num = NULL;
+    int8 *msg = NULL;
+	int32 msg_len;
+
+    char cmgs[MSM_NUMBER_MAX] = {0};
+    char resp[RES_NUM_MIN] = {0};
+
+    char smscPDU[30] = {0};
+    char **pdu = NULL;
+    char smsc[4] = {0};
+    char msg_e_b[HAL_SMS_CONTENT_LEN] = {0};// +1 for end of string.*2:A char array contains two elements of a string for each value
+
+    int char_set = 0;
+    //int lsms_flag = 0;
+    int err = 0;
+    int i = 0;
+
+    msg = (int8 *)p_msg->content;
+
+    msg_len = strlen(p_msg->content);
+
+    phone_num = (int8 *)p_msg->addr;
+
+    if (p_msg->format == 0)//7
+        char_set = 0;
+    else if (p_msg->format == 1)//8
+        char_set = 1;
+    else if (p_msg->format == 2)//UCS2
+        char_set = 2;
+    else
+    {
+        LOGE("ql_sms_send_msg_async format error");
+        return QL_ERR_FAILED;
+    }
+
+    if(strcmp((char*)msg,"") == 0 || msg[0] == '\0')
+    {
+        LOGE("ql_sms_send_msg_async msg [%s]",msg);
+        return QL_ERR_FAILED;
+    }
+
+    if(strcmp((char*)phone_num,"") == 0 || phone_num[0] == '\0')
+    {
+        LOGE("ql_sms_send_msg_async phone_num [%s]",phone_num);
+        return QL_ERR_FAILED;
+    }
+
+    kal_int32 msg_num = 0;
+    kal_int32 pdu_msg_len = 0;
+    kal_int32 status = MDAPI_RET_ERROR;
+    kal_int32 index = 0;
+
+    if(char_set == 1) //8bit
+    {
+        ArrayToStr((unsigned char *)msg, (unsigned int)msg_len, msg_e_b);
+        status = _mdapi_sms_get_msg_num(msg_e_b, char_set, &msg_num, &pdu_msg_len);
+    }
+    else //7bit usc2
+    {
+        status = _mdapi_sms_get_msg_num((char *)msg, char_set, &msg_num, &pdu_msg_len);
+    }
+    
+    LOGE("msg_len = [%d] ,msg_num=[%d]",msg_len, msg_num);
+    if(status == MDAPI_RET_ERROR)
+    {
+        LOGE("get message number failed");
+        return QL_ERR_FAILED;
+    }
+    else
+    {        
+        //allocate memery for **pdu
+        pdu = (char **)malloc(sizeof(char *) * msg_num);
+        if(pdu == NULL)
+        {
+            LOGE("allocate memory for pdu failed");
+            return QL_ERR_FAILED;
+        }
+        else
+        {
+            for(index = 0; index < msg_num; index++)
+            {
+                pdu[index] = (char *)malloc(sizeof(char)*MAX_PDU_SIZE);
+                if(pdu[index] == NULL)
+                {
+                    for(i = 0; i < index; i++)
+                    {
+                        free(pdu[i]);
+                        pdu[i] = NULL;
+                    }
+                    free(pdu);
+                    pdu = NULL;
+                    LOGE("allocate memory for pdu[%d] failed",index);
+                    return QL_ERR_FAILED;
+                }
+                else
+                {
+                    memset(pdu[index], 0, MAX_PDU_SIZE);
+                    LOGE("pdu[%d} init value is: %s ",index, pdu[index]);
+                }
+            }
+        }
+    }
+
+    //allocate memory for **pdu success
+    if(index == msg_num)
+    {
+        if(char_set == 1)//8bit
+        {
+            smsPduEncode(smsc, (char *)phone_num, msg_e_b, char_set, smscPDU, pdu);
+        }
+        else
+        {
+            smsPduEncode(smsc, (char *)phone_num, (char *)msg, char_set, smscPDU, pdu);
+        }
+        for(index = 0; index < msg_num; index++)
+        {
+            char pdu_data[MAX_PDU_SIZE] = {0};
+            char *p = pdu_data;
+
+            LOGE("index:%d",index);
+            LOGE("smscPDU: %s, pdu: %s",smscPDU, pdu[index]);
+            sprintf(p, "%s",smscPDU);
+            LOGE("pdu_data:%s\n", pdu_data);
+            int sc = strlen(pdu_data);
+            sprintf(p+strlen(p), "%s", pdu[index]);
+            LOGE("pdu_data:%s", pdu_data);
+
+            int t = strlen(pdu_data);
+            sprintf(cmgs, "%d,%s", (t-sc)/2, pdu_data);
+            LOGE("cmgs:%s\n", cmgs);
+            memset(resp, 0, sizeof(resp));
+
+            err = mbtk_sms_cmgf_set(sms_handle->handle, 0);
+            if(err)
+            {
+                LOGE("cmgf set error : %d", err);
+                for(index = 0; index < msg_num; index++){
+                    free(pdu[index]);
+                    pdu[index] = NULL;
+                }
+                free(pdu);
+                pdu = NULL;
+                return QL_ERR_FAILED;
+            }
+            else
+            {
+                LOGD("cmgf set success");
+            }
+
+            err = mbtk_sms_cmgs_set(sms_handle->handle, cmgs, resp);
+            if(err)
+            {
+                LOGE("cmgs send fail (%d)",err);
+                for(index = 0; index < msg_num; index++){
+                    free(pdu[index]);
+                    pdu[index] = NULL;
+                }
+                free(pdu);
+                pdu = NULL;
+                return QL_ERR_FAILED;
+            }
+            else
+            {
+                LOGD("cmgs send success, resp:%s", resp);
+            }
+
+        }
+    }
+
+    for(index = 0; index < msg_num; index++){
+        free(pdu[index]);
+        pdu[index] = NULL;
+    }
+    free(pdu);
+    pdu = NULL;
+
+    *id = 1;
+    cb(1, 1);
+
+    return QL_ERR_OK;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Sets SMS message reception callback hanlder.
+  @param[in] cb message reception callback handler.
+  @return Whether the message reception callback hanlder was set 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_sms_set_msg_recv_cb(ql_sms_msg_recv_cb_f cb)
+{
+    if(NULL == sms_handle)
+    {
+        LOGE("[ql_sms_set_msg_recv_cb] sms handle not init.");
+        return QL_ERR_NOT_INIT;
+    }
+
+    sms_handle->recv_cb = cb;
+
+    return QL_ERR_OK;
+
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Sends PDU synchronously.
+  @param[in] p_pdu SMS PDU.
+  @return Whether the PDU was successfully sent synchronously.
+  @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_sms_send_pdu(ql_sms_pdu_t *p_pdu);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Sends PDU asynchronously.
+  @param[in] p_pdu sms pdu.
+  @param[out] id id for this async operation.
+  @param[in] cb async callback.
+  @return Whether the PDU was successfully sent asynchronously.
+  @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_sms_send_pdu_async(ql_sms_pdu_t *p_pdu, int *id, ql_sms_pdu_async_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Sets SMS PDU reception callback hanlder.
+  @param[in] cb PDU reception callback handler.
+  @return Whether the PDU reception callback hanlder was set 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_sms_set_pdu_recv_cb(ql_sms_pdu_recv_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_sms_set_service_error_cb(ql_sms_service_error_cb_f cb)
+{
+    if(NULL == sms_handle)
+    {
+        LOGE("[ql_sms_set_service_error_cb] sms handle not init.");
+        return QL_ERR_NOT_INIT;
+    }
+
+    sms_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_sms_bind_subscription(QL_SMS_SUBSCRIPTION_E sub);
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_test_utils.c b/mbtk/libql_lib_v2_rilv2/ql_test_utils.c
new file mode 100755
index 0000000..b28f3cd
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_test_utils.c
@@ -0,0 +1,330 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file test_utils.c 
+  @brief Test related interface definition
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  Copyright (c) 2018 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
+  --------   ---          ----------------------------------------------------------
+  20190508   tyler.kuang  Created .
+-------------------------------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include "ql_test_utils.h"
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Read a int value from stdin 
+  @param[out] val, Return read data
+  @return 
+  0 - successful
+  1 - read an enter 
+  -1 - invalid input
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int t_get_int(int *val)
+{
+    int dat;
+    char *ptr_end = NULL;
+    char buf[256] = {0};
+
+    if(NULL == fgets(buf, sizeof(buf)-1, stdin))
+    {
+        return -1;
+    }
+    
+    if(0 == buf[0])
+    {
+        return -1;
+    }
+
+    if(buf[0] == '\n')
+    {
+        return 1;
+    }
+
+    dat = strtol(buf, &ptr_end, 10);
+    if(ptr_end!=NULL && ptr_end[0]!='\n')
+    {
+        return -1;
+    }
+
+    if(val)
+    {
+        val[0] = dat;
+    }
+
+    return 0;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Read a uint32 value from stdin 
+  @param[out] val, Return read data
+  @return 
+  0 - successful
+  1 - read an enter 
+  -1 - invalid input
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int t_get_hex(uint32_t *val)
+{
+    int dat;
+    char *ptr_end = NULL;
+    char buf[256] = {0};
+
+    if(fgets(buf, sizeof(buf)-1, stdin) == NULL)
+    {
+        return -1;
+    }
+    
+    if(0 == buf[0])
+    {
+        return -1;
+    }
+
+    if(buf[0] == '\n')
+    {
+        return 1;
+    }
+
+    dat = strtol(buf, &ptr_end, 16);
+    if(ptr_end!=NULL && ptr_end[0]!='\n')
+    {
+        return -1;
+    }
+
+    if(val)
+    {
+        val[0] = dat;
+    }
+
+    return 0;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Read a char value from stdin 
+  @param[out] val, Return read data
+  @return 
+  0 - successful
+  1 - read an enter 
+  -1 - invalid input
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int t_get_char(int *val)
+{
+    char buf[256] = {0};
+
+    if(fgets(buf, sizeof(buf)-1, stdin) == NULL)
+    {
+        return -1;
+    }
+    
+    if(0 == buf[0])
+    {
+        return -1;
+    }
+
+    if(buf[0] == '\n')
+    {
+        return 1;
+    }
+
+    if(buf[1]!='\n')
+    {
+        return -1;
+    }
+
+    if(val)
+    {
+        val[0] = buf[0];
+    }
+
+    return 0;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Read a string value from stdin 
+  @param[out] val, Return read data
+  @return 
+  0 - successful
+  1 - read an enter 
+  -1 - invalid input
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int t_get_string(char *str_buf, int str_len)
+{
+    char *ptr;
+    char buf[256] = {0};
+
+    if(fgets(buf, sizeof(buf)-1, stdin) == NULL)
+    {
+        return -1;
+    }
+    
+    if(0 == buf[0])
+    {
+        return -1;
+    }
+
+    if(buf[0] == '\n')
+    {
+        return 1;
+    }
+    
+    ptr = strchr(buf, '\n');
+    if(ptr)
+    {
+        ptr[0] = 0;
+    }
+    
+    strncpy(str_buf, buf, str_len-1);
+    
+    return 0;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Read a list of int values from stdin 
+  @param[out] val, Return read datas
+  @param[out&in] val, Input buffer length, output the number of read
+  @return 
+  0 - successful
+  1 - read an enter 
+  -1 - invalid input
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int t_get_int_list(int *dat_buf, int *dat_len)
+{
+    int idx = 0;
+    int len;
+    int dat;
+    char *ptr, *ptr_save;
+    char *ptr_end;
+    char buf[256] = {0};
+
+    if(!dat_buf || !dat_len)
+    {
+        return -1;
+    }
+
+    len = dat_len[0];
+
+    if(fgets(buf, sizeof(buf)-1, stdin) == NULL)
+    {
+        return -1;
+    }
+
+    if(0 == buf[0])
+    {
+        return -1;
+    }
+
+    if(buf[0] == '\n')
+    {
+        return 1;
+    }
+
+    for(ptr=strtok_r(buf, ",.: \t\r\n", &ptr_save); 
+            ptr!=NULL;
+            ptr=strtok_r(NULL, ",.: \t\r\n", &ptr_save))
+    {
+        dat = strtol(ptr, &ptr_end, 10);
+        if(ptr_end!=NULL && ptr_end[0]!=0)
+        {
+            return -1;
+        }
+        if(idx >= len)
+        {
+            return 0;
+        }
+
+        dat_buf[idx] = dat;
+        idx++;
+    }
+    
+    dat_len[0] = idx;
+    return 0;
+}
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @brief Read a list of float values from stdin 
+  @param[out] val, Return read datas
+  @param[out&in] val, Input buffer length, output the number of read
+  @return 
+  0 - successful
+  1 - read an enter 
+  -1 - invalid input
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int t_get_float_list(float *dat_buf, int *dat_len)
+{
+    int idx = 0;
+    int len;
+    float dat;
+    char *ptr, *ptr_save;
+    char *ptr_end;
+    char buf[256] = {0};
+
+    if(!dat_buf || !dat_len)
+    {
+        return -1;
+    }
+
+    len = dat_len[0];
+
+    if(fgets(buf, sizeof(buf)-1, stdin) == NULL)
+    {
+        return -1;
+    }
+
+    if(0 == buf[0])
+    {
+        return -1;
+    }
+
+    if(buf[0] == '\n')
+    {
+        return 1;
+    }
+
+    for(ptr=strtok_r(buf, ",: \t\r\n", &ptr_save); 
+            ptr!=NULL;
+            ptr=strtok_r(NULL, ",: \t\r\n", &ptr_save))
+    {
+        dat = strtof(ptr, &ptr_end);
+        if(ptr_end!=NULL && ptr_end[0]!=0)
+        {
+            return -1;
+        }
+        if(idx >= len)
+        {
+            return 0;
+        }
+
+        dat_buf[idx] = dat;
+        idx++;
+    }
+    
+    dat_len[0] = idx;
+    return 0;
+}
+
+
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);
+
+
diff --git a/mbtk/libql_lib_v2_rilv2/ql_wifi.c b/mbtk/libql_lib_v2_rilv2/ql_wifi.c
new file mode 100755
index 0000000..90c6424
--- /dev/null
+++ b/mbtk/libql_lib_v2_rilv2/ql_wifi.c
@@ -0,0 +1,1172 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_wifi.h
+  @brief  Wi-Fi service API
+
+  @detailes
+  Quectel  series module Wi-Fi service.
+
+  @htmlonly
+  <span style="font-weight: bold">History</span>
+  @endhtmlonly
+
+  when       |   who       |    what, where, why
+  --------   |   ---       |    ----------------------------------------------------------
+  2020-04-03 |   ewen.li   |    Created .
+  2021-11-08 |   ewen.li   |    Add Wi-Fi P2P API and callback function .
+
+  Copyright (c) 2019 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
+  Quectel Wireless Solution Proprietary and Confidential.
+-------------------------------------------------------------------------------------------------*/
+#ifndef __QL_WIFI_H__
+#define __QL_WIFI_H__
+
+#include "ql_wifi_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Wi-Fi enable status callback function.
+
+  @param[in]  pre_status: The previous Wi-Fi enable status.
+  @param[in]  status: The current Wi-Fi enable status.
+
+  @retval  void
+  */
+/*-----------------------------------------------------------------------------------------------*/
+typedef void (*ql_wifi_enable_status_ind_cb_f)(QL_WIFI_ENABLE_STATUS_E pre_status, QL_WIFI_ENABLE_STATUS_E status);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  AP mode status callback function.
+
+  @param[in]  pre_status: The previous AP mode status.
+  @param[in]  p_msg: The current AP mode status information.
+
+  @retval  void
+  */
+/*-----------------------------------------------------------------------------------------------*/
+typedef void (*ql_wifi_ap_status_ind_cb_f)(QL_WIFI_AP_INDEX_E index, QL_WIFI_AP_STATUS_E pre_status, ql_wifi_ap_status_t *p_msg);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  STA mode status callback function.
+
+  @param[in]  pre_status: The previous STA mode status.
+  @param[in]  p_msg: The current STA mode status information.
+
+  @retval  void
+  */
+/*-----------------------------------------------------------------------------------------------*/
+typedef void (*ql_wifi_sta_status_ind_cb_f)(QL_WIFI_STA_STATUS_E pre_status, ql_wifi_sta_status_t *p_msg);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  STA scan results callback function.
+
+  @param[in]  p_msg: The information list of external hotspots.
+
+  @retval  void
+  */
+/*-----------------------------------------------------------------------------------------------*/
+typedef void (*ql_wifi_sta_scan_result_ind_cb_f)(ql_wifi_sta_scan_result_t *p_msg);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This is a callback function for status of connection between AP and STA device.
+
+  @param[in]  index: The index of AP mode.
+  @param[in]  p_msg: The status of connection between AP and STA device.
+
+  @retval  void
+  */
+/*-----------------------------------------------------------------------------------------------*/
+typedef void (*ql_wifi_ap_sta_connect_ind_cb_f)(QL_WIFI_AP_INDEX_E index, ql_wifi_sta_connect_status_t *p_msg);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Wi-Fi service error callback function.
+
+  @param[in]  error: Error code.
+
+  @retval  void
+  */
+/*-----------------------------------------------------------------------------------------------*/
+typedef void (*ql_wifi_service_error_cb_f)(int error);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This is a callback function for status of P2P enable.
+
+  @param[in]  pre_status: The previous P2P enable status.
+  @param[in]  status: The current P2P enable status.
+
+  @retval  void
+  */
+/*-----------------------------------------------------------------------------------------------*/
+typedef void (*ql_wifi_p2p_enable_status_ind_cb_f)(QL_WIFI_P2P_ENABLE_STATUS_E pre_status, QL_WIFI_P2P_ENABLE_STATUS_E status);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  The found p2p device callback function.
+
+  @param[in]  p_msg: The information of p2p device 
+
+  @retval  void
+  */
+/*-----------------------------------------------------------------------------------------------*/
+typedef void (*ql_wifi_p2p_dev_found_ind_cb_f)(ql_wifi_p2p_found_dev_info_t *p_msg);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  Peer p2p device requesting connection callback function.
+
+  @param[in]  p_msg: The information of peer p2p device 
+
+  @retval  void
+  */
+/*-----------------------------------------------------------------------------------------------*/
+typedef void (*ql_wifi_p2p_peer_dev_req_ind_cb_f)(ql_wifi_p2p_req_peer_dev_info_t *pmsg);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  P2P status callback function.
+
+  @param[in]  pre_status: The previous P2P status.
+  @param[in]  status: The current P2P status information.
+
+  @retval  void
+  */
+/*-----------------------------------------------------------------------------------------------*/
+typedef void (*ql_wifi_p2p_status_ind_cb_f)(QL_WIFI_P2P_STATUS_E pre_status, ql_wifi_p2p_status_t *p_msg);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function initializes Wi-Fi service.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_SERVICE_NOT_READY: Wi-Fi service is not ready. It is recommended to try again.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+
+  @note  Before other Wi-Fi APIs are used, this function must be called to initialize the Wi-Fi service.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_init(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function deinitializes Wi-Fi service.
+
+  @retval  QL_ERR_OK: Successful execution.
+           Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_deinit(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the country code of wlan driver
+
+  @param[in]  country_code: The country code to be set. The country code cannot exceed 2 bytes and is not empty. For example,  CN represents China.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+
+  @note  Before calling the ql_wifi_enable(), call this function firstly to set country code,
+         If this function is not called, The country code "CN" will be used by default.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_country_code_set(const char *country_code);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the country code of wlan driver.
+
+  @param[out]  country_code_buf: The buffer for storing the current country code. The buffer size is recommended to be 3 bytes.
+  @param[in]   The length of buffer.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_country_code_get(char *country_code_buf, int buf_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function enables Wi-Fi function.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_enable(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function disables Wi-Fi function.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_disable(void);
+
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function set bridge function.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_set_bridge(char *bridge);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function registers Wi-Fi enable status callback function.
+
+  @param[in]  cb: The Wi-Fi enable status callback function.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_set_enable_status_ind_cb(ql_wifi_enable_status_ind_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the Wi-Fi working mode.
+
+  @param[in]  mode: The Wi-Fi working mode to be set.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_work_mode_set(QL_WIFI_WORK_MODE_E mode);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the current Wi-Fi working mode.
+
+  @param[out]  p_mode: The current Wi-Fi working mode.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_work_mode_get(QL_WIFI_WORK_MODE_E *p_mode);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the SSID in AP mode.
+
+  @param[in]  idx: The index of AP mode.
+  @param[in]  ssid: The SSID to be set. It should be within 32 bytes and is not empty.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_ssid_set(QL_WIFI_AP_INDEX_E idx, const char *ssid);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the SSID in AP mode.
+
+  @param[in]   idx: The index of AP mode.
+  @param[out]  ssid_buf: The buffer for storing the current SSID, the buffer size is recommended to be 33 bytes.
+  @param[in]   buf_len: The length of the buffer.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_ssid_get(QL_WIFI_AP_INDEX_E idx, char *ssid_buf, int buf_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the SSID hiding status in AP mode.
+
+  @param[in]  idx: The index of AP mode.
+  @param[in]  ssid_hidden: The SSID hiding status to be set.
+                           0: The SSID is not hidden.
+                           1: The SSID is hidden.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_ssid_hidden_set(QL_WIFI_AP_INDEX_E idx, int ssid_hidden);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the SSID hiding status in AP mode.
+
+  @param[in]  idx: The index of AP mode.
+  @param[out]  p_ssid_hidden: The current SSID hiding status in AP mode.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_ssid_hidden_get(QL_WIFI_AP_INDEX_E idx, int *p_ssid_hidden);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the working protocol mode in AP mode.
+
+  @param[in]  idx: The index of AP mode.
+  @param[in]  mode: The working protocol mode to be set.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_mode_set(QL_WIFI_AP_INDEX_E idx, QL_WIFI_AP_MODE_TYPE_E mode);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the working protocol mode in AP mode.
+
+  @param[in]   idx: The index of AP mode.
+  @param[out]  p_mode: The current working protocol mode in AP mode.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_mode_get(QL_WIFI_AP_INDEX_E idx, QL_WIFI_AP_MODE_TYPE_E *p_mode);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the bandwidth in AP mode.
+
+  @param[in]  idx: The index of AP mode.
+  @param[in]  bandwidth: The bandwidth to be set.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_bandwidth_set(QL_WIFI_AP_INDEX_E idx, QL_WIFI_BANDWIDTH_E bandwidth);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the bandwidth in AP mode.
+
+  @param[in]   idx: The index of AP mode.
+  @param[out]  p_bandwidth: The current bandwidth in AP mode.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_bandwidth_get(QL_WIFI_AP_INDEX_E idx, QL_WIFI_BANDWIDTH_E *p_bandwidth);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the channel in AP mode.
+
+  @param[in]  idx: The index of AP mode.
+  @param[in]  channel: The channel to be set.
+                       0: Adaptive
+                       1/2/3/4/5/6/7/8/9/10/11/12/13/14: 2.4G channel.
+                       36/40/44/48/52/56/60/64/100/104/108/112/116/120/124/128/132/136/140/144/149/153/157/161/165: 5GHZ channel.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_channel_set(QL_WIFI_AP_INDEX_E idx, int channel);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the channel in AP mode.
+
+  @param[in]  idx: The index of AP mode.
+  @param[out]  p_channel: The currently-used channel in AP mode.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_channel_get(QL_WIFI_AP_INDEX_E idx, int *p_channel);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the maximum number of terminal connections in AP mode.
+
+  @param[in]  idx: The index of AP mode.
+  @param[in]  max_sta_num: The maximum number of terminal connections in AP mode to be set. Range: 1~32.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_max_sta_num_set(QL_WIFI_AP_INDEX_E idx, int max_sta_num);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the maximum number of terminal connections in AP mode.
+
+  @param[in]  idx: The index of AP mode.
+  @param[out]  p_max_sta_num: The current maximum number of terminal connections in AP mode.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_max_sta_num_get(QL_WIFI_AP_INDEX_E idx, int *p_max_sta_num);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the country code in AP mode.
+
+  @param[in]  idx: The index of AP mode.
+  @param[in]  country_code: The country code to be set. The country code cannot exceed 2 bytes and is not empty. For example,  CN represents China.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_country_code_set(QL_WIFI_AP_INDEX_E idx, const char *country_code);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the country code in AP mode.
+
+  @param[in]   idx: The index of AP mode.
+  @param[out]  country_code_buf: The buffer for storing the current country code. The buffer size is recommended to be 3 bytes.
+  @param[in]   The length of buffer.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_country_code_get(QL_WIFI_AP_INDEX_E idx, char *country_code_buf, int buf_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the AP isolation state.
+
+  @param[in]  idx: The index of AP mode.
+  @param[in]  isolate: AP isolation status to be set.
+                       0: AP is not isolated.
+                       1: AP is isolated.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_isolate_set(QL_WIFI_AP_INDEX_E idx, int isolate);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the AP isolation state.
+
+  @param[in]   idx: The index of AP mode.
+  @param[out]  p_isolate: The current AP isolation status.
+                          0: AP is not isolated.
+                          1: AP is isolated.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_isolate_get(QL_WIFI_AP_INDEX_E idx, int *p_isolate);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets MAC address access rules in AP mode.
+
+  @param[in]  idx: The index of AP mode.
+  @param[in]  acl_rule: MAC address access rules to be set.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_mac_acl_rule_set(QL_WIFI_AP_INDEX_E idx, QL_WIFI_MAC_ACL_RULE_E acl_rule);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets MAC address access rules in AP mode.
+
+  @param[in]   idx: The index of AP mode.
+  @param[out]  p_acl_rule: The current MAC address access rules.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_mac_acl_rule_get(QL_WIFI_AP_INDEX_E idx, QL_WIFI_MAC_ACL_RULE_E *p_acl_rule);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function adds or deletes the specified MAC address for the current MAC address access rule.
+
+  @param[in]  idx: The index of AP mode.
+  @param[in]  cmd: MAC address operation command.
+  @param[in]  macaddr: MAC address to be added or deleted., The format of MAC address 
+                       must be %02X:%02X:%02X:%02X:%02X:%02X, For example: 1A:2B:3C:4D:56:78.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_acl_mac_set(QL_WIFI_AP_INDEX_E idx, QL_WIFI_ACL_MAC_CMD_E cmd, const char *macaddr);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets all MAC addresses in the current MAC address access rule.
+
+  @param[in]   idx: The index of AP mode.
+  @param[out]  p_mac_list: MAC address list.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_acl_mac_get(QL_WIFI_AP_INDEX_E idx, ql_wifi_acl_mac_list_t *p_mac_list);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the authentication in AP mode.
+
+  @param[in]  idx: The index of AP mode.
+  @param[in]  p_auth: The authentication information to be set.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_auth_set(QL_WIFI_AP_INDEX_E idx, ql_wifi_ap_auth_t *p_auth);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the authentication information in AP mode.
+
+  @param[in]   idx: The index of AP mode.
+  @param[out]  p_auth: The current authentication information.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_auth_get(QL_WIFI_AP_INDEX_E idx, ql_wifi_ap_auth_t *p_auth);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function registers the AP mode status callback function.
+
+  @param[in]  cb: The AP mode status callback function.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_set_status_ind_cb(ql_wifi_ap_status_ind_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function starts the AP function.
+
+  @param[in]  index: The index of AP mode.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_start(QL_WIFI_AP_INDEX_E index);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function stops the AP function.
+
+  @param[in]  index: The index of AP mode.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_stop(QL_WIFI_AP_INDEX_E index);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the AP mode status information.
+
+  @param[in]   index: The index of AP mode.
+  @param[out]  p_sta: The current AP mode status information.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_ap_get_status(QL_WIFI_AP_INDEX_E index, ql_wifi_ap_status_t *p_sta);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the SSID in STA mode.
+
+  @param[in]  ssid: The SSID to be set. The SSID cannot exceed 32 bytes and is not empty.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_sta_ssid_set(const char *ssid);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the SSID in STA mode.
+
+  @param[out]  ssid_buf: The buffer for storing the current SSID.
+  @param[in]   buf_len: The length of the buffer.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_sta_ssid_get(char *ssid_buf, int buf_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the authentication in STA mode.
+
+  @param[in]  p_auth: The authentication information to be set.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_sta_auth_set(ql_wifi_sta_auth_t *p_auth);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the authentication information in STA mode.
+
+  @param[out]  p_auth: The current authentication information.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_sta_auth_get(ql_wifi_sta_auth_t *p_auth);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function registers the STA mode status callback function.
+
+  @param[in]  cb: The STA mode status callback function.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_sta_set_status_ind_cb(ql_wifi_sta_status_ind_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function starts the STA function.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_sta_start(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function stops the STA function.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_sta_stop(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the STA mode status information.
+
+  @param[out]  p_sta: The current STA mode status information.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_sta_get_status(ql_wifi_sta_status_t *p_sta);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function scans for external hotspots in STA mode.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_sta_start_scan(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function registers the scan result callback function.
+
+  @param[in]  cb: The scan result callback function.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_sta_set_scan_result_ind_cb(ql_wifi_sta_scan_result_ind_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function registers the callback function for status of connection between AP and STA device.
+
+  @param[in]  cb: The callback function for status of connection between AP and STA device.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_set_ap_sta_connect_ind_cb(ql_wifi_ap_sta_connect_ind_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function registers the Wi-Fi service error callback function.
+
+  @param[in]  cb: Wi-Fi service error callback function, executed only when the Wi-Fi service exits abnormally.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_set_service_error_cb(ql_wifi_service_error_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the P2P device name.
+
+  @param[in]  dev_name: The device name to be set.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_dev_name_set(const char *dev_name);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the P2P device name.
+
+  @param[out]  dev_name_buf: The buffer for storing the current device name.
+  @param[in]   buf_len: The length of the buffer.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_dev_name_get(char *dev_name_buf, int buf_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the P2P device type.
+
+  @param[in]  dev_type: The device type to be set.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_dev_type_set(const char *dev_type);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the P2P device type.
+
+  @param[out]  dev_type_buf: The buffer for storing the current device type.
+  @param[in]   buf_len: The length of the buffer.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_dev_type_get(char *dev_type_buf, int buf_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the operating class and operating channel in P2P mode.
+
+  @param[in]  oper_class:   The operating class to be set.
+  @param[in]  oper_channel: The operating channel to be set.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+
+  @note  The operating class and operating channel can determine the center frequency,
+         The following are the corresponding values.
+     --------------------------------------------------------------------------------------------
+     |  oper_class  |       oper_channel        |          frequency          | channel spacing |
+     |-------------------------------------------------------------------------------------------
+     |      81      |           1-13            |   2407 + 5 * oper_channel   |      25MHz      |
+     |      82      |            14             |   2414 + 5 * oper_channel   |      25MHz      |
+     |      115     |        36,40,44,48        |   5000 + 5 * oper_channel   |      20MHz      |
+     |      116     |           36,44           |   5000 + 5 * oper_channel   |      40MHz      |
+     |      117     |           40,48           |   5000 + 5 * oper_channel   |      40MHz      |
+     |      124     |     149,153,157,161       |   5000 + 5 * oper_channel   |      20MHz      |
+     |      125     |    149,153,157,161,165    |   5000 + 5 * oper_channel   |      20MHz      |
+     |      126     |          149,157          |   5000 + 5 * oper_channel   |      40MHz      |
+     |      127     |          153,161          |   5000 + 5 * oper_channel   |      40MHz      |
+     --------------------------------------------------------------------------------------------
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_oper_class_channel_set(int oper_class, int oper_channel);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the operating class and operating channel in P2P mode.
+
+  @param[out]  p_oper_class:   The currently-used operating class in p2p mode.
+  @param[out]  p_oper_channel: The currently-used operating channel in p2p mode.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_oper_class_channel_get(int *p_oper_class, int *p_oper_channel);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function sets the suffix of ssid.
+
+  @param[in]  ssid_postfix: The suffix of ssid to be set.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_ssid_postfix_set(const char *ssid_postfix);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets the suffix of ssid.
+
+  @param[out]  ssid_postfix_buf: The buffer for storing the current suffix of ssid.
+  @param[in]   buf_len: The length of the buffer.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_ssid_postfix_get(char *ssid_postfix_buf, int buf_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function registers the P2P enable status callback function.
+
+  @param[in]  cb: P2P enable status callback function.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_set_enable_status_ind_cb(ql_wifi_p2p_enable_status_ind_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function enables P2P function.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_enable(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function disables P2P function.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_disable(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function registers the found p2p device callback function.
+
+  @param[in]  cb: The found p2p device callback function.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_set_dev_found_ind_cb(ql_wifi_p2p_dev_found_ind_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function start finding P2P device.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_dev_find_start(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function stop finding P2P device.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_dev_find_stop(void);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function gets P2P mode status information.
+
+  @param[out]  p_status: The current P2P mode status information.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_get_status(ql_wifi_p2p_status_t *p_status);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function registers the P2P status callback function.
+
+  @param[in]  cb: The P2P status callback function.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_set_status_ind_cb(ql_wifi_p2p_status_ind_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function registers peer p2p device requesting connection callback function.
+
+  @param[in]  cb: Peer p2p device requesting connection callback function.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_set_peer_dev_req_ind_cb(ql_wifi_p2p_peer_dev_req_ind_cb_f cb);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function establishes a P2P connection.
+
+  @param[in]  macaddr: The MAC address of peer P2P device.
+  @param[in]  wps_method: key words: "pbc", "pin" and pin_code, The pin_code is a string that 
+                          dynamically generated random from peer display.
+  @param[in]  go_intent: Degree of desire to be GO, range: 0-15.
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  QL_ERR_INVALID_ARG: Failed execution due to illegal parameter.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_connect(const char *macaddr, const char *method, int go_intent);
+
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @brief  This function disconnects a P2P connection
+
+  @retval  QL_ERR_OK: Successful execution.
+  @retval  QL_ERR_NOT_INIT: Failed execution. The Wi-Fi service is not initialized.
+  @retval  QL_ERR_SERVICE_ABORT: Failed execution due to Wi-Fi service error.
+  @retval  Other value: Failed execution. See ql_type.h for the error code.
+  */
+/*-----------------------------------------------------------------------------------------------*/
+int ql_wifi_p2p_disconnect(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+