Add basic change for v1453

Change-Id: I9497a61bbc3717f66413794a4e7dee0347c0bc33
diff --git a/mbtk/test/libql_lib_v2/Makefile b/mbtk/test/libql_lib_v2/Makefile
new file mode 100755
index 0000000..401a563
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/Makefile
@@ -0,0 +1,34 @@
+BUILD_ROOT = $(shell pwd)/../..
+include $(BUILD_ROOT)/Make.defines
+
+INC_DIR +=
+
+LIB_DIR +=
+
+LIBS += -lmbtk_lib -lql_lib
+
+CFLAGS = $(CFLAGS_TEST)
+
+DEFINE +=
+
+LOCAL_SRC_FILES = $(wildcard *.c) $(wildcard *.cpp)
+
+$(info LOCAL_SRC_FILES = $(LOCAL_SRC_FILES))
+
+OBJS = $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(LOCAL_SRC_FILES)))
+BINS = $(patsubst %.o,%,$(OBJS))
+
+all: $(BINS)
+
+$(BINS):$(OBJS)
+	@echo "  BIN     $@"
+	$(CC) $(CFLAGS) $(LIB_DIR) $(LIBS) $@.o -o $(OUT_DIR)/bin/$@
+
+%.o:%.c
+	$(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+%.o:%.cpp
+	$(CC) $(CFLAGS) $(INC_DIR) $(DEFINE) -c $< -o $@
+
+clean:
+	rm -f $(OBJS)
diff --git a/mbtk/test/libql_lib_v2/ql_adc_test.c b/mbtk/test/libql_lib_v2/ql_adc_test.c
new file mode 100755
index 0000000..d82a5b9
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_adc_test.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include "ql_adc.h"
+
+int main(int argc, char *argv[])
+{
+    if(argc != 2) {
+        printf("ql_adc_test <0/1/2>\n");
+        return -1;
+    }
+
+    int adc = atoi(argv[1]);
+    if(adc != 0 && adc != 1 && adc != 2) {
+        printf("ql_adc_test <0/1/2>\n");
+        return -1;
+    }
+
+    int result = ql_adc_show((ADC_CHANNEL_E)(adc + 1));
+
+    printf("ADC : %d\n", result);
+
+    return 0;
+}
+
diff --git a/mbtk/test/libql_lib_v2/ql_atc_test.c b/mbtk/test/libql_lib_v2/ql_atc_test.c
new file mode 100755
index 0000000..47c00ac
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_atc_test.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include "ql_atc.h"
+
+
+int main(int argc, char *argv[])
+{
+    if(argc != 2) {
+        printf("ql_atc_test <at>\n");
+        return -1;
+    }
+
+    if(ql_atc_init()) {
+        printf("ql_atc_init() fail.\n");
+        return -1;
+    }
+
+    char resp[1024];
+    if(ql_atc_send(argv[1], resp, sizeof(resp))) {
+        printf("ql_atc_send() fail.\n");
+        return -1;
+    }
+
+    if(ql_atc_deinit()) {
+        printf("ql_atc_deinit() fail.\n");
+        return -1;
+    }
+
+    printf("RSP : %s\n", resp);
+
+    return 0;
+}
diff --git a/mbtk/test/libql_lib_v2/ql_audio_test.c b/mbtk/test/libql_lib_v2/ql_audio_test.c
new file mode 100755
index 0000000..1944fb5
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_audio_test.c
@@ -0,0 +1,541 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file m_audio.c
+  @brief audio API example
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  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
+  --------     ---          ----------------------------------------------------------
+  2021-11-03   dameng.lin      Create.
+-------------------------------------------------------------------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include "ql_v2/ql_type.h"
+#include "ql_v2/ql_audio_pcm.h"
+#include "ql_v2/ql_audio_cfg.h"
+#include "ql_v2/ql_test_utils.h"
+
+typedef void (*show_handler_f)(void);
+
+typedef struct
+{
+    const char *name;
+    show_handler_f handle;
+}audio_show_t;
+
+typedef struct
+{
+    int playback_dest;
+    int block_flag;
+    char file_name[128];
+}audio_playback_info_t;
+
+static ql_audio_handle_t g_playback_handle = QL_AUDIO_INVALID_HANDLE;
+static int g_playback_end = 0;
+
+
+void item_ql_audio_init(void)
+{
+    int ret = 0;
+
+    printf("test ql_audio_init: ");
+    ret = ql_audio_init();
+    if(QL_ERR_OK != ret)
+    {
+        printf("Failed to init audio service, ret = %d\n", ret);
+    }
+    else
+    {
+        printf("Success to init audio service\n");
+    }
+}
+
+static void audio_service_error_cb_func(int error)
+{
+    printf("===== Audio Service Abort ===== error = %d\n",error);
+}
+
+static void item_ql_audio_set_service_error_cb(void)
+{
+    int ret = QL_ERR_OK;
+
+    printf("test ql_audio_set_service_error_cb: \n");
+    ret = ql_audio_set_service_error_cb(audio_service_error_cb_func);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_audio_set_service_error_cb, ret=%d\n", ret);
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+}
+
+static void item_ql_audio_set_loopback_enable_state(void)
+{
+    int ret = QL_ERR_OK;
+    int loopback_enable_state = 0;
+
+    printf("test ql_audio_set_loopback_enable_state: \n");
+    printf("please enter the loopback enable state(0-1): ");
+    ret = t_get_int(&loopback_enable_state);
+    if(ret != 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    ret = ql_audio_set_loopback_enable_state(loopback_enable_state);
+    if (QL_ERR_OK != ret)
+    {
+        printf("Failed to set loopback enable state, ret = %d\n", ret);
+    }
+    else
+    {
+        printf("Success to set loopback enable state\n");
+    }
+}
+
+static void item_ql_audio_get_loopback_enable_state(void)
+{
+    int ret = QL_ERR_OK;
+    int32_t loopback_enable_state = 0;
+
+    printf("test ql_audio_get_loopback_enable_state: \n");
+
+    ret = ql_audio_get_loopback_enable_state(&loopback_enable_state);
+    if (QL_ERR_OK != ret)
+    {
+        printf("Failed to get loopback enable state, ret = %d\n", ret);
+    }
+    else
+    {
+        printf("Success to get loopback enable state, loopback_enable_state = %d\n", loopback_enable_state);
+    }
+}
+
+
+static void item_ql_audio_set_tx_voice_mic_gain(void)
+{
+    int ret = QL_ERR_OK;
+    int tx_voice_mic_gain = 0;
+
+    printf("test ql_audio_set_tx_voice_mic_gain: \n");
+    printf("please enter the tx voice mic gain(0-65535): ");
+    ret = t_get_int(&tx_voice_mic_gain);
+    if(ret != 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    ret = ql_audio_set_tx_voice_mic_gain(tx_voice_mic_gain);
+    if (QL_ERR_OK != ret)
+    {
+        printf("Failed to set tx voice mic gain, ret = %d\n", ret);
+    }
+    else
+    {
+        printf("Success to set tx voice mic gain\n");
+    }
+}
+
+static void item_ql_audio_get_tx_voice_mic_gain(void)
+{
+    int ret = QL_ERR_OK;
+    int32_t tx_voice_mic_gain = 0;
+
+    printf("test ql_audio_get_tx_voice_mic_gain: \n");
+
+    ret = ql_audio_get_tx_voice_mic_gain(&tx_voice_mic_gain);
+    if (QL_ERR_OK != ret)
+    {
+        printf("Failed to get tx voice mic gain, ret = %d\n", ret);
+    }
+    else
+    {
+        printf("Success to get tx voice mic gain, tx_voice_mic_gain = %d\n", tx_voice_mic_gain);
+    }
+}
+
+static void item_ql_audio_set_codec_down_vol(void)
+{
+    int ret = QL_ERR_OK;
+    int down_volume = 0;
+
+    printf("test ql_audio_set_codec_down_vol: \n");
+    printf("please enter the codec down volume(0-100): ");
+    ret = t_get_int(&down_volume);
+    if(ret != 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    ret = ql_audio_set_codec_down_vol(down_volume);
+    if (QL_ERR_OK != ret)
+    {
+        printf("Failed to set codec down volume, ret = %d\n", ret);
+    }
+    else
+    {
+        printf("Success to set codec down volume\n");
+    }
+}
+
+static void item_ql_audio_get_codec_down_vol(void)
+{
+    int ret = QL_ERR_OK;
+    int32_t down_volume = 0;
+
+    printf("test ql_audio_get_codec_down_vol: \n");
+
+    ret = ql_audio_get_codec_down_vol(&down_volume);
+    if (QL_ERR_OK != ret)
+    {
+        printf("Failed to get codec down volume, ret = %d\n", ret);
+    }
+    else
+    {
+        printf("Success to codec down volume, down_volume = %d\n", down_volume);
+    }
+}
+
+void item_ql_audio_deinit(void)
+{
+    int ret = 0;
+
+    printf("test ql_audio_deinit: ");
+    ret = ql_audio_deinit();
+    if(QL_ERR_OK != ret)
+    {
+        printf("Failed to deinit audio service, ret = %d\n", ret);
+    }
+    else
+    {
+        printf("Success to deinit audio service\n");
+    }
+}
+
+static int default_playback_state(ql_audio_handle_t handle, void *params, QL_AUDIO_PLAYBACK_STATE_E state)
+{
+    int ret = 0;
+
+    switch(state)
+    {
+        case QL_AUDIO_PLAYBACK_STATE_OPEN:
+        {
+            printf("QL_AUDIO_PLAYBACK_STATE_OPEN\n");
+            break;
+        }
+        case QL_AUDIO_PLAYBACK_STATE_PREPARE:
+        {
+            printf("QL_AUDIO_PLAYBACK_STATE_PREPARE\n");
+            break;
+        }
+        case QL_AUDIO_PLAYBACK_STATE_PLAYING:
+        {
+            printf("QL_AUDIO_PLAYBACK_STATE_PLAYING\n");
+            break;
+        }
+        case QL_AUDIO_PLAYBACK_STATE_FINISHED:
+        {
+            printf("QL_AUDIO_PLAYBACK_STATE_FINISHED\n");
+            g_playback_end = 1;
+            break;
+        }
+        case QL_AUDIO_PLAYBACK_STATE_PAUSE:
+        {
+            printf("QL_AUDIO_PLAYBACK_STATE_PAUSE\n");
+            break;
+        }
+        case QL_AUDIO_PLAYBACK_STATE_ERROR:
+        {
+            printf("QL_AUDIO_PLAYBACK_STATE_ERROR\n");
+            g_playback_end = 1;
+            break;
+        }
+        default:
+        {
+            printf("INVALID PALYBACK STATE\n");
+            ret = -1;
+            break;
+        }
+    }
+
+    return ret;
+}
+
+static void *ql_audio_play_file_thread(void *args)
+{
+    int ret = QL_ERR_OK;
+    uint32_t be_dai_mask = 0;
+    ql_audio_handle_t handle = QL_AUDIO_INVALID_HANDLE;
+
+    audio_playback_info_t *playback_info = (audio_playback_info_t *)args;
+    if (NULL == playback_info)
+    {
+        printf("invalid params\n");
+        return NULL;
+    }
+
+    switch(playback_info->playback_dest)
+    {
+        case 0:
+        {
+            be_dai_mask = QL_AUDIO_BE_DAI_MASK_PLAYBACK_PRI_PCM;
+            break;
+        }
+        case 1:
+        {
+            be_dai_mask = QL_AUDIO_BE_DAI_MASK_PLAYBACK_VOICE_TX;
+            break;
+        }
+        case 2:
+        {
+            be_dai_mask = QL_AUDIO_BE_DAI_MASK_PLAYBACK_PRI_PCM | QL_AUDIO_BE_DAI_MASK_PLAYBACK_VOICE_TX;
+            break;
+        }
+        default:
+        {
+            printf("invalid playback destination\n");
+            free(playback_info);
+            playback_info = NULL;
+            return NULL;
+        }
+    }
+
+    handle = ql_audio_playback_open(QL_AUDIO_FE_PCM_DEV_MULTIMEDIA1, be_dai_mask);
+    if (QL_AUDIO_INVALID_HANDLE >= handle)
+    {
+        printf("Failed to open playback\n");
+        free(playback_info);
+        playback_info = NULL;
+        return NULL;
+    }
+
+    g_playback_handle = handle;
+
+    printf("playback handle = %d",g_playback_handle);
+    ql_audio_playback_set_block_flag(g_playback_handle, playback_info->block_flag);
+
+    ret = ql_audio_playback_file_prepare(g_playback_handle,
+                                         playback_info->file_name,
+                                         NULL,
+                                         default_playback_state,
+                                         NULL);
+    if (QL_ERR_OK != ret)
+    {
+        printf("Failed to prepare playback file\n");
+        free(playback_info);
+        playback_info = NULL;
+        ql_audio_playback_close(g_playback_handle);
+        return NULL;
+    }
+    printf("playback handle = %d",g_playback_handle);
+
+	ret = ql_audio_playback_play(g_playback_handle);
+    if (QL_ERR_OK != ret)
+    {
+        printf("Failed to play file\n");
+        free(playback_info);
+        playback_info = NULL;
+        ql_audio_playback_close(g_playback_handle);
+        return NULL;
+    }
+
+    while(0 == g_playback_end)
+    {
+        usleep(100 * 1000);
+    }
+
+    printf("End playing file\n");
+    ql_audio_playback_close(g_playback_handle);
+    g_playback_handle = QL_AUDIO_INVALID_HANDLE;
+    g_playback_end = 0;
+
+    free(playback_info);
+    playback_info = NULL;
+
+    return NULL;
+}
+
+static void item_ql_audio_playback_play_file(void)
+{
+    int ret = 0;
+    pthread_t thread_id;
+    pthread_attr_t thread_attr;
+    audio_playback_info_t *playback_info = NULL;
+
+    printf("test ql_audio_playback_play_file: \n");
+
+    playback_info = (audio_playback_info_t *)malloc(sizeof(audio_playback_info_t));
+    if (NULL == playback_info)
+    {
+        printf("Failed to malloc memory\n");
+        return;
+    }
+    memset(playback_info, 0, sizeof(audio_playback_info_t));
+
+    printf("please enter the file name: ");
+    ret = t_get_string(playback_info->file_name,sizeof(playback_info->file_name));
+    if(ret != 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    printf("please enter the playback destination(0-To pcm interface / 1-To voice / 2-To pcm interface and voice): ");
+    ret = t_get_int(&(playback_info->playback_dest));
+    if(ret != 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    printf("please enter the block flag(0-nonblock / 1-block): ");
+    ret = t_get_int(&(playback_info->block_flag));
+    if(ret != 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    pthread_attr_init(&thread_attr);
+    pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
+
+    ret = pthread_create(&thread_id, &thread_attr, ql_audio_play_file_thread, (void *)playback_info);
+    if (0 > ret)
+    {
+        printf("Failed to create play file thread, ret = %d, err = %s\n", ret, strerror(errno));
+    }
+
+    pthread_attr_destroy(&thread_attr);
+}
+
+
+static audio_show_t audio_show[] =
+{
+    { "ql_audio_init",                          item_ql_audio_init                         },
+    { "ql_audio_set_service_error_cb",          item_ql_audio_set_service_error_cb         },
+    { "ql_audio_set_loopback_enable_state",     item_ql_audio_set_loopback_enable_state    },
+    { "ql_audio_get_loopback_enable_state",     item_ql_audio_get_loopback_enable_state    },
+    { "ql_audio_set_tx_voice_mic_gain",         item_ql_audio_set_tx_voice_mic_gain        },
+    { "ql_audio_get_tx_voice_mic_gain",         item_ql_audio_get_tx_voice_mic_gain        },
+    { "ql_audio_set_codec_down_vol",            item_ql_audio_set_codec_down_vol           },
+    { "ql_audio_get_codec_down_vol",            item_ql_audio_get_codec_down_vol           },
+    { "ql_audio_playback_play_file",            item_ql_audio_playback_play_file           },
+    { "ql_audio_deinit",                        item_ql_audio_deinit                       }
+	
+};
+
+int audio_get_int(int *val)
+{
+    int dat;
+    char *ptr_end = NULL;
+    char buf[256] = {0};
+
+    if (NULL == val)
+    {   
+        return -1;
+    }
+
+    if (fgets(buf, sizeof(buf), stdin) == NULL)
+    {
+        return -1;
+    }
+
+    if('\0' == buf[0])
+    {
+        return -1;
+    }
+
+    if('\n' == buf[0])
+    {
+        return 1;
+    }
+
+    dat = strtol(buf, &ptr_end, 10); 
+    if((NULL != ptr_end) && ('\n' != ptr_end[0]))
+    {
+        return -1;
+    }
+
+    *val = dat;
+    return 0;
+}
+
+static void dump_audio_show(void)
+{
+    int i = 0;
+
+    for(i = 0; i < sizeof(audio_show)/sizeof(audio_show[0]); i++)
+    {
+        printf("%d\t%s\n", i, audio_show[i].name);
+    }
+    printf("-1\texit\n");
+}
+
+
+int main(int argc, char **argv)
+{
+    int ret = 0;
+    int index = 0;
+
+    dump_audio_show();
+
+    while (1)
+    {
+        printf("\n");
+        printf("Please enter your choice: ");
+        ret = audio_get_int(&index);
+        printf("\n");
+        if(ret < 0)
+        {
+            printf("Invalid input\n");
+            continue;
+        }
+        else if(ret == 1)
+        {
+            dump_audio_show();
+            continue;
+        }
+
+        if (index == -1)
+        {
+            break;
+        }
+
+        if ((index < 0) || (index >= sizeof(audio_show)/sizeof(audio_show[0])))
+        {
+            printf("Not support index: %d\n", index);
+            continue;
+        }
+
+        if (NULL != audio_show[index].handle)
+        {
+            audio_show[index].handle();
+        }
+    }
+
+    return 0;
+}
+
+
+
diff --git a/mbtk/test/libql_lib_v2/ql_data_call_main_apn_test.c b/mbtk/test/libql_lib_v2/ql_data_call_main_apn_test.c
new file mode 100755
index 0000000..8921f4f
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_data_call_main_apn_test.c
@@ -0,0 +1,250 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file main_apn.c
+  @brief Example how to set and get APN configuration
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  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
+  --------   ---          ----------------------------------------------------------
+  20190624   tyler.kuang  Created .
+-------------------------------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include "ql_type.h"
+#include "ql_data_call.h"
+
+const char *g_options_short = "a:n:v:f:u:p:sg";
+
+struct option g_options_long[] = {
+    {"set",        no_argument,          0,     's'},
+    {"get",        no_argument,          0,     'g'},
+    {"apn_id",     required_argument,    0,     'a'},
+    {"apn_name",   required_argument,    0,     'n'},
+    {"ip_ver",     required_argument,    0,     'v'},
+    {"auth_pref",  required_argument,    0,     'f'},
+    {"username",   required_argument,    0,     'u'},
+    {"password",   required_argument,    0,     'p'},
+    {NULL,         0,                    0,      0 }
+};
+
+#define USAGE_STRING "exec --[set|s]|[get|g], set or get apn configuration\r\n"\
+    "     --apn_id|a number, apn id, range:1-16\r\n"\
+    "     [--ip_ver|v number], ip vresion:4-IPV4,6-IPV6,10-IPV4V6\r\n"\
+    "     [--apn_name|n string], apn name\r\n"\
+    "     [--auth_pref|f number], auth pref:0-none,1-pap,2-chap,3-pan&chap\r\n"\
+    "     [--username|u string], \r\n"\
+    "     [--password|p string], auth pref:0-none,1-pap,2-chap,3-pan&chap\r\n"\
+    "exp : exec -g -a 1\r\n " \
+    "      exec -s -a 4 -v 4 -n test_apn -f 0 -u test_username -p test_password\r\n "
+
+
+void usage(void)
+{
+    printf("%s", USAGE_STRING);
+}
+
+
+int main(int argc, char *argv[])
+{
+    int c;
+    int dat;
+    int ret;
+    int opt_idx = 0;
+    int retry_cnt = 0;
+
+    int opt_type = -1; /*1-get 2-set*/
+    int apn_id = -1;
+    int ip_ver = QL_NET_IP_VER_V4;
+    int auth_pref = QL_NET_AUTH_PREF_PAP_CHAP_NOT_ALLOWED;
+    char apn_name[128] = {0};
+    char username[128] = {0};
+    char password[128] = {0};
+
+    ql_data_call_apn_config_t cfg;
+
+    while(1)
+    {
+        c = getopt_long(argc, argv, g_options_short, g_options_long, &opt_idx);
+        if(c==-1)
+        {
+            break;
+        }
+
+        switch(c) {
+            case 's':
+                opt_type = 2;
+                break;
+            case 'g':
+                opt_type = 1;
+                break;
+
+            case 'a':
+                apn_id = atoi(optarg);
+                if(apn_id<=0 || apn_id>QL_NET_MAX_APN_ID)
+                {
+                    printf("Invalid apn_id : %d\n", apn_id);
+                    return -1;
+                }
+
+                break;
+            case 'f':
+                dat = atoi(optarg);
+                switch(dat)
+                {
+                    case 0:
+                        auth_pref = QL_NET_AUTH_PREF_PAP_CHAP_NOT_ALLOWED;
+                        break;
+                    case 1:
+                        auth_pref = QL_NET_AUTH_PREF_PAP_ONLY_ALLOWED;
+                        break;
+                    case 2:
+                        auth_pref = QL_NET_AUTH_PREF_CHAP_ONLY_ALLOWED;
+                        break;
+                    case 3:
+                        auth_pref = QL_NET_AUTH_PREF_PAP_CHAP_BOTH_ALLOWED;
+                        break;
+                    default:
+                        printf("Invalid auth pref : %d\n", dat);
+                        return -1;
+                }
+                break;
+            case 'v':
+                dat = atoi(optarg);
+                if(4 == dat)
+                {
+                    ip_ver = QL_NET_IP_VER_V4;
+                }
+                else if(6 == dat)
+                {
+                    ip_ver = QL_NET_IP_VER_V6;
+                }
+                else if(10 == dat)
+                {
+                    ip_ver = QL_NET_IP_VER_V4V6;
+                }
+                else
+                {
+                    printf("Invalid ip_ver : %d\n", dat);
+                    return -1;
+                }
+                break;
+
+            case 'n':
+                strncpy(apn_name, optarg, sizeof(apn_name)-1);
+                break;
+
+            case 'u':
+                strncpy(username, optarg, sizeof(username)-1);
+                break;
+
+            case 'p':
+                strncpy(password, optarg, sizeof(password)-1);
+                break;
+
+            default:
+                usage();
+                return 0;
+        }
+    }
+
+    if(opt_type!=1 && opt_type!=2)
+    {
+        usage();
+        return 0;
+    }
+
+    if(apn_id<=0 || apn_id>QL_NET_MAX_APN_ID)
+    {
+        usage();
+        return 0;
+    }
+
+    retry_cnt = 20*1000/100; /** timeout : 20S */
+    while(retry_cnt>0)
+    {
+        ret = ql_data_call_init();
+        if(ret == QL_ERR_SERVICE_NOT_READY)
+        {
+            retry_cnt--;
+            usleep(100*1000); /** sleep 100ms */
+        }
+        break;
+    }
+
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_init, ret=%d", ret);
+        return -1;
+    }
+
+
+    /** get apn info */
+    if(opt_type == 1)
+    {
+        memset(&cfg, 0 ,sizeof(cfg));
+        ret = ql_data_call_get_apn_config(apn_id, &cfg);
+        if(ret != QL_ERR_OK)
+        {
+            printf("Failed to get apn configuration, ret=%d\n", ret);
+            return -1;
+        }
+        printf("Succeed to get apn configuration\n");
+        printf("apn_id     : %d\n", apn_id);
+        printf("ip_ver     : %d\n", cfg.ip_ver);
+        printf("auth_pref  : %d\n", cfg.auth_pref);
+        printf("apn_name   : %s\n", cfg.apn_name);
+        printf("username   : %s\n", cfg.username);
+        printf("password   : %s\n", cfg.password);
+    }
+    else
+    {
+        memset(&cfg, 0, sizeof(cfg));
+        cfg.ip_ver = ip_ver;
+        cfg.auth_pref = auth_pref;
+        strncpy(cfg.apn_name, apn_name, sizeof(cfg.apn_name)-1);
+        strncpy(cfg.username, username, sizeof(cfg.username)-1);
+        strncpy(cfg.password, password, sizeof(cfg.password)-1);
+
+        printf("Start to set apn configuration\n");
+        printf("apn_id     : %d\n", apn_id);
+        printf("ip_ver     : %d\n", cfg.ip_ver);
+        printf("auth_pref  : %d\n", cfg.auth_pref);
+        printf("apn_name   : %s\n", cfg.apn_name);
+        printf("username   : %s\n", cfg.username);
+        printf("password   : %s\n", cfg.password);
+
+        ret = ql_data_call_set_apn_config(apn_id, &cfg);
+        if(ret != QL_ERR_OK)
+        {
+            printf("Failed to set apn configuration, ret=%d\n", ret);
+            return -1;
+        }
+        printf("Succeed to set apn configuration\n");
+    }
+
+
+    return 0;
+}
+
diff --git a/mbtk/test/libql_lib_v2/ql_data_call_main_data_call_test.c b/mbtk/test/libql_lib_v2/ql_data_call_main_data_call_test.c
new file mode 100755
index 0000000..f6fb33d
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_data_call_main_data_call_test.c
@@ -0,0 +1,332 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file main_data_call.c
+  @brief Example how to data call 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
+  --------   ---          ----------------------------------------------------------
+  20190624   tyler.kuang  Created .
+-------------------------------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include "ql_type.h"
+#include "ql_data_call.h"
+
+const char *g_options_short = "i:n:a:v:r:dhd";
+
+struct option g_options_long[] = {
+    {"call_id",    required_argument,    0,     'i'},
+    {"call_name",  required_argument,    0,     'n'},
+    {"apn_id",     required_argument,    0,     'a'},
+    {"ip_ver",     required_argument,    0,     'v'},
+    {"reconnect",  required_argument,    0,     'r'},
+    {"default",    no_argument,          0,     'd'},
+    {"help",       no_argument,          0,     'h'},
+    {NULL,         0,                    0,      0 }
+};
+
+#define USAGE_STRING "exec --call_id|i,data call ID\r\n"\
+                     "     [--call_name|n], data call name\r\n"\
+                     "     --apn_id|a, APN ID, range:1-16\r\n"\
+                     "     [--ip_ver|v], IP vresion:4-IPV4,6-IPV6\r\n"\
+                     "     [--reconnect|r] reconnect interval in SEC\r\n"\
+                     "     [--default|d], set to system default network\r\n"\
+                     "exp : exec -a 1 -n test_network -i 4 -d\r\n "
+
+int g_is_default_network = 0;
+int g_call_id = -1;
+
+void usage(void)
+{
+    printf("%s", USAGE_STRING);
+}
+
+void data_call_status_ind_cb(int call_id,
+        QL_NET_DATA_CALL_STATUS_E pre_call_status,
+        ql_data_call_status_t *p_msg)
+{
+    FILE *fp;
+    char cmd_buf[256];
+
+    /** not for this data call */
+    if(call_id != g_call_id)
+    {
+        return;
+    }
+
+    printf("data call status change, form %d to %d\n", pre_call_status, p_msg->call_status);
+    if(p_msg->call_status == QL_NET_DATA_CALL_STATUS_CONNECTED)
+    {
+        printf("call_id     : %d\n", p_msg->call_id);
+        printf("call_name   : %s\n", p_msg->call_name);
+        printf("device_name : %s\n", p_msg->device);
+        if(p_msg->has_addr)
+        {
+            printf("IPV4 addr    : %s\n", p_msg->addr.addr);
+            printf("IPV4 gateway : %s\n", p_msg->addr.gateway);
+            printf("IPV4 netmask : %s\n", p_msg->addr.netmask);
+            printf("IPV4 dnsp    : %s\n", p_msg->addr.dnsp);
+            printf("IPV4 dnss    : %s\n", p_msg->addr.dnss);
+
+            if(g_is_default_network)
+            {
+                /** set system default router */
+                snprintf(cmd_buf, sizeof(cmd_buf), "ip ro add default via %s dev %s",
+                        p_msg->addr.gateway, p_msg->device);
+                system(cmd_buf);
+
+                system("iptables -t filter -F");
+
+                snprintf(cmd_buf, sizeof(cmd_buf), "iptables -t nat -A POSTROUTING -o %s -j MASQUERADE", p_msg->device);
+                system(cmd_buf);
+
+                /** set system dns configuration*/
+                fp = fopen("/tmp/resolv_v4.conf", "w");
+                if(!fp)
+                {
+                    printf("Failed to write resolv file, err=%s\n", strerror(errno));
+                    return;
+                }
+
+                if(p_msg->addr.dnsp[0])
+                {
+                    fprintf(fp, "nameserver %s\n", p_msg->addr.dnsp);
+                }
+
+                if(p_msg->addr.dnss[0])
+                {
+                    fprintf(fp, "nameserver %s\n", p_msg->addr.dnss);
+                }
+                fclose(fp);
+
+                system("echo \"\" > /etc/resolv.conf");
+                if(access("/tmp/resolv_v4.conf", F_OK) == 0)
+                {
+                    system("cat /tmp/resolv_v4.conf >> /etc/resolv.conf");
+                }
+                if(access("/tmp/resolv_v6.conf", F_OK) == 0)
+                {
+                    system("cat /tmp/resolv_v6.conf >> /etc/resolv.conf");
+                }
+            }
+        }
+
+        if(p_msg->has_addr6)
+        {
+            printf("IPV6 addr    : %s\n", p_msg->addr6.addr);
+            printf("IPV6 gateway : %s\n", p_msg->addr6.gateway);
+            printf("IPV6 netmask : %s\n", p_msg->addr6.prefix);
+            printf("IPV6 dnsp    : %s\n", p_msg->addr6.dnsp);
+            printf("IPV6 dnss    : %s\n", p_msg->addr6.dnss);
+
+            if(g_is_default_network)
+            {
+                /** set system default router */
+                snprintf(cmd_buf, sizeof(cmd_buf), "ip -6 ro add default via %s dev %s",
+                        p_msg->addr6.gateway, p_msg->device);
+                system(cmd_buf);
+
+                /** set system dns configuration*/
+                fp = fopen("/tmp/resolv_v6.conf", "w");
+                if(!fp)
+                {
+                    printf("Failed to write resolv file, err=%s\n", strerror(errno));
+                    return;
+                }
+
+                if(p_msg->addr6.dnsp[0])
+                {
+                    fprintf(fp, "nameserver %s\n", p_msg->addr6.dnsp);
+                }
+
+                if(p_msg->addr6.dnss[0])
+                {
+                    fprintf(fp, "nameserver %s\n", p_msg->addr6.dnss);
+                }
+                fclose(fp);
+
+                system("echo \"\" > /etc/resolv.conf");
+                if(access("/tmp/resolv_v4.conf", F_OK) == 0)
+                {
+                    system("cat /tmp/resolv_v4.conf >> /etc/resolv.conf");
+                }
+                if(access("/tmp/resolv_v6.conf", F_OK) == 0)
+                {
+                    system("cat /tmp/resolv_v6.conf >> /etc/resolv.conf");
+                }
+            }
+        }
+    }
+}
+
+
+int main(int argc, char *argv[])
+{
+    int c;
+    int dat;
+    int ret;
+    int opt_idx = 0;
+    int retry_cnt = 0;
+
+    ql_data_call_param_t *p_cfg;
+    int reconnect_interval = 0;
+    int apn_id = -1;
+    int ip_ver = QL_NET_IP_VER_V4;
+    char call_name[128] = "test_network";
+
+    while(1)
+    {
+        c = getopt_long(argc, argv, g_options_short, g_options_long, &opt_idx);
+        if(c==-1)
+        {
+            break;
+        }
+
+        switch(c) {
+            case 'i':
+                g_call_id = atoi(optarg);
+                if(g_call_id < 0)
+                {
+                    printf("Invalid call id : %d", g_call_id);
+                    return -1;
+                }
+                break;
+
+            case 'r':
+                reconnect_interval = atoi(optarg);
+                if(reconnect_interval<=0)
+                {
+                    printf("Invalid reconnect interval : %d\n", reconnect_interval);
+                    return -1;
+                }
+                break;
+
+            case 'n':
+                strncpy(call_name, optarg, sizeof(call_name)-1);
+                break;
+
+            case 'a':
+                apn_id = atoi(optarg);
+                if(apn_id<=0 || apn_id>QL_NET_MAX_APN_ID)
+                {
+                    printf("Invalid apn_id : %d\n", apn_id);
+                    return -1;
+                }
+
+                break;
+            case 'v':
+                dat = atoi(optarg);
+                if(4 == dat)
+                {
+                    ip_ver = QL_NET_IP_VER_V4;
+                }
+                else if(6 == dat)
+                {
+                    ip_ver = QL_NET_IP_VER_V6;
+                }
+                else
+                {
+                    printf("Invalid ip_ver : %d\n", dat);
+                    return -1;
+                }
+                break;
+
+            case 'd':
+                g_is_default_network = 1;
+                break;
+            default:
+                usage();
+                return 0;
+        }
+    }
+
+    if(g_call_id < 0)
+    {
+        usage();
+        return 0;
+    }
+
+    retry_cnt = 20*1000/100; /** timeout : 20S */
+    while(retry_cnt>0)
+    {
+        ret = ql_data_call_init();
+        if(ret == QL_ERR_SERVICE_NOT_READY)
+        {
+            retry_cnt--;
+            usleep(100*1000); /** sleep 100ms */
+	    continue;
+        }
+        break;
+    }
+
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_init, ret=%d", ret);
+        return -1;
+    }
+
+    ql_data_call_set_status_ind_cb(data_call_status_ind_cb);
+
+    ret = ql_data_call_create(g_call_id, call_name, 0);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to create data call, ret=%d\n", ret);
+        return -1;
+    }
+
+    p_cfg = ql_data_call_param_alloc();
+    ql_data_call_param_set_apn_id(p_cfg, apn_id);
+    ql_data_call_param_set_ip_version(p_cfg, ip_ver);
+
+    if(reconnect_interval > 0)
+    {
+        int time_list[2] = {0};
+        time_list[0] = reconnect_interval;
+        ql_data_call_param_set_reconnect_mode(p_cfg, QL_NET_DATA_CALL_RECONNECT_NORMAL);
+        ql_data_call_param_set_reconnect_interval(p_cfg, time_list, sizeof(time_list)/sizeof(time_list[0]));
+    }
+
+    ret = ql_data_call_config(g_call_id, p_cfg);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to config data call, ret=%d", ret);
+        return -1;
+    }
+
+    ret = ql_data_call_start(g_call_id);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to start data call, ret=%d", ret);
+        return -1;
+    }
+
+    while(1)
+    {
+        sleep(10);
+    }
+
+    return 0;
+}
diff --git a/mbtk/test/libql_lib_v2/ql_data_call_multi_data_call_test.c b/mbtk/test/libql_lib_v2/ql_data_call_multi_data_call_test.c
new file mode 100755
index 0000000..35610ca
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_data_call_multi_data_call_test.c
@@ -0,0 +1,320 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file main_apn.c
+  @brief Sample code for multiple data call
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  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
+  --------   ---          ----------------------------------------------------------
+  20191127   tyler.kuang  Created .
+-------------------------------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include "ql_type.h"
+#include "ql_data_call.h"
+
+#define APN_NAME_PUBLIC    "apnpublic"
+#define APN_NAME_PRIVATE   "apnprivate"
+
+#define DATA_CALL_APN_PUBLIC  3
+#define DATA_CALL_APN_PRIVATE 4
+
+#define DATA_CALL_ID_PUBLIC   1
+#define DATA_CALL_ID_PRIVATE  2
+
+void data_call_status_ind_cb(int call_id,
+        QL_NET_DATA_CALL_STATUS_E pre_call_status,
+        ql_data_call_status_t *p_msg)
+{
+    FILE *fp;
+    char cmd_buf[256];
+
+    /** not for this data call */
+    if(call_id!=DATA_CALL_ID_PUBLIC && call_id!=DATA_CALL_ID_PRIVATE)
+    {
+        return;
+    }
+
+    printf("data call %d:%s status change, form %d to %d\n",
+            call_id, p_msg->call_name, pre_call_status, p_msg->call_status);
+    if(p_msg->call_status == QL_NET_DATA_CALL_STATUS_CONNECTED)
+    {
+        printf("call_id     : %d\n", p_msg->call_id);
+        printf("call_name   : %s\n", p_msg->call_name);
+        printf("device_name : %s\n", p_msg->device);
+        if(p_msg->has_addr)
+        {
+            printf("IPV4 addr    : %s\n", p_msg->addr.addr);
+            printf("IPV4 gateway : %s\n", p_msg->addr.gateway);
+            printf("IPV4 netmask : %s\n", p_msg->addr.netmask);
+            printf("IPV4 dnsp    : %s\n", p_msg->addr.dnsp);
+            printf("IPV4 dnss    : %s\n", p_msg->addr.dnss);
+
+            if(call_id == DATA_CALL_ID_PUBLIC)
+            {
+                /** set system default router */
+                snprintf(cmd_buf, sizeof(cmd_buf), "ip ro add default via %s dev %s",
+                        p_msg->addr.gateway, p_msg->device);
+                system(cmd_buf);
+
+                system("iptables -t filter -F");
+
+                snprintf(cmd_buf, sizeof(cmd_buf), "iptables -t nat -A POSTROUTING -o %s -j MASQUERADE", p_msg->device);
+                system(cmd_buf);
+
+                /** set system dns configuration*/
+                fp = fopen("/tmp/resolv_v4.conf", "w");
+                if(!fp)
+                {
+                    printf("Failed to write resolv file, err=%s\n", strerror(errno));
+                    return;
+                }
+
+                if(p_msg->addr.dnsp[0])
+                {
+                    fprintf(fp, "nameserver %s\n", p_msg->addr.dnsp);
+                }
+
+                if(p_msg->addr.dnss[0])
+                {
+                    fprintf(fp, "nameserver %s\n", p_msg->addr.dnss);
+                }
+                fclose(fp);
+
+                system("echo \"\" > /etc/resolv.conf");
+                if(access("/tmp/resolv_v4.conf", F_OK) == 0)
+                {
+                    system("cat /tmp/resolv_v4.conf >> /etc/resolv.conf");
+                }
+                if(access("/tmp/resolv_v6.conf", F_OK) == 0)
+                {
+                    system("cat /tmp/resolv_v6.conf >> /etc/resolv.conf");
+                }
+            }
+        }
+
+        if(p_msg->has_addr6)
+        {
+            printf("IPV6 addr    : %s\n", p_msg->addr6.addr);
+            printf("IPV6 gateway : %s\n", p_msg->addr6.gateway);
+            printf("IPV6 netmask : %s\n", p_msg->addr6.prefix);
+            printf("IPV6 dnsp    : %s\n", p_msg->addr6.dnsp);
+            printf("IPV6 dnss    : %s\n", p_msg->addr6.dnss);
+
+            if(call_id == DATA_CALL_ID_PUBLIC)
+            {
+                /** set system default router */
+                snprintf(cmd_buf, sizeof(cmd_buf), "ip -6 ro add default via %s dev %s",
+                        p_msg->addr6.gateway, p_msg->device);
+                system(cmd_buf);
+
+                /** set system dns configuration*/
+                fp = fopen("/tmp/resolv_v6.conf", "w");
+                if(!fp)
+                {
+                    printf("Failed to write resolv file, err=%s\n", strerror(errno));
+                    return;
+                }
+
+                if(p_msg->addr6.dnsp[0])
+                {
+                    fprintf(fp, "nameserver %s\n", p_msg->addr6.dnsp);
+                }
+
+                if(p_msg->addr6.dnss[0])
+                {
+                    fprintf(fp, "nameserver %s\n", p_msg->addr6.dnss);
+                }
+                fclose(fp);
+
+                system("echo \"\" > /etc/resolv.conf");
+                if(access("/tmp/resolv_v4.conf", F_OK) == 0)
+                {
+                    system("cat /tmp/resolv_v4.conf >> /etc/resolv.conf");
+                }
+                if(access("/tmp/resolv_v6.conf", F_OK) == 0)
+                {
+                    system("cat /tmp/resolv_v6.conf >> /etc/resolv.conf");
+                }
+            }
+        }
+    }
+}
+
+static void data_call_service_error_cb(int error)
+{
+    if(error == QL_ERR_ABORTED) {
+        printf("RIL service exit!!!\n");
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    int ret = 0;
+    ql_data_call_apn_config_t apn_cfg;
+    ql_data_call_param_t *p_param = NULL;
+    int time_interval_list[20] = {0};
+    int retry_cnt = 20;
+
+    while(retry_cnt > 0)
+    {
+        ret = ql_data_call_init();
+
+        if(ret == QL_ERR_SERVICE_NOT_READY)
+        {
+            sleep(1);
+            retry_cnt --;
+            continue;
+        }
+        break;
+    }
+
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_init, ret=%d\n", ret);
+        return -1;
+    }
+
+    ql_data_call_set_status_ind_cb(data_call_status_ind_cb);
+
+    ql_data_call_set_service_error_cb(data_call_service_error_cb);
+
+    /**
+     * STEP 1: Set LTE default attach APN
+     */
+    memset(&apn_cfg, 0, sizeof(apn_cfg));
+    strncpy(apn_cfg.apn_name, APN_NAME_PRIVATE, sizeof(apn_cfg.apn_name));
+    apn_cfg.ip_ver = QL_NET_IP_VER_V4;
+
+    ret = ql_data_call_set_apn_config(1, &apn_cfg);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_set_apn_config, APN1, ret=%d\n", ret);
+        return -1;
+    }
+
+    /**
+     *  STEP 2: Set APN used by Data call
+     *  APN6 for public network
+     *  APN7 For private network
+     */
+    memset(&apn_cfg, 0, sizeof(apn_cfg));
+    strncpy(apn_cfg.apn_name, APN_NAME_PUBLIC, sizeof(apn_cfg.apn_name));
+    apn_cfg.ip_ver = QL_NET_IP_VER_V4;
+
+    ret = ql_data_call_set_apn_config(DATA_CALL_APN_PUBLIC, &apn_cfg);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_set_apn_config, APN_ID=%d, ret=%d\n", DATA_CALL_APN_PUBLIC, ret);
+        return -1;
+    }
+
+    memset(&apn_cfg, 0, sizeof(apn_cfg));
+    strncpy(apn_cfg.apn_name, APN_NAME_PRIVATE, sizeof(apn_cfg.apn_name));
+    apn_cfg.ip_ver = QL_NET_IP_VER_V4;
+
+    ret = ql_data_call_set_apn_config(DATA_CALL_APN_PRIVATE, &apn_cfg);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_set_apn_config, APN_ID=%d, ret=%d\n", DATA_CALL_APN_PRIVATE, ret);
+        return -1;
+    }
+
+    p_param = ql_data_call_param_alloc();
+    if(p_param == NULL)
+    {
+        printf("Failed to ql_data_call_param_alloc, memory is not enough\n");
+        return -1;
+    }
+
+    /**
+     * STEP 3: create and start data call
+     * Public network data call: call_id=1, call_name=public, APN6
+     * Private network data_call: call_id=2, call_name=private, APN7
+     */
+    ret = ql_data_call_create(DATA_CALL_ID_PUBLIC, "public", 0);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_create, call_id=%d, ret=%d\n", DATA_CALL_ID_PUBLIC, ret);
+        return -1;
+    }
+
+    ql_data_call_param_init(p_param);
+    ql_data_call_param_set_apn_id(p_param, DATA_CALL_APN_PUBLIC);
+    ql_data_call_param_set_ip_version(p_param, QL_NET_IP_VER_V4);
+    ql_data_call_param_set_reconnect_mode(p_param, QL_NET_DATA_CALL_RECONNECT_NORMAL);
+    time_interval_list[0] = 20;
+    ql_data_call_param_set_reconnect_interval(p_param, time_interval_list, 1);
+
+    ret = ql_data_call_config(DATA_CALL_ID_PUBLIC, p_param);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_config, call_id=%d, ret=%d\n", DATA_CALL_ID_PUBLIC, ret);
+        return -1;
+    }
+
+    printf("Start data call : public\n");
+    ret = ql_data_call_start(DATA_CALL_ID_PUBLIC);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_start, call_id=%d, ret=%d\n", DATA_CALL_ID_PUBLIC, ret);
+        return -1;
+    }
+
+    ret = ql_data_call_create(DATA_CALL_ID_PRIVATE, "private", 0);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_create, call_id=%d, ret=%d\n", DATA_CALL_ID_PRIVATE, ret);
+        return -1;
+    }
+
+    ql_data_call_param_init(p_param);
+    ql_data_call_param_set_apn_id(p_param, DATA_CALL_APN_PRIVATE);
+    ql_data_call_param_set_ip_version(p_param, QL_NET_IP_VER_V4);
+    ql_data_call_param_set_reconnect_mode(p_param, QL_NET_DATA_CALL_RECONNECT_NORMAL);
+    time_interval_list[0] = 20;
+    ql_data_call_param_set_reconnect_interval(p_param, time_interval_list, 1);
+
+    ret = ql_data_call_config(DATA_CALL_ID_PRIVATE, p_param);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_config, call_id=%d, ret=%d\n", DATA_CALL_ID_PRIVATE, ret);
+    }
+
+    printf("Start data call : private\n");
+    ret = ql_data_call_start(DATA_CALL_ID_PRIVATE);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_start, call_id=%d, ret=%d\n", DATA_CALL_ID_PRIVATE, ret);
+        return -1;
+    }
+
+    while(1)
+    {
+        sleep(1);
+    }
+
+    return 0;
+}
diff --git a/mbtk/test/libql_lib_v2/ql_data_call_test.c b/mbtk/test/libql_lib_v2/ql_data_call_test.c
new file mode 100755
index 0000000..240ef45
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_data_call_test.c
@@ -0,0 +1,965 @@
+#include <stdio.h>
+#include <string.h>
+#include "ql_type.h"
+#include "ql_data_call.h"
+#include "ql_nslookup.h"
+#include "mbtk_utils.h"
+
+typedef void (*item_handler_f)(void);
+
+typedef struct
+{
+    const char *name;
+    item_handler_f handle;
+} t_item_t;
+
+const char *ql_data_call_state_str(int state)
+{
+    switch(state)
+    {
+        case QL_NET_DATA_CALL_STATUS_NONE:
+            return "NONE";
+        case QL_NET_DATA_CALL_STATUS_CREATED:
+            return "CREATE";
+        case  QL_NET_DATA_CALL_STATUS_IDLE:
+            return "IDLE";
+        case  QL_NET_DATA_CALL_STATUS_CONNECTING:
+            return "CONNECTING";
+        case QL_NET_DATA_CALL_STATUS_PARTIAL_V4_CONNECTED:
+            return "PARTIAL_V4_CONNECTED";
+        case  QL_NET_DATA_CALL_STATUS_PARTIAL_V6_CONNECTED:
+            return "PARTIAL_V6_CONNECTED";
+        case QL_NET_DATA_CALL_STATUS_CONNECTED:
+            return "CONNECTED";
+        case  QL_NET_DATA_CALL_STATUS_DISCONNECTED:
+            return "DISCONNECTED";
+        case  QL_NET_DATA_CALL_STATUS_ERROR:
+            return "ERROR";
+        case  QL_NET_DATA_CALL_STATUS_DELETED:
+            return "DELETE";
+        default:
+            break;
+    };
+
+    return "UNKNOW";
+}
+
+
+void data_call_status_ind_cb(int call_id,
+        QL_NET_DATA_CALL_STATUS_E pre_call_status,
+        ql_data_call_status_t *p_msg)
+{
+    printf("----DATA CALL STATUS CHANGE EVENT:\n");
+    printf("\tcall_id=%d\n", call_id);
+    printf("\tpre_call_status=%s\n", ql_data_call_state_str(pre_call_status));
+    printf("\tcall_name=%s\n", p_msg->call_name);
+    printf("\tcall_status=%s\n", ql_data_call_state_str(p_msg->call_status));
+    if(p_msg->device[0])
+    {
+        printf("\tdevice=%s\n", p_msg->device);
+    }
+    if(p_msg->has_addr)
+    {
+        printf("\tIP4 : addr=%s\n", p_msg->addr.addr);
+        printf("\tIP4 : netmask=%s\n", p_msg->addr.netmask);
+        printf("\tIP4 : subnet_bits=%d\n", p_msg->addr.subnet_bits);
+        printf("\tIP4 : gateway=%s\n", p_msg->addr.gateway);
+        printf("\tIP4 : dnsp=%s\n", p_msg->addr.dnsp);
+        printf("\tIP4 : dnss=%s\n", p_msg->addr.dnss);
+    }
+
+    if(p_msg->has_addr6)
+    {
+        printf("\tIP6 : addr=%s\n", p_msg->addr6.addr);
+        printf("\tIP6 : prefix=%s\n", p_msg->addr6.prefix);
+        printf("\tIP6 : prefix_bits=%d\n", p_msg->addr6.prefix_bits);
+        printf("\tIP6 : gateway=%s\n", p_msg->addr6.gateway);
+        printf("\tIP6 : dnsp=%s\n", p_msg->addr6.dnsp);
+        printf("\tIP6 : dnss=%s\n", p_msg->addr6.dnss);
+    }
+
+    printf("\tcall_end_reason_type=%d\n", p_msg->call_end_reason_type);
+    printf("\tcall_end_reason_code=0x%X\n", p_msg->call_end_reason_code);
+}
+
+void data_call_service_error_cb(int error)
+{
+    printf("===== DATACALL Service Abort =====\n");
+}
+
+void item_ql_data_call_init(void)
+{
+    int ret = 0;
+    printf("Start to ql_data_call_init\n");
+    ret = ql_data_call_init();
+    if(ret == QL_ERR_OK)
+    {
+        printf("Successful\n");
+    }
+    else
+    {
+        printf("Failed to ql_data_call_init, ret=%d\n", ret);
+    }
+}
+
+void item_ql_data_call_set_service_error_cb(void)
+{
+    int ret = 0;
+    printf("Start to ql_data_call_set_service_error_cb\n");
+    ret = ql_data_call_set_service_error_cb(data_call_service_error_cb);
+    if(ret == QL_ERR_OK)
+    {
+        printf("Successful\n");
+    }
+    else
+    {
+        printf("Failed to ql_data_call_set_service_error_cb, ret=%d\n", ret);
+    }
+
+}
+
+void item_ql_data_call_deinit(void)
+{
+    int ret = 0;
+    printf("Start to ql_data_call_deinit\n");
+    ret = ql_data_call_deinit();
+    if(ret == QL_ERR_OK)
+    {
+        printf("Successful\n");
+    }
+    else
+    {
+        printf("Failed to ql_data_call_deinit, ret=%d\n", ret);
+    }
+}
+
+void item_ql_data_call_create(void)
+{
+    int ret = 0;
+    int call_id = -1;
+    char call_name[64] = {0};
+    int is_background = 0;
+
+    printf("Please input call_id :");
+    ret = t_get_int(&call_id);
+    if(ret != 0)
+    {
+       printf("Invalid input\n");
+       return;
+    }
+
+    printf("Please input call name :");
+    ret = t_get_string(call_name, sizeof(call_name));
+    if(ret != 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    printf("Working in background ?[0|1] :");
+    ret = t_get_int(&is_background);
+    if(ret != 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    printf("call_id=%d\n", call_id);
+    printf("call_name=%s\n", call_name);
+    printf("is_background=%d\n", is_background);
+    printf("Start to ql_data_call_create\n");
+    ret = ql_data_call_create(call_id, call_name, is_background);
+
+    if(ret == QL_ERR_OK)
+    {
+        printf("Successful\n");
+    }
+    else
+    {
+        printf("Failed to ql_data_call_create, ret=%d\n", ret);
+    }
+}
+
+void dump_data_call_config(ql_data_call_param_t *pcfg)
+{
+    int ret;
+    int dat;
+    int i;
+    int dat_list[128];
+    int dat_len;
+
+    ret = ql_data_call_param_get_apn_id(pcfg, &dat);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to get apn_id\n");
+        return;
+    }
+
+    printf("apn_id  : %d\n", dat);
+
+    ret = ql_data_call_param_get_ip_version(pcfg, &dat);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to get ip_version\n");
+        return;
+    }
+    printf("ip_version : %d\n", dat);
+
+    ret = ql_data_call_param_get_reconnect_mode(pcfg, &dat);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to get reconnect_mode\n");
+        return;
+    }
+    printf("reconnect_mode : %d\n", dat);
+
+    dat_len = sizeof(dat_list)/sizeof(dat_list[0]);
+    ret = ql_data_call_param_get_reconnect_interval(pcfg, dat_list, &dat_len);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to get reconnect interval\n");
+        return;
+    }
+
+    printf("interval : ");
+    for(i=0; i<dat_len; i++)
+    {
+        if(dat_list[i]==0)
+        {
+            break;
+        }
+        if(i!=0)
+        {
+            printf("%c", ',');
+        }
+        printf("%d", dat_list[i]);
+    }
+    printf("\n");
+}
+
+void item_ql_data_call_config(void)
+{
+    int ret = 0;
+    int call_id;
+    int apn_id;
+    int dat = 0;
+    ql_data_call_param_t *pcfg;
+    int dat_buf[128];
+    int dat_len = sizeof(dat_buf)/sizeof(dat_buf[0]);
+
+    pcfg = ql_data_call_param_alloc();
+    if(pcfg == NULL)
+    {
+
+        printf("Failed to ql_data_call_param_alloc");
+        return;
+    }
+
+    do
+    {
+        printf("Please input call_id :");
+        ret = t_get_int(&call_id);
+        if(ret != 0)
+        {
+            printf("Invalid input\n");
+            ret = -1;
+            break;
+        }
+
+        printf("Please input apn_id :");
+        ret = t_get_int(&apn_id);
+        if(ret != 0)
+        {
+            printf("Invalid input\n");
+            ret = -1;
+            break;
+        }
+
+        if(apn_id<1 || apn_id>QL_NET_MAX_APN_ID)
+        {
+            printf("Invalid apn_id\n");
+            ret = -1;
+            break;
+        }
+
+        ql_data_call_param_set_apn_id(pcfg, apn_id);
+
+        printf("Please input ip_version [1-IPV4,2-IPV6,3-IPV4V6] :");
+        ret = t_get_int(&dat);
+        if(ret < 0)
+        {
+            printf("Invalid input\n");
+            ret = -1;
+            break;
+        }
+
+        if(ret == 0)
+        {
+            if(!IS_QL_NET_IP_VER_VALID(dat))
+            {
+                printf("Unsupport ip_version : %d\n", dat);
+                ret = -1;
+                break;
+            }
+
+            ql_data_call_param_set_ip_version(pcfg, dat);
+        }
+
+        printf("Please input reconnect_mode [0-disable,1-normal,2-mode1,3-mode2] :");
+        ret = t_get_int(&dat);
+        if(ret < 0)
+        {
+            printf("Invalid input\n");
+            ret = -1;
+            break;
+        }
+
+        if(ret == 0)
+        {
+            if(!IS_QL_NET_DATA_CALL_RECONNECT_MODE_VALID(dat))
+            {
+                printf("Unsupport mode : %d\n", dat);
+                ret = -1;
+                break;
+            }
+           ql_data_call_param_set_reconnect_mode(pcfg, dat);
+        }
+
+
+        printf("Please input interval_list [split by ,.:] :");
+        dat_len = sizeof(dat_buf)/sizeof(dat_buf[0]);
+        ret = t_get_int_list(dat_buf, &dat_len);
+        if(ret < 0)
+        {
+            printf("Invalid input\n");
+            ret = -1;
+            break;
+        }
+
+        if(ret == 0)
+        {
+            ql_data_call_param_set_reconnect_interval(pcfg, dat_buf, dat_len);
+        }
+
+        ret = 0;
+    }
+    while(0);
+
+    if(ret == 0)
+    {
+        dump_data_call_config(pcfg);
+        printf("Accept ? [Y|N] :");
+        ret = t_get_char(&dat);
+        if(ret < 0)
+        {
+            printf("Invalid input\n");
+        }
+        else
+        {
+            if(ret==1 || dat=='Y' || dat=='y')
+            {
+                printf("Start to ql_data_call_config\n");
+                ret = ql_data_call_config(call_id, pcfg);
+                if(ret != QL_ERR_OK)
+                {
+                    printf("Failed to ql_data_call_config, ret=%d\n", ret);
+                }
+                else
+                {
+                    printf("Successful\n");
+                }
+            }
+            else
+            {
+                printf("Skip ql_data_call_config");
+            }
+        }
+    }
+
+    ql_data_call_param_free(pcfg);
+}
+
+
+void item_ql_data_call_get_config(void)
+{
+    int ret = 0;
+    int call_id;
+    ql_data_call_param_t *pcfg;
+
+    pcfg = ql_data_call_param_alloc();
+    if(pcfg == NULL)
+    {
+
+        printf("Failed to ql_data_call_param_alloc");
+        return;
+    }
+
+    do
+    {
+        printf("Please input call_id :");
+        ret = t_get_int(&call_id);
+        if(ret != 0)
+        {
+            printf("Invalid input\n");
+            ret = -1;
+            break;
+        }
+
+        ret = ql_data_call_get_config(call_id, pcfg);
+        if(ret != QL_ERR_OK)
+        {
+            printf("Failed to ql_data_call_get_config, ret=%d\n", ret);
+            ret = -1;
+            break;
+        }
+
+        printf("Successful\n");
+
+        dump_data_call_config(pcfg);
+    } while(0);
+
+    ql_data_call_param_free(pcfg);
+}
+
+void item_ql_data_call_start(void)
+{
+    int ret = 0;
+    int call_id = -1;
+
+    printf("Please input call_id :");
+    ret = t_get_int(&call_id);
+    if(ret != 0)
+    {
+       printf("Invalid input\n");
+       return;
+    }
+
+    printf("Start to ql_data_call_start, data_call=%d\n", call_id);
+    ret = ql_data_call_start(call_id);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_start, ret=%d\n", ret);
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+}
+
+void item_ql_data_call_stop(void)
+{
+    int ret = 0;
+    int call_id = -1;
+
+    printf("Please input call_id :");
+    ret = t_get_int(&call_id);
+    if(ret != 0)
+    {
+       printf("Invalid input\n");
+       return;
+    }
+
+    printf("Start to ql_data_call_stop, data_call=%d\n", call_id);
+    ret = ql_data_call_stop(call_id);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_stop, ret=%d\n", ret);
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+}
+
+void item_ql_data_call_delete(void)
+{
+    int ret = 0;
+    int call_id = -1;
+
+    printf("Please input call_id :");
+    ret = t_get_int(&call_id);
+    if(ret != 0)
+    {
+       printf("Invalid input\n");
+       return;
+    }
+
+    printf("Start to ql_data_call_delete, data_call=%d\n", call_id);
+    ret = ql_data_call_delete(call_id);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_delete, ret=%d\n", ret);
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+}
+
+void item_ql_data_call_get_list(void)
+{
+    int i;
+    int ret = 0;
+    ql_data_call_item_t item_list[20];
+    int list_len = ARRAY_SIZE(item_list);
+
+    memset(item_list,0,sizeof(ql_data_call_item_t)*20);
+    printf("Start to ql_data_call_get_list\n");
+    ret = ql_data_call_get_list(item_list, &list_len);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_get_list, ret=%d\n", ret);
+    }
+    else
+    {
+        printf("Successful, instance_num=%d\n", list_len);
+        for(i=0; i<list_len; i++)
+        {
+            printf("%d\t%d\t%s\n", i, item_list[i].call_id, item_list[i].call_name);
+        }
+    }
+}
+
+void  item_ql_data_call_get_status(void)
+{
+    int ret = 0;
+    int call_id;
+    ql_data_call_status_t sta = {0};
+
+    printf("Please input call_id :");
+    ret = t_get_int(&call_id);
+    if(ret != 0)
+    {
+       printf("Invalid input\n");
+       return;
+    }
+
+    printf("Start to ql_data_call_get_status\n");
+    ret = ql_data_call_get_status(call_id, &sta);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_get_status, ret=%d\n", ret);
+        return;
+    }
+
+    printf("Successful\n");
+    printf("call_id : %d\n", sta.call_id);
+    printf("call_name : %s\n", sta.call_name);
+    printf("call_status : %s\n", ql_data_call_state_str(sta.call_status));
+
+    if(sta.device[0])
+    {
+        printf("device : %s\n", sta.device);
+    }
+
+    if(sta.has_addr)
+    {
+        printf("\tip4 ip      : %s\n", sta.addr.addr);
+        printf("\tip4 netmask : %s\n", sta.addr.netmask);
+        printf("\tip4 subnet_bits : %d\n", sta.addr.subnet_bits);
+        printf("\tip4 gateway : %s\n", sta.addr.gateway);
+        printf("\tip4_dnsp    : %s\n", sta.addr.dnsp);
+        printf("\tip4_dnss    : %s\n", sta.addr.dnss);
+    }
+
+    if(sta.has_addr6)
+    {
+        printf("\tip6 ip      : %s\n", sta.addr6.addr);
+        printf("\tip6 prefix  : %s\n", sta.addr6.prefix);
+        printf("\tip6 prefix_bits : %d\n", sta.addr6.prefix_bits);
+        printf("\tip6 gatway      : %s\n", sta.addr6.gateway);
+        printf("\tip6 dnsp    : %s\n", sta.addr6.dnsp);
+        printf("\tip6 dnss    : %s\n", sta.addr6.dnss);
+    }
+
+    printf("call_end_reason_type : %d\n", sta.call_end_reason_type);
+    printf("call_end_reason_code : 0x%X\n", sta.call_end_reason_code);
+}
+
+void item_ql_data_call_set_status_ind_cb(void)
+{
+    int ret;
+
+    printf("Start to ql_data_call_set_status_ind_cb\n");
+    ret = ql_data_call_set_status_ind_cb(data_call_status_ind_cb);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_set_status_ind_cb, ret=%d\n", ret);
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+}
+
+void dump_apn_cfg(ql_data_call_apn_config_t *p_cfg)
+{
+    printf("ip_version : %d\n", p_cfg->ip_ver);
+    printf("auth_pref : %d\n", p_cfg->auth_pref);
+    printf("apn_name  : %s\n", p_cfg->apn_name);
+    printf("username  : %s\n", p_cfg->username);
+    printf("password  : %s\n", p_cfg->password);
+}
+
+void item_ql_data_call_set_apn_config(void)
+{
+    int ret;
+    int dat;
+    int apn_id = 0;
+    ql_data_call_apn_config_t cfg = {0};
+
+    printf("Start to item_ql_data_call_set_apn_config\n");
+
+    printf("Please input apn_id :");
+    ret = t_get_int(&apn_id);
+    if(ret != 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    if(apn_id<1 || apn_id>16)
+    {
+        printf("Invalid apn_id : %d\n", apn_id);
+        return;
+    }
+
+    printf("Please input auth_pref [0-NONE,1-PAP,2-CHAP,3-PAP&CHAP] :");
+    ret = t_get_int(&dat);
+    if(ret < 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    if(ret == 0)
+    {
+        if(!IS_QL_NET_AUTH_PREF_VALID(dat))
+        {
+            printf("Unspport auth_pref : %d\n", dat);
+            return;
+        }
+
+        cfg.auth_pref = dat;
+    }
+
+    printf("Please input ip_version [1-IPV4,2-IPV6,3-IPV4V6] :");
+    ret = t_get_int(&dat);
+    if(ret < 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    if(ret == 0)
+    {
+        if(!IS_QL_NET_IP_VER_VALID(dat))
+        {
+            printf("Unsupport ip_version : %d\n", dat);
+            return;
+        }
+
+        cfg.ip_ver = dat;
+    }
+
+    printf("Please input apn_name :");
+    ret = t_get_string(cfg.apn_name, sizeof(cfg.apn_name));
+    if(ret < 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    printf("Please input username :");
+    ret = t_get_string(cfg.username, sizeof(cfg.username));
+    if(ret < 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    printf("Please input password :");
+    ret = t_get_string(cfg.password, sizeof(cfg.password));
+    if(ret < 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    printf("apn_id : %d", apn_id);
+    dump_apn_cfg(&cfg);
+
+    ret = ql_data_call_set_apn_config(apn_id, &cfg);
+
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_set_apn_config, ret=%d\n", ret);
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+}
+
+void item_ql_data_call_get_apn_config(void)
+{
+    int ret;
+    int apn_id = 0;
+    ql_data_call_apn_config_t cfg = {0};
+
+    printf("Start to item_ql_data_call_get_apn_config\n");
+
+    printf("Please input apn_id :");
+    ret = t_get_int(&apn_id);
+    if(ret != 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    if(apn_id<1 || apn_id>16)
+    {
+        printf("Invalid apn_id : %d\n", apn_id);
+        return;
+    }
+
+    ret = ql_data_call_get_apn_config(apn_id, &cfg);
+
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_set_apn_config, ret=%d\n", ret);
+    }
+    else
+    {
+        printf("Successful\n");
+        printf("apn_id : %d\n", apn_id);
+        dump_apn_cfg(&cfg);
+    }
+}
+
+#if 0
+void item_ql_nslookup(void)
+{
+    printf("start ql_nslookup\n");
+    int i;
+    int ret = 0;
+    char ip_str[128];
+    char ip_family[5];
+    char hostname[64];
+    char dns_server_ip[20];
+    QUERY_IP_TYPE ip_type;
+    hostaddr_info_u resolved_addr;
+
+    memset(ip_str, 0, sizeof(ip_str));
+    memset(ip_family, 0, sizeof(ip_family));
+    memset(hostname, 0, sizeof(hostname));
+    memset(dns_server_ip, 0, sizeof(dns_server_ip));
+
+    printf("please input domain name: ");
+    ret = t_get_string(hostname, sizeof(hostname));
+    if(ret != 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    printf("please input dns ip address: ");
+    ret = t_get_string(dns_server_ip, sizeof(dns_server_ip));
+    if(ret != 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    printf("please input ipfamily(v4/v6): ");
+    ret = t_get_string(ip_family, sizeof(ip_family));
+    if(ret != 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    if(0 == strcmp(ip_family, "v4"))
+    {
+        ip_type = QUERY_IPV4_E;
+    }
+    else if(0 == strcmp(ip_family, "v6"))
+    {
+        ip_type = QUERY_IPV6_E;
+    }
+    else
+    {
+        printf("Invalid ip type\n");
+        return;
+    }
+
+
+    ql_nslookup(hostname, dns_server_ip, ip_type, &resolved_addr);
+
+    //printf resolved addr
+    for (i = 0; i < resolved_addr.addr_cnt; i++) {
+         inet_ntop(AF_INET, &resolved_addr.addr[i].s_addr, ip_str, sizeof(ip_str));
+         printf("%s has IPv4 address : %s\n", hostname, ip_str);
+    }
+
+    for (i = 0; i < resolved_addr.addr6_cnt; i++) {
+         inet_ntop(AF_INET6, &resolved_addr.addr6[i].s6_addr, ip_str, sizeof(ip_str));
+         printf("%s has IPv6 address : %s\n", hostname, ip_str);
+    }
+
+    return;
+}
+#endif
+
+void item_ql_data_call_set_attach_apn_config(void)
+{
+    int ret;
+    int dat;
+    ql_data_call_apn_config_t cfg = {0};
+
+    printf("Start to item_ql_data_call_set_attach_apn_config,apn id is 1\n");
+    printf("Please input auth_pref [0-NONE,1-PAP,2-CHAP,3-PAP&CHAP] :");
+    ret = t_get_int(&dat);
+    if(ret < 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    if(ret == 0)
+    {
+        if(!IS_QL_NET_AUTH_PREF_VALID(dat))
+        {
+            printf("Unspport auth_pref : %d\n", dat);
+            return;
+        }
+
+        cfg.auth_pref = dat;
+    }
+
+    printf("Please input ip_version [1-IPV4,2-IPV6,3-IPV4V6] :");
+    ret = t_get_int(&dat);
+    if(ret < 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    if(ret == 0)
+    {
+        if(!IS_QL_NET_IP_VER_VALID(dat))
+        {
+            printf("Unsupport ip_version : %d\n", dat);
+            return;
+        }
+
+        cfg.ip_ver = dat;
+    }
+
+    printf("Please input apn_name :");
+    ret = t_get_string(cfg.apn_name, sizeof(cfg.apn_name));
+    if(ret < 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    printf("Please input username :");
+    ret = t_get_string(cfg.username, sizeof(cfg.username));
+    if(ret < 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+
+    printf("Please input password :");
+    ret = t_get_string(cfg.password, sizeof(cfg.password));
+    if(ret < 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+    dump_apn_cfg(&cfg);
+
+    ret = ql_data_call_set_attach_apn_config(&cfg);
+
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_data_call_set_apn_config, ret=%d\n", ret);
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+}
+
+static t_item_t ql_data_call_items[] =
+{
+    {"ql_data_call_init", item_ql_data_call_init},
+    {"ql_data_call_create", item_ql_data_call_create},
+    {"ql_data_call_config",item_ql_data_call_config},
+    {"ql_data_call_get_config",item_ql_data_call_get_config},
+    {"ql_data_call_start", item_ql_data_call_start},
+    {"ql_data_call_stop", item_ql_data_call_stop},
+    {"ql_data_call_delete", item_ql_data_call_delete},
+    {"ql_data_call_get_list", item_ql_data_call_get_list},
+    {"ql_data_call_get_status", item_ql_data_call_get_status},
+    {"ql_data_call_set_status_ind_cb", item_ql_data_call_set_status_ind_cb},
+    {"ql_data_call_set_apn_config", item_ql_data_call_set_apn_config},
+    {"ql_data_call_get_apn_config", item_ql_data_call_get_apn_config},
+    {"ql_data_call_set_service_error_cb", item_ql_data_call_set_service_error_cb},
+    {"ql_data_call_deinit", item_ql_data_call_deinit},
+//    {"ql_nslookup",item_ql_nslookup},
+    {"ql_data_call_set_attach_apn_config", item_ql_data_call_set_attach_apn_config}
+};
+
+static void help()
+{
+    int i = 0;
+    printf("Test Items:\n");
+    while(i < ARRAY_SIZE(ql_data_call_items)) {
+        printf("%d : %s\n", i, ql_data_call_items[i].name);
+        i++;
+    }
+    printf(":");
+}
+
+int main(int argc, char *argv[])
+{
+    char cmd[1024];
+    help();
+    while(1)
+    {
+        memset(cmd, 0, sizeof(cmd));
+        if(fgets(cmd, sizeof(cmd), stdin))
+        {
+            char *ptr = cmd + strlen(cmd) - 1;
+            while(ptr >= cmd && (*ptr == '\r' || *ptr == '\n'))
+            {
+                *ptr-- = '\0';
+            }
+
+            if(strlen(cmd) > 0) {
+                if(isdigit(cmd[0])) {
+                    int item = atoi(cmd);
+                    if(item >= 0 && item < ARRAY_SIZE(ql_data_call_items)) {
+                        ql_data_call_items[item].handle();
+                    }
+                }
+                else if(!strcasecmp(cmd, "h")) {
+                    help();
+                }
+                else if(!strcasecmp(cmd, "q")) {
+                    break;
+                }
+            }
+            else {
+                printf("\n");
+            }
+        }
+    }
+    return 0;
+}
+
+
+
diff --git a/mbtk/test/libql_lib_v2/ql_dm_test.c b/mbtk/test/libql_lib_v2/ql_dm_test.c
new file mode 100755
index 0000000..409c460
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_dm_test.c
@@ -0,0 +1,553 @@
+

+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+#include <unistd.h>

+#include <ctype.h>

+#include <stdio.h>

+#include <sys/time.h>

+

+#include "ql_v2/ql_type.h"

+#include "ql_dm.h"

+

+

+
+#define T_ARRAY_SIZE(items) (sizeof(items)/sizeof(items[0]))

+

+typedef void (*item_handler_f)(void);
+typedef int (*init_handler_f)(void);
+typedef int (*deinit_handler_f)(void);
+
+

+
+typedef struct
+{
+    const char *name;
+    item_handler_f handle;
+} t_item_t;
+
+typedef struct
+{
+    const char *name;
+    int item_len;
+    t_item_t *item_list;
+} t_module_t;
+

+typedef struct
+{
+    const char *name;
+    init_handler_f init_handle;
+    deinit_handler_f deinit_handle;
+} t_init_t;

+

+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;

+}

+

+

+static int internal_dm_get_air_plane_mode(QL_DM_AIR_PLANE_MODE_TYPE_E mode, char* buf, int buf_len);

+

+

+void dm_air_plane_mode_event_ind_cb(QL_DM_AIR_PLANE_MODE_TYPE_E air_plane_mode)

+{

+    char mode_info[16] = {0};

+

+    printf("Recv event indication : air plane mode changed event\n");

+

+    if(internal_dm_get_air_plane_mode(air_plane_mode, mode_info, sizeof(mode_info)) == 0)

+    {

+        printf("unrecognized air plane mode:%d\n", air_plane_mode);

+    }

+    else

+    {

+        printf("current air plane mode is %s\n", mode_info);

+    }

+}

+

+void dm_modem_state_change_ind_cb(int modem_state)

+{

+    printf("Recv event indication : modem status changed event\n");

+    if(QL_DM_MODEM_STATE_ONLINE == modem_state)

+    {

+        printf("current modem status is ONLINE\n");

+    }

+    else if(QL_DM_MODEM_STATE_OFFLINE == modem_state)

+    {

+        printf("current modem status is OFFLINE\n");

+    }

+    else

+    {

+        printf("current modem status is UNKNOWN\n");

+    }

+}

+

+void dm_service_error_cb(int error)

+{

+    printf("===== DM Service Abort =====\n");

+}

+

+void item_ql_dm_init(void)

+{

+    int ret = 0;

+

+    printf("Start to ql_dm_init: ");

+    ret = ql_dm_init();

+    if(ret == QL_ERR_OK)

+    {

+        printf("dm init ok\n");

+    }

+    else

+    {

+        printf("failed, ret=%d\n", ret);

+    }

+}

+

+void item_ql_dm_set_service_error_cb(void)

+{

+    int ret = 0;

+

+    printf("Start to item_ql_dm_set_service_error_cb : ");

+    ret = ql_dm_set_service_error_cb(dm_service_error_cb);

+    if(ret != QL_ERR_OK)

+    {

+        printf("failed, ret=%d\n", ret);

+    }

+    else

+    {

+        printf("successful\n");

+    }

+}

+

+void item_ql_dm_deinit(void)

+{

+    int ret = 0;

+

+    printf("Start to ql_dm_deinit: ");

+    ret = ql_dm_deinit();

+    if(ret == QL_ERR_OK)

+    {

+        printf("dm deinit ok\n");

+    }

+    else

+    {

+        printf("failed, ret=%d\n", ret);

+    }

+}

+

+void item_ql_dm_set_air_plane_mode_ind_cb(void)

+{

+    int ret = 0;

+    int reg_flag = 0;

+

+    printf("please input air plane mode reg option: (0: unreg, other: reg): ");

+    ret = t_get_int(&reg_flag);

+    if(ret != 0)

+    {

+        printf("Invalid input\n");

+        return;

+    }

+

+    if(reg_flag)

+    {

+        ret = ql_dm_set_air_plane_mode_ind_cb(dm_air_plane_mode_event_ind_cb);

+    }

+    else

+    {

+        ret = ql_dm_set_air_plane_mode_ind_cb(NULL);

+    }

+    printf("ql_dm_set_air_plane_mode_ind_cb ret = %d\n", ret);

+}

+

+void item_ql_dm_get_software_version(void)

+{

+    int ret;

+    char soft_ver[128] = {0};

+

+    ret = ql_dm_get_software_version(soft_ver, sizeof(soft_ver));

+

+    printf("ql_dm_get_software_version ret = %d, software version is %s\n", ret, soft_ver);

+}

+

+void item_ql_dm_set_modem_state_change_ind_cb(void)

+{

+    int ret = 0;

+    int reg_flag = 0;

+

+    printf("please input modem state reg option: (0: unreg, other: reg): ");

+    ret = t_get_int(&reg_flag);

+    if(ret != 0)

+    {

+        printf("Invalid input\n");

+        return;

+    }

+

+    if(reg_flag)

+    {

+        ret = ql_dm_set_modem_state_change_ind_cb(dm_modem_state_change_ind_cb);

+    }

+    else

+    {

+        ret = ql_dm_set_modem_state_change_ind_cb(NULL);

+    }

+    printf("ql_dm_set_modem_state_change_ind_cb ret = %d\n", ret);

+}

+

+void item_ql_dm_get_device_serial_numbers(void)

+{

+    int ret;

+    ql_dm_device_serial_numbers_info_t t_info;

+    memset(&t_info, 0, sizeof(ql_dm_device_serial_numbers_info_t));

+

+    ret = ql_dm_get_device_serial_numbers(&t_info);

+    printf("ql_dm_get_device_serial_number ret = %d", ret);

+    if(t_info.imei_valid)

+    {

+        printf(", imei is %s", t_info.imei);

+    }

+    if(t_info.imei2_valid)

+    {

+        printf(", imei2 is %s", t_info.imei2);

+    }

+    if(t_info.meid_valid)

+    {

+        printf(", meid is %s ", t_info.meid);

+    }

+    printf("\n");

+}

+

+void item_ql_dm_get_device_firmware_rev_id(void)

+{

+    int ret;

+    char firmware_rev_id[QL_DM_FIRMWARE_REV_MAX_LEN + 1] = {0};

+

+    ret = ql_dm_get_device_firmware_rev_id(firmware_rev_id, sizeof(firmware_rev_id));

+    printf("ql_dm_get_device_firmware_rev_id ret = %d, device revision id is %s\n",

+            ret, firmware_rev_id);

+}

+

+void item_ql_dm_get_air_plane_mode(void)

+{

+    int ret;

+    char mode_info[16] = {0};

+    QL_DM_AIR_PLANE_MODE_TYPE_E air_plane_mode;

+

+    ret = ql_dm_get_air_plane_mode(&air_plane_mode);

+

+    printf("ql_dm_get_air_plane_mode ret = %d, ", ret);

+    if(internal_dm_get_air_plane_mode(air_plane_mode, mode_info, sizeof(mode_info)) == 0)

+    {

+        printf("unrecognized air plane mode:%d\n", air_plane_mode);

+    }

+    else

+    {

+        printf("current air plane mode is %s\n", mode_info);

+    }

+}

+

+void item_ql_dm_set_air_plane_mode(void)

+{

+    int ret;

+    int mode;

+    QL_DM_AIR_PLANE_MODE_TYPE_E air_plane_mode;

+

+    printf("please input air plane mode(1: ON, 2: OFF): ");

+    ret = t_get_int(&mode);

+    if(ret != 0)

+    {

+        printf("Invalid input\n");

+        return;

+    }

+    air_plane_mode = mode;

+    if(air_plane_mode != QL_DM_AIR_PLANE_MODE_ON && air_plane_mode != QL_DM_AIR_PLANE_MODE_OFF)

+    {

+        printf("please input 1 or 2\n");

+        return;

+    }

+

+    ret = ql_dm_set_air_plane_mode(air_plane_mode);

+    printf("ql_dm_set_air_plane_mode ret = %d\n", ret);

+}

+

+static int internal_dm_get_air_plane_mode(QL_DM_AIR_PLANE_MODE_TYPE_E mode, char* buf, int buf_len)

+{

+    int ret_val = 1;

+

+    if(buf == NULL || buf_len < 2)

+    {

+        printf("param is valid\n");

+        return 0;

+    }

+

+    memset(buf, 0, buf_len);

+

+    switch(mode)

+    {

+        case QL_DM_AIR_PLANE_MODE_UNKNOWN:

+            strncpy(buf, "UNKNOWN", buf_len - 1);

+            buf[buf_len - 1] = '\0';

+            break;

+        case QL_DM_AIR_PLANE_MODE_ON:

+            strncpy(buf, "ON", buf_len - 1);

+            buf[buf_len - 1] = '\0';

+            break;

+        case QL_DM_AIR_PLANE_MODE_OFF:

+            strncpy(buf, "OFF", buf_len - 1);

+            buf[buf_len - 1] = '\0';

+            break;

+        case QL_DM_AIR_PLANE_MODE_NA:

+            strncpy(buf, "UNAVAILABLE", buf_len - 1);

+            buf[buf_len - 1] = '\0';

+            break;

+        default:

+            ret_val = 0;

+            break;

+    }

+    return ret_val;

+}

+

+

+static t_item_t ql_dm_items[] =

+{

+    {"ql_dm_init", item_ql_dm_init},

+    {"ql_dm_set_air_plane_mode_ind_cb", item_ql_dm_set_air_plane_mode_ind_cb},

+    {"ql_dm_get_software_version", item_ql_dm_get_software_version},

+    {"ql_dm_set_modem_state_change_ind_cb", item_ql_dm_set_modem_state_change_ind_cb},

+    {"ql_dm_get_device_serial_numbers", item_ql_dm_get_device_serial_numbers},

+    {"ql_dm_get_device_firmware_rev_id", item_ql_dm_get_device_firmware_rev_id},

+    {"ql_dm_get_air_plane_mode", item_ql_dm_get_air_plane_mode},

+    {"ql_dm_set_air_plane_mode", item_ql_dm_set_air_plane_mode},

+    {"ql_dm_set_service_error_cb", item_ql_dm_set_service_error_cb},

+    {"ql_dm_deinit",         item_ql_dm_deinit}

+};

+

+t_module_t ql_dm_module =

+{

+    "dm",

+    T_ARRAY_SIZE(ql_dm_items),

+    ql_dm_items

+};

+

+

+t_module_t *test_modules[] =

+{

+    &ql_dm_module,

+

+};

+

+void dump_modules(void)

+{

+    int i;

+

+    printf("\n");

+    for(i=0; i<T_ARRAY_SIZE(test_modules); i++)

+    {

+        printf("%d\t%s\n", i, test_modules[i]->name);

+    }

+    printf("-1\texit\n");

+}

+

+void dump_items(t_module_t *m)

+{

+    int i;

+

+    printf("\n");

+    printf("The current module is: \n");

+

+    for(i=0; i<m->item_len; i++)

+    {

+        printf("%d\t%s\n", i, m->item_list[i].name);

+    }

+    printf("-1\texit\n");

+}

+

+void enter_modules(t_module_t *m)

+{

+    int ret;

+    int idx;

+

+    dump_items(m);

+

+    while(1)

+    {

+        printf("Please enter your choice: ");

+        ret = t_get_int(&idx);

+        printf("\n");

+        if(ret < 0)

+        {

+            printf("Invalid input\n");

+            continue;

+        }

+        else if(ret == 1)

+        {

+            dump_items(m);

+            continue;

+        }

+

+        if(idx == -1)

+        {

+            break;

+        }

+

+        if(idx<0 || idx>=m->item_len)

+        {

+            printf("Not support idx: %d\n", idx);

+            continue;

+        }

+

+        printf("->Item : %s\n", m->item_list[idx].name);

+        m->item_list[idx].handle();

+    }

+}

+

+ static t_init_t init_func[] = {

+     {"ql_dm_init",ql_dm_init,ql_dm_deinit},

+

+

+};

+

+

+void test_init(int retry)

+{

+

+    int i = 0,j = 0;

+    for(i=0; i<T_ARRAY_SIZE(init_func); i++)

+    {

+        printf("Exec %s time = \n", init_func[i].name);

+        //clock_t start,end;

+        struct timeval start,end;

+

+        double cost_time = 0;

+        int ret = QL_ERR_OK;

+        for(j = 0;j < retry; j++)

+        {

+            if(QL_ERR_OK == ret )

+            {

+                //start = clock();

+                gettimeofday(&start, NULL);

+            }

+

+            ret = -1;

+            ret = init_func[i].init_handle();

+            if(QL_ERR_OK == ret)

+            {

+                //end = clock();

+                gettimeofday(&end, NULL);

+                long timeuse = 1000000*(end.tv_sec - start.tv_sec) + end.tv_usec-start.tv_usec;

+                //printf("%6.0f ",(double)(end-start));

+                printf("%ld ",timeuse/1000);

+                //cost_time = cost_time > (end-start) ?cost_time:(end-start);

+                cost_time = cost_time > (timeuse/1000) ?cost_time:(timeuse/1000);

+

+                init_func[i].deinit_handle();

+            }

+

+

+        }

+        printf("\n");

+        printf("Finish test. %s  max cost time = %6.0f ms\n",init_func[i].name, cost_time);

+

+    }

+

+

+}

+

+

+int main(int argc, char *argv[])

+{

+    int ret;

+    int idx;

+

+    if(argc > 1)

+    {

+      int c = -1;

+      int retry = -1;

+

+      while((c = getopt(argc, argv, "i:")) != -1)

+      {

+          if(-1 == c)

+          {

+              break;

+          }

+

+          switch(c)

+          {

+              case 'i':

+                  retry = atoi(optarg);

+                  test_init(retry);

+                  return 0;

+

+              default:

+                  printf("usage: ql_sdk_api_test -i  <retry count> to test init func\n");

+                  printf("       ql_sdk_api_test  to test sdk api\n");

+                  return -1;

+          }

+      }

+    }

+

+

+    dump_modules();

+

+    while(1)

+    {

+        printf("Please enter your choice: ");

+        ret = t_get_int(&idx);

+        printf("\n");

+        if(ret < 0)

+        {

+            printf("Invalid input\n");

+            continue;

+        }

+        else if(ret == 1)

+        {

+            dump_modules();

+            continue;

+        }

+

+        if(idx == -1)

+        {

+            break;

+        }

+

+        if(idx<0 || idx>=T_ARRAY_SIZE(test_modules))

+        {

+            printf("Not support idx: %d\n", idx);

+            continue;

+        }

+

+        enter_modules(test_modules[idx]);

+    }

+

+    return 0;

+}

+

diff --git a/mbtk/test/libql_lib_v2/ql_ecall_test.c b/mbtk/test/libql_lib_v2/ql_ecall_test.c
new file mode 100755
index 0000000..0ad1113
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_ecall_test.c
@@ -0,0 +1,1025 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <ctype.h>
+
+#include "ql_type.h"
+#include "ql_ms_voice.h"
+#include "ql_ecall.h"
+#include "mbtk_utils.h"
+
+typedef void (*item_handler_f)(void);
+
+typedef struct
+{
+    const char *name;
+    item_handler_f handle;
+} t_item_t;
+
+void item_ql_ecall_set_test_number(void)
+{
+    int ret = 0;
+    int sim_id;
+
+    char test_number[QL_VOICE_MAX_PHONE_NUMBER];
+
+    printf("test ql_voice_ecall_set_test_number: ");
+
+    printf("please enter test number: ");
+    char* find = NULL;
+
+    if(NULL == fgets(test_number, QL_VOICE_MAX_PHONE_NUMBER-1, stdin))
+        return;
+    find = strchr(test_number, '\n');
+    if(find)
+    {
+        *find = '\0';
+    }
+
+    printf("please enter the sim_id: ");
+
+    if(1 != scanf("%u", &sim_id))
+        return;
+    getchar();
+    printf("sim_id is %u\n", sim_id);
+
+    ret = ql_ecall_set_test_number(sim_id, test_number);
+
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+void item_ql_ecall_reset_ivs(void)
+{
+    int ret = 0;
+    int sim_id;
+
+    printf("please enter the sim_id: ");
+
+    if(1 != scanf("%u", &sim_id))
+        return;
+    getchar();
+    printf("sim_id is %u\n", sim_id);
+
+    ret = ql_ecall_reset_ivs(sim_id);
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+void fast_ecall_dial(void){
+    int ret = 0, v = 0;
+    ql_voice_ecall_info_t *p_info = NULL;
+    char *find = NULL;
+    uint32_t id;
+    int sim_id;
+
+    p_info = (ql_voice_ecall_info_t *)calloc(1, sizeof(*p_info));
+    if (NULL  == p_info)
+    {
+        printf("run out of memory\n");
+        return;
+    }
+
+    printf("please enter the sim_id: ");
+    if(1 != scanf("%d", &sim_id))
+        return;
+    getchar();
+
+    if(!QL_IS_SIM_VALID(sim_id))
+    {
+        printf("invalid sim_id\n");
+        free(p_info);
+        p_info = NULL;
+        return;
+    }
+
+    printf("sim_id is %d\n", sim_id);
+
+    printf("example MSD: 01 04 a9 81 d5 49 70 d6 5c 35 97 ca 04 20 c4 14 60 "
+        "0b be 5f 7e b1 4b a6 ee 10 4f c5 27 03 c1 80 q\n");
+    printf("please enter MSD(at most 140 hex), end with 'q': ");
+    while (1 == scanf("%x", &v))
+    {
+        p_info->msd[p_info->msd_len++] = v;
+    }
+    getchar();  // read `q'
+    getchar();  // read '\n'
+
+    printf("MSD ========[");
+    for(v = 0; v < p_info->msd_len; v ++)
+    {
+        printf("%02x ", p_info->msd[v]);
+    }
+    printf("]\n");
+
+    if (p_info->msd_len > QL_VOICE_MAX_ECALL_MSD)
+    {
+        printf("MSD too long\n");
+        free(p_info);
+        p_info = NULL;
+        return;
+    }
+
+    printf("please enter eCall type(1 - test, 2 - emergency,  3 - reconfig): ");
+    if(1 != scanf("%d", (int *)&p_info->type))
+        return;
+    getchar();
+
+    printf("please enter test number(emergency ecall should be empty): ");
+    find = NULL;
+    if(NULL == fgets(p_info->test_number, sizeof(p_info->test_number)-1, stdin))
+        return;
+    find = strchr(p_info->test_number, '\n');
+    if(find)
+    {
+        *find = '\0';
+    }
+
+    printf("how to trigger eCall(0 - manual, 1 - auto): ");
+    if(1 != scanf("%d", &p_info->auto_trigger))
+        return;
+    getchar();
+
+    ret = ql_ecall_dial(sim_id, p_info, &id);
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok, call_id is %u\n", id);
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+
+    free(p_info);
+    p_info = NULL;
+}
+
+void item_ql_ecall_dial(void)
+{
+    printf("test ql_voice_ecall_dial: \n");
+    printf("Is fast ecall? (1 - yes, other - wrong): ");
+    int is_fast;
+    scanf("%d", &is_fast);
+    getchar();
+
+    if(is_fast == 1){
+        printf("Dialling fast ecall\n");
+        fast_ecall_dial();
+    }else{
+        printf("Wrong arguments\n");
+    }
+}
+
+void item_ql_ecall_hangup(void)
+{
+    int ret = 0;
+//    int sim_id;
+
+    printf("test ql_voice_ecall_hangup: \n");
+    ret = ql_ecall_hangup();
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+void item_ql_ecall_update_msd_raw(void)
+{
+    int ret = 0, v = 0;
+    uint32_t msd_len = 0;
+    char msd[QL_VOICE_MAX_ECALL_MSD] = {0};
+
+    printf("test ql_voice_ecall_update_msd: \n");
+    printf("example MSD: 01 04 a9 81 d5 49 70 d6 5c 35 97 ca 04 20 c4 14 60 "
+        "0b be 5f 7e b1 4b a6 ee 10 4f c5 27 03 c1 80 q\n");
+    printf("please enter MSD(at most 140 hex), end with 'q': ");
+    while (1 == scanf("%x", &v))
+    {
+        if(msd_len >= QL_VOICE_MAX_ECALL_MSD)
+        {
+            printf("MSD too long\n");
+            int c;
+            while ((c = getchar()) != '\n' && c != EOF) { }
+            return;
+        }
+        else
+        {
+            msd[msd_len++] = v;
+        }
+    }
+    getchar();  // read `q'
+    getchar();  // read '\n'
+
+    ret = ql_ecall_update_msd_raw((uint8_t *)msd, msd_len);
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+void item_ql_ecall_push_msd(void)
+{
+    int ret = 0;
+
+    printf("test ql_voice_ecall_push_msd: \n");
+    ret = ql_ecall_push_msd();
+    if (ret == QL_ERR_OK)
+    {
+        printf("sql_ecall_push_msd OK\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static void ecall_user_ind_callback(int ind, void *userdata)
+{
+    printf("\n****** eCall indication Received ******\n");
+    printf("ecall_indication: %d - ", ind);
+
+    switch(ind){
+        case QL_ECALL_EVENT_SENDING_START:
+            printf("QL_ECALL_EVENT_SENDING_START\n");
+            break;
+        case QL_ECALL_EVENT_SENDING_MSD:
+            printf("QL_ECALL_EVENT_SENDING_MSD\n");
+            break;
+        case QL_ECALL_EVENT_LLACK_RECEIVED:
+            printf("QL_ECALL_EVENT_LLACK_RECEIVED\n");
+            break;
+        case QL_ECALL_EVENT_ALLACK_POSITIVE_RECEIVED:
+            printf("QL_ECALL_EVENT_ALLACK_POSITIVE_RECEIVED\n");
+            break;
+        case QL_ECALL_EVENT_ALLACK_CLEARDOWN_RECEIVED:
+            printf("QL_ECALL_EVENT_ALLACK_CLEARDOWN_RECEIVED\n");
+            break;
+        case QL_ECALL_EVENT_ACTIVE:
+            printf("QL_ECALL_EVENT_ACTIVE\n");
+            break;
+        case QL_ECALL_EVENT_DISCONNECTED:
+            printf("QL_ECALL_EVENT_DISCONNECTED\n");
+            break;
+        case QL_ECALL_EVENT_ABNORMAL_HANGUP:
+            printf("QL_ECALL_EVENT_ABNORMAL_HANGUP\n");
+            break;
+        case QL_ECALL_EVENT_ONLY_DEREGISTRATION:
+            printf("QL_ECALL_EVENT_ONLY_DEREGISTRATION\n");
+            break;
+        case QL_ECALL_EVENT_MAY_DEREGISTRATION:
+            printf("QL_ECALL_EVENT_MAY_DEREGISTRATION\n");
+            break;
+        case QL_ECALL_EVENT_PSAP_CALLBACK_START:
+            printf("QL_ECALL_EVENT_PSAP_CALLBACK_START\n");
+            break;
+        case QL_ECALL_EVENT_T2_TIMEOUT:
+            printf("QL_ECALL_EVENT_T2_TIMEOUT\n");
+            break;
+        case QL_ECALL_EVENT_T5_TIMEOUT:
+            printf("QL_ECALL_EVENT_T5_TIMEOUT\n");
+            break;
+        case QL_ECALL_EVENT_T6_TIMEOUT:
+            printf("QL_ECALL_EVENT_T6_TIMEOUT\n");
+            break;
+        case QL_ECALL_EVENT_T7_TIMEOUT:
+            printf("QL_ECALL_EVENT_T7_TIMEOUT\n");
+            break;
+        case QL_ECALL_EVENT_ECALL_STARTED:
+            printf("QL_ECALL_EVENT_ECALL_STARTED\n");
+            break;
+        case QL_ECALL_EVENT_INCOMING_CALL:
+            printf("QL_ECALL_EVENT_INCOMING_CALL\n");
+            break;
+        case QL_ECALL_EVENT_DIAL_DURATION_TIMEOUT:
+            printf("QL_ECALL_EVENT_DIAL_DURATION_TIMEOUT\n");
+            break;
+        case QL_ECALL_EVENT_INTERVAL_TIMEOUT:
+            printf("QL_ECALL_EVENT_INTERVAL_TIMEOUT\n");
+            break;
+        case QL_ECALL_EVENT_AUTO_ANSWER_TIMEOUT:
+            printf("QL_ECALL_EVENT_AUTO_ANSWER_TIMEOUT\n");
+            break;
+        default:
+            printf("UNKNOWN\n");
+            break;
+    }
+}
+
+void item_ql_ecall_init(void)
+{
+    int ret = 0;
+
+    printf("test ql_ecall_init: ");
+    ret = ql_ecall_init();
+    if(ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+void item_ql_ecall_deinit(void)
+{
+    int ret = 0;
+
+    printf("test ql_ecall_deinit: ");
+    ret = ql_ecall_deinit();
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+void item_ql_ecall_set_user_ind_cb(void)
+{
+    ql_ecall_set_user_ind_cb(ecall_user_ind_callback, NULL);
+}
+
+void item_ql_ecall_set_msd_version(void)
+{
+    int ret = 0;
+    uint8_t index=0;
+
+    printf("ecall MSD version(1-ASN1_ECALL_MSD_VERSION_1;  2-ASN1_ECALL_MSD_VERSION_2): \n");
+    scanf("%hhd", &index);
+    getchar();
+
+    if (1 == index)
+    {
+        ret = ql_ecall_set_msd_version(ASN1_ECALL_MSD_VERSION_1);
+        printf(" ql_ecall_get_msd_version ret = %d\n", ret);
+    }
+    else if(2 == index)
+    {
+        ret = ql_ecall_set_msd_version(ASN1_ECALL_MSD_VERSION_2);
+        printf(" ql_ecall_get_msd_version ret = %d\n", ret);
+    }
+    else
+    {
+        printf(" This version is not surport.\n");
+    }
+
+}
+
+void item_ql_ecall_get_msd_version(void)
+{
+    uint8_t msdVersion = 0;
+
+    ql_ecall_get_msd_version(&msdVersion);
+
+    if(msdVersion == ASN1_ECALL_MSD_VERSION_1)//unsupported
+    {
+        printf("MSD version is set to ASN1_ECALL_MSD_VERSION_1.\n");
+    }
+    else if (msdVersion == ASN1_ECALL_MSD_VERSION_2)//supported
+    {
+        printf("MSD version is set to ASN1_ECALL_MSD_VERSION_2.\n");
+    }
+    else
+    {
+        printf(" This version is not surport.\n");
+    }
+
+}
+
+void item_ql_ecall_set_system_type(void)
+{
+    int ret = 0;
+    uint8_t index=0;
+
+    printf("ecall system type(0-ECALL_SYSTEM_STD_PAN_EUROPEAN;  1-ECALL_SYSTEM_STD_ERA_GLONASS): \n");
+    scanf("%hhd", &index);
+    getchar();
+
+    if (0 == index)
+    {
+        ret = ql_ecall_set_system_std(ECALL_SYSTEM_STD_PAN_EUROPEAN);
+        printf(" ql_ecall_set_system_std ret = %d\n", ret);
+    }
+    else if(1 == index)
+    {
+        ret = ql_ecall_set_system_std(ECALL_SYSTEM_STD_ERA_GLONASS);
+        printf(" ql_ecall_set_system_std ret = %d\n", ret);
+    }
+    else
+    {
+        printf(" This version is not surport.\n");
+    }
+}
+
+void item_ql_ecall_get_system_type(void)
+{
+    ECALL_SYSTEM_STD_E system_std;
+    ql_ecall_get_system_std(&system_std);
+    if(system_std == ECALL_SYSTEM_STD_PAN_EUROPEAN)
+    {
+        printf("Ecall system type set to ECALL_SYSTEM_STD_PAN_EUROPEAN.\n");
+    }
+    else if (system_std == ECALL_SYSTEM_STD_ERA_GLONASS)
+    {
+        printf("Ecall system type set to ECALL_SYSTEM_STD_ERA_GLONASS.\n");
+    }
+    else
+    {
+        printf("Ecall system type set to unsupported value.\n");
+    }
+}
+
+void item_ql_ecall_set_msd_vehicle_type(void)
+{
+    int ret = 0;
+    uint8_t index=0;
+
+    printf("Please input VehicleType:\n");
+    printf("MSD_VEHICLE_PASSENGER_M1=1\n");
+    printf("MSD_VEHICLE_BUS_M2=2\n");
+    printf("MSD_VEHICLE_BUS_M3=3\n");
+    printf("MSD_VEHICLE_COMMERCIAL_N1=4\n");
+    printf("MSD_VEHICLE_HEAVY_N2=5\n");
+    printf("MSD_VEHICLE_HEAVY_N3=6\n");
+    printf("MSD_VEHICLE_MOTORCYCLE_L1E=7\n");
+    printf("MSD_VEHICLE_MOTORCYCLE_L2E=8\n");
+    printf("MSD_VEHICLE_MOTORCYCLE_L3E=9\n");
+    printf("MSD_VEHICLE_MOTORCYCLE_L4E=10\n");
+    printf("MSD_VEHICLE_MOTORCYCLE_L5E=11\n");
+    printf("MSD_VEHICLE_MOTORCYCLE_L6E=12\n");
+    printf("MSD_VEHICLE_MOTORCYCLE_L7E=13\n");
+
+    scanf("%hhd", &index);
+    getchar();
+
+    ret = ql_ecall_set_msd_vehicle_type(index);
+    printf(" ql_ecall_set_msd_vehicle_type ret = %d\n", ret);
+
+}
+
+void item_ql_ecall_get_msd_vehicle_type(void)
+{
+    uint8_t vehicleType = 0;
+    ql_ecall_get_msd_vehicle_type(&vehicleType);
+    printf("VehicalType is set to: %u\n", vehicleType);
+
+}
+
+void item_ql_ecall_set_msd_position(void)
+{
+    int ret = 0;
+    int32_t latitude, longitude, direction = 0;
+
+    printf("Please input latitude(example:+48898064):\n");
+    scanf("%d", &latitude);
+    getchar();
+
+    printf("Please input longitude(example:+2218092):\n");
+    scanf("%d", &longitude);
+    getchar();
+
+    printf("Please input direction(example:0):\n");
+    scanf("%d", &direction);
+    getchar();
+
+    ret = ql_ecall_set_msd_position(true, latitude, longitude, direction);
+    printf(" ql_ecall_set_msd_position ret = %d\n", ret);
+}
+
+void item_ql_ecall_set_msd_position1(void)
+{
+    int ret = 0;
+    int32_t latitudeDeltaN1, longitudeDeltaN1 = 0;
+
+    printf("Please input latitudeDeltaN1(-512 ~ 511):\n");
+    scanf("%d", &latitudeDeltaN1);
+    getchar();
+
+    printf("Please input longitudeDeltaN1(-512 ~ 511):\n");
+    scanf("%d", &longitudeDeltaN1);
+    getchar();
+
+    ret = ql_ecall_set_msd_position_n1(latitudeDeltaN1, longitudeDeltaN1);
+    printf(" ql_ecall_set_msd_position_n1 ret = %d\n", ret);
+}
+
+void item_ql_ecall_set_msd_position2(void)
+{
+    int ret = 0;
+    int32_t latitudeDeltaN2, longitudeDeltaN2 = 0;
+
+    printf("Please input latitudeDeltaN2(-512 ~ 511):\n");
+    scanf("%d", &latitudeDeltaN2);
+    getchar();
+
+    printf("Please input longitudeDeltaN2(-512 ~ 511):\n");
+    scanf("%d", &longitudeDeltaN2);
+    getchar();
+
+    ret = ql_ecall_set_msd_position_n2(latitudeDeltaN2, longitudeDeltaN2);
+    printf(" ql_ecall_set_msd_position_n2 ret = %d\n", ret);
+}
+
+void item_ql_ecall_set_number_of_passengers(void)
+{
+//    int ret = 0;
+    uint8_t numberOfPassengers=0;
+
+    printf("Please input msd numberOfPassengers:\n");
+    if(1 != scanf("%hhd", &numberOfPassengers))
+        return;
+    getchar();
+
+    ql_ecall_set_msd_passengers_count(numberOfPassengers);
+}
+
+void item_ql_ecall_set_msd_propulsion_type(void)
+{
+//    int ret = 0;
+    uint8_t propulsionType = 0;
+
+    printf("Please input vehicle propulsion type:\n");
+    printf("ECALL_MSD_PROPULSION_TYPE_GASOLINE=0x1\n");
+    printf("ECALL_MSD_PROPULSION_TYPE_DIESEL=0x2\n");
+    printf("ECALL_MSD_PROPULSION_TYPE_NATURALGAS=0x4\n");
+    printf("ECALL_MSD_PROPULSION_TYPE_PROPANE=0x8\n");
+    printf("ECALL_MSD_PROPULSION_TYPE_ELECTRIC=0x10\n");
+    printf("ECALL_MSD_PROPULSION_TYPE_HYDROGEN=0x20\n");
+    printf("ECALL_MSD_PROPULSION_TYPE_OTHER=0x40\n");
+
+    scanf("%hhx", &propulsionType);
+    getchar();
+
+    ql_ecall_set_msd_propulsion_type(propulsionType);
+}
+
+void item_ql_ecall_get_msd_propulsion_type(void)
+{
+    uint8_t propulsionType = 0;
+
+    ql_ecall_get_msd_propulsion_type(&propulsionType);
+
+    printf("PropulsionType set to: 0x%x\n", propulsionType);
+
+}
+
+void item_ql_ecall_get_msd_call_type(void)
+{
+
+    bool type;
+    ql_ecall_get_msd_call_type(&type);
+
+    printf(" item_ql_ecall_get_msd_call_type type = %s\n", type ? "Test" : "Emergency" );
+}
+
+void item_ql_ecall_set_msd_call_type(void)
+{
+    uint8_t index = 0;
+    printf("Input call type: Test(0) Emergency(1)\n");
+    scanf("%hhd", &index);
+    getchar();
+
+    ql_ecall_set_msd_call_type(index == 0);
+
+    printf(" ql_ecall_set_msd_call_type type = %d\n", index);
+}
+
+
+void item_ql_ecall_set_msd_vin(void)
+{
+    int ret = 0;
+    uint8_t index = 0;
+    msd_Vin_t vin = {0};
+    char* find = NULL;
+    char vin_str[QL_ECALL_MAX_VIN];
+
+    printf("Input: default(0) other(1)\n");
+    scanf("%hhd", &index);
+    getchar();
+    if(index)
+    {
+        printf("Please insert VIN:\n");
+        fgets(vin_str, QL_ECALL_MAX_VIN-1, stdin);
+        find = strchr(vin_str, '\n');
+        if(find)
+        {
+            *find = '\0';
+        }
+        // example 1: WM9VDSVDSYA123456
+        // example 2: 4Y1SL65848Z411439
+        // example 3: VF37BRFVE12345678
+        memcpy(&vin.isowmi, vin_str,3);
+        memcpy(&vin.isovds, (vin_str+3),6);
+        memcpy(&vin.isovisModelyear, (vin_str+9) ,1);
+        memcpy(&vin.isovisSeqPlant,  (vin_str+10) ,7);
+        printf("isowmi:%s isovds:%s isovisModelyear:%s,isovisSeqPlant:%s\n",vin.isowmi,vin.isovds,vin.isovisModelyear,vin.isovisSeqPlant);
+    }
+    else
+    {
+        memcpy(&vin.isowmi,"WM9",3);
+        memcpy(&vin.isovds,"VDSVDS",6);
+        memcpy(&vin.isovisModelyear,"Y",1);
+        memcpy(&vin.isovisSeqPlant,"A123456",7);
+        printf("isowmi:%s isovds:%s isovisModelyear:%s,isovisSeqPlant:%s\n",vin.isowmi,vin.isovds,vin.isovisModelyear,vin.isovisSeqPlant);
+    }
+
+    ret = ql_ecall_set_msd_vin(vin);
+    printf(" ql_ecall_set_msd_vin ret = %d\n", ret);
+}
+
+void item_ql_ecall_get_msd_vin(void)
+{
+    int ret = 0;
+    msd_Vin_t vin;
+    char vin_str[QL_ECALL_MAX_VIN];
+
+    ret = ql_ecall_get_msd_vin(&vin);
+    if(0<strlen(vin.isowmi)&&0<strlen(vin.isovds)&&0<strlen(vin.isovisModelyear)&&0<strlen(vin.isovisSeqPlant))
+    {
+        sprintf(vin_str,"%s%s%s%s",vin.isowmi,vin.isovds,vin.isovisModelyear,vin.isovisSeqPlant);
+    }
+    else
+    {
+        printf(" vin is NULL\n");
+        return;
+    }
+    printf(" ql_ecall_get_msd_vin ret = %d\n", ret);
+
+    printf("VIN=%s\n",vin_str);
+}
+
+void item_ql_ecall_set_msd_tx_mode(void)
+{
+    int ret = 0;
+    uint8_t index = 0;
+
+    printf("Please choose MSD Tx Mode: PULL(0) PUSH(1)\n");
+    scanf("%hhd", &index);
+    getchar();
+
+    if(index == 0)
+    {
+        ret = ql_ecall_set_msd_tx_mode(QL_ECALL_TX_MODE_PULL);
+        printf(" ql_ecall_set_msd_tx_mode ret = %d\n", ret);
+    }
+    else if(index == 1)
+    {
+        ret = ql_ecall_set_msd_tx_mode(QL_ECALL_TX_MODE_PUSH);
+        printf(" ql_ecall_set_msd_tx_mode ret = %d\n", ret);
+    }
+    else
+    {
+        printf("Unsupported MSD transmission mode.\n");
+    }
+}
+
+void item_ql_ecall_get_msd_tx_mode(void)
+{
+    QL_ECALL_MSD_TX_MODE_E tx_mode;
+
+    ql_ecall_get_msd_tx_mode(&tx_mode);
+    if(tx_mode == QL_ECALL_TX_MODE_PULL)
+    {
+        printf("MSD Transmission mode is set to QL_ECALL_TX_MODE_PULL\n");
+    }
+    else if (tx_mode == QL_ECALL_TX_MODE_PUSH)
+    {
+        printf("MSD Transmission mode is set to QL_ECALL_TX_MODE_PUSH\n");
+    }
+}
+
+void item_ql_ecall_start_test(void)
+{
+    int ret = 0;
+    int sim_id;
+
+    printf("please enter the sim_id: ");
+    ret = scanf("%d", &sim_id);
+    getchar();
+
+    if(!QL_IS_SIM_VALID(sim_id))
+    {
+        printf("invalid sim_id\n");
+        return;
+    }
+
+    ret = ql_ecall_start_test(sim_id);
+    printf(" ql_ecall_start_test ret = %d\n", ret);
+}
+
+void item_ql_ecall_start_manual(void)
+{
+    int ret = 0;
+    int sim_id;
+
+    printf("please enter the sim_id: ");
+    ret = scanf("%d", &sim_id);
+    getchar();
+
+    if(!QL_IS_SIM_VALID(sim_id))
+    {
+        printf("invalid sim_id\n");
+        return;
+    }
+
+    ret = ql_ecall_start_manual(sim_id);
+    printf(" ql_ecall_start_manual ret = %d\n", ret);
+}
+
+void item_ql_ecall_start_automatic(void)
+{
+    int ret = 0;
+    int sim_id;
+
+    printf("please enter the sim_id: ");
+    ret = scanf("%d", &sim_id);
+    getchar();
+
+    if(!QL_IS_SIM_VALID(sim_id))
+    {
+        printf("invalid sim_id\n");
+        return;
+    }
+
+    ret = ql_ecall_start_automatic(sim_id);
+    printf(" ql_ecall_start_automatic ret = %d\n", ret);
+}
+
+void item_ql_ecall_terminate_nw_registration(void)
+{
+    int ret;
+
+    ret = ql_ecall_terminate_nw_registration();
+    if(ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+void item_ql_ecall_set_interval_between_attempts(void)
+{
+    uint16_t interval = 0;
+
+    printf("Please input interval between attempts in seconds:\n");
+    scanf("%hd", &interval);
+    getchar();
+
+    ql_ecall_set_interval_between_dial_attempts(interval);
+}
+
+void item_ql_ecall_get_interval_between_attempts(void)
+{
+    uint16_t interval = 0;
+    ql_ecall_get_interval_between_dial_attempts(&interval);
+
+    printf("Interval between attempts is set to %hd seconds:\n", interval);
+
+}
+
+void item_ql_ecall_update_msd (void)
+{
+    int ret = 0;
+    ret = ql_ecall_update_msd();
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+void item_ql_ecall_set_config_info(void)
+{
+    ql_ecall_config_t ecall_context_info;
+
+    printf("Whether the time of T5 timer is valid(0:no, 1:yes):\n");
+    scanf("%hhd", &ecall_context_info.t5_timeout_ms_valid);
+    getchar();
+    if(ecall_context_info.t5_timeout_ms_valid)
+    {
+        printf("please input the time of T5 timer(example:5000ms):\n");
+        scanf("%hd", &ecall_context_info.t5_timeout_ms);
+        getchar();
+    }
+
+    printf("Whether the time of T6 timer is valid(0:no, 1:yes):\n");
+    scanf("%hhd", &ecall_context_info.t6_timeout_ms_valid);
+    getchar();
+    if(ecall_context_info.t6_timeout_ms_valid)
+    {
+        printf("please input the time of T6 timer(example:5000ms):\n");
+        scanf("%hd", &ecall_context_info.t6_timeout_ms);
+        getchar();
+    }
+
+    printf("Whether the time of T7 timer is valid(0:no, 1:yes):\n");
+    scanf("%hhd", &ecall_context_info.t7_timeout_ms_valid);
+    getchar();
+    if(ecall_context_info.t7_timeout_ms_valid)
+    {
+        printf("please input the time of T7 timer(example:20000ms):\n");
+        scanf("%hd", &ecall_context_info.t7_timeout_ms);
+        getchar();
+    }
+
+    printf("Whether the time of auto answer timer is valid(0:no, 1:yes):\n");
+    scanf("%hhd", &ecall_context_info.autoAnswer_timeout_ms_valid);
+    getchar();
+    if(ecall_context_info.autoAnswer_timeout_ms_valid)
+    {
+        printf("please input the time of auto answer  timer(example:3600000ms):\n");
+        scanf("%d", &ecall_context_info.autoAnswer_timeout_ms);
+        getchar();
+    }
+
+    printf("Whether the time of dialDurationTimer is valid(0:no, 1:yes):\n");
+    scanf("%hhd", &ecall_context_info.dialDurationTimer_timout_ms_valid);
+    getchar();
+    if(ecall_context_info.dialDurationTimer_timout_ms_valid)
+    {
+        printf("please input the time of dialDurationTimer(example:120000ms):\n");
+        scanf("%d", &ecall_context_info.dialDurationTimer_timout_ms);
+        getchar();
+    }
+
+    printf("(Not supported)Whether the maxDialAttempts is valid(0:no, 1:yes):\n");
+    scanf("%hhd", &ecall_context_info.maxDialAttempts_valid);
+    getchar();
+    if(ecall_context_info.maxDialAttempts_valid)
+    {
+        printf("please input maxDialAttempts:\n");
+        scanf("%d", &ecall_context_info.maxDialAttempts);
+        getchar();
+    }
+
+    printf("(Not supported)Whether the intervalBetweenAttempts is valid(0:no, 1:yes):\n");
+    scanf("%hhd", &ecall_context_info.intervalBetweenAttempts_valid);
+    getchar();
+    if(ecall_context_info.intervalBetweenAttempts_valid)
+    {
+        printf("please input intervalBetweenAttempts(example:30s):\n");
+        scanf("%hd", &ecall_context_info.intervalBetweenAttempts);
+        getchar();
+    }
+
+    printf("(Not supported)Whether the resetEcallSessionMode is valid(0:no, 1:yes):\n");
+    scanf("%hhd", &ecall_context_info.resetEcallSessionMode_valid);
+    getchar();
+    if(ecall_context_info.resetEcallSessionMode_valid)
+    {
+        printf("please input resetEcallSessionMode(example: 1,autoanswer):\n");
+        scanf("%hhd", &ecall_context_info.resetEcallSessionMode);
+        getchar();
+    }
+
+    ql_ecall_set_config_info(ecall_context_info);
+    printf("ok!\n");
+}
+
+void item_ql_ecall_get_config_info(void)
+{
+    ql_ecall_config_t ecall_context_info;
+
+    ql_ecall_get_config_info(&ecall_context_info);
+
+    printf("ok!\n");
+    printf("the time of T5 timer is %hd\n", ecall_context_info.t5_timeout_ms);
+    printf("the time of T6 timer is %hd\n", ecall_context_info.t6_timeout_ms);
+    printf("the time of T7 timer is %hd\n", ecall_context_info.t7_timeout_ms);
+    printf("the time of dialDurationTimer is %d\n", ecall_context_info.dialDurationTimer_timout_ms);
+    printf("the maximum redial attempts is %d\n", ecall_context_info.maxDialAttempts);
+    //printf("the interval value between dial attempts is %hd\n", ecall_context_info.intervalBetweenAttempts);
+}
+
+void item_ql_ecall_set_ecall_only_mode(void)
+{
+    int ret = 0;
+    int ecall_only_value = 0;
+
+    printf("ecall set ecall only mode(0:disable,1:enable): \n");
+    scanf("%d", &ecall_only_value);
+    getchar();
+
+    ret = ql_ecall_set_ecall_only_mode(ecall_only_value);
+    printf(" ql_ecall_set_ecall_only_mode ret = %d\n", ret);
+}
+
+static t_item_t ql_ecall_items[] =
+{
+    {"ql_ecall_init", item_ql_ecall_init},
+    {"ql_ecall_dial", item_ql_ecall_dial},
+    {"ql_ecall_start_test", item_ql_ecall_start_test},
+    {"ql_ecall_start_manual", item_ql_ecall_start_manual},
+    {"ql_ecall_start_automatic", item_ql_ecall_start_automatic},
+    {"ql_ecall_hangup", item_ql_ecall_hangup},
+    {"ql_ecall_set_user_ind_cb", item_ql_ecall_set_user_ind_cb},
+    {"ql_voice_ecall_set_test_number", item_ql_ecall_set_test_number},
+    {"ql_ecall_set_system_type", item_ql_ecall_set_system_type},
+    {"ql_ecall_get_system_type", item_ql_ecall_get_system_type},
+    {"ql_ecall_update_msd_raw", item_ql_ecall_update_msd_raw},
+    {"ql_ecall_push_msd", item_ql_ecall_push_msd},
+    {"ql_voice_ecall_reset_ivs", item_ql_ecall_reset_ivs},
+    {"ql_ecall_set_msd_call_type", item_ql_ecall_set_msd_call_type},
+    {"ql_ecall_get_msd_call_type", item_ql_ecall_get_msd_call_type},
+    {"ql_ecall_set_msd_vin", item_ql_ecall_set_msd_vin},
+    {"ql_ecall_get_msd_vin", item_ql_ecall_get_msd_vin},
+    {"ql_ecall_set_msd_version", item_ql_ecall_set_msd_version},
+    {"ql_ecall_get_msd_version", item_ql_ecall_get_msd_version},
+    {"ql_ecall_set_msd_tx_mode", item_ql_ecall_set_msd_tx_mode},
+    {"ql_ecall_get_msd_tx_mode", item_ql_ecall_get_msd_tx_mode},
+    {"ql_ecall_set_msd_position", item_ql_ecall_set_msd_position},
+    {"ql_ecall_set_msd_position1", item_ql_ecall_set_msd_position1},
+    {"ql_ecall_set_msd_position2", item_ql_ecall_set_msd_position2},
+    {"ql_ecall_set_msd_vehicle_type", item_ql_ecall_set_msd_vehicle_type},
+    {"ql_ecall_get_msd_vehicle_type", item_ql_ecall_get_msd_vehicle_type},
+    {"ql_ecall_set_number_of_passengers", item_ql_ecall_set_number_of_passengers},
+    {"ql_ecall_set_msd_propulsion_type", item_ql_ecall_set_msd_propulsion_type},
+    {"ql_ecall_get_msd_propulsion_type", item_ql_ecall_get_msd_propulsion_type},
+    {"ql_ecall_terminate_nw_registration", item_ql_ecall_terminate_nw_registration},
+    {"ql_ecall_set_interval_between_attempts", item_ql_ecall_set_interval_between_attempts},
+    {"ql_ecall_get_interval_between_attempts", item_ql_ecall_get_interval_between_attempts},
+    {"ql_ecall_update_msd", item_ql_ecall_update_msd},
+    {"ql_ecall_set_config_info", item_ql_ecall_set_config_info},
+    {"ql_ecall_get_config_info", item_ql_ecall_get_config_info},
+    {"ql_ecall_set_ecall_only_mode", item_ql_ecall_set_ecall_only_mode},
+    {"ql_ecall_deinit", item_ql_ecall_deinit}
+};
+
+static void help()
+{
+    int i = 0;
+    printf("Test Items:\n");
+    while(i < ARRAY_SIZE(ql_ecall_items)) {
+        printf("%d : %s\n", i, ql_ecall_items[i].name);
+        i++;
+    }
+    printf(":");
+}
+
+int main(int argc, char *argv[])
+{
+    char cmd[1024];
+    help();
+    while(1)
+    {
+        memset(cmd, 0, sizeof(cmd));
+        if(fgets(cmd, sizeof(cmd), stdin))
+        {
+            char *ptr = cmd + strlen(cmd) - 1;
+            while(ptr >= cmd && (*ptr == '\r' || *ptr == '\n'))
+            {
+                *ptr-- = '\0';
+            }
+
+            if(strlen(cmd) > 0) {
+                if(isdigit(cmd[0])) {
+                    int item = atoi(cmd);
+                    if(item >= 0 && item < ARRAY_SIZE(ql_ecall_items)) {
+                        ql_ecall_items[item].handle();
+                    }
+                }
+                else if(!strcasecmp(cmd, "h")) {
+                    help();
+                }
+                else if(!strcasecmp(cmd, "q")) {
+                    break;
+                }
+            }
+            else {
+                printf("\n");
+            }
+        }
+    }
+    return 0;
+}
+
diff --git a/mbtk/test/libql_lib_v2/ql_gnss_test.c b/mbtk/test/libql_lib_v2/ql_gnss_test.c
new file mode 100755
index 0000000..dc766a9
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_gnss_test.c
@@ -0,0 +1,725 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_gnss_test.c
+  @brief GNSS 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 <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "ql_test_utils.h"
+#include "ql_type.h"
+#include "ql_gnss.h"
+
+#define IS_DIGIT(x)    ( ((x-'0')>=0) && ((x-'0')<=9) )
+
+
+static void gnss_ind_cb(void *msg)
+{
+    uint8_t *msg_id = NULL; 
+    msg_id = msg;
+    if(*msg_id == QL_GNSS_NMEA_MSG)
+    {
+        nmea_srv_ind_msg *data = (nmea_srv_ind_msg *)msg;
+        printf("time=%d %s",data->time,data->nmea_sentence);
+    }
+    else if (*msg_id == QL_GNSS_STATUS_MSG)
+    {
+        gnss_status_ind_msg *data = (gnss_status_ind_msg *)msg;
+        switch(data->g_status)
+        {
+            case QL_GNSS_STATUS_FOTA_START:
+                printf("gnss engine fota req\n");
+                break;    
+            case QL_GNSS_STATUS_FOTA_BOOT:
+                printf("gnss engine fota bootloader\n");
+                break;    
+            case  QL_GNSS_STATUS_FOTA_FIRM:
+                printf("gnss engine fota firmware\n");
+                break;    
+            case  QL_GNSS_STATUS_WORKING:
+                printf("gnss engine working\n");
+                break;    
+            default:
+                break;
+        };
+    }
+    else
+    {
+      printf("Invalue msg !!!");
+    }
+}
+
+#if 0
+static void gnss_service_error_cb(int error)
+{
+    printf("===== GNSS Service Abort =====\n");
+}
+#endif
+
+static void item_ql_gnss_init(void)
+{
+    int err = QL_ERR_OK;
+    printf("Start to ql_gnss_init\n");
+    err = ql_gnss_init();
+    if(err == QL_ERR_OK)
+    {
+        printf("Successful\n");
+    }
+    else
+    {
+        printf("Failed to ql_gnss_init, err=%d\n", err);
+    }
+}
+
+
+static void item_ql_gnss_set_ind_cb(void)
+{
+    int err = QL_ERR_OK;
+
+    printf("Start to ql_gnss_set_ind_cb\n");
+    err = ql_gnss_set_ind_cb(gnss_ind_cb);
+    if(err != QL_ERR_OK)
+    {
+        printf("Failed to ql_gnss_set_ind_cb, err=%d\n", err);
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+}
+
+#if 0
+static void item_ql_gnss_set_service_error_cb(void)
+{
+    int err = QL_ERR_OK;
+    printf("Start to item_ql_gnss_set_service_error_cb\n");
+    err = ql_gnss_set_service_error_cb(gnss_service_error_cb);
+    if(err == QL_ERR_OK)
+    {
+        printf("Successful\n");
+    }
+    else
+    {
+        printf("Failed to item_ql_gnss_set_service_error_cb, err=%d\n", err);
+    }
+
+}
+#endif
+
+static void item_ql_gnss_start(void)
+{
+    int err = QL_ERR_OK;
+
+    printf("Start to ql_gnss_start\n");
+    err = ql_gnss_start();
+    if(err != QL_ERR_OK)
+    {
+        printf("Failed to start gnss , err=%d\n", err);
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+}
+
+
+static void item_ql_gnss_stop(void)
+{
+    int err = QL_ERR_OK;
+    
+    printf("Start to ql_gnss_stop\n");
+    err = ql_gnss_stop();
+    if(err != QL_ERR_OK)
+    {
+        printf("Failed to stop gnss, err=%d\n", err);
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+}
+
+#if 0
+static void item_ql_gnss_get_engine_state(void)
+{
+    int err = QL_ERR_OK;
+    QL_GNSS_ENGINE_STATE_E state = 0;
+
+    printf("Start ql_gnss_get_engine_state : \n");
+    err = ql_gnss_get_engine_state(&state);
+    if(err != QL_ERR_OK)
+    {
+        printf("Get engine state  faild %d\n",err);
+    }
+    else
+    {
+        if(state)
+        {
+            printf("Engine state is on\n");
+        }
+        else
+        {
+            printf("Engine state is off\n");
+        }
+    }
+}
+#endif
+
+#if 0
+static void ql_gnss_get_constellation_show(char *str_p, QL_GNSS_CONSTELLATION_MASK_E mask)
+{
+    switch (mask)
+    {
+    case GPS_ONLY:
+        snprintf(str_p, 100, "%s", "GPS");
+        break;
+    case BDS_ONLY:
+        snprintf(str_p, 100, "%s", "BDS_ONLY");
+        break;
+    case GPS_BDS:
+        snprintf(str_p, 100, "%s", "GPS+BDS");
+        break;
+    case GLONASS_ONLY:
+        snprintf(str_p, 100, "%s", "GLONASS_ONLY");
+        break;
+    case GPS_GLONASS:
+        snprintf(str_p, 100, "%s", "GPS+GLONASS");
+        break; 
+    case BDS_GLONASS:
+        snprintf(str_p, 100, "%s", "BDS+GLONASS");
+        break;
+    case GPS_BDS_GLONASS:
+        snprintf(str_p, 100, "%s", "GPS+BDS+GLONASS");
+        break;
+    case GPS_SBAS_QZSS:
+        snprintf(str_p, 100, "%s", "GPS+SBAS+QZSS");
+        break;
+    case GPS_BDS_GALILEO_SBAS_QZSS:
+        snprintf(str_p, 100, "%s", "GPS+BDS+GALILEO+SBAS+QZSS");
+        break;
+    case GPS_GLONASS_GALILEO_SBAS_QZSS:
+        snprintf(str_p, 100, "%s", "GPS+GLONASS+GALILEO+SBAS+QZSS");
+        break;
+    default:
+        snprintf(str_p, 100, "%s", "error");
+        break;
+    };
+}
+
+static void item_ql_gnss_get_constellation(void)
+{
+    int err = QL_ERR_OK;
+    QL_GNSS_CONSTELLATION_MASK_E mask = 0;
+    printf("Start ql_gnss_get_constellation : \n");
+    err = ql_gnss_get_constellation(&mask);
+    if (err != QL_ERR_OK)
+    {
+        printf("Set Constellation  faild %d\n", err);
+    }
+    else
+    {
+        switch (mask)
+        {
+        case GPS_SBAS_QZSS:
+            printf("GPS+SBAS+QZSS\n");
+            break;
+        case BDS_ONLY:
+            printf("BDS_ONLY\n");
+            break;
+        case GPS_BDS_GALILEO_SBAS_QZSS:
+            printf("GPS+BDS+GALILEO+SBAS+QZSS\n");
+            break;
+        case GPS_GLONASS_GALILEO_SBAS_QZSS:
+            printf("GPS+GLONASS+GALILEO+SBAS+QZSS\n");
+            break;
+        case GPS_ONLY:
+            printf("GPS_ONLY\n");
+            break;
+        case GPS_BDS:
+            printf("GPS_BDS\n");
+            break;
+        case GLONASS_ONLY:
+            printf("GLONASS_ONLY\n");
+            break;
+        case GPS_GLONASS:
+            printf("GPS+GLONASS\n");
+            break;
+        case BDS_GLONASS:
+            printf("BDS+GLONASS\n");
+            break;
+        case GPS_BDS_GLONASS:
+            printf("GPS+BDS+GLONASS\n");
+            break;
+        default:
+            break;
+        };
+    }
+}
+
+/*
+EC200 Supported constellations
+(GPS+SBAS+QZSS--0x08|BDS_ONLY--0x10|GPS+BDS+GALILEO+SBAS+QZSS--0x11|GPS+GLONASS+GALILEO+SBAS+QZSS--0x101)");
+
+AG35CET  Supported constellations
+(GPS_ONLY--0x01|BDS_ONLY--0x02|GPS_BDS--0x03|GLONASS_ONLY--0x04)|GPS_GLONASS--0x05|BDS_GLONASS--0x06|GPS_BDS_GLONASS--0x07")
+
+AG35EUT  Supported constellations
+(GPS_ONLY--0x01|BDS_ONLY--0x02|GPS_BDS--0x03|GLONASS_ONLY--0x04)|GPS_GLONASS--0x05|BDS_GLONASS--0x06|GPS_BDS_GLONASS--0x07|
+GALILEO_ONLY--0x08|GPS_GALILEO--0x09|BD_GALILEO--0x10|GPS_BDS_GLONASS_GALILEO--0x11")
+*/
+static void item_ql_gnss_set_constellation(void)
+{
+    int err = QL_ERR_OK;
+    uint32_t input = 0;
+    QL_GNSS_CONSTELLATION_MASK_E constellation = 0;
+    printf("Please input gnss constellation:\n");
+    scanf("%x",&input);
+    printf("input=%x\n",input);
+    constellation = (QL_GNSS_CONSTELLATION_MASK_E)input;
+    err = ql_gnss_set_constellation(constellation);
+    if(err != QL_ERR_OK)
+    {
+        printf("Failed to set gnss constellation mask:%x err=%d\n",constellation,err);
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+}
+
+static void item_ql_gnss_set_nmea_type(void)
+{
+    int err = QL_ERR_OK;
+    uint32_t input = 0;
+
+    printf("Please input nmea type bitmask:\n");
+    printf("(GST|ZDA|VTG|RMC|GSV|GSA|GLL|GGA)(HEX Base, i.e.0xff)\n");
+    scanf("%x",&input);
+    printf("input=%x\n",input);
+    err = ql_gnss_set_nmea_type(input);
+    if(err != QL_ERR_OK)
+    {
+        printf("Failed to set nmea type with type:%x: err=%d\n",input,err);
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+}
+
+static void item_ql_gnss_get_nmea_version(void)
+{
+    int err = QL_ERR_OK;
+    QL_GNSS_NMEA_VERSION_ID_E version = 0;
+
+    printf("Start to get nmea_version \n");
+    err = ql_gnss_get_nmea_version(&version);
+    if(err != QL_ERR_OK)
+    {
+        printf("Failed to get nmea_version with version:%d, err=%d\n",version, err);
+    }
+    else
+    {
+        printf("Successful\n");
+        if(QL_GNSS_NMEA_VERSION_V30 == version)
+        {
+            printf("Nmea_version is 3.0\n");
+        }
+        else if(QL_GNSS_NMEA_VERSION_V41 == version)
+        {
+            printf("Nmea_version is 4.0\n");
+        }
+    }
+    
+}
+
+
+static void item_ql_gnss_set_nmea_version(void)
+{
+    int err = QL_ERR_OK;
+    uint32_t input=0;
+    QL_GNSS_NMEA_VERSION_ID_E version;
+    
+    printf("Please input nmea verson : 0--nema v3.0|1--nema v4.1\n");
+    scanf("%d",&input);
+    printf("Start to set nmea_version with version:%d\n",input);
+    version = (QL_GNSS_NMEA_VERSION_ID_E)input;
+    err = ql_gnss_set_nmea_version(version);
+    if(err != QL_ERR_OK)
+    {
+        printf("Failed to set nmea_version with version:%d, err=%d\n",version, err);
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+}
+#endif
+
+static void item_ql_gnss_set_start_mode(void)
+{
+    int err = QL_ERR_OK;
+    uint32_t input=0;
+    QL_GNSS_START_MODE_E mode;
+
+    printf("Please input mode : 0--cold start|1--warm start|2--hot start\n");
+    scanf("%d",&input);
+    printf("Start to ql_set_start_mode with modem:%d\n",input);
+    mode = (QL_GNSS_START_MODE_E)input;
+    err = ql_gnss_set_start_mode(mode);
+    if(err != QL_ERR_OK)
+    {
+        printf("Failed to Start to ql_set_start_mode with modem:%d, err=%d\n",mode, err);
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+}
+
+
+static void item_ql_gnss_set_agnss_mode(void)
+{
+    int err = QL_ERR_OK;
+    uint32_t input=0;
+
+    printf("Please input mode : 0x01--GPS| 0x02--BD| 0x04--GLONASS| 0x08--GALILEO| 0x10--QZSS \n");
+    scanf("%x",&input);
+    printf("Start to ql_set_agnss_mode with modem:%x\n",input);
+    err = ql_gnss_set_agnss_mode(input);
+    if(err != QL_ERR_OK)
+    {
+        printf("Failed to Start to ql_set_agnss_mode with modem:%d, err=%d\n",input, err);
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+
+}
+
+static void item_ql_gnss_inject_agnss_data(void)
+{
+    int err = QL_ERR_OK;
+
+    err = ql_gnss_inject_agnss_data();
+    if (err != QL_ERR_OK)
+    {
+        printf("Failed to inject agnss  err=%d\n", err);
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+}
+
+#if 0
+static int convertUtcTimeMsec(char *utc_str,uint64_t *msec)
+{
+    int i =0;
+    int temp =0;
+    int date[6] = {0};
+    char ch;
+    unsigned char field = 0;
+    struct tm t;
+    while(1)
+    {
+        ch = utc_str[i++];
+
+        if(IS_DIGIT(ch))
+        {
+            temp *= 10;
+            temp += ch - '0';
+        }
+        else if(ch == ' ')
+        {
+            continue;
+        }
+        else if(ch == '-' || ch == ' ' || ch == ':' || ch == '\0')
+        {
+            date[field] = temp;
+            field++;
+            temp = 0;
+
+            if(ch == '\0')
+            {
+                printf("parse char success\n");
+                break;
+            }
+        }
+        else
+        {
+            printf("ch=%c,ch=%d,invalid char\n",ch,ch);
+            return -1;
+        }
+    }
+
+    if(date[0] < 1900
+        || date[1] < 1 || date[1] > 12
+        || date[2] < 1 || date[2] > 31
+        || date[3] < 0 || date[3] > 23
+        || date[4] < 0 || date[4] > 59
+        || date[5] < 0 || date[5] > 59
+         ) 
+     {
+         return -1;
+     }
+
+     t.tm_sec = date[5];
+     t.tm_min = date[4];
+     t.tm_hour = date[3];
+     t.tm_mday = date[2];
+     t.tm_mon = date[1] -1;
+     t.tm_year = date[0] - 1900;
+     t.tm_isdst = 0;
+
+     *msec = (uint64_t)1000 * (uint64_t)mktime(&t);
+     return 0;
+
+}
+
+static void item_ql_gnss_inject_utc_time(void)
+{
+    int err = QL_ERR_OK;
+    int input = 0;
+    uint64_t utc_time;
+    char buff[128]={0};
+    printf("Start ql_inject_utc_time : \n");
+    printf("Please Select Time:\n1-Current System time\n2-Input Time,Format:YYYY-MM-DD hh:mm:ss\n:");
+    scanf("%d",&input);
+    if(err !=0)
+    {
+        printf("Input error\n");
+        return ;
+    }
+    switch(input)
+    {
+        case 1:
+            utc_time=(uint64_t)time(NULL)*1000;
+            system("date");
+            break;
+        case 2:
+            err = t_get_string(buff, sizeof(buff));
+            if(err !=0)
+            {
+                printf("Input error\n");
+                return ;
+            }
+            convertUtcTimeMsec(buff,&utc_time);
+            break;
+            default:
+                printf("Not select!!!\n");
+                return ;
+    }
+    err = ql_gnss_inject_utc_time(utc_time);
+    if(err != QL_ERR_OK)
+    {
+        printf("Failed to Inject Utc Time  %d\n",err);
+    }
+    else
+    {
+        printf("Successful!\n");
+    }
+}
+
+
+
+
+static void item_ql_gnss_suspend(void)
+{
+    int err = QL_ERR_OK;
+
+    printf("Start to ql_gnss_suspend\n");
+    err = ql_gnss_suspend();
+    if(err != QL_ERR_OK)
+    {
+        printf("Failed to set ql_gnss_suspend\n");
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+}
+
+
+static void item_ql_gnss_resume(void)
+{
+    int err = QL_ERR_OK;
+
+    printf("Start to ql_gnss_resume\n");
+    err = ql_gnss_resume();
+    if(err != QL_ERR_OK)
+    {
+        printf("Failed to set ql_gnss_resume\n");
+    }
+    else
+    {
+        printf("Successful\n");
+    }
+}
+#endif
+
+static void item_ql_gnss_deinit(void)
+{
+    int err = QL_ERR_OK;
+
+    printf("Start to ql_gnss_deinit\n");
+    err = ql_gnss_deinit();
+    if(err == QL_ERR_OK)
+    {
+        printf("Successful\n");
+    }
+    else
+    {
+        printf("Failed to ql_gnss_deinit, err=%d\n", err);
+    }
+}
+
+static t_item_t ql_gnss_items[] = 
+{
+    {"ql_gnss_init", item_ql_gnss_init},
+    {"ql_gnss_nmea_ind_cb", item_ql_gnss_set_ind_cb},
+//    {"ql_gnss_get_engine_state",item_ql_gnss_get_engine_state},
+    {"ql_gnss_start",item_ql_gnss_start},
+    {"ql_gnss_stop", item_ql_gnss_stop},
+//    {"ql_gnss_get_nmea_version",item_ql_gnss_get_nmea_version},
+//    {"ql_gnss_set_nmea_version",item_ql_gnss_set_nmea_version},
+//    {"ql_gnss_set_nmea_type",item_ql_gnss_set_nmea_type},
+//    {"ql_gnss_get_constellation",item_ql_gnss_get_constellation},
+//    {"ql_gnss_set_constellation",item_ql_gnss_set_constellation},  
+    {"ql_gnss_set_start_mode",item_ql_gnss_set_start_mode},
+    {"ql_gnss_set_agnss_mode",item_ql_gnss_set_agnss_mode},
+    {"ql_gnss_inject_agnss_data",item_ql_gnss_inject_agnss_data},
+//    {"ql_gnss_inject_utc_time",item_ql_gnss_inject_utc_time},
+//    {"ql_gnss_suspend", item_ql_gnss_suspend},
+//    {"ql_gnss_resume", item_ql_gnss_resume},
+//    {"ql_gnss_set_service_error_cb",item_ql_gnss_set_service_error_cb},
+    {"ql_gnss_deinit", item_ql_gnss_deinit},
+};
+
+t_module_t ql_gnss_module =
+{
+    "gnss",
+    T_ARRAY_SIZE(ql_gnss_items),
+    ql_gnss_items
+};
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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    
+    if(0 == buf[0])
+    {
+        return -1;
+    }
+#endif
+    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;
+}
+
+void dump_items()
+{
+    int i;
+
+    printf("\n");
+    printf("The current module is: \n");
+
+    for(i=0; i< ql_gnss_module.item_len; i++)
+    {
+        printf("%d\t%s\n", i, ql_gnss_module.item_list[i].name);
+    }
+    printf("-1\texit\n");
+}
+
+int main(int argc, char *argv[])
+{
+    int ret;
+    int idx;
+
+    dump_items();
+
+    while(1)
+    {
+        printf("Please enter your choice: ");
+        ret = t_get_int(&idx);
+        printf("\n");
+        if(ret < 0)
+        {
+            printf("Invalid input\n");
+            continue;
+        }
+        else if(ret == 1)
+        {
+            dump_items();
+            continue;
+        }
+
+        if(idx == -1)
+        {
+            break;
+        }
+
+        if(idx<0 || idx>=ql_gnss_module.item_len)
+        {
+            printf("Not support idx: %d\n", idx);
+            continue;
+        }
+
+        printf("->Item : %s\n", ql_gnss_module.item_list[idx].name);
+        ql_gnss_module.item_list[idx].handle();
+    }
+
+    return 0;
+}
+
diff --git a/mbtk/test/libql_lib_v2/ql_gpio_test.c b/mbtk/test/libql_lib_v2/ql_gpio_test.c
new file mode 100755
index 0000000..6d68052
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_gpio_test.c
@@ -0,0 +1,172 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "ql_gpio.h"
+#include "mbtk_log.h"
+
+int gpio_g = -1;
+
+int main(int argc, char *argv[])
+{
+    char operator[10];
+    int opt;
+    int ret;
+    int gpio;
+    int direction;
+    int value;
+//    int pullsel;
+
+	mbtk_log_init("radio", "GPIO_TEST");
+
+    printf("=========ql gpio main=========\n"
+        "\t0 exit\n"
+        "\t1 gpio init\n"
+		"\t2 gpio uninit\n"
+        "\t3 gpio set direction\n"
+        "\t4 gpio set level\n"
+        "\t5 gpio get level\n"
+        "operator: >> \n");
+
+    while(1)
+    {
+		memset(operator, 0, sizeof(operator));
+        if(NULL != fgets(operator, sizeof(operator), stdin))
+            break;
+        fflush(stdin);
+        opt = atoi(operator);
+        switch (opt)
+        {
+        case 0:
+            printf("main exit\n");
+            return 0;
+        case 1:
+            {
+				printf("INPUT gpio \n");
+				memset(operator, 0, sizeof(operator));
+				if(NULL == fgets(operator, sizeof(operator), stdin))
+                    break;
+				fflush(stdin);
+				gpio = atoi(operator);
+				printf("gpio is %d\n", gpio);
+				ret = ql_gpio_init(gpio, 1, 1, 0);
+				if(ret != 0)
+				{
+					printf("ql_gpio_init fail\n");
+				}
+				else
+				{
+					printf("ql_gpio_init success\n");
+					gpio_g = gpio;
+				}
+            }
+            break;
+        case 2:
+            {
+				printf(">>>>>gpio uninit\n");
+				if (gpio_g != -1)
+				{
+					ret = ql_gpio_uninit(gpio_g);
+					if(ret != 0)
+					{
+						printf("ql_gpio_uninit fail\n");
+						printf("ret=%d\n", ret);
+					}
+					else
+					{
+						printf("ql_gpio_uninit success\n");
+						gpio_g = -1;
+					}
+				}
+				else
+				{
+					printf(">>>>>pleas gpio init<<<<<\n");
+				}
+            }
+            break;
+        case 3:
+            {
+                printf(">>>>>Input set direction<<<<<\n");
+				memset(operator, 0, sizeof(operator));
+				if(NULL == fgets(operator, sizeof(operator), stdin))
+                    break;
+				fflush(stdin);
+				direction = atoi(operator);
+				if (gpio_g != -1)
+				{
+					ret = ql_gpio_set_direction(gpio_g, direction);
+					if(ret != 0)
+					{
+						printf("ql_gpio_set_direction fail\n");
+					}
+					else
+					{
+						printf("ql_gpio_set_direction success\n");
+					}
+				}
+				else
+				{
+					printf(">>>>>pleas gpio init<<<<<\n");
+				}
+            }
+            break;
+        case 4:
+            {
+                printf(">>>>>Input set level<<<<<\n");
+				memset(operator, 0, sizeof(operator));
+				if(NULL == fgets(operator, sizeof(operator), stdin))
+                    break;
+				fflush(stdin);
+				value = atoi(operator);
+				if (gpio_g != -1)
+				{
+					ret = ql_gpio_set_level(gpio_g, value);
+					if(ret < 0)
+					{
+						printf("ql_gpio_set_level fail\n");
+					}
+					else
+					{
+						printf("ql_gpio_set_level success\n");
+					}
+				}
+				else
+				{
+					printf(">>>>>pleas gpio init<<<<<\n");
+				}
+            }
+            break;
+        case 5:
+            {
+                printf(">>>>>Input get level<<<<<\n");
+				if (gpio_g != -1)
+				{
+					ret = ql_gpio_get_level(gpio_g);
+					if(ret < 0)
+					{
+						printf("ql_gpio_get_level fail\n");
+						printf("ret=%d\n", ret);
+					}
+					else
+					{
+						printf("ql_gpio_get_level success\n");
+						printf("ret=%d\n", ret);
+					}
+				}
+				else
+				{
+					printf(">>>>>pleas gpio init<<<<<\n");
+				}
+            }
+            break;
+
+
+        default:
+            break;
+        }
+
+    }
+
+    return 0;
+
+}
diff --git a/mbtk/test/libql_lib_v2/ql_gpio_v2_test.c b/mbtk/test/libql_lib_v2/ql_gpio_v2_test.c
new file mode 100755
index 0000000..9f2fb4d
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_gpio_v2_test.c
@@ -0,0 +1,73 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "ql_gpio.h"
+
+static ENUM_PINNAME m_gpio_pin_gpio = PINNAME_GPIO_120;
+
+void callback_onAlarm(int param)
+{
+	int lvl = ql_gpio_get_level(m_gpio_pin_gpio);
+	if (lvl < 0)
+	{
+		printf("< fail to read pin level >\n");
+		return;
+	}
+	if (1 == lvl)
+	{
+		ql_gpio_set_level(m_gpio_pin_gpio, PINLEVEL_LOW);
+		printf("< Pull pin level to low >\n");
+	}else{
+		ql_gpio_set_level(m_gpio_pin_gpio, PINLEVEL_HIGH);
+		printf("< Pull pin level to high >\n");
+	}
+
+	alarm(1);
+}
+
+void exit_sig(int param)
+{
+   //Exit to release gpio
+   ql_gpio_uninit(m_gpio_pin_gpio);
+
+   exit(1);
+}
+
+int main(int argc, char* argv[])
+{
+	int iRet;
+
+	printf("< OpenLinux: GPIO example >\n");
+#if 0
+	/*
+	 *Note:
+	 * When using gpio configure, you need to determine whether the function of pin is gpio function.
+	 * If it is not gpio function, the following gpio configure are invalid.
+	 * You can use the ql_set_gpio_function to setting.
+	 */
+	iRet = ql_check_pin_function_status(m_gpio_pin_gpio);
+	if(iRet == 0){
+		iRet = ql_set_gpio_function(m_gpio_pin_gpio,1);
+		printf("< Set gpio(%d) function iRet=%d status=%d>\n", m_gpio_pin_gpio,iRet,ql_check_pin_function_status(m_gpio_pin_gpio));
+	}
+#endif
+	/*
+	* Before using gpio init the application layer,you first need to determine whether it is used in the driver.
+	*/
+	iRet = ql_gpio_init(m_gpio_pin_gpio, PINDIRECTION_OUT, PINLEVEL_HIGH, PINPULLSEL_DISABLE);
+	printf("< Init GPIO: pin=%d, dir=%d, level=%d, iRet=%d >\n", m_gpio_pin_gpio, PINDIRECTION_OUT, PINLEVEL_HIGH, iRet);
+
+	signal(SIGALRM, callback_onAlarm);
+	alarm(2);
+
+    signal(SIGINT, exit_sig);
+    while (1)
+	{
+		sleep(1);
+	}
+
+    return 0;
+}
diff --git a/mbtk/test/libql_lib_v2/ql_nw_test.c b/mbtk/test/libql_lib_v2/ql_nw_test.c
new file mode 100755
index 0000000..409a966
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_nw_test.c
@@ -0,0 +1,1747 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_nw_test.c 
+  @brief nw test module 
+*/
+/*-----------------------------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------------------------------
+  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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "ql_test_utils.h"
+#include "ql_type.h"
+#include "ql_nw.h"
+
+
+#if 0
+static int internal_nw_get_nas_rat(int radio, char* buf, int buf_len);
+#endif
+static int internal_nw_get_net_status(QL_NW_NETWORK_STATUS_TYPE_E net, char* buf, int buf_len);
+static int internal_nw_get_radio_tech(QL_NW_RADIO_TECH_TYPE_E radio, char* buf, int buf_len);
+static int internal_nw_get_tech_domain(QL_NW_TECH_DOMAIN_TYPE_E domain, char* buf, int buf_len);
+static int internal_nw_get_signal_strength_level(QL_NW_SIGNAL_STRENGTH_LEVEL_E level, char* buf, int buf_len);
+static void internal_nw_get_mcc_mnc_value(char *plmn, int plmn_len, unsigned short *mcc, unsigned short *mnc);
+static void internal_nw_get_service_option(unsigned short so_mask, char *buf, int buf_len);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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;
+}
+
+void nw_voice_reg_event_ind_cb(ql_nw_reg_status_info_t *ind)
+{
+    char domain_info[16] = {0};
+    char radio_info[16] = {0};
+    char svc_opt[128] = {0};
+
+    if(ind == NULL)
+    {
+        printf("recv voice reg ind event, param is null\n");
+        return;
+    }
+    printf("recv voice reg ind event, detail info:\n");
+
+    if(internal_nw_get_tech_domain(ind->tech_domain, domain_info, sizeof(domain_info)) == 0)
+    {
+        printf("\ttech_domain is unrecognized:%d, ", ind->tech_domain);
+    }
+    else
+    {
+        printf("\ttech_domain = %s, ", domain_info);
+    }
+
+    if(internal_nw_get_radio_tech(ind->radio_tech, radio_info, sizeof(radio_info)) == 0)
+    {
+        printf("radio_tech is unrecognized:%d, ", ind->radio_tech);
+    }
+    else
+    {
+        printf("radio_tech = %s, ", radio_info);
+    }
+
+    printf("roaming = %d, reg_status = %d, deny_reason = %d\n", 
+            ind->roaming, ind->reg_state, ind->deny_reason);
+
+    if(QL_NW_RADIO_TECH_NR5G != ind->radio_tech)
+    {
+        printf("\tmcc=%s, mnc=%s, forbidden=%d, cid=0x%X, lac=%d, psc=%d, tac=%d, endc_available=%d\n",
+                ind->mcc,
+                ind->mnc,
+                ind->forbidden,
+                ind->cid,
+                ind->lac,
+                ind->psc,
+                ind->tac,
+                ind->endc_available);
+
+        printf("\tinPRL=%d, css=%d, sid=%d, nid=%d, bsid=%d\n",
+                ind->inPRL,
+                ind->css,
+                ind->sid,
+                ind->nid,
+                ind->bsid);
+    }
+    else
+    { 
+        printf("\tmcc=%s, mnc=%s, forbidden=%d, cid=0x%llX, pci=%d, tac=%d\n",
+                ind->mcc,
+                ind->mnc,
+                ind->forbidden,
+                ind->nr5g_cid,
+                ind->nr5g_pci,
+                ind->nr5g_tac);
+
+        internal_nw_get_service_option(ind->nr5g_svc_opt, svc_opt, sizeof(svc_opt));
+        printf("\tsvc_opt(%d)=%s\n", ind->nr5g_svc_opt, svc_opt);
+    } 
+}
+
+#if 0
+void nw_data_reg_event_ind_cb(ql_nw_reg_status_info_t *ind)
+{
+    char domain_info[16] = {0};
+    char radio_info[16] = {0};
+    char svc_opt[128] = {0};
+    
+    if(ind == NULL)
+    {
+        printf("recv data reg ind event, param is null\n");
+        return;
+    }
+    printf("recv data reg ind event, detail info:\n");
+    
+    if(internal_nw_get_tech_domain(ind->tech_domain, domain_info, sizeof(domain_info)) == 0)
+    {
+        printf("\ttech_domain is unrecognized:%d, ", ind->tech_domain);
+    }
+    else
+    {
+        printf("\ttech_domain = %s, ", domain_info);
+    }
+
+    if(internal_nw_get_radio_tech(ind->radio_tech, radio_info, sizeof(radio_info)) == 0)
+    {
+        printf("radio_tech is unrecognized:%d, ", ind->radio_tech);
+    }
+    else
+    {
+        printf("radio_tech = %s, ", radio_info);
+    }
+
+    printf("roaming = %d, reg_status = %d, deny_reason = %d\n", 
+            ind->roaming, ind->reg_state, ind->deny_reason);
+
+    if(QL_NW_RADIO_TECH_NR5G != ind->radio_tech)
+    {
+        printf("\tmcc=%s, mnc=%s, forbidden=%d, cid=0x%X, lac=%d, psc=%d, tac=%d, endc_available=%d\n",
+                ind->mcc,
+                ind->mnc,
+                ind->forbidden,
+                ind->cid,
+                ind->lac,
+                ind->psc,
+                ind->tac,
+                ind->endc_available);
+
+        printf("\tinPRL=%d, css=%d, sid=%d, nid=%d, bsid=%d\n",
+                ind->inPRL,
+                ind->css,
+                ind->sid,
+                ind->nid,
+                ind->bsid);
+    }
+    else
+    { 
+        printf("\tmcc=%s, mnc=%s, forbidden=%d, cid=0x%llX, pci=%d, tac=%d\n",
+                ind->mcc,
+                ind->mnc,
+                ind->forbidden,
+                ind->nr5g_cid,
+                ind->nr5g_pci,
+                ind->nr5g_tac);
+
+        internal_nw_get_service_option(ind->nr5g_svc_opt, svc_opt, sizeof(svc_opt));
+        printf("\tsvc_opt(%d)=%s\n", ind->nr5g_svc_opt, svc_opt);
+    }
+}
+#endif
+
+void nw_signal_strength_event_ind_cb(ql_nw_signal_strength_info_t *ind, QL_NW_SIGNAL_STRENGTH_LEVEL_E level)
+{
+    char level_info[16] = {0};
+
+    if(ind == NULL)
+    {
+        printf("recv signal strength ind event, param is null\n");
+        return;
+    }
+
+    printf("recv event indication : signal strength event\n");
+
+    if(ind->has_gsm)
+    {
+        printf("gsm_sig_info: rssi=%d\n", ind->gsm.rssi);
+    } 
+
+    if(ind->has_wcdma)
+    {
+        printf("wcdma_sig_info: rssi=%d, ecio=%d\n", 
+                ind->wcdma.rssi, 
+                ind->wcdma.ecio); 
+    } 
+    if(ind->has_tdscdma)
+    {
+        printf("tdscdma_sig_info: rssi=%d, rscp=%d, ecio=%d, sinr=%d\n", 
+                ind->tdscdma.rssi, 
+                ind->tdscdma.rscp,
+                ind->tdscdma.ecio,
+                ind->tdscdma.sinr);
+    } 
+    if(ind->has_lte)
+    {
+        printf("lte_sig_info: rssi=%d, rsrq=%d, rsrp=%d, snr=%d\n", 
+                ind->lte.rssi, 
+                ind->lte.rsrq,
+                ind->lte.rsrp,
+                ind->lte.snr);
+    } 
+    if(ind->has_nr5g)
+    {
+        printf("nr5g_sig_info: rsrp=%hd, rsrq=%hd, snr=%hd\n",
+                ind->nr5g.rsrp,
+                ind->nr5g.rsrq,
+                ind->nr5g.snr);
+    }
+    if(ind->has_cdma)
+    {
+        printf("cdma_sig_info: rssi=%d, ecio=%d\n", 
+                ind->cdma.rssi, 
+                ind->cdma.ecio);
+    } 
+    if(ind->has_hdr)
+    {
+        printf("hdr_sig_info: rssi=%d, ecio=%d, sinr=%d, io=%d\n", 
+                ind->hdr.rssi, 
+                ind->hdr.ecio,
+                ind->hdr.sinr,
+                ind->hdr.io);
+    }
+    
+    if(internal_nw_get_signal_strength_level(level, level_info, sizeof(level_info)) == 0)
+    {
+        printf("signal strength level is %d, unrecognized\n", level);
+    }
+    else
+    {
+        printf("signal strength level is %s\n", level_info);
+    }
+}
+
+#if 0
+void nw_cell_access_status_event_ind_cb(QL_NW_CELL_ACCESS_STATE_TYPE_E status)
+{
+    printf("recv event indication : cell access status event\n");
+    printf("status = %d\n", status);
+}
+
+void nw_nitz_time_update_event_ind_cb(ql_nw_nitz_time_info_t *ind)
+{
+    if(ind == NULL)
+    {
+        printf("recv nitz time update ind event, param is null\n");
+        return;
+    }
+    printf("recv event indication : nitz time update event\n");
+    printf("nitz_time=%s, abs_time=%lld, leap_sec=%d\n",
+            ind->nitz_time, ind->abs_time, ind->leap_sec);
+}
+
+void nw_wea_alert_event_ind_cb(ql_nw_wea_alert_info_t *ind)
+{
+    if(ind == NULL)
+    {
+        printf("recv wea alert ind event, param is null\n");
+        return;
+    }
+    
+    printf("recv event indication : wea alert event, wea_alert_info_valid:[%d]\n", 
+            ind->wea_alert_info_valid);
+    if(ind->wea_alert_info_valid)
+    {
+        printf("wea alert info:[%s] \n",ind->wea_alert_info);
+    }
+}
+
+void nw_etws_alert_event_ind_cb(ql_nw_etws_alert_info_t *ind)
+{
+    if(ind == NULL)
+    {
+        printf("recv etws alert ind event, param is null\n");
+        return;
+    }
+    printf("recv event indication : etws alert event, etws_primary_info_valid:[%d] etws_secondary_info_valid:[%d]\n", 
+            ind->etws_primary_info_valid, ind->etws_secondary_info_valid);
+    if(ind->etws_primary_info_valid)
+    {
+        printf("etws primary alert info:[%s] \n", ind->etws_primary_info);
+    }
+    if(ind->etws_secondary_info_valid)
+    {
+        printf("etws secondary alert info:[%s] \n",
+            ind->etws_secondary_info);
+    }
+}
+
+void nw_network_scan_async_cb(int async_id, ql_nw_scan_result_list_info_t *info)
+{
+    int i = 0;
+    char net_info[16] = {0};
+    char radio_info[16] = {0};
+
+    printf("network scan async callback, async id is %d, list_len=%d, detail info:\n", async_id, info->entry_len);
+    for(i = 0; i < info->entry_len; i++)
+    {
+        memset(net_info, 0, sizeof(net_info));
+        memset(radio_info, 0, sizeof(radio_info));
+        printf("\t[%d]: long_eons=%s, short_eons=%s, mcc=%s, mnc=%s, ",
+               i,
+               info->entry[i].operator_name.long_eons,
+               info->entry[i].operator_name.short_eons,
+               info->entry[i].operator_name.mcc,
+               info->entry[i].operator_name.mnc);
+
+
+        if(internal_nw_get_net_status(info->entry[i].network_status, net_info, sizeof(net_info)) == 0)
+        {
+            printf("unrecognized network_status:%d, ", info->entry[i].network_status);
+        }
+        else
+        {
+            printf("network_status=%s, ", net_info);
+        }
+
+        if(internal_nw_get_radio_tech(info->entry[i].rat, radio_info, sizeof(radio_info)) == 0)
+        {
+            printf("unrecognized rat:%d\n ", info->entry[i].rat);
+        }
+        else
+        {
+            printf("radio_tech=%s\n", radio_info);
+        }
+    }
+}
+#endif
+
+void nw_service_error_cb(int error)
+{
+    printf("===== NW Service Abort =====\n");
+}
+
+void item_ql_nw_init(void)
+{
+    int ret = 0;
+    
+    printf("Start to ql_nw_init: ");
+    ret = ql_nw_init();
+    if(ret == QL_ERR_OK)
+    {
+        printf("nw init ok\n");
+    }
+    else
+    {
+        printf("failed, ret=%d\n", ret);
+    }
+}
+
+void item_ql_nw_deinit(void)
+{
+    int ret = 0;
+    
+    printf("Start to ql_nw_deinit: ");
+    ret = ql_nw_deinit();
+    if(ret == QL_ERR_OK)
+    {
+        printf("nw deinit ok\n");
+    }
+    else
+    {
+        printf("failed, ret=%d\n", ret);
+    }
+}
+
+#if 0
+void item_ql_nw_network_scan(void)
+{
+    int ret;
+    int async_id = 0;
+
+    ret = ql_nw_network_scan(&async_id, nw_network_scan_async_cb);
+    if(ret == QL_ERR_OK)
+    {
+        printf("async network scan succeed, token id is %d\n", async_id);
+    }
+    else
+    {
+        printf("async network scan failed, token id is %d, ret=%d", async_id, ret);
+    }
+}
+#endif
+
+void item_ql_nw_set_power_mode(void)
+{
+    int ret;
+    uint32_t mode = 0;
+
+    printf("please input power mode mask hex(VOICE | SMS | SIM | NETWORK | NORMAL): ");
+    ret = t_get_hex(&mode);
+    if(ret != 0)
+    {
+        printf("Invalid input\n");
+        return;
+    }
+    ret = ql_nw_set_power_mode(mode);
+    printf("ql_nw_set_lower_power_mode ret = %d\n", ret);
+}
+
+#if 0
+void item_ql_nw_set_pref_nwmode_roaming(void)
+{
+    int ret;
+    uint32_t mask = 0;
+    ql_nw_pref_nwmode_roaming_info_t t_info;
+
+    memset(&t_info, 0, sizeof(t_info));
+    printf("please input config mask hex(TDSCDMA | LTE | EVDO | CDMA | WCDMA | GSM): ");
+    ret = t_get_hex(&mask);
+    if(ret != 0)
+    {    
+        printf("Invalid input\n");
+        return;
+    }
+    t_info.preferred_nw_mode = mask;
+
+#if 0
+    printf("please input roaming pref(0:off 1:on): ");
+    ret = t_get_int((int *)&mask);
+    if(ret != 0)
+    {    
+        printf("Invalid input\n");
+        return;
+    }
+
+    t_info.preferred_roaming = mask;
+#endif
+    ret = ql_nw_set_pref_nwmode_roaming(&t_info);
+    printf("ql_nw_set_config ret = %d\n", ret);
+}
+
+void item_ql_nw_get_pref_nwmode_roaming(void)
+{
+    int ret;
+    ql_nw_pref_nwmode_roaming_info_t t_info;
+
+    memset(&t_info, 0, sizeof(t_info));
+    ret = ql_nw_get_pref_nwmode_roaming(&t_info);
+#if 0    
+    printf("ql_nw_get_config ret = %d\npreferred_nw_mode=%#llx, preferred_roaming=%d\n", 
+            ret, t_info.preferred_nw_mode, t_info.preferred_roaming);
+#else
+    printf("ql_nw_get_config ret = %d\npreferred_nw_mode=%#llx\n", 
+            ret, t_info.preferred_nw_mode);
+#endif            
+}
+
+void item_ql_nw_get_mobile_operator_name(void)
+{
+    int ret;
+    ql_nw_mobile_operator_name_info_t t_info;
+
+    memset(&t_info, 0, sizeof(t_info));
+    ret = ql_nw_get_mobile_operator_name(&t_info);
+    printf("ql_nw_get_operator_name ret = %d, long_eons=%s, short_eons=%s, mcc=%s, mnc=%s\n", 
+        ret,
+        t_info.long_eons, 
+        t_info.short_eons, 
+        t_info.mcc, 
+        t_info.mnc);
+}
+
+void item_ql_nw_get_cell_info(void)
+{
+    int i;
+    int ret;
+    unsigned short mcc;
+    unsigned short mnc;
+    ql_nw_cell_info_t t_info;
+
+    memset(&t_info, 0, sizeof(t_info));
+    ret = ql_nw_get_cell_info(&t_info);
+    printf("ql_nw_get_cell_info ret = %d, detail info:\n", ret);
+    
+    if(t_info.gsm_info_valid)
+    {
+        printf("gsm cell information:\n");
+        for(i = 0; i < t_info.gsm_info_len; i++)
+        {
+            printf("\tcid=%d,plmn=0x%02x 0x%02x 0x%02x,lac=%d,arfcn=%d,bsic=%d,rssi=%d,", 
+                    t_info.gsm_info[i].cid, 
+                    t_info.gsm_info[i].plmn[0], 
+                    t_info.gsm_info[i].plmn[1], 
+                    t_info.gsm_info[i].plmn[2], 
+                    t_info.gsm_info[i].lac, 
+                    t_info.gsm_info[i].arfcn, 
+                    t_info.gsm_info[i].bsic, 
+                    t_info.gsm_info[i].rssi);
+
+            internal_nw_get_mcc_mnc_value(t_info.gsm_info[i].plmn, 3, &mcc, &mnc);
+            printf("convert plmn to mcc=%d,mnc=%02d\n", mcc, mnc);
+        }
+    }
+
+    if(t_info.umts_info_valid)
+    {
+        printf("umts cell information:\n");
+        for(i = 0; i < t_info.umts_info_len; i++)
+        {
+            printf("\tcid=%d,lcid=%d,plmn=0x%02x 0x%02x 0x%02x,lac=%d,uarfcn=%d,psc=%d,rssi=%d,", 
+                    t_info.umts_info[i].cid,
+                    t_info.umts_info[i].lcid, 
+                    t_info.umts_info[i].plmn[0], 
+                    t_info.umts_info[i].plmn[1], 
+                    t_info.umts_info[i].plmn[2], 
+                    t_info.umts_info[i].lac, 
+                    t_info.umts_info[i].uarfcn, 
+                    t_info.umts_info[i].psc, 
+                    t_info.umts_info[i].rssi);
+            internal_nw_get_mcc_mnc_value(t_info.umts_info[i].plmn, 3, &mcc, &mnc);
+            printf("convert plmn to mcc=%d,mnc=%02d\n", mcc, mnc);
+        }
+    }
+
+    if(t_info.lte_info_valid)
+    {
+        printf("lte cell information:\n");
+        for(i = 0; i < t_info.lte_info_len; i++)
+        {
+            printf("\tcid=%d,plmn=0x%02x 0x%02x 0x%02x,tac=%d,pci=%d,earfcn=%d,rssi=%d,", 
+                    t_info.lte_info[i].cid, 
+                    t_info.lte_info[i].plmn[0], 
+                    t_info.lte_info[i].plmn[1], 
+                    t_info.lte_info[i].plmn[2], 
+                    t_info.lte_info[i].tac, 
+                    t_info.lte_info[i].pci, 
+                    t_info.lte_info[i].earfcn, 
+                    t_info.lte_info[i].rssi);
+            internal_nw_get_mcc_mnc_value(t_info.lte_info[i].plmn, 3, &mcc, &mnc);
+            printf("convert plmn to mcc=%d,mnc=%02d\n", mcc, mnc);
+        }
+    }
+  
+    if(t_info.nr5g_info_valid)
+    {
+        printf("nr5g cell information:\n");
+        printf("\tcid=%lld,plmn=0x%02x 0x%02x 0x%02x,tac=%d,pci=%d,arfcn=%d,rsrp=%d,rsrq=%d,snr=%d,", 
+                t_info.nr5g_info.cid, 
+                t_info.nr5g_info.plmn[0], 
+                t_info.nr5g_info.plmn[1], 
+                t_info.nr5g_info.plmn[2], 
+                t_info.nr5g_info.tac, 
+                t_info.nr5g_info.pci, 
+                t_info.nr5g_info.arfcn, 
+                t_info.nr5g_info.rsrp,
+                t_info.nr5g_info.rsrq,
+                t_info.nr5g_info.snr);
+        internal_nw_get_mcc_mnc_value(t_info.nr5g_info.plmn, 3, &mcc, &mnc);
+        printf("convert plmn to mcc=%d,mnc=%02d\n", mcc, mnc);
+    }
+
+    if(t_info.cdma_info_valid)
+    {
+        printf("cdma cell information:\n");
+        printf("\tsid=%d,nid=%d,bid=%d,refpn=%d,base_lat=%d,base_long=%d,rssi=%d\n", 
+                t_info.cdma_info.sid,
+                t_info.cdma_info.nid,
+                t_info.cdma_info.bid,
+                t_info.cdma_info.refpn,
+                t_info.cdma_info.base_lat,
+                t_info.cdma_info.base_long,
+                t_info.cdma_info.rssi);  
+    }
+}
+#endif
+
+void item_ql_nw_get_voice_reg_status(void)
+{
+    int ret;
+    char domain_info[16] = {0};
+    char radio_info[16] = {0};
+    char svc_opt[128] = {0};
+    ql_nw_reg_status_info_t t_info;
+
+    memset(&t_info, 0, sizeof(t_info));
+    ret = ql_nw_get_voice_reg_status(&t_info);
+
+    printf("ql_nw_get_voice_reg_status ret = %d, detail info:\n", ret);
+
+    if(internal_nw_get_tech_domain(t_info.tech_domain, domain_info, sizeof(domain_info)) == 0)
+    {
+        printf("\ttech_domain is unrecognized:%d, ", t_info.tech_domain);
+    }
+    else
+    {
+        printf("\ttech_domain = %s, ", domain_info);
+    }
+
+    if(internal_nw_get_radio_tech(t_info.radio_tech, radio_info, sizeof(radio_info)) == 0)
+    {
+        printf("radio_tech is unrecognized:%d, ", t_info.radio_tech);
+    }
+    else
+    {
+        printf("radio_tech = %s, ", radio_info);
+    }
+
+    printf("roaming = %d, reg_status = %d, deny_reason = %d\n", 
+            t_info.roaming, t_info.reg_state, t_info.deny_reason);
+
+    if(QL_NW_RADIO_TECH_NR5G != t_info.radio_tech)
+    {
+        printf("\tmcc=%s, mnc=%s, forbidden=%d, cid=0x%X, lac=%d, psc=%d, tac=%d, endc_available=%d\n",
+                t_info.mcc,
+                t_info.mnc,
+                t_info.forbidden,
+                t_info.cid,
+                t_info.lac,
+                t_info.psc,
+                t_info.tac,
+                t_info.endc_available);
+
+        printf("\tinPRL=%d, css=%d, sid=%d, nid=%d, bsid=%d\n",
+                t_info.inPRL,
+                t_info.css,
+                t_info.sid,
+                t_info.nid,
+                t_info.bsid);
+    }
+    else
+    { 
+        printf("\tmcc=%s, mnc=%s, forbidden=%d, cid=0x%llX, pci=%d, tac=%d\n",
+                t_info.mcc,
+                t_info.mnc,
+                t_info.forbidden,
+                t_info.nr5g_cid,
+                t_info.nr5g_pci,
+                t_info.nr5g_tac);
+
+        internal_nw_get_service_option(t_info.nr5g_svc_opt, svc_opt, sizeof(svc_opt));
+        printf("\tsvc_opt(%d)=%s\n", t_info.nr5g_svc_opt, svc_opt);
+    }
+}
+
+void item_ql_nw_get_data_reg_status(void)
+{
+    int ret;
+    char domain_info[16] = {0};
+    char radio_info[16] = {0};
+    char svc_opt[128] = {0};
+    ql_nw_reg_status_info_t t_info;
+
+    memset(&t_info, 0, sizeof(t_info));
+    ret = ql_nw_get_data_reg_status(&t_info);
+    
+    printf("ql_nw_get_data_reg_status ret = %d, detail info:\n", ret);
+    
+    if(internal_nw_get_tech_domain(t_info.tech_domain, domain_info, sizeof(domain_info)) == 0)
+    {
+        printf("\ttech_domain is unrecognized:%d, ", t_info.tech_domain);
+    }
+    else
+    {
+        printf("\ttech_domain = %s, ", domain_info);
+    }
+
+    if(internal_nw_get_radio_tech(t_info.radio_tech, radio_info, sizeof(radio_info)) == 0)
+    {
+        printf("radio_tech is unrecognized:%d, ", t_info.radio_tech);
+    }
+    else
+    {
+        printf("radio_tech = %s, ", radio_info);
+    }
+
+    printf("roaming = %d, reg_status = %d, deny_reason = %d\n", 
+            t_info.roaming, t_info.reg_state, t_info.deny_reason);
+
+    if(QL_NW_RADIO_TECH_NR5G != t_info.radio_tech)
+    {
+        printf("\tmcc=%s, mnc=%s, forbidden=%d, cid=0x%X, lac=%d, psc=%d, endc_available=%d\n",
+                t_info.mcc,
+                t_info.mnc,
+                t_info.forbidden,
+                t_info.cid,
+                t_info.lac,
+                t_info.psc,
+                //t_info.tac,  // tac not valid  in item_ql_nw_get_data_reg_status ,use item_ql_nw_get_cell_info
+                t_info.endc_available);
+
+        printf("\tinPRL=%d, css=%d, sid=%d, nid=%d, bsid=%d\n",
+                t_info.inPRL,
+                t_info.css,
+                t_info.sid,
+                t_info.nid,
+                t_info.bsid);
+    }
+    else
+    { 
+        printf("\tmcc=%s, mnc=%s, forbidden=%d, cid=0x%llX, pci=%d, tac=%d\n",
+                t_info.mcc,
+                t_info.mnc,
+                t_info.forbidden,
+                t_info.nr5g_cid,
+                t_info.nr5g_pci,
+                t_info.nr5g_tac);
+
+        internal_nw_get_service_option(t_info.nr5g_svc_opt, svc_opt, sizeof(svc_opt));
+        printf("\tsvc_opt(%d)=%s\n", t_info.nr5g_svc_opt, svc_opt);
+    }
+
+}
+
+void item_ql_nw_get_signal_strength(void)
+{
+    int ret;
+    char level_info[16] = {0};
+    ql_nw_signal_strength_info_t info;
+    QL_NW_SIGNAL_STRENGTH_LEVEL_E level = QL_NW_SIGNAL_STRENGTH_LEVEL_NONE;
+
+    memset(&info, 0, sizeof(info));
+    ret = ql_nw_get_signal_strength(&info, &level);
+    if (QL_ERR_OK != ret)
+    {
+        printf("failed, ret = %d\n", ret);
+        return;
+    }
+
+    if(info.has_gsm)
+    {
+        printf("gsm_sig_info: rssi=%hhd\n", info.gsm.rssi);
+    } 
+
+    if(info.has_wcdma)
+    {
+        printf("wcdma_sig_info: rssi=%hhd, ecio=%hd\n",
+                info.wcdma.rssi,
+                info.wcdma.ecio);
+    } 
+
+    if(info.has_tdscdma)
+    {
+        printf("tdscdma_sig_info: rssi=%hhd, rscp=%hhd, ecio=%hd, sinr=%hhd\n",
+                info.tdscdma.rssi,
+                info.tdscdma.rscp,
+                info.tdscdma.ecio,
+                info.tdscdma.sinr);
+    } 
+
+    if(info.has_lte)
+    {
+        printf("lte_sig_info: rssi=%hhd, rsrq=%hhd, rsrp=%hd, snr=%hd\n",
+                info.lte.rssi,
+                info.lte.rsrq,
+                info.lte.rsrp,
+                info.lte.snr);
+    } 
+    
+    if(info.has_nr5g)
+    {
+        printf("nr5g_sig_info: rsrp=%hd, rsrq=%hd, snr=%hd\n",
+                info.nr5g.rsrp,
+                info.nr5g.rsrq,
+                info.nr5g.snr);
+    }
+
+    if(info.has_cdma)
+    {
+        printf("cdma_sig_info: rssi=%hhd, ecio=%hd\n",
+                info.cdma.rssi,
+                info.cdma.ecio);
+    } 
+
+    if(info.has_hdr)
+    {
+        printf("hdr_sig_info: rssi=%hhd, ecio=%hd, sinr=%hd, io=%d\n",
+                info.hdr.rssi,
+                info.hdr.ecio,
+                info.hdr.sinr,
+                info.hdr.io);
+    }
+
+    if(internal_nw_get_signal_strength_level(level, level_info, sizeof(level_info)) == 0)
+    {
+        printf("signal strength level is %d, unrecognized\n", level);
+    }
+    else
+    {
+        printf("signal strength level is %s\n", level_info);
+    }
+}
+
+#if 0
+void item_ql_nw_get_cell_access_status(void)
+{
+    int ret;
+    QL_NW_CELL_ACCESS_STATE_TYPE_E e_state;
+
+    ret = ql_nw_get_cell_access_status(&e_state);
+    printf("ql_nw_get_cell_access_state ret = %d, e_state=%d\n", ret, e_state);
+}
+
+void item_ql_nw_get_nitz_time_info(void)
+{
+    int ret;
+    ql_nw_nitz_time_info_t t_info;
+
+    memset(&t_info, 0, sizeof(t_info));
+    ret = ql_nw_get_nitz_time_info(&t_info);
+    printf("ql_nw_get_nitz_time_info ret = %d\n nitz_time=%s, abs_time=%lld, leap_sec=%hhd\n", 
+        ret,
+        t_info.nitz_time, 
+        t_info.abs_time, 
+        t_info.leap_sec);
+}
+#endif
+
+void item_ql_nw_set_voice_reg_ind_cb(void)
+{
+    int ret = 0;
+    int reg_flag = 0;
+    
+    printf("please input voice reg option: (0: unreg, other: reg): ");
+    ret = t_get_int(&reg_flag);
+    if(ret != 0)
+    {    
+        printf("Invalid input\n");
+        return;
+    }
+    if(reg_flag)
+    {
+        ret = ql_nw_set_voice_reg_ind_cb(nw_voice_reg_event_ind_cb);
+    }
+    else
+    {
+        ret = ql_nw_set_voice_reg_ind_cb(NULL);
+    }
+    printf("ql_nw_reg_voice_reg_event ret = %d\n", ret);
+}
+
+#if 0
+void item_ql_nw_set_data_reg_ind_cb(void)
+{
+    int ret = 0;
+    int reg_flag = 0;
+    
+    printf("please input data reg option: (0: unreg, other: reg): ");
+    ret = t_get_int(&reg_flag);
+    if(ret != 0)
+    {    
+        printf("Invalid input\n");
+        return;
+    }
+    if(reg_flag)
+    {
+        ret = ql_nw_set_data_reg_ind_cb(nw_data_reg_event_ind_cb);
+    }
+    else
+    {
+        ret = ql_nw_set_data_reg_ind_cb(NULL);
+    }
+    printf("ql_nw_reg_data_reg_event ret = %d\n", ret);
+}
+#endif
+
+void item_ql_nw_set_signal_strength_chg_ind_cb(void)
+{
+    int ret = 0;
+    int reg_flag = 0;
+    
+    printf("please input signal strength change reg option: (0: unreg, other: reg): ");
+    ret = t_get_int(&reg_flag);
+    if(ret != 0)
+    {    
+        printf("Invalid input\n");
+        return;
+    }
+    
+    if(reg_flag)
+    {
+        ret = ql_nw_set_signal_strength_ind_cb(nw_signal_strength_event_ind_cb);
+    }
+    else
+    {
+        ret = ql_nw_set_signal_strength_ind_cb(NULL);
+    }
+    printf("ql_nw_reg_signal_strength_chg_event ret = %d\n", ret);
+}
+
+#if 0
+void item_ql_nw_set_cell_access_status_chg_ind_cb(void)
+{
+    int ret = 0;
+    int reg_flag = 0;
+    
+    printf("please input cell access status change reg option: (0: unreg, other: reg): ");
+    ret = t_get_int(&reg_flag);
+    if(ret != 0)
+    {    
+        printf("Invalid input\n");
+        return;
+    }
+    
+    if(reg_flag)
+    {
+        ret = ql_nw_set_cell_access_status_ind_cb(nw_cell_access_status_event_ind_cb);
+    }
+    else
+    {
+        ret = ql_nw_set_cell_access_status_ind_cb(NULL);
+    }
+    printf("ql_nw_reg_cell_access_status_event ret = %d\n", ret);
+}
+
+void item_ql_nw_set_nitz_time_update_ind_cb(void)
+{
+    int ret = 0;
+    int reg_flag = 0;
+    
+    printf("please input nitz time update reg option: (0: unreg, other: reg): ");
+    ret = t_get_int(&reg_flag);
+    if(ret != 0)
+    {    
+        printf("Invalid input\n");
+        return;
+    }
+
+    if(reg_flag)
+    {
+        ret = ql_nw_set_nitz_time_update_ind_cb(nw_nitz_time_update_event_ind_cb);
+    }
+    else
+    {
+        ret = ql_nw_set_nitz_time_update_ind_cb(NULL);
+    }
+    printf("ql_nw_reg_nitz_time_update_event ret = %d\n", ret);
+}
+
+void item_ql_nw_set_wea_alert_ind_cb(void)
+{
+    int ret = 0;
+    int reg_flag = 0;
+    
+    printf("please input wea alert reg option: (0: unreg, other: reg): ");
+    ret = t_get_int(&reg_flag);
+    if(ret != 0)
+    {    
+        printf("Invalid input\n");
+        return;
+    }
+
+    if(reg_flag)
+    {
+        ret = ql_nw_set_wea_alert_ind_cb(nw_wea_alert_event_ind_cb);
+    }
+    else
+    {
+        ret = ql_nw_set_wea_alert_ind_cb(NULL);
+    }
+    printf("ql_nw_set_wea_alert_ind_cb ret = %d\n", ret);
+}
+
+void item_ql_nw_set_etws_alert_ind_cb(void)
+{
+    int ret = 0;
+    int reg_flag = 0;
+    
+    printf("please input etws alert reg option: (0: unreg, other: reg): ");
+    ret = t_get_int(&reg_flag);
+    if(ret != 0)
+    {    
+        printf("Invalid input\n");
+        return;
+    }
+
+    if(reg_flag)
+    {
+        ret = ql_nw_set_etws_alert_ind_cb(nw_etws_alert_event_ind_cb);
+    }
+    else
+    {
+        ret = ql_nw_set_etws_alert_ind_cb(NULL);
+    }
+    printf("ql_nw_set_etws_alert_ind_cb ret = %d\n", ret);
+}
+#endif
+
+static void internal_nw_get_mcc_mnc_value(char *plmn, int plmn_len, unsigned short *mcc, unsigned short *mnc)
+{
+    int mcc1 = 0, mcc2 = 0, mcc3 = 0;
+    int mnc1 = 0, mnc2 = 0, mnc3 = 0;
+    
+    if(plmn_len < 3 || plmn == NULL) {
+        printf("get mcc mnc from plmn fail, param is invalid\n");
+        return;
+    }
+
+    mcc1 = plmn[0] & 0X0F;
+    mcc2 = plmn[0] >> 4;
+    mcc3 = plmn[1] & 0x0F;
+    
+    mnc3 = plmn[1] >> 4;
+    mnc2 = plmn[2] >> 4;
+    mnc1 = plmn[2] & 0x0F;
+    
+    *mcc = mcc1 * 100 + mcc2 * 10 + mcc3;
+    
+    if(0X0F == mnc3) {
+        *mnc = mnc1 * 10 + mnc2;
+    }
+    else {
+        *mnc = mnc1 * 100 + mnc2 * 10 + mnc3;
+    }
+}
+
+static int internal_nw_get_net_status(QL_NW_NETWORK_STATUS_TYPE_E net, char* buf, int buf_len)
+{
+    int ret_val = 1;
+    
+    if(buf == NULL || buf_len < 2)
+    {
+        printf("param is valid\n");
+        return 0;
+    }
+
+    memset(buf, 0, buf_len);
+    
+    switch(net)
+    {
+        case QL_NW_NETWORK_STATUS_NONE:
+            strncpy(buf, "NONE", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_NETWORK_STATUS_CURRENT_SERVING:
+            strncpy(buf, "CURRENT_SERVING", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_NETWORK_STATUS_PREFERRED:
+            strncpy(buf, "PREFERED", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_NETWORK_STATUS_NOT_PREFERRED:
+            strncpy(buf, "NOT_PREFERRED", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_NETWORK_STATUS_AVAILABLE:
+            strncpy(buf, "AVAILABLE", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_NETWORK_STATUS_FORBIDDEN:
+            strncpy(buf, "FORBIDDEN", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        default:
+            ret_val = 0;
+            break;
+    }
+    return ret_val;
+}
+
+#if 0
+static int internal_nw_get_nas_rat(int radio, char* buf, int buf_len)
+{
+    int ret_val = 1;
+    
+    if(buf == NULL || buf_len < 2)
+    {
+        printf("param is valid\n");
+        return 0;
+    }
+
+    memset(buf, 0, buf_len);
+    
+    switch(radio)
+    {
+        case 0:
+            strncpy(buf, "UNKNOWN", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case 1:
+            strncpy(buf, "GSM", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case 2:
+            strncpy(buf, "WCDMA", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case 3:
+            strncpy(buf, "TDSCDMA", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case 4:
+            strncpy(buf, "LTE", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case 5:
+            strncpy(buf, "NR5G", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case 6:
+            strncpy(buf, "CDMA", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case 7:
+            strncpy(buf, "HDR", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        default:
+            ret_val = 0;
+            break;
+    }
+    return ret_val;
+}
+#endif
+
+static int internal_nw_get_radio_tech(QL_NW_RADIO_TECH_TYPE_E radio, char* buf, int buf_len)
+{
+    int ret_val = 1;
+    
+    if(buf == NULL || buf_len < 2)
+    {
+        printf("param is valid\n");
+        return 0;
+    }
+
+    memset(buf, 0, buf_len);
+    
+    switch(radio)
+    {
+        case QL_NW_RADIO_TECH_TD_SCDMA:
+            strncpy(buf, "TD_SCDMA", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_GSM:
+            strncpy(buf, "GSM", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_HSPAP:
+            strncpy(buf, "HSPAP", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_LTE:
+            strncpy(buf, "LTE", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_EHRPD:
+            strncpy(buf, "EHRPD", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_EVDO_B:
+            strncpy(buf, "EVDO_B", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_HSPA:
+            strncpy(buf, "HSPA", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_HSUPA:
+            strncpy(buf, "HSUPA", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_HSDPA:
+            strncpy(buf, "HSDPA", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_EVDO_A:
+            strncpy(buf, "EVDO_A", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_EVDO_0:
+            strncpy(buf, "EVDO_0", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_1xRTT:
+            strncpy(buf, "1xRTT", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_IS95B:
+            strncpy(buf, "IS95B", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_IS95A:
+            strncpy(buf, "IS95A", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_UMTS:
+            strncpy(buf, "UMTS", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_EDGE:
+            strncpy(buf, "EDGE", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_GPRS:
+            strncpy(buf, "GPRS", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_NR5G:
+            strncpy(buf, "NR5G", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_RADIO_TECH_NONE:
+            strncpy(buf, "NONE", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        default:
+            ret_val = 0;
+            break;
+    }
+    return ret_val;
+}
+
+static int internal_nw_get_tech_domain(QL_NW_TECH_DOMAIN_TYPE_E domain, char* buf, int buf_len)
+{
+    int ret_val = 1;
+    
+    if(buf == NULL || buf_len < 2)
+    {
+        printf("param is valid\n");
+        return 0;
+    }
+
+    memset(buf, 0, buf_len);
+    
+    switch(domain)
+    {
+        case QL_NW_TECH_DOMAIN_NONE:
+            strncpy(buf, "NONE", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_TECH_DOMAIN_3GPP:
+            strncpy(buf, "3GPP", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_TECH_DOMAIN_3GPP2:
+            strncpy(buf, "3GPP2", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        default:
+            ret_val = 0;
+            break;
+    }
+    return ret_val;
+}
+
+static int internal_nw_get_signal_strength_level(QL_NW_SIGNAL_STRENGTH_LEVEL_E level, char* buf, int buf_len)
+{
+    int ret_val = 1;
+    
+    if(buf == NULL || buf_len < 2)
+    {
+        printf("param is valid\n");
+        return 0;
+    }
+
+    memset(buf, 0, buf_len);
+    
+    switch(level)
+    {
+        case QL_NW_SIGNAL_STRENGTH_LEVEL_NONE:
+            strncpy(buf, "UNKNOWN", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_SIGNAL_STRENGTH_LEVEL_POOR:
+            strncpy(buf, "POOR", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_SIGNAL_STRENGTH_LEVEL_MODERATE:
+            strncpy(buf, "MODERATE", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_SIGNAL_STRENGTH_LEVEL_GOOD:
+            strncpy(buf, "GOOD", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        case QL_NW_SIGNAL_STRENGTH_LEVEL_GREAT:
+            strncpy(buf, "GREAT", buf_len - 1);
+            buf[buf_len - 1] = '\0';
+            break;
+        default:
+            ret_val = 0;
+            break;
+    }
+    return ret_val;
+}
+
+static void internal_nw_get_service_option(unsigned short so_mask, char *buf, int buf_len)
+{
+    int remain_len = buf_len;
+
+    if(NULL == buf || buf_len < 2)
+    {
+        printf("param is valid\n");
+        return;
+    }
+    memset(buf, 0, buf_len);
+
+    if(so_mask & QL_NW_NR5G_SO_TDD)
+    {
+        if(remain_len > strlen("NR5G_TDD|") + 1)
+        {
+            strcat(buf + (buf_len - remain_len), "NR5G_TDD|");
+            remain_len = buf_len - strlen("NR5G_TDD|");
+        }
+    }
+
+    if(so_mask & QL_NW_NR5G_SO_SUB6)
+    {
+        if(remain_len > strlen("NR5G_SUB6|") + 1)
+        {
+            strcat(buf + (buf_len - remain_len), "NR5G_SUB6|");
+            remain_len = buf_len - strlen("NR5G_SUB6|");
+        }
+    }
+
+    if(so_mask & QL_NW_NR5G_SO_MMWAVE)
+    {
+        if(remain_len > strlen("NR5G_MMWAVE|") + 1)
+        {
+            strcat(buf + (buf_len - remain_len), "NR5G_MMWAVE|");
+            remain_len = buf_len - strlen("NR5G_MMWAVE|");
+        }
+    }
+    
+    if(so_mask & QL_NW_NR5G_SO_NSA)
+    {
+        if(remain_len > strlen("NR5G_NSA|") + 1)
+        {
+            strcat(buf + (buf_len - remain_len), "NR5G_NSA|");
+            remain_len = buf_len - strlen("NR5G_NSA|");
+        }
+    }
+    
+    if(so_mask & QL_NW_NR5G_SO_SA)
+    {
+        if(remain_len > strlen("NR5G_SA|") + 1)
+        {
+            strcat(buf + (buf_len - remain_len), "NR5G_SA|");
+            remain_len = buf_len - strlen("NR5G_SA|");
+        }
+    }
+
+    if(strlen(buf) > 0)
+    {
+        buf[strlen(buf) - 1] = '\0';
+    }
+    return;
+}
+
+#if 0
+void item_ql_nw_wea_set_config(void)
+{
+    int ret = 0;
+    int choice = 0;
+    int item = 0;
+    ql_nw_wea_config_t config = {0};
+
+    printf("test ql_nw_wea_set_config: \n");
+    printf(" 1)Presidential_alert\n");
+    printf(" 2)Extreme_alert\n");
+    printf(" 3)Severe_alert\n");
+    printf(" 4)Amber_alert\n");
+    printf(" 5)PublicSafety_alert\n");
+    printf(" 6)StateLocalTest_alert\n");
+    printf(" 7)RMT_alert\n");
+    printf(" 8)Exercise_alert\n");
+    printf(" 9)CMSPDefined_alert\n");
+    printf("10)Spanish_alert\n");
+    printf("please enter item to config: ");
+    ret = t_get_int(&choice);
+    if(ret != 0)
+    {    
+        printf("Invalid input\n");
+        return;
+    }
+    printf("\n");
+
+    switch (choice)
+    {
+        case 1:
+            item |= QL_NW_WEA_CONFIG_PRESIDENTIAL_ALERT;
+            printf("Presidential_alert: 0 - disable, 1 - enable:");
+            if(scanf("%hhu", &config.Presidential_alert) != 1)
+            {
+                printf("Invalid input\n");
+                return;
+            }
+            break;
+        case 2:
+            item |= QL_NW_WEA_CONFIG_EXTREME_ALERT;
+            printf("Extreme_alert: 0 - disable, 1 - enable:");
+            if(scanf("%hhu", &config.Extreme_alert) != 1)
+            {    
+                printf("Invalid input\n");
+                return;
+            }
+            break;
+        case 3:
+            item |= QL_NW_WEA_CONFIG_SEVERE_ALERT;
+            printf("Severe_alert: 0 - disable, 1 - enable:");
+            if(scanf("%hhu", &config.Severe_alert) != 1)
+            {    
+                printf("Invalid input\n");
+                return;
+            }
+            break;
+        case 4:
+            item |= QL_NW_WEA_CONFIG_AMBER_ALERT;
+            printf("Amber_alert: 0 - disable, 1 - enable:");
+            if(scanf("%hhu", &config.Amber_alert) != 1)
+            {    
+                printf("Invalid input\n");
+                return;
+            }   
+            break;
+        case 5:
+            item |= QL_NW_WEA_CONFIG_PUBLIC_SAFETY_ALERT;
+            printf("PublicSafety_alert: 0 - disable, 1 - enable:");
+            if(scanf("%hhu", &config.PublicSafety_alert) != 1)
+            {    
+                printf("Invalid input\n");
+                return;
+            }
+            break;
+        case 6:
+            item |= QL_NW_WEA_CONFIG_STATE_LOCAL_TEST_ALERT;
+            printf("StateLocalTest_alert: 0 - disable, 1 - enable:");
+            if(scanf("%hhu", &config.StateLocalTest_alert) != 1)
+            {    
+                printf("Invalid input\n");
+                return;
+            }
+            break;
+        case 7:
+            item |= QL_NW_WEA_CONFIG_RMT_ALERT;
+            printf("RMT_alert: 0 - disable, 1 - enable:");
+            if(scanf("%hhu", &config.RMT_alert) != 1)
+            {    
+                printf("Invalid input\n");
+                return;
+            }
+            break;
+        case 8:
+            item |= QL_NW_WEA_CONFIG_EXERCISE_ALERT;
+            printf("Exercise_alert: 0 - disable, 1 - enable:");
+            if(scanf("%hhu", &config.Exercise_alert) != 1)
+            {    
+                printf("Invalid input\n");
+                return;
+            }
+            break;
+        case 9:
+            item |= QL_NW_WEA_CONFIG_CMSP_DEFINED_ALERT;
+            printf("CMSPDefined_alert: 0 - disable, 1 - enable:");
+            if(scanf("%hhu", &config.CMSPDefined_alert) != 1)
+            {    
+                printf("Invalid input\n");
+                return;
+            }
+            break;
+        case 10:
+            item |= QL_NW_WEA_CONFIG_SPANISH_ALERT;
+            printf("Spanish_alert: 0 - disable, 1 - enable:");
+            if(scanf("%hhu", &config.Spanish_alert) != 1)
+            {    
+                printf("Invalid input\n");
+                return;
+            }
+            break;
+        default:
+            printf("bad choice: %d\n", choice);
+            return;
+    }
+    ret = getchar();
+
+    ret = ql_nw_set_wea_config(item, &config);
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+void item_ql_nw_wea_get_config(void)
+{
+    int ret = 0;
+    ql_nw_wea_config_t config = {0};
+
+    printf("test ql_nw_get_wea_config: \n");
+    ret = ql_nw_get_wea_config(&config);
+    if (ret == QL_ERR_OK)
+    {
+        printf("****** wea Config ******\n");
+        printf("Presidential_alert: %s\n", config.Presidential_alert ? "true" : "false");
+        printf("Extreme_alert: %s\n", config.Extreme_alert ? "true" : "false");
+        printf("Severe_alert: %s\n", config.Severe_alert ? "true" : "false");
+        printf("Amber_alert: %s\n", config.Amber_alert ? "true" : "false");
+        printf("PublicSafety_alert: %s\n", config.PublicSafety_alert ? "true" : "false");
+        printf("StateLocalTest_alert: %s\n", config.StateLocalTest_alert ? "true" : "false");
+        printf("RMT_alert: %s\n", config.RMT_alert ? "true" : "false");
+        printf("Exercise_alert: %s\n", config.Exercise_alert ? "true" : "false");
+        printf("CMSPDefined_alert: %s\n", config.CMSPDefined_alert ? "true" : "false");
+        printf("Spanish_alert: %s\n", config.Spanish_alert ? "true" : "false");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+void item_ql_nw_etws_set_config(void)
+{
+    int ret = 0;
+    int etws_enable = 0;
+
+    printf("please input etws config (0: disable,  1: enable): ");
+    ret = t_get_int(&etws_enable);
+    if(ret != 0)
+    {    
+        printf("Invalid input\n");
+        return;
+    }
+
+    ret = ql_nw_set_etws_config((unsigned char)etws_enable);
+    printf("item_ql_nw_etws_set_config ret = %d\n", ret);
+}
+
+void item_ql_nw_etws_get_config(void)
+{
+    int ret = 0;
+    unsigned char etws_enable = 0;
+
+    ret = ql_nw_get_etws_config(&etws_enable);
+    printf("ql_nw_get_etws_config ret = %d \t etws_enable=%d\n", 
+            ret, etws_enable);
+}
+#endif
+
+void item_ql_nw_set_service_error_cb(void)
+{
+    int ret = 0;
+
+    ret = ql_nw_set_service_error_cb(nw_service_error_cb);
+    if(ret != QL_ERR_OK)
+    {
+        printf("Failed to ql_nw_set_service_error_cb, ret=%d\n", ret);
+    }
+    else
+    {
+        printf("Sucessful\n");
+    }
+}
+
+
+static t_item_t ql_nw_items[] = 
+{
+      
+    {"ql_nw_init", item_ql_nw_init},
+//    {"ql_nw_network_scan", item_ql_nw_network_scan},
+    {"ql_nw_set_power_mode", item_ql_nw_set_power_mode},
+//    {"ql_nw_set_pref_nwmode_roaming", item_ql_nw_set_pref_nwmode_roaming},
+//    {"ql_nw_get_pref_nwmode_roaming", item_ql_nw_get_pref_nwmode_roaming},
+//    {"ql_nw_get_mobile_operator_name", item_ql_nw_get_mobile_operator_name},
+//    {"ql_nw_get_cell_info", item_ql_nw_get_cell_info},
+    {"ql_nw_get_voice_reg_status", item_ql_nw_get_voice_reg_status},
+    {"ql_nw_get_data_reg_status", item_ql_nw_get_data_reg_status},
+    {"ql_nw_get_signal_strength", item_ql_nw_get_signal_strength},
+//    {"ql_nw_get_cell_access_status", item_ql_nw_get_cell_access_status},
+//    {"ql_nw_get_nitz_time_info", item_ql_nw_get_nitz_time_info},
+    {"ql_nw_set_voice_reg_ind_cb", item_ql_nw_set_voice_reg_ind_cb},
+//    {"ql_nw_set_data_reg_ind_cb", item_ql_nw_set_data_reg_ind_cb},
+    {"ql_nw_set_signal_strength_chg_ind_cb", item_ql_nw_set_signal_strength_chg_ind_cb},
+//    {"ql_nw_set_cell_access_status_chg_ind_cb", item_ql_nw_set_cell_access_status_chg_ind_cb},
+//    {"ql_nw_set_nitz_time_update_ind_cb", item_ql_nw_set_nitz_time_update_ind_cb},
+//    {"ql_nw_set_wea_alert_ind_cb", item_ql_nw_set_wea_alert_ind_cb},
+//    {"ql_nw_wea_set_config", item_ql_nw_wea_set_config},
+//    {"ql_nw_wea_get_config", item_ql_nw_wea_get_config},
+//    {"ql_nw_set_etws_alert_ind_cb", item_ql_nw_set_etws_alert_ind_cb},
+//    {"ql_nw_etws_set_config", item_ql_nw_etws_set_config},
+//    {"ql_nw_etws_get_config", item_ql_nw_etws_get_config},
+    {"ql_nw_set_service_error_cb", item_ql_nw_set_service_error_cb},
+    {"ql_nw_deinit", item_ql_nw_deinit},
+};
+
+t_module_t ql_nw_module =
+{
+    "nw",
+    T_ARRAY_SIZE(ql_nw_items),
+    ql_nw_items
+};
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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    
+    if(0 == buf[0])
+    {
+        return -1;
+    }
+#endif
+    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;
+}
+
+void dump_items()
+{
+    int i;
+
+    printf("\n");
+    printf("The current module is: \n");
+
+    for(i=0; i< ql_nw_module.item_len; i++)
+    {
+        printf("%d\t%s\n", i, ql_nw_module.item_list[i].name);
+    }
+    printf("-1\texit\n");
+}
+
+int main(int argc, char *argv[])
+{
+    int ret;
+    int idx;
+
+    dump_items();
+
+    while(1)
+    {
+        printf("Please enter your choice: ");
+        ret = t_get_int(&idx);
+        printf("\n");
+        if(ret < 0)
+        {
+            printf("Invalid input\n");
+            continue;
+        }
+        else if(ret == 1)
+        {
+            dump_items();
+            continue;
+        }
+
+        if(idx == -1)
+        {
+            break;
+        }
+
+        if(idx<0 || idx>=ql_nw_module.item_len)
+        {
+            printf("Not support idx: %d\n", idx);
+            continue;
+        }
+
+        printf("->Item : %s\n", ql_nw_module.item_list[idx].name);
+        ql_nw_module.item_list[idx].handle();
+    }
+
+    return 0;
+}
+
diff --git a/mbtk/test/libql_lib_v2/ql_sim_test.c b/mbtk/test/libql_lib_v2/ql_sim_test.c
new file mode 100755
index 0000000..f71d93e
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_sim_test.c
@@ -0,0 +1,1886 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_sim_test.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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "ql_type.h"
+#include "ql_sim.h"
+#include "ql_test_utils.h"
+
+
+static void item_ql_sim_init(void)
+{
+    int ret = 0;
+    
+    printf("test ql_sim_init: ");
+    ret = ql_sim_init();
+    if(ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static void item_ql_sim_deinit(void)
+{
+    int ret = 0;
+
+    printf("test ql_sim_deinit: ");
+    ret = ql_sim_deinit();
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static void item_ql_sim_get_imsi(void)
+{
+    int ret = 0;
+    char imsi[QL_SIM_IMSI_LENGTH+1] = {0};
+    int input = 0;
+    QL_SIM_SLOT_E slot;
+    QL_SIM_APP_TYPE_E app_type;
+
+    printf("test ql_sim_get_imsi: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+
+    printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): ");
+    scanf("%d", &input);
+    getchar();
+    switch (input)
+    {
+        case 0:
+            app_type = QL_SIM_APP_TYPE_UNKNOWN;
+            break;
+        case 1:
+            app_type = QL_SIM_APP_TYPE_3GPP;
+            break;
+        case 2:
+            app_type = QL_SIM_APP_TYPE_3GPP2;
+            break;
+        case 3:
+            app_type = QL_SIM_APP_TYPE_ISIM;
+            break;
+        default:
+            printf("bad app type: %d\n", input);
+            return;
+    }
+    
+    ret = ql_sim_get_imsi(slot, app_type, imsi, sizeof(imsi));
+    if (ret == QL_ERR_OK)
+    {
+        printf("IMSI: %s\n", imsi);
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static void item_ql_sim_get_iccid(void)
+{
+    int ret = 0;
+    char iccid[QL_SIM_ICCID_LENGTH+1] = {0};
+    int input = 0;
+    QL_SIM_SLOT_E slot;
+
+    printf("test ql_sim_get_iccid: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+    
+    ret = ql_sim_get_iccid(slot, iccid, sizeof(iccid));
+    if (ret == QL_ERR_OK)
+    {
+        printf("ICCID: %s\n", iccid);
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static void item_ql_sim_get_phone_num(void)
+{
+    int ret = 0;
+    char num[QL_SIM_PHONE_NUMBER_MAX+1] = {0};
+    int input = 0;
+    QL_SIM_SLOT_E slot;
+    QL_SIM_APP_TYPE_E app_type;
+
+    printf("test ql_sim_get_phone_num: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+
+    printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): ");
+    scanf("%d", &input);
+    getchar();
+    switch (input)
+    {
+        case 0:
+            app_type = QL_SIM_APP_TYPE_UNKNOWN;
+            break;
+        case 1:
+            app_type = QL_SIM_APP_TYPE_3GPP;
+            break;
+        case 2:
+            app_type = QL_SIM_APP_TYPE_3GPP2;
+            break;
+        case 3:
+            app_type = QL_SIM_APP_TYPE_ISIM;
+            break;
+        default:
+            printf("bad app type: %d\n", input);
+            return;
+    }
+    
+    ret = ql_sim_get_phone_num(slot, app_type, num, sizeof(num));
+    if (ret == QL_ERR_OK)
+    {
+        printf("Phone number: %s\n", num);
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static void print_ascii(char *prefix, char *postfix, char *ascii, int len)
+{
+    int i = 0;
+    printf("%s", prefix);
+    for (i = 0; i < len; i++)
+    {
+        putchar(ascii[i]);
+    }
+    printf("%s",  postfix);
+}
+
+static void item_ql_sim_get_operators(void)
+{
+    int ret = 0;
+    ql_sim_operator_list_t list = {0};
+    int input = 0;
+    QL_SIM_SLOT_E slot;
+
+    printf("test ql_sim_get_operators: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+    
+    ret = ql_sim_get_operators(slot, &list);
+    if (ret == QL_ERR_OK)
+    {
+        if (0 == list.len)
+        {
+            printf("No operators found\n");
+        }
+        else
+        {
+            int i = 0;
+            printf("found %d opertators:\n", list.len);
+            for (i = 0; i < list.len; i++)
+            {
+                printf(" #%02d: ", i + 1);
+                print_ascii("MCC: ", "", list.operators[i].mcc, (int)sizeof(list.operators[i].mcc));
+                print_ascii(", MNC: ", "\n",list.operators[i].mnc, list.operators[i].mnc_len);
+            }
+        }
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static void item_ql_sim_enable_pin(void)
+{
+    int ret = 0;
+    int len = 0;
+    char c;
+    char pin_value[QL_SIM_PIN_MAX*2] = {0};
+    int input = 0;
+    QL_SIM_SLOT_E slot;
+    QL_SIM_APP_TYPE_E app_type;
+    QL_SIM_PIN_E pin;
+
+    printf("test ql_sim_enable_pin: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+
+    printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): ");
+    scanf("%d", &input);
+    getchar();
+    switch (input)
+    {
+        case 0:
+            app_type = QL_SIM_APP_TYPE_UNKNOWN;
+            break;
+        case 1:
+            app_type = QL_SIM_APP_TYPE_3GPP;
+            break;
+        case 2:
+            app_type = QL_SIM_APP_TYPE_3GPP2;
+            break;
+        case 3:
+            app_type = QL_SIM_APP_TYPE_ISIM;
+            break;
+        default:
+            printf("bad app type: %d\n", input);
+            return;
+    }
+
+    printf("please enter pin(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        pin = QL_SIM_PIN_1;
+    }
+    else if (2 == input)
+    {
+        pin = QL_SIM_PIN_2;
+    }
+    else
+    {
+        printf("bad pin: %d\n", input);
+        return;
+    }
+
+    printf("please enter pin value(at most %d digit): ", QL_SIM_PIN_MAX);
+    if (NULL == fgets(pin_value, sizeof(pin_value), stdin))
+    {
+        printf("can not read pin value\n");
+        return;
+    }
+    len = strlen(pin_value);
+    if ('\n' == pin_value[len-1])
+    {
+        pin_value[len-1] = 0;
+        len--;
+    }
+    printf("pin value: %s\n", pin_value);
+    
+    printf("proceed? [y/n]: ");
+    c = getchar();
+    if ('\n' != c)
+    {
+        getchar();
+    }
+    if ('Y' != c && 'y' != c)
+    {
+        printf("abort\n");
+        return;
+    }
+    
+    ret = ql_sim_enable_pin(slot, app_type, pin, pin_value);
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static void item_ql_sim_disable_pin(void)
+{
+    int ret = 0;
+    int len = 0;
+    char c;
+    char pin_value[QL_SIM_PIN_MAX*2] = {0};
+    int input = 0;
+    QL_SIM_SLOT_E slot;
+    QL_SIM_APP_TYPE_E app_type;
+    QL_SIM_PIN_E pin;
+
+    printf("test ql_sim_disable_pin: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+
+    printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): ");
+    scanf("%d", &input);
+    getchar();
+    switch (input)
+    {
+        case 0:
+            app_type = QL_SIM_APP_TYPE_UNKNOWN;
+            break;
+        case 1:
+            app_type = QL_SIM_APP_TYPE_3GPP;
+            break;
+        case 2:
+            app_type = QL_SIM_APP_TYPE_3GPP2;
+            break;
+        case 3:
+            app_type = QL_SIM_APP_TYPE_ISIM;
+            break;
+        default:
+            printf("bad app type: %d\n", input);
+            return;
+    }
+
+    printf("please enter pin(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        pin = QL_SIM_PIN_1;
+    }
+    else if (2 == input)
+    {
+        pin = QL_SIM_PIN_2;
+    }
+    else
+    {
+        printf("bad pin: %d\n", input);
+        return;
+    }
+
+    printf("please enter pin value(at most %d digit): ", QL_SIM_PIN_MAX);
+    if (NULL == fgets(pin_value, sizeof(pin_value), stdin))
+    {
+        printf("can not read pin value\n");
+        return;
+    }
+    len = strlen(pin_value);
+    if ('\n' == pin_value[len-1])
+    {
+        pin_value[len-1] = 0;
+        len--;
+    }
+    printf("pin value: %s\n", pin_value);
+    
+    printf("proceed? [y/n]: ");
+    c = getchar();
+    if ('\n' != c)
+    {
+        getchar();
+    }
+    if ('Y' != c && 'y' != c)
+    {
+        printf("abort\n");
+        return;
+    }
+    
+    ret = ql_sim_disable_pin(slot, app_type, pin, pin_value);
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static void item_ql_sim_verify_pin(void)
+{
+    int ret = 0;
+    int len = 0;
+    char c;
+    char pin_value[QL_SIM_PIN_MAX*2] = {0};
+    int input = 0;
+    QL_SIM_SLOT_E slot;
+    QL_SIM_APP_TYPE_E app_type;
+    QL_SIM_PIN_E pin;
+
+    printf("test ql_sim_verify_pin: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+
+    printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): ");
+    scanf("%d", &input);
+    getchar();
+    switch (input)
+    {
+        case 0:
+            app_type = QL_SIM_APP_TYPE_UNKNOWN;
+            break;
+        case 1:
+            app_type = QL_SIM_APP_TYPE_3GPP;
+            break;
+        case 2:
+            app_type = QL_SIM_APP_TYPE_3GPP2;
+            break;
+        case 3:
+            app_type = QL_SIM_APP_TYPE_ISIM;
+            break;
+        default:
+            printf("bad app type: %d\n", input);
+            return;
+    }
+
+    printf("please enter pin(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        pin = QL_SIM_PIN_1;
+    }
+    else if (2 == input)
+    {
+        pin = QL_SIM_PIN_2;
+    }
+    else
+    {
+        printf("bad pin: %d\n", input);
+        return;
+    }
+
+    printf("please enter pin value(at most %d digit): ", QL_SIM_PIN_MAX);
+    if (NULL == fgets(pin_value, sizeof(pin_value), stdin))
+    {
+        printf("can not read pin value\n");
+        return;
+    }
+    len = strlen(pin_value);
+    if ('\n' == pin_value[len-1])
+    {
+        pin_value[len-1] = 0;
+        len--;
+    }
+    printf("pin value: %s\n", pin_value);
+    
+    printf("proceed? [y/n]: ");
+    c = getchar();
+    if ('\n' != c)
+    {
+        getchar();
+    }
+    if ('Y' != c && 'y' != c)
+    {
+        printf("abort\n");
+        return;
+    }
+    
+    ret = ql_sim_verify_pin(slot, app_type, pin, pin_value);
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static void item_ql_sim_change_pin(void)
+{
+    int ret = 0;
+    int old_len = 0;
+    int new_len = 0;
+    char c;
+    char old_pin_value[QL_SIM_PIN_MAX*2] = {0};
+    char new_pin_value[QL_SIM_PIN_MAX*2] = {0};
+    int input = 0;
+    QL_SIM_SLOT_E slot;
+    QL_SIM_APP_TYPE_E app_type;
+    QL_SIM_PIN_E pin;
+
+    printf("test ql_sim_change_pin: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+
+    printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): ");
+    scanf("%d", &input);
+    getchar();
+    switch (input)
+    {
+        case 0:
+            app_type = QL_SIM_APP_TYPE_UNKNOWN;
+            break;
+        case 1:
+            app_type = QL_SIM_APP_TYPE_3GPP;
+            break;
+        case 2:
+            app_type = QL_SIM_APP_TYPE_3GPP2;
+            break;
+        case 3:
+            app_type = QL_SIM_APP_TYPE_ISIM;
+            break;
+        default:
+            printf("bad app type: %d\n", input);
+            return;
+    }
+
+    printf("please enter pin(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        pin = QL_SIM_PIN_1;
+    }
+    else if (2 == input)
+    {
+        pin = QL_SIM_PIN_2;
+    }
+    else
+    {
+        printf("bad pin: %d\n", input);
+        return;
+    }
+
+    printf("please enter old pin value(at most %d digit): ", QL_SIM_PIN_MAX);
+    if (NULL == fgets(old_pin_value, sizeof(old_pin_value), stdin))
+    {
+        printf("can not read old pin value\n");
+        return;
+    }
+    old_len = strlen(old_pin_value);
+    if ('\n' == old_pin_value[old_len-1])
+    {
+        old_pin_value[old_len-1] = 0;
+        old_len--;
+    }
+
+    printf("please enter new pin value(at most %d digit): ", QL_SIM_PIN_MAX);
+    if (NULL == fgets(new_pin_value, sizeof(new_pin_value), stdin))
+    {
+        printf("can not read new pin value\n");
+        return;
+    }
+    new_len = strlen(new_pin_value);
+    if ('\n' == new_pin_value[new_len-1])
+    {
+        new_pin_value[new_len-1] = 0;
+        new_len--;
+    }
+    printf("old pin value: %s\n", old_pin_value);
+    printf("new pin value: %s\n", new_pin_value);
+    
+    printf("proceed? [y/n]: ");
+    c = getchar();
+    if ('\n' != c)
+    {
+        getchar();
+    }
+    if ('Y' != c && 'y' != c)
+    {
+        printf("abort\n");
+        return;
+    }
+    
+    ret = ql_sim_change_pin(slot, app_type, pin, old_pin_value, new_pin_value);
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static void item_ql_sim_unblock_pin(void)
+{
+    int ret = 0;
+    int len = 0;
+    int new_len = 0;
+    char c;
+    char puk_value[QL_SIM_PIN_MAX*2] = {0};
+    char new_pin_value[QL_SIM_PIN_MAX*2] = {0};
+    int input = 0;
+    QL_SIM_SLOT_E slot;
+    QL_SIM_APP_TYPE_E app_type;
+    QL_SIM_PIN_E pin;
+
+    printf("test ql_sim_unblock_pin: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+
+    printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): ");
+    scanf("%d", &input);
+    getchar();
+    switch (input)
+    {
+        case 0:
+            app_type = QL_SIM_APP_TYPE_UNKNOWN;
+            break;
+        case 1:
+            app_type = QL_SIM_APP_TYPE_3GPP;
+            break;
+        case 2:
+            app_type = QL_SIM_APP_TYPE_3GPP2;
+            break;
+        case 3:
+            app_type = QL_SIM_APP_TYPE_ISIM;
+            break;
+        default:
+            printf("bad app type: %d\n", input);
+            return;
+    }
+
+    printf("please enter pin(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        pin = QL_SIM_PIN_1;
+    }
+    else if (2 == input)
+    {
+        pin = QL_SIM_PIN_2;
+    }
+    else
+    {
+        printf("bad pin: %d\n", input);
+        return;
+    }
+
+    printf("please enter puk value(at most %d digit): ", QL_SIM_PIN_MAX);
+    if (NULL == fgets(puk_value, sizeof(puk_value), stdin))
+    {
+        printf("can not read old pin value\n");
+        return;
+    }
+    len = strlen(puk_value);
+    if ('\n' == puk_value[len-1])
+    {
+        puk_value[len-1] = 0;
+        len--;
+    }
+
+    printf("please enter new pin value(at most %d digit): ", QL_SIM_PIN_MAX);
+    if (NULL == fgets(new_pin_value, sizeof(new_pin_value), stdin))
+    {
+        printf("can not read new pin value\n");
+        return;
+    }
+    new_len = strlen(new_pin_value);
+    if ('\n' == new_pin_value[new_len-1])
+    {
+        new_pin_value[new_len-1] = 0;
+        new_len--;
+    }
+    printf("    puk value: %s\n", puk_value);
+    printf("new pin value: %s\n", new_pin_value);
+    
+    printf("proceed? [y/n]: ");
+    c = getchar();
+    if ('\n' != c)
+    {
+        getchar();
+    }
+    if ('Y' != c && 'y' != c)
+    {
+        printf("abort\n");
+        return;
+    }
+    
+    ret = ql_sim_unblock_pin(slot, app_type, pin, puk_value, new_pin_value);
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static char *card_state_desc(QL_SIM_CARD_STATE_E state)
+{
+    switch (state)
+    {
+        case QL_SIM_CARD_STATE_UNKNOWN:
+            return "unknown";
+        case QL_SIM_CARD_STATE_ABSENT:
+            return "absent";
+        case QL_SIM_CARD_STATE_PRESENT:
+            return "present";
+        case QL_SIM_CARD_STATE_ERROR_UNKNOWN:
+            return "unknown error";
+        case QL_SIM_CARD_STATE_ERROR_POWER_DOWN:
+            return "power down";
+        case QL_SIM_CARD_STATE_ERROR_POLL_ERROR:
+            return "poll error";
+        case QL_SIM_CARD_STATE_ERROR_NO_ATR_RECEIVED:
+            return "failed to receive an answer to reset";
+        case QL_SIM_CARD_STATE_ERROR_VOLT_MISMATCH:
+            return "voltage mismatch";
+        case QL_SIM_CARD_STATE_ERROR_PARITY_ERROR:
+            return "parity error";
+        case QL_SIM_CARD_STATE_ERROR_SIM_TECHNICAL_PROBLEMS:
+            return "technical problems";
+        default:
+            return "N/A";
+    }
+}
+
+static char *card_type_desc(QL_SIM_CARD_TYPE_E type)
+{
+    switch (type)
+    {
+        case QL_SIM_CARD_TYPE_UNKNOWN:
+            return "unknown";
+        case QL_SIM_CARD_TYPE_ICC:
+            return "ICC";
+        case QL_SIM_CARD_TYPE_UICC:
+            return "UICC";
+        default: 
+            return "N/A";
+    }
+}
+
+static char *card_subscription_desc(QL_SIM_SUBSCRIPTION_E subscription)
+{
+    switch (subscription)
+    {
+        case QL_SIM_SUBSCRIPTION_NONE:
+            return "nonprovisioning";
+        case QL_SIM_SUBSCRIPTION_PRI:
+            return "primary provisioning subscription";
+        case QL_SIM_SUBSCRIPTION_SEC:
+            return "secondary provisioning subscription";
+        default:
+            return "N/A";
+    }
+}
+
+static char *card_app_state_desc(QL_SIM_APP_STATE_E state)
+{
+    switch (state)
+    {
+        case QL_SIM_APP_STATE_UNKNOWN:
+            return "unknown";
+        case QL_SIM_APP_STATE_DETECTED:
+            return "detected";
+        case QL_SIM_APP_STATE_PIN1_REQ:
+            return "PIN1 required";
+        case QL_SIM_APP_STATE_PUK1_REQ:
+            return "PUK1 required";
+        case QL_SIM_APP_STATE_INITALIZATING:
+            return "initializing";
+        case QL_SIM_APP_STATE_PERSO_CK_REQ:
+            return "personalization control key required";
+        case QL_SIM_APP_STATE_PERSO_PUK_REQ:
+            return "personalization unblock key required";
+        case QL_SIM_APP_STATE_PERSO_PERMANENTLY_BLOCKED:
+            return "personalization is permanently blocked";
+        case QL_SIM_APP_STATE_PIN1_PERM_BLOCKED:
+            return "PIN1 is permanently blocked";
+        case QL_SIM_APP_STATE_ILLEGAL:
+            return "illegal";
+        case QL_SIM_APP_STATE_READY:
+            return "ready";
+        default:
+            return "N/A";
+    }
+}
+
+static char *card_perso_feature_desc(QL_SIM_PERSO_FEATURE_E feature)
+{
+    switch (feature)
+    {
+        case QL_SIM_PERSO_FEATURE_UNKNOWN:
+            return "unknown";
+        case QL_SIM_PERSO_FEATURE_3GPP_NETWORK:
+            return "featurization based on 3GPP MCC and MNC";
+        case QL_SIM_PERSO_FEATURE_3GPP_NETWORK_SUBSET:
+            return "featurization based on 3GPP MCC, MNC, and IMSI digits 6 and 7";
+        case QL_SIM_PERSO_FEATURE_3GPP_SERVICE_PROVIDER:
+            return "featurization based on 3GPP MCC, MNC, and GID1";
+        case QL_SIM_PERSO_FEATURE_3GPP_CORPORATE:
+            return "featurization based on 3GPP MCC, MNC, GID1, and GID2";
+        case QL_SIM_PERSO_FEATURE_3GPP_SIM:
+            return "featurization based on the 3GPP IMSI";
+        case QL_SIM_PERSO_FEATURE_3GPP2_NETWORK_TYPE_1:
+            return "featurization based on 3GPP2 MCC and MNC";
+        case QL_SIM_PERSO_FEATURE_3GPP2_NETWORK_TYPE_2:
+            return "featurization based on 3GPP2 IRM code";
+        case QL_SIM_PERSO_FEATURE_3GPP2_RUIM:
+            return "featurization based on 3GPP2 IMSI_M";
+        default:
+            return "N/A";
+    }
+}
+
+static char *card_pin_state_desc(QL_SIM_PIN_STATE_E state)
+{
+    switch (state)
+    {
+        case QL_SIM_PIN_STATE_UNKNOWN:
+            return "unknown";
+        case QL_SIM_PIN_STATE_ENABLED_NOT_VERIFIED:
+            return "PIN required, but has not been verified";
+        case QL_SIM_PIN_STATE_ENABLED_VERIFIED:
+            return "PIN required and has been verified";
+        case QL_SIM_PIN_STATE_DISABLED:
+            return "PIN not required";
+        case QL_SIM_PIN_STATE_BLOCKED:
+            return "PIN verification has failed too many times and is blocked. "
+                   "Recoverable through PUK verification";
+        case QL_SIM_PIN_STATE_PERMANENTLY_BLOCKED:
+            return "PUK verification has failed too many times and is not recoverable";
+        default:
+            return "N/A";
+    }
+}
+
+
+static void item_ql_sim_get_card_info(void)
+{
+    int ret = 0;
+    ql_sim_card_info_t info = {0};
+    int input = 0;
+    QL_SIM_SLOT_E slot;
+
+    printf("test ql_sim_get_card_info: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+    
+    ret = ql_sim_get_card_info(slot, &info);
+    if (ret != QL_ERR_OK)
+    {
+        printf("failed, ret = %d\n", ret);
+        return;
+    }
+    printf("========= CARD INFO =========\n");
+    printf("state: %s\n", card_state_desc(info.state));
+    printf("type: %s\n", card_type_desc(info.type));
+    printf("3gpp:\n");
+    printf(" app state: %s\n", card_app_state_desc(info.app_3gpp.app_state));
+    printf(" PIN 1 retries: %hhu\n", info.app_3gpp.pin1_num_retries);
+    printf(" PUK 1 retries: %hhu\n", info.app_3gpp.puk1_num_retries);
+    printf(" PIN 2 retries: %hhu\n", info.app_3gpp.pin2_num_retries);
+    printf(" PUK 2 retries: %hhu\n", info.app_3gpp.puk2_num_retries);
+    printf("3gpp2:\n");
+    printf(" app state: %s\n", card_app_state_desc(info.app_3gpp2.app_state));
+    printf(" PIN 1 retries: %hhu\n", info.app_3gpp2.pin1_num_retries);
+    printf(" PUK 1 retries: %hhu\n", info.app_3gpp2.puk1_num_retries);
+    printf(" PIN 2 retries: %hhu\n", info.app_3gpp2.pin2_num_retries);
+    printf(" PUK 2 retries: %hhu\n", info.app_3gpp2.puk2_num_retries);
+    printf("isim:\n");
+    printf(" app state: %s\n", card_app_state_desc(info.app_isim.app_state));
+    printf(" PIN 1 retries: %hhu\n", info.app_isim.pin1_num_retries);
+    printf(" PUK 1 retries: %hhu\n", info.app_isim.puk1_num_retries);
+    printf(" PIN 2 retries: %hhu\n", info.app_isim.pin2_num_retries);
+    printf(" PUK 2 retries: %hhu\n", info.app_isim.puk2_num_retries);
+}
+
+#if 0
+static void item_ql_sim_read_file(void)
+{
+    int ret = 0;
+    int input = 0;
+    int len = 0;
+    QL_SIM_SLOT_E slot;
+    QL_SIM_APP_TYPE_E app_type;
+    ql_sim_file_t file = {0};
+
+    printf("test ql_sim_read_file: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+
+    printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): ");
+    scanf("%d", &input);
+    getchar();
+    switch (input)
+    {
+        case 0:
+            app_type = QL_SIM_APP_TYPE_UNKNOWN;
+            break;
+        case 1:
+            app_type = QL_SIM_APP_TYPE_3GPP;
+            break;
+        case 2:
+            app_type = QL_SIM_APP_TYPE_3GPP2;
+            break;
+        case 3:
+            app_type = QL_SIM_APP_TYPE_ISIM;
+            break;
+        default:
+            printf("bad app type: %d\n", input);
+            return;
+    }
+
+    printf("please enter file path(at most %d hex[0·9A-F], e.g 3F002FE2): ", QL_SIM_PATH_MAX);
+    if (NULL == fgets(file.path, QL_SIM_PATH_MAX, stdin))
+    {
+        printf("can not read file path\n");
+        return;
+    }
+    len = strlen(file.path);
+    if ('\n' == file.path[len-1])
+    {
+        file.path[len-1] = 0;
+        len--;
+    }
+    file.path_len = (uint32_t)len;
+
+    printf("please enter record index(0 for transparent access): ");
+    scanf("%hhu", (uint8_t *)&file.record_idx);
+    getchar();
+    
+    ret = ql_sim_read_file(slot, app_type, &file);
+    if (ret == QL_ERR_OK)
+    {
+        printf("data length: %u\n", file.data_len);
+        uint32_t i = 0;
+        printf("data: ");
+        for (i = 0; i < file.data_len; i++)
+        {
+            printf("%02x ", file.data[i]);
+        }
+        printf("\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static void item_ql_sim_write_file(void)
+{
+    int ret = 0;
+    int input = 0;
+    int len = 0;
+    uint8_t v;
+    QL_SIM_SLOT_E slot;
+    QL_SIM_APP_TYPE_E app_type;
+    ql_sim_file_t file = {0};
+
+    printf("test ql_sim_write_file: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+
+    printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): ");
+    scanf("%d", &input);
+    getchar();
+    switch (input)
+    {
+        case 0:
+            app_type = QL_SIM_APP_TYPE_UNKNOWN;
+            break;
+        case 1:
+            app_type = QL_SIM_APP_TYPE_3GPP;
+            break;
+        case 2:
+            app_type = QL_SIM_APP_TYPE_3GPP2;
+            break;
+        case 3:
+            app_type = QL_SIM_APP_TYPE_ISIM;
+            break;
+        default:
+            printf("bad app type: %d\n", input);
+            return;
+    }
+
+    printf("please enter file path(at most %d hex[0·9A-F], e.g 3F002FE2): ", QL_SIM_PATH_MAX);
+    if (NULL == fgets(file.path, QL_SIM_PATH_MAX, stdin))
+    {
+        printf("can not read file path\n");
+        return;
+    }
+    len = strlen(file.path);
+    if ('\n' == file.path[len-1])
+    {
+        file.path[len-1] = 0;
+        len--;
+    }
+    file.path_len = (uint32_t)len;
+
+    printf("please enter record index(0 for transparent access): ");
+    scanf("%hhu", (uint8_t *)&file.record_idx);
+    getchar();
+
+    printf("please enter data(hex, end with `q'): ");
+    while (1 == scanf("%hhx", &v))
+    {
+        file.data[file.data_len++] = v;
+    }
+    getchar();  // read `q'
+    getchar();  // read '\n'
+    
+    printf("please enter data offset: ");
+    scanf("%hu", &file.offset);
+    getchar();
+    
+    ret = ql_sim_write_file(slot, app_type, &file);
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static char *file_type_desc(QL_SIM_FILE_TYPE_E type)
+{
+    switch (type)
+    {
+        case QL_SIM_FILE_TYPE_UNKNOWN:
+            return "unknown";
+        case QL_SIM_FILE_TYPE_TRANSPARENT:
+            return "transparent";
+        case QL_SIM_FILE_TYPE_CYCLIC:
+            return "cyclic";
+        case QL_SIM_FILE_TYPE_LINEAR_FIXED:
+            return "linear fixed";
+        default: 
+            return "N/A";
+    }
+}
+
+static void item_ql_sim_get_file_info(void)
+{
+    int ret = 0;
+    int input = 0;
+    int len = 0;
+    QL_SIM_SLOT_E slot;
+    QL_SIM_APP_TYPE_E app_type;
+    ql_sim_file_info_t info = {0};
+
+    printf("test ql_sim_get_file_info: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+
+    printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): ");
+    scanf("%d", &input);
+    getchar();
+    switch (input)
+    {
+        case 0:
+            app_type = QL_SIM_APP_TYPE_UNKNOWN;
+            break;
+        case 1:
+            app_type = QL_SIM_APP_TYPE_3GPP;
+            break;
+        case 2:
+            app_type = QL_SIM_APP_TYPE_3GPP2;
+            break;
+        case 3:
+            app_type = QL_SIM_APP_TYPE_ISIM;
+            break;
+        default:
+            printf("bad app type: %d\n", input);
+            return;
+    }
+
+    printf("please enter file path(at most %d hex[0·9A-F], e.g 3F002FE2): ", QL_SIM_PATH_MAX);
+    if (NULL == fgets(info.path, QL_SIM_PATH_MAX, stdin))
+    {
+        printf("can not read file path\n");
+        return;
+    }
+    len = strlen(info.path);
+    if ('\n' == info.path[len-1])
+    {
+        info.path[len-1] = 0;
+        len--;
+    }
+    info.path_len = (uint32_t)len;
+    
+    ret = ql_sim_get_file_info(slot, app_type, &info);
+    if (ret == QL_ERR_OK)
+    {
+        printf("========= FILE INFO =========\n");
+        printf("path: %s\n", info.path);
+        printf("type: %s\n", file_type_desc(info.file_type));
+        printf("file size: %hu\n", info.file_size);
+        printf("record size: %hu\n", info.record_size);
+        printf("record count: %hu\n", info.record_count);
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static void item_ql_sim_read_phone_book(void)
+{
+    int ret = 0;
+    int input = 0;
+    QL_SIM_SLOT_E slot;
+    QL_SIM_APP_TYPE_E app_type;
+    uint8_t record_idx = 0;
+    ql_sim_phone_book_record_t record;
+
+    memset(&record,0,sizeof(ql_sim_phone_book_record_t));
+    printf("test ql_sim_read_phone_book: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+
+    printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): ");
+    scanf("%d", &input);
+    getchar();
+    switch (input)
+    {
+        case 0:
+            app_type = QL_SIM_APP_TYPE_UNKNOWN;
+            break;
+        case 1:
+            app_type = QL_SIM_APP_TYPE_3GPP;
+            break;
+        case 2:
+            app_type = QL_SIM_APP_TYPE_3GPP2;
+            break;
+        case 3:
+            app_type = QL_SIM_APP_TYPE_ISIM;
+            break;
+        default:
+            printf("bad app type: %d\n", input);
+            return;
+    }
+
+    printf("please enter record index: ");
+    scanf("%hhu", &record_idx);
+    getchar();
+    
+    
+    ret = ql_sim_read_phone_book(slot, app_type, QL_SIM_PB_DEFAULT_PATH, record_idx, &record);
+    if (ret == QL_ERR_OK)
+    {
+        printf("Name: %s\n", record.name);
+        printf("Number: %s\n", record.number);
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static void item_ql_sim_write_phone_book(void)
+{
+    int ret = 0;
+    int input = 0;
+    int len = 0;
+    QL_SIM_SLOT_E slot;
+    QL_SIM_APP_TYPE_E app_type;
+    uint8_t record_idx = 0;
+    ql_sim_phone_book_record_t record;
+
+    memset(&record,0,sizeof(ql_sim_phone_book_record_t));
+    printf("test ql_sim_write_phone_book: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+
+    printf("please enter app type(0-unknown, 1-3gpp, 2-3gpp2, 3-isim): ");
+    scanf("%d", &input);
+    getchar();
+    switch (input)
+    {
+        case 0:
+            app_type = QL_SIM_APP_TYPE_UNKNOWN;
+            break;
+        case 1:
+            app_type = QL_SIM_APP_TYPE_3GPP;
+            break;
+        case 2:
+            app_type = QL_SIM_APP_TYPE_3GPP2;
+            break;
+        case 3:
+            app_type = QL_SIM_APP_TYPE_ISIM;
+            break;
+        default:
+            printf("bad app type: %d\n", input);
+            return;
+    }
+
+    printf("please enter record index: ");
+    scanf("%hhu", &record_idx);
+    getchar();
+
+    printf("please enter name(at most %d chars): ", QL_SIM_PHONE_BOOK_NAME_MAX - 1);
+    if (NULL == fgets(record.name, QL_SIM_PHONE_BOOK_NAME_MAX, stdin))
+    {
+        printf("\nname will be set to 0\n");
+    }
+    else
+    {
+        len = strlen(record.name);
+        if ('\n' == record.name[len-1])
+        {
+            record.name[len-1] = 0;
+        }
+    }
+    
+
+    printf("please enter number(at most %d digits): ", QL_SIM_PHONE_BOOK_NUMBER_MAX - 1);
+    if (NULL == fgets(record.number, QL_SIM_PHONE_BOOK_NUMBER_MAX, stdin))
+    {
+        printf("\nnumber will be set to 0\n");
+    }
+    else
+    {
+        len = strlen(record.number);
+        if ('\n' == record.number[len-1])
+        {
+            record.number[len-1] = 0;
+        }
+    }
+    
+    ret = ql_sim_write_phone_book(slot, app_type, QL_SIM_PB_DEFAULT_PATH, record_idx, &record);
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static void item_ql_sim_open_logical_channel(void)
+{
+    int ret = 0;
+    int input = 0;
+    QL_SIM_SLOT_E slot;
+    uint8_t channel_id = 0;
+
+    printf("test ql_sim_open_logical_channel: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+    
+    ret = ql_sim_open_logical_channel(slot, &channel_id);
+    if (ret == QL_ERR_OK)
+    {
+        printf("channel id: %hhu\n", channel_id);
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static void item_ql_sim_close_logical_channel(void)
+{
+    int ret = 0;
+    int input = 0;
+    QL_SIM_SLOT_E slot;
+    uint8_t channel_id = 0;
+
+    printf("test ql_sim_close_logical_channel: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+
+    printf("please enter channel id: ");
+    scanf("%hhu", &channel_id);
+    getchar();
+    
+    ret = ql_sim_close_logical_channel(slot, channel_id);
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+static void item_ql_sim_send_apdu(void)
+{
+    int ret = 0;
+    int input = 0;
+    uint8_t v = 0;
+    QL_SIM_SLOT_E slot;
+    ql_sim_apdu_t *p_apdu = NULL;
+    uint8_t channel_id = 0;
+
+    printf("test ql_sim_send_apdu: \n");
+
+    p_apdu = calloc(1, sizeof(*p_apdu));
+    if (NULL == p_apdu)
+    {
+        printf("run out of memory\n");
+        return;
+    }
+    
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        slot = QL_SIM_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        slot = QL_SIM_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        free(p_apdu);
+        p_apdu = NULL;
+        return;
+    }
+
+    printf("please enter channel id: ");
+    scanf("%hhu", &channel_id);
+    getchar();
+
+    printf("please enter apdu data(hex, end with `q'): ");
+    while (1 == scanf("%hhx", &v))
+    {
+        p_apdu->req_apdu[p_apdu->req_apdu_len++] = v;
+    }
+    getchar();  // read `q'
+    getchar();  // read '\n'
+    
+    ret = ql_sim_send_apdu(slot, channel_id, p_apdu);
+    if (ret == QL_ERR_OK)
+    {
+        uint32_t i = 0;
+        printf("repsonse apdu: ");
+        for (i = 0; i < p_apdu->resp_apdu_len; i++)
+        {
+            printf("%c", p_apdu->resp_apdu[i]);
+        }
+        printf("\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+    free(p_apdu);
+    p_apdu = NULL;
+}
+#endif
+
+static void sim_card_status_cb(int slot, ql_sim_card_info_t *p_info)
+{
+    printf("========= CARD STATUS =========\n");
+    switch (slot)
+    {
+        case 0:
+            printf("slot: invalid\n");
+            break;
+        case 1:
+            printf("slot: 1\n");
+            break;
+        case 2:
+            printf("slot: 2\n");
+            break;
+    }
+    
+    if (NULL == p_info)
+    {
+        printf("status: unavailable\n");
+        return;
+    }
+    
+    printf("state: %s\n", card_state_desc(p_info->state));
+    printf("type: %s\n", card_type_desc(p_info->type));
+    printf("3gpp:\n");
+    printf(" app state: %s\n", card_app_state_desc(p_info->app_3gpp.app_state));
+    printf(" PIN 1 retries: %hhu\n", p_info->app_3gpp.pin1_num_retries);
+    printf(" PUK 1 retries: %hhu\n", p_info->app_3gpp.puk1_num_retries);
+    printf(" PIN 2 retries: %hhu\n", p_info->app_3gpp.pin2_num_retries);
+    printf(" PUK 2 retries: %hhu\n", p_info->app_3gpp.puk2_num_retries);
+    printf("3gpp2:\n");
+    printf(" app state: %s\n", card_app_state_desc(p_info->app_3gpp2.app_state));
+    printf(" PIN 1 retries: %hhu\n", p_info->app_3gpp2.pin1_num_retries);
+    printf(" PUK 1 retries: %hhu\n", p_info->app_3gpp2.puk1_num_retries);
+    printf(" PIN 2 retries: %hhu\n", p_info->app_3gpp2.pin2_num_retries);
+    printf(" PUK 2 retries: %hhu\n", p_info->app_3gpp2.puk2_num_retries);
+    printf("isim:\n");
+    printf(" app state: %s\n", card_app_state_desc(p_info->app_isim.app_state));
+    printf(" PIN 1 retries: %hhu\n", p_info->app_isim.pin1_num_retries);
+    printf(" PUK 1 retries: %hhu\n", p_info->app_isim.puk1_num_retries);
+    printf(" PIN 2 retries: %hhu\n", p_info->app_isim.pin2_num_retries);
+    printf(" PUK 2 retries: %hhu\n", p_info->app_isim.puk2_num_retries);
+}
+
+static void item_ql_sim_set_card_status_cb(void)
+{
+    int ret = 0;
+
+    printf("test ql_sim_set_card_status_cb: ");
+    ret = ql_sim_set_card_status_cb((ql_sim_card_status_cb_f)sim_card_status_cb);
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+void sim_servicie_error_cb(int error)
+{
+    printf("===== SIM Service Abort =====\n");
+}
+
+void item_ql_sim_set_service_error_cb(void)
+{
+    int ret = 0;
+    printf("test ql_sim_set_service_error_cb: \n");
+
+    ret = ql_sim_set_service_error_cb(sim_servicie_error_cb);
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+#if 0
+void item_ql_sim_switch_slot(void)
+{
+    int ret = 0;
+    int input = 0;
+    QL_SIM_PHY_SLOT_E phy_slot = 0;
+    printf("test item_ql_sim_switch_slot: \n");
+    printf("please enter slot(1 or 2): ");
+    scanf("%d", &input);
+    getchar();
+    if (1 == input)
+    {
+        phy_slot = QL_SIM_PHY_SLOT_1;
+    }
+    else if (2 == input)
+    {
+        phy_slot = QL_SIM_PHY_SLOT_2;
+    }
+    else
+    {
+        printf("bad slot: %d\n", input);
+        return;
+    }
+    ret = ql_sim_switch_slot(QL_SIM_SLOT_1, phy_slot);
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+}
+
+void item_ql_sim_get_active_slots(void)
+{
+    int ret = 0;
+    ql_sim_active_slots_t *p_active_slots = (ql_sim_active_slots_t *)malloc(sizeof(ql_sim_active_slots_t));
+    if (p_active_slots == NULL) {  
+        printf("Memory allocation failed.\n");  
+        return -1;  
+    }
+    p_active_slots->active_slots_len = 0;
+    p_active_slots->active_slots[0] = 0;
+    printf("test item_ql_sim_get_active_slots: \n");
+    ret = ql_sim_get_active_slots(p_active_slots);
+    if (ret == QL_ERR_OK)
+    {
+        printf("ok\n");
+	printf("p_active_slots(QL_SIM_PHY_SLOT_1/2 = B01/B02) = %X \n",p_active_slots->active_slots[0]);
+    }
+    else
+    {
+        printf("failed, ret = %d\n", ret);
+    }
+    free(p_active_slots);
+}
+#endif
+
+static t_item_t ql_sim_items[] =
+{
+    {"ql_sim_init", item_ql_sim_init},
+    {"ql_sim_get_imsi", item_ql_sim_get_imsi},
+    {"ql_sim_get_iccid", item_ql_sim_get_iccid},
+    {"ql_sim_get_phone_num", item_ql_sim_get_phone_num},
+    {"ql_sim_get_operators", item_ql_sim_get_operators},
+    {"ql_sim_enable_pin", item_ql_sim_enable_pin},
+    {"ql_sim_disable_pin", item_ql_sim_disable_pin},
+    {"ql_sim_verify_pin", item_ql_sim_verify_pin},
+    {"ql_sim_change_pin", item_ql_sim_change_pin},
+    {"ql_sim_unblock_pin", item_ql_sim_unblock_pin},
+    {"ql_sim_get_card_info", item_ql_sim_get_card_info},
+//    {"ql_sim_read_file", item_ql_sim_read_file},
+//    {"ql_sim_write_file", item_ql_sim_write_file},
+//    {"ql_sim_get_file_info", item_ql_sim_get_file_info},
+//    {"ql_sim_read_phone_book", item_ql_sim_read_phone_book},
+//   {"ql_sim_write_phone_book", item_ql_sim_write_phone_book},
+//    {"ql_sim_open_logical_channel", item_ql_sim_open_logical_channel},
+//    {"ql_sim_close_logical_channel", item_ql_sim_close_logical_channel},
+//    {"ql_sim_send_apdu", item_ql_sim_send_apdu},
+    {"ql_sim_set_card_status_cb", item_ql_sim_set_card_status_cb},
+    {"ql_sim_set_service_error_cb", item_ql_sim_set_service_error_cb},
+//    {"ql_sim_switch_slot", item_ql_sim_switch_slot},
+//    {"ql_sim_get_active_slots", item_ql_sim_get_active_slots},
+    {"ql_sim_deinit", item_ql_sim_deinit},
+};
+
+t_module_t ql_sim_module =
+{
+    "sim",
+    T_ARRAY_SIZE(ql_sim_items),
+    ql_sim_items
+};
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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    
+    if(0 == buf[0])
+    {
+        return -1;
+    }
+#endif
+    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;
+}
+
+void dump_items()
+{
+    int i;
+
+    printf("\n");
+    printf("The current module is: \n");
+
+    for(i=0; i< ql_sim_module.item_len; i++)
+    {
+        printf("%d\t%s\n", i, ql_sim_module.item_list[i].name);
+    }
+    printf("-1\texit\n");
+}
+
+int main(int argc, char *argv[])
+{
+    int ret;
+    int idx;
+
+    dump_items();
+
+    while(1)
+    {
+        printf("Please enter your choice: ");
+        ret = t_get_int(&idx);
+        printf("\n");
+        if(ret < 0)
+        {
+            printf("Invalid input\n");
+            continue;
+        }
+        else if(ret == 1)
+        {
+            dump_items();
+            continue;
+        }
+
+        if(idx == -1)
+        {
+            break;
+        }
+
+        if(idx<0 || idx>=ql_sim_module.item_len)
+        {
+            printf("Not support idx: %d\n", idx);
+            continue;
+        }
+
+        printf("->Item : %s\n", ql_sim_module.item_list[idx].name);
+        ql_sim_module.item_list[idx].handle();
+    }
+
+    return 0;
+}
+
+
+
diff --git a/mbtk/test/libql_lib_v2/ql_sleep_wakelock_test.c b/mbtk/test/libql_lib_v2/ql_sleep_wakelock_test.c
new file mode 100755
index 0000000..0303c72
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_sleep_wakelock_test.c
@@ -0,0 +1,157 @@
+#include "ql_sleep_wakelock.h"
+#include "ql_lpm.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stddef.h>
+#include "mbtk_type.h"
+#include "mbtk_log.h"
+
+static void ql_lpm_handler(ql_lpm_edge_t edge_state)
+{
+    printf("this is ql_lpm_handler, edge_state=%d\n", edge_state);
+}
+
+int main(int argc, char *argv[])
+{
+    char operator[10];
+    int opt;
+    int lv_voll = 0;
+    int fd_t;
+    mbtk_log_init("radio", "SLEEP_TEST");
+
+    printf("=========ql sleep main=========\n"
+        "\t0 exit\n"
+        "\t1 autosuspend enable\n"
+        "\t2 wakelock create\n"
+        "\t3 wakelock lock\n"
+        "\t4 wakelock unlock\n"
+        "\t5 wakelock destroy\n"
+	    "\t6 lpm init\n"
+        "\t7 lpm deinit\n"	
+        "operator: >> \n");
+
+    while(1)
+    {
+        fgets(operator, sizeof(operator), stdin);
+        fflush(stdin);
+        opt = atoi(operator);
+        switch (opt)
+        {
+        case 0:
+            printf("main exit\n");
+            return 0;
+        case 1:
+            {
+                printf(">>>>>Input 0 or 1<<<<<\n");
+                char tmp_en[4]={0};
+                memset(tmp_en, 0x00, sizeof(tmp_en));
+                fgets(tmp_en, sizeof(tmp_en)-1, stdin);
+                fflush(stdin);
+
+                if (tmp_en[0] == '0' || tmp_en[0] == '1')
+                    ql_autosleep_enable(tmp_en[0]);
+                else
+                    printf(">>>>>re Input 0 or 1 error<<<<<\n");
+            }
+            break;
+        case 2:
+            {
+                printf(">>>>>Input name<<<<<\n");
+                char t_name[64]={0};
+                int len_name;
+                char tmp_c[64]={0};
+                memset(tmp_c, 0x00, sizeof(tmp_c));
+                fgets(tmp_c, sizeof(tmp_c)-1, stdin);
+                fflush(stdin);
+                len_name = strlen(tmp_c)-1;
+                strncpy(t_name, tmp_c, len_name);
+                printf(">>>>>name=[%s] name_len=[%d]<<<<<\n",t_name, len_name);
+
+                fd_t = ql_slp_wakelock_create(t_name, len_name);
+                if (fd_t == -1)
+                {
+                    printf(">>>>>Output error =[%d]<<<<<\n",fd_t);
+                }
+                else
+                {
+                    printf(">>>>>Output ID NUM =[%d]<<<<<\n",fd_t);
+                }
+            }
+            break;
+        case 3:
+            {
+                printf(">>>>>Input ID NUM<<<<<\n");
+                char tmp_l[127]={0};
+                fgets(tmp_l, sizeof(tmp_l), stdin);
+                fflush(stdin);
+                fd_t = atoi(tmp_l);
+                fd_t = ql_slp_wakelock_lock(fd_t);
+                if (fd_t == -1)
+                {
+                    printf(">>>>>Output error =[%d]<<<<<\n",fd_t);
+                }
+                else
+                {
+                    printf(">>>>>Output succuess<<<<<\n");
+                }
+            }
+            break;
+        case 4:
+            {
+                printf(">>>>>Input ID NUM<<<<<\n");
+                char tmp_ul[127]={0};
+                memset(tmp_ul, 0x00, sizeof(tmp_ul));
+                fgets(tmp_ul, sizeof(tmp_ul)-1, stdin);
+                fflush(stdin);
+                fd_t = atoi(tmp_ul);
+                fd_t = ql_slp_wakelock_unlock(fd_t);
+                if (fd_t == -1)
+                {
+                    printf(">>>>>Output error =[%d]<<<<<\n",fd_t);
+                }
+                else
+                {
+                    printf(">>>>>Output succuess<<<<<\n");
+                }
+            }
+            break;
+        case 5:
+            {
+                printf(">>>>>Input ID NUM<<<<<\n");
+                char tmp_d[127]={0};
+                memset(tmp_d, 0x00, sizeof(tmp_d));
+                fgets(tmp_d, sizeof(tmp_d)-1, stdin);
+                fflush(stdin);
+                fd_t = atoi(tmp_d);
+                fd_t = ql_slp_wakelock_destroy(fd_t);
+                if (fd_t == -1)
+                {
+                    printf(">>>>>Output error =[%d]<<<<<\n",fd_t);
+                }
+                else
+                {
+                    printf(">>>>>Output succuess<<<<<\n");
+                }
+            }
+            break;
+        case 6:
+            {
+				int ret;
+				ret = ql_lpm_init(ql_lpm_handler);
+				printf("ql lpm init, ret: %d\n", ret);		
+            }
+            break;
+        case 7:
+            ql_lpm_deinit();
+            break;
+			
+        default:
+            break;
+        }
+
+    }
+
+    return 0;
+}
+
diff --git a/mbtk/test/libql_lib_v2/ql_sms_test.c b/mbtk/test/libql_lib_v2/ql_sms_test.c
new file mode 100755
index 0000000..1ebdde2
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_sms_test.c
@@ -0,0 +1,162 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "ql_sms.h"
+#include "mbtk_log.h"
+
+
+
+void sms_msg_recv_cb(ql_sms_msg_t *p_msg, ql_sms_timestamp_t *timestamp,
+                                             ql_sms_user_data_head_t *head)
+{
+    printf("sms_msg_recv_cb succeess!\n");
+    printf("format: %d, addr:%s, content_size:%d, content:%s\n", p_msg->format, p_msg->addr, p_msg->content_size, p_msg->content);
+    printf("timestamp: %d-%d-%d %d:%d:%d\n", timestamp->year, timestamp->month, timestamp->day, timestamp->hours, timestamp->minutes, timestamp->seconds);
+}
+
+void sms_servicie_error_cb(int error)
+{
+    printf("===== SMS Service Abort =====\n");
+}
+
+void sms_msg_async_cb_f(int id, int result)
+{
+    printf("===== sms_msg_recv_cb =====\n");
+}
+
+
+
+
+int main(int argc, char *argv[])
+{
+    char operator[10];
+    int opt;
+    int ret;
+//    int sms;
+//    int direction;
+//    int value;
+//    int pullsel;
+
+	mbtk_log_init("radio", "SMS_TEST");
+
+    printf("=========ql sms main=========\n"
+        "\t0 exit\n"
+        "\t1 sms init\n"
+		"\t2 sms deinit\n"
+        "\t3 sms set msg recv cb\n"
+        "\t4 sms set ser error cb\n"
+        "\t5 sms send msg async\n"
+        "operator: >> \n");
+
+    while(1)
+    {
+		memset(operator, 0, sizeof(operator));
+        if(NULL == fgets(operator, sizeof(operator), stdin))
+            break;
+        fflush(stdin);
+        opt = atoi(operator);
+        switch (opt)
+        {
+        case 0:
+            printf("main exit\n");
+            return 0;
+        case 1:
+            {
+                printf(">>>>>sms init\n");
+				ret = ql_sms_init();
+				if(ret != 0)
+				{
+					printf("ql_sms_init fail\n");
+				}
+				else
+				{
+					printf("ql_sms_init success\n");
+				}
+            }
+            break;
+        case 2:
+            {
+				printf(">>>>>sms uninit\n");
+
+				ret = ql_sms_deinit();
+				if(ret != 0)
+				{
+					printf("ql_sms_uninit fail\n");
+					printf("ret=%d\n", ret);
+				}
+				else
+				{
+					printf("ql_sms_uninit success\n");
+
+				}
+            }
+            break;
+        case 3:
+            {
+                printf(">>>>>Input set recv cb<<<<<\n");
+
+				ret = ql_sms_set_msg_recv_cb(sms_msg_recv_cb);
+				if(ret != 0)
+				{
+					printf("ql_sms_set_msg_recv_cb fail\n");
+				}
+				else
+				{
+					printf("ql_sms_set_msg_recv_cb success\n");
+				}
+
+            }
+            break;
+        case 4:
+            {
+                printf(">>>>>Input set ser cb<<<<<\n");
+
+			    ret = ql_sms_set_service_error_cb(sms_servicie_error_cb);
+				if(ret < 0)
+				{
+					printf("ql_sms_set_service_error_cb fail\n");
+				}
+				else
+				{
+					printf("ql_sms_set_service_error_cb success\n");
+				}
+
+            }
+            break;
+        case 5:
+            {
+                printf(">>>>>Input send msg<<<<<\n");
+
+                ql_sms_msg_t    sms_msg = {0};
+                int id = 0;
+                char addr[128] = "19130850401";
+                char content[128] = "hello";
+                sms_msg.format = 1;
+                memcpy(sms_msg.addr, addr, strlen(addr));
+                sms_msg.content_size = strlen(content);
+                memcpy(sms_msg.content, content, strlen(content));
+
+
+                ret = ql_sms_send_msg_async(&sms_msg, &id, sms_msg_async_cb_f);
+				if(ret < 0)
+				{
+					printf("ql_sms_send_msg_async fail\n");
+				}
+				else
+				{
+					printf("ql_sms_send_msg_async success\n");
+				}
+            }
+            break;
+
+
+        default:
+            break;
+        }
+
+    }
+
+    return 0;
+
+}
diff --git a/mbtk/test/libql_lib_v2/ql_test_abfota.c b/mbtk/test/libql_lib_v2/ql_test_abfota.c
new file mode 100755
index 0000000..04ef676
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_test_abfota.c
@@ -0,0 +1,570 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+#include <pthread.h>
+#include "ql_fota_api.h"
+#include "fota_info.h"
+#include "ql_fota.h"
+//#include "ql_fota_log.h"
+#include "ql_absys_api.h"
+//#include "test_utils.h"
+
+
+typedef void (*item_handler_f)(void);
+typedef int (*init_handler_f)(void);
+typedef int (*deinit_handler_f)(void);
+
+
+#define T_ARRAY_SIZE(items) (sizeof(items)/sizeof(items[0]))
+
+typedef struct
+{
+    const char *name;
+    item_handler_f handle;
+} t_item_t;
+
+typedef struct
+{
+    const char *name;
+    int item_len;
+    t_item_t *item_list;
+} t_module_t;
+
+typedef struct
+{
+    const char *name;
+    init_handler_f init_handle;
+    deinit_handler_f deinit_handle;
+} t_init_t;
+
+int t_get_int(int *val);
+int t_get_hex(uint32_t *val);
+int t_get_char(int *val);
+int t_get_string(char *str_buf, int str_len);
+int t_get_int_list(int *dat_buf, int *dat_len);
+int t_get_float_list(float *dat_buf, int *dat_len);
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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;
+}
+#if 0
+#define DEBUG_INFO
+#ifdef DEBUG_INFO
+#define LOG_DBG(fmt, ...) printf("[DBG][%s_%d][%ld] "fmt"\n", __FUNCTION__, __LINE__, time(NULL), ##__VA_ARGS__)
+#else
+#define LOG_DBG(fmt, ...)
+#endif
+#define LOG_ERR(fmt, ...) printf("[DBG][%s_%d][%ld] "fmt"\n", __FUNCTION__, __LINE__, time(NULL), ##__VA_ARGS__)
+#endif
+
+#define ITEM_NUM (sizeof(g_items)/sizeof(g_items[0]))
+
+void test_ota_api_start(void);
+void test_get_fota_upgrade_info(void);
+void test_ql_absys_switch(void);
+void test_ql_absys_get_cur_active_part(void);
+void test_ql_absys_sync(void);
+void test_ql_absys_getstatus(void);
+void test_ql_fota_fw_write_by_url(void);
+
+t_item_t g_items[] = {
+    {"API : ql_abfota_start_update", test_ota_api_start},
+    {"API : ql_abfota_get_update_status", test_get_fota_upgrade_info},
+	{"API : ql_absys_switch", test_ql_absys_switch},
+	{"API : ql_absys_sync", test_ql_absys_sync},
+	{"API : ql_absys_get_cur_active_part", test_ql_absys_get_cur_active_part},
+	{"API : ql_absys_getstatus", test_ql_absys_getstatus}
+};
+
+void dump_items(void)
+{
+    int i;
+
+    printf("\n");
+
+    for(i=0; i<ITEM_NUM; i++)
+    {
+        printf("%d\t%s\n", i, g_items[i].name);
+    }
+    printf("-1\texit\n");
+}
+
+int main(int argc, const char **argv)
+{
+	int ret = -1;
+    int idx = 0;
+
+    printf("Quectel OTA API test sample, version : v0.0.1\n");
+
+	dump_items();
+
+	while(1) {
+        printf("Please enter your choice: ");
+        ret = t_get_int(&idx);
+        printf("\n");
+        if(ret < 0) {
+            printf("Invalid input\n");
+            continue;
+        } else if(ret == 1) {
+            dump_items();
+            continue;
+        }
+
+        if(idx == -1) {
+            break;
+        }
+
+        if(idx<0 || idx>=ITEM_NUM) {
+            printf("Not support idx: %d\n", idx);
+            continue;
+        }
+
+        g_items[idx].handle();
+    }
+    return 0;
+}
+
+void test_ota_api_start(void)
+{
+    char package_file[128] = {0};
+    int ret = -1;
+
+    printf("please input the fota fbf package file dir: \n");
+	printf("eg: /user_data/\n");
+	//fota包同时已经放入该路径下
+	memset(package_file, 0x0, sizeof(package_file));
+	scanf("%s", package_file);
+	fflush(stdin);
+    ret = t_get_string((char*)package_file, sizeof(package_file));
+    if (ret < 0 || package_file[0] == 0) {
+        printf("Invalid package file\n");
+        return;
+    }
+
+    ret = ql_abfota_start_update((char*)package_file);
+
+    if (ret != 0) {
+        printf("run ql_abfota_start_update failed, api return: %d\n", ret);
+        return;
+    }
+
+    printf("Update in-active partition SUCCEED\n");
+    return;
+}
+
+void test_ql_absys_getstatus(void)
+{
+    int status = 0;
+//    char stat_buf[16] = {0};
+    sysstatus_t sys_state;
+    status = ql_absys_getstatus(&sys_state);
+    if (status < 0) {
+        printf("failed to get absys status!!!\n");
+        return;
+    }
+
+	if (sys_state.is_damaged == 0)
+	{
+		printf("absys partition status : succeed\n");
+	}
+	else
+	{
+		printf("absys partition status : damaged\n");
+		printf("absys partition damaged position : %s\n", sys_state.damaged_partname);
+		printf("absys needsync!!!\n");
+	}
+    return;
+}
+
+
+void test_get_fota_upgrade_info(void)
+{   
+    int ret = -1;
+    char stat_buf[16] = {0};
+    update_info_t update_info;
+    ret = ql_abfota_get_update_status(&update_info);
+    if ( ret != 0) {
+        printf("run ql_abfota_start_update failed, api return: %d\n", ret);
+        return;
+    }
+
+    memset(stat_buf, 0, sizeof(stat_buf));
+
+    switch (update_info.ota_state) {
+        case SUCCEED:
+            strncpy(stat_buf, "SUCCEED", strlen("SUCCEED")+1);
+        break;
+        case UPDATE:
+            strncpy(stat_buf, "UPDATE", strlen("UPDATE")+1);
+        break;
+        case BACKUP:
+            strncpy(stat_buf, "BACKUP", strlen("BACKUP")+1);
+        break;
+        case FAILED:
+            strncpy(stat_buf, "FAILED", strlen("FAILED")+1);
+        break;
+        case WRITEDONE:
+            strncpy(stat_buf, "WRITEDONE", strlen("WRITEDONE")+1);
+        break;
+        case NEEDSYNC:
+            strncpy(stat_buf, "NEEDSYNC", strlen("NEEDSYNC")+1);
+        break;
+        case UNKNOWN_STATUS:
+        default:
+            strncpy(stat_buf, "UNKNOWN_STATUS", strlen("UNKNOWN_STATUS")+1);
+        break;
+    }
+
+	printf("Current fota progress: %d\n", update_info.percentage);
+    printf("Current fota state: %s\n", stat_buf);
+    printf("Current fota exit code: %d\n", update_info.exit_code);
+
+    return;
+}
+
+void test_ql_absys_switch(void)
+{
+    int ret = -1;
+    ret = ql_absys_switch();
+    if (ret != 0) {           
+        printf("run ql_absys_switch failed, api return: %d\n", ret);
+        return;               
+    }  
+
+    printf("It is okay to swith AB part to run\n");
+    sleep(1);
+
+    system("reboot");
+    return;
+}
+
+
+void test_ql_absys_sync(void) 
+{
+    int ret = -1;             
+
+    ret = ql_absys_sync();    
+    if (ret != 0) {
+        printf("run ql_absys_sync failed, api return: %d\n", ret);
+        return;
+    }            
+
+    printf("do AB sync succeed\n");
+    return;
+}
+
+
+void test_ql_absys_get_cur_active_part(void)
+{
+    int ret = -1;
+    absystem_t cur_system;
+
+    ret = ql_absys_get_cur_active_part(&cur_system);
+    if (ret != 0) {
+        printf("run ql_absys_get_cur_active_part failed, api return: %d\n", ret);
+        return;
+    }
+
+    printf("Current active part is %c\n", (cur_system ? 'B': 'A'));
+    return;
+}
\ No newline at end of file
diff --git a/mbtk/test/libql_lib_v2/ql_test_utils.h b/mbtk/test/libql_lib_v2/ql_test_utils.h
new file mode 100755
index 0000000..2f6aa93
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_test_utils.h
@@ -0,0 +1,140 @@
+/*-----------------------------------------------------------------------------------------------*/
+/**
+  @file ql_test_utils.h 
+  @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 .
+-------------------------------------------------------------------------------------------------*/
+
+#ifndef __TEST_UTILS_H__
+#define  __TEST_UTILS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+typedef void (*item_handler_f)(void);
+typedef int (*init_handler_f)(void);
+typedef int (*deinit_handler_f)(void);
+
+
+#define T_ARRAY_SIZE(items) (sizeof(items)/sizeof(items[0]))
+
+typedef struct
+{
+    const char *name;
+    item_handler_f handle;
+} t_item_t;
+
+typedef struct
+{
+    const char *name;
+    int item_len;
+    t_item_t *item_list;
+} t_module_t;
+
+typedef struct
+{
+    const char *name;
+    init_handler_f init_handle;
+    deinit_handler_f deinit_handle;
+} t_init_t;
+
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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);
+
+/*-----------------------------------------------------------------------------------------------*/
+/** 
+  @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);
+
+
+#ifdef __cplusplus
+} 
+#endif
+
+#endif
+
diff --git a/mbtk/test/libql_lib_v2/ql_voice_test.c b/mbtk/test/libql_lib_v2/ql_voice_test.c
new file mode 100755
index 0000000..61a6cc3
--- /dev/null
+++ b/mbtk/test/libql_lib_v2/ql_voice_test.c
@@ -0,0 +1,236 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "ql_voice.h"
+
+
+
+void voice_call_cb(ql_voice_record_array_t *p_arr)
+{
+
+    printf("len1-voice_call_cb-id:%d, number:%s, state:%d, tech:%d, dir:%d, end_reason:%d\n", p_arr->records[0].id, p_arr->records[0].number, p_arr->records[0].state, p_arr->records[0].tech,
+                     p_arr->records[0].dir, p_arr->records[0].end_reason);
+    if(2 == p_arr->len)
+    {
+    printf("len2-id:%d, number:%s, state:%d, tech:%d, dir:%d, end_reason:%d\n", p_arr->records[1].id, p_arr->records[1].number, p_arr->records[1].state, p_arr->records[1].tech,
+                                    p_arr->records[1].dir, p_arr->records[1].end_reason);
+    }
+}
+
+void voice_servicie_error_cb(int error)
+{
+    printf("===== voice Service Abort =====\n");
+}
+
+
+
+
+
+
+int main(int argc, char *argv[])
+{
+    char operator[10];
+    int opt;
+    int ret;
+    int voice;
+    int direction;
+    int value;
+    int pullsel;
+
+	mbtk_log_init("radio", "voice_TEST");
+
+    printf("=========ql voice main=========\n"
+        "\t0 exit\n"
+        "\t1 voice init\n"
+		"\t2 voice deinit\n"
+        "\t3 voice set call cb\n"
+        "\t4 voice set ser error cb\n"
+        "\t5 voice dial\n"
+        "\t6 voice hangup all\n"
+        "\t7 voice answer\n"
+        "\t8 voice get records\n"
+        "\t9 voice send dtmf char\n"
+        "operator: >> \n");
+
+    while(1)
+    {
+		memset(operator, 0, sizeof(operator));
+        fgets(operator, sizeof(operator), stdin);
+        fflush(stdin);
+        opt = atoi(operator);
+        switch (opt)
+        {
+        case 0:
+            printf("main exit\n");
+            return 0;
+        case 1:
+            {
+                printf(">>>>>voice init\n");
+				ret = ql_voice_init();
+				if(ret != 0)
+				{
+					printf("ql_voice_init fail\n");
+				}
+				else
+				{
+					printf("ql_voice_init success\n");
+				}
+            }
+            break;
+        case 2:
+            {
+				printf(">>>>>voice uninit\n");
+
+				ret = ql_voice_deinit();
+				if(ret != 0)
+				{
+					printf("ql_voice_uninit fail\n");
+					printf("ret=%d\n", ret);
+				}
+				else
+				{
+					printf("ql_voice_uninit success\n");
+
+				}
+            }
+            break;
+        case 3:
+            {
+                printf(">>>>>Input set recv cb<<<<<\n");
+
+				ret = ql_voice_set_call_cb(voice_call_cb);
+				if(ret != 0)
+				{
+					printf("ql_voice_set_msg_recv_cb fail\n");
+				}
+				else
+				{
+					printf("ql_voice_set_msg_recv_cb success\n");
+				}
+
+            }
+            break;
+        case 4:
+            {
+                printf(">>>>>Input set ser cb<<<<<\n");
+
+			    ret = ql_voice_set_service_error_cb(voice_servicie_error_cb);
+				if(ret < 0)
+				{
+					printf("ql_voice_set_service_error_cb fail\n");
+				}
+				else
+				{
+					printf("ql_voice_set_service_error_cb success\n");
+				}
+
+            }
+            break;
+        case 5:
+            {
+                printf(">>>>>Input ql_voice_dial<<<<<\n");
+
+                uint32_t id = 0;
+                ret = ql_voice_dial("13388257090", 11, &id);
+                printf("id:%d", id);
+				if(ret < 0)
+				{
+					printf("ql_voice_dial fail\n");
+				}
+				else
+				{
+					printf("ql_voice_dial success\n");
+				}
+            }
+            break;
+        case 6:
+            {
+                printf(">>>>>Input ql_voice_hangup_all<<<<<\n");
+
+                int id = 0;
+                ret = ql_voice_hangup_all();
+                if(ret < 0)
+                {
+                    printf("ql_voice_hangup_all fail\n");
+                }
+                else
+                {
+                    printf("ql_voice_hangup_all success\n");
+                }
+            }
+            break;
+        case 7:
+            {
+                printf(">>>>>Input ql_voice_answer<<<<<\n");
+
+                int id = 0;
+                ret = ql_voice_answer(1);
+				if(ret < 0)
+				{
+					printf("ql_voice_answer fail\n");
+				}
+				else
+				{
+					printf("ql_voice_answer success\n");
+				}
+            }
+            break;
+        case 8:
+            {
+                printf(">>>>>Input ql_voice_get_records<<<<<\n");
+
+                ql_voice_record_array_t arr;
+                ret = ql_voice_get_records(&arr);
+                printf("len1-id:%d, number:%s, state:%d, tech:%d, dir:%d, end_reason:%d\n", arr.records[0].id, arr.records[0].number, arr.records[0].state, arr.records[0].tech,
+                            arr.records[0].dir, arr.records[0].end_reason);
+                if(2 == arr.len)
+                {
+                    printf("len2-id:%d, number:%s, state:%d, tech:%d, dir:%d, end_reason:%d\n", arr.records[1].id, arr.records[1].number, arr.records[1].state, arr.records[1].tech,
+                        arr.records[1].dir, arr.records[1].end_reason);
+                }
+
+                if(ret < 0)
+                {
+                    printf("ql_voice_get_records fail\n");
+                }
+                else
+                {
+                    printf("ql_voice_get_records success\n");
+                }
+            }
+            break;
+         case 9:
+            {
+                printf(">>>>>Input ql_voice_send_dtmf_char<<<<<\n");
+
+
+                char inputChar;
+
+                printf("Enter set dtmf\n");
+                scanf(" %c", &inputChar);
+                printf("inputChar is %c\n", inputChar);
+
+                ret = ql_voice_send_dtmf_char(1, inputChar);
+				if(ret < 0)
+				{
+					printf("ql_voice_send_dtmf_char fail\n");
+				}
+				else
+				{
+					printf("ql_voice_send_dtmf_char success\n");
+				}
+            }
+            break;
+
+
+
+        default:
+            break;
+        }
+
+    }
+
+    return 0;
+
+}