Add toolchain and mbtk source

Change-Id: Ie12546301367ea59240bf23d5e184ad7e36e40b3
diff --git a/mbtk/test/Makefile b/mbtk/test/Makefile
new file mode 100755
index 0000000..3a10f89
--- /dev/null
+++ b/mbtk/test/Makefile
@@ -0,0 +1,41 @@
+ROOT = $(shell pwd)/../..
+include ../Make.defines
+
+LOCAL_PATH=$(BUILD_ROOT)/test
+
+INC_DIR += 
+	
+LIB_DIR +=
+
+LIBS += -lmbtk_lib -lql_lib -llynq_lib -lmbtk_mqtt_lib -lpolarssl -laudio-apu -lcutils -ltinyalsa -lacm
+
+CFLAGS += 
+
+DEFINE +=
+
+MY_FILES_PATH:=$(LOCAL_PATH)
+#ifeq ($(CONFIG_MBTK_QL_SUPPORT),y)
+#MY_FILES_PATH += $(LOCAL_PATH)/ql
+#endif
+
+#ifeq ($(CONFIG_MBTK_PLATFORM),linux)
+#MY_FILES_PATH += $(LOCAL_PATH)/platform/linux
+#endif
+
+MY_FILES_SUFFIX:=%.c %.cpp
+My_All_Files := $(foreach src_path,$(MY_FILES_PATH), $(shell find "$(src_path)" -type f))
+MY_SRC_LIST  := $(filter $(MY_FILES_SUFFIX),$(My_All_Files))
+MY_SRC_LIST  := $(MY_SRC_LIST:$(LOCAL_PATH)/%=%)
+LOCAL_SRC_FILES += $(MY_SRC_LIST)
+$(info LOCAL_SRC_FILES = $(LOCAL_SRC_FILES))
+
+BINS = $(patsubst %.c,%,$(LOCAL_SRC_FILES))
+
+all: $(BINS)
+
+$(BINS):
+	@echo "  BIN     $@"
+	$(CC) $(CFLAGS) -o $(OUT_DIR)/bin/$@ $@.c $(DEFINE) $(INC_DIR) $(LIB_DIR) $(LIBS)
+
+clean:
+	
\ No newline at end of file
diff --git a/mbtk/test/aiti_audio_test.c b/mbtk/test/aiti_audio_test.c
new file mode 100755
index 0000000..c9fa936
--- /dev/null
+++ b/mbtk/test/aiti_audio_test.c
@@ -0,0 +1,540 @@
+#include "mbtk_type.h"
+#include <fcntl.h>
+#include <stdint.h>
+#include <limits.h>
+#include <termios.h>
+#include <stdarg.h>
+// #include "ql_at.h"
+#include "ql/ql_audio.h"
+// #include "mopen_tts.h"
+
+#define MBTK_AUD_DEMO_WAV "/data/demo.wav"
+
+#define MBTK_AUD_DEMO_WAV1 "/data/demo1.wav"
+
+
+int play_hdl = 0;
+static int record_fd = 0;
+
+
+int Ql_cb_playback(int hdl, int result)
+{
+    printf("%s: hdl=%d, result=%d\n\r", __func__, hdl, result);
+    if (result == AUD_PLAYER_FINISHED || result == AUD_PLAYER_NODATA)
+    {
+        printf("%s: play finished\n\r", __func__);
+    }
+    return 0;
+}
+
+void record_cb_func(int cb_result, char* databuf, unsigned int len)
+{
+    int rc;
+
+    if(NULL != databuf && len > 0 && record_fd > 0)
+    {
+        //for debug:save into file
+        rc = write(record_fd, databuf, len);
+        if (rc < 0) {
+            printf("%s: error writing to file!\n", __FUNCTION__);
+        } else if (rc < len) {
+            printf("%s: wrote less the buffer size!\n", __FUNCTION__);
+        }
+    }
+}
+
+
+int MBTK_wav_pcm16Le_check(int fd)
+{
+    struct wav_header hdr;
+
+    if (fd <= 0)
+        return -1;
+
+    if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr))
+    {
+        printf("\n%s: cannot read header\n", __FUNCTION__);
+        return -1;
+    }
+
+        printf("hdr.riff_id:%X, hdr.riff_fmt:%X, hdr.fmt_id:%X", hdr.riff_id, hdr.riff_fmt, hdr.fmt_id);
+
+    if ((hdr.riff_id != ID_RIFF)
+            || (hdr.riff_fmt != ID_WAVE)
+            || (hdr.fmt_id != ID_FMT))
+    {
+        printf("\n%s: is not a riff/wave file\n", __FUNCTION__);
+        return -1;
+    }
+
+    if ((hdr.audio_format != FORMAT_PCM) || (hdr.fmt_sz != 16)) {
+        printf("\n%s: is not pcm format\n", __FUNCTION__);
+        return -1;
+    }
+
+    if (hdr.bits_per_sample != 16) {
+        printf("\n%s: is not 16bit per sample\n", __FUNCTION__);
+        return -1;
+    }
+
+    printf("audio_format: %d,num_channels: %d,sample_rate: %d,byte_rate: %d,bits_per_sample:  %d data_sz: %d\n",
+           hdr.audio_format, hdr.num_channels, hdr.sample_rate, hdr.byte_rate, hdr.bits_per_sample, hdr.data_sz);
+
+    return hdr.data_sz;
+}
+
+int MBTK_wav_pcm16Le_set(int fd)
+{
+    struct wav_header hdr;
+
+    if (fd <= 0)
+        return -1;
+
+    memset(&hdr, 0, sizeof(struct wav_header));
+
+    hdr.riff_id = ID_RIFF;
+    hdr.riff_fmt = ID_WAVE;
+    hdr.fmt_id = ID_FMT;
+    hdr.fmt_sz = 16;
+    hdr.audio_format = FORMAT_PCM;
+    hdr.num_channels = 1;
+    hdr.sample_rate = 8000;
+    hdr.bits_per_sample = 16;
+    hdr.byte_rate = (8000 * 1 * hdr.bits_per_sample) / 8;
+    hdr.block_align = (hdr.bits_per_sample * 1) / 8;
+    hdr.data_id = ID_DATA;
+    hdr.data_sz = 0;
+
+    hdr.riff_sz = hdr.data_sz + 44 - 8;
+    if (write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
+        return -1;
+    }
+
+    return 0;
+}
+
+unsigned char* handle_file1(char *audioFilePath)
+{
+    long filesize;
+    unsigned char *pcmBuf = NULL;
+    FILE *fp = NULL;
+    int size;
+
+    // 处理文件格式
+    fp = fopen(audioFilePath, "rb");
+    if (!fp) {
+        printf("%s:fopen failed",__func__);
+    }
+    
+    fseek(fp,0,SEEK_END);
+    filesize=ftell(fp);
+    printf("%s:filesize:%d\n", __func__, filesize);
+    fseek(fp,44,SEEK_SET);
+    pcmBuf =(unsigned char *)malloc(sizeof(char)*filesize);
+    memset(pcmBuf,0,sizeof(char)*filesize);
+//    fread(pcmBuf, filesize-44,1, fp);
+    fread(pcmBuf, 1, filesize-44, fp);
+    fclose(fp);
+
+    printf("strlen(pcmBuf):%d\n", strlen(pcmBuf));
+
+    return pcmBuf;
+}
+
+void *audio_thread(void *arg)
+{
+    printf("audio_thread(1)----------\n");
+    Ql_Playback_Samprate_Set(1);
+    int play_hdl = 0;
+    int fd = 0;
+    int ret;
+    int file_size =0;
+    int file_size1 =0;
+    unsigned char *pcmBuf = NULL;
+    unsigned char *pcmBuf1 = NULL;
+
+    play_hdl = Ql_AudPlayer_Open(NULL, Ql_cb_playback);
+    if(0 == play_hdl)
+    {
+        printf("Ql_AudPlayer_Open fail\n");
+    }
+
+    fd = open(MBTK_AUD_DEMO_WAV, O_RDWR);
+    if (fd <= 0)
+    {
+        printf("Open fail\n");
+    }
+
+    int fd1 = open(MBTK_AUD_DEMO_WAV1, O_RDWR);
+    printf("fd1:%d\n", fd1);
+    if (fd1 <= 0)
+    {
+        printf("Open fail\n");
+    }
+
+    file_size = MBTK_wav_pcm16Le_check(fd);
+
+    file_size1 = MBTK_wav_pcm16Le_check(fd1);
+    printf("file_size:%d, file_size1:%d\n", file_size, file_size1);
+
+    pcmBuf = handle_file1(MBTK_AUD_DEMO_WAV);
+
+    pcmBuf1 = handle_file1(MBTK_AUD_DEMO_WAV1);
+    
+    if(file_size > 0  && file_size1 > 0 )
+    {
+        if(pcmBuf != NULL)
+        {
+            ret = Ql_AudPlayer_Play(play_hdl, pcmBuf, file_size);
+            printf("ret:%d\n", ret);
+        }
+
+        Ql_Rxgain_Set(3);
+        if(pcmBuf1 != NULL)
+        {
+            ret = Ql_AudPlayer_Play(play_hdl, pcmBuf1, file_size1);
+            printf("ret:%d\n", ret);
+        }
+
+    }
+
+    Ql_AudPlayer_Close(play_hdl);
+    close(fd);
+    close(fd1);
+    return 0;
+}
+
+
+void *audio_play_file_thread(void *arg)
+{
+    char operator[10];
+
+    int fd = open(MBTK_AUD_DEMO_WAV, O_RDWR);
+    if (fd <= 0)
+        return 0;
+
+    int fd1 = open(MBTK_AUD_DEMO_WAV1, O_RDWR);
+    if (fd1 <= 0)
+        return 0;
+    
+    Ql_AudPlayer_PlayFrmFile(play_hdl, fd, 0);
+
+    Ql_Rxgain_Set(3);
+
+    Ql_AudPlayer_PlayFrmFile(play_hdl, fd1, 0);
+
+    close(fd);
+    close(fd1);
+
+    return 0;
+}
+
+
+int aplay_thread(char *audioFilePath)
+{
+    int res;
+    pthread_t play_thread;
+
+    res = pthread_create(&play_thread, NULL, audio_thread, audioFilePath);
+    if (res != 0) {
+        printf("%s:pthread_create failed",__func__);
+        return 0;
+    }
+
+    return 0;
+}
+
+
+int aplay_file_thread(int play_hdl)
+{
+    int res;
+    pthread_t play_thread;
+    int hdl = play_hdl;
+
+    res = pthread_create(&play_thread, NULL, audio_play_file_thread, &hdl);
+    if (res != 0) {
+        printf("%s:pthread_create failed",__func__);
+        return 0;
+    }
+
+    return 0;
+}
+
+
+
+void aplay(void)
+{
+    char operator[10];
+    char databuf[1024];
+    int opt = 0;
+    int fd = 0;
+    int size = 0;
+    int state;
+    int handler = 0;
+    int file_size = 0 ;
+
+    while(1)
+    {
+        printf("=========aplay========2\n"
+            "\t 0 Open PCM\n"
+            "\t 1 Play Stream\n"
+            "\t 2 Play file\n"
+            "\t 3 Close\n"
+            "\t 4 play stream thread\n"
+            "\t 5 pause\n"
+            "\t 6 repause\n"
+            "\t 7 play file thread\n"
+            "\t 8 play mp3\n"
+            "\t others exit\n\n"
+            "operator >> ");
+
+        fflush(stdin);
+        fgets(operator, sizeof(operator), stdin);
+        opt = atoi(operator);
+        switch (opt)
+        {
+            case 0:
+                Ql_Playback_Samprate_Set(1);
+                play_hdl = Ql_AudPlayer_Open(NULL, Ql_cb_playback);
+                if(0 == play_hdl)
+                    printf("Ql_AudPlayer_Open fail\n");
+
+                printf("\nplay_hdl:%d\n", play_hdl);
+                break;
+            case 1:
+               if(0 == play_hdl)
+                    continue;
+
+                fd = open(MBTK_AUD_DEMO_WAV, O_RDWR);
+                if (fd <= 0)
+                    continue;
+
+                file_size = MBTK_wav_pcm16Le_check(fd);
+                printf("file_size:%d\n", file_size);
+                if(file_size > 0 )
+                {
+                    unsigned char *pcmBuf = NULL;
+                    char *p1 = pcmBuf;
+                    pcmBuf = handle_file1(MBTK_AUD_DEMO_WAV);
+                    if(pcmBuf != NULL)
+                    {
+                        if(-1 == Ql_AudPlayer_Play(play_hdl, pcmBuf, file_size))
+                                printf("\n------\n");
+                    }
+
+                }
+
+//                Ql_Rxgain_Set(5);
+
+                close(fd);
+                break;
+            case 2:
+                if(0 == play_hdl)
+                    continue;
+
+                fd = open(MBTK_AUD_DEMO_WAV, O_RDWR);
+                if (fd <= 0)
+                    continue;
+
+                if(1)
+                {
+                    Ql_AudPlayer_PlayFrmFile(play_hdl, fd, 44);
+                }
+                else
+                {
+                    printf("aplay file type error\n");
+                }
+                close(fd);
+                break;
+            case 3:
+                if(0 == play_hdl)
+                    continue;
+                Ql_AudPlayer_Close(play_hdl);
+                break;
+            case 4:
+                aplay_thread(MBTK_AUD_DEMO_WAV);
+                break;
+            case 5:
+                if(0 == play_hdl)
+                    continue;
+                Ql_AudPlayer_Pause(play_hdl);
+                break;
+            case 6:
+                if(0 == play_hdl)
+                    continue;
+                Ql_AudPlayer_Resume(play_hdl);
+                break;
+            case 7:
+                if(0 == play_hdl)
+                    continue;
+                aplay_file_thread(play_hdl);
+                break;
+            case 8:
+           //     Ql_Mp3_To_Wav("/data/demo.wav", "/data/mp3demo.mp3", play_hdl);
+                Ql_Mp3_To_Play("/data/mp3demo.mp3", play_hdl, 0);
+                break;
+            default:
+                return;
+        }
+
+        sleep(1);
+    }
+
+    printf("aplay exit\n");
+    return ;
+}
+void arec(void)
+{
+    int ret;
+    char operator[10];
+    int opt;
+    int hdl = 0;
+
+    while(1)
+    {
+        printf("=======arec======\n"
+            "\t 0 Open PCM\n"
+            "\t 1 Start Record\n"
+            "\t 2 Get state\n"
+            "\t 3 Pause\n"
+            "\t 4 Resume\n"
+            "\t 5 Stop\n"
+            "\t 6 Close\n"
+            "\t others exit\n\n"
+            "operator >> ");
+
+        fflush(stdin);
+        fgets(operator, sizeof(operator), stdin);
+        opt = atoi(operator);
+        switch (opt)
+        {
+            case 0:
+                Ql_Playback_Samprate_Set(0);
+                hdl = Ql_AudRecorder_Open(NULL, record_cb_func);
+                if (hdl == 0)
+                    return ;
+                break;
+            case 1:
+                if(0 == hdl)
+                {
+                    printf("audio is not initialized yet.\n");
+                    continue;
+                }
+
+                if(0 != record_fd)
+                {
+                    printf("audio It's already being recorded.\n");
+                    continue;
+                }
+                record_fd = open(MBTK_AUD_DEMO_WAV, O_RDWR|O_CREAT|O_TRUNC, 0644);
+                if (record_fd <= 0)
+                    printf("file open error\n");
+
+                if(0 == MBTK_wav_pcm16Le_set(record_fd))
+                {
+                    ret = Ql_AudRecorder_StartRecord();
+                    if(0 != ret)
+                    {
+                        printf("audio record error: %d\n", ret);
+                        close(record_fd);
+                        record_fd = 0;
+                    }
+                }
+                else
+                {
+                    printf("arec set file header error\n");
+                    close(record_fd);
+                    record_fd = 0;
+                }
+                break;
+            case 2:
+                // printf("arec state : %d\n", state);
+                break;
+            case 3:
+                break;
+            case 4:
+                break;
+            case 5:
+                break;
+            case 6:
+                Ql_AudRecorder_Close();
+                if(record_fd > 0)
+                {
+                    close(record_fd);
+                    record_fd = 0;
+                }
+                break;
+            default:
+                return;
+        }
+
+        sleep(1);
+    }
+
+    printf("arec exit\n");
+    return ;
+}
+int main(void)
+{
+    char operator[10];
+    int opt;
+
+//    printf("Ql_Mp3_To_Wav()\n");
+//    mbtk_audio_mp3_to_wav("/data/demo.wav", "/data/mp3demo.mp3");
+ //   Ql_Mp3_To_Wav("/data/demo.wav", "/data/mp3demo.mp3");
+
+    while(1)
+    {
+        printf("=========audio main=========\n"
+            "\t0 exit\n"
+            "\t1 aplay\n"
+            "\t2 arec\n"
+            "\t3 set speaker Volume\n"
+            "\t4 get speaker Volume\n"
+            "\t5 set mic Volume\n"
+            "\t6 get mic Volume\n"
+            "\t7 tts\n"
+            "\t8 tone\n"
+            "operator: >> ");
+
+        fgets(operator, sizeof(operator), stdin);
+        fflush(stdin);
+        opt = atoi(operator);
+        switch (opt)
+        {
+            case 0:
+                printf("main exit\n");
+                return 0;
+            case 1:
+                aplay();
+                break;
+            case 2:
+                arec();
+                break;
+            case 3:
+                mbtk_at_rec(NULL);
+                break;
+            case 4:
+                mbtk_at_play(NULL);
+                break;
+            case 5:
+                break;
+            case 6:
+                break;
+            case 7:
+                break;
+            case 8:
+                break;
+            default:
+                break;
+        }
+
+        sleep(1);
+    }
+
+    return 0;
+}
+
+
+
+
diff --git a/mbtk/test/at.c b/mbtk/test/at.c
new file mode 100755
index 0000000..c69ba82
--- /dev/null
+++ b/mbtk/test/at.c
@@ -0,0 +1,652 @@
+#include <termios.h>
+#include <pthread.h>
+#include <sys/un.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <netinet/in.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/select.h>
+
+#include "ql/ql_uart.h"
+#include "mbtk_type.h"
+
+//#define AT_TYPE_SOCKET
+#define MBTK_LOG
+
+#ifdef MBTK_LOG
+#include "mbtk_log.h"
+#else
+#define LOGE printf
+#define LOGD printf
+#define LOGV printf
+#define LOGI printf
+#endif
+
+#define DATABITS	CS8
+#define STOPBITS	0
+#define PARITYON        0
+#define PARITY          0
+
+typedef enum {
+    AT_MODE_SOCK_1 = 0,
+    AT_MODE_SOCK_2,
+    AT_MODE_DEV_1,
+    AT_MODE_DEV_2
+} at_mode_enum;
+
+static int epoll_fd = -1;
+static struct epoll_event epoll_events[20];
+static int at_fd = -1;
+static at_mode_enum at_mode = AT_MODE_SOCK_1;
+
+static char *at_rsp_complete_tag[] = {
+        "OK",
+        "ERROR",
+        "CONNECT",
+		"+CMS ERROR:",
+		"+CME ERROR:",
+		"NO ANSWER",
+		"NO DIALTONE",
+		NULL};
+
+//#ifdef AT_TYPE_SOCKET
+#define TEMP_FAILURE_RETRY(exp) ({         \
+    typeof (exp) _rc;                      \
+    do {                                   \
+        _rc = (exp);                       \
+    } while (_rc == -1 && errno == EINTR); \
+    _rc; })
+//#endif
+
+static void at_epoll_change(int is_add,int fd)
+{
+    struct epoll_event ev;
+    memset(&ev,0x0,sizeof(struct epoll_event));
+    ev.data.fd = fd;
+    ev.events = EPOLLIN | EPOLLET;
+    if(is_add)
+    {
+        epoll_ctl(epoll_fd,EPOLL_CTL_ADD,fd,&ev);
+    }
+    else
+    {
+        epoll_ctl(epoll_fd,EPOLL_CTL_DEL,fd,&ev);
+    }
+}
+
+static int at_set_fd_noblock(int fd)
+{
+    // Set O_NONBLOCK
+    int flags = fcntl(fd, F_GETFL, 0);
+    if (flags < 0) {
+        LOGE("Get flags error:%s\n", strerror(errno));
+        return -1;
+    }
+    flags |= O_NONBLOCK;
+    if (fcntl(fd, F_SETFL, flags) < 0) {
+        LOGE("Set flags error:%s\n", strerror(errno));
+        return -1;
+    }
+
+    return 0;
+}
+
+//#ifdef AT_TYPE_SOCKET
+int openSocket(const char* sockname)
+{
+	int sock = socket(AF_UNIX, SOCK_STREAM, 0);
+	if (sock < 0) {
+		LOGE("Error create socket: %s\n", strerror(errno));
+		return -1;
+	}
+	struct sockaddr_un addr;
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+	strncpy(addr.sun_path, sockname, sizeof(addr.sun_path));
+	while (TEMP_FAILURE_RETRY(connect(sock,(const struct sockaddr*)&addr, sizeof(addr))) != 0) {
+		LOGE("Error connect to socket %s: %s, try again", sockname, strerror(errno));
+		sleep(1);
+	}
+
+#if 0
+	int sk_flags = fcntl(sock, F_GETFL, 0);
+	fcntl(sock, F_SETFL, sk_flags | O_NONBLOCK);
+#endif
+
+	return sock;
+}
+
+//#else
+
+static int at_open(char *dev)
+{
+    // Init USB PC port.
+    struct termios ser_settings;
+    int fd = -1;
+
+usb_pc_init:
+    fd = open(dev,O_RDWR);
+    if(fd <= 0)
+    {
+        if(errno == ENODEV)
+        {
+            LOGD("Wait dev[%s] ready...",dev);
+            usleep(500000);
+            goto usb_pc_init;
+        }
+
+        LOGE("Cannot open USB PC port[%s] - [errno = %d]",dev,errno);
+        return -1;
+    }
+
+    tcgetattr(fd, &ser_settings);
+    cfmakeraw(&ser_settings);
+    //ser_settings.c_lflag |= (ECHO | ECHONL);
+    //ser_settings.c_lflag &= ~ECHOCTL;
+    tcsetattr(fd, TCSANOW, &ser_settings);
+
+#if 0
+    if(at_set_fd_noblock(at_fd))
+    {
+        LOGE("at_set_fd_noblock() fail.");
+        return -1;
+    }
+
+    at_epoll_change(1, at_fd);
+#endif
+
+    return fd;
+}
+//#endif
+
+static int adb_port_open(const char *dev, unsigned int baud)
+{
+	int fd;
+
+	while((fd = open(dev, O_RDWR)) < 0)
+	{
+		printf("%s: open %s failed\n", __func__, dev);
+		sleep(1);
+	}
+
+	/* set newtio */
+	struct termios newtio;
+	memset(&newtio, 0, sizeof(newtio));
+#if 0
+	(void)fcntl(fd, F_SETFL, 0);
+	newtio.c_cflag = BAUD | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD;
+	newtio.c_iflag = IGNPAR;
+	newtio.c_oflag = 0;
+	newtio.c_lflag = 0;    /* disable ECHO, ICANON, etc... */
+
+	newtio.c_cc[VERASE]   = 0x8;      /* del */
+	newtio.c_cc[VEOF]     = 4;      /* Ctrl-d */
+	newtio.c_cc[VMIN]     = 1;      /* blocking read until 1 character arrives */
+	newtio.c_cc[VEOL]     = 0xD;      /* '\0' */
+
+	tcflush(fd, TCIFLUSH);
+	tcsetattr(fd, TCSANOW, &newtio);
+#else
+	if (tcflush(fd, TCIOFLUSH) < 0) {
+		printf("Could not flush uart port\n");
+		return -1;
+	}
+
+    newtio.c_cc[VTIME]    = 0;   /* inter-character timer unused */
+    newtio.c_cc[VMIN]	   = 1;   /* blocking read until 5 chars received */
+    newtio.c_cflag |= (CS8 | CLOCAL | CREAD);
+    newtio.c_iflag = IGNPAR;
+    newtio.c_oflag = 0;
+    newtio.c_lflag = 0;
+
+	int rate = baud;  // Default bitrate.
+	switch(rate)
+	{
+		case 300:
+			cfsetospeed(&newtio, B300);
+			cfsetispeed(&newtio, B300);
+			break;
+		case 600:
+			cfsetospeed(&newtio, B600);
+			cfsetispeed(&newtio, B600);
+			break;
+		case 1200:
+			cfsetospeed(&newtio, B1200);
+			cfsetispeed(&newtio, B1200);
+			break;
+		case 2400:
+			cfsetospeed(&newtio, B2400);
+			cfsetispeed(&newtio, B2400);
+			break;
+		case 4800:
+			cfsetospeed(&newtio, B4800);
+			cfsetispeed(&newtio, B4800);
+			break;
+		case 9600:
+			cfsetospeed(&newtio, B9600);
+			cfsetispeed(&newtio, B9600);
+			break;
+		case 19200:
+			cfsetospeed(&newtio, B19200);
+			cfsetispeed(&newtio, B19200);
+			break;
+		case 38400:
+			cfsetospeed(&newtio, B38400);
+			cfsetispeed(&newtio, B38400);
+			break;
+		case 57600:
+			cfsetospeed(&newtio, B57600);
+			cfsetispeed(&newtio, B57600);
+			break;
+		case 115200:
+			cfsetospeed(&newtio, B115200);
+			cfsetispeed(&newtio, B115200);
+			break;
+		case 230400:
+			cfsetospeed(&newtio, B230400);
+			cfsetispeed(&newtio, B230400);
+			break;
+		case 460800:
+			cfsetospeed(&newtio, B460800);
+			cfsetispeed(&newtio, B460800);
+			break;
+		case 921600:
+			cfsetospeed(&newtio, B921600);
+			cfsetispeed(&newtio, B921600);
+			break;
+		case 1500000:
+			cfsetospeed(&newtio, B1500000);
+			cfsetispeed(&newtio, B1500000);
+			break;
+		case 2000000:
+			cfsetospeed(&newtio, B2000000);
+			cfsetispeed(&newtio, B2000000);
+			break;
+		case 3000000:
+			cfsetospeed(&newtio, B3000000);
+			cfsetispeed(&newtio, B3000000);
+			break;
+		case 4000000:
+			cfsetospeed(&newtio, B4000000);
+			cfsetispeed(&newtio, B4000000);
+			break;
+		default:
+			cfsetospeed(&newtio, B115200);
+			cfsetispeed(&newtio, B115200);
+			break;
+	}
+
+	if (tcsetattr(fd, TCSANOW, &newtio) < 0) {
+		printf("Can't set port setting\n");
+		return -1;
+	}
+	/* Blocking behavior */
+	fcntl(fd, F_SETFL, 0);
+#endif
+
+    return fd;
+}
+
+
+static void signal_process(int signal_num) {
+    if(at_fd > 0) {
+        close(at_fd);
+    }
+#ifdef MBTK_LOG
+    LOGD("Exit by sig - %d\n", signal_num);
+#endif
+    exit(0);
+}
+
+static void* read_thread_run( void *arg)
+{
+    //UNUSED(arg);
+
+    char at_rsp[1024];
+    char *ptr;
+    int index;
+    int len;
+    while(at_fd > 0) {
+        memset(at_rsp, 0x0, 1024);
+        index = 0;
+        len = 0;
+        while(1) {
+            if((len = read(at_fd, at_rsp + index, 1024)) > 0) {
+                ptr = at_rsp;
+                while(*ptr == '\r' || *ptr == '\n')
+                {
+                    ptr++;
+                }
+                if(strlen(ptr) > 0 && ptr[strlen(ptr) - 1] == '\n') {
+                    printf("<%s\n", ptr);
+#ifdef MBTK_LOG
+                    LOGV("RSP:%s", ptr);
+#endif
+
+                    break;
+                } else {
+                    index += len;
+                }
+            } else {
+                LOGE("Read error:%d",errno);
+                return NULL;
+            }
+        }
+    }
+
+    LOGD("read_thread_run() exit.\n");
+    return NULL;
+}
+
+static int read_thread_start()
+{
+    pthread_t tid;
+    pthread_attr_t attr;
+    pthread_attr_init (&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+    int ret = pthread_create(&tid, &attr, read_thread_run, &attr);
+    if (ret < 0)
+    {
+        LOGE("pthread_create\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int at_complete(char *rsp)
+{
+#if 0
+    char *ptr = at_rsp_complete_tag;
+    while(ptr) {
+        LOGD("ptr = %s", ptr);
+        if(strstr(rsp, ptr)) {
+            LOGD("%s , %s", rsp, ptr);
+            return 1;
+        }
+        ptr++;
+    }
+#else
+    int i = 0;
+    while(at_rsp_complete_tag[i]) {
+        LOGD("ptr = %s", at_rsp_complete_tag[i]);
+        if(strstr(rsp, at_rsp_complete_tag[i])) {
+            LOGD("%s , %s", rsp, at_rsp_complete_tag[i]);
+            return 1;
+        }
+        i++;
+    }
+
+#endif
+    return 0;
+}
+
+static void at_rsp_read()
+{
+    char at_rsp[1024];
+    int len = 0;
+    while(1) {
+        memset(at_rsp, 0x0, 1024);
+        if((len = read(at_fd, at_rsp, 1024)) > 0) {
+            printf("%s", at_rsp);
+            if(at_complete(at_rsp)) {
+                break;
+            }
+        } else {
+            printf("Read error:%d\n",errno);
+            break;
+        }
+    }
+}
+
+static void help()
+{
+    printf("at : Enter AT mode(Socket).\n");
+    printf("at <at_cmd>: Send AT command(Socket).\n");
+    printf("at <dev>: Enter AT mode(Device).\n");
+    printf("at <dev> echo: ´®¿ÚÊý¾Ý»ØÏÔ¡£\n");
+    printf("at <dev> <at_cmd>: Send AT command(Device).\n");
+}
+
+static void sig_process(int sig)
+{
+    LOGI("I got signal %d\n", sig);
+    switch(sig)
+    {
+        case SIGINT: // Ctrl + C
+        {
+            LOGI("Exit by SIGINT.\n");
+            exit(0);
+        }
+        case SIGQUIT: // Ctrl + \ (ÀàËÆ SIGINT £¬µ«Òª²úÉúcoreÎļþ)
+        {
+            LOGI("Exit by SIGQUIT.\n");
+            exit(0);
+        }
+        case SIGTERM:// ĬÈÏkill   (ͬ SIGKILL £¬µ« SIGKILL ²»¿É²¶»ñ)
+        {
+            LOGI("Exit by SIGTERM.\n");
+            exit(0);
+        }
+        case SIGTSTP:// Ctrl + Z (ͬ SIGSTOP £¬µ« SIGSTOP ²»¿É²¶»ñ)
+        {
+            LOGI("Exit by SIGTSTP.\n");
+            exit(0);
+        }
+        case SIGSEGV: // Èç¿ÕÖ¸Õë
+        {
+            LOGI("Exit by SIGSEGV.\n");
+            exit(0);
+        }
+        default:
+        {
+            LOGI("Unknown sig:%d\n",sig);
+            break;
+        }
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    //UNUSED(argc);
+    //UNUSED(argv);
+    signal(SIGINT, sig_process);
+    signal(SIGQUIT, sig_process);
+    signal(SIGTERM, sig_process);
+    //signal(SIGTSTP, sig_process);
+    //signal(SIGSEGV, sig_process);
+
+#ifdef MBTK_LOG
+    mbtk_log_init("radio", "MBTK_AT");
+    LOGI("mbtk_at start.");
+#endif
+
+    signal(SIGKILL, signal_process);
+    signal(SIGINT, signal_process);
+    signal(SIGQUIT, signal_process);
+    signal(SIGTERM, signal_process);
+
+    char *at_cmd = NULL;
+    bool echo = FALSE;
+    if(argc == 1) {
+        at_mode = AT_MODE_SOCK_1;
+    } else if(argc == 2) {
+        if(!strncasecmp(argv[1], "at", 2)) {
+            at_mode = AT_MODE_SOCK_2;
+            at_cmd = argv[1];
+        } else if(!strncasecmp(argv[1], "/dev/", 5)) {
+            at_mode = AT_MODE_DEV_1;
+        } else {
+            help();
+            return -1;
+        }
+    } else if(argc == 3) {
+        if(!strncasecmp(argv[1], "/dev/", 5) && (!strncasecmp(argv[2], "at", 2) || !strncasecmp(argv[2], "echo", 4))) {
+            at_mode = AT_MODE_DEV_2;
+            if(!strncasecmp(argv[2], "at", 2)) {
+                at_cmd = argv[2];
+            } else {
+                echo = TRUE;
+            }
+        } else {
+            help();
+            return -1;
+        }
+    } else {
+        help();
+        return -1;
+    }
+#if 0
+#ifdef AT_TYPE_SOCKET
+    at_fd = openSocket("/tmp/atcmdmbtk");
+#else
+	at_fd = at_open(argv[1]);
+#endif
+    if(at_fd > 0) {
+#ifdef AT_TYPE_SOCKET
+        if(argc > 1) {
+            char *at_cmd = argv[1];
+#else
+	    if(argc > 2) {
+            char *at_cmd = argv[2];
+#endif
+#endif
+
+    if(at_mode == AT_MODE_SOCK_1 || at_mode == AT_MODE_SOCK_2) {
+        at_fd = openSocket("/tmp/atcmdmbtk");
+    } else {
+#if 0
+        at_fd = at_open(argv[1]);
+#else
+        if(echo) {
+            at_fd = adb_port_open(argv[1], 115200);
+        } else {
+            at_fd = at_open(argv[1]);
+        }
+#endif
+    }
+    if(at_fd > 0) {
+        if(at_cmd != NULL) {
+            char *ptr = at_cmd + strlen(at_cmd) - 1;
+            while(ptr >= at_cmd && (*ptr == '\r' || *ptr == '\n'))
+            {
+                *ptr-- = '\0';
+            }
+            // printf("AT:[%ld]%s\n", strlen(at_cmd), at_cmd);
+            if(!strncasecmp(at_cmd, "at", 2))
+            {
+                *(++ptr) = '\r';
+                *(++ptr) = '\n';
+                if(write(at_fd, at_cmd, strlen(at_cmd)) <= 0) {
+                    printf("Write error:%d\n", errno);
+                } else {
+                    // Read response.
+                    at_rsp_read();
+                }
+            } else {
+                printf("AT error!\n");
+            }
+        } else {
+            if(echo) {
+                char read_buff[1024];
+                char write_buff[1024];
+                int len;
+#if 0
+                fd_set fds;
+                int fdcount, nfds = 0;
+                while(1) {
+                    FD_SET(at_fd, &fds);
+        		    if(at_fd > nfds)
+        			    nfds = at_fd;
+
+                    fdcount = select(nfds + 1, &fds, NULL, NULL, NULL);
+        			if(fdcount < 0) /* error */
+        			{
+        				printf("select returned %d, errno %d, continue\r", fdcount, errno);
+        				sleep(1);
+        				continue;
+        			}
+
+        			if(FD_ISSET(at_fd, &fds))
+        			{
+                        FD_CLR(at_fd, &fds);
+                        memset(read_buff, 0x0, 1024);
+                        if((len = read(at_fd, read_buff, 1024)) > 0) {
+                            memset(write_buff, 0x0, 1024);
+                            printf("%s\n", read_buff);
+                            len = snprintf(write_buff, 1024, "%s\n", read_buff);
+                            write(at_fd, write_buff, len);
+                        } else {
+                            printf("Read error:%d\n",errno);
+                            return NULL;
+                        }
+                    }
+                }
+#else
+                printf("Waitting data!!!\n");
+                while(1) {
+                    memset(read_buff, 0x0, 1024);
+                    if((len = read(at_fd, read_buff, 1024)) > 0) {
+                        memset(write_buff, 0x0, 1024);
+                        printf("%s\n", read_buff);
+                        len = snprintf(write_buff, 1024, "%s\n", read_buff);
+                        write(at_fd, write_buff, len);
+                    } else {
+                        printf("Read error:%d\n",errno);
+                        return NULL;
+                    }
+                }
+#endif
+            } else {
+                setbuf(stdout, NULL);
+                read_thread_start();
+                char at_cmd[100];
+                //printf(">>");
+                while(1)
+                {
+                    memset(at_cmd, 0x0, 100);
+                    if(fgets(at_cmd, 100, stdin))
+                    {
+                        char *ptr = at_cmd + strlen(at_cmd) - 1;
+                        while(ptr >= at_cmd && (*ptr == '\r' || *ptr == '\n'))
+                        {
+                            *ptr-- = '\0';
+                        }
+                        // printf("AT:[%ld]%s\n", strlen(at_cmd), at_cmd);
+                        if(!strncasecmp(at_cmd, "at", 2))
+                        {
+                            *(++ptr) = '\r';
+                            *(++ptr) = '\n';
+                            if(write(at_fd, at_cmd, strlen(at_cmd)) <= 0) {
+                                LOGE("Write error:%d",errno);
+                                break;
+                            }
+                            printf(">%s",at_cmd);
+#ifdef MBTK_LOG
+                            LOGV("AT:%s",at_cmd);
+#endif
+                        } else if(!strcasecmp(at_cmd, "q")) {
+                            break;
+                        } else {
+                            printf("\n");
+                        }
+                    }
+                }
+            }
+        }
+
+        close(at_fd);
+
+#ifdef MBTK_LOG
+        LOGD("EXIT");
+#endif
+    }
+
+    return 0;
+}
diff --git a/mbtk/test/audio_test.c b/mbtk/test/audio_test.c
new file mode 100755
index 0000000..3391a84
--- /dev/null
+++ b/mbtk/test/audio_test.c
@@ -0,0 +1,336 @@
+#include "mbtk_type.h"
+#include <fcntl.h>
+#include <stdint.h>
+#include <limits.h>
+#include <termios.h>
+#include <stdarg.h>
+// #include "ql_at.h"
+#include "ql/ql_audio.h"
+// #include "mopen_tts.h"
+
+#define MBTK_AUD_DEMO_WAV "/data/demo.wav"
+
+static int record_fd = 0;
+
+int Ql_cb_playback(int hdl, int result)
+{
+    printf("%s: hdl=%d, result=%d\n\r", __func__, hdl, result);
+    if (result == AUD_PLAYER_FINISHED || result == AUD_PLAYER_NODATA)
+    {
+        printf("%s: play finished\n\r", __func__);
+    }
+    return 0;
+}
+
+void record_cb_func(int cb_result, char* databuf, unsigned int len)
+{
+    int rc;
+
+    if(NULL != databuf && len > 0 && record_fd > 0)
+    {
+        //for debug:save into file
+        rc = write(record_fd, databuf, len);
+        if (rc < 0) {
+            printf("%s: error writing to file!\n", __FUNCTION__);
+        } else if (rc < len) {
+            printf("%s: wrote less the buffer size!\n", __FUNCTION__);
+        }
+    }
+}
+int MBTK_wav_pcm16Le_check(int fd)
+{
+    struct wav_header hdr;
+
+    if (fd <= 0)
+        return -1;
+
+    if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr))
+    {
+        printf("\n%s: cannot read header\n", __FUNCTION__);
+        return -1;
+    }
+
+    if ((hdr.riff_id != ID_RIFF)
+            || (hdr.riff_fmt != ID_WAVE)
+            || (hdr.fmt_id != ID_FMT))
+    {
+        printf("\n%s: is not a riff/wave file\n", __FUNCTION__);
+        return -1;
+    }
+
+    if ((hdr.audio_format != FORMAT_PCM) || (hdr.fmt_sz != 16)) {
+        printf("\n%s: is not pcm format\n", __FUNCTION__);
+        return -1;
+    }
+
+    if (hdr.bits_per_sample != 16) {
+        printf("\n%s: is not 16bit per sample\n", __FUNCTION__);
+        return -1;
+    }
+
+    return 0;
+}
+
+int MBTK_wav_pcm16Le_set(int fd)
+{
+    struct wav_header hdr;
+
+    if (fd <= 0)
+        return -1;
+
+    memset(&hdr, 0, sizeof(struct wav_header));
+
+    hdr.riff_id = ID_RIFF;
+    hdr.riff_fmt = ID_WAVE;
+    hdr.fmt_id = ID_FMT;
+    hdr.fmt_sz = 16;
+    hdr.audio_format = FORMAT_PCM;
+    hdr.num_channels = 1;
+    hdr.sample_rate = 8000;
+    hdr.bits_per_sample = 16;
+    hdr.byte_rate = (8000 * 1 * hdr.bits_per_sample) / 8;
+    hdr.block_align = (hdr.bits_per_sample * 1) / 8;
+    hdr.data_id = ID_DATA;
+    hdr.data_sz = 0;
+
+    hdr.riff_sz = hdr.data_sz + 44 - 8;
+    if (write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
+        return -1;
+    }
+
+    return 0;
+}
+void aplay(void)
+{
+    char operator[10];
+    char databuf[1024];
+    int opt = 0;
+    int fd = 0;
+    int size = 0;
+    int state;
+    int play_hdl = 0;
+
+    while(1)
+    {
+        printf("=========aplay========\n"
+            "\t 0 Open PCM\n"
+            "\t 1 Play Stream\n"
+            "\t 2 Play file\n"
+            "\t 3 Close\n"
+            "\t others exit\n\n"
+            "operator >> ");
+
+        fflush(stdin);
+        fgets(operator, sizeof(operator), stdin);
+        opt = atoi(operator);
+        switch (opt)
+        {
+            case 0:
+                play_hdl = Ql_AudPlayer_Open(NULL, Ql_cb_playback);
+                if(0 == play_hdl)
+                    printf("Ql_AudPlayer_Open fail\n");
+                break;
+            case 1:
+               if(0 == play_hdl)
+                    continue;
+
+                fd = open(MBTK_AUD_DEMO_WAV, O_RDWR);
+                if (fd <= 0)
+                    continue;
+
+                if(0 == MBTK_wav_pcm16Le_check(fd))
+                {
+                    memset(databuf, 0, sizeof(databuf));
+                    while(0 < (size = read(fd, databuf, sizeof(databuf))))
+                    {
+                        if(-1 == Ql_AudPlayer_Play(play_hdl, databuf, size))
+                            break;
+                    }
+                    printf("aplay Stream end \n");
+                }
+
+                close(fd);
+                break;
+            case 2:
+                if(0 == play_hdl)
+                    continue;
+
+                fd = open(MBTK_AUD_DEMO_WAV, O_RDWR);
+                if (fd <= 0)
+                    continue;
+
+                if(0 == MBTK_wav_pcm16Le_check(fd))
+                {
+                    Ql_AudPlayer_PlayFrmFile(play_hdl, fd, 0);
+                }
+                else
+                {
+                    printf("aplay file type error\n");
+                }
+                close(fd);
+                break;
+            case 3:
+                if(0 == play_hdl)
+                    continue;
+                Ql_AudPlayer_Close(play_hdl);
+                break;
+            case 4:
+            //    aplay_thread(MBTK_AUD_DEMO_WAV);
+                Ql_Mp3_To_Play("/data/mp3demo.mp3", play_hdl, 0);
+                break;
+            default:
+                return;
+        }
+
+        sleep(1);
+    }
+
+    printf("aplay exit\n");
+    return ;
+}
+void arec(void)
+{
+    int ret;
+    char operator[10];
+    int opt;
+    int hdl = 0;
+
+    while(1)
+    {
+        printf("=======arec======\n"
+            "\t 0 Open PCM\n"
+            "\t 1 Start Record\n"
+            "\t 2 Get state\n"
+            "\t 3 Pause\n"
+            "\t 4 Resume\n"
+            "\t 5 Stop\n"
+            "\t 6 Close\n"
+            "\t others exit\n\n"
+            "operator >> ");
+
+        fflush(stdin);
+        fgets(operator, sizeof(operator), stdin);
+        opt = atoi(operator);
+        switch (opt)
+        {
+            case 0:
+                hdl = Ql_AudRecorder_Open(NULL, record_cb_func);
+                if (hdl == 0)
+                    return ;
+                break;
+            case 1:
+                if(0 == hdl)
+                {
+                    printf("audio is not initialized yet.\n");
+                    continue;
+                }
+
+                if(0 != record_fd)
+                {
+                    printf("audio It's already being recorded.\n");
+                    continue;
+                }
+                record_fd = open(MBTK_AUD_DEMO_WAV, O_RDWR|O_CREAT|O_TRUNC, 0644);
+                if (record_fd <= 0)
+                    printf("file open error\n");
+
+                if(0 == MBTK_wav_pcm16Le_set(record_fd))
+                {
+                    ret = Ql_AudRecorder_StartRecord();
+                    if(0 != ret)
+                    {
+                        printf("audio record error: %d\n", ret);
+                        close(record_fd);
+                        record_fd = 0;
+                    }
+                }
+                else
+                {
+                    printf("arec set file header error\n");
+                    close(record_fd);
+                    record_fd = 0;
+                }
+                break;
+            case 2:
+                // printf("arec state : %d\n", state);
+                break;
+            case 3:
+                break;
+            case 4:
+                break;
+            case 5:
+                break;
+            case 6:
+                Ql_AudRecorder_Close();
+                if(record_fd > 0)
+                {
+                    close(record_fd);
+                    record_fd = 0;
+                }
+                break;
+            default:
+                return;
+        }
+
+        sleep(1);
+    }
+
+    printf("arec exit\n");
+    return ;
+}
+int main(void)
+{
+    char operator[10];
+    int opt;
+
+    while(1)
+    {
+        printf("=========audio main=========\n"
+            "\t0 exit\n"
+            "\t1 aplay\n"
+            "\t2 arec\n"
+            "\t3 set speaker Volume\n"
+            "\t4 get speaker Volume\n"
+            "\t5 set mic Volume\n"
+            "\t6 get mic Volume\n"
+            "\t7 tts\n"
+            "\t8 tone\n"
+            "operator: >> ");
+
+        fgets(operator, sizeof(operator), stdin);
+        fflush(stdin);
+        opt = atoi(operator);
+        switch (opt)
+        {
+            case 0:
+                printf("main exit\n");
+                return 0;
+            case 1:
+                aplay();
+                break;
+            case 2:
+                arec();
+                break;
+            case 3:
+                mbtk_at_rec(NULL);
+                break;
+            case 4:
+                mbtk_at_play(NULL);
+                break;
+            case 5:
+                break;
+            case 6:
+                break;
+            case 7:
+                break;
+            case 8:
+                break;
+            default:
+                break;
+        }
+
+        sleep(1);
+    }
+
+    return 0;
+}
diff --git a/mbtk/test/framebuffer_demo.c b/mbtk/test/framebuffer_demo.c
new file mode 100755
index 0000000..281e9ab
--- /dev/null
+++ b/mbtk/test/framebuffer_demo.c
@@ -0,0 +1,283 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <math.h>
+
+/**< \brief 根据实际情况修改,此处为unsigned short是565的屏,根据程序打印出的
+    bits_per_pixel的值可以判断出输出格式是565还是888 */
+// typedef unsigned int color_t;
+typedef unsigned short color_t;
+/**< \brief 定义每个像素点对应的位数,如果是565的屏则为16,如果是888的屏则为32 */
+// #define BITS_PER_PIXEL    32
+#define BITS_PER_PIXEL    16
+
+static struct fb_var_screeninfo __g_vinfo;    /* 显示信息 */
+color_t *__gp_frame;                    /* 虚拟屏幕首地址 */
+
+#pragma pack(2)
+typedef unsigned short WORD;
+typedef unsigned char BYTE;
+typedef unsigned int DWORD;
+typedef int LONG;
+
+typedef struct tagBITMAPFILEHEADER
+{
+    WORD bfType;        // 位图文件的类型,必须为BM
+    DWORD bfSize;       // 位图文件的大小,以字节为单位
+    WORD bfReserved1;   // 位图文件保留字,必须为0
+    WORD bfReserved2;   // 位图文件保留字,必须为0
+    DWORD bfOffBits;    // 位图数据的起始位置,以相对于位图
+                        // 文件头的偏移量表示,以字节为单位
+} BITMAPFILEHEADER;
+
+typedef struct tagBITMAPINFOHEADER
+{
+    DWORD biSize; // 本结构所占用字节数
+    LONG biWidth; // 位图的宽度,以像素为单位
+    LONG biHeight; // 位图的高度,以像素为单位
+    WORD biPlanes; // 目标设备的级别,必须为1
+    WORD biBitCount;// 每个像素所需的位数,必须是1(双色),
+         // 4(16色),8(256色)或24(真彩色)之一
+    DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),
+        // 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
+    DWORD biSizeImage; // 位图的大小,以字节为单位
+    LONG biXPelsPerMeter; // 位图水平分辨率,每米像素数
+    LONG biYPelsPerMeter; // 位图垂直分辨率,每米像素数
+    DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数
+    DWORD biClrImportant;// 位图显示过程中重要的颜色数
+} BITMAPINFOHEADER;
+#pragma pack(0)
+
+typedef WORD (*bmp_xx_to_16)(char *);
+
+//画点
+void draw_point(int x, int y, color_t color)
+{
+    color_t *p = __gp_frame;
+
+    p += __g_vinfo.xres * y + x;
+    *p = color;
+}
+
+WORD bmp_24_to_16(char *input)
+{
+    /* 如果使用的bmp图片的颜色深度是24位,适用于888的屏,但如果一定要在565的屏
+        上显示,则取红色的高5位,绿色的高6位和蓝色的高5位,拼成16位的数据
+        进行显示。这样做并不是最好的办法,更好的方法是将需要丢失的部分数
+        据进行进位或舍去。
+        */
+    WORD c;
+    char b, g, r;
+    r = *input >> 3;
+    input++;
+    g = *input >> 2;
+    input++;
+    b = *input >> 3;
+
+    c = (b << 11) | (g << 5) | r;
+
+    return c;
+}
+
+WORD bmp_16_to_16(char *input)
+{
+    WORD c;
+
+    c = *input;
+    input++;
+    c = (c << 8) | *input;
+    c = ((c >> 8) & 0x00ff) | ((c & 0x00ff) << 8);
+
+    return c;
+}
+
+//功能:在指定坐标显示指定BPM24位图
+//参数:(x , y)坐标
+//        pic:24位BMP图像
+void Show_BMP(int x , int y , const char *pic)
+{
+    int fd = 0;
+    color_t c;
+    BITMAPFILEHEADER filehead;
+    BITMAPINFOHEADER infohead;
+    int i,j;
+    unsigned char pixel_byte;
+    unsigned char *p = NULL , *p_data = NULL;
+    int width_error = 0;
+    short* t_data = NULL;
+    bmp_xx_to_16 transform_func = NULL;
+    int index = 0;
+
+    printf("%s: %s\n", __FUNCTION__, pic);
+    fd = open(pic , O_RDONLY);
+    if(fd == -1) {
+        printf("fail to open\n");
+        return;
+    }
+
+    read(fd , &filehead , sizeof(filehead));
+    read(fd , &infohead , sizeof(infohead));
+    printf("bfType: 0x%x, bfSize: %d, bfOffBits: 0x%x\n", filehead.bfType, filehead.bfSize, filehead.bfOffBits);
+
+    printf("biSize: %d, biWidth: %d, biHeight: %d\n", infohead.biSize, infohead.biWidth, infohead.biHeight);
+    printf("biPlanes: %d, biBitCount: %d, biCompression: %d\n", infohead.biPlanes, infohead.biBitCount, infohead.biCompression);
+    printf("biSizeImage: %d, biXPelsPerMeter: %d, biYPelsPerMeter: %d\n", infohead.biSizeImage, infohead.biXPelsPerMeter, infohead.biYPelsPerMeter);
+
+    width_error = (4 - infohead.biWidth * 3 % 4) % 4;
+    pixel_byte = infohead.biBitCount / 8;
+
+    if (16 == infohead.biBitCount) {
+        transform_func = bmp_16_to_16;
+    } else if (24 == infohead.biBitCount) {
+        transform_func = bmp_24_to_16;
+    } else {
+        printf("Not Suppurt %d bmp\n", infohead.biBitCount);
+        close(fd);
+        return;
+    }
+
+    t_data = malloc(__g_vinfo.xres_virtual * __g_vinfo.yres_virtual * __g_vinfo.bits_per_pixel / 8);
+
+    if(t_data == NULL) {
+        perror("fail to malloc");
+    }
+
+    p_data = malloc(infohead.biSizeImage);
+    if(p_data == NULL) {
+        perror("fail to malloc");
+    }
+
+    printf("biSizeImage:%d, width_error: %d\n", infohead.biSizeImage, width_error);
+    read(fd , p_data , infohead.biSizeImage);
+    p = p_data;
+
+    int ret;
+    char data[24] = {0};
+    int debug_fd = open("/data/debug_fb", O_RDWR|O_CREAT|O_TRUNC, 0644);
+    if (debug_fd < 0) {
+        printf("debug_fb open error\n");
+        return;
+    }
+    printf("height:%d, width:%d\n", infohead.biHeight, infohead.biWidth);
+    for(j = infohead.biHeight - 1; j >= 0; j--) {
+        for(i = 0; i < infohead.biWidth; i++) {
+            c = transform_func(p);
+            // c = *p;
+            p += pixel_byte;
+            // c = ((c >> 8) & 0x00ff) | ((c & 0x00ff) << 8);
+            t_data[__g_vinfo.xres * (y + j) + (x + i)] = c;
+            // draw_point(x + i, y + j, c);
+            index++;
+
+            sprintf(data, "index:%d, i:%d, j:%d\n", index, i, j);
+            ret = write(debug_fd, data, strlen(data));
+            if (ret < 0) {
+                printf("%s write error\n", __FUNCTION__);
+            }
+        }
+        p += width_error;
+    }
+    close(debug_fd);
+    printf("%s: %d\n", __FUNCTION__, infohead.biHeight * infohead.biWidth * __g_vinfo.bits_per_pixel / 8);
+    memcpy(__gp_frame, t_data,
+           infohead.biHeight * infohead.biWidth * __g_vinfo.bits_per_pixel / 8);
+    printf("%s: %d\n", __FUNCTION__, index);
+    free(p_data);
+    free(t_data);
+    close(fd);
+}
+
+/**
+ * \brief 填充整屏
+ */
+void full_screen (color_t color)
+{
+    int i;
+    color_t *p = __gp_frame;
+
+    for (i = 0; i < __g_vinfo.xres_virtual * __g_vinfo.yres_virtual; i++) {
+        *p++ = color;
+    }
+}
+
+/**
+ * \brief 清屏
+ */
+void clear()
+{
+    full_screen(0);
+}
+
+/* framebuffer初始化 */
+int framebuffer_init (void)
+{
+    int fd = 0;
+
+    fd = open("/dev/fb0", O_RDWR);
+    if (fd == -1) {
+        perror("fail to open /dev/fb0\n");
+        return -1;
+    }
+
+    /* 获取显示信息 */
+    ioctl(fd, FBIOGET_VSCREENINFO, &__g_vinfo);                     /* 获取显示信息 */
+    printf("bits_per_pixel = %d\n", __g_vinfo.bits_per_pixel);      /* 得到一个像素点对应的位数 */
+    printf("xres_virtual = %d\n", __g_vinfo.xres_virtual);            /* 打印虚拟屏幕列数 */
+    printf("yres_virtual = %d\n", __g_vinfo.yres_virtual);            /* 打印虚拟屏幕行数 */
+    printf("xres = %d\n", __g_vinfo.xres);                            /* 打印屏幕列数 */
+    printf("yres = %d\n", __g_vinfo.yres);                            /* 打印屏幕行数 */
+
+    int len = __g_vinfo.xres_virtual * __g_vinfo.yres_virtual * __g_vinfo.bits_per_pixel / 8;    /* 映射区大小 */
+
+    printf("fb size = %d\n", len);
+    __gp_frame = mmap(NULL,                             /* 映射区的开始地址,为NULL表示由系统决定映射区的起始地址 */
+                      len,
+                      PROT_WRITE | PROT_READ,            /* 内存保护标志(可读可写) */
+                      MAP_SHARED,                        /* 映射对象类型(与其他进程共享) */
+                      fd,                                /* 有效的文件描述符 */
+                      0);                                /* 被映射内容的偏移量 */
+    if (__gp_frame == NULL) {
+        perror("fail to mmap\n");
+        return -1;
+    }
+
+    return fd;
+}
+
+
+int main(int argc, const char *argv[])
+{
+    int fd;
+
+    if (argc < 2) {
+        printf("%s \" img \"", argv[0]);
+        exit(1);
+    }
+
+    fd = framebuffer_init();
+    if (fd < 0) {
+        printf("framebuffer_init error\n");
+        return 0;
+    }
+
+    printf("framebuffer_init Success.\n");
+    /* 清屏 */
+    clear();
+
+    printf("clear Success.\n");
+
+    // full_screen(0xF800);  // 显示红色
+
+    Show_BMP(0 , 0 , argv[1]);
+
+    close(fd);
+
+    return 0;
+}
diff --git a/mbtk/test/gnss_basic_demo.c b/mbtk/test/gnss_basic_demo.c
new file mode 100755
index 0000000..3d5b485
--- /dev/null
+++ b/mbtk/test/gnss_basic_demo.c
@@ -0,0 +1,514 @@
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <pthread.h>
+#include <errno.h>
+#include <time.h>
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+
+#define MBTK_GNSS_DEV  "/dev/ttyS2"
+
+#define MBTK_UART_RECV_BUFFER_SIZE 1024
+#define MBTK_UART_SEND_BUFFER_MAX 128
+#define GPS_DEV "/sys/devices/soc.0/d4000000.apb/mbtk-dev-op/gps_power"
+
+static int dev_fd = 0;
+static int inited = 0;
+static pthread_t  uart_pthread;
+
+static int mopen_open_gps(int state)
+{
+    int fd, ret;
+    char s[4] = "on";
+    fd = open(GPS_DEV, O_RDWR | O_TRUNC, 0644);
+    if (fd < 0) {
+        printf("[%s]  file [%s] open error\n", __FUNCTION__, GPS_DEV);
+        return -1;
+    }
+    if (0 == state) {
+        memcpy(s, "off", 3);
+    }
+    ret = write(fd, s, 4);
+    if (ret < 0) {
+        printf("%s: error writing to file!\n", __FUNCTION__);
+        close(fd);
+        return -2;
+    }
+
+    close(fd);
+    return 0;
+}
+
+void mopen_gnss_NonBlock(int fd, int cmd)
+{
+    int flags;
+
+    flags = fcntl(fd, F_GETFL, 0);
+    if (cmd) {
+        flags |= O_NONBLOCK;
+    } else {
+        flags &= ~O_NONBLOCK;
+    }
+
+    fcntl(fd, F_SETFL, flags);
+}
+
+int set_baudrate(int fd, int baudrate)
+{
+    struct termios options, oldtio;
+
+    if (fcntl(fd, F_SETFL, 0) < 0) {
+        printf("fcntl failed!\n");
+        return -1;
+    }
+
+    if (tcgetattr(fd, &oldtio) != 0) {
+        printf("setup serial error!\n");
+        return -1;
+    }
+
+    /* Get the current options for the port... */
+    tcgetattr(fd, &options);
+
+    /* Set the baud rates to baudrate... */
+    cfsetispeed(&options, baudrate);
+    cfsetospeed(&options, baudrate);
+    tcsetattr(fd, TCSANOW, &options);
+
+    if (0 != tcgetattr(fd, &options)) {
+        printf("get options error!\n");
+        return -1;
+    }
+
+    /*
+     * 8bit Data,no partity,1 stop bit...
+     */
+    options.c_cflag &= ~PARENB;//无奇偶校验
+    options.c_cflag &= ~CSTOPB;//停止位,1位
+    options.c_cflag &= ~CSIZE; //数据位的位掩码
+    options.c_cflag |= CS8;    //数据位,8位
+
+    cfmakeraw(&options);
+
+    /*
+     * Set the new options for the port...
+     */
+    if (tcsetattr(fd, TCSANOW, &options) != 0) {
+        printf("setup serial error!\n");
+        return -1 ;
+    }
+
+    return 0 ;
+}
+
+int mopen_gnss_open(char* dev, int baudrate)
+{
+    int ret;
+    int fd = 0;
+
+    fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);
+    if (fd < 0) {
+        return -1;
+    }
+    printf("curent dev: %s, fd: %d \n", dev, fd);
+
+    if (baudrate) {
+        printf("set baudrate: %d \n", baudrate);
+        ret = set_baudrate(fd, baudrate);
+        if (-1 == ret) {
+            close(fd);
+            return -1;
+        }
+    } else {
+        set_baudrate(fd, B9600);
+    }
+
+    return fd;
+}
+
+static int mopen_gnss_read(int fd, char* buf, unsigned int buf_len)
+{
+    buf_len = (buf_len > MBTK_UART_RECV_BUFFER_SIZE ? MBTK_UART_RECV_BUFFER_SIZE : buf_len);
+    return read(fd, buf, buf_len);
+}
+
+int mopen_gnss_write(int fd, const char* buf, unsigned int buf_len)
+{
+    size_t size;
+    size_t size_to_wr;
+    ssize_t size_written;
+    if (MBTK_UART_SEND_BUFFER_MAX < buf_len) {
+        return -1;
+    }
+    for (size = 0; size < buf_len;) {
+        size_to_wr = buf_len - size;
+        if (size_to_wr > MBTK_UART_SEND_BUFFER_MAX) {
+            size_to_wr = MBTK_UART_SEND_BUFFER_MAX;
+        }
+
+        size_written = write(fd, &buf[size], size_to_wr);
+        if (size_written == -1) {
+            return -1;
+        }
+        printf("send cmd: %s", &buf[size]);
+        size += size_written;
+        if (size_written != size_to_wr) {
+            return size;
+        }
+    }
+    return size;
+}
+
+int mopen_gnss_close(int fd)
+{
+    return close(fd);
+}
+
+int mopen_send_cmd(int baud, char *cmd)
+{
+    int fd, __baud;
+    char buf[24] = {0};
+
+    printf("set baud: %d\n", baud);
+    if (115200 == baud)
+        __baud = B115200;
+    else
+        __baud = B9600;
+
+    fd = mopen_gnss_open(MBTK_GNSS_DEV, __baud);
+    if (fd < 0) {
+        printf("Open %s error!!\r\n", MBTK_GNSS_DEV);
+        return -1;
+    }
+
+    sprintf(buf, "$%s\r\n", cmd);
+    mopen_gnss_write(fd, buf, strlen(buf));
+    close(fd);
+
+    return 0;
+}
+
+static void gnss_uart_pthread(void* hdl)
+{
+    int ret = 0;
+    char buf[MBTK_UART_RECV_BUFFER_SIZE] = {0};
+
+    pthread_detach(pthread_self());
+
+    memset(buf, 0, sizeof(buf));
+    while (inited) {
+        ret = mopen_gnss_read(dev_fd, buf, MBTK_UART_RECV_BUFFER_SIZE);
+        if (ret > 0) {
+            printf("read: [%d] %s\n", ret, buf);
+            memset(buf, 0, sizeof(buf));
+        } else {
+            printf("read error\n");
+        }
+        usleep(100000);
+    }
+
+    pthread_exit(NULL);
+}
+
+int mopen_gnss_send_cmd(const char* cmd, int cmd_len)
+{
+    return  mopen_gnss_write(dev_fd, cmd, cmd_len);
+}
+
+/**
+ *  \brief mopen_gnss_dev_reset
+ *
+ *  Detailed description
+ *
+ *  \param
+ *         type: 0 软件复位
+ *               1 芯片级复位(看门狗)
+ *               2 板级复位
+ *               3 接收机停止
+ *         mode :
+ *         0 : 热启动
+ *         1 : 温启动
+ *         2 : 冷启动
+ *  \return return type
+ */
+int mopen_gnss_dev_reset(int type, int mode)
+{
+    int ret;
+    // h00 热启动
+    // h01 温启动
+    // h85 冷启动
+    char send_buf[36] = {0};
+
+    if (0 == mode || 1 == mode) {
+        snprintf(send_buf, sizeof(send_buf), "$RESET,%d,h0%d\r\n", type, mode);
+    } else if (2 == mode) {
+        snprintf(send_buf, sizeof(send_buf), "$RESET,%d,h85\r\n", type);
+    } else if (3 == mode) {
+        snprintf(send_buf, sizeof(send_buf), "$RESET,%d,hFF\r\n", type);
+    } else {
+        printf("%s reset mode invalid.\n", __func__);
+        return -2;
+    }
+    printf("%s : %s\n", __FUNCTION__, send_buf);
+    ret = mopen_gnss_send_cmd(send_buf, strlen(send_buf));
+    if (ret < 0) {
+        printf("%s %d FAIL.	ret:%d\n", __FUNCTION__, __LINE__, ret);
+        return -1;
+    }
+    // set_baudrate(handle->dev_fd, B9600);
+
+    return 0;
+}
+
+int mopen_gnss_get_device_info(void)
+{
+    int ret;
+    char* send_buf = "$PDTINFO\r\n";
+
+    ret = mopen_gnss_send_cmd(send_buf, strlen(send_buf));
+    if (ret < 0) {
+        printf("mopen_gnss_client_init FAIL.	ret:%d\n", ret);
+        return -1;
+    }
+
+    return 0;
+}
+/**
+ * @brief      mopen_gnss_set_system_config
+ *
+ * @details    设置卫星系统配置
+ *
+ * @param      mode
+ *             0 -> H01(1) –GPS L1+SBAS+QZSS
+ *             1 -> H10 – BDS B1
+ *             2 -> H101 2 – GPS+GLONASS+GALILEO+SBAS+QZSS
+ *             3 -> H11 3 – GPS+BDS+GALILEO+SBAS+QZSS
+ * @return     return type
+ */
+int mopen_gnss_set_system_config(int mode)
+{
+    int ret;
+    char send_buf[20] = "$CFGSYS,H10\r\n";
+    char* str_mode[4] = {"H01", "H10", "H101", "H11"};
+
+    if (mode > 3) {
+        printf("%s param invalid.\n", __func__);
+        return -2;
+    }
+    snprintf(send_buf, sizeof(send_buf), "$CFGSYS,%s\r\n", str_mode[mode]);
+    ret = mopen_gnss_send_cmd(send_buf, strlen(send_buf));
+    if (ret < 0) {
+        printf("%s FAIL. ret:%d\n", __FUNCTION__, ret);
+        return -3;
+    }
+
+    return 0;
+}
+
+/**
+* @brief 使用popen调用终端并获取执行结果
+*
+* @param[in] cmd 命令内容
+* @param[out] result 保存结果的地址
+* @return 0或1 执行状态,成功或失败
+*/
+int exec_cmd(const char* cmd, char* result)
+{
+    FILE* pipe = popen(cmd, "r");
+    if (!pipe) {
+        return -1;
+    }
+
+    char buffer[256] = {0};
+    while (!feof(pipe)) {
+        if (fgets(buffer, 256, pipe)) {
+            strstr(buffer, "GA");
+            printf("%s", buffer);
+            memset(buffer, 0, sizeof(buffer));
+        }
+    }
+    pclose(pipe);
+    return 0;
+}
+
+/*
+  sync : 1
+ */
+int mopen_gnss_firmware_update(void)
+{
+    const char* cmd = "mbtk_gnss_update -d /dev/ttyS2 \
+                       -l /etc/mbtk/bootloader_r3.0.0_build6773_uartboot_115200.pkg \
+                       -f /etc/mbtk/UC6228CI-R3.4.0.0Build7258_mfg.pkg";
+
+    printf("Mopen Gnss Firmware Update -> \n");
+    int ret = exec_cmd(cmd, NULL);
+    if (0 == ret) {
+        printf("Gnss update result: %x\n", ret);
+    }
+
+    printf("%s %d: %d.\n", __FUNCTION__, __LINE__, ret);
+    return ret;
+}
+
+/**
+ * @brief      mopen_gnss_get_uart
+ *
+ * @details    get uart config info.
+ *             $CFGPRT,1,h0,9600,129,3*57
+ *
+ * @param      param
+ *
+ * @return     return type
+ */
+int mopen_gnss_get_uart(void)
+{
+    int ret;
+    char* send_buf = "$CFGPRT,1\r\n";
+    // char *send_buf = "$CFGPRT,2\r\n";
+
+    ret = mopen_gnss_send_cmd(send_buf, strlen(send_buf));
+    if (ret < 0) {
+        printf("mopen_gnss_client_init FAIL.	ret:%d\n", ret);
+        return -1;
+    }
+    return 0;
+}
+int mopen_gnss_client_init(int baudrate)
+{
+    int ret;
+
+    ret = mopen_open_gps(1);
+    if (ret) {
+        printf("GNSS open init error\n");
+        return -4;
+    }
+    sleep(1);
+
+    dev_fd = mopen_gnss_open(MBTK_GNSS_DEV, baudrate);
+
+    pthread_create(&uart_pthread, NULL, (void*)gnss_uart_pthread, NULL);
+    inited = 1;
+
+    return ret;
+}
+
+static int _kill_pthread(pthread_t pid, int kill)
+{
+    int ret;
+
+    if (kill) {
+        ret = pthread_cancel(pid);
+        pthread_join(pid, NULL);
+    }
+    do {
+        ret = pthread_kill(pid, 0);
+        if (ret == ESRCH) {
+            printf("The specified thread does not exist or has terminated\n");
+        } else if (ret == EINVAL) {
+            printf("Useless signal\n");
+        } else {
+            printf("The thread exists\n");
+        }
+        usleep(100000);
+    } while (0 == ret);
+
+    return 0;
+}
+
+int mopen_gnss_client_deinit(void)
+{
+    int ret;
+
+    mopen_gnss_close(dev_fd);
+    ret = mopen_open_gps(0);
+    if (ret) {
+        printf("GNSS close init error\n");
+        return -1;
+    }
+    inited = 0;
+    printf("kill thread uart.\n");
+    _kill_pthread(uart_pthread, 1);
+
+    return 0;
+}
+
+void user_help(void)
+{
+    printf("=========gnss main=========\n"
+           "\t0 exit\n"
+           "\t1 gnss init\n"
+           "\t2 gnss deinit\n"
+           "\t3 gnss reset\n"
+           "\t4 gnss update Firmware\n"
+           "\t5 gnss System config\n"
+           "\t6 gnss uart\n"
+           "\t7 gnss set uart 115200\n"
+           "please input operator: >> ");
+}
+
+int main(int argc, char* argv[])
+{
+    int ret;
+    int opt;
+
+    if (argc > 1) {
+        printf("%s, %s\n", argv[1], argv[2]);
+        opt = atoi(argv[1]);
+        printf("%s, %s\n", argv[1], argv[2]);
+        mopen_send_cmd(opt, argv[2]);
+        return 0;
+    }
+    while (1) {
+        user_help();
+        scanf("%d", &opt);
+        switch (opt) {
+        case 0:
+            printf("main exit\n");
+            return 0;
+        case 1:
+            ret = mopen_gnss_client_init(0);
+            if (ret < 0) {
+                printf("lynq_gnss_init FAIL.	ret:%d\n", ret);
+                return -1;
+            }
+            opt = 0;
+            break;
+        case 2: {
+            mopen_gnss_client_deinit();
+            break;
+        }
+        case 3: {
+            mopen_gnss_dev_reset(0, 0);
+            break;
+        }
+        case 4: {
+            mopen_gnss_firmware_update();
+            break;
+        }
+        case 5: {
+            mopen_gnss_set_system_config(2);
+            break;
+        }
+        case 6: {
+            mopen_gnss_get_device_info();
+            sleep(1);
+            mopen_gnss_get_uart();
+
+            break;
+        }
+        case 7: {
+            ret = mopen_gnss_client_init(115200);
+            break;
+        }
+        default:
+            break;
+        }
+    }
+    return 0;
+}
diff --git a/mbtk/test/gnss_update_demo.c b/mbtk/test/gnss_update_demo.c
new file mode 100755
index 0000000..d797f04
--- /dev/null
+++ b/mbtk/test/gnss_update_demo.c
@@ -0,0 +1,1283 @@
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/times.h>
+#include <sys/types.h>
+#include <termios.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <sched.h>
+#include <limits.h>
+#include <linux/serial.h>
+
+#define RTM_FILE_NAME "rtm.bin"
+
+#define PARA_ERR                -1
+#define FILE_CHECK_ERR          -2
+#define ENTER_UPDATE_MODE_ERR   -3
+#define UPDATE_ERR              -4
+#define UART_DEV_ERR            -5
+
+#define XMODEM_SOH 0x01
+#define XMODEM_STX 0x02
+#define XMODEM_EOT 0x04
+#define XMODEM_ACK 0x06
+#define XMODEM_NAK 0x15
+#define XMODEM_CAN 0x18
+#define XMODEM_CRC_CHR	'C'
+#define XMODEM_CRC_SIZE 2		/* Crc_High Byte + Crc_Low Byte */
+#define XMODEM_FRAME_ID_SIZE 2 		/* Frame_Id + 255-Frame_Id */
+#define XMODEM_DATA_SIZE_SOH 128  	/* for Xmodem protocol */
+#define XMODEM_DATA_SIZE_STX 1024 	/* for 1K xmodem protocol */
+#define USE_1K_XMODEM 1  		/* 1 for use 1k_xmodem 0 for xmodem */
+#define	TIMEOUT_USEC	0
+#define	TIMEOUT_SEC		10
+
+#if (USE_1K_XMODEM)
+#define XMODEM_DATA_SIZE 	XMODEM_DATA_SIZE_STX
+#define XMODEM_HEAD		XMODEM_STX
+#else
+#define XMODEM_DATA_SIZE 	XMODEM_DATA_SIZE_SOH
+#define XMODEM_HEAD 		XMODEM_SOH
+#endif
+
+
+/******************************************************************************
+ * 时间处理相关的宏
+ *****************************************************************************/
+// 时间超时标志
+int timeout_sign = 1;
+// 获取当前时间
+#define GET_TIME()  { gettimeofday(&time_m, NULL); \
+	time_m.tv_sec += TIMEOUT_SEC;\
+}
+// 设置从循环中退出的时间
+#define SET_TIME_OUT(x)  { gettimeofday(&time_m, NULL); \
+	time_m.tv_sec += x;\
+}
+// 检测时间是否超时,超时则退出当前函数
+#define CHK_TIME()  { gettimeofday(&time_n, NULL); \
+	if(time_n.tv_sec > time_m.tv_sec) { \
+		printf("\ntimeout!!!\n\n");\
+		close(fd); \
+		return ret; \
+	} \
+}
+// 检测时间是否超时,超时则退出当前循环
+#define CHK_TIME_BREAK()  { gettimeofday(&time_n, NULL); \
+	if(time_n.tv_sec > time_m.tv_sec) { \
+		timeout_sign = 1; 	\
+		printf("\ntimeout!!!\n\n");\
+		break; \
+	} \
+}
+// 检测延时是否到达,到达则退出当前循环
+#define DELAY_TIME_BREAK()  { gettimeofday(&time_n, NULL); \
+	if(time_n.tv_sec > time_m.tv_sec) { \
+		timeout_sign = 1; 	\
+		break; \
+	} \
+}
+
+// 检测时间是否超时,超时则退出当前函数
+#define CHK_TIME1()  { gettimeofday(&time_n, NULL); \
+	if(time_n.tv_sec > time_m.tv_sec) { \
+		printf("\ntimeout!!!\n\n");\
+		if(datafile != NULL) \
+		fclose(datafile); \
+		return ret; \
+	} \
+}
+
+
+/******************************************************************************
+ * APData 相关定义、声明
+ *****************************************************************************/
+// APData 数据头部定义
+typedef struct {
+	unsigned int  ih_magic;		// Image Header Magic Number
+	unsigned int  ih_dcrc;		// Image Data CRC checksum
+	unsigned int  ih_time;		// Image Creation Timestamp
+	unsigned int  ih_size;		// Image Data Size
+	unsigned int  ih_compress;		// Image Header compress or not:0, not compress
+	unsigned int  pkg_flash_addr;	// flash memory offset for package
+	unsigned int  pkg_run_addr;		// Run time address for this package
+	unsigned int  ih_hcrc;		// Image Header CRC checksum
+} uc_image_header_t;
+
+// APData 数据头部长度
+#define HEADERLEN 32
+// APData 接收状态类型
+typedef enum ReceStat{
+	WAIT_FD = 1,
+	WAIT_FC,
+	WAIT_FB,
+	WAIT_FA,
+	RECE_HEADER,
+	RECE_DATA,
+} RecvStat_t;
+// APData 接收状态变量
+static RecvStat_t recvStat = WAIT_FD;
+// APData 接收状态变量
+static int isStartReceive = 0;
+// APData 开始接收
+void af_start_receive();
+// APData 停止接收,在数据接收完成或出错时调用
+void af_stop_receive();
+// 获取isStartReceive 变量值
+int af_is_start_receive();
+// APData 数据接收入口
+int af_add_char(char *file, unsigned char c);
+// 校验 APData 数据头
+int af_check_header(unsigned char *pbuf, unsigned int len);
+// 校验 APData 数据区
+int af_check_data(unsigned int * pbuf, unsigned int len);
+// 获取 APData 数据长度
+int af_get_data_len();
+// APData 数据接收缓存
+unsigned int recv_buf[1024 * 2];
+unsigned char *pbuf;
+int data_len;
+// 校验文件
+int check_file(char *fname);
+
+/******************************************************************************
+ * 与接收机串口通讯相关定义、声明
+ *****************************************************************************/
+// select功能使用变量
+static int use_select = 1;
+// 初始化串口资源
+int initial_serialPort(char * serial_device);
+// 设置串口波特率
+int set_baudrate(int fd, int baudrate);
+// 检测串口数据
+static int select_read(int fd, int timeout);
+// 读取串口数据
+ssize_t deal_read(int fd, void *buf, size_t count);
+// 向接收机发送串口数据
+static void gps_dev_send(int fd, char *msg);
+// 通过xmodem协议向接收机发送串口数据
+int xmodem_send(int fd, char *fname);
+
+/******************************************************************************
+ * apflash 功能函数
+ *****************************************************************************/
+// 检测接收机发送的'YC'信号,如果收到,则标志着接收机进入boot模式,并可以通过xmodem发送数据
+int check_YC(char newchar);
+// 获取 APData 数据, 应该在接收机定位且星历数据接收完整时获取
+int getAPData(int fd, char *file);
+// 向接收机发送 APData 数据,有效的APData数据可以让CI模块迅速定位
+int sendAPData(int fd, char *ap);
+// 校验 APData 数据文件
+int checkAPData(char *apFile);
+// 为接收机加载BootLoader,该流程执行时,需要根据终端提示,给接收机下电和上电,确保接收机进入boot模式
+int downloadBL(int fd, char *bl);
+// 为接收机加载Firmware,该流程必须在加载BootLoader之后进行
+int downloadFW(int fd, char *fw);
+
+void printGetapUsage(char *app)
+{
+	printf("\n%s getap -d receiverPort [-b baudrate] [-h] -a apfile \n", app);
+	printf("\tfunction: read APData from receiver\n");
+	printf("\tparas:\n");
+	printf("\t\treceiverPort: Port that connected to receiver\n");
+	printf("\t\tbaudrate: baudrate of receiverPort\n");
+}
+
+void printSendapUsage(char *app)
+{
+	printf("\n%s sendap -d receiverPort [-b baudrate] [-h] -a apfile\n", app);
+	printf("\tfunction: send APData to receiver\n");
+	printf("\tparas:\n");
+	printf("\t\treceiverPort: Port that connected to receiver\n");
+	printf("\t\tbaudrate: baudrate of receiverPort\n");
+}
+
+void printCheckapUsage(char *app)
+{
+	printf("\n%s checkap -a apfile [-h]\n", app);
+	printf("\tfunction: check APData\n");
+	printf("\tparas:\n");
+	printf("\t\tapfile: APData file\n");
+}
+
+void printDownloadblUsage(char *app)
+{
+	printf("\n%s downbl -d receiverPort [-b baudrate] -l bootloader [-h]\n", app);
+	printf("\tfunction: download bootloader to receiver\n");
+	printf("\tparas:\n");
+	printf("\t\treceiverPort: Port that connected to receiver\n");
+	printf("\t\tbaudrate: baudrate of receiverPort\n");
+	printf("\t\tbootloader: bootloader file\n");
+}
+
+void printDownloadfwUsage(char *app)
+{
+	printf("\n%s downfw -d receiverPort [-b baudrate] -f firmware [-h]\n", app);
+	printf("\tfunction: download firmware to receiver\n");
+	printf("\tparas:\n");
+	printf("\t\treceiverPort: Port that connected to receiver\n");
+	printf("\t\tbaudrate: baudrate of receiverPort\n");
+	printf("\t\tfirmware: firmware file\n");
+}
+
+void printUsage(char *app)
+{
+	printGetapUsage(app);
+	printSendapUsage(app);
+	printCheckapUsage(app);
+	printDownloadblUsage(app);
+	printDownloadfwUsage(app);
+}
+
+#define GPS_DEV "/sys/devices/soc.0/d4000000.apb/mbtk-dev-op/gps_power"
+
+static int mopen_open_gps(int state)
+{
+    int fd, ret;
+    char s[4] = "on";
+    fd = open(GPS_DEV, O_RDWR | O_TRUNC, 0644);
+    if(fd < 0) {
+        printf("[%s]  file [%s] open error\n", __FUNCTION__, GPS_DEV);
+        return -1;
+    }
+    if(0 == state)
+    {
+        memcpy(s, "off", 3);
+    }
+    ret = write(fd, s, 4);
+    if (ret < 0) {
+        printf("%s: error writing to file!\n", __FUNCTION__);
+        close(fd);
+        return -2;
+    }
+
+    close(fd);
+    return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	int c;
+	int ret = 0;
+	int fd = -1;
+	int paraMask = 0;
+	int baud = 115200;
+	char devPort[200] = {0};
+	char fw[200] = {0};
+	char bl[200] = {0};
+	char ap[200] = {0};
+	int func = 0; // 1:getap, 2:sendap, 3:downbl, 4:downfw, 5:checkap
+
+	// Verify arguments
+	if (argc < 2) {
+		printf("Usage:\n");
+		printUsage(argv[0]);
+		exit(1);
+	}
+
+	if(strcmp(argv[1], "getap") == 0) {
+		func = 1;
+		paraMask = 1;
+	} else if (strcmp(argv[1], "sendap") == 0) {
+		func = 2;
+		paraMask = 1;
+	} else if (strcmp(argv[1], "downbl") == 0) {
+		func = 3;
+		paraMask = 9;
+	} else if (strcmp(argv[1], "downfw") == 0) {
+		func = 4;
+		paraMask = 5;
+	} else if (strcmp(argv[1], "checkap") == 0) {
+		func = 5;
+		paraMask = 16;
+	} else {
+		printf("Usage:\n");
+		printUsage(argv[0]);
+		exit(1);
+	}
+
+	for(;;) {
+		opterr = 0;
+		c = getopt(argc, argv, "d:b:f:l:a:h");
+		if(c < 0)
+			break;
+		switch(c) {
+			case 'd':
+				snprintf(devPort, 200, "%s", optarg);
+				printf("receiver port: %s\n", devPort);
+				paraMask &= ~1;
+				break;
+			case 'b':
+				baud = atoi(optarg);
+				printf("baud rate: %d\n", baud);
+				break;
+			case 'f':
+				snprintf(fw, 200, "%s", optarg);
+				printf("firmware: %s\n", fw);
+				paraMask &= ~4;
+				break;
+			case 'l':
+				snprintf(bl, 200, "%s", optarg);
+				printf("bootloader: %s\n", bl);
+				paraMask &= ~8;
+				break;
+			case 'a':
+				snprintf(ap, 200, "%s", optarg);
+				printf("apdata file: %s\n", ap);
+				paraMask &= ~16;
+				break;
+			case 'h':
+			default:
+				printf("Usage:\n");
+				if (func == 1)
+					printGetapUsage(argv[0]);
+				else if (func == 2)
+					printSendapUsage(argv[0]);
+				else if (func == 3)
+					printDownloadblUsage(argv[0]);
+				else if (func == 4)
+					printDownloadfwUsage(argv[0]);
+				else if (func == 5)
+					printCheckapUsage(argv[0]);
+				else
+					printUsage(argv[0]);
+				exit(1);
+		}
+	}
+	if (paraMask) {
+		if (func == 1)
+			printGetapUsage(argv[0]);
+		else if (func == 2)
+			printSendapUsage(argv[0]);
+		else if (func == 3)
+			printDownloadblUsage(argv[0]);
+		else if (func == 4)
+			printDownloadfwUsage(argv[0]);
+		else if (func == 5)
+			printCheckapUsage(argv[0]);
+		else
+			printUsage(argv[0]);
+		exit(1);
+	}
+
+	// Open serial port
+	if (func != 5) {
+		if ((fd = initial_serialPort(devPort)) == -1)
+		{
+			printf("Can't open COM\n");
+			return UART_DEV_ERR;
+		}
+		if (baud == 115200) {
+			set_baudrate(fd, B115200);
+		} else if (baud == 921600) {
+			set_baudrate(fd, B921600);
+		} else if (baud == 1843200) {
+			set_baudrate(fd, B1500000);
+		} else {
+			printf("baudrate %d not supported\n", baud);
+			close(fd);
+			exit(1);
+		}
+	}
+
+	// execute function
+	switch(func) {
+		case 1:
+			ret = getAPData(fd, ap);
+			break;
+		case 2:
+			ret = sendAPData(fd, ap);
+			break;
+		case 3:
+			ret = downloadBL(fd, bl);
+			break;
+		case 4:
+			ret = downloadFW(fd, fw);
+			break;
+		case 5:
+			ret = checkAPData(ap);
+			break;
+		default:break;
+	}
+	close(fd);
+	return ret;
+
+}
+
+int getAPData(int fd, char *file)
+{
+	int rByte = 0;
+	char rbuf[4096];
+	int ret = 0, i;
+	struct timeval time_m, time_n;
+
+    if (NULL == file) {
+	    printf("Please input file!! \n");
+		return 1;
+    }
+	if (!fd)
+		return 1;
+	printf("Get apdata\n");
+	gps_dev_send(fd, "$ReqRecvFlash\r\n");
+	af_start_receive();
+	GET_TIME();
+	while(1) {
+		CHK_TIME();
+		if(select_read(fd,1) > 0)
+			usleep(50000);
+		else
+			continue;
+
+		rByte = deal_read(fd,&rbuf,sizeof(rbuf));
+		if(rByte >= 1){
+			if(af_is_start_receive()) {
+				for(i = 0; i < rByte; i++)
+					af_add_char(file, rbuf[i]);
+			} else {
+				break;
+			}
+		}
+	}
+
+	checkAPData(file);
+	return 0;
+}
+
+int sendAPData(int fd, char *apFile)
+{
+	int rByte = 0;
+	char rbuf[4096];
+	int ret = 0;
+	struct timeval time_m, time_n;
+
+	if(access(apFile, F_OK) != -1)
+	{
+		// Download APData only if the file exits
+		printf("Download APData...\n");
+		if(xmodem_send(fd, apFile))
+		{
+			printf("xmodem error!\n");
+			close(fd);
+			return ENTER_UPDATE_MODE_ERR;
+		}
+		// Waiting for 'C'
+		GET_TIME();
+		while(1)
+		{
+			CHK_TIME();
+			if(select_read(fd,1) > 0)
+				usleep(500000);
+			else
+				continue;
+			rByte = deal_read(fd,&rbuf,sizeof(rbuf)-1);
+			rbuf[rByte] = 0;
+			if(rByte > 0)
+			{
+				if(rbuf[rByte - 1] == 'C')
+					break;
+			}
+		}
+		printf("download APData success\n");
+	}
+	else
+	{
+		printf("file err!\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int checkAPData(char *apFile)
+{
+	printf("Checking %s\n", apFile);
+	if(check_file(apFile))
+	{
+		printf("file error!\n");
+		return FILE_CHECK_ERR;
+
+	}
+	else
+	{
+		printf("pass\r\n");
+	}
+	return 0;
+}
+
+int downloadFW(int fd, char *fw)
+{
+    int ret;
+	struct timeval time_m, time_n;
+	char rbuf[512];
+
+    if(NULL == fw) {
+	    printf("Error: Can't find firmware.\n");
+        return -1;
+    }
+	printf("Download firmware...\n");
+	if(xmodem_send(fd, fw) < 0) {
+		printf("xmodem error! send firmware failed!\n");
+		close(fd);
+		return UPDATE_ERR;
+	}
+
+	printf("Download firmware success\n");
+	return 0;
+}
+
+int downloadBL(int fd, char *bl)
+{
+	int rByte = 0;
+	char rbuf[4096];
+	char name[128];
+	int ret = 0;
+	struct timeval time_m, time_n;
+
+    if(NULL == bl) {
+	    printf("Error: Can't find bootloader.\n");
+        return -1;
+    }
+	printf("------Please Powerdown the receiver!\n");
+    mopen_open_gps(0);
+	SET_TIME_OUT(3);
+	while(1) {
+		DELAY_TIME_BREAK(); //
+		if(select_read(fd,1) > 0)
+			usleep(50000);
+		else
+			continue;
+
+		rByte = deal_read(fd,&rbuf,sizeof(rbuf));
+	}
+	int start = 0,finish = 0;
+
+	memset(name, 0, sizeof(name));
+	sprintf(name,"M!T");
+	printf("waiting for YC, timeout is %d s\n", TIMEOUT_SEC);
+	printf("-------Please Powerup the receiver!\n");
+    mopen_open_gps(1);
+	// Waiting for 'YC'
+	GET_TIME();
+	while(1) {
+		int finish = 0, i;
+		CHK_TIME_BREAK(); //
+		rByte = write( fd, name, strlen(name));
+		rByte = select_read(fd,1);
+		if(rByte <= 0)
+			continue;
+		rByte = deal_read(fd, rbuf, sizeof(rbuf) - 1);
+		rbuf[rByte] = 0;
+		for (i = 0 ; i < rByte; i++)
+		{
+			if (check_YC(rbuf[i])) {
+				printf("Receive 'YC'\n");
+				finish = 1;
+				break;
+			}
+		}
+		if (finish)
+			break;
+	}
+	//wait 'YC' timeout deal
+	if (timeout_sign == 1)
+	{
+		//wait NAK
+		GET_TIME();
+		while(1)
+		{
+			CHK_TIME();
+			if(select_read(fd,1) <= 0)
+				continue;
+
+			rByte = deal_read(fd, rbuf,sizeof(rbuf));
+			if (rbuf[rByte-1] == 'C')
+			{
+				printf("###read xmodem start character 'C'.\n");
+				break;
+			}
+		}
+	}
+	use_select = 1;
+	printf("download bootloader...\n");
+
+	// Transfer bootloader via xmodem protocal
+	// if(xmodem_send(fd, "./bootloader.bin")) {
+	if(xmodem_send(fd, bl)) {
+		printf("xmodem error!\n");
+		close(fd);
+		return ENTER_UPDATE_MODE_ERR;
+	}
+	printf("download bootloader success\n");
+	return 0;
+}
+
+int check_YC(char newchar)
+{
+	int static state = 0;
+	int ret = 0;
+	switch (state) {
+		case 0:
+			if (newchar == 'Y')
+				state = 1;
+			break;
+		case 1:
+			if (newchar == 'C') {
+				state = 1;
+				ret = 1;
+			}
+			break;
+		default:
+			state = 0;
+	}
+	return ret;
+}
+
+const unsigned short CRC16_Table[256] = {
+	0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+	0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+	0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+	0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+	0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+	0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+	0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+	0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+	0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+	0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+	0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+	0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+	0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+	0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+	0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+	0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+	0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+	0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+	0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+	0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+	0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+	0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+	0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+	0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+	0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+	0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+	0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+	0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+	0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+	0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+	0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+	0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+};
+
+unsigned short crc16_ccitt(const unsigned char *buf, int len)
+{
+	register int counter;
+	register unsigned short crc = 0;
+	for (counter = 0; counter < len; counter++)
+		crc = (crc << 8) ^ CRC16_Table[((crc >> 8) ^ *(char *)buf++) & 0x00FF];
+	return crc;
+}
+
+
+unsigned int checksum32(unsigned int * pbuf, unsigned int len)
+{
+	unsigned int i, sumValue = 0;
+	len >>=2;
+
+	for(i=0;i<len;i++)
+	{
+		sumValue += *pbuf++;
+	}
+	return sumValue;
+}
+
+void af_start_receive()
+{
+	recvStat = WAIT_FD;
+	isStartReceive = 1;
+	return;
+}
+
+void af_stop_receive()
+{
+    int i;
+	printf("%s:%d\r\n", __FUNCTION__, __LINE__);
+	printf("%s:%d  recvStat = %d\r\n", __FUNCTION__, __LINE__, recvStat);
+	pbuf = (unsigned char *)recv_buf;
+	for(i = 0; i < 4636; i++){
+		if(i % 32 == 0)printf("\r\n");
+		printf("%02X ", pbuf[i]);
+	}
+	printf("\r\n");
+	isStartReceive = 0;
+	return;
+}
+
+int af_is_start_receive()
+{
+	return isStartReceive;
+}
+
+int af_check_header(unsigned char *pbuf, unsigned int len)
+{
+	unsigned int crc = crc16_ccitt(pbuf, len-4);
+
+	if(crc == *(unsigned int *)(pbuf + len - 4))
+		return 1;
+	else
+		return 0;
+}
+
+int af_check_data(unsigned int * pbuf, unsigned int len)
+{
+	unsigned int cs = checksum32(pbuf + 8, len);
+	if(cs == pbuf[1])
+		return 1;
+	else
+		return 0;
+}
+
+int af_get_data_len()
+{
+	int len = *(int *)(recv_buf+3);
+	return len;
+}
+
+int af_add_char(char *file, unsigned char c)
+{
+	int ret = 0;
+	switch(recvStat){
+		case WAIT_FD:
+			if(c == 0xfd){
+				pbuf = (unsigned char *)recv_buf;
+				pbuf[0] = c;
+				recvStat = WAIT_FC;
+				printf("------------received 0xfd\r\n");
+			}
+			break;
+		case WAIT_FC:
+			if(c == 0xfc){
+				pbuf[1] = c;
+				recvStat = WAIT_FB;
+				printf("------------received 0xfc\r\n");
+			}else{
+				af_stop_receive();
+			}
+			break;
+		case WAIT_FB:
+			if(c == 0xfb){
+				pbuf[2] = c;
+				recvStat = WAIT_FA;
+				printf("------------received 0xfb\r\n");
+			}else{
+				af_stop_receive();
+			}
+			break;
+		case WAIT_FA:
+			if(c == 0xfa){
+				pbuf[3] = c;
+				recvStat = RECE_HEADER;
+				pbuf += 4;
+				printf("------------received 0xfa\r\n");
+			}else{
+				af_stop_receive();
+			}
+			break;
+		case RECE_HEADER:
+			*pbuf = c;
+			pbuf++;
+			if((pbuf - (unsigned char *)recv_buf) == HEADERLEN){
+				if(af_check_header((unsigned char *)recv_buf, HEADERLEN)){
+					recvStat = RECE_DATA;
+					data_len = af_get_data_len();
+				}else{
+					af_stop_receive();
+				}
+			}
+			break;
+		case RECE_DATA:
+			*pbuf = c;
+			pbuf++;
+			if((pbuf - (unsigned char *)recv_buf) == data_len + HEADERLEN){
+				if(af_check_data(recv_buf, recv_buf[3])){
+					int fd = open(file, O_WRONLY|O_CREAT, S_IRWXU);
+					write(fd, recv_buf, pbuf - (unsigned char *)recv_buf);
+					printf("%s:%d rtm len = %ld\r\n", __FUNCTION__, __LINE__, pbuf-(unsigned char *)recv_buf);
+					close(fd);
+					printf("receive rtm\n");
+				}else{
+					printf("af_check_data false!");
+				}
+				af_stop_receive();
+			}
+			ret = 1;
+			break;
+		default:
+			printf("%s:recvStat = %d\r\n", __FUNCTION__, recvStat);
+			break;
+	}
+	return ret;
+}
+
+
+
+ssize_t deal_read(int fd, void *buf, size_t count)
+{
+	int ret = 0;
+
+	while (1)
+	{
+		ret = read(fd, buf, count);
+		if (ret == 0)
+		{
+			printf("read serial return 0, please check serial device.\n");
+			exit(UART_DEV_ERR);
+		}
+		if(ret < 0)
+		{
+			if ((errno == EAGAIN) || (errno == EINTR))
+			{
+				printf("read serial return -1, errno = %d, retry.\n", errno);
+				continue;
+			}
+			else
+			{
+				printf("read serial return -1, errno = %d, please check serial device.\n", errno);
+				exit(UART_DEV_ERR);
+			}
+		}
+		return ret;
+	}
+}
+
+unsigned short get_crc16 ( char *ptr, unsigned short count )
+{
+	unsigned short crc, i;
+
+	crc = 0;
+	while(count--)
+	{
+		crc = crc ^ (int) *ptr++ << 8;
+
+		for(i = 0; i < 8; i++)
+		{
+			if(crc & 0x8000)
+				crc = crc << 1 ^ 0x1021;
+			else
+				crc = crc << 1;
+		}
+	}
+
+	return (crc & 0xFFFF);
+}
+
+void dump_u(void *buf, int len)
+{
+	unsigned char *p = (unsigned char *)buf;
+	int i;
+
+	for(i = 0; i < len; i++) {
+		if(i % 16 == 0) printf("%04x:", i);
+		if(i % 16 == 8) printf(" -");
+		printf(" %02x", p[i]);
+		if(i % 16 == 15) printf("\n");
+	}
+	if(i % 16) printf("\n");
+}
+
+unsigned int get_file_size(const char * name)
+{
+	struct stat statbuff;
+	//unsigned int size, checksum;
+	if(stat(name, &statbuff) < 0)
+		return -1;
+	else
+		return statbuff.st_size;
+}
+
+
+int check_file(char * fname)
+{
+	FILE *fd;
+	uc_image_header_t header;
+	unsigned int buf[1024];
+	unsigned int fsize, checksum, i;
+	unsigned int len;
+	unsigned short crc;
+	size_t rByte;
+
+	if((fd=fopen(fname,"rb"))==NULL)
+	{
+		printf("\n can't open (%s) or not exist!(errno=%d:%s) \n", fname, errno, strerror(errno));
+		return -1;
+	}
+
+	fsize = get_file_size(fname);
+
+	printf("file size [%d]\n",fsize);
+
+	if(fsize == 0)
+		return -1;
+
+	while(fsize > sizeof(header)) {
+		rByte = fread((char *)&header, sizeof(char), sizeof(header), fd);
+
+		dump_u((char *)&header, sizeof(header));
+
+		crc = get_crc16 ( (char *) &header, sizeof(header)-4);
+		printf("crc16  [%08x]\n", crc);
+
+		if((header.ih_hcrc & 0xFFFF) != crc) {
+			fclose(fd);
+			return -1;
+		}
+
+		fsize -= sizeof(header);
+		fsize -= header.ih_size;
+		checksum = 0;
+		len = header.ih_size;
+		while(len > 0)
+		{
+			if(len >= 1024 )
+				rByte = 1024;
+			else
+				rByte = len;
+
+			memset(buf, 0, sizeof(buf));
+			rByte = fread((char *)buf, 1, rByte, fd);
+			for(i = 0; i < (rByte+3)/4; i++)
+				checksum += buf[i];
+
+			len -= rByte;
+		}
+		printf("checksum  [%08x]\n\n",checksum);
+
+		if( checksum != header.ih_dcrc) {
+			fclose(fd);
+			return -1;
+		}
+	}
+
+	fclose(fd);
+	return 0;
+}
+
+static int select_read(int fd, int timeout) //1ms
+{
+	fd_set set;
+	struct timeval t;
+	int ret;
+	int i = timeout;
+
+	if(use_select) {
+		do {
+			FD_ZERO(&set);
+			FD_SET(fd, &set);
+			t.tv_sec = 0;
+			t.tv_usec = 100;
+
+			ret = select(FD_SETSIZE, &set, NULL, NULL, &t );
+			if(ret == 0) continue;
+			if(ret < 0 && errno == EINTR)continue;
+			else return ret;
+		} while(i--);
+	} else {
+		struct timeval t0, t1;
+		long dt = 0;
+		int c;
+
+		gettimeofday(&t0, NULL);
+		do {
+			c = 0;
+			ret = ioctl(fd, FIONREAD, &c);
+			if(c > 0) { ret = c; break; }
+
+			gettimeofday(&t1, NULL);
+			dt = t1.tv_usec - t0.tv_usec;
+			dt += (t1.tv_sec-t0.tv_sec)*1000*1000;
+		} while(dt/1000 < timeout);
+	}
+
+	return ret;
+}
+
+int set_baudrate(int fd, int baudrate)
+{
+	struct termios options, oldtio;
+
+	if(fcntl(fd, F_SETFL, 0) < 0) {
+		printf("fcntl failed!\n");
+		return -1;
+	}
+
+	if(tcgetattr(fd, &oldtio) != 0) {
+		printf("setup serial error!\n");
+		return -1;
+	}
+
+	/* Get the current options for the port... */
+	tcgetattr(fd, &options);
+
+	/* Set the baud rates to baudrate... */
+	cfsetispeed(&options,baudrate);
+	cfsetospeed(&options,baudrate);
+	tcsetattr(fd, TCSANOW, &options);
+
+	if (0 != tcgetattr(fd, &options))
+	{
+		printf("get options error!\n");
+		return -1;
+	}
+
+	/*
+	 * 8bit Data,no partity,1 stop bit...
+	 */
+	options.c_cflag &= ~PARENB;//无奇偶校验
+	options.c_cflag &= ~CSTOPB;//停止位,1位
+	options.c_cflag &= ~CSIZE; //数据位的位掩码
+	options.c_cflag |= CS8;    //数据位,8位
+
+	cfmakeraw(&options);
+
+	/*
+	 * Set the new options for the port...
+	 */
+	if (tcsetattr(fd, TCSANOW, &options) != 0)
+	{
+		printf("setup serial error!\n");
+		return -1 ;
+	}
+
+	return 0 ;
+}
+
+int initial_serialPort(char * serial_device)
+{
+	int fd;
+	fd = open( serial_device , O_RDWR );
+	if ( fd == -1 )
+	{
+		/* open error! */
+		printf("Can't open serial port(%s)!(errno=%d:%s) \n", serial_device, errno, strerror(errno));
+		return -1;
+	}
+
+	set_baudrate(fd, B9600);
+
+	return fd ;
+}
+
+static void gps_dev_send(int fd, char *msg)
+{
+	int i, n, ret;
+
+	i = strlen(msg);
+
+	n = 0;
+
+	printf("function gps_dev_send: %s", msg);
+	do {
+
+		ret = write(fd, msg + n, i - n);
+
+		if (ret < 0 && errno == EINTR) {
+			continue;
+		}
+
+		n += ret;
+
+	} while (n < i);
+
+	// drain cmd
+	tcdrain(fd);
+
+	return;
+}
+
+int xmodem_send(int fd, char *fname)
+{
+	char packet_data[XMODEM_DATA_SIZE];
+	char frame_data[XMODEM_DATA_SIZE + XMODEM_CRC_SIZE + XMODEM_FRAME_ID_SIZE + 1];
+	int ret = -1;
+
+	FILE *datafile;
+	int complete,retry_num,pack_counter,read_number,write_number,i;
+	unsigned short crc_value;
+	unsigned char ack_id = 'C';
+	struct timeval time_m, time_n;
+
+	datafile = NULL;
+	pack_counter = 0;	// 包计数器清零
+	complete = 0;
+	retry_num = 0;
+
+	printf("[%s]\n",fname);
+	//只读方式打开一个准备发送的文件,如果不存在就报错,退出程序。
+	if((datafile=fopen(fname,"rb"))==NULL)
+	{
+		printf("\n can't open (%s) or not exist!(errno=%d:%s) \n", fname, errno, strerror(errno));
+		return -1;
+	}
+	else
+	{
+		printf("Ready to send the file:%s\n",fname);
+	}
+
+	printf("Waiting for signal C/NAK!\n");
+	GET_TIME();
+	while(1)
+	{
+		CHK_TIME1();
+		if(select_read(fd,1) > 0)
+			usleep(10000);
+		else
+			continue;
+
+		//read(fd,&ack_id,1);
+		deal_read(fd,&ack_id,1);
+		if(ack_id == 'C')
+			break;
+	}
+
+	printf("The signal NAK: %02x ok!!!\n",ack_id);//打印接收到的NAK信息
+
+	while(!complete)
+	{
+		switch(ack_id)
+		{
+			case XMODEM_CRC_CHR:	// 接收到字符'C'开始启动传输,并使用CRC校验
+				printf("begining to Send file %s...\n",fname);
+
+			case XMODEM_ACK:        //0x06
+				retry_num = 0;
+				pack_counter++;
+
+				read_number = fread(packet_data, sizeof(char), XMODEM_DATA_SIZE, datafile);
+				//从打开的datafile指向的文件中读取
+				//XMODEM_DATA_SIZE 个(char)数据,
+				//放到packet_data这个数组中
+				if(read_number > 0)//read_number为返回的读取实际字节数
+				{
+					//printf("test:read_number:%d\n", read_number);
+					if(read_number < XMODEM_DATA_SIZE_STX)
+					{
+						printf("Start filling the last frame!\n");
+						for(; read_number < XMODEM_DATA_SIZE; read_number++)
+							packet_data[read_number] = 0x1A;  // 不足128字节用0x1A填充
+						//printf("replenish data.\n");
+					}
+
+					frame_data[0] = XMODEM_HEAD;  // 帧开始字符
+					frame_data[1] = (char)pack_counter;  // 信息包序号
+					frame_data[2] = (char)(255 - frame_data[1]);  // 信息包序号的补码
+
+					for(i=0; i < XMODEM_DATA_SIZE; i++)  // 128字节的数据段
+						frame_data[i+3] = packet_data[i];//把收到的字符和信息头一起打包
+
+					crc_value = get_crc16(packet_data, XMODEM_DATA_SIZE); // 16位crc校验
+					frame_data[XMODEM_DATA_SIZE+3] = (unsigned char)(crc_value >> 8);// 高八位数据
+					frame_data[XMODEM_DATA_SIZE+4] = (unsigned char)(crc_value);     //低八位数据
+
+					/* 发送133字节数据 */
+					write_number = write( fd, frame_data, XMODEM_DATA_SIZE + 5);//向串口写一个包数据,即133字节数据
+					printf("."); //ADD: process
+					fflush(stdout);
+					//printf("waiting for next ACK... \n......\n");
+
+					GET_TIME();
+					while(1)
+					{
+						CHK_TIME1();
+						if(select_read(fd,1) > 0)
+							usleep(10000);
+						else
+							continue;
+
+						//read(fd,&ack_id,1);
+						deal_read(fd,&ack_id,1);
+						break;
+					}
+
+					if(ack_id == XMODEM_ACK) {
+						//printf("ACK Ok!!Ready sending next pack!\n");
+						;
+					}
+					else
+					{
+						printf("ACK Error!\n");
+						printf("0x%02X\n",ack_id);
+						//printf("pack_counter = %d\n", pack_counter);
+					}
+				}
+
+				else  // 文件发送完成
+				{
+					ack_id = XMODEM_EOT;
+					complete = 1;
+					printf("Complete ACK\n");
+
+					GET_TIME();
+					while(ack_id != XMODEM_ACK)
+					{
+						CHK_TIME1();
+						ack_id = XMODEM_EOT;
+						write_number = write(fd,&ack_id,1);
+						while((deal_read(fd, &ack_id, 1)) <= 0);
+					}
+					printf("Send file successful!!!\n");
+					fclose(datafile);
+					datafile = NULL;
+				}
+				break;
+
+			case XMODEM_NAK:
+				if( retry_num++ > 10)
+				{
+					printf("Retry too many times,Quit!\n");
+					complete = 1;
+				}
+				else //重试,发送
+				{
+					write_number = write(fd, frame_data, XMODEM_DATA_SIZE + 5);
+					printf("Retry for ACK,%d,%d...", pack_counter, write_number);
+
+					GET_TIME();
+					while(1)
+					{
+						CHK_TIME1();
+						if(select_read(fd,1) > 0)
+							usleep(100);
+						else
+							continue;
+
+						//read(fd,&ack_id,1);
+						deal_read(fd,&ack_id,1);
+						break;
+					}
+
+					if( ack_id == XMODEM_ACK )
+						printf("OK\n");
+					else
+						printf("Error!\n");
+				}
+				break;
+			default:
+				printf("Fatal Error! %d\n", ack_id);
+				complete = 1;
+				return -1;
+				break;
+		}
+	}
+
+	if( datafile != NULL )
+		fclose(datafile);
+
+	return 0;
+}
diff --git a/mbtk/test/iconv_demo.cc b/mbtk/test/iconv_demo.cc
new file mode 100755
index 0000000..de95454
--- /dev/null
+++ b/mbtk/test/iconv_demo.cc
@@ -0,0 +1,204 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iconv.h>
+#include <errno.h>
+#include <stddef.h>
+
+struct outbuf
+{
+    struct outbuf *next;
+    char *outptr;
+    size_t outbytesleft;
+    char buf[256];
+};
+
+char *eazyiconv(const char *to, const char *from,
+                char *str, size_t str_blen, size_t str_elemsize, size_t out_tailzero_blen, size_t *out_size,
+                const char *replchr)
+{
+    char *retstr = NULL;
+    struct outbuf *outhead = NULL;
+    struct outbuf *outtail = NULL;
+    struct outbuf *outiter = NULL;
+    iconv_t cd = NULL;
+    char *inptr = str;
+    size_t inbytesleft = str_blen;
+    int retval = 0;
+    int err = 0;
+    size_t blocksize = 0;
+    size_t totalsize = 0;
+    char *retiter = NULL;
+    unsigned int chrval = 0;
+    iconv_t cdreplchr = NULL;
+    char replchrfmtbuf[256] = "";
+    char replchrbuf[256] = "";
+    char *replchrfmtptr = replchrfmtbuf;
+    size_t replchrfmtleft = sizeof replchrfmtbuf;
+    char *replchrptr = replchrbuf;
+    size_t replchrleft = sizeof replchrbuf;
+    int replchr_blen = 0;
+
+    cd = iconv_open(to, from);
+    if (cd == (iconv_t)-1)
+    {
+        goto noclean;
+    }
+
+    outhead = outtail = calloc(1, sizeof(struct outbuf));
+    if (outtail == NULL)
+    {
+        goto clean_cd;
+    }
+    outtail->next = NULL;
+    outtail->outptr = outtail->buf;
+    outtail->outbytesleft = sizeof outtail->buf;
+    memset(outtail->buf, 0, sizeof outtail->buf);
+
+    while (1)
+    {
+        retval = iconv(cd, &inptr, &inbytesleft, &outtail->outptr, &outtail->outbytesleft);
+        if (retval == -1)
+            err = errno;
+        else
+            err = 0;
+        switch (err)
+        {
+            case 0:
+                outiter = calloc(1, sizeof(struct outbuf));
+                if (outiter == NULL)
+                {
+                    goto clean_outbufs;
+                }
+                if (inptr == NULL) // succeeded cleanup iconv
+                {
+                    goto succeeded;
+                }
+                else // fully succeeded iconv
+                {
+                    inptr = NULL; // do cleanup iconv
+                    inbytesleft = 0;
+                }
+                break;
+            case EINVAL: // incomplete tail sequence
+            case EILSEQ: // invalid sequence
+                chrval = 0;
+                memcpy(&chrval, inptr, str_elemsize > sizeof chrval ? sizeof chrval : str_elemsize);
+                snprintf(replchrfmtbuf, sizeof replchrfmtbuf, replchr, chrval);
+                inptr += str_elemsize;
+                inbytesleft -= str_elemsize;
+
+                cdreplchr = iconv_open(to, "UTF-8");
+                if (cdreplchr == (iconv_t)-1)
+                {
+                    goto clean_outbufs;
+                }
+                replchrfmtptr = replchrfmtbuf;
+                replchrfmtleft = strlen(replchrfmtbuf);
+                replchrptr = replchrbuf;
+                replchrleft = sizeof replchrbuf;
+                iconv(cdreplchr, &replchrfmtptr, &replchrfmtleft, &replchrptr, &replchrleft);
+                iconv(cdreplchr, NULL, NULL, &replchrptr, &replchrleft);
+                iconv_close(cdreplchr);
+                replchr_blen = replchrptr - replchrbuf;
+
+                if (outtail->outbytesleft < replchr_blen)
+                {
+                    outiter = calloc(1, sizeof(struct outbuf));
+                    if (outiter == NULL)
+                    {
+                        goto clean_outbufs;
+                    }
+                    outtail->next = outiter;
+                    outtail = outiter;
+                    outtail->next = NULL;
+                    outtail->outptr = outtail->buf;
+                    outtail->outbytesleft = sizeof outtail->buf;
+                    memset(outtail->buf, 0, sizeof outtail->buf);
+                }
+                memcpy(outtail->outptr, replchrbuf, replchr_blen);
+                outtail->outptr += replchr_blen;
+                outtail->outbytesleft -= replchr_blen;
+                break;
+            case E2BIG: // no enough space
+                outiter = calloc(1, sizeof(struct outbuf));
+                if (outiter == NULL)
+                {
+                    goto clean_outbufs;
+                }
+                outtail->next = outiter;
+                outtail = outiter;
+                outtail->next = NULL;
+                outtail->outptr = outtail->buf;
+                outtail->outbytesleft = sizeof outtail->buf;
+                memset(outtail->buf, 0, sizeof outtail->buf);
+                break;
+            default:
+                break;
+        }
+    }
+
+succeeded:
+    totalsize = 0;
+    for (outiter = outhead; outiter != NULL; outiter = outiter->next)
+    {
+        blocksize = outiter->outptr - outiter->buf;
+        totalsize += blocksize;
+    }
+    retstr = calloc(totalsize + out_tailzero_blen, 1);
+    if (retstr == NULL)
+    {
+        goto clean_outbufs;
+    }
+    retiter = retstr;
+    for (outiter = outhead; outiter != NULL; outiter = outiter->next)
+    {
+        blocksize = outiter->outptr - outiter->buf;
+        memcpy(retiter, outiter->buf, blocksize);
+        retiter += blocksize;
+    }
+    memset(retiter, 0, out_tailzero_blen);
+    *out_size = totalsize;
+
+clean_outbufs:
+    while (outhead != NULL)
+    {
+        outiter = outhead;
+        outhead = outhead->next;
+        free(outiter);
+    }
+    outtail = NULL;
+clean_cd:
+    iconv_close(cd);
+noclean:
+    return retstr;
+}
+
+int main(int argc, char **argv)
+{
+    if (argc < 7)
+    {
+        printf("usage: eiconv_test from_charset from_elemsize to_charset to_elemsize from_file to_file (no utf-16/32)\n");
+        return 0;
+    }
+    FILE *from_file = fopen(argv[5], "rb");
+    fseek(from_file, 0, SEEK_END);
+    off_t fsize = ftell(from_file);
+    fseek(from_file, 0, SEEK_SET);
+    char *from_str = malloc(fsize + 1);
+    fread(from_str, 1, fsize, from_file);
+    fclose(from_file);
+
+    size_t out_size = 0;
+    char *to_str = eazyiconv(argv[3], argv[1],
+                             from_str, fsize, atoi(argv[2]), atoi(argv[4]), &out_size,
+                             "<0x%02X>");
+
+    FILE *to_file = fopen(argv[6], "wb");
+    fwrite(to_str, 1, out_size, to_file);
+    free(to_str);
+    fclose(to_file);
+    return 0;
+}
+
+
diff --git a/mbtk/test/key_ev_demo.c b/mbtk/test/key_ev_demo.c
new file mode 100755
index 0000000..190e4a6
--- /dev/null
+++ b/mbtk/test/key_ev_demo.c
@@ -0,0 +1,249 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <poll.h>
+#include <errno.h>
+#include <linux/input.h>
+#include <sys/stat.h>
+#include <sys/reboot.h>
+#include <sys/timerfd.h>
+#include <time.h>
+
+#include "mbtk_type.h"
+#include "mbtk_log.h"
+
+
+#define MAX_DEVICES 16
+#define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int)
+#define POWER_KEY_LONG_PRESS_TIMEOUT 8000  // 8s
+#define POWER_KEY_PRESS_TIMEOUT 2000  // 2s
+
+static struct pollfd ev_fds[MAX_DEVICES];
+static unsigned ev_count = 0;
+
+
+static int ev_init(void)
+{
+    DIR *dir;
+    struct dirent *de;
+    int fd;
+
+    fd = open("/dev/rtc0", O_RDONLY);
+    if (fd < 0)
+    {
+        LOGW("open rtc0 error\n");
+    }
+    else
+    {
+        ev_fds[ev_count].fd = fd;
+        ev_fds[ev_count].events = POLLIN;
+        ev_count++;
+        LOGI("Monitor /dev/rtc0");
+    }
+
+    dir = opendir("/dev/input");
+    if (dir != NULL)
+    {
+        LOGI("dir = /dev/input");
+        while ((de = readdir(dir)) != NULL)
+        {
+            if (strncmp(de->d_name, "event", 5))
+                continue;
+            fd = openat(dirfd(dir), de->d_name, O_RDONLY);
+            if (fd < 0)
+                continue;
+
+            ev_fds[ev_count].fd = fd;
+            ev_fds[ev_count].events = POLLIN;
+            ioctl(fd, EVIOCSSUSPENDBLOCK, 1);
+            ev_count++;
+            if (ev_count == MAX_DEVICES)
+                break;
+
+            LOGI("Monitor /dev/input/%s", de->d_name);
+        }
+
+        closedir(dir);
+    }
+    else
+    {
+        LOGE("opendir() fail.[%d]",errno);
+        return -1;
+    }
+    return 0;
+}
+
+static void ev_exit(void)
+{
+    while (ev_count > 0)
+    {
+        close(ev_fds[--ev_count].fd);
+    }
+}
+
+/* wait: 0 dont wait; -1 wait forever; >0 wait ms */
+static int ev_get(struct input_event *ev, int wait_ms)
+{
+    int r;
+    unsigned n;
+    unsigned long alarm_data;
+
+//    if(wait_ms < 0)
+//    {
+//        LOGE("poll event return\n");
+//        return -1;
+//    }
+
+    LOGI("Waitting data...");
+    r = poll(ev_fds, ev_count, wait_ms);
+    LOGI("Get Data:result = %d",r);
+
+    if (r > 0)
+    {
+        for (n = 0; n < ev_count; n++)
+        {
+            if (ev_fds[n].revents & POLLIN)
+            {
+                if (n == 0)
+                {
+                    r = read(ev_fds[n].fd, &alarm_data, sizeof(alarm_data));
+                    LOGD("get form 0 is %ld", alarm_data);
+                    ev->type = EV_KEY;
+                    ev->code = KEY_BRL_DOT8;
+                    ev->value = 1;
+                    return 0;
+                }
+                else
+                {
+                    r = read(ev_fds[n].fd, ev, sizeof(*ev));
+                    if (r == sizeof(*ev))
+                        return 0;
+                }
+            }
+        }
+    }
+    return -1;
+}
+
+
+static void power_process(bool down, struct timeval *time)
+{
+    printf("POWER_KEY - %s,Time : %ld %ld \n", down ? "DOWN" : "UP", time->tv_sec, time->tv_usec);
+#if 0
+	static struct timeval down_time;
+    static bool key_down;
+    if(down)  // Down
+    {
+        key_down = true;
+        power_long_press_timeout = false;
+        down_time.tv_sec = time->tv_sec;
+        down_time.tv_usec = time->tv_usec;
+        signal(SIGALRM, power_key_timer_alrm);
+        struct itimerval val;
+        // Only time
+        val.it_interval.tv_sec  = 0;
+        val.it_interval.tv_usec = 0;
+        // Time
+        if(POWER_KEY_LONG_PRESS_TIMEOUT >= 1000)
+        {
+            val.it_value.tv_sec  = POWER_KEY_LONG_PRESS_TIMEOUT/1000;
+            val.it_value.tv_usec = POWER_KEY_LONG_PRESS_TIMEOUT%1000;
+        }
+        else
+        {
+            val.it_value.tv_sec  = 0;
+            val.it_value.tv_usec = POWER_KEY_LONG_PRESS_TIMEOUT;
+        }
+        if (setitimer(ITIMER_REAL, &val, NULL) == -1)
+        {
+            LOGE("setitimer fail.[%d]",errno);
+            return;
+        }
+    }
+    else     // UP
+    {
+        if(key_down)
+        {
+            // ms
+            long time_used = (time->tv_sec - down_time.tv_sec) * 1000 + (time->tv_usec - down_time.tv_usec) / 1000;
+            LOGI("Down time[%ld,%ld], Up time[%ld,%ld], time_used = %ld ms",down_time.tv_sec,down_time.tv_usec,
+                 time->tv_sec,time->tv_usec,time_used);
+
+            if(!power_long_press_timeout)
+            {
+                // Cancel alarm
+                struct itimerval value;
+                value.it_value.tv_sec = 0;
+                value.it_value.tv_usec = 0;
+                value.it_interval = value.it_value;
+                setitimer(ITIMER_REAL, &value, NULL);
+
+                if(time_used <= POWER_KEY_PRESS_TIMEOUT)
+                {
+                    screen_state_change(false);
+                }
+                else
+                {
+                    LOGI("Press timeout.");
+                }
+            }
+            else
+            {
+                LOGI("Long Press timeout.");
+            }
+        }
+        else
+        {
+            LOGI("UP key for screen on.");
+        }
+
+        key_down = false;
+    }
+#endif
+}
+
+
+int main(int argc, char *argv[])
+{
+	mbtk_log_init(NULL, "MBTK_KEY");
+    // Open dev
+    ev_init();
+
+    int ret = 0;
+    struct input_event ev;
+    while(1)
+    {
+        ret = ev_get(&ev, -1);
+        if(ret)
+        {
+            LOGW("ev_get() fail.");
+            continue;
+        }
+
+        LOGI("ev:time[%ld,%ld],type:%d,code:%d,value:%d",ev.time.tv_sec,ev.time.tv_usec,
+             ev.type,ev.code,ev.value);
+        if(ev.type != EV_KEY)
+        {
+            LOGW("event type error.[%d]",ev.type);
+            continue;
+        }
+
+        switch(ev.code)
+        {
+            case KEY_POWER:   // Power key
+            {
+                power_process(ev.value, &(ev.time));
+                break;
+            }
+            default:
+            {
+                LOGD("Unknown KEY[%d]",ev.code);
+                break;
+            }
+        }
+    }
+    return 0;
+}
diff --git a/mbtk/test/lynq_gnss_test.c b/mbtk/test/lynq_gnss_test.c
new file mode 100755
index 0000000..9ba5185
--- /dev/null
+++ b/mbtk/test/lynq_gnss_test.c
@@ -0,0 +1,179 @@
+/**
+ *   \file gnss_test.c
+ *   \brief A Documented file.
+ *
+ *  Detailed description
+ *   \Author:  Sniper <e190@163.com>
+ *   \Version: 1.0.0
+ *   \Date: 2022-03-26
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <errno.h>
+#include <termios.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include "mbtk_type.h"
+#include "lynq/lynq_gnss.h"
+//#include "mbtk_gnss.h"
+
+void gnss_handler_cb
+(
+    uint32 h_loc,
+    int    e_msg_id,
+    void   *pv_data,
+    void   *context_ptr
+) {
+    printf("e_msg_id=%d\n", e_msg_id);
+    switch(e_msg_id)
+    {
+        case E_LYNQ_LOC_MSG_ID_STATUS_INFO:
+            break;
+        case E_LYNQ_LOC_MSG_ID_LOCATION_INFO:
+            break;
+        case E_LYNQ_LOC_MSG_ID_SV_INFO:
+            break;
+        case E_LYNQ_LOC_MSG_ID_NMEA_INFO:
+        {
+            LYNQ_LOC_NMEA_INFO_T  *pt_nmea = (LYNQ_LOC_NMEA_INFO_T *)pv_data;
+
+            printf("NMEA info: timestamp=%lld, length=%d, nmea=%s\n",
+                    pt_nmea->timestamp, pt_nmea->length, pt_nmea->nmea);
+            break;
+        }
+        case E_LYNQ_LOC_MSG_ID_CAPABILITIES_INFO:
+            break;
+        case E_LYNQ_LOC_MSG_ID_AGPS_STATUS:
+            break;
+        case E_LYNQ_LOC_MSG_ID_NI_NOTIFICATION:
+            break;
+        case E_LYNQ_LOC_MSG_ID_XTRA_REPORT_SERVER:
+            break;
+    }
+}
+#if 1
+int main(int argc, char *argv[])
+{
+    int ret;
+
+    ret = lynq_gnss_enable_glonass();
+    if(ret < 0) {
+        printf("lynq_gnss_init FAIL.	ret:%d\n",ret);
+        return -1;
+    }
+
+    ret = lynq_gnss_init();
+    if(ret < 0) {
+        printf("lynq_gnss_init FAIL.	ret:%d\n",ret);
+        return -1;
+    }
+
+    lynq_gnss_callback_reg(gnss_handler_cb);
+
+    ret = lynq_gnss_agps_dataconnopen();
+    if(ret < 0) {
+        printf("lynq_gnss_agps_dataconnopen FAIL. ret:%d\n", ret);
+        return -1;
+    }
+
+    ret = lynq_gnss_start();
+    if(ret < 0) {
+        printf("lynq_gnss_start FAIL.	ret:%d\n",ret);
+        return -1;
+    }
+    sleep(10);
+    ret = lynq_gnss_stop();
+    if(ret < 0) {
+        printf("lynq_gnss_stop FAIL.	ret:%d\n",ret);
+        return -1;
+    }
+    ret = lynq_gnss_deinit();
+    if(ret < 0) {
+        printf("lynq_gnss_deinit FAIL.	ret:%d\n",ret);
+        return -1;
+    }
+    return 0;
+}
+
+#else
+
+int main(int argc, char *argv[])
+{
+    int ret;
+    int opt;
+    char dev_file[12] = {0};
+
+    while(1)
+    {
+        printf("=========gnss main=========\n"
+            "\t0 exit\n"
+            "\t1 gnss init\n"
+            "\t2 gnss add callback function\n"
+            "\t3 gnss start\n"
+            "\t4 gnss stop\n"
+            "\t5 gnss deinit\n"
+            "\t6 agps down\n"
+            "please input operator: >> ");
+        scanf("%d", &opt);
+        switch (opt)
+        {
+        case 0:
+            printf("main exit\n");
+            return 0;
+        case 1:
+            ret = lynq_gnss_init();
+            if(ret < 0)
+            {
+                printf("lynq_gnss_init FAIL.	ret:%d\n",ret);
+                return -1;
+            }
+            opt = 0;
+            break;
+        case 2:
+        {
+
+            lynq_gnss_callback_reg(gnss_handler_cb);
+            break;
+        }
+        case 3:
+        {
+            lynq_gnss_start();
+            break;
+        }
+        case 4:
+        {
+            lynq_gnss_stop();
+            break;
+        }
+        case 5:
+        {
+            lynq_gnss_deinit();
+            break;
+        }
+        case 6:
+        {
+            ret = lynq_gnss_agps_dataconnopen();
+            if(ret < 0)
+            {
+                printf("lynq_gnss_agps_dataconnopen FAIL. ret:%d\n", ret);
+                return -1;
+            }
+            break;
+        }
+        default:
+            break;
+        }
+    }
+
+    return 0;
+}
+#endif
diff --git a/mbtk/test/lynq_sms_test.c b/mbtk/test/lynq_sms_test.c
new file mode 100755
index 0000000..e16893d
--- /dev/null
+++ b/mbtk/test/lynq_sms_test.c
@@ -0,0 +1,126 @@
+/**
+ *   \file dtmf_test.c
+ *   \brief A Documented file.
+ *
+ *  Detailed description
+ *   \Author:  jinLuo
+ *   \Version: 1.0.0
+ *   \Date: 2022-12-1
+ */
+
+/******************************************************************************\
+ *   Include files
+\******************************************************************************/
+#include <pthread.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <poll.h>
+#include <stdlib.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "lynq/lynq_sms_api.h"
+
+
+int main(int argc, char *argv[])
+{
+    char operator[20];
+    int opt;
+    int ret, uToken; 
+	char serNum[50] = {0};
+
+    while(1)
+    {
+        printf("=========audio main=========\n"
+            "\t0 exit\n"
+            "\t1 sms init\n"
+            "\t2 send sms\n"
+            "\t3 wait receive new sms\n"
+            "\t4 delete sms(int index);\n"
+            "\t5 list sms\n"
+            "\t6 query sms storage status\n"
+            "\t7 query service number\n"
+            "\t8 set service number\n"
+            "\t9 deinit sms\n"
+            "operator: >> ");
+        fgets(operator, sizeof(operator), stdin);
+        fflush(stdin);
+        opt = atoi(operator);
+        switch (opt)
+        {
+        case 0:
+            printf("main exit\n");
+            return 0;
+        case 1:
+            lynq_init_sms(uToken);
+            break;
+        case 2:
+			printf("please input volume (0~1): \n");
+            fgets(operator, sizeof(operator), stdin);
+            fflush(stdin);
+            opt = atoi(operator);
+			if(opt)
+			{
+				lynq_send_sms("15775590631", 1, "nihaoma,wohenhao"); //text mode
+			}
+			else{
+				lynq_send_sms("29", 0, "0891683108200805F011000D91685177550996F70008A80E4F60597D5417FF1F62115F88597D");  //pud mode
+			}
+            break;
+        case 3:
+            lynq_wait_receive_new_sms(&uToken);
+            break;
+		case 4:
+            printf("please input volume (0~100): \n");
+            fgets(operator, sizeof(operator), stdin);
+            fflush(stdin);
+            opt = atoi(operator);
+			lynq_delete_sms(opt);
+            break;
+		case 5:
+			printf("please input index (0~50): \n");
+            fgets(operator, sizeof(operator), stdin);
+            fflush(stdin);
+            opt = atoi(operator);
+            lynq_list_sms(1, opt, "ALL" ); 
+				//opt : 0 ; Query all stored SMS messages
+				//opt : > 0 ; Gets the content of the SMS message starting from the index number 
+			break;
+		case 6:
+            lynq_query_sms_storage_status();
+			break;
+        case 7:
+            ret = lynq_get_smsc_address(serNum);
+            if(!ret)
+                printf("get_smsc:%s\n", serNum);
+            break;
+        case 8:
+            printf("please input service num: \n");
+            fgets(operator, sizeof(operator), stdin);
+            fflush(stdin);
+            ret= lynq_set_smsc_address(operator);
+            break;
+        case 9:
+            lynq_deinit_sms();
+            break;
+        default:
+            break;
+        }
+    }
+
+    return 0;
+}
diff --git a/mbtk/test/mbtk_adc_test.c b/mbtk/test/mbtk_adc_test.c
new file mode 100755
index 0000000..2d1b689
--- /dev/null
+++ b/mbtk/test/mbtk_adc_test.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+
+#include "mbtk_adc.h"
+
+int main(int argc, char *argv[])
+{
+    int adc = mbtk_adc_get(MBTK_ADC0);
+    if(adc > 0) {
+        printf("ADC0 = %d\n", adc);
+    } else {
+        printf("Get ADC0 fail.\n");
+    }
+
+    adc = mbtk_adc_get(MBTK_ADC1);
+    if(adc > 0) {
+        printf("ADC1 = %d\n", adc);
+    } else {
+        printf("Get ADC1 fail.\n");
+    }
+    return 0;
+}
+
diff --git a/mbtk/test/mbtk_at_test.c b/mbtk/test/mbtk_at_test.c
new file mode 100755
index 0000000..a6cb361
--- /dev/null
+++ b/mbtk/test/mbtk_at_test.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+
+#include "mbtk_at.h"
+
+#define LOGE printf
+#define LOGI printf
+
+int main(int argc, char *argv[])
+{
+    if(argc != 2) {
+        LOGE("./at_test at_cmd\n");
+        return -1;
+    }
+
+    if(mbtk_at_init()) {
+        LOGE("mbtk_at_init() fail.\n");
+        return -1;
+    }
+
+    char at_rsp[2048];
+    if(!mbtk_at_send(argv[1], at_rsp, 2048)) {
+        LOGI("%s", at_rsp);
+    } else {
+        LOGE("mbtk_at_send() fail.\n");
+    }
+
+    if(mbtk_at_deinit()) {
+        LOGE("mbtk_at_deinit() fail.\n");
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/mbtk/test/mbtk_coap_test.c b/mbtk/test/mbtk_coap_test.c
new file mode 100755
index 0000000..4159a34
--- /dev/null
+++ b/mbtk/test/mbtk_coap_test.c
@@ -0,0 +1,53 @@
+#include <string.h>
+#include "mbtk_type.h"
+#include "ql/ql_vcall.h"
+#include "mbtk_coap.h"
+#include "mbtk_coap_api.h"
+
+int coap_get_method(void);
+
+int coap_post_method(void);
+
+
+int main(int argc, char *argv[])
+{
+    char operator[10];
+    int opt;
+    int    ret     = -1;
+
+	printf("coap_demo star\r\n");
+	coap_get_method();
+
+	sleep(20);
+	coap_post_method();
+
+    return 0;
+}
+
+
+int coap_get_method(void)
+{
+	int ret = -1;
+	ret = mbtk_coap_ecoapnew_exec_cmd("134.102.218.18",5683,0,0);    //server ip, port
+	mbtk_coap_ecoapmsgid_exec_cmd(1);								//set message id
+	mbtk_coap_ecoaptype_exec_cmd(0);								//set message type
+	mbtk_coap_ecoapcode_exec_cmd(1);								//set Get request method
+	mbtk_coap_ecoapopt_exec_cmd("b474657374",10);					//set option
+
+	mbtk_coap_ecoapsend_exec_cmd(1, 0, NULL);						//request Get
+	return 0;
+}
+
+
+int coap_post_method(void)
+{
+	int ret = -1;
+	ret = mbtk_coap_ecoapnew_exec_cmd("134.102.218.18",5683,0,0);     //server ip, port
+	mbtk_coap_ecoapmsgid_exec_cmd(3);            					//set message id
+	mbtk_coap_ecoaptype_exec_cmd(0);             					//set message type
+	mbtk_coap_ecoapcode_exec_cmd(2);			 					//set Post request method
+	mbtk_coap_ecoapopt_exec_cmd("b474657374",10);					//set option
+
+	mbtk_coap_ecoapsend_exec_cmd(3, 7, "1111111");  				//request post
+	return 0;
+}
diff --git a/mbtk/test/mbtk_dtmf_test.c b/mbtk/test/mbtk_dtmf_test.c
new file mode 100755
index 0000000..a21464e
--- /dev/null
+++ b/mbtk/test/mbtk_dtmf_test.c
@@ -0,0 +1,94 @@
+/**
+ *   \file dtmf_test.c
+ *   \brief A Documented file.
+ *
+ *  Detailed description
+ *   \Author:  js.wang <js.wang@mobiletek.cn>
+ *   \Version: 1.0.0
+ *   \Date: 2022-03-31
+ */
+
+/******************************************************************************\
+ *   Include files
+\******************************************************************************/
+#include <pthread.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <poll.h>
+#include <stdlib.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "mbtk_audio.h"
+
+void dtmf_cb(char dtmf)
+{
+    printf("%s:%c\n", __FUNCTION__, dtmf);
+}
+
+void audio_volume_cb(int volume)
+{
+    printf("%s:%d\n", __FUNCTION__, volume);
+}
+
+int main(int argc, char *argv[])
+{
+    char operator[10];
+    int opt;
+    mbtk_audio_client_handle_type dtmf_handle;
+
+
+    while(1)
+    {
+        printf("=========audio main=========\n"
+            "\t0 exit\n"
+            "\t1 audio init\n"
+            "\t2 audio get volume\n"
+            "\t3 audio set volume\n"
+            "\t4 audio deinit\n"
+            "operator: >> ");
+        fgets(operator, sizeof(operator), stdin);
+        fflush(stdin);
+        opt = atoi(operator);
+        switch (opt)
+        {
+        case 0:
+            printf("main exit\n");
+            return 0;
+        case 1:
+            mbtk_audio_ubus_client_init(&dtmf_handle, dtmf_cb);
+            break;
+        case 2:
+            mbtk_audio_ubus_volume_get(audio_volume_cb);
+            break;
+        case 3:
+            printf("please input volume (0~100): \n");
+            fgets(operator, sizeof(operator), stdin);
+            fflush(stdin);
+            opt = atoi(operator);
+            mbtk_audio_ubus_volume_set(opt);
+            break;
+        case 4:
+            mbtk_audio_ubus_client_deinit(dtmf_handle);
+            break;
+        default:
+            break;
+        }
+    }
+
+    return 0;
+}
diff --git a/mbtk/test/mbtk_ftp_test.c b/mbtk/test/mbtk_ftp_test.c
new file mode 100755
index 0000000..481108d
--- /dev/null
+++ b/mbtk/test/mbtk_ftp_test.c
@@ -0,0 +1,144 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "mbtk_type.h"
+#include "mbtk_ftp.h"
+#include "mbtk_log.h"
+#include "mbtk_str.h"
+
+static int ftp_cmd_process(mbtk_ftp_handle handle, const char *cmd)
+{
+    if(!strncasecmp(cmd, "download", 8)) {
+        // Download file: /data
+        uint32 len_count = 0;
+        uint32 len;
+        int download_time = 0;
+
+        uint32 file_size = mbtk_ftp_file_size(handle, "/Luo/Luo_up.txt");
+        if(file_size > 0)
+        {
+            printf("Will download file:/data[%d]\n", file_size);
+            // Start download
+            len = mbtk_ftp_download_start(handle, "/Luo/Luo_up.txt", "/tmp/ftp_data", NULL);
+            if(len > 0)
+            {
+                len_count += len;
+                download_time++;
+                printf("Download[time-%d] size:[%d / %d]\n", download_time, len_count, file_size);
+                while (len_count < file_size
+                       && download_time <= 10 // Try 10 times.
+                       && (len = mbtk_ftp_download_continue(handle)) > 0)
+                {
+                    len_count += len;
+                    download_time++;
+                    printf("Download[time-%d] size:[%d / %d]\n", download_time, len_count, file_size);
+                }
+
+                printf("Download complete - [%d / %d].\n",len_count, file_size);
+            }
+            else
+            {
+                printf("FTP download fail[%d / %d].\n",len_count, file_size);
+                return -1;
+            }
+        }else {
+            printf("File error.\n");
+            return -1;
+        }
+    }
+    else if(!strncasecmp(cmd, "upload", 6)) {
+        int len = 0;
+        len = mbtk_ftp_upload_start(handle, "/Luo/up_ftp3.txt", "/tmp/ftp_data", 0);
+        if( len != 0)
+        {
+            printf("FTP update fail\n");
+            return -1;
+        }
+        else
+        {
+            printf("FTP update success\n");
+        }
+    }
+    else if(!strncasecmp(cmd, "pwd", 3)) {
+        char path[50] = {0};
+        mbtk_ftp_error_enum err = mbtk_ftp_pwd(handle, path);
+        if(FTP_ERR_SUCCESS != err) {
+            printf("mbtk_ftp_pwd() fail:%d\n", err);
+            return -1;
+        }
+
+        printf("PWD : %s\n", path);
+    } else if(!strncasecmp(cmd, "cd ", 3)) {
+        char path[50] = {0};
+        memcpy(path, cmd + 3, strlen(cmd) - 3);
+        mbtk_ftp_error_enum err = mbtk_ftp_cd(handle, path);
+        if(FTP_ERR_SUCCESS != err) {
+            printf("mbtk_ftp_cd() fail:%d\n", err);
+            return -1;
+        }
+
+        printf("cd %s\n", path);
+    } else if(!strncasecmp(cmd, "ls", 2)) {
+        mbtk_ftp_file_info_s list_head;
+        mbtk_ftp_error_enum err = mbtk_ftp_dir_ls(handle, &list_head);
+        if(FTP_ERR_SUCCESS != err) {
+            printf("mbtk_ftp_dir_ls() fail:%d\n", err);
+            return -1;
+        }
+
+        mbtk_ftp_file_info_s *f_ptr = list_head.next;
+        while(f_ptr && !str_empty(f_ptr->name)) {
+            printf("%s, %s, %d\n", f_ptr->name, f_ptr->is_file ? "F" : "D", f_ptr->size);
+            f_ptr = f_ptr->next;
+        }
+    } else {
+        printf("Unknow CMD.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    mbtk_ftp_handle handle = mbtk_ftp_init("58.246.1.50", 6521, FTP_AUTH_TYPE_NON, false, false);
+    if(handle < 0) {
+        printf("mbtk_ftp_init() fail.\n");
+        return -1;
+    }
+
+    mbtk_ftp_error_enum err = mbtk_ftp_login(handle, " FTP_TST", "FTPTST_0320");
+    if(err != FTP_ERR_SUCCESS) {
+        printf("mbtk_ftp_login() fail:%d\n", err);
+        goto ftp_exit;
+    }
+
+    printf("Login success.\nCMD:");
+
+    char cmd[50];
+    while(1) {
+        memset(cmd, 0, 50);
+        gets(cmd);
+        if(!strcasecmp(cmd, "q")) {
+            break;
+        } else {
+            ftp_cmd_process(handle, cmd);
+        }
+
+        printf("CMD:");
+    }
+
+    printf("FTP test success.\n");
+ftp_quit:
+    mbtk_ftp_quit(handle);
+ftp_exit:
+    mbtk_ftp_deinit(handle);
+    printf("FTP test complete.\n");
+    return 0;
+
+}
+
diff --git a/mbtk/test/mbtk_http_test.c b/mbtk/test/mbtk_http_test.c
new file mode 100755
index 0000000..edfd81d
--- /dev/null
+++ b/mbtk/test/mbtk_http_test.c
@@ -0,0 +1,74 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#define LOG_TAG "mbtk_http"
+#include "mbtk_type.h"
+#include "mbtk_http.h"
+#include "mbtk_log.h"
+
+
+static void http_data_cb_func(
+    int session_id, mbtk_http_data_type_enum type,
+    void *data,int data_len)
+{
+    if(type == MBTK_HTTP_DATA_HEADER) {
+        printf("Header(%d):%s\n",data_len,(char*)data);
+    } else if(type == MBTK_HTTP_DATA_CONTENT) {
+        printf("Data(%d):%s\n",data_len,(char*)data);
+    } else {
+        LOGI(">>>>>Complete<<<<<\n");
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    if(argc != 2) {
+        LOGE("ARG error.");
+        return -1;
+    }
+
+    LOGI("MBTK HTTP Version 1.1");
+
+    int http_handle = mbtk_http_handle_get(TRUE, http_data_cb_func);
+    if(http_handle < 0)
+    {
+        LOGE("mbtk_http_handle_get() fail.");
+        return -1;
+    }
+
+    int http_session = mbtk_http_session_create(http_handle,HTTP_OPTION_GET,HTTP_VERSION_1_1);
+    if(http_handle < 0)
+    {
+        LOGE("mbtk_http_session_create() fail.");
+        return -1;
+    }
+
+    if(mbtk_http_session_url_set(http_handle, http_session, argv[1])) {
+        LOGE("mbtk_http_session_url_set() fail.\n");
+        return -1;
+    }
+
+    const mbtk_http_session_t* session = mbtk_http_session_get(http_handle, http_session);
+    LOGI("HTTP:%d,%s,%d,%s\n",session->option,session->host,session->port,session->uri);
+
+
+    if(mbtk_http_session_start(http_handle, http_session)) {
+        LOGE("mbtk_http_session_start() fail.\n");
+        return -1;
+    }
+
+
+    if(mbtk_http_handle_free(http_handle))
+    {
+        LOGE("mbtk_http_handle_free() fail.");
+        return -1;
+    }
+
+    LOGI("MBTK_HTTP exit.");
+    return 0;
+
+}
diff --git a/mbtk/test/mbtk_info_test.c b/mbtk/test/mbtk_info_test.c
new file mode 100755
index 0000000..73a7050
--- /dev/null
+++ b/mbtk/test/mbtk_info_test.c
@@ -0,0 +1,1281 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <sys/epoll.h>
+#include <string.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include "mbtk_info_api.h"
+#include "lynq/lynq_sms_api.h"
+
+//#include "lynq_net_api.h"
+
+static mbtk_info_handle_t* info_handle = NULL;
+
+void net_state_change_cb(const void* data, int data_len)
+{
+
+}
+
+void call_state_change_cb(const void* data, int data_len)
+{
+    mbtk_call_info_t *reg = (mbtk_call_info_t *)data;
+    switch (reg->call_wait)
+    {
+        case MBTK_CLCC:
+            printf("\r\nRING : %d, %d, %d, %d, %d, %s, %d\r\n", reg->dir1, reg->dir, reg->state, reg->mode, reg->mpty, reg->phone_number, reg->type);
+            break;
+        case MBTK_DISCONNECTED:
+            printf("\r\nRING : call dis connected!\r\n");
+            break;
+        case MBTK_CPAS:
+            printf("\r\nCALL : Call state = %d\r\n", reg->pas);
+            /*
+                MBTK_CALL_RADY,                 //MT allows commands from TA/TE
+                MBTK_CALL_UNAVAILABLE,          //MT does not allow commands from TA/TE
+                MBTK_CALL_UNKNOWN,              //MT is not guaranteed to respond to instructions
+                MBTK_CALL_RINGING,              //MT is ready for commands from TA/TE, but the ringer is active
+                MBTK_CALL_PROGRESS,             //MT is ready for commands from TA/TE, but a call is in progress
+                MBTK_CALL_ASLEEP,               //MT is unable to process commands from TA/TE because it is in a low functionality state
+                MBTK_CALL_ACTIVE,
+            */
+           switch (reg->pas)
+           {
+                case MBTK_CALL_RADY:
+                    printf("CALL: call READY\r\n");
+                    break;
+                case MBTK_CALL_UNAVAILABLE:
+                    printf("CALL: call unavaliable\r\n");
+                    break;
+                case MBTK_CALL_UNKNOWN:
+                    printf("CALL: call unknown\r\n");
+                    break;
+                case MBTK_CALL_RINGING:
+                    printf("CALL: call ringing\r\n");
+                    break;
+                case MBTK_CALL_PROGRESS:
+                    printf("CALL: call progress\r\n");
+                    break;
+                case MBTK_CALL_ASLEEP:
+                    printf("CALL: call asleep\r\n");
+                    break;
+                case MBTK_CALL_ACTIVE:
+                    printf("CALL: call active\r\n");
+                    break;
+                default:
+                    printf("\r\n");
+                    break;
+           }
+            break;
+        default:
+            printf("\r\nRING : None call_wait = %d\r\n", reg->call_wait);
+            break;
+    }
+    /*
+    if(reg->call_wait == )         //CLCC
+    {
+        printf("\r\nRING : %d, %d, %d, %d, %d, %s, %d\r\n", reg->dir1, reg->dir, reg->state, reg->mode, reg->mpty, reg->phone_number, reg->type);
+    }
+    else if(reg->call_wait == 2)    //Disconnected
+    {
+        printf("\r\nRING : call dis connected!\r\n");
+    }
+    else
+    {
+        printf("\r\nRING : None\r\n");
+    }
+    */
+}
+
+void sms_state_change_cb(const void* data, int data_len)
+{
+    LOGV("sms_state_change_cb()----------start\n");
+	uint8 *ptr = (uint8*)data;
+		printf("3sms_state_change_cb() : %s\n", ptr);
+
+	struct SMS_Struct s = PDUDecoding(ptr);
+	printf("服务中心地址: %s\n", s.SCA);
+    printf("发送方地址: %s\n", s.OA);
+    printf("服务中心时间戳: %s\n", s.SCTS);
+    printf("消息内容: %s\n", s.UD);
+    printf("数据编码方案: %s\n", DSC_to_msg(s.DCS));
+
+}
+
+void radio_state_change_cb(const void* data, int data_len)
+{
+    uint8 *ptr = (uint8*)data;
+    printf("Radio state : %d\n", *ptr);
+}
+
+void sim_state_change_cb(const void* data, int data_len)
+{
+    uint8 *ptr = (uint8*)data;
+    printf("SIM state : %d\n", *ptr);
+}
+
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+static void test2(int is_ipv6, char *ip)
+{
+    char ipaddr[20] = {0};
+	if(is_ipv6) {
+        struct in6_addr sin_addr;
+        if(inet_pton(AF_INET6, ip, &sin_addr) < 0) {
+            printf("inet_pton() fail.\n");
+        } else {
+		    log_hex("IPv6", &sin_addr, sizeof(struct in6_addr));
+        }
+	} else {
+	    struct in_addr sin_addr;
+        if(inet_pton(AF_INET, ip, &sin_addr) < 0) {
+            printf("inet_pton() fail.\n");
+        } else {
+		    log_hex("IPv4", &sin_addr, sizeof(struct in_addr));
+        }
+	}
+}
+
+
+static void help()
+{
+    printf("version: Get version.\n");
+    printf("imei: Get IMEI.\n");
+    printf("sn: Get SN.\n");
+    printf("meid: Get MEID.\n");
+    printf("volte: Get VoLTE state.\n");
+    printf("volte 0: Close VoLTE.\n");
+    printf("volte 1: Open VoLTE.\n");
+    printf("radio: Get radio state.\n");
+    printf("radio 0: Close radio.\n");
+    printf("radio 1: Open radio.\n");
+    printf("sim: Get sim state.\n");
+    printf("avail_net: Get available network.\n");
+    printf("imsi: Get IMSI.\n");
+    printf("iccid: Get ICCID.\n");
+    printf("pn: Get Phone Number.\n");
+    printf("sel_mode: Get network select mode.\n");
+    printf("sel_mode <sel_mode> <net_type> <plmn>: Set network select mode.\n");
+    printf("band: Get current bands.\n");
+    printf("band support: Get support bands.\n");
+    printf("band <net_pref> <gsm_band> <umts_band> <tdlte_band> <fddlte_band>: Set current bands.\n");
+    printf("signal: Get network signal.\n");
+    printf("reg: Get network registe information.\n");
+    printf("cell: Get current cell information.\n");
+    printf("shutdown <0,1,2>: reboot/poweroff/halt system.\n");
+    printf("power_sim <0,1>: Power off/on sim.\n");
+    printf("temp <0,1>: Get SOC/RF temperature.\n");
+    printf("time <0,1,2> YYYY-MM-DD HH:MM:SS : Set system time as CELL/NTP/User.\n");
+    printf("apn : Get current apns.\n");
+    printf("apn <cid> <1/2/3/4> <apn> : Set apn.\n");
+    printf("data_call <0/1/2> <cid> <timeout>: Stop/Start/State data call.\n");
+    printf("call: Call the phone number.\n");
+    printf("answer: Answer the phone call.\n");
+    printf("hangup: Hang up all phone call. No id.\n");
+    printf("hangup 0: Hang up waiting or background phone call.\n");
+    printf("hangup 1: Hang up a phone call.\n");
+    printf("hangup 2: Hang up a phone call.\n");
+    printf("hangup 3: Hangup foreground resume background call.\n");
+    printf("waitin: Returns the list of current calls.\n");
+    printf("mute: Get mute state.\n");
+    printf("mute 0: Close mute.\n");
+    printf("mute 1: Open mute.\n");
+    printf("dtmf : Set dtmf character[0, 1, 2, ..., A, B, C, D, *, #], duration [300-600].\n   Such as: dtmf 0 300\n");
+}
+
+static void sig_process(int sig)
+{
+    LOGI("I got signal %d\n", sig);
+    switch(sig)
+    {
+        case SIGINT: // Ctrl + C
+        {
+            LOGI("Exit by SIGINT.\n");
+            mbtk_info_handle_free(&info_handle);
+            exit(0);
+        }
+        case SIGQUIT: // Ctrl + \ (类似 SIGINT ,但要产生core文件)
+        {
+            LOGI("Exit by SIGQUIT.\n");
+            mbtk_info_handle_free(&info_handle);
+            exit(0);
+        }
+        case SIGTERM:// 默认kill   (同 SIGKILL ,但 SIGKILL 不可捕获)
+        {
+            LOGI("Exit by SIGTERM.\n");
+            mbtk_info_handle_free(&info_handle);
+            exit(0);
+        }
+        case SIGTSTP:// Ctrl + Z (同 SIGSTOP ,但 SIGSTOP 不可捕获)
+        {
+            LOGI("Exit by SIGTSTP.\n");
+            exit(0);
+        }
+        case SIGSEGV: // 如空指针
+        {
+            LOGI("Exit by SIGSEGV.\n");
+            exit(0);
+        }
+        default:
+        {
+            LOGI("Unknown sig:%d\n",sig);
+            break;
+        }
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    signal(SIGINT, sig_process);
+    signal(SIGQUIT, sig_process);
+    signal(SIGTERM, sig_process);
+    //signal(SIGTSTP, sig_process);
+    //signal(SIGSEGV, sig_process);
+
+    mbtk_log_init(NULL,"INFO_CLI");
+
+    //test2(0, "192.168.1.198");
+    //test2(1, "2409:8162:140:cd3c:1:2:1494:72ba");
+    //test2(1, "254.128.0.0.0.0.0.0.0.1.0.2.144.5.212.239");
+    //test2(1, "2400:3200::1");
+
+    info_handle = mbtk_info_handle_get();
+    if(!info_handle)
+    {
+        return -1;
+    }
+
+    mbtk_net_state_change_cb_reg(info_handle, net_state_change_cb);
+    mbtk_call_state_change_cb_reg(info_handle, call_state_change_cb);
+    mbtk_sms_state_change_cb_reg(info_handle, sms_state_change_cb);
+    mbtk_radio_state_change_cb_reg(info_handle, radio_state_change_cb);
+    mbtk_sim_state_change_cb_reg(info_handle, sim_state_change_cb);
+
+    printf(">>>>>>>>>>>>>>>>>>>>>>>>Enter cmd:\n");
+    char cmd[100];
+    while(1)
+    {
+        memset(cmd, 0, 100);
+        int err;
+        if(fgets(cmd, 100, stdin))
+        {
+            char *ptr = cmd + strlen(cmd) - 1;
+            while(ptr >= cmd && (*ptr == '\r' || *ptr == '\n'))
+            {
+                *ptr-- = '\0';
+            }
+            if(!strncasecmp(cmd, "version", 7))
+            {
+                char version[50] = {0};
+                err = mbtk_version_get(info_handle, version);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Version : %s\n", version);
+                }
+            } else if(!strncasecmp(cmd, "imei", 4)){
+                char imei[50] = {0};
+                err = mbtk_imei_get(info_handle, imei);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("IMEI : %s\n", imei);
+                }
+            } else if(!strncasecmp(cmd, "sn", 2)){
+                char sn[50] = {0};
+                err = mbtk_sn_get(info_handle, sn);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("SN : %s\n", sn);
+                }
+            } else if(!strncasecmp(cmd, "meid", 4)){
+                char meid[50] = {0};
+                err = mbtk_meid_get(info_handle, meid);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("MEID : %s\n", meid);
+                }
+            } else if(!strncasecmp(cmd, "volte", 5)){ // "volte" or "volte 0" or "volte 1"
+                int volte;
+                if(!strcasecmp(cmd, "volte")) { // Get
+                    err = mbtk_volte_state_get(info_handle, &volte);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE : %d\n", volte);
+                    }
+                } else { // Set
+                    if(!strcasecmp(cmd, "volte 1")) { // Open VoLTE
+                        volte = 1;
+                    } else { // Close VoLTE
+                        volte = 0;
+                    }
+                    err = mbtk_volte_state_set(info_handle, volte);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE set success\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "radio", 5)){ // "radio" or "radio 0" or "radio 1"
+                int radio;
+                if(!strcasecmp(cmd, "radio")) { // Get
+                    err = mbtk_radio_state_get(info_handle, &radio);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Radio : %d\n", radio);
+                    }
+                } else { // Set
+                    if(!strcasecmp(cmd, "radio 1")) { // Open radio
+                        radio = 1;
+                    } else { // Close radio
+                        radio = 0;
+                    }
+                    err = mbtk_radio_state_set(info_handle, radio);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Radio set success\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "sim", 3)){
+                mbtk_sim_state_enum sim;
+                err = mbtk_sim_state_get(info_handle, &sim);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Sim : %d\n", sim);
+                }
+            } else if(!strncasecmp(cmd, "imsi", 4)){
+                char imsi[50] = {0};
+                err = mbtk_imsi_get(info_handle, imsi);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("IMSI : %s\n", imsi);
+                }
+            } else if(!strncasecmp(cmd, "iccid", 5)){
+                char iccid[50] = {0};
+                err = mbtk_iccid_get(info_handle, iccid);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("ICCID : %s\n", iccid);
+                }
+            } else if(!strncasecmp(cmd, "pn", 2)){
+                char phone_number[50] = {0};
+                err = mbtk_phone_number_get(info_handle, phone_number);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Phone Number : %s\n", phone_number);
+                }
+            } else if(!strncasecmp(cmd, "avail_net", 9)){
+                list_node_t* net_list = NULL;
+                err = mbtk_available_net_get(info_handle, &net_list);
+                if(err || net_list == NULL) {
+                    printf("Error : %d\n", err);
+                } else {
+                    mbtk_net_info_t* net = NULL;
+                    list_first(net_list);
+                    while ((net = (mbtk_net_info_t*) list_next(net_list)))
+                    {
+                        printf("Net : %d, %d, %d, %d\n", net->net_sel_mode, net->net_type, net->net_state, net->plmn);
+                    }
+                }
+                list_free(net_list);
+            } else if(!strncasecmp(cmd, "cell", 4)){
+                char *ptr = strstr(cmd, ",");	 //CPMS,ME,ME,ME
+				if(ptr == NULL)
+				{
+                    printf("ptr == NULL\n");
+                    list_node_t* cell_list = NULL;
+                    int type;
+                    err = mbtk_cell_get(info_handle, &type, &cell_list);
+                    if(err || cell_list == NULL) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        list_first(cell_list);
+                        mbtk_cell_info_t* cell = (mbtk_cell_info_t*) list_next(cell_list);
+                        if(cell) { // Current server cell.
+                            switch(type)
+                            {
+                                case 0:
+                                    printf("GSM : lac=%d, ci=%d, arfcn=%d, bsic=%d\n", cell->value1, cell->value2, cell->value3, cell->value4);
+                                    break;
+                                case 1:
+                                    printf("UMTS : lac=%d, ci=%d, arfcn=%d\n", cell->value1, cell->value2, cell->value3);
+                                    break;
+                                case 2:
+                                    printf("LTE : tac=%d, PCI=%d, dlEuarfcn=%d, ulEuarfcn=%d, band=%d\n", cell->value1, cell->value2, cell->value3, cell->value4, cell->value5);
+                                    break;
+                                default:
+                                    break;
+                            }
+                        }
+                        while ((cell = (mbtk_cell_info_t*) list_next(cell_list)))
+                        {
+                            switch(type)
+                            {
+                                case 0:
+                                    printf("CELL : %d, %d, %d, %d, %d", cell->value1, cell->value2, cell->value3, cell->value4, cell->value5);
+                                    break;
+                                case 1:
+                                    printf("CELL : lac=%d, ci=%d, arfcn=%d\n", cell->value1, cell->value2, cell->value3);
+                                    break;
+                                case 2:
+                                    printf("CELL : phyCellId=%d, euArfcn=%d, rsrp=%d, rsrq=%d\n", cell->value1, cell->value2, cell->value3, cell->value4);
+                                    break;
+                                default:
+                                    break;
+                            }
+                        }
+                    }
+                    list_free(cell_list);
+                }
+                else{
+                    char *ptr = strstr(cmd, ",");	 //cell,2,3,,40936,430
+					char mem[50]={0};
+					char resp[1024] = {0};
+					if(ptr != NULL)
+					{
+						ptr++;
+						memset(mem, 0, sizeof(mem));
+						memcpy(mem, ptr, strlen(ptr));
+						printf("cell:%s\n", mem);
+					}
+					printf("cell_mem: %s \n", mem);
+
+					memset(resp, 0, sizeof(resp));
+					err = mbtk_cell_set(info_handle, mem, resp);
+					if(err) {
+						printf("Error : %d\n", err);
+					} else {
+						printf("cell set . resp:%s\n", resp);
+					}
+
+                }
+            } else if(!strncasecmp(cmd, "sel_mode", 8)){ // "sel_mode" or "sel_mode 1 7 46000"
+                mbtk_net_info_t net;
+                memset(&net, 0, sizeof(mbtk_net_info_t));
+                if(!strcasecmp(cmd, "sel_mode")) { // Get
+                    err = mbtk_net_sel_mode_get(info_handle, &net);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Net : %d, %d, %d, %d\n", net.net_sel_mode, net.net_type, net.net_state, net.plmn);
+                    }
+                } else { // Set
+                    char *ptr = strstr(cmd, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    net.net_sel_mode = (uint8)atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    net.net_type = (uint8)atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    net.plmn = (uint32)atoi(ptr);
+
+                    err = mbtk_net_sel_mode_set(info_handle, &net);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Net select mode set success\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "band", 4)){ // "band" or "band support" or "band 0 79 147 482 524503"
+                mbtk_band_info_t band;
+                if(!strcasecmp(cmd, "band")) { // Get
+                    err = mbtk_current_band_get(info_handle, &band);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Band : %d, %d, %d, %d, %d\n", band.net_pref, band.gsm_band, band.umts_band, band.tdlte_band, band.fddlte_band);
+                    }
+                } else if(!strcasecmp(cmd, "band support")) { // Get
+                    err = mbtk_support_band_get(info_handle, &band);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Band : %d, %d, %d, %d, %d\n", band.net_pref, band.gsm_band, band.umts_band, band.tdlte_band, band.fddlte_band);
+                    }
+                } else { // "band 0 79 147 482 524503"
+                    char *ptr = strstr(cmd, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    band.net_pref = (uint8)atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    band.gsm_band = (uint16)atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    band.umts_band = (uint16)atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    band.tdlte_band = (uint32)atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    band.fddlte_band = (uint32)atoi(ptr);
+
+                    err = mbtk_current_band_set(info_handle, &band);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Band set success\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "signal", 6)){
+                mbtk_signal_info_t signal;
+                err = mbtk_net_signal_get(info_handle, &signal);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Signal : %d, %d, %d, %d, %d, %d, %d, %d\n", signal.type, signal.rssi, signal.rxlev, signal.ber,
+                        signal.rscp, signal.ecno, signal.rsrq, signal.rsrp);
+                }
+            } else if(!strncasecmp(cmd, "reg", 3)){
+                mbtk_net_reg_info_t reg;
+                err = mbtk_net_reg_get(info_handle, &reg);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("REG : call_state=%d, data_state=%d, ims_state=%d, net_type=%d, %04x, %08x\n", reg.call_state, reg.data_state, reg.ims_state, reg.type, reg.lac, reg.ci);
+                }
+            } else if(!strncasecmp(cmd, "call", 4)){
+                char phone_number[12];
+                char *ptr = strstr(cmd, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                memset(phone_number,0,strlen(phone_number));
+                memcpy(phone_number,ptr,strlen(ptr));
+                printf("phone number is: %s\n",phone_number);
+                err = mbtk_call_start(info_handle, phone_number);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Call success.\n");
+                }
+            } else if(!strncasecmp(cmd, "answer", 6)){
+                err = mbtk_call_answer(info_handle);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Call success.\n");
+                }
+            } else if(!strncasecmp(cmd, "hangup", 6)){
+                int phone_id;
+                if(!strcasecmp(cmd, "hangup")) { // hang up all
+                    err = mbtk_call_hang(info_handle);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Call hang up all.\n");
+                    }
+                } else if(!strcasecmp(cmd, "hangup 0")) {
+                    err = mbtk_waiting_or_background_call_hang(info_handle);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Call hang up waiting or background.\n");
+                    }
+                } else if(!strcasecmp(cmd, "hangup 3")) {
+                    err = mbtk_foreground_resume_background_call_hang(info_handle);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Call hang up foreground resume background.\n");
+                    }
+                } else {
+                    if(!strcasecmp(cmd, "hangup 1")) { // hang up a call
+                        phone_id = 1;
+                    } else if(!strcasecmp(cmd, "hangup 2")) {
+                        phone_id = 2;
+                    } else {
+                        printf("Error : Invalid input\n");
+                    }
+                    err = mbtk_a_call_hang(info_handle, phone_id);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("A Call hang up.\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "waitin", 6)){
+                mbtk_call_info_t reg;
+                err = mbtk_call_reg_get(info_handle, &reg);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    if(reg.call_wait == 0) {
+                        printf("No call ring\n");
+                    }
+                    else {
+                        printf("RING : %d, %d, %d, %d, %d, %s, %d\n", reg.dir1, reg.dir, reg.state, reg.mode, reg.mpty, reg.phone_number, reg.type);
+                    }
+                }
+            } else if(!strncasecmp(cmd, "mute", 4)){ // "mute" or "mute 0" or "mute 1"
+                int mute;
+                if(!strcasecmp(cmd, "mute")) { // Get
+                    err = mbtk_mute_state_get(info_handle, &mute);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("mute : %d\n", mute);
+                    }
+                } else { // Set
+                    if(!strcasecmp(cmd, "mute 1")) { // on mute
+                        mute = 1;
+                    } else { // off mute
+                        mute = 0;
+                    }
+                    err = mbtk_mute_state_set(info_handle, mute);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("mute set success\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "DTMF", 4)){ // valid character: (0, 1, ..., 9, A, B, C, D, *, #)
+
+                mbtk_call_dtmf_info_t reg;
+
+                char *ptr = strstr(cmd, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                reg.character = *ptr;
+
+                ptr = strstr(ptr, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                reg.duration = (uint32)atoi(ptr);
+                printf("DTMF character is: %c,%d\n",reg.character, reg.duration);
+                err = mbtk_dtmf_send(info_handle, &reg);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("DTMF success.\n");
+                }
+            } else if(!strncasecmp(cmd, "shutdown", 8)){
+                if(!strcasecmp(cmd, "shutdown 0")) {
+                    err = mbtk_system_reboot(0);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Success.\n");
+                    }
+                } else if(!strcasecmp(cmd, "shutdown 1")) {
+                    err = mbtk_system_reboot(1);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Success.\n");
+                    }
+                } else if(!strcasecmp(cmd, "shutdown 2")) {
+                    err = mbtk_system_reboot(2);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Success.\n");
+                    }
+                } else {
+                    printf("Error.");
+                }
+            } else if(!strncasecmp(cmd, "power_sim", 9)){
+                if(!strcasecmp(cmd, "power_sim 0")) {
+                    err = mbtk_sim_power_set(0);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Success.\n");
+                    }
+                } else if(!strcasecmp(cmd, "power_sim 1")) {
+                    err = mbtk_sim_power_set(1);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Success.\n");
+                    }
+                } else {
+                    printf("Error.");
+                }
+            } else if(!strncasecmp(cmd, "temp", 4)){
+                int temp;
+                if(!strcasecmp(cmd, "temp 0")) {
+                    err = mbtk_temp_get(info_handle, 0, &temp);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("SOC : %d\n", temp);
+                    }
+                } else if(!strcasecmp(cmd, "temp 1")) {
+                    err = mbtk_temp_get(info_handle, 1, &temp);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("RF : %d\n", temp);
+                    }
+                } else {
+                    printf("Error.");
+                }
+            } else if(!strncasecmp(cmd, "time", 4)){
+                if(!strcasecmp(cmd, "time 0")) {
+                    err = mbtk_time_set(info_handle, 0, NULL);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Success.\n");
+                    }
+                } else if(!strcasecmp(cmd, "time 1")) {
+                    err = mbtk_time_set(info_handle, 1, NULL);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Success.\n");
+                    }
+                } else if(!strncasecmp(cmd, "time 2 ", 7)) {
+                    err = mbtk_time_set(info_handle, 2, cmd + 7);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Success.\n");
+                    }
+                } else { // Get time type.
+                    int time_type;
+                    err = mbtk_time_get(info_handle, &time_type);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Time type:%d.\n", time_type);
+                    }
+                }
+            } else if(!strncasecmp(cmd, "apn", 3)){
+                if(!strcasecmp(cmd, "apn")) { // Get apn
+                #define APN_MAX 10
+                    mbtk_apn_info_t apns[APN_MAX];
+                    int apn_num = APN_MAX;
+                    err = mbtk_apn_get(info_handle, &apn_num, apns);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("APN Num:%d\n", apn_num);
+                        int i = 0;
+                        while(i < apn_num) {
+                            printf("APN : %d, %s, %s\n", apns[i].cid, apn2str(apns[i].ip_type), apns[i].apn);
+                            i++;
+                        }
+                    }
+                } else { // apn <cid> <0/1/2/3> <apn>
+                    char *ptr = strstr(cmd, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    int cid = atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    mbtk_ip_type_enum ip_type = (mbtk_ip_type_enum)atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    char *apn  = ptr;
+
+                    err = mbtk_apn_set(info_handle, cid, ip_type, apn, NULL, NULL, NULL);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("APN set success\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "data_call", 9)){ // data_call <0/1/2> <cid> <timeout>
+                // data_call <0/1/2> <cid> <timeout>
+                char *ptr = strstr(cmd, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                mbtk_data_call_type_enum type = (mbtk_data_call_type_enum)atoi(ptr);
+
+                ptr = strstr(ptr, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                int cid = atoi(ptr);
+
+                ptr = strstr(ptr, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                int timeout = atoi(ptr);
+
+                if(type == MBTK_DATA_CALL_START) {
+                    err = mbtk_data_call_start(info_handle, cid, 0, FALSE, timeout);
+                } else if(type == MBTK_DATA_CALL_STOP) {
+                    err = mbtk_data_call_stop(info_handle, cid, timeout);
+                } else {
+                    mbtk_ipv4_info_t ipv4;
+                    mbtk_ipv6_info_t ipv6;
+                    err = mbtk_data_call_state_get(info_handle, cid, &ipv4, &ipv6);
+                    if(!err) {
+                        if(ipv4.valid) {
+                            // log_hex("IPv4", &ipv4, sizeof(mbtk_ipv4_info_t));
+                            char ip_tmp[20];
+
+                            memset(ip_tmp, 0, 20);
+                            if(inet_ntop(AF_INET, &(ipv4.IPAddr), ip_tmp, 20) == NULL) {
+                                printf("IP error.\n");
+                            } else {
+                                printf("IP : %s\n", ip_tmp);
+                            }
+
+                            memset(ip_tmp, 0, 20);
+                            if(inet_ntop(AF_INET, &(ipv4.PrimaryDNS), ip_tmp, 20) == NULL) {
+                                printf("PrimaryDNS error.\n");
+                            } else {
+                                printf("PrimaryDNS : %s\n", ip_tmp);
+                            }
+
+                            memset(ip_tmp, 0, 20);
+                            if(inet_ntop(AF_INET, &(ipv4.SecondaryDNS), ip_tmp, 20) == NULL) {
+                                printf("SecondaryDNS error.\n");
+                            } else {
+                                printf("SecondaryDNS : %s\n", ip_tmp);
+                            }
+
+                            memset(ip_tmp, 0, 20);
+                            if(inet_ntop(AF_INET, &(ipv4.GateWay), ip_tmp, 20) == NULL) {
+                                printf("GateWay error.\n");
+                            } else {
+                                printf("GateWay : %s\n", ip_tmp);
+                            }
+
+                            memset(ip_tmp, 0, 20);
+                            if(inet_ntop(AF_INET, &(ipv4.NetMask), ip_tmp, 20) == NULL) {
+                                printf("NetMask error.\n");
+                            } else {
+                                printf("NetMask : %s\n", ip_tmp);
+                            }
+                        }
+
+                        if(ipv6.valid) {
+                            // log_hex("IPv6", &ipv6, sizeof(mbtk_ipv6_info_t));
+                            char ip_tmp[50];
+
+                            memset(ip_tmp, 0, 50);
+                            if(ipv6_2_str(&(ipv6.IPV6Addr), ip_tmp)) {
+                                printf("IP error.\n");
+                            } else {
+                                printf("IP : %s\n", ip_tmp);
+                            }
+
+                            memset(ip_tmp, 0, 50);
+                            if(ipv6_2_str(&(ipv6.PrimaryDNS), ip_tmp)) {
+                                printf("PrimaryDNS error.\n");
+                            } else {
+                                printf("PrimaryDNS : %s\n", ip_tmp);
+                            }
+
+                            memset(ip_tmp, 0, 50);
+                            if(ipv6_2_str(&(ipv6.SecondaryDNS), ip_tmp)) {
+                                printf("SecondaryDNS error.\n");
+                            } else {
+                                printf("SecondaryDNS : %s\n", ip_tmp);
+                            }
+
+                            memset(ip_tmp, 0, 50);
+                            if(ipv6_2_str(&(ipv6.GateWay), ip_tmp)) {
+                                printf("GateWay error.\n");
+                            } else {
+                                printf("GateWay : %s\n", ip_tmp);
+                            }
+
+                            memset(ip_tmp, 0, 50);
+                            if(ipv6_2_str(&(ipv6.NetMask), ip_tmp)) {
+                                printf("NetMask error.\n");
+                            } else {
+                                printf("NetMask : %s\n", ip_tmp);
+                            }
+                        }
+                    }
+                }
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("DATA_CALL success\n");
+                }
+            }else if(!strncasecmp(cmd, "cmgf", 4)){ // set mode 0: pud, 1:text
+                int mode;
+                if(!strcasecmp(cmd, "cmgf")) { // Get
+                    err = mbtk_sms_cmgf_get(info_handle, &mode);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE : %d\n", mode);
+                    }
+                } else { // Set
+                    if(!strcasecmp(cmd, "cmgf 1")) { // cmgf 1
+                        mode = 1;
+                    } else { //
+                        mode = 0;
+                    }
+                    printf("mode:%d\n", mode);
+                    sleep(2);
+                   err = mbtk_sms_cmgf_set(info_handle, mode);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE set success\n");
+                    }
+                }
+            }else if(!strncasecmp(cmd, "cpms", 4)){ // //CPMS=ME, ME, ME
+				char mem[100] = {0};
+                char resp[100] = {0};
+                if(!strcasecmp(cmd, "cpms")) { // Get
+                    err = mbtk_sms_cpms_get(info_handle, &mem);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("cpms : %s\n", mem);
+                    }
+                } else { // Set
+
+					char *ptr = strstr(cmd, ",");    //CPMS,ME,ME,ME
+                    if(ptr != NULL)
+				    {
+				    	ptr++;
+                        memset(mem, 0, sizeof(mem));
+				        memcpy(mem, ptr, strlen(ptr));
+						printf("cpms:%s\n", mem);
+				    }
+                    printf("cpms 0\n");
+
+                    memset(resp, 0, sizeof(resp));
+                    err = mbtk_sms_cpms_set(info_handle, mem, resp);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("cpms set success. resp:%s\n", resp);
+                    }
+                }
+            }else if(!strncasecmp(cmd, "cmgs", 4)){ //   AT+CMGS="10086", CMGS TEST
+                char cmgs[1024] = {0};
+                char resp[50] = {0};
+                if(!strcasecmp(cmd, "cmgs")) { // Get
+                    int mode;
+                //    err = mbtk_sms_cmgs_get(info_handle, &mode);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE : %d\n", mode);
+                    }
+                } else { // Set
+
+							/*
+							*AT+CMGS="10086", CMGS TEST	                  // Send a SMS
+							> CMGS TEST
+							+CMGS: 17
+							OK
+							*/
+
+                    char *ptr = strstr(cmd, "cmgs,");      //CMGS="10086",hf
+                    if(ptr != NULL)
+				    {
+				    	ptr = strstr(cmd, ",");
+                        ptr++;
+                        memset(cmgs, 0, sizeof(cmgs));
+				        memcpy(cmgs, ptr, strlen(ptr));
+						printf("1cmgs:%s, strlen(cmgs):%d\n", cmgs, strlen(cmgs));
+				    }
+
+					memset(resp, 0, sizeof(resp));
+                    err = mbtk_sms_cmgs_set(info_handle, cmgs, resp);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("cmgs set success . resp:%s\n", resp);
+                    }
+                }
+            }else if(!strncasecmp(cmd, "cmss", 4)){ // +CMSS=<index>[,<da>[,<toda>]]
+                char cmss[20] = {0};
+                char resp[20] = {0};
+                if(!strcasecmp(cmd, "cmgs")) { // Get
+                    printf("cmss : OK\n");
+
+                } else {
+                    char *ptr = strstr(cmd, "cmss,");    //CMSS=<index>
+                    if(ptr != NULL)
+				    {
+                        ptr = strstr(cmd, ",");
+				    	ptr++;
+                        memset(cmss, 0, sizeof(cmss));
+				        memcpy(cmss, ptr, strlen(ptr));
+						printf("1cmss:%s\n", cmss);
+				    }
+
+
+                    err = mbtk_sms_cmss_set(info_handle, cmss, resp);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("cmss set success. resp:%s\n", resp);
+                    }
+                }
+            }
+            else if(!strncasecmp(cmd, "cmgr", 4)){ // +CMGR=<index
+                int index = 0;
+                char resp[1024] = {0};
+                if(!strcasecmp(cmd, "cmgr")) { // Get
+                    printf("cmgr : OK\n");
+
+                } else {
+                    char *ptr = strstr(cmd, "cmgr,");    //+CMGR <index>
+                    if(ptr != NULL)
+				    {
+                        ptr = strstr(cmd, ",");
+                        ptr++;
+				    	index = atoi(ptr);
+				    }
+                    printf("1index:%d\n", index);
+
+                    memset(resp, 0, sizeof(resp));
+                    err = mbtk_sms_cmgr_set(info_handle, index, resp);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("cmgr set success. rep:%s\n", resp);
+                    }
+                }
+            }
+            else if(!strncasecmp(cmd, "cmgw", 4)){ // +CMGW=<oa/da>[,<tooa/toda>[,<stat>]]<CR>
+                                                    //+CMGW=<length>[,<stat>]<CR>PDU is given<ctrl-Z/ESC>
+                char cmgw[128] = {0};
+                char resp[50] = {0};
+                if(!strcasecmp(cmd, "cmgw")) { // Get
+                    printf("cmgw : OK\n");
+
+                } else {
+                    char *ptr = strstr(cmd, "cmgw,");    //+CMGW, <oa/da>, data
+                    if(ptr != NULL)
+				    {
+                        ptr = strstr(cmd, ",");
+				    	ptr++;
+                        memset(cmgw, 0, sizeof(cmgw));
+				        memcpy(cmgw, ptr, strlen(ptr));
+						printf("cmgw:%s\n", cmgw);
+				    }
+
+                    memset(resp, 0, sizeof(resp));
+                    err = mbtk_sms_cmgw_set(info_handle, cmgw, resp);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("cmgw set success. resp:%s\n", resp);
+                    }
+                }
+            }
+            else if(!strncasecmp(cmd, "cmgd", 4)){ // +CMGD=<index>[,<delflag>
+                                                    //
+                char cmgd[128] = {0};
+                if(!strcasecmp(cmd, "cmgd")) { // Get
+                    printf("cmgd : OK\n");
+
+                } else {
+                    char *ptr = strstr(cmd, ",");    //+CMGD=<index>[,<delflag>
+                    if(ptr != NULL)
+				    {
+				    	ptr++;
+                        memset(cmgd, 0, sizeof(cmgd));
+				        memcpy(cmgd, ptr, strlen(ptr));
+						printf("1cmgd:%s\n", cmgd);
+				    }
+
+
+                    err = mbtk_sms_cmgd_set(info_handle, cmgd);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE set success\n");
+                    }
+                }
+            }
+            else if(!strncasecmp(cmd, "cmgl", 4)){ // AT+CMGL[=<stat>]
+                                                    //
+                char cmgl[128] = {0};
+                char resp[5*1024] ={0};
+                if(!strcasecmp(cmd, "cmgl")) { // Get
+                    printf("cmgl : OK\n");
+
+                } else {
+                    char *ptr = strstr(cmd, "cmgl,");  //  AT+CMGL[=<stat>]
+                    if(ptr != NULL)
+				    {
+                        ptr = strstr(cmd, ",");
+				    	ptr++;
+                        memset(cmgl, 0, sizeof(cmgl));
+				        memcpy(cmgl, ptr, strlen(ptr));
+						printf("0cmgl:%s\n", cmgl);
+				    }
+
+					memset(resp, 0, sizeof(resp));
+                    err = mbtk_sms_cmgl_set(info_handle, cmgl, resp);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                      //  printf("cmgl set success, reg:%s\n",resp);
+                    }
+                }
+            }
+            else if(!strncasecmp(cmd, "csca", 4)){ // AT+CSCA=<number> [,<type>]
+                                                    //
+                char csca[128] = {0};
+                if(!strcasecmp(cmd, "csca")) { // Get
+                    err = mbtk_sms_csca_get(info_handle, csca);
+                    if(err) {
+                        printf("mbtk_sms_csca_get Error : %d\n", err);
+                    } else {
+                        printf("mbtk_sms_csca_get success\n");
+                    }
+
+                } else {
+                    char *ptr = strstr(cmd, ",");  //  AT+CSCA=<number> [,<type>]
+                    if(ptr != NULL)
+				    {
+				    	ptr++;
+                        memset(csca, 0, sizeof(csca));
+				        memcpy(csca, ptr, strlen(ptr));
+						printf("csca:%s\n", csca);
+				    }
+
+                    err = mbtk_sms_csca_set(info_handle, csca);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE set success\n");
+                    }
+                }
+            }
+            else if(!strncasecmp(cmd, "csmp", 4)){ // AT+CSMP=[<fo>[,<vp>[,<pid>[,<dcs>]]]]
+                                                    //
+                char csmp[128] = {0};
+                if(!strcasecmp(cmd, "csmp")) { // Get
+                    printf("cmgl : OK\n");
+
+                } else {
+                    char *ptr = strstr(cmd, ",");  //  AT+CSMP=[<fo>[,<vp>[,<pid>[,<dcs>]]]]
+                    if(ptr != NULL)
+				    {
+				    	ptr++;
+                        memset(csmp, 0, sizeof(csmp));
+				        memcpy(csmp, ptr, strlen(ptr));
+						printf("csmp:%s\n", csmp);
+				    }
+
+                    err = mbtk_sms_csmp_set(info_handle, csmp);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE set success\n");
+                    }
+                }
+            }
+            else if(!strncasecmp(cmd, "cscb", 4)){ // AT+CSCB=<[<mode>[,<mids>[,<dcss>]]]>
+                                                    //
+                char cscb[128] = {0};
+                if(!strcasecmp(cmd, "cscb")) { // Get
+                    printf("cmgl : OK\n");
+
+                } else {
+                    char *ptr = strstr(cmd, ",");  //  AT+CSCB=<[<mode>[,<mids>[,<dcss>]]]>
+                    if(ptr != NULL)
+				    {
+				    	ptr++;
+                        memset(cscb, 0, sizeof(cscb));
+				        memcpy(cscb, ptr, strlen(ptr));
+						printf("cscb:%s\n", cscb);
+				    }
+
+                    err = mbtk_sms_cscb_set(info_handle, cscb);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("VoLTE set success\n");
+                    }
+                }
+            }
+            else if(!strcasecmp(cmd, "h") || !strcasecmp(cmd, "help")) {
+                help();
+            } else if(!strcasecmp(cmd, "q")) {
+                mbtk_info_handle_free(&info_handle);
+                break;
+            } else {
+                printf("\n");
+            }
+        }
+    }
+
+    LOG("Client exec complete.");
+#if 1
+    while(1)
+    {
+        sleep(1000 * 365 * 24 * 60 * 60);
+    }
+#else
+    sleep(1);
+#endif
+    return 0;
+}
diff --git a/mbtk/test/mbtk_mqtt_aliyun_test.c b/mbtk/test/mbtk_mqtt_aliyun_test.c
new file mode 100755
index 0000000..923b123
--- /dev/null
+++ b/mbtk/test/mbtk_mqtt_aliyun_test.c
@@ -0,0 +1,190 @@
+#include <stdio.h>
+#include "mbtk_mqtt.h"
+#include "pthread.h"
+#include "string.h"
+#include "unistd.h"
+#include "sys/stat.h"
+#include "sys/types.h"
+#include "sys/socket.h"
+#include "netinet/in.h"
+#include "arpa/inet.h"
+#include "fcntl.h"
+#include "mbtk_sock2.h"
+/*
+typedef struct {
+    char clientId[255];
+    char deviceToken[255];
+} regnwl_info_t;
+*/
+
+int aliyun_xiyinyimi_connect(mbtk_mqtt_device_session_t *device, regnwl_info_t *regn);
+
+struct opts_struct opts = {
+    (char *)"iot-dev", 0, (char *)"\n", QOS0, "admin", "password", (char *)"localhost", 1883, 0
+};//初始化结构体
+
+iot_device_info_t gateway = {
+    .iotstatus = IOT_STATUS_LOGIN,
+    .model = {"2022"},
+    .company = {"/my"}
+};//初始化主题
+
+static Cloud_MQTT_t *miot_mqtt;
+
+void set_mqtt_t(Cloud_MQTT_t *piot_mqtt)
+{
+    miot_mqtt = piot_mqtt;
+}
+Cloud_MQTT_t * get_mqtt_t()
+{
+    return miot_mqtt;
+}
+
+void mqtt_data_rx_cb(void *pbuf, int len) 
+{
+
+    printf("data = %s\n", (unsigned char *)pbuf);	//打印接收到的数据
+}
+
+
+void MQTTMessageArrived_Cb(MessageData* md)
+{
+    MQTTMessage *message = md->message; 
+
+    Cloud_MQTT_t *piot_mqtt = get_mqtt_t();
+
+    if (NULL != piot_mqtt->DataArrived_Cb) {
+        piot_mqtt->DataArrived_Cb((void *)message->payload, message->payloadlen);//异步消息体
+    }
+}
+
+
+void *mqtt_thread(void *arg)
+{
+    while (gateway.iotstatus != IOT_STATUS_DROP){
+        printf("gateway.iotstatus is %d\n",gateway.iotstatus);
+        iot_yield(arg,&gateway);									//维持服务器稳定,断开重连
+    }
+    printf("gateway.iotstatus is IOT_STATUS_DROP");
+//    mqtt_device_disconnect(arg);
+    pthread_exit(NULL);
+    return NULL;
+}
+
+
+
+//int mbtk_aliyun_mqtt_register_init(mbtk_mqtt_device_session_t *mbtk_mqtt_device )
+int main(int argc, char *argv[])
+{
+
+    printf("aliyun mqtt start2\n");
+    int ret, len; 
+    char will_msg[256] = {"hello world"};						//初始化遗嘱数据
+    static int i = 0;
+
+    mbtk_mqtt_device_session_t mbtk_mqtt_device = {0};
+    memcpy(mbtk_mqtt_device.device_name, argv[1] , strlen(argv[1]));
+    memcpy(mbtk_mqtt_device.product_key, "a14Vv4QUPeP" , strlen("a14Vv4QUPeP"));
+    memcpy(mbtk_mqtt_device.product_secret, "GiBigxEaluyAPnD4" , strlen( "GiBigxEaluyAPnD4"));
+    mbtk_mqtt_device.host = 0;
+    mbtk_mqtt_device.port = 1883;
+
+
+    Cloud_MQTT_t *Iot_mqtt;
+    Iot_mqtt = (Cloud_MQTT_t *)malloc(sizeof(Cloud_MQTT_t));
+    memset(Iot_mqtt,0x0,sizeof(Cloud_MQTT_t));
+
+    //一型一密免预注册mqtt
+    mbtk_aliyun_mqtt_one_type_one_secret_unregin_set_info_init(Iot_mqtt, &mbtk_mqtt_device,60*1000,4,mqtt_data_rx_cb);
+
+    mqtt_will_msg_set(Iot_mqtt, will_msg, strlen(will_msg));	//设置遗嘱
+    set_mqtt_t(Iot_mqtt);   
+    ret = mbtk_aliyun_mqtt_one_type_one_secret_unregin_device_connect(Iot_mqtt);						//初始化并连接mqtt服务器
+
+    printf("connect success\n");
+    int rc = mbtk_MQTTSubscribe(&Iot_mqtt->Client, Iot_mqtt->sub_topic, opts.qos, MQTTMessageArrived_Cb);
+    if (rc) {
+        printf("mqtt subscribe fail \n");
+        char clientId[255] = {0};
+        char deviceToken[255] = {0};
+        if(! mbtk_aliyun_mqtt_one_type_one_secret_unregin_get_regin_info(clientId, deviceToken) )
+        {
+            regnwl_info_t regn_info = {0};
+            memcpy(regn_info.clientId,clientId , strlen(clientId));
+            memcpy(regn_info.deviceToken, deviceToken , strlen(deviceToken));
+            printf("example\n");
+            printf("%s\n, %s\n", clientId, deviceToken);
+            aliyun_xiyinyimi_connect(&mbtk_mqtt_device, &regn_info);
+        }
+    }
+
+    return 0;
+}
+
+int aliyun_xiyinyimi_connect(mbtk_mqtt_device_session_t *device, regnwl_info_t *regn)
+{
+
+    int ret, len; 
+    char will_msg[256] = {"hello world"};						//初始化遗嘱数据
+    static int retry_count = 0;
+    pthread_t thread_ID;      //定义线程id
+    static int i = 0;
+
+    Cloud_MQTT_t *Iot_mqtt;
+    Iot_mqtt = (Cloud_MQTT_t *)malloc(sizeof(Cloud_MQTT_t));
+    memset(Iot_mqtt,0x0,sizeof(Cloud_MQTT_t));
+    
+
+    iot_aliyun_mqtt_one_type_one_secret_unregin_connect_init(Iot_mqtt,device, regn->clientId, regn->deviceToken, 30,3,"aaa","aaa",mqtt_data_rx_cb);	
+
+//    iot_mqtt_init(Iot_mqtt,host,port, client, user, pass,30,3,"aaa","aaa",mqtt_data_rx_cb);	
+
+    mqtt_will_msg_set(Iot_mqtt, will_msg, strlen(will_msg));	//设置遗嘱
+
+    set_mqtt_t(Iot_mqtt);    
+    ret = mqtt_device_connect(Iot_mqtt);						//初始化并连接mqtt服务器
+    
+
+    while (ret < 0 && retry_count <= 5) {
+        printf("ret = %d\r\n", ret);
+        retry_count ++ ;
+        printf("retry_count = %d\n",retry_count);
+        sleep(3);
+        ret = mqtt_device_connect(Iot_mqtt);
+    }
+    if(ret < 0 && retry_count > 5)
+    {
+        printf("reconnect times more than 5 exit\n");
+        return NULL;
+    }
+    retry_count = 0;
+
+    printf("connect success\n");
+    int rc = mbtk_MQTTSubscribe(&Iot_mqtt->Client, Iot_mqtt->sub_topic, opts.qos, MQTTMessageArrived_Cb);
+    if (rc) {
+        printf("mqtt subscribe fail \n");
+        ret = -105;
+        return 0;
+    }
+    gateway.iotstatus = IOT_STATUS_CONNECT;
+    
+    pthread_create(&thread_ID, NULL, &mqtt_thread, (void *)Iot_mqtt);	//创建一个线程执行mqtt客户端
+    pthread_detach(thread_ID);	//设置线程结束收尸
+
+    while (1)
+    {
+        mbtk_MQTTPublish("my yes", 6, 0,&Iot_mqtt->Client,Iot_mqtt->pub_topic,2,0);//循环发布"my yes"
+        sleep(3);						//睡眠3s
+        i++;
+        if (i > 5)
+        {
+            mbtk_MQTTUnsubscribe(&Iot_mqtt->Client,Iot_mqtt->sub_topic);
+            break;
+        }
+    }
+    return 0;
+}
+
+
+
+
diff --git a/mbtk/test/mbtk_mqtt_test.c b/mbtk/test/mbtk_mqtt_test.c
new file mode 100755
index 0000000..5d99258
--- /dev/null
+++ b/mbtk/test/mbtk_mqtt_test.c
@@ -0,0 +1,127 @@
+#include <stdio.h>
+#include "mbtk_mqtt.h"
+#include "pthread.h"
+#include "string.h"
+#include "unistd.h"
+#include "sys/stat.h"
+#include "sys/types.h"
+#include "sys/socket.h"
+#include "netinet/in.h"
+#include "arpa/inet.h"
+#include "fcntl.h"
+#include "mbtk_sock2.h"
+
+
+struct opts_struct opts = {
+    (char *)"iot-dev", 0, (char *)"\n", QOS0, "admin", "password", (char *)"localhost", 1883, 0
+};//初始化结构体
+
+iot_device_info_t gateway = {
+    .iotstatus = IOT_STATUS_LOGIN,
+    .model = {"2022"},
+    .company = {"/my"}
+};//初始化主题
+
+static Cloud_MQTT_t *miot_mqtt;
+
+void set_mqtt_t(Cloud_MQTT_t *piot_mqtt)
+{
+    miot_mqtt = piot_mqtt;
+}
+Cloud_MQTT_t * get_mqtt_t()
+{
+    return miot_mqtt;
+}
+
+void mqtt_data_rx_cb(void *pbuf, int len)
+{
+
+    printf("data = %s\n", (unsigned char *)pbuf);	//打印接收到的数据
+}
+
+
+void MQTTMessageArrived_Cb(MessageData* md)
+{
+    MQTTMessage *message = md->message;
+
+    Cloud_MQTT_t *piot_mqtt = get_mqtt_t();
+
+    if (NULL != piot_mqtt->DataArrived_Cb) {
+        piot_mqtt->DataArrived_Cb((void *)message->payload, message->payloadlen);//异步消息体
+    }
+}
+
+void *mqtt_thread(void *arg)
+{
+    while (gateway.iotstatus != IOT_STATUS_DROP){
+        printf("gateway.iotstatus is %d\n",gateway.iotstatus);
+        iot_yield(arg,&gateway);									//维持服务器稳定,断开重连
+    }
+    printf("gateway.iotstatus is IOT_STATUS_DROP");
+//    mqtt_device_disconnect(arg);
+    pthread_exit(NULL);
+    return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+    if(argc >6 || argc < 4)
+    {
+        printf("input error.\n example:./mqtt_test 192.168.1.1 8080 clientid username password\n");
+        return 0;
+    }
+    int ret, len;
+    char will_msg[256] = {"hello world"};						//初始化遗嘱数据
+    static int retry_count = 0;
+    pthread_t thread_ID;      //定义线程id
+    static int i = 0;
+
+    Cloud_MQTT_t *Iot_mqtt;
+    Iot_mqtt = (Cloud_MQTT_t *)malloc(sizeof(Cloud_MQTT_t));
+    memset(Iot_mqtt,0x0,sizeof(Cloud_MQTT_t));
+
+    iot_mqtt_init(Iot_mqtt,argv[1],atoi(argv[2]),argv[3],argv[4],argv[5],30,3,"aaa","aaa",mqtt_data_rx_cb);									//初始化
+    mqtt_will_msg_set(Iot_mqtt, will_msg, strlen(will_msg));	//设置遗嘱
+    set_mqtt_t(Iot_mqtt);
+    ret = mqtt_device_connect(Iot_mqtt);						//初始化并连接mqtt服务器
+
+
+    while (ret < 0 && retry_count <= 5) {
+        printf("ret = %d\r\n", ret);
+        retry_count ++ ;
+        printf("retry_count = %d\n",retry_count);
+        sleep(3);
+        ret = mqtt_device_connect(Iot_mqtt);
+    }
+    if(ret < 0 && retry_count > 5)
+    {
+        printf("reconnect times more than 5 exit\n");
+        return NULL;
+    }
+    retry_count = 0;
+
+    printf("connect success\n");
+    int rc = mbtk_MQTTSubscribe(&Iot_mqtt->Client, Iot_mqtt->sub_topic, opts.qos, MQTTMessageArrived_Cb);
+    if (rc) {
+        printf("mqtt subscribe fail \n");
+        ret = -105;
+        return 0;
+    }
+    gateway.iotstatus = IOT_STATUS_CONNECT;
+
+    pthread_create(&thread_ID, NULL, &mqtt_thread, (void *)Iot_mqtt);	//创建一个线程执行mqtt客户端
+    pthread_detach(thread_ID);	//设置线程结束收尸
+
+    while (1)
+    {
+        mbtk_MQTTPublish("my yes", 6, 0,&Iot_mqtt->Client,Iot_mqtt->pub_topic,2,0);//循环发布"my yes"
+        sleep(3);						//睡眠3s
+        i++;
+        if (i > 5)
+        {
+            mbtk_MQTTUnsubscribe(&Iot_mqtt->Client,Iot_mqtt->sub_topic);
+            break;
+        }
+    }
+    return 0;
+}
diff --git a/mbtk/test/mbtk_net_control_test.c b/mbtk/test/mbtk_net_control_test.c
new file mode 100755
index 0000000..89e7a7f
--- /dev/null
+++ b/mbtk/test/mbtk_net_control_test.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#define LOG_TAG "mbtk_net"
+#include "mbtk_type.h"
+#include "mbtk_net_control.h"
+#include "mbtk_log.h"
+
+
+int main(int argc, char *argv[])
+{
+    if(argc != 2) {
+        LOGE("ARG error.");
+        return -1;
+    }
+
+    LOGI("net_control start.");
+
+    if(!strcmp(argv[1], "on")) {
+        if(mbtk_net_enable(TRUE)) {
+            printf("Open Net fail.\n");
+        } else {
+            printf("Open Net success.\n");
+        }
+    } else if(!strcmp(argv[1], "off")) {
+        if(mbtk_net_enable(FALSE)) {
+            printf("Close Net fail.\n");
+        } else {
+            printf("Close Net success.\n");
+        }
+    } else if(!strcmp(argv[1], "get")) {
+        mbtk_net_state_t state = mbtk_net_state_get();
+        printf("Net State : %d\n", state);
+    } else {
+        printf("Unknown arg : %s\n", argv[1]);
+    }
+
+
+    LOGI("net_control exit.");
+    return 0;
+
+}
+
+
diff --git a/mbtk/test/polarssl_demo.c b/mbtk/test/polarssl_demo.c
new file mode 100755
index 0000000..d43b4d8
--- /dev/null
+++ b/mbtk/test/polarssl_demo.c
@@ -0,0 +1,479 @@
+#include <stdio.h>
+#include "mbtk_log.h"
+#include "ql/ql_mcm_sim.h"
+#include <sys/socket.h>
+#include <polarssl/net.h>
+#include <polarssl/ssl.h>
+#include <polarssl/entropy.h>
+#include <polarssl/ctr_drbg.h>
+#include <polarssl/certs.h>
+#include <polarssl/x509.h>
+#include <polarssl/error.h>
+#include <polarssl/debug.h>
+#include <polarssl/config.h>
+
+#define DFL_SERVER_NAME         "asr"
+#define DFL_SERVER_ADDR         NULL
+#define DFL_SERVER_PORT         4433
+#define DFL_REQUEST_PAGE        "/"
+#define DFL_REQUEST_SIZE        -1
+#define DFL_DEBUG_LEVEL         0
+#define DFL_NBIO                0
+#define DFL_CA_FILE             "/ca.crt"
+#define DFL_CA_PATH             "/ca.crt"
+#define DFL_CRT_FILE            "/client.crt"
+#define DFL_KEY_FILE            "/client.key"
+#define DFL_PSK                 ""
+#define DFL_PSK_IDENTITY        "Client_identity"
+#define DFL_FORCE_CIPHER        0
+#define DFL_RENEGOTIATION       SSL_RENEGOTIATION_DISABLED
+#define DFL_ALLOW_LEGACY        SSL_LEGACY_NO_RENEGOTIATION
+#define DFL_RENEGOTIATE         0
+#define DFL_EXCHANGES           1
+#define DFL_MIN_VERSION         SSL_MINOR_VERSION_3
+#define DFL_MAX_VERSION         SSL_MINOR_VERSION_3
+#define DFL_AUTH_MODE           SSL_VERIFY_REQUIRED
+#define DFL_MFL_CODE            SSL_MAX_FRAG_LEN_NONE
+#define DFL_TRUNC_HMAC          0
+#define DFL_RECONNECT           0
+#define DFL_RECO_DELAY          0
+#define DFL_TICKETS             SSL_SESSION_TICKETS_ENABLED
+#define DFL_ALPN_STRING         NULL
+
+#define GET_REQUEST "GET %s HTTP/1.0\r\nExtra-header: "
+#define GET_REQUEST_END "\r\n\r\n"
+
+#define  CA_CERT \
+"-----BEGIN CERTIFICATE-----\r\n" \
+"MIIDKjCCAhICCQCOewfZiRCiNjANBgkqhkiG9w0BAQUFADBXMQswCQYDVQQGEwJD\r\n" \
+"TjEQMA4GA1UECBMHU2lDaHVhbjEVMBMGA1UEChMMTU9CSUxFVEVLLkNBMQswCQYD\r\n" \
+"VQQLEwJJVDESMBAGA1UEAxMJTU9CSUxFVEVLMB4XDTE4MDkxODA4MDUzMloXDTMz\r\n" \
+"MDkxOTA4MDUzMlowVzELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB1NpQ2h1YW4xFTAT\r\n" \
+"BgNVBAoTDE1PQklMRVRFSy5DQTELMAkGA1UECxMCSVQxEjAQBgNVBAMTCU1PQklM\r\n" \
+"RVRFSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOkdYJF1h1xjKbY0\r\n" \
+"ipbl88G653PiCh8ZMjmIUYeiDKC8+0wtXZtHvQIl6AncOzBy9XHVOctbKn34exC8\r\n" \
+"SEotMuo2T49vs9VtE8GYu2pOrf3m42NpLRnYAxfm9qw53CMHx+Jn7Oa9fnxa8haA\r\n" \
+"pRc2BTVadWGoS8EEwoZFk0eNb7Z2Gc7U0c+GhISI4oVTTocGvGgMzkvduu5JJbbc\r\n" \
+"BOcNFrii9sRO9vtOYQtqOEg01Uum2Dwp/o2bDLXNJEqAIh4WACiM4iPmmlRHWT2y\r\n" \
+"NjQ3vcbEdrFwbHRtO46+Vw54HnSyCoFb3uCHMNMvXObZ/8AU9E3Cgat4j0sgEeB0\r\n" \
+"hqA4MiMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAtEAjf0CjsLgG9ROdmp1qXYft\r\n" \
+"+ndIT5l82KRK57ZQsfdFbnJOvALeF/ICKU0M2TXgJNiGOA5RxDi00YYdMbOIPwVZ\r\n" \
+"JH4b87J/LYdLAGf+Q+kVI6gWH3hPm4Jzfzq/40KVrf3mpa54yWz6ZYtwfxBjrMgr\r\n" \
+"IVe0O5SIJ99lsddgzgUkqYN2vWJW2zZ50xuXOAyo+pOnjzX0wuOcaBT3JCHWJRAb\r\n" \
+"VhJCf9JbswDgnddJerqFtB8pnpAOdGokLCOoM06q3s3P9mhGX+72HXdX7G8CSAuG\r\n" \
+"PVCGf6RaF0/G4B9R1c3du3lZRlQWfx2pxyU0LS86iFQFWqzqcWEXIcULVdcErQ==\r\n" \
+"-----END CERTIFICATE-----\r\n"
+
+const char ca1_cert[]= CA_CERT;
+
+
+struct options
+{
+    const char *server_name;    /* hostname of the server (client only)     */
+    const char *server_addr;    /* address of the server (client only)      */
+    int server_port;            /* port on which the ssl service runs       */
+    int debug_level;            /* level of debugging                       */
+    int nbio;                   /* should I/O be blocking?                  */
+    const char *request_page;   /* page on server to request                */
+    int request_size;           /* pad request with header to requested size */
+    const char *ca_file;        /* the file with the CA certificate(s)      */
+    const char *ca_path;        /* the path with the CA certificate(s) reside */
+    const char *crt_file;       /* the file with the client certificate     */
+    const char *key_file;       /* the file with the client key             */
+    const char *psk;            /* the pre-shared key                       */
+    const char *psk_identity;   /* the pre-shared key identity              */
+    int force_ciphersuite[2];   /* protocol/ciphersuite to use, or all      */
+    int renegotiation;          /* enable / disable renegotiation           */
+    int allow_legacy;           /* allow legacy renegotiation               */
+    int renegotiate;            /* attempt renegotiation?                   */
+    int renego_delay;           /* delay before enforcing renegotiation     */
+    int exchanges;              /* number of data exchanges                 */
+    int min_version;            /* minimum protocol version accepted        */
+    int max_version;            /* maximum protocol version accepted        */
+    int auth_mode;              /* verify mode for connection               */
+    unsigned char mfl_code;     /* code for maximum fragment length         */
+    int trunc_hmac;             /* negotiate truncated hmac or not          */
+    int reconnect;              /* attempt to resume session                */
+    int reco_delay;             /* delay in seconds before resuming session */
+    int tickets;                /* enable / disable session tickets         */
+    const char *alpn_string;    /* ALPN supported protocols                 */
+} opt;
+
+
+static sim_client_handle_type cli_handle;
+int server_fd = -1;
+
+static void my_debug( void *ctx, int level, const char *str )
+{
+    ((void) level);
+
+    fprintf( (FILE *) ctx, "%s", str );
+    fflush(  (FILE *) ctx  );
+}
+
+
+static int ssl_client_init()
+{
+    int ret = 0, len, tail_len, i, written, frags;
+    unsigned char buf[SSL_MAX_CONTENT_LEN + 1];
+    const char *pers = "ssl_client";
+
+    entropy_context entropy;
+    ctr_drbg_context ctr_drbg;
+    ssl_context ssl;
+    ssl_session saved_session;
+    x509_crt cacert;
+    x509_crt clicert;
+    pk_context pkey;
+
+    memset( &ssl, 0, sizeof( ssl_context ) );
+    memset( &saved_session, 0, sizeof( ssl_session ) );
+    x509_crt_init( &cacert );
+    x509_crt_init( &clicert );
+    pk_init( &pkey );
+
+    fflush( stdout );
+
+     /*
+     * 0. Initialize the RNG and the session data
+     */
+
+    entropy_init( &entropy );
+    if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
+                               (const unsigned char *) pers,
+                               strlen( pers ) ) ) != 0 )
+    {
+        printf( " failed\n  ! ctr_drbg_init returned -0x%x\n", -ret );
+        goto exit;
+    }
+
+    printf( " ok\n" );
+
+     /*
+     * 1.1. Load the trusted CA
+     */
+    //ret = x509_crt_parse(&cacert,ca1_cert,strlen(ca1_cert));
+    ret = x509_crt_parse_file( &cacert, opt.ca_path );
+    if( ret < 0 )
+    {
+        printf( " failed\n  !  ca x509_crt_parse returned -0x%x\n\n", -ret );
+        goto exit;
+    }
+    printf( " ok\n" );
+
+     /*
+     * 1.2. Load own certificate and private key
+     *
+     * (can be skipped if client authentication is not required)
+     */
+
+    ret = x509_crt_parse_file( &clicert, opt.crt_file );
+    if( ret != 0 )
+    {
+        printf( " failed\n  !  crt x509_crt_parse returned -0x%x\n\n", -ret );
+        goto exit;
+    }
+
+    ret = pk_parse_keyfile( &pkey, opt.key_file, NULL);
+    if( ret != 0 )
+    {
+        printf( " failed\n  !  key x509_crt_parse returned -0x%x\n\n", -ret );
+        goto exit;
+    }
+
+    printf( " ok\n" );
+
+     /*
+     * 2. Setup stuff
+     */
+    printf( "  . Setting up the SSL/TLS structure..." );
+    fflush( stdout );
+
+    if( ( ret = ssl_init( &ssl ) ) != 0 )
+    {
+        printf( " failed\n  ! ssl_init returned -0x%x\n\n", -ret );
+        goto exit;
+    }
+
+    ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
+    ssl_set_authmode( &ssl, opt.auth_mode );
+
+    ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
+    ssl_set_dbg( &ssl, my_debug, stdout );
+
+    ssl_set_bio( &ssl, net_recv, &server_fd, net_send, &server_fd );
+
+    ssl_set_renegotiation( &ssl, opt.renegotiation );
+    ssl_legacy_renegotiation( &ssl, opt.allow_legacy );
+
+    ssl_set_ca_chain( &ssl, &cacert, NULL, NULL );
+
+    if( ( ret = ssl_set_own_cert( &ssl, &clicert, &pkey ) ) != 0 )
+        {
+            printf( " failed\n  ! ssl_set_own_cert returned %d\n\n", ret );
+            goto exit;
+        }
+    if( opt.min_version != -1 )
+        ssl_set_min_version( &ssl, SSL_MAJOR_VERSION_3, opt.min_version );
+    if( opt.max_version != -1 )
+        ssl_set_max_version( &ssl, SSL_MAJOR_VERSION_3, opt.max_version );
+    printf( " ok\n" );
+    /*
+     * 3. Handshake
+     */
+    printf( "  . Performing the SSL/TLS handshake..." );
+    fflush( stdout );
+
+    while( ( ret = ssl_handshake( &ssl ) ) != 0 )
+    {
+        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
+        {
+            printf( " failed\n  ! ssl_handshake returned -0x%x\n", -ret );
+            if( ret == POLARSSL_ERR_X509_CERT_VERIFY_FAILED )
+                printf(
+                    "    Unable to verify the server's certificate. "
+                        "Either it is invalid,\n"
+                    "    or you didn't set ca_file or ca_path "
+                        "to an appropriate value.\n"
+                    "    Alternatively, you may want to use "
+                        "auth_mode=optional for testing purposes.\n" );
+            printf( "\n" );
+            goto exit;
+        }
+    }
+
+    printf( " ok\n    [ Protocol is %s ]\n    [ Ciphersuite is %s ]\n",
+            ssl_get_version( &ssl ), ssl_get_ciphersuite( &ssl ) );
+
+    /*
+     * 4. Verify the server certificate
+     */
+    printf( "  . Verifying peer X.509 certificate..." );
+
+    if( ( ret = ssl_get_verify_result( &ssl ) ) != 0 )
+    {
+        printf( " failed\n" );
+
+        if( ( ret & BADCERT_EXPIRED ) != 0 )
+            printf( "  ! server certificate has expired\n" );
+
+        if( ( ret & BADCERT_REVOKED ) != 0 )
+            printf( "  ! server certificate has been revoked\n" );
+
+        if( ( ret & BADCERT_CN_MISMATCH ) != 0 )
+            printf( "  ! CN mismatch (expected CN=%s)\n", opt.server_name );
+
+        if( ( ret & BADCERT_NOT_TRUSTED ) != 0 )
+            printf( "  ! self-signed or not signed by a trusted CA\n" );
+
+        printf( "\n" );
+    }
+    else
+        printf( " ok\n" );
+
+    if( ssl_get_peer_cert( &ssl ) != NULL )
+    {
+        printf( "  . Peer certificate information    ...\n" );
+        x509_crt_info( (char *) buf, sizeof( buf ) - 1, "      ",
+                       ssl_get_peer_cert( &ssl ) );
+        printf( "%s\n", buf );
+    }
+    /*
+     * 5. Write the GET request
+     */
+    printf( "  > Write to server:" );
+    fflush( stdout );
+
+    len = snprintf( (char *) buf, sizeof(buf) - 1, GET_REQUEST,
+                    opt.request_page );
+    tail_len = strlen( GET_REQUEST_END );
+
+    /* Add padding to GET request to reach opt.request_size in length */
+    if( opt.request_size != DFL_REQUEST_SIZE &&
+        len + tail_len < opt.request_size )
+    {
+        memset( buf + len, 'A', opt.request_size - len - tail_len );
+        len += opt.request_size - len - tail_len;
+    }
+
+    strncpy( (char *) buf + len, GET_REQUEST_END, sizeof(buf) - len - 1 );
+    len += tail_len;
+
+    /* Truncate if request size is smaller than the "natural" size */
+    if( opt.request_size != DFL_REQUEST_SIZE &&
+        len > opt.request_size )
+    {
+        len = opt.request_size;
+
+        /* Still end with \r\n unless that's really not possible */
+        if( len >= 2 ) buf[len - 2] = '\r';
+        if( len >= 1 ) buf[len - 1] = '\n';
+    }
+
+    for( written = 0, frags = 0; written < len; written += ret, frags++ )
+    {
+        while( ( ret = ssl_write( &ssl, buf + written, len - written ) ) <= 0 )
+        {
+            if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
+            {
+                printf( " failed\n  ! ssl_write returned -0x%x\n\n", -ret );
+                goto exit;
+            }
+        }
+    }
+
+    buf[written] = '\0';
+    printf( " %d bytes written in %d fragments\n\n%s\n", written, frags, (char *) buf );
+
+    /*
+     * 6. Read the HTTP response
+     */
+    printf( "  < Read from server:" );
+    fflush( stdout );
+
+    do
+    {
+        len = sizeof( buf ) - 1;
+        memset( buf, 0, sizeof( buf ) );
+        ret = ssl_read( &ssl, buf, len );
+
+        if( ret == POLARSSL_ERR_NET_WANT_READ ||
+            ret == POLARSSL_ERR_NET_WANT_WRITE )
+            continue;
+
+        if( ret <= 0 )
+        {
+            switch( ret )
+            {
+                case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
+                    printf( " connection was closed gracefully\n" );
+                    ret = 0;
+                    goto close_notify;
+
+                case 0:
+                case POLARSSL_ERR_NET_CONN_RESET:
+                    printf( " connection was reset by peer\n" );
+                    ret = 0;
+                    goto exit;
+
+                default:
+                    printf( " ssl_read returned -0x%x\n", -ret );
+                    goto exit;
+            }
+        }
+
+        len = ret;
+        buf[len] = '\0';
+        printf( " %d bytes read\n\n%s", len, (char *) buf );
+
+        /* End of message should be detected according to the syntax of the
+         * application protocol (eg HTTP), just use a dummy test here. */
+        if( ret > 0 && buf[len-1] == '\n' )
+        {
+            ret = 0;
+            break;
+        }
+    }
+    while( 1 );
+
+    /*
+     * 7. Done, cleanly close the connection
+     */
+close_notify:
+        printf( "  . Closing the connection..." );
+
+        while( ( ret = ssl_close_notify( &ssl ) ) < 0 )
+        {
+            if( ret == POLARSSL_ERR_NET_CONN_RESET )
+            {
+                printf( " ok (already closed by peer)\n" );
+                ret = 0;
+                goto exit;
+            }
+
+            if( ret != POLARSSL_ERR_NET_WANT_READ &&
+                ret != POLARSSL_ERR_NET_WANT_WRITE )
+            {
+                printf( " failed\n  ! ssl_close_notify returned %d\n\n", ret );
+                goto exit;
+            }
+        }
+
+        printf( " ok\n" );
+exit:
+    if( server_fd )
+        net_close( server_fd );
+
+    x509_crt_free( &clicert );
+    x509_crt_free( &cacert );
+    pk_free( &pkey );
+    ssl_session_free( &saved_session );
+    ssl_free( &ssl );
+    ctr_drbg_free( &ctr_drbg );
+    entropy_free( &entropy );
+
+    printf( " ok end\n" );
+    return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    printf("Start!\n");
+
+    opt.server_name         = DFL_SERVER_NAME;
+    opt.server_addr         = DFL_SERVER_ADDR;
+    opt.server_port         = DFL_SERVER_PORT;
+    opt.debug_level         = DFL_DEBUG_LEVEL;
+    opt.nbio                = DFL_NBIO;
+    opt.request_page        = DFL_REQUEST_PAGE;
+    opt.request_size        = DFL_REQUEST_SIZE;
+    opt.ca_file             = DFL_CA_FILE;
+    opt.ca_path             = DFL_CA_PATH;
+    opt.crt_file            = DFL_CRT_FILE;
+    opt.key_file            = DFL_KEY_FILE;
+    opt.psk                 = DFL_PSK;
+    opt.psk_identity        = DFL_PSK_IDENTITY;
+    opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
+    opt.renegotiation       = DFL_RENEGOTIATION;
+    opt.allow_legacy        = DFL_ALLOW_LEGACY;
+    opt.renegotiate         = DFL_RENEGOTIATE;
+    opt.exchanges           = DFL_EXCHANGES;
+    opt.min_version         = DFL_MIN_VERSION;
+    opt.max_version         = DFL_MAX_VERSION;
+    opt.auth_mode           = DFL_AUTH_MODE;
+    opt.mfl_code            = DFL_MFL_CODE;
+    opt.trunc_hmac          = DFL_TRUNC_HMAC;
+    opt.reconnect           = DFL_RECONNECT;
+    opt.reco_delay          = DFL_RECO_DELAY;
+    opt.tickets             = DFL_TICKETS;
+    opt.alpn_string         = DFL_ALPN_STRING;
+
+
+    if(argc < 3)
+    {
+        printf("input error \n example: mbtk_test ip prot\n");
+        return -1;
+    }
+    opt.server_addr = argv[1];
+    opt.server_port = atoi(argv[2]);
+
+    int ret = -1;
+    if( ( ret = net_connect( &server_fd, opt.server_addr,
+                                         opt.server_port ) ) != 0 )
+    {
+        printf( " failed\n  ! net_connect returned -0x%x\n\n", -ret );
+        return -1;
+    }
+
+    ret = net_set_nonblock( server_fd );
+    if( ret != 0 )
+    {
+        printf( " failed\n  ! net_set_(non)block() returned -0x%x\n\n", -ret );
+        return -1;
+    }
+    printf( " ok\n" );
+    ret = ssl_client_init();
+    printf("ret is %d\n",ret);
+    printf("End!\n");
+    return 0;
+}
diff --git a/mbtk/test/ql_DSI_ConnectManager_test.c b/mbtk/test/ql_DSI_ConnectManager_test.c
new file mode 100755
index 0000000..ae7edcc
--- /dev/null
+++ b/mbtk/test/ql_DSI_ConnectManager_test.c
@@ -0,0 +1,364 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <sys/epoll.h>
+#include <string.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include "ql/DSI_ConnectManager.h"
+#include "mbtk_log.h"
+
+static void help()
+{
+    printf("apn_get <cid> : Get current apns.\n");
+    printf("apn <cid> <0/1/2> <apn> [<user> <pass> <auth>] : Set apn (IPV4V6/IPV4/IPV6).\n");
+    printf("data_call <0/1/2> <cid> <timeout>: Stop/Start/State data call.\n");
+    printf("data_call_ex <0/1/2> <cid> <timeout>: Stop/Start/State data call.\n");
+}
+
+static int proc_exit()
+{
+    int err = ql_wan_release();
+    if(err)
+    {
+        printf("ql_wan_release fail.");
+        return -1;
+    }
+    return 0;
+}
+
+static void sig_process(int sig)
+{
+    LOGI("I got signal %d\n", sig);
+    switch(sig)
+    {
+        case SIGINT: // Ctrl + C
+        {
+            LOGI("Exit by SIGINT.\n");
+            proc_exit();
+            exit(0);
+        }
+        case SIGQUIT: // Ctrl + \ (类似 SIGINT ,但要产生core文件)
+        {
+            LOGI("Exit by SIGQUIT.\n");
+            proc_exit();
+            exit(0);
+        }
+        case SIGTERM:// 默认kill   (同 SIGKILL ,但 SIGKILL 不可捕获)
+        {
+            LOGI("Exit by SIGTERM.\n");
+            proc_exit();
+            exit(0);
+        }
+        case SIGTSTP:// Ctrl + Z (同 SIGSTOP ,但 SIGSTOP 不可捕获)
+        {
+            LOGI("Exit by SIGTSTP.\n");
+            exit(0);
+        }
+        case SIGSEGV: // 如空指针
+        {
+            LOGI("Exit by SIGSEGV.\n");
+            exit(0);
+        }
+        default:
+        {
+            LOGI("Unknown sig:%d\n",sig);
+            break;
+        }
+    }
+}
+
+static void data_call_status_cb(int status)
+{
+    printf("DATA_CALL_STATE:%d\n", status);
+}
+
+static void data_call_ex_status_cb(int cid,int iptype,int status,int cause)
+{
+    printf("DATA_CALL_EX_STATE:%d, %d, %d, %d\n", cid, iptype, status, cause);
+}
+
+int main(int argc, char *argv[])
+{
+    signal(SIGINT, sig_process);
+    signal(SIGQUIT, sig_process);
+    signal(SIGTERM, sig_process);
+    //signal(SIGTSTP, sig_process);
+    //signal(SIGSEGV, sig_process);
+
+    mbtk_log_init(NULL,"MBTK_QL_TEST");
+
+    //test2(0, "192.168.1.198");
+    //test2(1, "2409:8162:140:cd3c:1:2:1494:72ba");
+    //test2(1, "254.128.0.0.0.0.0.0.0.1.0.2.144.5.212.239");
+    //test2(1, "2400:3200::1");
+
+    int err = ql_wan_init();
+    if(err)
+    {
+        printf("ql_wan_init fail.");
+        return -1;
+    }
+
+    printf(">>>>>>>>>>>>>>>>>>>>>>>>Enter cmd:\n");
+    char cmd[100];
+    while(1)
+    {
+        memset(cmd, 0, 100);
+        if(fgets(cmd, 100, stdin))
+        {
+            char *ptr = cmd + strlen(cmd) - 1;
+            while(ptr >= cmd && (*ptr == '\r' || *ptr == '\n'))
+            {
+                *ptr-- = '\0';
+            }
+
+            if(!strncasecmp(cmd, "apn", 3)){
+                if(!strncasecmp(cmd, "apn_get", 7)) { // Get apn
+                    char *ptr = strstr(cmd, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    int cid = atoi(ptr);
+                    int ip_type = -1;
+                    char apn[128] = {0};
+                    char userName[128] = {0};
+                    char password[128] = {0};
+                    int auth = -1;
+                    err = ql_wan_getapn(cid, &ip_type, apn, 128, userName, 128, password, 128, &auth);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("APN : %d, %d, %s, %s, %s, %d\n", cid, ip_type, apn, userName, password, auth);
+                    }
+                } else { // apn <cid> <0/1/2> <apn> [<user> <pass> <auth>]
+                    char *ptr = strstr(cmd, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    int cid = atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    int ip_type = atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    char apn[128] = {0};
+                    memcpy(apn, ptr, strlen(ptr));
+                    char *tmp = apn;
+                    while(*tmp) {
+                        if(*tmp == ' ') {
+                            *tmp = '\0';
+                            break;
+                        }
+                        tmp++;
+                    }
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL) {
+                        err = ql_wan_setapn(cid, ip_type, apn, NULL, NULL, QL_DSI_AUTH_PREF_NULL);
+                    } else {
+                        while(*ptr != '\0' && *ptr == ' ')
+                            ptr++;
+                        char user[128] = {0};
+                        memcpy(user, ptr, strlen(ptr));
+                        tmp = user;
+                        while(*tmp) {
+                            if(*tmp == ' ') {
+                                *tmp = '\0';
+                                break;
+                            }
+                            tmp++;
+                        }
+
+                        ptr = strstr(ptr, " ");
+                        if(ptr == NULL)
+                            continue;
+                        while(*ptr != '\0' && *ptr == ' ')
+                            ptr++;
+                        char pass[128] = {0};
+                        memcpy(pass, ptr, strlen(ptr));
+                        tmp = pass;
+                        while(*tmp) {
+                            if(*tmp == ' ') {
+                                *tmp = '\0';
+                                break;
+                            }
+                            tmp++;
+                        }
+
+                        ptr = strstr(ptr, " ");
+                        if(ptr == NULL)
+                            continue;
+                        while(*ptr != '\0' && *ptr == ' ')
+                            ptr++;
+                        QL_DSI_AUTH_PREF_T auth  = (QL_DSI_AUTH_PREF_T)atoi(ptr);
+
+                        err = ql_wan_setapn(cid, ip_type, apn, user, pass, auth);
+                    }
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("APN set success\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "data_call_ex", 12)){ // data_call_ex <0/1/2> <cid> <timeout>
+                // data_call <0/1/2> <cid> <timeout>
+                char *ptr = strstr(cmd, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                int type = atoi(ptr);
+
+                ptr = strstr(ptr, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                int cid = atoi(ptr);
+
+                ptr = strstr(ptr, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                int timeout = atoi(ptr);
+
+                switch (type)
+                {
+                    case 0:
+                        err = ql_wan_stop(cid);
+                        break;
+                    case 1:
+                        err = ql_wan_start_ex(cid, 1, data_call_ex_status_cb);
+                        break;
+                    case 2: {
+                        ql_data_call_info info;
+                        err = ql_get_data_call_info(cid, &info);
+                        if(!err) {
+                            printf("cid : %d, ip_type : %d\n", info.profile_idx, info.ip_type);
+                            if(info.v4.state) {
+                                printf("%s: %s, %s, %s\n", info.v4.addr.name, info.v4.addr.ip, info.v4.addr.pri_dns, info.v4.addr.sec_dns);
+                            } else {
+                                printf("IPV4 not available.\n");
+                            }
+
+                            if(info.v6.state) {
+                                printf("%s: %s, %s, %s\n", info.v6.addr.name, info.v6.addr.ip, info.v6.addr.pri_dns, info.v6.addr.sec_dns);
+                            } else {
+                                printf("IPV6 not available.\n");
+                            }
+                        }
+                        break;
+                    }
+                    default:
+                        printf("Type error:%d\n", type);
+                        break;
+                }
+
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("DATA_CALL success\n");
+                }
+            } else if(!strncasecmp(cmd, "data_call", 9)){ // data_call <0/1/2> <cid> <timeout>
+                // data_call <0/1/2> <cid> <timeout>
+                char *ptr = strstr(cmd, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                int type = atoi(ptr);
+
+                ptr = strstr(ptr, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                int cid = atoi(ptr);
+
+                ptr = strstr(ptr, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                int timeout = atoi(ptr);
+
+                switch (type)
+                {
+                    case 0:
+                        err = ql_wan_stop(cid);
+                        break;
+                    case 1:
+                        err = ql_wan_start(cid, 1, data_call_status_cb);
+                        break;
+                    case 2: {
+                        ql_data_call_info info;
+                        err = ql_get_data_call_info(cid, &info);
+                        if(!err) {
+                            printf("cid : %d, ip_type : %d\n", info.profile_idx, info.ip_type);
+                            if(info.v4.state) {
+                                printf("%s: %s, %s, %s\n", info.v4.addr.name, info.v4.addr.ip, info.v4.addr.pri_dns, info.v4.addr.sec_dns);
+                            } else {
+                                printf("IPV4 not available.\n");
+                            }
+
+                            if(info.v6.state) {
+                                printf("%s: %s, %s, %s\n", info.v6.addr.name, info.v6.addr.ip, info.v6.addr.pri_dns, info.v6.addr.sec_dns);
+                            } else {
+                                printf("IPV6 not available.\n");
+                            }
+                        }
+                        break;
+                    }
+                    default:
+                        printf("Type error:%d\n", type);
+                        break;
+                }
+
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("DATA_CALL success\n");
+                }
+            }
+            else if(!strcasecmp(cmd, "h") || !strcasecmp(cmd, "help")) {
+                help();
+            } else if(!strcasecmp(cmd, "q")) {
+                break;
+            } else {
+                printf("\n");
+            }
+        }
+    }
+
+    proc_exit();
+
+    LOGI("Client exec complete.");
+#if 1
+    while(1)
+    {
+        sleep(1000 * 365 * 24 * 60 * 60);
+    }
+#else
+    sleep(1);
+#endif
+    return 0;
+}
+
diff --git a/mbtk/test/ql_adc_test.c b/mbtk/test/ql_adc_test.c
new file mode 100755
index 0000000..6eb83f6
--- /dev/null
+++ b/mbtk/test/ql_adc_test.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+
+#include "ql/ql_adc.h"
+
+int main(int argc, char *argv[])
+{
+    int adc = ql_adc_show(ADC0);
+    if(adc > 0) {
+        printf("ADC0 = %d\n", adc);
+    } else {
+        printf("Get ADC0 fail.\n");
+    }
+
+    adc = ql_adc_show(ADC1);
+    if(adc > 0) {
+        printf("ADC1 = %d\n", adc);
+    } else {
+        printf("Get ADC1 fail.\n");
+    }
+    return 0;
+}
+
diff --git a/mbtk/test/ql_call_test.c b/mbtk/test/ql_call_test.c
new file mode 100755
index 0000000..3d41fed
--- /dev/null
+++ b/mbtk/test/ql_call_test.c
@@ -0,0 +1,283 @@
+#include "mbtk_type.h"
+#include "ql/ql_at.h"
+#include "ql/ql_vcall.h"
+#include "ql/ql_mcm_call.h"
+
+typedef struct
+{
+    int  cmdIdx;
+    char *funcName;
+} st_api_test_case;
+
+//for server test
+st_api_test_case at_api_testcases[] =
+{
+    {0,   "print_help"},
+    {1,   "QL_Voice_Call_Ecall"},
+    {2,   "QL_Voice_Call_Ecall_HangUp"},
+
+    {-1,    NULL}
+};
+
+void print_help(void)
+{
+    int i;
+
+    printf("Supported test cases:\n");
+    for(i = 0; ; i++)
+    {
+        if(at_api_testcases[i].cmdIdx == -1)
+        {
+            break;
+        }
+        printf("%d:\t%s\n", at_api_testcases[i].cmdIdx, at_api_testcases[i].funcName);
+    }
+}
+
+static void ql_voice_call_ind_func(unsigned int ind_id,
+                                   void* ind_data,
+                                   uint32_t ind_data_len)
+{
+    if(NULL == ind_data)
+    {
+        return;
+    }
+
+    switch(ind_id)
+    {
+        case E_QL_MCM_VOICE_CALL_IND:
+        {
+            if(ind_data_len != sizeof(ql_mcm_voice_call_ind))
+            {
+                break;
+            }
+
+            ql_mcm_voice_call_ind *pVoiceCallInd = (ql_mcm_voice_call_ind*)ind_data;
+
+            char *call_state[] = {"INCOMING", "DIALING", "ALERTING", "ACTIVE", "HOLDING", "END", "WAITING"};
+
+            int i = 0;
+            for(i = 0; i < pVoiceCallInd->calls_len; i++)
+            {
+                printf("######### Call id=%d, PhoneNum:%s, event=%s!  ######\n",
+                            pVoiceCallInd->calls[i].call_id, pVoiceCallInd->calls[i].number, call_state[pVoiceCallInd->calls[i].state]);
+            }
+
+            break;
+        }
+
+        case E_QL_MCM_VOICE_ECALL_STATUE_IND:
+        {
+            if(ind_data_len != sizeof(ql_mcm_voice_ecall_status_ind))
+            {
+                break;
+            }
+
+            ql_mcm_voice_ecall_status_ind *pEcallStatusInd
+                                           = (ql_mcm_voice_ecall_status_ind*)ind_data;
+
+            if (pEcallStatusInd->ecall_msd_tx_status_valid)
+            {
+                if (pEcallStatusInd->ecall_msd_tx_status == E_QL_MCM_VOICE_ECALL_MSD_TRANSMISSION_STATUS_SUCCESS)
+                {
+                    printf("========== Ecall status  call_id =%d ,   ecall msd tx success.\r\n", pEcallStatusInd->call_id);
+                }
+                else
+                {
+                    printf("========== Ecall status  call_id =%d ,   ecall msd tx failure.\r\n",  pEcallStatusInd->call_id);
+                }
+            }
+            else
+            {
+                printf("========== Ecall status  call_id =%d  \r\n", pEcallStatusInd->call_id);
+            }
+
+            break;
+        }
+
+        case E_QL_MCM_VOICE_UNKOWN_IND:
+        default:
+            break;
+    }
+}
+
+#if 0
+int main(int argc, char *argv[])
+{
+    int    cmdIdx  = 0;
+    int    ret     = E_QL_OK;
+    char   phoneNum[32] = {0};
+    voice_client_handle_type    h_voice     = 0;
+    int                         voice_call_id = 0;
+
+    printf("QL_Voice_Call_Client_Init .....\n");
+    ret = QL_Voice_Call_Client_Init(&h_voice);
+    if(ret < 0)
+    {
+        printf("QL_Voice_Call_Client_Init FAIL.	ret:%d\n",ret);
+        return -1;
+    }
+    printf("QL_Voice_Call_Client_Init ret = %d, with h_voice=%d\n", ret, h_voice);
+
+    ret = QL_Voice_Call_AddCommonStateHandler(h_voice, (QL_VoiceCall_CommonStateHandlerFunc_t)ql_voice_call_ind_func);
+    if(ret < 0)
+    {
+        printf("QL_Voice_Call_AddCommonStateHandler FAIL.		ret:%d\n",ret);
+        return -1;
+    }
+    printf("QL_Voice_Call_AddCommonStateHandler ret = %d\n", ret);
+
+    print_help();
+
+    while(1)
+    {
+        printf("please input cmd index(-1 exit): ");
+        scanf("%d", &cmdIdx);
+        if(cmdIdx == -1)
+        {
+            break;
+        }
+
+        switch(cmdIdx)
+        {
+        case 0://"print_help"
+        {
+            print_help();
+            break;
+        }
+       	case 1://"QL_Voice_Call_Ecall"
+        {
+            char    PhoneNum[32]                  = {0};
+            printf("please input dest phone number: \n");
+            scanf("%s", PhoneNum);
+
+			char    msd[140+1]                  = {0};
+            printf("please input msd content: \n");
+            scanf("%s", msd);
+
+            E_QL_MCM_ECALL_VARIANT_T ecall_mode;
+            printf("please input ecall mode(1:test 2:emergency): \n");
+            scanf("%d", &ecall_mode);
+            QL_Voice_Call_Start(h_voice, E_QL_VCALL_EXTERNAL_SLOT_1, PhoneNum, NULL);
+            // ret = QL_Voice_Call_Ecall(h_voice, E_QL_VCALL_EXTERNAL_SLOT_1, PhoneNum,
+            //                           ecall_mode, &voice_call_id);
+			printf(" voice_call_id = %d\n", voice_call_id);
+            printf(" ret = %d\n", ret);
+            break;
+        }
+        case 2://QL_Voice_Call_Ecall_HangUp
+        {
+            ret = QL_Voice_Call_Ecall_HangUp(h_voice);
+            printf(" ret = %d\n", ret);
+            break;
+        }
+
+       default:
+            print_help();
+            break;
+        }
+    }
+
+    ret = QL_Voice_Call_RemoveCommonStateHandler(h_voice);
+    if(ret < 0)
+    {
+        printf("QL_Voice_Call_RemoveCommonStateHandler.	ret:%d\n",ret);
+        return -1;
+    }
+    printf("QL_Voice_Call_RemoveCommonStateHandler ret = %d\n", ret);
+
+    ret = QL_Voice_Call_Client_Deinit(h_voice);
+    if(ret < 0)
+    {
+        printf("QL_Voice_Call_Client_Deinit FAIL.	ret:%d\n",ret);
+        return -1;
+    }
+    printf("QL_Voice_Call_Client_Deinit ret = %d, with h_voice=%d\n", ret, h_voice);
+
+    return 0;
+}
+#else
+
+int main(int argc, char *argv[])
+{
+    char operator[10];
+    int opt;
+    int    ret     = E_QL_OK;
+    char   phoneNum[32] = {0};
+    voice_client_handle_type    h_voice     = 0;
+
+    while(1)
+    {
+        printf("=========call main=========\n"
+            "\t0 exit\n"
+            "\t1 call init\n"
+            "\t2 call register handle\n"
+            "\t3 call start\n"
+            "\t4 call end\n"
+            "\t5 call answer\n"
+            "\t6 call set auto answer\n"
+            "\t7 call hold\n"
+            "\t8 call unhold\n"
+            "\t9 call deinit\n"
+            "operator: >> ");
+
+        fgets(operator, sizeof(operator), stdin);
+        fflush(stdin);
+        opt = atoi(operator);
+        switch (opt)
+        {
+        case 0:
+            printf("main exit\n");
+            return 0;
+        case 1:
+            ret = QL_Voice_Call_Client_Init(&h_voice);
+            if(ret < 0)
+            {
+                printf("QL_Voice_Call_Client_Init FAIL.	ret:%d\n",ret);
+                return -1;
+            }
+            printf("QL_Voice_Call_Client_Init ret = %d, with h_voice=%d\n", ret, h_voice);
+
+            break;
+        case 2:
+            ret = QL_Voice_Call_AddCommonStateHandler(h_voice, (QL_VoiceCall_CommonStateHandlerFunc_t)ql_voice_call_ind_func);
+            if(ret < 0)
+            {
+                printf("QL_Voice_Call_AddCommonStateHandler FAIL.		ret:%d\n",ret);
+                return -1;
+            }
+            break;
+        case 3:
+            QL_Voice_Call_Start(h_voice, 0, "15982066434", NULL);
+            break;
+        case 4:
+            QL_Voice_Call_End(h_voice, 0);
+            break;
+        case 5:
+            QL_Voice_Call_Answer(h_voice, 0);
+            break;
+        case 6:
+            QL_Voice_Call_SetAutoAnswer(h_voice, E_QL_MCM_VOICE_AUTO_ANSWER_ENABLE, 6000);
+            break;
+        case 7:
+            QL_Voice_Call_Hold(h_voice);
+            break;
+        case 8:
+            QL_Voice_Call_UnHold(h_voice);
+            break;
+        case 9:
+            QL_Voice_Call_Client_Deinit(h_voice);
+            break;
+        case 10:
+            // QL_Voice_Call_UnHold;
+            break;
+        default:
+            break;
+        }
+
+        sleep(1);
+    }
+
+    return 0;
+}
+#endif
diff --git a/mbtk/test/ql_dev_test.c b/mbtk/test/ql_dev_test.c
new file mode 100755
index 0000000..105f460
--- /dev/null
+++ b/mbtk/test/ql_dev_test.c
@@ -0,0 +1,201 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <sys/epoll.h>
+#include <string.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include "ql/ql_dev.h"
+#include "mbtk_log.h"
+
+static void help()
+{
+    printf("version: Get version.\n");
+    printf("imei: Get IMEI.\n");
+    printf("sn: Get SN.\n");
+    printf("model: Get Model.\n");
+    printf("cfun: Get radio state.\n");
+    printf("cfun <state> <rest>: Set radio state.\n");
+}
+
+static int proc_exit()
+{
+    QL_DEV_ERROR_CODE err = ql_dev_release();
+    if(QL_DEV_SUCCESS != err)
+    {
+        printf("ql_dev_release fail.");
+        return -1;
+    }
+    return 0;
+}
+
+static void sig_process(int sig)
+{
+    LOGI("I got signal %d\n", sig);
+    switch(sig)
+    {
+        case SIGINT: // Ctrl + C
+        {
+            LOGI("Exit by SIGINT.\n");
+            proc_exit();
+            exit(0);
+        }
+        case SIGQUIT: // Ctrl + \ (类似 SIGINT ,但要产生core文件)
+        {
+            LOGI("Exit by SIGQUIT.\n");
+            proc_exit();
+            exit(0);
+        }
+        case SIGTERM:// 默认kill   (同 SIGKILL ,但 SIGKILL 不可捕获)
+        {
+            LOGI("Exit by SIGTERM.\n");
+            proc_exit();
+            exit(0);
+        }
+        case SIGTSTP:// Ctrl + Z (同 SIGSTOP ,但 SIGSTOP 不可捕获)
+        {
+            LOGI("Exit by SIGTSTP.\n");
+            exit(0);
+        }
+        case SIGSEGV: // 如空指针
+        {
+            LOGI("Exit by SIGSEGV.\n");
+            exit(0);
+        }
+        default:
+        {
+            LOGI("Unknown sig:%d\n",sig);
+            break;
+        }
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    signal(SIGINT, sig_process);
+    signal(SIGQUIT, sig_process);
+    signal(SIGTERM, sig_process);
+    //signal(SIGTSTP, sig_process);
+    //signal(SIGSEGV, sig_process);
+
+    mbtk_log_init(NULL,"MBTK_QL_TEST");
+
+    //test2(0, "192.168.1.198");
+    //test2(1, "2409:8162:140:cd3c:1:2:1494:72ba");
+    //test2(1, "254.128.0.0.0.0.0.0.0.1.0.2.144.5.212.239");
+    //test2(1, "2400:3200::1");
+
+    QL_DEV_ERROR_CODE err = ql_dev_init();
+    if(QL_DEV_SUCCESS != err)
+    {
+        printf("ql_dev_init fail.");
+        return -1;
+    }
+
+    printf(">>>>>>>>>>>>>>>>>>>>>>>>Enter cmd:\n");
+    char cmd[100];
+    while(1)
+    {
+        memset(cmd, 0, 100);
+        if(fgets(cmd, 100, stdin))
+        {
+            char *ptr = cmd + strlen(cmd) - 1;
+            while(ptr >= cmd && (*ptr == '\r' || *ptr == '\n'))
+            {
+                *ptr-- = '\0';
+            }
+
+            if(!strncasecmp(cmd, "version", 7))
+            {
+                char version[50] = {0};
+                err = ql_dev_get_firmware_version(version);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Version : %s\n", version);
+                }
+            } else if(!strncasecmp(cmd, "imei", 4)){
+                char imei[50] = {0};
+                err = ql_dev_get_imei(imei);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("IMEI : %s\n", imei);
+                }
+            } else if(!strncasecmp(cmd, "sn", 2)){
+                char sn[50] = {0};
+                err = ql_dev_get_sn(sn);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("SN : %s\n", sn);
+                }
+            } else if(!strncasecmp(cmd, "model", 5)){
+                char model[50] = {0};
+                err = ql_dev_get_model(model);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Model : %s\n", model);
+                }
+            } else if(!strncasecmp(cmd, "cfun", 4)){
+                int cfun;
+                if(!strcasecmp(cmd, "cfun")) { // Get
+                    err = ql_dev_get_modem_fun(&cfun);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Cfun : %d\n", cfun);
+                    }
+                } else { // Set
+                    char *ptr = strstr(cmd, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    cfun = atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    int rst = atoi(ptr);
+                    err = ql_dev_set_modem_fun((QL_DEV_MODEM_FUNCTION)cfun, rst);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("cfun set success\n");
+                    }
+                }
+            }
+            else if(!strcasecmp(cmd, "h") || !strcasecmp(cmd, "help")) {
+                help();
+            } else if(!strcasecmp(cmd, "q")) {
+                break;
+            } else {
+                printf("\n");
+            }
+        }
+    }
+
+    proc_exit();
+
+    LOGI("Client exec complete.");
+#if 1
+    while(1)
+    {
+        sleep(1000 * 365 * 24 * 60 * 60);
+    }
+#else
+    sleep(1);
+#endif
+    return 0;
+}
+
diff --git a/mbtk/test/ql_gpio_test.c b/mbtk/test/ql_gpio_test.c
new file mode 100755
index 0000000..c2b2754
--- /dev/null
+++ b/mbtk/test/ql_gpio_test.c
@@ -0,0 +1,44 @@
+#include "ql/ql_gpio.h"
+#include "mbtk_log.h"
+
+int main(int argc, char *argv[])
+{
+    mbtk_log_init("radio", "MBTK_GPIO");
+
+    if(argc != 2) {
+        printf("./gpio_test <gpio>\n");
+        return -1;
+    }
+
+    int tmp_gpio = atoi(argv[1]);
+    if(tmp_gpio <= 0) {
+        printf("GPIO error : %d\n", tmp_gpio);
+        return -1;
+    }
+
+    Enum_PinName gpio = (Enum_PinName)tmp_gpio;
+    if(Ql_GPIO_Init(gpio, PINDIRECTION_OUT, PINLEVEL_LOW, PINPULLSEL_DISABLE)) {
+        printf("Ql_GPIO_Init() fail.\n");
+        return -1;
+    }
+
+    printf("GPIO : %d, dir : %s, level : %d\n", gpio, Ql_GPIO_GetDirection(gpio) == PINDIRECTION_IN ? "in" : "out",
+        Ql_GPIO_GetLevel(gpio));
+
+    if(Ql_GPIO_SetLevel(gpio, PINLEVEL_HIGH)) {
+        printf("Ql_GPIO_SetLevel() fail.\n");
+        return -1;
+    }
+
+    printf("GPIO : %d, dir : %s, level : %d\n", gpio, Ql_GPIO_GetDirection(gpio) == PINDIRECTION_IN ? "in" : "out",
+        Ql_GPIO_GetLevel(gpio));
+
+    if(Ql_GPIO_Uninit(gpio)) {
+        printf("Ql_GPIO_Uninit() fail.\n");
+        return -1;
+    }
+
+    printf("Success!!!\n");
+    return 0;
+}
+
diff --git a/mbtk/test/ql_i2c_test.c b/mbtk/test/ql_i2c_test.c
new file mode 100755
index 0000000..04aed4d
--- /dev/null
+++ b/mbtk/test/ql_i2c_test.c
@@ -0,0 +1,31 @@
+#include "ql/ql_i2c.h"
+
+
+int main(int argc, char *argv[])
+{
+	int fd = -1;
+    if(argc != 2) {
+        printf("./i2c_test <dev>\n");
+        return -1;
+    }
+    char send_data[64] = {0};
+	send_data[0] = 0x55;
+	send_data[1] = 0x00;
+	send_data[2] = 0x84;
+    fd= Ql_I2C_Init(argv[1]);
+    if(fd <= 0) {
+        printf("Ql_I2C_Init() fail.\n");
+        return -1;
+    }
+
+	if(Ql_I2C_Write(fd, 0x12, 0x10,send_data, 3) < 0) {
+        printf("Ql_I2C_Write() fail.\n");
+        return -1;
+	}
+
+    Ql_I2C_Deinit(fd);
+
+    printf("Success!!!\n");
+
+    return 0;
+}
diff --git a/mbtk/test/ql_nw_test.c b/mbtk/test/ql_nw_test.c
new file mode 100755
index 0000000..81acb5c
--- /dev/null
+++ b/mbtk/test/ql_nw_test.c
@@ -0,0 +1,334 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <sys/epoll.h>
+#include <string.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include "ql/ql_nw.h"
+#include "mbtk_log.h"
+
+static void help()
+{
+    printf("net_pref : Get net prefferred.\n");
+    printf("net_pref <net_pref> <roaming> : Set net prefferred.\n");
+    printf("net_time : Get network time.\n");
+    printf("operator : Get current operator information.\n");
+    printf("net_avail : Get available networks.\n");
+    printf("reg : Get current reg info.\n");
+    printf("sel_mode: Get network select mode.\n");
+    printf("sel_mode <sel_mode> <net_type> <plmn>: Set network select mode.\n");
+    printf("signal : Get current signal.\n");
+    printf("cell : Get cell info.\n");
+    printf("volte : Get VOLTE state.\n");
+    printf("csq_signal : Get current csq signal.\n");
+}
+
+static int proc_exit()
+{
+    QL_NW_ERROR_CODE err = ql_nw_release();
+    if(QL_NW_SUCCESS != err)
+    {
+        printf("ql_nw_release fail.");
+        return -1;
+    }
+    return 0;
+}
+
+static void sig_process(int sig)
+{
+    LOGI("I got signal %d\n", sig);
+    switch(sig)
+    {
+        case SIGINT: // Ctrl + C
+        {
+            LOGI("Exit by SIGINT.\n");
+            proc_exit();
+            exit(0);
+        }
+        case SIGQUIT: // Ctrl + \ (类似 SIGINT ,但要产生core文件)
+        {
+            LOGI("Exit by SIGQUIT.\n");
+            proc_exit();
+            exit(0);
+        }
+        case SIGTERM:// 默认kill   (同 SIGKILL ,但 SIGKILL 不可捕获)
+        {
+            LOGI("Exit by SIGTERM.\n");
+            proc_exit();
+            exit(0);
+        }
+        case SIGTSTP:// Ctrl + Z (同 SIGSTOP ,但 SIGSTOP 不可捕获)
+        {
+            LOGI("Exit by SIGTSTP.\n");
+            exit(0);
+        }
+        case SIGSEGV: // 如空指针
+        {
+            LOGI("Exit by SIGSEGV.\n");
+            exit(0);
+        }
+        default:
+        {
+            LOGI("Unknown sig:%d\n",sig);
+            break;
+        }
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    signal(SIGINT, sig_process);
+    signal(SIGQUIT, sig_process);
+    signal(SIGTERM, sig_process);
+    //signal(SIGTSTP, sig_process);
+    //signal(SIGSEGV, sig_process);
+
+    mbtk_log_init(NULL,"MBTK_QL_TEST");
+
+    //test2(0, "192.168.1.198");
+    //test2(1, "2409:8162:140:cd3c:1:2:1494:72ba");
+    //test2(1, "254.128.0.0.0.0.0.0.0.1.0.2.144.5.212.239");
+    //test2(1, "2400:3200::1");
+
+    QL_NW_ERROR_CODE err = ql_nw_init();
+    if(QL_NW_SUCCESS != err)
+    {
+        printf("ql_nw_init fail.");
+        return -1;
+    }
+
+    printf(">>>>>>>>>>>>>>>>>>>>>>>>Enter cmd:\n");
+    char cmd[100];
+    while(1)
+    {
+        memset(cmd, 0, 100);
+        if(fgets(cmd, 100, stdin))
+        {
+            char *ptr = cmd + strlen(cmd) - 1;
+            while(ptr >= cmd && (*ptr == '\r' || *ptr == '\n'))
+            {
+                *ptr-- = '\0';
+            }
+
+            if(!strncasecmp(cmd, "net_pref", 8)){
+                QL_NW_CONFIG_INFO_T net_pref;
+                if(!strcasecmp(cmd, "net_pref")) { // Get
+                    err = ql_nw_get_config(&net_pref);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("net_pref : %d, roaming : %d\n", net_pref.preferred_nw_mode, net_pref.roaming_pref);
+                    }
+                } else { // Set
+                    char *ptr = strstr(cmd, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    net_pref.preferred_nw_mode = atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    net_pref.roaming_pref = atoi(ptr);
+
+                    err = ql_nw_set_config(&net_pref);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("net_pref set success\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "net_time", 8)){
+                QL_NW_NITZ_TIME_INFO_T time;
+                err = ql_nw_get_nitz_time_info(&time);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Time : %s, %ld, %d\n", time.nitz_time, time.abs_time, time.leap_sec);
+                }
+            } else if(!strncasecmp(cmd, "operator", 8)){
+                QL_NW_OPERATOR_INFO_T operator;
+                err = ql_nw_get_operator_name(&operator);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Operator : %s, %s, %s, %s\n", operator.long_eons, operator.short_eons, operator.mcc, operator.mnc);
+                }
+            } else if(!strncasecmp(cmd, "net_avail", 9)){
+                QL_NW_SCAN_RESULT_LIST_INFO_T nets;
+                err = ql_nw_perform_scan(&nets);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    if(nets.entry_len > 0) {
+                        int i = 0;
+                        for(; i < nets.entry_len; i++) {
+                            printf("Net %d: %d, %d, %s, %s, %s, %s\n", i+1, nets.entry[i].status, nets.entry[i].act,
+                                nets.entry[i].operator_name.long_eons, nets.entry[i].operator_name.short_eons,
+                                nets.entry[i].operator_name.mcc, nets.entry[i].operator_name.mnc);
+                        }
+                    }
+                }
+            } else if(!strncasecmp(cmd, "reg", 3)){
+                QL_NW_REG_STATUS_INFO_T reg;
+                err = ql_nw_get_reg_status(&reg);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Data Reg:%d, %d, %x, %x\n", reg.data_reg.state, reg.data_reg.rat, reg.data_reg.lac, reg.data_reg.cid);
+                    printf("Voice Reg:%d, %d, %x, %x\n", reg.voice_reg.state, reg.voice_reg.rat, reg.voice_reg.lac, reg.voice_reg.cid);
+                }
+            } else if(!strncasecmp(cmd, "sel_mode", 8)){ // "sel_mode" or "sel_mode 460 00 7"
+                QL_NW_SELECTION_INFO_T net;
+                memset(&net, 0, sizeof(QL_NW_SELECTION_INFO_T));
+                if(!strcasecmp(cmd, "sel_mode")) { // Get
+                    err = ql_nw_get_selection(&net);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Net : %d, %s, %s, %d\n", net.nw_selection_mode , net.mcc , net.mnc , net.act);
+                    }
+                } else { // Set
+                    char *ptr = strstr(cmd, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    net.nw_selection_mode = atoi(ptr);
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    //net.mcc = (uint8)atoi(ptr);
+                    memcpy(net.mcc, ptr, 4);
+                    int i = 0;
+                    while(i < 4) {
+                        if(net.mcc[i] == ' ') {
+                            net.mcc[i] = '\0';
+                            break;
+                        }
+                        i++;
+                    }
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    //net.mnc = (uint32)atoi(ptr);
+                    memcpy(net.mnc, ptr, 4);
+                    i = 0;
+                    while(i < 4) {
+                        if(net.mnc[i] == ' ') {
+                            net.mnc[i] = '\0';
+                            break;
+                        }
+                        i++;
+                    }
+
+                    ptr = strstr(ptr, " ");
+                    if(ptr == NULL)
+                        continue;
+                    while(*ptr != '\0' && *ptr == ' ')
+                        ptr++;
+                    net.act = (QL_NW_ACCESS_TECHNOLOGY)atoi(ptr);
+
+                    err = ql_nw_set_selection(&net);
+                    if(err) {
+                        printf("Error : %d\n", err);
+                    } else {
+                        printf("Net select mode set success\n");
+                    }
+                }
+            } else if(!strncasecmp(cmd, "signal", 6)){
+                QL_NW_SIGNAL_STRENGTH_INFO_T sig;
+                err = ql_nw_get_signal_strength(&sig);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Signal GSM:%d, %d, %d, %d\n", sig.GW_SignalStrength.rscp, sig.GW_SignalStrength.bitErrorRate, sig.GW_SignalStrength.rscp, sig.GW_SignalStrength.ecio);
+                    printf("Signal LTE:%d, %d, %d, %d, %d\n", sig.LTE_SignalStrength.rssi , sig.LTE_SignalStrength.rsrp, sig.LTE_SignalStrength.rsrq, sig.LTE_SignalStrength.rssnr, sig.LTE_SignalStrength.cqi);
+                }
+            } else if(!strncasecmp(cmd, "cell", 4)){
+                QL_NW_CELL_INFO_T cell;
+                err = ql_nw_get_cell_info(&cell);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    int i = 0;
+                    if(cell.gsm_info_valid) {
+                        while(i < cell.gsm_info_num) {
+                            printf("GSM cell %d: %d, %x, %d, %d, %x, %d, %d\n", i + 1, cell.gsm_info[i].flag, cell.gsm_info[i].cid, cell.gsm_info[i].mcc, cell.gsm_info[i].mnc, cell.gsm_info[i].lac, cell.gsm_info[i].arfcn, cell.gsm_info[i].bsic);
+                            i++;
+                        }
+                    }
+
+                    if(cell.umts_info_valid) {
+                        i = 0;
+                        while(i < cell.umts_info_num) {
+                            printf("UMTS cell %d: %d, %x, %x, %d, %d, %x, %d, %d\n", i + 1, cell.umts_info[i].flag , cell.umts_info[i].cid, cell.umts_info[i].lcid, cell.umts_info[i].mcc, cell.umts_info[i].mnc, cell.umts_info[i].lac, cell.umts_info[i].uarfcn, cell.umts_info[i].psc);
+                            i++;
+                        }
+                    }
+
+                    if(cell.lte_info_valid) {
+                        i = 0;
+                        while(i < cell.lte_info_num) {
+                            printf("LTE cell %d: %d, %x, %d, %d, %x, %d, %d\n", i + 1, cell.lte_info[i].flag, cell.lte_info[i].cid, cell.lte_info[i].mcc, cell.lte_info[i].mnc, cell.lte_info[i].tac, cell.lte_info[i].pci, cell.lte_info[i].earfcn);
+                            i++;
+                        }
+                    }
+                }
+            } else if(!strncasecmp(cmd, "volte", 5)){
+                VOLTE_STATE state;
+                err = ql_nw_get_volte_state(&state);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("VOLTE state : %d\n", state.reg_state);
+                }
+            } else if(!strncasecmp(cmd, "csq_signal", 10)){
+                QL_NW_CSQ_SIGNAL_STRENGTH_INFO_T signal;
+                err = ql_nw_csq_get_signal_strength(&signal);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("+CSQ : %d, %d\n", signal.rssi, signal.bitErrorRate);
+                }
+            }
+            else if(!strcasecmp(cmd, "h") || !strcasecmp(cmd, "help")) {
+                help();
+            } else if(!strcasecmp(cmd, "q")) {
+                break;
+            } else {
+                printf("\n");
+            }
+        }
+    }
+
+    proc_exit();
+
+    LOGI("Client exec complete.");
+#if 1
+    while(1)
+    {
+        sleep(1000 * 365 * 24 * 60 * 60);
+    }
+#else
+    sleep(1);
+#endif
+    return 0;
+}
+
diff --git a/mbtk/test/ql_sim_test.c b/mbtk/test/ql_sim_test.c
new file mode 100755
index 0000000..f907ab3
--- /dev/null
+++ b/mbtk/test/ql_sim_test.c
@@ -0,0 +1,274 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <pthread.h>
+#include <sys/epoll.h>
+#include <string.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include "ql/ql_sim.h"
+#include "mbtk_log.h"
+
+static void help()
+{
+    printf("imsi : Get IMSI.\n");
+    printf("iccid : Get ICCID.\n");
+    printf("pn : Get phone number.\n");
+    printf("pin_en <pin> : Enable pin.\n");
+    printf("pin_dis <pin> : Disable pin.\n");
+    printf("pin_ch <old_pin> <new_pin> : Change pin.\n");
+    printf("pin_verify <pin> : Verify pin.\n");
+    printf("puk_unlock <puk> <new_pin> : Unlock using PUK.\n");
+    printf("sim : Get sim state.\n");
+}
+
+static int proc_exit()
+{
+    QL_SIM_ERROR_CODE err = ql_sim_release();
+    if(QL_SIM_SUCCESS != err)
+    {
+        printf("ql_sim_release fail.");
+        return -1;
+    }
+    return 0;
+}
+
+static void sig_process(int sig)
+{
+    LOGI("I got signal %d\n", sig);
+    switch(sig)
+    {
+        case SIGINT: // Ctrl + C
+        {
+            LOGI("Exit by SIGINT.\n");
+            proc_exit();
+            exit(0);
+        }
+        case SIGQUIT: // Ctrl + \ (类似 SIGINT ,但要产生core文件)
+        {
+            LOGI("Exit by SIGQUIT.\n");
+            proc_exit();
+            exit(0);
+        }
+        case SIGTERM:// 默认kill   (同 SIGKILL ,但 SIGKILL 不可捕获)
+        {
+            LOGI("Exit by SIGTERM.\n");
+            proc_exit();
+            exit(0);
+        }
+        case SIGTSTP:// Ctrl + Z (同 SIGSTOP ,但 SIGSTOP 不可捕获)
+        {
+            LOGI("Exit by SIGTSTP.\n");
+            exit(0);
+        }
+        case SIGSEGV: // 如空指针
+        {
+            LOGI("Exit by SIGSEGV.\n");
+            exit(0);
+        }
+        default:
+        {
+            LOGI("Unknown sig:%d\n",sig);
+            break;
+        }
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    signal(SIGINT, sig_process);
+    signal(SIGQUIT, sig_process);
+    signal(SIGTERM, sig_process);
+    //signal(SIGTSTP, sig_process);
+    //signal(SIGSEGV, sig_process);
+
+    mbtk_log_init(NULL,"MBTK_QL_TEST");
+
+    //test2(0, "192.168.1.198");
+    //test2(1, "2409:8162:140:cd3c:1:2:1494:72ba");
+    //test2(1, "254.128.0.0.0.0.0.0.0.1.0.2.144.5.212.239");
+    //test2(1, "2400:3200::1");
+
+    QL_SIM_ERROR_CODE err = ql_sim_init();
+    if(QL_SIM_SUCCESS != err)
+    {
+        printf("ql_sim_init fail.");
+        return -1;
+    }
+
+    printf(">>>>>>>>>>>>>>>>>>>>>>>>Enter cmd:\n");
+    char cmd[100];
+    while(1)
+    {
+        memset(cmd, 0, 100);
+        if(fgets(cmd, 100, stdin))
+        {
+            char *ptr = cmd + strlen(cmd) - 1;
+            while(ptr >= cmd && (*ptr == '\r' || *ptr == '\n'))
+            {
+                *ptr-- = '\0';
+            }
+
+            if(!strncasecmp(cmd, "imsi", 4)){
+                char imsi[30];
+                err = ql_sim_get_imsi(imsi, 30);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("IMSI : %s\n", imsi);
+                }
+            }else if(!strncasecmp(cmd, "iccid", 5)){
+                char iccid[30];
+                err = ql_sim_get_iccid(iccid, 30);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("ICCID : %s\n", iccid);
+                }
+            }else if(!strncasecmp(cmd, "pn", 2)){
+                char phonenumber[30];
+                err = ql_sim_get_phonenumber(phonenumber, 30);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("PhoneNumber : %s\n", phonenumber);
+                }
+            }else if(!strncasecmp(cmd, "pin_en", 6)){ // pin_en <pin>
+                QL_SIM_VERIFY_PIN_INFO pin = {0};
+                char *ptr = strstr(cmd, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                memcpy(pin.pin_value, ptr, strlen(ptr));
+
+                err = ql_sim_enable_pin(&pin);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Enable PIN(%s) success.\n", pin.pin_value);
+                }
+            }else if(!strncasecmp(cmd, "pin_dis", 7)){ // pin_dis <pin>
+                QL_SIM_VERIFY_PIN_INFO pin = {0};
+                char *ptr = strstr(cmd, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                memcpy(pin.pin_value, ptr, strlen(ptr));
+
+                err = ql_sim_disable_pin(&pin);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Disable PIN(%s) success.\n", pin.pin_value);
+                }
+            }else if(!strncasecmp(cmd, "pin_ch", 6)){ // pin_ch <old_pin> <new_pin>
+                QL_SIM_CHANGE_PIN_INFO pin = {0};
+                char *ptr = strstr(cmd, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+
+                char *tmp = pin.old_pin_value;
+                while(*ptr != '\0' && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') {
+                    *tmp++ = *ptr++;
+                }
+                *tmp = '\0';
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+
+                tmp = pin.new_pin_value;
+                while(*ptr != '\0' && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') {
+                    *tmp++ = *ptr++;
+                }
+                *tmp = '\0';
+
+                err = ql_sim_change_pin(&pin);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Change PIN(%s -> %s) success.\n", pin.old_pin_value, pin.new_pin_value);
+                }
+            }else if(!strncasecmp(cmd, "pin_verify", 10)){ // pin_verify <pin>
+                QL_SIM_VERIFY_PIN_INFO pin = {0};
+                char *ptr = strstr(cmd, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+                memcpy(pin.pin_value, ptr, strlen(ptr));
+
+                err = ql_sim_verify_pin(&pin);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Verify PIN(%s) success.\n", pin.pin_value);
+                }
+            }else if(!strncasecmp(cmd, "puk_unlock", 10)){ // puk_unlock <puk> <new_pin>
+                QL_SIM_UNBLOCK_PIN_INFO pin = {0};
+                char *ptr = strstr(cmd, " ");
+                if(ptr == NULL)
+                    continue;
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+
+                char *tmp = pin.puk_value;
+                while(*ptr != '\0' && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') {
+                    *tmp++ = *ptr++;
+                }
+                *tmp = '\0';
+                while(*ptr != '\0' && *ptr == ' ')
+                    ptr++;
+
+                tmp = pin.new_pin_value;
+                while(*ptr != '\0' && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') {
+                    *tmp++ = *ptr++;
+                }
+                *tmp = '\0';
+
+                err = ql_sim_unblock_pin(&pin);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("PUI unlock(PUK:%s   PIN:%s) success.\n", pin.puk_value, pin.new_pin_value);
+                }
+            }else if(!strncasecmp(cmd, "sim", 3)){
+                QL_SIM_CARD_STATUS_INFO sim;
+                err = ql_sim_get_card_status(&sim);
+                if(err) {
+                    printf("Error : %d\n", err);
+                } else {
+                    printf("Sim type:%d, state:%d, PIN:%d,%d,%d,%d\n", sim.card_type, sim.card_state, sim.card_pin_info.pin1_num_retries, sim.card_pin_info.pin2_num_retries, sim.card_pin_info.puk1_num_retries, sim.card_pin_info.puk2_num_retries);
+                }
+            }
+            else if(!strcasecmp(cmd, "h") || !strcasecmp(cmd, "help")) {
+                help();
+            } else if(!strcasecmp(cmd, "q")) {
+                break;
+            } else {
+                printf("\n");
+            }
+        }
+    }
+
+    proc_exit();
+
+    LOGI("Client exec complete.");
+#if 1
+    while(1)
+    {
+        sleep(1000 * 365 * 24 * 60 * 60);
+    }
+#else
+    sleep(1);
+#endif
+    return 0;
+}
+
diff --git a/mbtk/test/ql_sms_test.c b/mbtk/test/ql_sms_test.c
new file mode 100755
index 0000000..2d07d80
--- /dev/null
+++ b/mbtk/test/ql_sms_test.c
@@ -0,0 +1,120 @@
+/**

+ *   \file dtmf_test.c

+ *   \brief A Documented file.

+ *

+ *  Detailed description

+ *   \Author:  jinLuo

+ *   \Version: 1.0.0

+ *   \Date: 2022-12-1

+ */

+

+/******************************************************************************\

+ *   Include files

+\******************************************************************************/

+#include <pthread.h>

+#include <time.h>

+#include <sys/ioctl.h>

+#include <fcntl.h>

+#include <unistd.h>

+#include <sys/types.h>

+#include <sys/stat.h>

+#include <fcntl.h>

+#include <string.h>

+#include <stdio.h>

+#include <signal.h>

+#include <unistd.h>

+#include <fcntl.h>

+#include <errno.h>

+#include <string.h>

+#include <stdlib.h>

+#include <poll.h>

+#include <stdlib.h>

+

+#include <sys/ioctl.h>

+#include <sys/types.h>

+#include <sys/stat.h>

+#include "ql/ql_sms.h"

+

+

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

+{

+    char operator[10];

+    char serNum[50] = {0};

+    char phonenumter[20] ={0};

+    int opt;

+    int ret, uToken; 

+

+    while(1)

+    {

+        printf("=========audio main=========\n"

+            "\t0 exit\n"

+            "\t1 sms init\n"

+            "\t2 send sms\n"

+            "\t3 wait receive new sms\n"

+            "\t4 delete sms(int index);\n"

+            "\t5 list sms\n"

+            "\t6 query sms storage status\n"

+            "\t7 query service number\n"

+            "\t8 set service number\n"

+            "\t9 deinit sms\n"

+            "operator: >> ");

+        fgets(operator, sizeof(operator), stdin);

+        fflush(stdin);

+        opt = atoi(operator);

+        switch (opt)

+        {

+        case 0:

+            printf("main exit\n");

+            return 0;

+        case 1:

+            ql_sms_init();

+            break;

+        case 2:

+            ql_sms_send_text_msg("+8615775690697", "hello world", 1);

+            break;

+        case 3:

+            ql_sms_add_event_handler(NULL, NULL);

+            break;

+		case 4:

+            ql_sms_send_pdu_msg("+8615775690697","你好",1);

+            break;

+       //     printf("please input volume (0~100): \n");

+       //     fgets(operator, sizeof(operator), stdin);

+       //     fflush(stdin);

+       //     opt = atoi(operator);

+		//	lynq_delete_sms(opt);

+            break;

+		case 5:

+			printf("please input index (0~50): \n");

+            fgets(operator, sizeof(operator), stdin);

+            fflush(stdin);

+            opt = atoi(operator);

+       //     lynq_list_sms(1, opt, "ALL" );

+			break;

+		case 6:

+        //    lynq_query_sms_storage_status();

+			break;

+        case 7:

+            ret = ql_sms_get_sms_center_address(serNum);

+            if(!ret)

+                printf("get_smsc:%s\n", serNum);

+            break;

+        case 8:

+        //    printf("please input service num: \n");

+        //    fgets(phonenumter, sizeof(phonenumter), stdin);

+        //    fflush(stdin);

+        //    memcpy(phonenumter, "+8613800280500", "+8613800280500");

+            

+        //    ret= ql_sms_set_sms_center_address(phonenumter);

+            ret= ql_sms_set_sms_center_address("+8613800280500");

+            break;

+        case 9:

+            ql_sms_release();

+            break;

+        default:

+            break;

+        }

+    }

+

+    return 0;

+}

diff --git a/mbtk/test/ql_spi_test.c b/mbtk/test/ql_spi_test.c
new file mode 100755
index 0000000..dff5208
--- /dev/null
+++ b/mbtk/test/ql_spi_test.c
@@ -0,0 +1,92 @@
+#include "ql/ql_spi.h"
+
+
+int main(int argc, char *argv[])
+{
+    char send_data[64] = {0};
+	char read_data[64] = {0};
+	char crc = 0;
+	int i = 0;
+	int j = 0;
+
+    //system("echo PB6 > /sys/kernel/debug/sunxi_pinctrl/sunxi_pin");
+    //system("echo PB6 1 > /sys/kernel/debug/sunxi_pinctrl/function");
+    //system("echo PB6 0 > /sys/kernel/debug/sunxi_pinctrl/data");
+
+#if 0
+static const char *device = "/dev/spidev1.0\0";
+static uint8_t mode = 3; /* SPI通信使用全双工,设置CPOL=0,CPHA=0。 */
+static uint8_t bits = 8; /* 8bits读写,MSB first。*/
+static uint32_t speed = 100 * 1000;/* 设置0.5M传输速度 */
+static uint16_t delay = 500;
+#endif
+    int fd = -1;
+	/* spi 初始化程序 */
+	if((fd = Ql_SPI_Init("/dev/spidev1.0", SPIMODE3, 8, S_13M)) <= 0)
+	{
+        printf("Ql_SPI_Init() fail.\n");
+        return -1;
+	}
+
+	send_data[0] = 0x55;
+	send_data[1] = 0x00;
+	send_data[2] = 0x84;
+	send_data[3] = 0x00;
+	send_data[4] = 0x08;
+	send_data[5] = 0x00;
+	send_data[6] = 0x00;
+
+	crc = send_data[1];
+	for (i = 2; i < 7; i++)
+	{
+		crc ^= send_data[i];
+	}
+	crc = ~crc;
+
+	send_data[7] = crc;
+
+	printf("send data:");
+	for (i = 0; i < 8; i++)
+	{
+		printf("%#x, ", send_data[i]);
+	}
+	printf("\n");
+
+	/* spi 发送数据 */
+	if(Ql_SPI_Write_Read(fd, send_data,read_data, 8)) {
+        printf("Ql_SPI_Write_Read() fail.\n");
+        return -1;
+	}
+
+#if 0
+	printf("read data:");
+	for (j = 0; j < 20; j++)
+	{
+		printf("%#x, ", read_data[j]);
+	}
+
+	usleep(10000);
+
+	memset(read_data, 0, sizeof(read_data));
+	memset(send_data, 0, sizeof(send_data));
+	/* spi 读取数据 */
+	if(Ql_SPI_Write_Read(fd, send_data,read_data, 16)) {
+        printf("Ql_SPI_Write_Read() fail.\n");
+        return -1;
+	}
+
+	printf("read data:");
+	for (j = 0; j < 20; j++)
+	{
+		printf("%#x, ", read_data[j]);
+	}
+#endif
+
+    if(Ql_SPI_DeInit(fd)) {
+        printf("Ql_SPI_DeInit() fail.\n");
+        return -1;
+    }
+
+    printf("success!!!\n");
+    return 0;
+}
diff --git a/mbtk/test/ql_uart_test.c b/mbtk/test/ql_uart_test.c
new file mode 100755
index 0000000..3936ef6
--- /dev/null
+++ b/mbtk/test/ql_uart_test.c
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <errno.h>
+
+#include "ql/ql_uart.h"
+
+
+int main(int argc, char *argv[])
+{
+    if(argc != 3) {
+        printf("./uart_test <dev> <baudrate>\n");
+        return -1;
+    }
+
+    int fd = Ql_UART_Open(argv[1], (Enum_BaudRate)atoi(argv[2]), FC_NONE);
+    if(fd < 0) {
+        printf("Ql_UART_Open() fail.\n");
+        return -1;
+    }
+
+    ST_UARTDCB dcb;
+    memset(&dcb, 0x0, sizeof(ST_UARTDCB));
+    dcb.databit = DB_CS8;
+    dcb.parity = PB_NONE;
+    dcb.flowctrl = FC_NONE;
+
+    if(Ql_UART_SetDCB(fd, &dcb)) {
+        printf("Ql_UART_SetDCB() fail.\n");
+        return -1;
+    }
+
+    char buff[1024];
+    int len;
+    while(1) {
+        memset(buff, 0x0 ,1024);
+        len = Ql_UART_Read(fd, buff, 1024);
+        if(len > 0) {
+            if(memcmp(buff, "exit", 4) == 0) {
+                Ql_UART_Write(fd, "exit\r\n", 6);
+                break;
+            } else {
+                printf("<%s\n", buff);
+
+                Ql_UART_Write(fd, "OK\r\n", 4);
+            }
+        } else {
+            printf("Ql_UART_Read() fail:%d, errno = %d\n", len, errno);
+        }
+    }
+    Ql_UART_Close(fd);
+
+    printf("exit!!!\n");
+
+    return 0;
+}
+
+
diff --git a/mbtk/test/ql_voice_test.c b/mbtk/test/ql_voice_test.c
new file mode 100755
index 0000000..43af279
--- /dev/null
+++ b/mbtk/test/ql_voice_test.c
@@ -0,0 +1,91 @@
+#include "mbtk_type.h"
+//#include "ql/ql_vcall.h"
+//#include "ql/ql_mcm_call.h"
+#include "ql/ql_voice.h"
+
+
+
+
+int main(int argc, char *argv[])
+{
+    char operator[10] = {0};
+    int opt;
+    int    ret     = 0;
+    char   phoneNum[32] = {0};
+    int    h_voice     = 0;
+
+    while(1)
+    {
+        printf("=========call main=========\n"
+            "\t0 exit\n"
+            "\t1 call init\n"
+            "\t2 call register handle\n"
+            "\t3 call start\n"
+            "\t4 call end\n"
+            "\t5 call answer\n"
+            "\t6 call set auto answer\n"
+            "\t7 call hold\n"
+            "\t8 call unhold\n"
+            "\t9 call deinit\n"
+            "operator: >> ");
+
+        fgets(operator, sizeof(operator), stdin);
+        fflush(stdin);
+        opt = atoi(operator);
+        switch (opt)
+        {
+        case 0:
+            printf("main exit\n");
+            return 0;
+        case 1:
+            ret = ql_voice_call_init();
+            if(ret < 0)
+            {
+                printf("ql_voice_call_init FAIL.	ret:%d\n",ret);
+                return -1;
+            }
+            printf("ql_voice_call_init ret = %d, with h_voice=%d\n", ret, h_voice);
+
+            break;
+        case 2:
+            ret = ql_voice_call_event_register(NULL, NULL);
+            if(ret < 0)
+            {
+                printf("ql_voice_call_event_register FAIL.		ret:%d\n",ret);
+                return -1;
+            }
+            break;
+        case 3:
+            ql_voice_call_start("15775690697");
+            break;
+        case 4:
+            ql_voice_call_end();
+            break;
+        case 5:
+            ql_voice_call_answer();
+            break;
+        case 6:
+            ql_voice_auto_answer(6000);
+            break;
+        case 7:
+            ql_voice_call_hold();
+            break;
+        case 8:
+            ql_voice_call_unhold();
+            break;
+        case 9:
+            ql_voice_call_release();
+            break;
+        case 10:
+            // QL_Voice_Call_UnHold;
+            break;
+        default:
+            break;
+        }
+
+        sleep(1);
+    }
+
+    return 0;
+}
+
diff --git a/mbtk/test/touch_ev_demo.c b/mbtk/test/touch_ev_demo.c
new file mode 100755
index 0000000..b7ae90d
--- /dev/null
+++ b/mbtk/test/touch_ev_demo.c
@@ -0,0 +1,374 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <linux/input.h>
+#include <unistd.h>
+#include <linux/fb.h>
+#include <sys/mman.h>
+#include <time.h>
+#include <pthread.h>
+#include <sys/poll.h>
+#include <dirent.h>
+#include <stdbool.h>
+
+#ifndef TRUE
+#define TRUE   1   /* Boolean true value. */
+#endif
+
+#ifndef true
+#define true   1   /* Boolean true value. */
+#endif
+
+#ifndef FALSE
+#define FALSE  0   /* Boolean false value. */
+#endif
+
+#ifndef false
+#define false  0   /* Boolean false value. */
+#endif
+
+
+#ifndef NULL
+#define NULL  0
+#endif
+
+
+#ifndef null
+#define null  0
+#endif
+
+#define LOGI printf
+#define LOGE printf
+
+/**
+ * Compiler-digit : 16
+ * char : 1     (%c)
+ * char* : 2
+ * short int : 2
+ * int : 2      (%d)
+ * unsigned int : 2  (%u)
+ * float : 4    (%f)
+ * double : 8   (%f)
+ * long : 4
+ * unsigned long : 4
+ * long long : 8
+ * unsigned long long : 8
+ *
+ *
+ * Compiler-digit : 32
+ * char : 1
+ * char* : 4
+ * short int : 2
+ * int : 4
+ * unsigned int : 4
+ * float : 4
+ * double : 8
+ * long : 4
+ * unsigned long : 4
+ * long long : 8
+ * unsigned long long : 8
+ *
+ *
+ * Compiler-digit : 64
+ * char : 1
+ * char* : 8
+ * short int : 2
+ * int : 4
+ * unsigned int : 4
+ * float : 4
+ * double : 8
+ * long : 8
+ * unsigned long : 8
+ * long long : 8
+ * unsigned long long : 8
+ */
+typedef unsigned char boolean; /* Boolean value type. */
+// typedef unsigned char bool; /* Boolean value type. */
+typedef unsigned long long uint64; /* Unsigned 64 bit value */
+typedef unsigned long long uint64_t; /* Unsigned 64 bit value */
+typedef unsigned int uint32; /* Unsigned 32 bit value */
+typedef unsigned int uint32_t; /* Unsigned 32 bit value */
+typedef unsigned short uint16; /* Unsigned 16 bit value */
+typedef unsigned short uint16_t;
+typedef unsigned char uint8; /* Unsigned 8  bit value */
+typedef unsigned char uint8_t;
+typedef signed long long int64; /* Signed 64 bit value */
+typedef signed long long sint64; /* Signed 64 bit value */
+typedef signed int int32; /* Signed 32 bit value */
+typedef signed int sint32; /* Signed 32 bit value */
+typedef signed short int16; /* Signed 16 bit value */
+typedef signed short sint16; /* Signed 16 bit value */
+typedef signed char int8; /* Signed 8  bit value */
+typedef signed char sint8; /* Signed 8  bit value */
+typedef unsigned char byte; /* byte type */
+
+//#include "mbtk_type.h"
+//#include "mbtk_log.h"
+
+typedef int (*ev_callback)(int fd, uint32_t epevents, void *data);
+
+typedef enum {
+    ACTION_DOWN,
+    ACTION_MOVE,
+    ACTION_UP,
+    ACTION_CANCEL
+} touch_event_action_enum;
+
+typedef struct {
+    touch_event_action_enum action;
+    int x;
+    int y;
+} touch_event;
+
+static int move_x;
+static touch_event event_pre;
+static bool action_down_get = false;
+static bool action_touched = false;
+
+#define MAX_DEVICES 16
+#define MAX_MISC_FDS 16
+
+#define BITS_PER_LONG (sizeof(unsigned long) * 8)
+#define BITS_TO_LONGS(x) (((x) + BITS_PER_LONG - 1) / BITS_PER_LONG)
+
+#define test_bit(bit, array) \
+    ((array)[(bit)/BITS_PER_LONG] & (1 << ((bit) % BITS_PER_LONG)))
+
+struct fd_info {
+    ev_callback cb;
+    void *data;
+};
+
+static struct pollfd ev_fds[MAX_DEVICES + MAX_MISC_FDS];
+static struct fd_info ev_fdinfo[MAX_DEVICES + MAX_MISC_FDS];
+
+static unsigned ev_count = 0;
+static unsigned ev_dev_count = 0;
+static unsigned ev_misc_count = 0;
+
+int ev_get_input(int fd, short revents, struct input_event *ev);
+bool event_process(struct input_event ev);
+
+int ev_cb(int fd, uint32_t epevents, void *data)
+{
+    struct input_event ev;
+
+    int retval = ev_get_input(fd, epevents, &ev);
+    if(retval < 0) return -1;
+
+    if(!event_process(ev)) return 0;
+
+    return 0;
+}
+
+int ev_init(void *data)
+{
+    DIR *dir;
+    struct dirent *de;
+    int fd;
+
+    dir = opendir("/dev/input");
+    if(dir != 0) {
+        while((de = readdir(dir))) {
+            unsigned long ev_bits[BITS_TO_LONGS(EV_MAX)];
+
+//            fprintf(stderr,"/dev/input/%s\n", de->d_name);
+            if(strncmp(de->d_name,"event",5)) continue;
+            fd = openat(dirfd(dir), de->d_name, O_RDONLY);
+            if(fd < 0) continue;
+
+            /* read the evbits of the input device */
+            if (ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) < 0) {
+                close(fd);
+                continue;
+            }
+
+            /* TODO: add ability to specify event masks. For now, just assume
+             * that only EV_KEY and EV_REL event types are ever needed. */
+            if (!test_bit(EV_KEY, ev_bits) && !test_bit(EV_REL, ev_bits)) {
+                close(fd);
+                continue;
+            }
+
+            ev_fds[ev_count].fd = fd;
+            ev_fds[ev_count].events = POLLIN;
+            ev_fdinfo[ev_count].cb = ev_cb;
+            ev_fdinfo[ev_count].data = data;
+            ev_count++;
+            ev_dev_count++;
+            if(ev_dev_count == MAX_DEVICES) break;
+        }
+    }
+
+    return 0;
+}
+
+void ev_exit(void)
+{
+    while (ev_count > 0) {
+        close(ev_fds[--ev_count].fd);
+    }
+    ev_misc_count = 0;
+    ev_dev_count = 0;
+}
+
+int ev_wait(int timeout)
+{
+    int r;
+
+    r = poll(ev_fds, ev_count, timeout);
+    if (r <= 0)
+        return -1;
+    return 0;
+}
+
+void ev_dispatch(void)
+{
+    unsigned n;
+    int ret;
+
+    for (n = 0; n < ev_count; n++) {
+        ev_callback cb = ev_fdinfo[n].cb;
+        if (cb && (ev_fds[n].revents & ev_fds[n].events))
+            cb(ev_fds[n].fd, ev_fds[n].revents, ev_fdinfo[n].data);
+    }
+}
+
+int ev_get_input(int fd, short revents, struct input_event *ev)
+{
+    int r;
+
+    if (revents & POLLIN) {
+        r = read(fd, ev, sizeof(*ev));
+        if (r == sizeof(*ev))
+            return 0;
+    }
+    return -1;
+}
+
+bool event_process(struct input_event ev)
+{
+    LOGI("Event:%d,%d,%d\n", ev.type, ev.code, ev.value);
+
+//    if(ev.type != EV_KEY){
+//        return false;
+//    }
+
+    bool is_touch = true;
+    // Touch Down/Up
+    if(ev.type == EV_KEY && ev.code == BTN_TOUCH) {
+        if(!!ev.value) { // Down
+            action_down_get = true;
+            action_touched = true;
+        }
+        else // UP
+        {
+            action_down_get = false;
+            action_touched = false;
+        }
+    } else if(ev.type == EV_ABS) { // Touch move
+        if(!action_touched) // No down
+            return false;
+    } else if(ev.type != EV_KEY) {
+        return false;
+    } else {
+        is_touch = false;
+    }
+
+    if (!is_touch && ev.value < 2){ // 2 is long press events
+        int down = !!ev.value;
+        if (down){
+            LOGI("LongPress : DOWN.");
+            //if(!l->onKeyDown(ev.type, ev.code)) return false;
+        }else{
+            //if(!l->onKeyUp(ev.type, ev.code)) return false;
+            LOGI("LongPress : UP.");
+        }
+    } else if (is_touch) {
+        touch_event m_event;
+        if(ev.type == EV_ABS) { // Move
+            if(ev.code == KEY_SLASH) { // X
+                move_x = ev.value;
+            } else if(ev.code == KEY_RIGHTSHIFT) { // Y
+                if(action_down_get)
+                {
+                    m_event.action = ACTION_DOWN;
+                    action_down_get = false;
+                } else {
+                    m_event.action = ACTION_MOVE;
+                }
+                m_event.x = move_x;
+                m_event.y = ev.value;
+
+                if(event_pre.x != m_event.x
+                    || event_pre.y != m_event.y)
+                {
+                    event_pre.x = m_event.x;
+                    event_pre.y = m_event.y;
+                #ifdef MBTK_TP_RESIZE_SUPPORT
+                    point_resize(getScreenWidth(),
+                        getScreenHeight(),
+                        mStatusBar->isVisibility() ? mStatusBar->getHeight() : 0,
+                        &m_event);
+                #endif
+                    LOGI("Window onTouchEvent action:%d (%d,%d) -> (%d,%d)",
+                        m_event.action, event_pre.x, event_pre.y, m_event.x, m_event.y);
+
+                }
+            } else {
+                // Do nothing
+            }
+        } else if(!action_down_get){ // UP
+            m_event.action = ACTION_UP;
+            m_event.x = event_pre.x;
+            m_event.y = event_pre.y;
+
+        #ifdef MBTK_TP_RESIZE_SUPPORT
+            point_resize(getScreenWidth(),
+                getScreenHeight(),
+                mStatusBar->isVisibility() ? mStatusBar->getHeight() : 0,
+                &m_event);
+        #endif
+
+            LOGI("Window onTouchEvent action:%d (%d,%d) -> (%d,%d)",
+                m_event.action, event_pre.x, event_pre.y, m_event.x, m_event.y);
+
+        } else {
+            // Do nothing
+        }
+    } else {
+        // Do nothing
+    }
+
+    //invalidate();
+
+    return true;
+}
+
+int main(int argc, char *argv[])
+{
+    mbtk_log_init(NULL, "MBTK_EVENT");
+
+    if(ev_init(NULL)) {
+        LOGE("ev_init() fail.");
+        return -1;
+    }
+
+    LOGI("event getting...");
+    while(1) {
+        if(!ev_wait(-1))
+            ev_dispatch();
+    }
+
+    LOGI("exit!!!");
+    return 0;
+}